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.

432 lines
12 KiB

  1. // dllreg.cpp -- autmatic registration and unregistration
  2. //
  3. #include "priv.h"
  4. #include <advpub.h>
  5. #include <comcat.h>
  6. #include <msieftp.h>
  7. // helper macros
  8. // ADVPACK will return E_UNEXPECTED if you try to uninstall (which does a registry restore)
  9. // on an INF section that was never installed. We uninstall sections that may never have
  10. // been installed, so this MACRO will quiet these errors.
  11. #define QuietInstallNoOp(hr) ((E_UNEXPECTED == hr) ? S_OK : hr)
  12. const CHAR c_szIexploreKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE";
  13. /*----------------------------------------------------------
  14. Purpose: Queries the registry for the location of the path
  15. of Internet Explorer and returns it in pszBuf.
  16. Returns: TRUE on success
  17. FALSE if path cannot be determined
  18. Cond: --
  19. */
  20. BOOL
  21. GetIEPath(
  22. OUT LPSTR pszBuf,
  23. IN DWORD cchBuf)
  24. {
  25. BOOL bRet = FALSE;
  26. HKEY hkey;
  27. *pszBuf = '\0';
  28. // Get the path of Internet Explorer
  29. if (NO_ERROR != RegOpenKeyA(HKEY_LOCAL_MACHINE, c_szIexploreKey, &hkey))
  30. {
  31. }
  32. else
  33. {
  34. DWORD cbBrowser;
  35. DWORD dwType;
  36. lstrcatA(pszBuf, "\"");
  37. cbBrowser = CbFromCchA(cchBuf - lstrlenA(" -nohome") - 4);
  38. if (NO_ERROR != RegQueryValueExA(hkey, "", NULL, &dwType,
  39. (LPBYTE)&pszBuf[1], &cbBrowser))
  40. {
  41. }
  42. else
  43. {
  44. bRet = TRUE;
  45. }
  46. lstrcatA(pszBuf, "\"");
  47. RegCloseKey(hkey);
  48. }
  49. return bRet;
  50. }
  51. BOOL UnregisterTypeLibrary(const CLSID* piidLibrary)
  52. {
  53. TCHAR szScratch[GUIDSTR_MAX];
  54. HKEY hk;
  55. BOOL fResult = FALSE;
  56. // convert the libid into a string.
  57. //
  58. SHStringFromGUID(*piidLibrary, szScratch, ARRAYSIZE(szScratch));
  59. if (RegOpenKey(HKEY_CLASSES_ROOT, TEXT("TypeLib"), &hk) == ERROR_SUCCESS) {
  60. fResult = RegDeleteKey(hk, szScratch);
  61. RegCloseKey(hk);
  62. }
  63. return fResult;
  64. }
  65. HRESULT FtpRegTypeLib(void)
  66. {
  67. HRESULT hr = S_OK;
  68. ITypeLib *pTypeLib;
  69. DWORD dwPathLen;
  70. TCHAR szTmp[MAX_PATH];
  71. #ifdef UNICODE
  72. WCHAR *pwsz = szTmp;
  73. #else
  74. WCHAR pwsz[MAX_PATH];
  75. #endif
  76. // Load and register our type library.
  77. //
  78. dwPathLen = GetModuleFileName(HINST_THISDLL, szTmp, ARRAYSIZE(szTmp));
  79. #ifndef UNICODE
  80. if (SHAnsiToUnicode(szTmp, pwsz, MAX_PATH))
  81. #endif
  82. {
  83. hr = LoadTypeLib(pwsz, &pTypeLib);
  84. if (SUCCEEDED(hr))
  85. {
  86. // call the unregister type library as we had some old junk that
  87. // was registered by a previous version of OleAut32, which is now causing
  88. // the current version to not work on NT...
  89. UnregisterTypeLibrary(&LIBID_MSIEFTPLib);
  90. hr = RegisterTypeLib(pTypeLib, pwsz, NULL);
  91. if (FAILED(hr))
  92. {
  93. TraceMsg(TF_WARNING, "MSIEFTP: RegisterTypeLib failed (%x)", hr);
  94. }
  95. pTypeLib->Release();
  96. }
  97. else
  98. {
  99. TraceMsg(TF_WARNING, "MSIEFTP: LoadTypeLib failed (%x)", hr);
  100. }
  101. }
  102. #ifndef UNICODE
  103. else {
  104. hr = E_FAIL;
  105. }
  106. #endif
  107. return hr;
  108. }
  109. /*----------------------------------------------------------
  110. Purpose: Calls the ADVPACK entry-point which executes an inf
  111. file section.
  112. Returns:
  113. Cond: --
  114. */
  115. HRESULT CallRegInstall(HINSTANCE hinstFTP, LPSTR szSection)
  116. {
  117. HRESULT hr = E_FAIL;
  118. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  119. if (hinstAdvPack)
  120. {
  121. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  122. if (pfnri)
  123. {
  124. char szThisDLL[MAX_PATH];
  125. // Get the location of this DLL from the HINSTANCE
  126. if ( !EVAL(GetModuleFileNameA(hinstFTP, szThisDLL, ARRAYSIZE(szThisDLL))) )
  127. {
  128. // Failed, just say "msieftp.exe"
  129. StrCpyNA(szThisDLL, "msieftp.exe", ARRAYSIZE(szThisDLL));
  130. }
  131. STRENTRY seReg[] = {
  132. { "THISDLL", szThisDLL },
  133. // These two NT-specific entries must be at the end
  134. { "25", "%SystemRoot%" },
  135. { "11", "%SystemRoot%\\system32" },
  136. };
  137. STRTABLE stReg = { ARRAYSIZE(seReg) - 2, seReg };
  138. hr = pfnri(g_hinst, szSection, &stReg);
  139. }
  140. FreeLibrary(hinstAdvPack);
  141. }
  142. return hr;
  143. }
  144. STDAPI DllRegisterServer(void)
  145. {
  146. HRESULT hr;
  147. // Delete any old registration entries, then add the new ones.
  148. // Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
  149. // (The inf engine doesn't guarantee DelReg/AddReg order, that's
  150. // why we explicitly unreg and reg here.)
  151. //
  152. HINSTANCE hinstFTP = GetModuleHandle(TEXT("MSIEFTP.DLL"));
  153. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  154. hr = CallRegInstall(hinstFTP, "FtpShellExtensionInstall");
  155. ASSERT(SUCCEEDED(hr));
  156. FtpRegTypeLib();
  157. if (hinstAdvPack)
  158. FreeLibrary(hinstAdvPack);
  159. return hr;
  160. }
  161. STDAPI DllUnregisterServer(void)
  162. {
  163. HRESULT hr;
  164. HINSTANCE hinstFTP = GetModuleHandle(TEXT("MSIEFTP.DLL"));
  165. // UnInstall the registry values
  166. hr = CallRegInstall(hinstFTP, "FtpShellExtensionUninstall");
  167. UnregisterTypeLibrary(&LIBID_MSIEFTPLib);
  168. return hr;
  169. }
  170. /*----------------------------------------------------------
  171. Purpose: Install/uninstall user settings
  172. Description: Note that this function has special error handling.
  173. The function will keep hrExternal with the worse error
  174. but will only stop executing util the internal error (hr)
  175. gets really bad. This is because we need the external
  176. error to catch incorrectly authored INFs but the internal
  177. error to be robust in attempting to install other INF sections
  178. even if one doesn't make it.
  179. */
  180. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  181. {
  182. return S_OK;
  183. }
  184. class CFtpInstaller : public IFtpInstaller
  185. {
  186. public:
  187. //////////////////////////////////////////////////////
  188. // Public Interfaces
  189. //////////////////////////////////////////////////////
  190. // *** IUnknown ***
  191. virtual STDMETHODIMP_(ULONG) AddRef(void);
  192. virtual STDMETHODIMP_(ULONG) Release(void);
  193. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  194. // *** IFtpInstaller ***
  195. virtual STDMETHODIMP IsIEDefautlFTPClient(void);
  196. virtual STDMETHODIMP RestoreFTPClient(void);
  197. virtual STDMETHODIMP MakeIEDefautlFTPClient(void);
  198. protected:
  199. CFtpInstaller();
  200. ~CFtpInstaller();
  201. friend HRESULT CFtpInstaller_Create(REFIID riid, LPVOID * ppv);
  202. private:
  203. int m_cRef;
  204. };
  205. /*****************************************************************************\
  206. FUNCTION: CFtpInstaller_Create
  207. DESCRIPTION:
  208. \*****************************************************************************/
  209. HRESULT CFtpInstaller_Create(REFIID riid, LPVOID * ppv)
  210. {
  211. HRESULT hr = E_OUTOFMEMORY;
  212. CFtpInstaller * pfi = new CFtpInstaller();
  213. if (EVAL(pfi))
  214. {
  215. hr = pfi->QueryInterface(riid, ppv);
  216. pfi->Release();
  217. }
  218. return hr;
  219. }
  220. /****************************************************\
  221. Constructor
  222. \****************************************************/
  223. CFtpInstaller::CFtpInstaller() : m_cRef(1)
  224. {
  225. DllAddRef();
  226. }
  227. /****************************************************\
  228. Destructor
  229. \****************************************************/
  230. CFtpInstaller::~CFtpInstaller()
  231. {
  232. DllRelease();
  233. }
  234. //===========================
  235. // *** IUnknown Interface ***
  236. //===========================
  237. ULONG CFtpInstaller::AddRef()
  238. {
  239. m_cRef++;
  240. return m_cRef;
  241. }
  242. ULONG CFtpInstaller::Release()
  243. {
  244. ASSERT(m_cRef > 0);
  245. m_cRef--;
  246. if (m_cRef > 0)
  247. return m_cRef;
  248. delete this;
  249. return 0;
  250. }
  251. HRESULT CFtpInstaller::QueryInterface(REFIID riid, void **ppvObj)
  252. {
  253. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IFtpInstaller))
  254. {
  255. *ppvObj = SAFECAST(this, IFtpInstaller*);
  256. }
  257. else
  258. {
  259. *ppvObj = NULL;
  260. return E_NOINTERFACE;
  261. }
  262. AddRef();
  263. return S_OK;
  264. }
  265. /***************************************************\
  266. Return values:
  267. S_OK - IE is default FTP client AND other client exists
  268. S_FALSE - IE not default FTP client (other client exists of course)
  269. E_FAIL - IE is default FTP client AND no other client exists
  270. \***************************************************/
  271. HRESULT CFtpInstaller::IsIEDefautlFTPClient(void)
  272. {
  273. HRESULT hr = E_FAIL;
  274. TCHAR szDefaultFTPClient[MAX_PATH];
  275. DWORD cbSize = sizeof(szDefaultFTPClient);
  276. if (EVAL(ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, SZ_REGKEY_FTPCLASS, SZ_REGVALUE_DEFAULT_FTP_CLIENT, NULL, szDefaultFTPClient, &cbSize)))
  277. {
  278. // Are we the default client?
  279. if (!StrCmpI(szDefaultFTPClient, SZ_REGDATA_IE_FTP_CLIENT))
  280. {
  281. DWORD dwType;
  282. // Yes. Is someone else installed?
  283. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_FTPFOLDER, SZ_REGVALUE_PREVIOUS_FTP_CLIENT, &dwType, szDefaultFTPClient, &cbSize))
  284. {
  285. // Yes, so display UI so the user can switch back to them.
  286. hr = S_OK;
  287. }
  288. }
  289. else
  290. {
  291. // No, so someone else is installed and is default. Display UI.
  292. hr = S_FALSE;
  293. }
  294. }
  295. return hr;
  296. }
  297. HRESULT CFtpInstaller::RestoreFTPClient(void)
  298. {
  299. HRESULT hr = S_OK;
  300. TCHAR szDefaultFTPClient[MAX_PATH];
  301. DWORD cbSize = sizeof(szDefaultFTPClient);
  302. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_FTPFOLDER, SZ_REGVALUE_PREVIOUS_FTP_CLIENT, NULL, szDefaultFTPClient, &cbSize))
  303. {
  304. EVAL(ERROR_SUCCESS == SHSetValue(HKEY_CLASSES_ROOT, SZ_REGKEY_FTPCLASS, SZ_REGVALUE_DEFAULT_FTP_CLIENT, REG_SZ, szDefaultFTPClient, ((lstrlen(szDefaultFTPClient) + 1) * sizeof(TCHAR))));
  305. EVAL(ERROR_SUCCESS == SHDeleteValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_FTPFOLDER, SZ_REGVALUE_PREVIOUS_FTP_CLIENT));
  306. }
  307. return hr;
  308. }
  309. HRESULT BackupCurrentFTPClient(void)
  310. {
  311. HRESULT hr = S_OK;
  312. TCHAR szDefaultFTPClient[MAX_PATH];
  313. DWORD cbSize = sizeof(szDefaultFTPClient);
  314. // Is a handler installed and is it not ours?
  315. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, SZ_REGKEY_FTPCLASS, SZ_REGVALUE_DEFAULT_FTP_CLIENT, NULL, szDefaultFTPClient, &cbSize) &&
  316. StrCmpI(szDefaultFTPClient, SZ_REGDATA_IE_FTP_CLIENT))
  317. {
  318. // Yes, so back it up to be restored later if needed.
  319. EVAL(ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, SZ_REGKEY_FTPCLASS, SZ_REGVALUE_DEFAULT_FTP_CLIENT, NULL, szDefaultFTPClient, &cbSize));
  320. EVAL(ERROR_SUCCESS == SHSetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_FTPFOLDER, SZ_REGVALUE_PREVIOUS_FTP_CLIENT, REG_SZ, szDefaultFTPClient, ((lstrlen(szDefaultFTPClient) + 1) * sizeof(TCHAR))));
  321. }
  322. return hr;
  323. }
  324. HRESULT CFtpInstaller::MakeIEDefautlFTPClient(void)
  325. {
  326. HRESULT hr = S_OK;
  327. EVAL(SUCCEEDED(BackupCurrentFTPClient()));
  328. HINSTANCE hinstFTP = GetModuleHandle(TEXT("MSIEFTP.DLL"));
  329. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  330. hr = CallRegInstall(hinstFTP, "FtpForceAssociations");
  331. ASSERT(SUCCEEDED(hr));
  332. if (hinstAdvPack)
  333. FreeLibrary(hinstAdvPack);
  334. return hr;
  335. }