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.

1770 lines
56 KiB

  1. #include <windows.h>
  2. #include <fusenetincludes.h>
  3. #include <stdio.h>
  4. #include "mg.h"
  5. #include "manifestnode.h"
  6. #include "xmlutil.h"
  7. #include "assemblycache.h"
  8. #include "version.h"
  9. #define DIRECTORY_PATH 0
  10. #define FILE_PATH 1
  11. #define DEFAULT_POLLING_INTERVAL L"6"
  12. #define MAX_DEPLOY_DIRS (5)
  13. CString g_sDeployDirs[MAX_DEPLOY_DIRS];
  14. DWORD g_dwDeployDirs=0;
  15. typedef enum _COMMAND_MODE_ {
  16. CmdUsage,
  17. CmdTemplate,
  18. CmdList,
  19. CmdDependencyList,
  20. CmdSubscription,
  21. CmdManifest,
  22. } COMMAND_MODE, *LPCOMMAND_MODE;
  23. CString g_sTargetDir;
  24. CString g_sTemplateFile;
  25. CString g_sAppManifestURL;
  26. CString g_sPollingInterval;
  27. CString g_sSubscriptionManifestDir;
  28. CString g_sAppManifestFile;
  29. CString g_sAppBase;
  30. BOOL g_bFailOnWarnings=TRUE;
  31. BOOL g_bLookInGACForDependencies;
  32. BOOL g_bCopyDependentSystemAssemblies;
  33. class __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4")) private_MSXML_DOMDocument30;
  34. typedef HRESULT(*PFNGETCORSYSTEMDIRECTORY)(LPWSTR, DWORD, LPDWORD);
  35. typedef HRESULT (__stdcall *PFNCREATEASSEMBLYCACHE) (IAssemblyCache **ppAsmCache, DWORD dwReserved);
  36. #define WZ_MSCOREE_DLL_NAME L"mscoree.dll"
  37. #define GETCORSYSTEMDIRECTORY_FN_NAME "GetCORSystemDirectory"
  38. #define CREATEASSEMBLYCACHE_FN_NAME "CreateAssemblyCache"
  39. #define WZ_FUSION_DLL_NAME L"Fusion.dll"
  40. // ---------------------------------------------------------------------------
  41. // CreateFusionAssemblyCache
  42. // ---------------------------------------------------------------------------
  43. HRESULT CreateFusionAssemblyCache(IAssemblyCache **ppFusionAsmCache)
  44. {
  45. HRESULT hr = S_OK;
  46. HMODULE hEEShim = NULL;
  47. HMODULE hFusion = NULL;
  48. WCHAR szFusionPath[MAX_PATH];
  49. DWORD ccPath = MAX_PATH;
  50. PFNGETCORSYSTEMDIRECTORY pfnGetCorSystemDirectory = NULL;
  51. PFNCREATEASSEMBLYCACHE pfnCreateAssemblyCache = NULL;
  52. // Find out where the current version of URT is installed
  53. hEEShim = LoadLibrary(WZ_MSCOREE_DLL_NAME);
  54. if(!hEEShim)
  55. {
  56. hr = E_FAIL;
  57. goto exit;
  58. }
  59. pfnGetCorSystemDirectory = (PFNGETCORSYSTEMDIRECTORY)
  60. GetProcAddress(hEEShim, GETCORSYSTEMDIRECTORY_FN_NAME);
  61. if((!pfnGetCorSystemDirectory))
  62. {
  63. hr = E_FAIL;
  64. goto exit;
  65. }
  66. // Get cor path.
  67. if (FAILED(hr = (pfnGetCorSystemDirectory(szFusionPath, MAX_PATH, &ccPath))))
  68. goto exit;
  69. // Form path to fusion.
  70. lstrcatW(szFusionPath, WZ_FUSION_DLL_NAME);
  71. hFusion = LoadLibrary(szFusionPath);
  72. if(!hFusion)
  73. {
  74. hr = E_FAIL;
  75. goto exit;
  76. }
  77. // Get method ptr.
  78. pfnCreateAssemblyCache = (PFNCREATEASSEMBLYCACHE)
  79. GetProcAddress(hFusion, CREATEASSEMBLYCACHE_FN_NAME);
  80. if((!pfnCreateAssemblyCache))
  81. {
  82. hr = E_FAIL;
  83. goto exit;
  84. }
  85. // Create the fusion cache interface.
  86. if (FAILED(hr = (pfnCreateAssemblyCache(ppFusionAsmCache, 0))))
  87. goto exit;
  88. hr = S_OK;
  89. exit:
  90. return hr;
  91. }
  92. /////////////////////////////////////////////////////////////////////////
  93. // PathNormalize
  94. // Creates absolute path from relative, using current directory of mg.exe or parent process.
  95. /////////////////////////////////////////////////////////////////////////
  96. HRESULT PathNormalize(LPWSTR pwzPath, LPWSTR *ppwzAbsolutePath, DWORD dwFlag, BOOL bExists)
  97. {
  98. HRESULT hr = S_OK;
  99. WCHAR pwzTempDir[MAX_PATH], pwzAbsolutePath[MAX_PATH];
  100. DWORD ccDir = MAX_PATH;
  101. *ppwzAbsolutePath = NULL;
  102. //If path is relative, prepend the current directory
  103. if (PathIsRelative(pwzPath))
  104. {
  105. GetCurrentDirectory(ccDir, pwzTempDir);
  106. StrCat(pwzTempDir, L"\\");
  107. StrCat(pwzTempDir, pwzPath);
  108. }
  109. else
  110. StrCpy(pwzTempDir, pwzPath);
  111. if (!PathCanonicalize(pwzAbsolutePath, pwzTempDir))
  112. {
  113. printf("Dir \"%ws\" canonicalize error\n", pwzTempDir);
  114. hr = E_FAIL;
  115. goto exit;
  116. }
  117. //If path is supposed to be a diesctory, append a trailing slash if not already there
  118. ccDir = lstrlen(pwzAbsolutePath);
  119. if (dwFlag == DIRECTORY_PATH && pwzAbsolutePath[ccDir -1] != L'\\')
  120. {
  121. pwzAbsolutePath[ccDir] = L'\\';
  122. pwzAbsolutePath[ccDir +1] = L'\0';
  123. }
  124. //Make sure the direcotry exists
  125. if (dwFlag == DIRECTORY_PATH && !bExists)
  126. {
  127. if(!PathIsDirectory(pwzAbsolutePath))
  128. {
  129. printf("Dir \"%ws\" is not a valid directory\n", pwzPath);
  130. hr = E_FAIL;
  131. goto exit;
  132. }
  133. }
  134. //Make sure the file exists
  135. else if (dwFlag == FILE_PATH)
  136. {
  137. if(!bExists)
  138. {
  139. if(!PathFileExists(pwzAbsolutePath))
  140. {
  141. printf("File \"%ws\" does not exist\n", pwzPath);
  142. hr = E_FAIL;
  143. goto exit;
  144. }
  145. }
  146. if(PathIsDirectory(pwzAbsolutePath))
  147. {
  148. printf("File \"%ws\" is a directory\n", pwzPath);
  149. hr = E_FAIL;
  150. goto exit;
  151. }
  152. }
  153. (*ppwzAbsolutePath) = WSTRDupDynamic(pwzAbsolutePath);
  154. exit:
  155. return hr;
  156. }
  157. /////////////////////////////////////////////////////////////////////////
  158. // IsUniqueManifest
  159. /////////////////////////////////////////////////////////////////////////
  160. HRESULT IsUniqueManifest(List<ManifestNode *> *pSeenAssemblyList,
  161. ManifestNode *pManifestNode)
  162. {
  163. HRESULT hr = S_OK;
  164. ManifestNode *pCurrentNode=NULL;
  165. LISTNODE pos;
  166. //cycle through list of unique manifests seen so far
  167. //if new manifest is not found, add it to the list
  168. pos = pSeenAssemblyList->GetHeadPosition();
  169. while (pos)
  170. {
  171. if (pCurrentNode = pSeenAssemblyList->GetNext(pos))
  172. {
  173. //Not Unique, go return
  174. if ((hr =pCurrentNode->IsEqual(pManifestNode)) == S_OK)
  175. {
  176. hr= S_FALSE;
  177. goto exit;
  178. }
  179. }
  180. }
  181. //No match, AsmId is unique, add it to the list
  182. //Dont release pAsmId since list doesnt ref count
  183. hr = S_OK;
  184. exit:
  185. return hr;
  186. }
  187. /////////////////////////////////////////////////////////////////////////
  188. // DequeueItem
  189. /////////////////////////////////////////////////////////////////////////
  190. HRESULT DequeueItem(List<ManifestNode*> *pList, ManifestNode** ppManifestNode)
  191. {
  192. HRESULT hr = S_OK;
  193. LISTNODE pos = NULL;
  194. (*ppManifestNode) = NULL;
  195. pos = pList->GetHeadPosition();
  196. if (!pos)
  197. {
  198. hr = S_FALSE;
  199. goto exit;
  200. }
  201. (*ppManifestNode) = pList->GetAt(pos);
  202. pList->RemoveAt(pos);
  203. exit:
  204. return hr;
  205. }
  206. /////////////////////////////////////////////////////////////////////////
  207. // ProbeForAssemblyInPath
  208. /////////////////////////////////////////////////////////////////////////
  209. HRESULT ProbeForAssemblyInPath(CString &sDeployDir, IAssemblyIdentity *pName, ManifestNode **ppManifestNode) //LPWSTR *ppwzFilePath, DWORD *pdwType)
  210. {
  211. HRESULT hr = S_OK;
  212. DWORD cbBuf = 0, ccBuf =0 ;
  213. LPWSTR pwzBuf = NULL;
  214. CString sName, sLocale, sPublicKeyToken, sCLRDisplayName, sRelativeAssemblyPath;
  215. CString sProbingPaths[6];
  216. IAssemblyIdentity *pAssemblyId= NULL;
  217. IAssemblyManifestImport *pManImport=NULL;
  218. // first try to find assembly by probing
  219. if(FAILED(hr = pName->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &cbBuf)))
  220. goto exit;
  221. sName.TakeOwnership(pwzBuf);
  222. if(FAILED(hr = pName->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzBuf, &cbBuf)))
  223. goto exit;
  224. sLocale.TakeOwnership(pwzBuf);
  225. if(FAILED(hr = pName->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf)
  226. && hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND)))
  227. goto exit;
  228. else if(hr == S_OK)
  229. sPublicKeyToken.TakeOwnership(pwzBuf);
  230. //bugbug - Hack to supress warning messages for not being able to find mscorlib
  231. if(sPublicKeyToken._pwz && !StrCmpI(sPublicKeyToken._pwz, L"b77a5c561934e089") && !StrCmpI(sName._pwz, L"mscorlib"))
  232. {
  233. hr = S_FALSE;
  234. goto exit;
  235. }
  236. //Set up the six different probing locations
  237. // 1: appBase\AssemblyName.dll
  238. // 2: appBase\AssemblyName.exe
  239. // 3: appBase\AssemblyName\AssemblyName.dll
  240. // 4: appBase\AssemblyName\AssemblyName.exe
  241. // 5: appBase\local\AssemblyName\AssemblyName.dll
  242. // 6: appBase\local\AssemblyName\AssemblyName.exe
  243. sProbingPaths[0].Assign(sDeployDir);
  244. sProbingPaths[0].Append(sName);
  245. sProbingPaths[1].Assign(sProbingPaths[0]);
  246. sProbingPaths[0].Append(L".dll");
  247. sProbingPaths[1].Append(L".exe");
  248. sProbingPaths[2].Assign(sDeployDir);
  249. sProbingPaths[2].Append(sName);
  250. sProbingPaths[2].Append(L"\\");
  251. sProbingPaths[2].Append(sName);
  252. sProbingPaths[3].Assign(sProbingPaths[2]);
  253. sProbingPaths[2].Append(L".dll");
  254. sProbingPaths[3].Append(L".exe");
  255. sProbingPaths[4].Assign(sDeployDir);
  256. sProbingPaths[4].Append(sLocale);
  257. sProbingPaths[4].Append(L"\\");
  258. sProbingPaths[4].Append(sName);
  259. sProbingPaths[4].Append(L"\\");
  260. sProbingPaths[4].Append(sName);
  261. sProbingPaths[5].Assign(sProbingPaths[4]);
  262. sProbingPaths[4].Append(L".dll");
  263. sProbingPaths[5].Append(L".exe");
  264. for (int i = 0; i < 6; i++)
  265. {
  266. //Check first to see if the file exists
  267. if (GetFileAttributes(sProbingPaths[i]._pwz) != -1)
  268. {
  269. hr = CreateAssemblyManifestImport(&pManImport, sProbingPaths[i]._pwz, NULL, 0);
  270. if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_BAD_FORMAT))
  271. goto exit;
  272. if(hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT) || (hr = pManImport->GetAssemblyIdentity(&pAssemblyId)) != S_OK)
  273. {
  274. SAFERELEASE(pManImport);
  275. continue;
  276. }
  277. //bugbug - need to make IsEqual function more robust
  278. //sanity check to make sure the assemblies are the same
  279. if (pName->IsEqual(pAssemblyId) != S_OK)
  280. {
  281. SAFERELEASE(pAssemblyId);
  282. SAFERELEASE(pManImport);
  283. continue;
  284. }
  285. // Match found
  286. (*ppManifestNode) = new ManifestNode(pManImport,
  287. sDeployDir._pwz,
  288. sProbingPaths[i]._pwz + sDeployDir._cc - 1,
  289. PRIVATE_ASSEMBLY);
  290. SAFERELEASE(pAssemblyId);
  291. SAFERELEASE(pManImport);
  292. hr = S_OK;
  293. goto exit;
  294. }
  295. }
  296. // assembly not found in this dir.
  297. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  298. exit:
  299. return hr;
  300. }
  301. /////////////////////////////////////////////////////////////////////////
  302. // ProbeForAssemblyInGAC
  303. /////////////////////////////////////////////////////////////////////////
  304. HRESULT ProbeForAssemblyInGAC(IAssemblyIdentity *pName, ManifestNode **ppManifestNode) //LPWSTR *ppwzFilePath, DWORD *pdwType)
  305. {
  306. HRESULT hr = S_OK;
  307. DWORD cbBuf = 0, ccBuf =0 ;
  308. LPWSTR pwzBuf = NULL;
  309. IAssemblyManifestImport *pManImport=NULL;
  310. CString sCLRDisplayName;
  311. WCHAR pwzPath[MAX_PATH];
  312. ASSEMBLY_INFO asmInfo;
  313. IAssemblyCache *pAsmCache = NULL;
  314. memset(&asmInfo, 0, sizeof(asmInfo));
  315. asmInfo.pszCurrentAssemblyPathBuf = pwzPath;
  316. asmInfo.cchBuf = MAX_PATH;
  317. if (FAILED(hr = CreateFusionAssemblyCache(&pAsmCache)))
  318. goto exit;
  319. if(FAILED(hr = pName->GetCLRDisplayName(NULL, &pwzBuf, &ccBuf)))
  320. goto exit;
  321. sCLRDisplayName.TakeOwnership(pwzBuf, ccBuf);
  322. if ((hr = pAsmCache->QueryAssemblyInfo(0, sCLRDisplayName._pwz, &asmInfo)) == S_OK)
  323. {
  324. // Assembly found in GAC
  325. if ((hr = CreateAssemblyManifestImport(&pManImport, asmInfo.pszCurrentAssemblyPathBuf, NULL, 0)) != S_OK)
  326. goto exit;
  327. (*ppManifestNode) = new ManifestNode(pManImport,
  328. NULL,
  329. asmInfo.pszCurrentAssemblyPathBuf,
  330. GAC_ASSEMBLY);
  331. goto exit;
  332. }
  333. exit:
  334. SAFERELEASE(pAsmCache);
  335. return hr;
  336. }
  337. /////////////////////////////////////////////////////////////////////////
  338. // ProbeForAssembly
  339. /////////////////////////////////////////////////////////////////////////
  340. HRESULT ProbeForAssembly(IAssemblyIdentity *pName, ManifestNode **ppManifestNode) //LPWSTR *ppwzFilePath, DWORD *pdwType)
  341. {
  342. HRESULT hr = S_OK;
  343. DWORD dwDirCount=0;
  344. *ppManifestNode = NULL;
  345. while(dwDirCount < g_dwDeployDirs)
  346. {
  347. if(SUCCEEDED(hr = ProbeForAssemblyInPath( g_sDeployDirs[dwDirCount],
  348. pName, ppManifestNode)))
  349. goto exit;
  350. dwDirCount++;
  351. }
  352. if( (IsKnownAssembly(pName, KNOWN_SYSTEM_ASSEMBLY) == S_OK)
  353. && (!g_bCopyDependentSystemAssemblies) )
  354. {
  355. hr = S_FALSE; // ignore system dependencies
  356. goto exit;
  357. }
  358. if( g_bLookInGACForDependencies )
  359. {
  360. //Can't find assembly by probing
  361. //Try to find the assembly in the GAC.
  362. if(SUCCEEDED(hr = ProbeForAssemblyInGAC(pName, ppManifestNode)))
  363. goto exit;
  364. }
  365. // assembly not found
  366. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  367. exit:
  368. return hr;
  369. }
  370. /////////////////////////////////////////////////////////////////////////
  371. // FindAssemblies
  372. // note: Assumes that pwzDir has a trailing slash.
  373. /////////////////////////////////////////////////////////////////////////
  374. HRESULT FindAllAssemblies (LPWSTR pwzDir, List<ManifestNode *> *pManifestList)
  375. {
  376. HRESULT hr = S_OK;
  377. HANDLE hFind = INVALID_HANDLE_VALUE;
  378. WIN32_FIND_DATA fdFile;
  379. IAssemblyIdentity *pTempAsmId=NULL;
  380. IAssemblyManifestImport *pManifestImport = NULL;
  381. ManifestNode *pManifestNode = NULL;
  382. CString sSearchString;
  383. DWORD dwLastError = 0;
  384. // set up search string to find all files in the passed in directory
  385. sSearchString.Assign(pwzDir);
  386. sSearchString.Append(L"*");
  387. if (sSearchString._cc > MAX_PATH)
  388. {
  389. hr = CO_E_PATHTOOLONG;
  390. printf("Error: Search path too long\n");
  391. goto exit;
  392. }
  393. hFind = FindFirstFile(sSearchString._pwz, &fdFile);
  394. if (hFind == INVALID_HANDLE_VALUE)
  395. {
  396. // BUGBUG - getlasterror() ?
  397. hr = E_FAIL;
  398. printf("Find file error\n");
  399. goto exit;
  400. }
  401. //enumerate through all the files in the directory,
  402. // and recursivly call FindAllAssemblies on any directories encountered
  403. while(TRUE)
  404. {
  405. if (StrCmp(fdFile.cFileName, L".") != 0 && StrCmp(fdFile.cFileName, L"..") != 0)
  406. {
  407. CString sFilePath;
  408. //create absolute file name by appending the filename to the dir name
  409. sFilePath.Assign(pwzDir);
  410. sFilePath.Append(fdFile.cFileName);
  411. if (sSearchString._cc > MAX_PATH)
  412. {
  413. hr = CO_E_PATHTOOLONG;
  414. printf("Error: File path too long\n");
  415. goto exit;
  416. }
  417. //If the file is a directory, recursivly call FindAllAssemblies
  418. if ((fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
  419. {
  420. sFilePath.Append(L"\\");
  421. if (FAILED(hr = FindAllAssemblies(sFilePath._pwz, pManifestList)))
  422. goto exit;
  423. }
  424. // If a file, check to see if it is a Assembly, if it is, add it to our master list
  425. else
  426. {
  427. if((hr = CreateAssemblyManifestImport(&pManifestImport, sFilePath._pwz, NULL, 0)) == S_OK)
  428. {
  429. // check to make sure file we just opened wasnt just an XML file
  430. if ((hr =pManifestImport->GetAssemblyIdentity(&pTempAsmId)) == S_OK)
  431. {
  432. // List does not AddRef, so dont release pManifestImport and refcount will stay at one
  433. // Clean up after list is no longer needed.
  434. pManifestNode = new ManifestNode(pManifestImport,
  435. g_sAppBase._pwz,
  436. sFilePath._pwz+g_sAppBase._cc-1,
  437. PRIVATE_ASSEMBLY);
  438. pManifestList->AddTail(pManifestNode);
  439. SAFERELEASE(pTempAsmId);
  440. }
  441. else if (FAILED(hr))
  442. goto exit;
  443. SAFERELEASE(pManifestImport);
  444. }
  445. }
  446. }
  447. if (!FindNextFile(hFind, &fdFile))
  448. {
  449. dwLastError = GetLastError();
  450. break;
  451. }
  452. }
  453. if(dwLastError == ERROR_NO_MORE_FILES)
  454. hr = S_OK;
  455. else
  456. hr = HRESULT_FROM_WIN32(dwLastError);
  457. exit:
  458. return hr;
  459. }
  460. /////////////////////////////////////////////////////////////////////////
  461. // TraverseManifestDependencyTree
  462. /////////////////////////////////////////////////////////////////////////
  463. HRESULT TraverseManifestDependencyTrees(List<ManifestNode *> *pManifestList,
  464. List<LPWSTR> *pAssemblyFileList, List<ManifestNode *> *pUniqueAssemblyList, BOOL bListMode)
  465. {
  466. HRESULT hr = S_OK;
  467. IAssemblyManifestImport *pDepManifestImport=NULL;
  468. IManifestInfo *pDepAsmInfo=NULL, *pFileInfo=NULL;
  469. IAssemblyIdentity *pAsmId=NULL;
  470. ManifestNode *pManifestNode=NULL, *pDepManifestNode = NULL;
  471. LPWSTR pwz = NULL;
  472. DWORD index = 0, cb = 0, cc = 0, dwFlag = 0, dwHash=0, dwType=0;
  473. CString sFileName, sRelativeFilePath, sAbsoluteFilePath, sBuffer, sManifestName;
  474. while((hr = DequeueItem(pManifestList, &pManifestNode)) == S_OK)
  475. {
  476. // If Assembly has already been parsed, no need doing it again, skip to the next assembly
  477. if ((hr = IsUniqueManifest(pUniqueAssemblyList, pManifestNode)) != S_OK)
  478. {
  479. SAFEDELETE(pManifestNode);
  480. continue;
  481. }
  482. pUniqueAssemblyList->AddTail(pManifestNode);
  483. pManifestNode->GetManifestFilePath(&pwz);
  484. sManifestName.TakeOwnership(pwz);
  485. //If the manifest was found by probing, add its name to the list of files
  486. hr =pManifestNode->GetManifestType(&dwType);
  487. if (dwType == PRIVATE_ASSEMBLY)
  488. {
  489. dwHash = HashString(sManifestName._pwz, HASHTABLE_SIZE, false);
  490. pAssemblyFileList[dwHash].AddTail(WSTRDupDynamic(sManifestName._pwz));
  491. //need the relative dir path of the manifest rwt the app base for future use
  492. sRelativeFilePath.Assign(sManifestName);
  493. sRelativeFilePath.RemoveLastElement();
  494. 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).
  495. sRelativeFilePath.Append(L"\\");
  496. }
  497. if(bListMode)
  498. fprintf(stderr, "\nAssembly %ws:\n", sManifestName._pwz);
  499. //Add all dependant assemblies to the queue to be later traversed
  500. while ((hr = pManifestNode->GetNextAssembly(index++, &pDepAsmInfo)) == S_OK)
  501. {
  502. if(FAILED(hr = pDepAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_ID, (LPVOID *)&pAsmId, &cb, &dwFlag)))
  503. goto exit;
  504. pAsmId->GetDisplayName(ASMID_DISPLAYNAME_NOMANGLING, &pwz, &cc);
  505. //Try to find the assembly by first probing, then by checking in the GAC.
  506. if(FAILED(hr = ProbeForAssembly(pAsmId, &pDepManifestNode)))
  507. {
  508. //Assembly not found, display warning message
  509. //Bugbug, should mg still spit out a manifest knowing that things are missing?
  510. fprintf(stderr, "WRN: Unable to find dependency %ws. in manifest %ws\n", pwz, sManifestName._pwz);
  511. if(g_bFailOnWarnings)
  512. {
  513. fprintf(stderr, "Warning treated as error. mg exiting....\n");
  514. hr = E_FAIL;
  515. goto exit;
  516. }
  517. SAFERELEASE(pAsmId);
  518. continue;
  519. }
  520. else if (hr == S_OK)
  521. {
  522. //Dont release since no add refing in the list is taking place
  523. if ((hr = IsUniqueManifest(pUniqueAssemblyList, pDepManifestNode)) == S_OK)
  524. pManifestList->AddTail(pDepManifestNode);
  525. SAFERELEASE(pAsmId);
  526. if(bListMode)
  527. fprintf(stderr, "\tDependant Assembly: %ws\n", pwz);
  528. }
  529. SAFERELEASE(pDepAsmInfo);
  530. }
  531. // Add all files to hash table
  532. index = 0;
  533. pManifestNode->GetManifestType(&dwType);
  534. while (dwType == PRIVATE_ASSEMBLY && pManifestNode->GetNextFile(index++, &pFileInfo) == S_OK)
  535. {
  536. LPWSTR pwzFileName = NULL;
  537. if(FAILED(pFileInfo->Get(MAN_INFO_ASM_FILE_NAME, (LPVOID *)&pwz, &cb, &dwFlag)))
  538. goto exit;
  539. sBuffer.TakeOwnership(pwz);
  540. sFileName.Assign(sRelativeFilePath);
  541. sFileName.Append(sBuffer);
  542. sAbsoluteFilePath.Assign(g_sAppBase);
  543. sAbsoluteFilePath.Append(sFileName);
  544. sFileName.ReleaseOwnership(&pwzFileName);
  545. dwHash = HashString(pwzFileName, HASHTABLE_SIZE, false);
  546. pAssemblyFileList[dwHash].AddTail(pwzFileName);
  547. //If file is listed as part of an assembly, but cannot be found, display a warning.
  548. //Bugbug, should mg still spit out a manifest knowing that things are missing?
  549. if(!PathFileExists(sAbsoluteFilePath._pwz))
  550. printf("Warning: File \"%ws\" does not exist and is called out in \"%ws\"\n",sAbsoluteFilePath._pwz, sManifestName._pwz);
  551. if(bListMode)
  552. fprintf(stderr, "\tDependant File: %ws\n", pwzFileName);
  553. //Release ownership since string is now part of hash table and hash table does not ref count
  554. // sFileName.ReleaseOwnership();
  555. }
  556. }
  557. hr = S_OK;
  558. exit:
  559. return hr;
  560. }
  561. /////////////////////////////////////////////////////////////////////////
  562. // CrossReferenceFiles
  563. /////////////////////////////////////////////////////////////////////////
  564. HRESULT CrossReferenceFiles(LPWSTR pwzDir, List<LPWSTR> *pAssemblyFileList, List<LPWSTR> *pRawFiles)
  565. {
  566. HRESULT hr = S_OK;
  567. HANDLE hFind = INVALID_HANDLE_VALUE;
  568. WIN32_FIND_DATA fdFile;
  569. DWORD dwHash = 0;
  570. LISTNODE pos;
  571. LPWSTR pwzBuf=NULL;
  572. bool bRawFile = FALSE;
  573. DWORD dwLastError = 0;
  574. CString sSearchString;
  575. // set up search string to find all files in the passed in directory
  576. sSearchString.Assign(pwzDir);
  577. sSearchString.Append(L"*");
  578. if (sSearchString._cc > MAX_PATH)
  579. {
  580. hr = CO_E_PATHTOOLONG;
  581. printf("Error: Search path too long\n");
  582. goto exit;
  583. }
  584. hFind = FindFirstFile(sSearchString._pwz, &fdFile);
  585. if (hFind == INVALID_HANDLE_VALUE)
  586. {
  587. hr = E_FAIL;
  588. printf("Find file error\n");
  589. goto exit;
  590. }
  591. //enumerate through all the files in the directory,
  592. // and recursivly call FindAllAssemblies on any directories encountered
  593. while(TRUE)
  594. {
  595. if (StrCmp(fdFile.cFileName, L".") != 0 && StrCmp(fdFile.cFileName, L"..") != 0)
  596. {
  597. CString sFilePath;
  598. //create absolute file name by appending the filename to the dir name
  599. sFilePath.Assign(pwzDir);
  600. sFilePath.Append(fdFile.cFileName);
  601. if (sSearchString._cc > MAX_PATH)
  602. {
  603. hr = CO_E_PATHTOOLONG;
  604. printf("Error: Search path too long\n");
  605. goto exit;
  606. }
  607. //if file is actually a direcoty, recrusivly call crossRefernceFiles on the Directory
  608. if ((fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
  609. {
  610. sFilePath.Append(L"\\");
  611. if (FAILED(hr = CrossReferenceFiles(sFilePath._pwz, pAssemblyFileList, pRawFiles)))
  612. goto exit;
  613. }
  614. else
  615. {
  616. //Check to see if the file is in the hash table.
  617. //If it isnt, then we know it is not called out from any assembly
  618. //add it to the Raw file list
  619. bRawFile = TRUE;
  620. dwHash = HashString(sFilePath._pwz+g_sAppBase._cc - 1, HASHTABLE_SIZE, false);
  621. pos = pAssemblyFileList[dwHash].GetHeadPosition();
  622. while (pos)
  623. {
  624. pwzBuf = pAssemblyFileList[dwHash].GetNext(pos);
  625. if (!StrCmpI(pwzBuf, sFilePath._pwz+g_sAppBase._cc - 1))
  626. {
  627. bRawFile = FALSE;
  628. break;
  629. }
  630. }
  631. if (bRawFile)
  632. {
  633. pwzBuf = WSTRDupDynamic(sFilePath._pwz+g_sAppBase._cc - 1);
  634. pRawFiles->AddTail(pwzBuf);
  635. }
  636. }
  637. }
  638. // BUGBUG - do fnf, check error.
  639. if (!FindNextFile(hFind, &fdFile))
  640. {
  641. dwLastError = GetLastError();
  642. break;
  643. }
  644. }
  645. if(dwLastError == ERROR_NO_MORE_FILES)
  646. hr = S_OK;
  647. else
  648. hr = HRESULT_FROM_WIN32(dwLastError);
  649. exit:
  650. return hr;
  651. }
  652. /////////////////////////////////////////////////////////////////////////
  653. // CopyRawFile
  654. /////////////////////////////////////////////////////////////////////////
  655. HRESULT CopyRawFile(LPWSTR pwzFilePath)
  656. {
  657. HRESULT hr = S_OK;
  658. CString sDest;
  659. CString sSrc;
  660. sDest.Assign(g_sTargetDir);
  661. sDest.Append(pwzFilePath); // this should be relative path ...
  662. if(FAILED(hr = CreateDirectoryHierarchy(sDest._pwz, NULL)))
  663. goto exit;
  664. sSrc.Assign(g_sAppBase);
  665. sSrc.Append(pwzFilePath);
  666. printf(" Copying RawFile from <%ws> TO <%ws> \n", sSrc._pwz, sDest._pwz);
  667. if(!::CopyFile(sSrc._pwz, sDest._pwz, FALSE))
  668. {
  669. hr = FusionpHresultFromLastError();
  670. goto exit;
  671. }
  672. exit:
  673. return hr;
  674. }
  675. /////////////////////////////////////////////////////////////////////////
  676. // CopyAssemblyBits
  677. /////////////////////////////////////////////////////////////////////////
  678. HRESULT CopyAssemblyBits(CString &sSrcDir, CString &sDestDir, ManifestNode *pManifestNode)
  679. {
  680. HRESULT hr = S_OK;
  681. DWORD nIndex=0;
  682. DWORD dwFlag;
  683. DWORD cbBuf;
  684. LPWSTR pwzBuf=NULL;
  685. IManifestInfo *pFileInfo = NULL;
  686. if(FAILED(hr = CreateDirectoryHierarchy(sDestDir._pwz, NULL)))
  687. goto exit;
  688. if(!::CopyFile(sSrcDir._pwz, sDestDir._pwz, FALSE))
  689. {
  690. hr = FusionpHresultFromLastError();
  691. goto exit;
  692. }
  693. //copy all file dependecies of the assembly as well
  694. nIndex = 0;
  695. while (pManifestNode->GetNextFile(nIndex++, &pFileInfo) == S_OK)
  696. {
  697. if(FAILED(pFileInfo->Get(MAN_INFO_ASM_FILE_NAME, (LPVOID *)&pwzBuf, &cbBuf, &dwFlag)))
  698. goto exit;
  699. // sRelativeFilePath.TakeOwnership(pwzBuf, ccBuf);
  700. sSrcDir.RemoveLastElement();
  701. sSrcDir.Append(L"\\");
  702. sSrcDir.Append(pwzBuf);
  703. sDestDir.RemoveLastElement();
  704. sDestDir.Append(L"\\");
  705. sDestDir.Append(pwzBuf);
  706. // CreateDirectoryHierarchy(sPrivateAssemblyDir._pwz, sRelativeFilePath._pwz);
  707. if(!::CopyFile(sSrcDir._pwz, sDestDir._pwz, FALSE))
  708. {
  709. hr = FusionpHresultFromLastError();
  710. goto exit;
  711. }
  712. SAFEDELETEARRAY(pwzBuf);
  713. SAFERELEASE(pFileInfo);
  714. }
  715. exit :
  716. SAFEDELETEARRAY(pwzBuf);
  717. SAFERELEASE(pFileInfo);
  718. return hr;
  719. }
  720. /////////////////////////////////////////////////////////////////////////
  721. // CopyAssembly
  722. /////////////////////////////////////////////////////////////////////////
  723. HRESULT CopyAssembly(ManifestNode *pManifestNode)
  724. {
  725. HRESULT hr = S_OK;
  726. CString sDest;
  727. CString sSrc;
  728. LPWSTR pwzManifestFilePath = NULL;
  729. LPWSTR pwzSrcDir=NULL;
  730. LPWSTR pwzTemp = NULL;
  731. DWORD dwType;
  732. IAssemblyIdentity *pAssemblyId = NULL;
  733. CString sAssemblyName;
  734. hr = pManifestNode->GetManifestFilePath(&pwzManifestFilePath);
  735. hr = pManifestNode->GetManifestType(&dwType);
  736. sDest.Assign(g_sTargetDir);
  737. if (dwType == PRIVATE_ASSEMBLY)
  738. {
  739. sDest.Append(pwzManifestFilePath); // this should be relative path ...
  740. if(FAILED(hr = pManifestNode->GetSrcRootDir(&pwzSrcDir)))
  741. goto exit;
  742. sSrc.Assign(pwzSrcDir);
  743. sSrc.Append(pwzManifestFilePath);
  744. }
  745. else if (dwType == GAC_ASSEMBLY)
  746. {
  747. LPWSTR pwzBuf = NULL;
  748. DWORD ccBuf = 0;
  749. pManifestNode->GetAssemblyIdentity(&pAssemblyId);
  750. if(FAILED(hr = pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  751. &pwzBuf,
  752. &ccBuf)))
  753. goto exit;
  754. if(!(pwzTemp = PathFindFileName(pwzManifestFilePath)))
  755. {
  756. hr = E_FAIL;
  757. goto exit;
  758. }
  759. sAssemblyName.TakeOwnership(pwzBuf);
  760. sAssemblyName.Append(L"\\");
  761. sAssemblyName.Append(pwzTemp); // manifest file name of the GAC assembly.
  762. sDest.Append(sAssemblyName);
  763. sSrc.Assign(pwzManifestFilePath);
  764. }
  765. printf(" Copying Assembly Man from <%ws> TO <%ws> \n", sSrc._pwz, sDest._pwz);
  766. hr = CopyAssemblyBits(sSrc, sDest, pManifestNode);
  767. if (dwType == GAC_ASSEMBLY)
  768. {
  769. // set the install codebase of the assembly copied from GAC
  770. // to that of its relative path in target dir. This will be written to manifest ??
  771. hr = pManifestNode->SetManifestFilePath(sAssemblyName._pwz);
  772. }
  773. exit:
  774. SAFEDELETEARRAY(pwzSrcDir);
  775. SAFEDELETEARRAY(pwzManifestFilePath);
  776. SAFERELEASE(pAssemblyId);
  777. return hr;
  778. }
  779. /////////////////////////////////////////////////////////////////////////
  780. // CopyFilesToTargetDir
  781. /////////////////////////////////////////////////////////////////////////
  782. HRESULT CopyFilesToTargetDir(List<ManifestNode*> *pUniqueManifestList, List<LPWSTR> *pRawFiles)
  783. {
  784. HRESULT hr = S_OK;
  785. ManifestNode *pManifestNode = NULL;
  786. LISTNODE pos;
  787. LPWSTR pwzBuf;
  788. //Cycle through all of the unique manifests
  789. pos = pUniqueManifestList->GetHeadPosition();
  790. while (pos)
  791. {
  792. pManifestNode = pUniqueManifestList->GetNext(pos);
  793. //if the manifest was found by probing initially, then it is already in the Appbase's directory
  794. //continue to the next manifest
  795. //if the manifest was found in the GAC and is not a system assembly, copy the
  796. //assembly into the Appbase
  797. if(FAILED(hr = CopyAssembly(pManifestNode)))
  798. goto exit;
  799. }
  800. //Copy RawFiles to Target Dir
  801. pos = pRawFiles->GetHeadPosition();
  802. while (pos)
  803. {
  804. pwzBuf = pRawFiles->GetNext(pos);
  805. if(FAILED(hr = CopyRawFile(pwzBuf)))
  806. goto exit;
  807. }
  808. exit:
  809. return hr;
  810. }
  811. /////////////////////////////////////////////////////////////////////////
  812. // PrivatizeAssemblies
  813. /////////////////////////////////////////////////////////////////////////
  814. HRESULT PrivatizeAssemblies(List<ManifestNode*> *pUniqueManifestList)
  815. {
  816. HRESULT hr = S_OK;
  817. ManifestNode *pManifestNode = NULL;
  818. LISTNODE pos;
  819. LPWSTR pwzBuf =NULL;
  820. DWORD dwType = 0, ccBuf = 0, cbBuf = 0, dwFlag = 0, nIndex = 0;
  821. IAssemblyIdentity *pAssemblyId = NULL;
  822. IManifestInfo *pFileInfo = NULL;
  823. WCHAR pwzPath[MAX_PATH];
  824. ASSEMBLY_INFO asmInfo;
  825. IAssemblyCache *pAsmCache = NULL;
  826. CString sPublicKeyToken, sCLRDisplayName;
  827. CString sAssemblyName, sAssemblyManifestFileName;
  828. CString sPrivateAssemblyPath, sPrivateAssemblyDir;
  829. CString sAssemblyGACPath, sAssemblyGACDir;
  830. CString sRelativeFilePath, sFileGACPath, sFilePrivatePath;
  831. CString sBuffer;
  832. memset(&asmInfo, 0, sizeof(asmInfo));
  833. asmInfo.pszCurrentAssemblyPathBuf = pwzPath;
  834. asmInfo.cchBuf = MAX_PATH;
  835. if (FAILED(hr = CreateFusionAssemblyCache(&pAsmCache)))
  836. goto exit;
  837. //Cycle through all of the unique manifests
  838. pos = pUniqueManifestList->GetHeadPosition();
  839. while (pos)
  840. {
  841. pManifestNode = pUniqueManifestList->GetNext(pos);
  842. hr = pManifestNode->GetManifestType(&dwType);
  843. //if the manifest was found by probing initially, then it is already in the Appbase's directory
  844. //continue to the next manifest
  845. //if the manifest was found in the GAC and is not a system assembly, copy the
  846. //assembly into the Appbase
  847. if (dwType == PRIVATE_ASSEMBLY)
  848. continue;
  849. else if (dwType == GAC_ASSEMBLY)
  850. {
  851. pManifestNode->GetAssemblyIdentity(&pAssemblyId);
  852. hr = pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf);
  853. sPublicKeyToken.TakeOwnership(pwzBuf);
  854. //if the assembly is a system assembly, skip to next manifest
  855. if (!StrCmpI(sPublicKeyToken._pwz, L"b77a5c561934e089") || !StrCmpI(sPublicKeyToken._pwz, L"b03f5f7f11d50a3a"))
  856. {
  857. SAFERELEASE(pAssemblyId);
  858. continue;
  859. }
  860. //get the assemblies dir by making a call into CreateAssemblyCache
  861. if(FAILED(hr = pAssemblyId->GetCLRDisplayName(NULL, &pwzBuf, &ccBuf)))
  862. goto exit;
  863. sCLRDisplayName.TakeOwnership(pwzBuf, ccBuf);
  864. if ((hr = pAsmCache->QueryAssemblyInfo(0, sCLRDisplayName._pwz, &asmInfo)) != S_OK)
  865. goto exit;
  866. sAssemblyGACPath.Assign(asmInfo.pszCurrentAssemblyPathBuf);
  867. sAssemblyGACPath.LastElement(sAssemblyManifestFileName);
  868. sAssemblyGACDir.Assign(sAssemblyGACPath);
  869. sAssemblyGACDir.RemoveLastElement();
  870. hr = pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf);
  871. sAssemblyName.TakeOwnership(pwzBuf);
  872. //set up the new directory to store the assembly in
  873. // g_sAppBase\assemblyname\,
  874. sPrivateAssemblyDir.Assign(g_sAppBase);
  875. sPrivateAssemblyDir.Append(sAssemblyName);
  876. sPrivateAssemblyDir.Append(L"\\");
  877. CreateDirectoryHierarchy(sPrivateAssemblyDir._pwz, sAssemblyManifestFileName._pwz);
  878. sPrivateAssemblyPath.Assign(sPrivateAssemblyDir);
  879. sPrivateAssemblyPath.Append(sAssemblyManifestFileName);
  880. ::CopyFile(sAssemblyGACPath._pwz, sPrivateAssemblyPath._pwz, FALSE);
  881. //copy all file dependecies of the assembly as well
  882. nIndex = 0;
  883. while (pManifestNode->GetNextFile(nIndex++, &pFileInfo) == S_OK)
  884. {
  885. if(FAILED(pFileInfo->Get(MAN_INFO_ASM_FILE_NAME, (LPVOID *)&pwzBuf, &cbBuf, &dwFlag)))
  886. goto exit;
  887. sRelativeFilePath.TakeOwnership(pwzBuf, ccBuf);
  888. sFileGACPath.Assign(sAssemblyGACDir);
  889. sFileGACPath.Append(sRelativeFilePath);
  890. sFilePrivatePath.Assign(sPrivateAssemblyDir);
  891. sFilePrivatePath.Append(sRelativeFilePath);
  892. CreateDirectoryHierarchy(sPrivateAssemblyDir._pwz, sRelativeFilePath._pwz);
  893. ::CopyFile(sFileGACPath._pwz, sFilePrivatePath._pwz, FALSE);
  894. }
  895. //update the manifestnode's FileName field with the new relative path wrt the Appbase
  896. pManifestNode->SetManifestFilePath(sPrivateAssemblyPath._pwz + g_sAppBase._cc - 1);
  897. pManifestNode->SetManifestType(PRIVATE_ASSEMBLY);
  898. SAFERELEASE(pAssemblyId);
  899. }
  900. }
  901. exit:
  902. SAFERELEASE(pAsmCache);
  903. return hr;
  904. }
  905. /////////////////////////////////////////////////////////////////////////
  906. //GetInitialDependencies
  907. /////////////////////////////////////////////////////////////////////////
  908. //Bugbug, Big Avalon Hack
  909. HRESULT GetInitialDependencies(LPWSTR pwzTemplatePath, List<ManifestNode *> *pManifestList)
  910. {
  911. HRESULT hr = S_OK;
  912. IXMLDOMDocument2 *pXMLDoc = NULL;
  913. IXMLDOMNode *pRootNode = NULL, *pSearchNode = NULL;
  914. BSTR bstrSearchString=NULL;
  915. ManifestNode *pManifestNode = NULL;
  916. WCHAR pwzPath[MAX_PATH];
  917. ASSEMBLY_INFO asmInfo;
  918. IAssemblyCache *pAsmCache = NULL;
  919. IAssemblyManifestImport *pManImport = NULL;
  920. if(FAILED(hr = LoadXMLDocument(pwzTemplatePath, &pXMLDoc)))
  921. goto exit;
  922. if(FAILED(hr = pXMLDoc->get_firstChild(&pRootNode)))
  923. goto exit;
  924. bstrSearchString = ::SysAllocString(L"//shellState[@entryImageType=\"avalon\"]");
  925. if (!bstrSearchString)
  926. {
  927. hr = E_OUTOFMEMORY;
  928. goto exit;
  929. }
  930. if (FAILED(hr = pRootNode->selectSingleNode(bstrSearchString, &pSearchNode)))
  931. {
  932. hr = S_FALSE;
  933. goto exit;
  934. }
  935. if (pSearchNode)
  936. {
  937. // Try to find the assembly in the GAC.
  938. memset(&asmInfo, 0, sizeof(asmInfo));
  939. asmInfo.pszCurrentAssemblyPathBuf = pwzPath;
  940. asmInfo.cchBuf = MAX_PATH;
  941. if (FAILED(hr = CreateFusionAssemblyCache(&pAsmCache)))
  942. goto exit;
  943. if ((hr = pAsmCache->QueryAssemblyInfo(0, L"Avalon.Application", &asmInfo)) == S_OK)
  944. {
  945. if ((hr = CreateAssemblyManifestImport(&pManImport, asmInfo.pszCurrentAssemblyPathBuf, NULL, 0)) != S_OK)
  946. goto exit;
  947. pManifestNode = new ManifestNode(pManImport,
  948. NULL,
  949. asmInfo.pszCurrentAssemblyPathBuf,
  950. GAC_ASSEMBLY);
  951. pManifestList->AddTail(pManifestNode);
  952. }
  953. else
  954. {
  955. hr = S_FALSE;
  956. fprintf(stderr, "Warning: Cannot find Avalon Runtime in GAC\n");
  957. }
  958. }
  959. exit:
  960. if (bstrSearchString)
  961. ::SysFreeString(bstrSearchString);
  962. SAFERELEASE(pSearchNode);
  963. SAFERELEASE(pRootNode);
  964. SAFERELEASE(pXMLDoc);
  965. SAFERELEASE(pManImport);
  966. SAFERELEASE(pAsmCache);
  967. return hr;
  968. }
  969. /////////////////////////////////////////////////////////////////////////
  970. // CreateSubscriptionManifest
  971. /////////////////////////////////////////////////////////////////////////
  972. HRESULT CreateSubscriptionManifest(LPWSTR pwzApplicationManifestPath,
  973. LPWSTR pwzSubscriptionManifestPath, LPWSTR pwzURL, LPWSTR pwzPollingInterval)
  974. {
  975. HRESULT hr = S_OK;
  976. IAssemblyManifestImport *pManImport = NULL;
  977. IAssemblyIdentity *pAppAssemblyId = NULL;
  978. CString sSubAssemblyName, sSubcriptionFilePath;
  979. LPWSTR pwzBuf = NULL;
  980. DWORD ccBuf = NULL;
  981. //createmanifest on the input file
  982. if(FAILED(hr = CreateAssemblyManifestImport(&pManImport, pwzApplicationManifestPath, NULL, 0)))
  983. goto exit;
  984. if((hr = pManImport->GetAssemblyIdentity(&pAppAssemblyId)) != S_OK)
  985. {
  986. hr = E_FAIL;
  987. goto exit;
  988. }
  989. //grab the name of the assembly
  990. //appended with ".subscription", this will be the subscription manifest name
  991. if(FAILED(hr = pAppAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  992. &pwzBuf, &ccBuf)))
  993. goto exit;
  994. sSubAssemblyName.TakeOwnership(pwzBuf, ccBuf);
  995. sSubAssemblyName.Append(L".subscription");
  996. sSubcriptionFilePath.Assign(pwzSubscriptionManifestPath);
  997. sSubcriptionFilePath.Append(sSubAssemblyName);
  998. if(FAILED(hr = CreateDirectoryHierarchy(sSubcriptionFilePath._pwz, NULL)))
  999. goto exit;
  1000. if(FAILED(hr = CreateXMLSubscriptionManifest(sSubcriptionFilePath._pwz, pAppAssemblyId, pwzURL, pwzPollingInterval)))
  1001. goto exit;
  1002. exit:
  1003. SAFERELEASE(pManImport);
  1004. SAFERELEASE(pAppAssemblyId);
  1005. return hr;
  1006. }
  1007. /////////////////////////////////////////////////////////////////////////
  1008. // PrintDependencies
  1009. /////////////////////////////////////////////////////////////////////////
  1010. HRESULT PrintDependencies(List <LPWSTR> *pRawFileList, List<ManifestNode *> *pUniqueManifestList)
  1011. {
  1012. HRESULT hr = S_OK;
  1013. LPWSTR pwzBuf = NULL, pwz= NULL;
  1014. DWORD dwType = 0;
  1015. ManifestNode *pManifestNode = NULL;
  1016. LISTNODE pos;
  1017. pos = pRawFileList->GetHeadPosition();
  1018. while(pos)
  1019. {
  1020. pwzBuf = pRawFileList->GetNext(pos);
  1021. fprintf(stderr, "Raw File : %ws\n", pwzBuf);
  1022. }
  1023. pos = pUniqueManifestList->GetHeadPosition();
  1024. while(pos)
  1025. {
  1026. pManifestNode = pUniqueManifestList->GetNext(pos);
  1027. pManifestNode->GetManifestFilePath(&pwzBuf);
  1028. pManifestNode->GetManifestType(&dwType);
  1029. if (dwType == PRIVATE_ASSEMBLY)
  1030. fprintf(stderr, "Manifest : %ws\n", pwzBuf);
  1031. else
  1032. {
  1033. pwz = StrRChr(pwzBuf, NULL, L'\\') + 1;
  1034. fprintf(stderr, "GAC Manifest : %ws\n", pwz);
  1035. }
  1036. SAFEDELETEARRAY(pwzBuf);
  1037. }
  1038. return hr;
  1039. }
  1040. /////////////////////////////////////////////////////////////////////////
  1041. // UsageTopLevel
  1042. /////////////////////////////////////////////////////////////////////////
  1043. HRESULT UsageTopLevel()
  1044. {
  1045. printf("Manifest Generator Usage: \n"
  1046. "mg -<mode> [<param_name>:<param_value> ... ]\n"
  1047. "Modes supported in mg\n"
  1048. "t: Generate Template File Mode\n"
  1049. "l: List Mode\n"
  1050. "d: List Dependency Mode\n"
  1051. "s: Subscription Manifest Gereration Mode \n"
  1052. "m: Manifest Generation Mode\n\n"
  1053. "For help on a Mode, Use \"mg -<mode> help\" \n"
  1054. "Valid <param_name>:<param_value> pairs \n"
  1055. "sd:<source_directory_path> \n"
  1056. "td:<target_dir> \n"
  1057. "dd:<dependency_dir> \n"
  1058. "tf:<template_file_path> \n"
  1059. "smd:<subscription_dir> \n"
  1060. "amf:<app_man_file> \n"
  1061. "amu:<app_man_URL> \n"
  1062. "si:<sync_interval> \n"
  1063. "WRN:allow -- meaning allow warnings. Deafault is exit on warnings.\n"
  1064. "GAC:follow -- meaning follow dependencies on GAC. Default is don't probe for dependencies in GAC\n"
  1065. "SYS:copy -- copy dependent system assemblies from GAC to target dir\n"
  1066. );
  1067. return S_OK;
  1068. }
  1069. /////////////////////////////////////////////////////////////////////////
  1070. // UsageCmdTemplate
  1071. /////////////////////////////////////////////////////////////////////////
  1072. HRESULT UsageCmdTemplate()
  1073. {
  1074. printf("Usage: \n"
  1075. "Template Mode:\n"
  1076. "mg -t tf:<file_path>\n\n"
  1077. "\t<file_path> = path where template manifest will be created.\n\n"
  1078. );
  1079. return S_OK;
  1080. }
  1081. /////////////////////////////////////////////////////////////////////////
  1082. // UsageCmdList
  1083. /////////////////////////////////////////////////////////////////////////
  1084. HRESULT UsageCmdList()
  1085. {
  1086. printf("Usage: \n"
  1087. "List Mode:\n"
  1088. "mg -l sd:<source_directory_path> [tf:<template_file_path>] [dd:<dependency_dir> \n\n"
  1089. "\t[source_directory_path] = path of Application to chase dependencies\n"
  1090. "\toptional: <template_file_path> = path of Template file\n"
  1091. "\toptional : <dependency_dir> = user defined dependency dir where some dependencies could be found\n\n"
  1092. );
  1093. return S_OK;
  1094. }
  1095. /////////////////////////////////////////////////////////////////////////
  1096. // UsageCmdDependencyList
  1097. /////////////////////////////////////////////////////////////////////////
  1098. HRESULT UsageCmdDependencyList()
  1099. {
  1100. printf("Usage: \n"
  1101. "List Dependency Mode:\n"
  1102. "mg -d sd:<source_directory_path> [dd:<dependency_dir> \n\n"
  1103. "\t<source_directory path> = path of Application to chase dependencies\n\n"
  1104. "\toptional : <dependency_dir> = user defined dependency dir where some dependencies could be found\n\n"
  1105. );
  1106. return S_OK;
  1107. }
  1108. /////////////////////////////////////////////////////////////////////////
  1109. // UsageCmdSubscription
  1110. /////////////////////////////////////////////////////////////////////////
  1111. HRESULT UsageCmdSubscription()
  1112. {
  1113. printf("Usage: \n"
  1114. "Subscription Manifest Gereration Mode:\n"
  1115. "mg -s smd:<subscription_dir> amf:<app_man_file> amu:<app_man_URL> [si:<sync_interval>] \n\n"
  1116. "\t<subscription_dir> = path where subscription manifest will be created\n"
  1117. "\t<app_man_file> = path to the Application manifest you wish to generate a subscription for\n"
  1118. "\t<app_man_URL] = URL of application manifest\n"
  1119. "\toptional: <sync_interval] = syncronize interval in hours\n\n"
  1120. );
  1121. return S_OK;
  1122. }
  1123. /////////////////////////////////////////////////////////////////////////
  1124. // UsageCmdManifest
  1125. /////////////////////////////////////////////////////////////////////////
  1126. HRESULT UsageCmdManifest()
  1127. {
  1128. printf("Usage: \n"
  1129. "Manifest Generation Mode:\n"
  1130. "mg -m sd:<source_dir> td:<target_dir> tf:<template_file> [dd:<dependency_dir>]\n\n"
  1131. "\t<source_dir> = path of the Application of which you want to generate a manifest for\n"
  1132. "\t<target_dir> = path to which all app files and dependencies will be copied\n"
  1133. "\t<template_file> = path of requried input Template file\n"
  1134. "\toptional : <dependency_dir> = user defined dependency dir where some dependencies could be found\n\n"
  1135. );
  1136. return S_OK;
  1137. }
  1138. /////////////////////////////////////////////////////////////////////////
  1139. // UsageAll
  1140. /////////////////////////////////////////////////////////////////////////
  1141. HRESULT UsageAll()
  1142. {
  1143. // call all above functions
  1144. return S_OK;
  1145. }
  1146. HRESULT UsageCommand(COMMAND_MODE CmdMode)
  1147. {
  1148. switch(CmdMode)
  1149. {
  1150. case CmdTemplate:
  1151. UsageCmdTemplate();
  1152. break;
  1153. case CmdList:
  1154. UsageCmdList();
  1155. break;
  1156. case CmdDependencyList:
  1157. UsageCmdDependencyList();
  1158. break;
  1159. case CmdSubscription:
  1160. UsageCmdSubscription();
  1161. break;
  1162. case CmdManifest:
  1163. UsageCmdManifest();
  1164. break;
  1165. default :
  1166. UsageTopLevel();
  1167. }
  1168. return S_OK;
  1169. }
  1170. HRESULT GetDir( LPWSTR pszSrc, LPWSTR *ppwzDir, BOOL bExists)
  1171. {
  1172. return PathNormalize(pszSrc, ppwzDir, DIRECTORY_PATH, bExists);
  1173. }
  1174. HRESULT GetFile( LPWSTR pszSrc, LPWSTR *ppwzFile, BOOL bExists)
  1175. {
  1176. return PathNormalize(pszSrc, ppwzFile, FILE_PATH, bExists);
  1177. }
  1178. /////////////////////////////////////////////////////////////////////////
  1179. // ParseCommandLineArgs
  1180. /////////////////////////////////////////////////////////////////////////
  1181. HRESULT ParseCommandLineArgs(int argc,
  1182. WCHAR **argv,
  1183. COMMAND_MODE & CmdMode
  1184. )
  1185. {
  1186. HRESULT hr = S_OK;
  1187. LPWSTR pszBuf=NULL;
  1188. if(argc < 2)
  1189. {
  1190. hr = E_FAIL;
  1191. goto exit;
  1192. }
  1193. if ( !StrCmpI(argv[1], L"-t"))
  1194. {
  1195. CmdMode = CmdTemplate;
  1196. }
  1197. else if ( !StrCmpI(argv[1], L"-l"))
  1198. {
  1199. CmdMode = CmdList;
  1200. }
  1201. else if ( !StrCmpI(argv[1], L"-d"))
  1202. {
  1203. CmdMode = CmdDependencyList;
  1204. }
  1205. else if ( !StrCmpI(argv[1], L"-s"))
  1206. {
  1207. CmdMode = CmdSubscription;
  1208. }
  1209. else if ( !StrCmpI(argv[1], L"-m"))
  1210. {
  1211. CmdMode = CmdManifest;
  1212. }
  1213. else
  1214. {
  1215. hr = E_FAIL;
  1216. goto exit;
  1217. }
  1218. int currArg = 2;
  1219. LPWSTR pwzParamName;
  1220. LPWSTR pwzParamValue;
  1221. while ( currArg < argc)
  1222. {
  1223. pwzParamName = argv[currArg];
  1224. if(pwzParamValue = StrChr(pwzParamName, L':'))
  1225. {
  1226. *pwzParamValue = L'\0';
  1227. pwzParamValue++;
  1228. }
  1229. if( (!pwzParamValue) || !lstrlen(pwzParamValue) )
  1230. {
  1231. if ( StrCmpI(pwzParamName, L"help"))
  1232. printf(" Param Value not specified for \"%s\" \n", pwzParamName);
  1233. hr = E_FAIL;
  1234. goto exit;
  1235. }
  1236. if ( !StrCmpI(pwzParamName, L"sd"))
  1237. {
  1238. if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE)))
  1239. goto exit;
  1240. g_sAppBase.Assign(pszBuf);
  1241. g_sDeployDirs[g_dwDeployDirs++].Assign(pszBuf);
  1242. }
  1243. else if ( !StrCmpI(pwzParamName, L"td"))
  1244. {
  1245. if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE)))
  1246. goto exit;
  1247. g_sTargetDir.Assign(pszBuf);
  1248. }
  1249. else if ( !StrCmpI(pwzParamName, L"dd"))
  1250. {
  1251. if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE)))
  1252. goto exit;
  1253. g_sDeployDirs[g_dwDeployDirs++].Assign(pszBuf);
  1254. }
  1255. else if ( !StrCmpI(pwzParamName, L"tf"))
  1256. {
  1257. if(FAILED(hr = GetFile(pwzParamValue, &pszBuf, TRUE)))
  1258. goto exit;
  1259. g_sTemplateFile.Assign(pszBuf);
  1260. }
  1261. else if ( !StrCmpI(pwzParamName, L"amu"))
  1262. {
  1263. g_sAppManifestURL.Assign(pwzParamValue);
  1264. }
  1265. else if ( !StrCmpI(pwzParamName, L"si"))
  1266. {
  1267. g_sPollingInterval.Assign(pwzParamValue);
  1268. }
  1269. else if ( !StrCmpI(pwzParamName, L"smd"))
  1270. {
  1271. if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE)))
  1272. goto exit;
  1273. g_sSubscriptionManifestDir.Assign(pszBuf);
  1274. }
  1275. else if ( !StrCmpI(pwzParamName, L"amf"))
  1276. {
  1277. if(FAILED(hr = GetFile(pwzParamValue, &pszBuf, TRUE)))
  1278. goto exit;
  1279. g_sAppManifestFile.Assign(pszBuf);
  1280. }
  1281. else if ( !StrCmpI(pwzParamName, L"WRN"))
  1282. {
  1283. g_bFailOnWarnings = 0;
  1284. }
  1285. else if ( !StrCmpI(pwzParamName, L"GAC"))
  1286. {
  1287. g_bLookInGACForDependencies = 1;
  1288. }
  1289. else if ( !StrCmpI(pwzParamName, L"SYS"))
  1290. {
  1291. g_bCopyDependentSystemAssemblies = 1;
  1292. }
  1293. else
  1294. {
  1295. hr = E_FAIL;
  1296. goto exit;
  1297. }
  1298. currArg++;
  1299. SAFEDELETEARRAY(pszBuf);
  1300. }
  1301. exit:
  1302. return hr;
  1303. }
  1304. /////////////////////////////////////////////////////////////////////////
  1305. // wmain
  1306. /////////////////////////////////////////////////////////////////////////
  1307. int __cdecl wmain(int argc, WCHAR **argv)
  1308. {
  1309. HRESULT hr = S_OK;
  1310. BOOL bCoInitialized = TRUE;
  1311. List<ManifestNode *> ManifestList;
  1312. List<ManifestNode *> UniqueManifestList;
  1313. List<LPWSTR> AssemblyFileList[HASHTABLE_SIZE];
  1314. List<LPWSTR> RawFiles;
  1315. DWORD dwType=0;
  1316. ManifestNode *pManifestNode = NULL;
  1317. LISTNODE pos;
  1318. BOOL bListMode = FALSE;
  1319. LPWSTR pwzBuf=NULL;
  1320. hr = CoInitialize(NULL);
  1321. if (FAILED(hr))
  1322. {
  1323. bCoInitialized = FALSE;
  1324. goto exit;
  1325. }
  1326. COMMAND_MODE CmdMode = CmdUsage;
  1327. // Parse
  1328. if(FAILED(hr = ParseCommandLineArgs(argc, argv, CmdMode)))
  1329. {
  1330. UsageCommand(CmdMode);
  1331. hr = S_OK;
  1332. goto exit;
  1333. }
  1334. // execute
  1335. switch(CmdMode)
  1336. {
  1337. case CmdTemplate:
  1338. if(g_sTemplateFile._cc <= 1)
  1339. {
  1340. hr = E_INVALIDARG;
  1341. goto exit;
  1342. }
  1343. hr = CreateAppManifestTemplate(g_sTemplateFile._pwz);
  1344. break;
  1345. case CmdDependencyList:
  1346. bListMode = TRUE;
  1347. // continue with CmdList.....
  1348. case CmdList:
  1349. {
  1350. if(g_sAppBase._cc <= 1)
  1351. {
  1352. hr = E_INVALIDARG;
  1353. goto exit;
  1354. }
  1355. if(g_sTemplateFile._cc >= 1)
  1356. {
  1357. if(FAILED(hr = GetInitialDependencies(g_sTemplateFile._pwz, &ManifestList)))
  1358. goto exit;
  1359. }
  1360. if(FAILED(hr = FindAllAssemblies(g_sAppBase._pwz, &ManifestList)))
  1361. goto exit;
  1362. if(FAILED(hr = TraverseManifestDependencyTrees(&ManifestList, AssemblyFileList, &UniqueManifestList, bListMode)))
  1363. goto exit;
  1364. if(FAILED(hr = CrossReferenceFiles(g_sAppBase._pwz, AssemblyFileList, &RawFiles)))
  1365. goto exit;
  1366. if(!bListMode)
  1367. {
  1368. if(FAILED(hr = PrintDependencies(&RawFiles, &UniqueManifestList)))
  1369. goto exit;
  1370. }
  1371. }
  1372. break;
  1373. case CmdManifest:
  1374. {
  1375. if((g_sAppBase._cc <= 1)
  1376. || (g_sTemplateFile._cc <= 1)
  1377. || (g_sTargetDir._cc <= 1)\
  1378. || !StrCmpI(g_sAppBase._pwz, g_sTargetDir._pwz))
  1379. {
  1380. hr = E_INVALIDARG;
  1381. goto exit;
  1382. }
  1383. if(FAILED(hr = GetInitialDependencies(g_sTemplateFile._pwz, &ManifestList)))
  1384. goto exit;
  1385. if(FAILED(hr = FindAllAssemblies(g_sAppBase._pwz, &ManifestList)))
  1386. goto exit;
  1387. if(FAILED(hr = TraverseManifestDependencyTrees(&ManifestList, AssemblyFileList, &UniqueManifestList, FALSE)))
  1388. goto exit;
  1389. if(FAILED(hr = CrossReferenceFiles(g_sAppBase._pwz, AssemblyFileList, &RawFiles)))
  1390. goto exit;
  1391. if(FAILED(hr = CopyFilesToTargetDir(&UniqueManifestList, &RawFiles)))
  1392. goto exit;
  1393. if(FAILED(hr = CreateXMLAppManifest(g_sTargetDir._pwz, g_sTemplateFile._pwz, &UniqueManifestList, &RawFiles)))
  1394. goto exit;
  1395. }
  1396. break;
  1397. case CmdSubscription:
  1398. if((g_sAppManifestFile._cc <= 1)
  1399. || (g_sSubscriptionManifestDir._cc <= 1)
  1400. || (g_sAppManifestURL._cc <= 1))
  1401. {
  1402. hr = E_INVALIDARG;
  1403. goto exit;
  1404. }
  1405. if(g_sPollingInterval._cc <= 1)
  1406. {
  1407. g_sPollingInterval.Assign(DEFAULT_POLLING_INTERVAL);
  1408. }
  1409. hr = CreateSubscriptionManifest(g_sAppManifestFile._pwz,
  1410. g_sSubscriptionManifestDir._pwz,
  1411. g_sAppManifestURL._pwz,
  1412. g_sPollingInterval._pwz);
  1413. break;
  1414. default :
  1415. hr = E_FAIL;
  1416. goto exit;
  1417. }
  1418. exit:
  1419. // Clean up hash table
  1420. for (int i = 0; i < HASHTABLE_SIZE; i++)
  1421. {
  1422. pos = AssemblyFileList[i].GetHeadPosition();
  1423. while (pos)
  1424. {
  1425. pwzBuf = AssemblyFileList[i].GetNext(pos);
  1426. SAFEDELETEARRAY(pwzBuf);
  1427. }
  1428. AssemblyFileList[i].RemoveAll();
  1429. }
  1430. //clean up Rawfilelist
  1431. pos = RawFiles.GetHeadPosition();
  1432. while (pos)
  1433. {
  1434. pwzBuf = RawFiles.GetNext(pos);
  1435. SAFEDELETEARRAY(pwzBuf);
  1436. }
  1437. RawFiles.RemoveAll();
  1438. // clean up ManifestList
  1439. pos = ManifestList.GetHeadPosition();
  1440. while (pos)
  1441. {
  1442. pManifestNode = ManifestList.GetNext(pos);
  1443. SAFEDELETE(pManifestNode);
  1444. }
  1445. ManifestList.RemoveAll();
  1446. // clean up UniqueManifestList
  1447. pos = UniqueManifestList.GetHeadPosition();
  1448. while (pos)
  1449. {
  1450. pManifestNode = UniqueManifestList.GetNext(pos);
  1451. SAFEDELETE(pManifestNode);
  1452. }
  1453. UniqueManifestList.RemoveAll();
  1454. if (bCoInitialized)
  1455. CoUninitialize();
  1456. if (FAILED(hr))
  1457. {
  1458. fprintf(stderr, "\nFailed with code 0x%x \n", hr);
  1459. UsageCommand(CmdMode);
  1460. }
  1461. return hr;
  1462. }