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.

329 lines
9.3 KiB

  1. #include <fusenetincludes.h>
  2. #include <activator.h>
  3. #include <versionmanagement.h>
  4. #include "dbglog.h"
  5. // debug msg stuff
  6. void
  7. Msg(LPCWSTR pwz)
  8. {
  9. MessageBox(NULL, pwz, L"ClickOnce", 0);
  10. }
  11. // ----------------------------------------------------------------------------
  12. void
  13. ShowError(LPCWSTR pwz)
  14. {
  15. MessageBox(NULL, pwz, L"ClickOnce Error", MB_ICONERROR);
  16. }
  17. // ----------------------------------------------------------------------------
  18. void
  19. ShowError(HRESULT hr, LPCWSTR pwz=NULL)
  20. {
  21. DWORD dwErrorCode = HRESULT_CODE(hr);
  22. LPWSTR MessageBuffer = NULL;
  23. DWORD dwBufferLength;
  24. // ISSUE-2002/03/27-felixybc note: check for E_OUTOFMEMORY?
  25. // Call FormatMessage() to allow for message
  26. // text to be acquired from the system
  27. if(dwBufferLength = FormatMessage(
  28. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  29. FORMAT_MESSAGE_IGNORE_INSERTS |
  30. FORMAT_MESSAGE_FROM_SYSTEM,
  31. NULL, // module to get message from (NULL == system)
  32. dwErrorCode,
  33. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
  34. (LPWSTR) &MessageBuffer,
  35. 0,
  36. NULL))
  37. {
  38. // BUGBUG: Process any inserts in MessageBuffer
  39. LPWSTR pwzMsg = MessageBuffer;
  40. CString sMsg;
  41. if (pwz != NULL)
  42. {
  43. if (SUCCEEDED(sMsg.Assign((LPWSTR)pwz)))
  44. if (SUCCEEDED(sMsg.Append(L"\n\n")))
  45. if (SUCCEEDED(sMsg.Append(MessageBuffer)))
  46. pwzMsg = sMsg._pwz;
  47. }
  48. // Display the string
  49. ShowError(pwzMsg);
  50. // Free the buffer allocated by the system
  51. LocalFree(MessageBuffer);
  52. }
  53. else
  54. {
  55. // ISSUE-2002/03/27-felixybc Error in this error handling code. Should print error code from format msg and orginal hr
  56. // should at least print error code?
  57. if (pwz != NULL)
  58. ShowError((LPWSTR)pwz);
  59. else
  60. ShowError(L"Error occurred. Unable to retrieve associated error message from the system.");
  61. }
  62. }
  63. /*void _stdcall
  64. EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
  65. hwnd - window handle that should be used as the owner window for
  66. any windows your DLL creates
  67. hinst - your DLL's instance handle
  68. lpszCmdLine - ASCIIZ command line your DLL should parse
  69. nCmdShow - describes how your DLL's windows should be displayed
  70. */
  71. // ---------------------------------------------------------------------------
  72. // DisableCurrentVersionW
  73. // The rundll32 entry point for rollback to previous version
  74. // The function should be named as 'DisableCurrentVersion' on rundll32's command line
  75. // ---------------------------------------------------------------------------
  76. void CALLBACK
  77. DisableCurrentVersionW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
  78. {
  79. HRESULT hr = S_OK;
  80. MAKE_ERROR_MACROS_STATIC(hr);
  81. LPVERSION_MANAGEMENT pVerMan = NULL;
  82. LPWSTR pwzDisplayNameMask = NULL;
  83. IF_FAILED_EXIT(CoInitialize(NULL));
  84. // parse commandline
  85. // accepted formats: "displayNameMask"
  86. if (*lpszCmdLine == L'\"')
  87. {
  88. LPWSTR pwz = NULL;
  89. pwz = wcschr(lpszCmdLine+1, L'\"');
  90. if (pwz != NULL)
  91. {
  92. *pwz = L'\0';
  93. pwzDisplayNameMask = lpszCmdLine+1;
  94. }
  95. }
  96. // exit if invalid arguments
  97. IF_NULL_EXIT(pwzDisplayNameMask, E_INVALIDARG);
  98. IF_FAILED_EXIT(CreateVersionManagement(&pVerMan, 0));
  99. IF_FAILED_EXIT(pVerMan->Rollback(pwzDisplayNameMask));
  100. if (hr == S_FALSE)
  101. Msg(L"Application files cannot be found. Operation is aborted.");
  102. exit:
  103. SAFERELEASE(pVerMan);
  104. if (FAILED(hr))
  105. {
  106. if (hr != E_ABORT)
  107. ShowError(hr);
  108. }
  109. CoUninitialize();
  110. return;
  111. }
  112. // ---------------------------------------------------------------------------
  113. // UninstallW
  114. // The rundll32 entry point for Control Panel's Add/Remove Program
  115. // The function should be named as 'Uninstall' on rundll32's command line
  116. // ---------------------------------------------------------------------------
  117. void CALLBACK
  118. UninstallW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
  119. {
  120. HRESULT hr = S_OK;
  121. MAKE_ERROR_MACROS_STATIC(hr);
  122. LPVERSION_MANAGEMENT pVerMan = NULL;
  123. LPWSTR pwzDisplayNameMask = NULL;
  124. LPWSTR pwzDesktopManifestPath = NULL;
  125. HKEY hkey = NULL;
  126. LONG lReturn = 0;
  127. IF_FAILED_EXIT(CoInitialize(NULL));
  128. // parse commandline
  129. // accepted formats: "displayNameMask" "pathToDesktopManifest"
  130. if (*lpszCmdLine == L'\"')
  131. {
  132. LPWSTR pwz = NULL;
  133. pwz = wcschr(lpszCmdLine+1, L'\"');
  134. if (pwz != NULL)
  135. {
  136. *pwz = L'\0';
  137. pwzDisplayNameMask = lpszCmdLine+1;
  138. pwz = wcschr(pwz+1, L'\"');
  139. if (pwz != NULL)
  140. {
  141. pwzDesktopManifestPath = pwz+1;
  142. pwz = wcschr(pwzDesktopManifestPath, L'\"');
  143. if (pwz != NULL)
  144. *pwz = L'\0';
  145. else
  146. pwzDesktopManifestPath = NULL;
  147. }
  148. }
  149. }
  150. // exit if invalid arguments
  151. IF_FALSE_EXIT(pwzDisplayNameMask != NULL && pwzDesktopManifestPath != NULL, E_INVALIDARG);
  152. IF_TRUE_EXIT(MessageBox(NULL, L"Do you want to remove this application and unregister its subscription?", L"ClickOnce",
  153. MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) != IDYES, E_ABORT);
  154. IF_FAILED_EXIT(CreateVersionManagement(&pVerMan, 0));
  155. IF_FAILED_EXIT(pVerMan->Uninstall(pwzDisplayNameMask, pwzDesktopManifestPath));
  156. if (hr == S_FALSE)
  157. {
  158. IF_TRUE_EXIT(MessageBox(NULL, L"The application can no longer be located on the system. Do you want to remove this entry?",
  159. L"ClickOnce", MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) == IDNO, E_ABORT);
  160. // delete registry uninstall info
  161. extern const WCHAR* pwzUninstallSubKey; // defined in versionmanagement.cpp
  162. // open uninstall key
  163. lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pwzUninstallSubKey, 0,
  164. DELETE, &hkey);
  165. IF_WIN32_FAILED_EXIT(lReturn);
  166. lReturn = RegDeleteKey(hkey, pwzDisplayNameMask);
  167. IF_WIN32_FAILED_EXIT(lReturn);
  168. }
  169. exit:
  170. SAFERELEASE(pVerMan);
  171. if (hkey)
  172. {
  173. lReturn = RegCloseKey(hkey);
  174. if (SUCCEEDED(hr))
  175. hr = (HRESULT_FROM_WIN32(lReturn));
  176. }
  177. if (FAILED(hr))
  178. {
  179. if (hr != E_ABORT)
  180. ShowError(hr);
  181. }
  182. CoUninitialize();
  183. return;
  184. }
  185. // ---------------------------------------------------------------------------
  186. // StartW
  187. // The single rundll32 entry point for both shell (file type host) and mimehandler/url
  188. // The function should be named as 'Start' on rundll32's command line
  189. // ---------------------------------------------------------------------------
  190. void CALLBACK
  191. StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
  192. {
  193. HRESULT hr = S_OK;
  194. MAKE_ERROR_MACROS_STATIC(hr);
  195. LPACTIVATOR pActivator = NULL;
  196. LPWSTR pwzShortcutPath = NULL;
  197. LPWSTR pwzShortcutUrl = NULL;
  198. BOOL bIsFromWeb = FALSE;
  199. CDebugLog * pDbgLog = NULL;
  200. if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
  201. {
  202. // ISSUE-2002/03/27-felixybc work around on longhorn builds, avalon bug 1493
  203. if(hr == RPC_E_CHANGED_MODE)
  204. hr = S_OK; // allow RPC_E_CHANGED_MODE error for now.
  205. else
  206. goto exit;
  207. }
  208. // parse commandline
  209. // accepted formats: "Path" <OR> "Path" "URL"
  210. if (*lpszCmdLine == L'\"')
  211. {
  212. LPWSTR pwz = NULL;
  213. pwz = wcschr(lpszCmdLine+1, L'\"');
  214. if (pwz != NULL)
  215. {
  216. *pwz = L'\0';
  217. // case 1 desktop/local, path to shortcut only
  218. pwzShortcutPath = lpszCmdLine+1;
  219. pwz = wcschr(pwz+1, L'\"');
  220. if (pwz != NULL)
  221. {
  222. pwzShortcutUrl = pwz+1;
  223. pwz = wcschr(pwzShortcutUrl, L'\"');
  224. if (pwz != NULL)
  225. {
  226. *pwz = L'\0';
  227. // case 2 url/mimehandler, path to temp shortcut and source URL
  228. bIsFromWeb = TRUE;
  229. }
  230. }
  231. }
  232. }
  233. // exit if invalid arguments. ShortcutUrl is incomplete if bIsFromWeb is FALSE
  234. IF_FALSE_EXIT(!(pwzShortcutPath == NULL || (pwzShortcutUrl != NULL && !bIsFromWeb)), E_INVALIDARG);
  235. IF_FAILED_EXIT(CreateLogObject(&pDbgLog, NULL));
  236. IF_FAILED_EXIT(CreateActivator(&pActivator, pDbgLog, 0));
  237. IF_FAILED_EXIT(pActivator->Initialize(pwzShortcutPath, pwzShortcutUrl));
  238. IF_FAILED_EXIT(pActivator->Process());
  239. IF_FAILED_EXIT(pActivator->Execute());
  240. exit:
  241. if(pDbgLog)
  242. {
  243. DUMPDEBUGLOG(pDbgLog, -1, hr);
  244. }
  245. SAFERELEASE(pActivator);
  246. if (FAILED(hr))
  247. {
  248. if (hr != E_ABORT)
  249. ShowError(hr);
  250. }
  251. if (bIsFromWeb)
  252. {
  253. // delete the temp file from the mimehandler
  254. // ignore return value
  255. DeleteFile(pwzShortcutPath);
  256. }
  257. CoUninitialize();
  258. SAFERELEASE(pDbgLog);
  259. return;
  260. }