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.

355 lines
8.7 KiB

  1. /*
  2. * persist.cpp - IPersist, IPersistFile implementations for
  3. * CFusionShortcut class.
  4. */
  5. /* Headers
  6. **********/
  7. #include "project.hpp" // for GetLastWin32Error
  8. /* Global Constants
  9. *******************/
  10. const WCHAR g_cwzDefaultFileNamePrompt[] = L"*.manifest";
  11. // ----------------------------------------------------------------------------
  12. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetCurFile(LPWSTR pwzFile,
  13. UINT ucbLen)
  14. {
  15. HRESULT hr=S_OK;
  16. if (m_pwzShortcutFile)
  17. {
  18. wcsncpy(pwzFile, m_pwzShortcutFile, ucbLen-1);
  19. pwzFile[ucbLen-1] = L'\0';
  20. }
  21. else
  22. hr = S_FALSE;
  23. ASSERT(hr == S_OK ||
  24. hr == S_FALSE);
  25. return(hr);
  26. }
  27. HRESULT STDMETHODCALLTYPE CFusionShortcut::Dirty(BOOL bDirty)
  28. {
  29. HRESULT hr=S_OK;
  30. if (bDirty)
  31. {
  32. SET_FLAG(m_dwFlags, FUSSHCUT_FL_DIRTY);
  33. //m_dwFlags = FUSSHCUT_FL_DIRTY;
  34. }
  35. else
  36. {
  37. CLEAR_FLAG(m_dwFlags, FUSSHCUT_FL_DIRTY);
  38. //m_dwFlags = FUSSHCUT_FL_NOTDIRTY;
  39. }
  40. return(hr);
  41. }
  42. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetClassID(CLSID* pclsid)
  43. {
  44. HRESULT hr=S_OK;
  45. if (pclsid == NULL)
  46. hr = E_INVALIDARG;
  47. else
  48. *pclsid = CLSID_FusionShortcut;
  49. return(hr);
  50. }
  51. HRESULT STDMETHODCALLTYPE CFusionShortcut::IsDirty(void)
  52. {
  53. HRESULT hr;
  54. if (IS_FLAG_SET(m_dwFlags, FUSSHCUT_FL_DIRTY))
  55. //if (m_dwFlags == FUSSHCUT_FL_DIRTY)
  56. // modified
  57. hr = S_OK;
  58. else
  59. // not modified
  60. hr = S_FALSE;
  61. return(hr);
  62. }
  63. HRESULT STDMETHODCALLTYPE CFusionShortcut::Save(LPCOLESTR pcwszFile,
  64. BOOL bRemember)
  65. {
  66. // BUGBUG: no save for now!
  67. return E_NOTIMPL;
  68. }
  69. HRESULT STDMETHODCALLTYPE CFusionShortcut::SaveCompleted(LPCOLESTR pcwszFile)
  70. {
  71. // BUGBUG: no save for now!
  72. return E_NOTIMPL;
  73. }
  74. HRESULT STDMETHODCALLTYPE CFusionShortcut::Load(LPCOLESTR pcwszFile,
  75. DWORD dwMode)
  76. {
  77. HRESULT hr = S_OK;
  78. LPWSTR pwzWorkingDir = NULL;
  79. LPWSTR pwzValue = NULL;
  80. DWORD dwCC = 0, dwCB = 0, dwFlag = 0;
  81. LPASSEMBLY_MANIFEST_IMPORT pManImport = NULL;
  82. LPASSEMBLY_CACHE_IMPORT pCacheImport = NULL;
  83. IManifestInfo *pAppInfo = NULL;
  84. IManifestInfo *pDependAsmInfo = NULL;
  85. // FEATURE: Validate dwMode here.
  86. // FEAUTRE: Implement dwMode flag support.
  87. if (!pcwszFile)
  88. {
  89. hr = E_INVALIDARG;
  90. goto exit;
  91. }
  92. // a hack check
  93. // BUGBUG?: this shouldn't be called more than once?
  94. // BUT: the rest of this code works even if called multiple times
  95. if (m_pwzWorkingDirectory)
  96. {
  97. hr = E_FAIL;
  98. goto exit;
  99. }
  100. // store the shortcut file name
  101. if (m_pwzShortcutFile)
  102. delete [] m_pwzShortcutFile;
  103. // (+ 1) for null terminator.
  104. m_pwzShortcutFile = new(WCHAR[wcslen(pcwszFile) + 1]);
  105. if (m_pwzShortcutFile)
  106. {
  107. wcscpy(m_pwzShortcutFile, pcwszFile);
  108. }
  109. else
  110. {
  111. hr = E_OUTOFMEMORY;
  112. goto exit;
  113. }
  114. if (FAILED(hr = CreateAssemblyManifestImport(&pManImport, m_pwzShortcutFile, NULL, 0)))
  115. goto exit;
  116. // check this 1st for pref...
  117. if (FAILED(hr=pManImport->GetManifestApplicationInfo(&pAppInfo)))
  118. goto exit;
  119. // can't continue without this...
  120. if (hr==S_FALSE)
  121. {
  122. hr = E_FAIL;
  123. goto exit;
  124. }
  125. if (m_pIdentity)
  126. m_pIdentity->Release();
  127. if (FAILED(hr = pManImport->GetAssemblyIdentity(&m_pIdentity)))
  128. goto exit;
  129. // can't continue without a cache dir, 'cos otherwise unknown behavior
  130. // BUGBUG: should check/code to ensure some continue to work
  131. // even without the complete name, eg. shell icon path, part of infotip
  132. if (FAILED(hr = CreateAssemblyCacheImport(&pCacheImport, m_pIdentity, CACHEIMP_CREATE_RESOLVE_REF_EX)))
  133. goto exit;
  134. pCacheImport->GetManifestFileDir(&pwzWorkingDir, &dwCC);
  135. if (dwCC < 2)
  136. {
  137. // this should never happen
  138. hr = E_UNEXPECTED;
  139. goto exit;
  140. }
  141. // remove last L'\\'
  142. *(pwzWorkingDir+dwCC-2) = L'\0';
  143. if (FAILED(hr=SetWorkingDirectory(pwzWorkingDir)))
  144. goto exit;
  145. // ignore failure
  146. pAppInfo->Get(MAN_INFO_APPLICATION_SHOWCOMMAND, (LPVOID *)&pwzValue, &dwCB, &dwFlag);
  147. if (pwzValue != NULL)
  148. {
  149. // default is normal
  150. int nShowCmd = SW_SHOWNORMAL;
  151. if (!_wcsicmp(pwzValue, L"maximized"))
  152. {
  153. nShowCmd = SW_SHOWMAXIMIZED;
  154. }
  155. else if (!_wcsicmp(pwzValue, L"minimized"))
  156. {
  157. nShowCmd = SW_SHOWMINIMIZED;
  158. }
  159. if (FAILED(hr=SetShowCmd(nShowCmd)))
  160. goto exit;
  161. delete [] pwzValue;
  162. }
  163. // ignore failure
  164. pAppInfo->Get(MAN_INFO_APPLICATION_ENTRYPOINT, (LPVOID *)&pwzValue, &dwCB, &dwFlag);
  165. if (pwzValue != NULL)
  166. {
  167. size_t ccWorkingDir = wcslen(pwzWorkingDir)+1;
  168. size_t ccEntryPoint = wcslen(pwzValue)+1;
  169. LPWSTR pwzTemp = new WCHAR[ccWorkingDir+ccEntryPoint]; // 2 strings + '\\' + '\0'
  170. // like .lnk or .url, entry point is under wzWorkingDir
  171. // 'path' is the target file of the shortcut, ie. the entry point of the app in this case
  172. if (pwzTemp == NULL)
  173. {
  174. hr = E_OUTOFMEMORY;
  175. goto exit;
  176. }
  177. memcpy(pwzTemp, pwzWorkingDir, ccWorkingDir * sizeof(WCHAR));
  178. if (!PathAppend(pwzTemp, pwzValue))
  179. hr = E_FAIL;
  180. else
  181. hr=SetPath(pwzTemp);
  182. delete [] pwzTemp;
  183. if (FAILED(hr))
  184. goto exit;
  185. delete [] pwzValue;
  186. }
  187. //else
  188. // ... if no entry point leave it blank so that the default icon will be used
  189. // ignore failure
  190. pAppInfo->Get(MAN_INFO_APPLICATION_FRIENDLYNAME, (LPVOID *)&pwzValue, &dwCB, &dwFlag);
  191. if (pwzValue != NULL)
  192. {
  193. if (FAILED(hr=SetDescription(pwzValue)))
  194. goto exit;
  195. delete [] pwzValue;
  196. }
  197. // ignore failure
  198. pAppInfo->Get(MAN_INFO_APPLICATION_ICONFILE, (LPVOID *)&pwzValue, &dwCB, &dwFlag);
  199. if (pwzValue != NULL)
  200. {
  201. LPWSTR pwzValue2 = NULL;
  202. pAppInfo->Get(MAN_INFO_APPLICATION_ICONINDEX, (LPVOID *)&pwzValue2, &dwCB, &dwFlag);
  203. if (pwzValue2 != NULL)
  204. {
  205. LPWSTR pwzStopString = NULL;
  206. hr=SetIconLocation(pwzValue, (int) wcstol(pwzValue2, &pwzStopString, 10));
  207. delete [] pwzValue2;
  208. if (FAILED(hr))
  209. goto exit;
  210. }
  211. delete [] pwzValue;
  212. }
  213. // ignore failure
  214. pAppInfo->Get(MAN_INFO_APPLICATION_HOTKEY, (LPVOID *)&pwzValue, &dwCB, &dwFlag);
  215. if (pwzValue != NULL)
  216. {
  217. LPWSTR pwzStopString = NULL;
  218. if (FAILED(hr=SetHotkey((WORD) wcstol(pwzValue, &pwzStopString, 10))))
  219. goto exit;
  220. delete [] pwzValue;
  221. }
  222. // note: this method of getting the codebase is only valid for desktop (and subscription) manifests
  223. // thus the hardcoded index '0'
  224. // ignore failure
  225. pManImport->GetNextAssembly(0, &pDependAsmInfo);
  226. if (pDependAsmInfo != NULL)
  227. {
  228. pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_CODEBASE, (LPVOID *)&pwzValue, &dwCB, &dwFlag);
  229. if (pwzValue != NULL)
  230. {
  231. if (FAILED(hr=SetCodebase(pwzValue)))
  232. goto exit;
  233. delete [] pwzValue;
  234. }
  235. }
  236. pwzValue = NULL;
  237. exit:
  238. if (pwzValue != NULL)
  239. delete [] pwzValue;
  240. if (pwzWorkingDir != NULL)
  241. delete [] pwzWorkingDir;
  242. if (pDependAsmInfo != NULL)
  243. pDependAsmInfo->Release();
  244. if (pAppInfo != NULL)
  245. pAppInfo->Release();
  246. if (pCacheImport != NULL)
  247. pCacheImport->Release();
  248. if (pManImport != NULL)
  249. pManImport->Release();
  250. return(hr);
  251. }
  252. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetCurFile(LPOLESTR *ppwszFile)
  253. {
  254. HRESULT hr = S_OK;
  255. LPOLESTR pwszTempFile;
  256. if (ppwszFile == NULL)
  257. {
  258. hr = E_INVALIDARG;
  259. goto exit;
  260. }
  261. // BUGBUG?: ensure *ppwszFile NULL?
  262. if (m_pwzShortcutFile)
  263. {
  264. pwszTempFile = m_pwzShortcutFile;
  265. }
  266. else
  267. {
  268. pwszTempFile = (LPWSTR) g_cwzDefaultFileNamePrompt;
  269. hr = S_FALSE;
  270. }
  271. *ppwszFile = (LPOLESTR) CoTaskMemAlloc((wcslen(pwszTempFile) + 1) * sizeof(*pwszTempFile));
  272. if (*ppwszFile)
  273. wcscpy(*ppwszFile, pwszTempFile);
  274. else
  275. hr = E_OUTOFMEMORY;
  276. exit:
  277. return(hr);
  278. }