Source code of Windows XP (NT5)
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.

433 lines
12 KiB

  1. // dllreg.c -- autmatic registration and unregistration
  2. //
  3. #include "priv.h"
  4. #include <advpub.h>
  5. #include <comcat.h>
  6. #include <winineti.h>
  7. #include "resource.h"
  8. #include "regkeys.h"
  9. #include "DllRegHelper.h"
  10. #ifdef UNIX
  11. #include "unixstuff.h"
  12. #endif
  13. void AddNotepadToOpenWithList();
  14. //=--------------------------------------------------------------------------=
  15. // miscellaneous [useful] numerical constants
  16. //=--------------------------------------------------------------------------=
  17. // the length of a guid once printed out with -'s, leading and trailing bracket,
  18. // plus 1 for NULL
  19. //
  20. #define GUID_STR_LEN 40
  21. // ISSUE/010429/davidjen need to register typelib LIBID_BrowseUI
  22. // before checkin in verify if this typelib already gets registered by setup!!!!!!!
  23. #ifndef ATL_ENABLED
  24. #define ATL_ENABLED
  25. #endif
  26. //=--------------------------------------------------------------------------=
  27. // UnregisterTypeLibrary
  28. //=--------------------------------------------------------------------------=
  29. // blows away the type library keys for a given libid.
  30. //
  31. // Parameters:
  32. // REFCLSID - [in] libid to blow away.
  33. //
  34. // Output:
  35. // BOOL - TRUE OK, FALSE bad.
  36. //
  37. // Notes:
  38. // - WARNING: this function just blows away the entire type library section,
  39. // including all localized versions of the type library. mildly anti-
  40. // social, but not killer.
  41. //
  42. #ifdef ATL_ENABLED
  43. BOOL UnregisterTypeLibrary
  44. (
  45. const CLSID* piidLibrary
  46. )
  47. {
  48. TCHAR szScratch[GUID_STR_LEN];
  49. HKEY hk;
  50. // convert the libid into a string.
  51. //
  52. SHStringFromGUID(*piidLibrary, szScratch, ARRAYSIZE(szScratch));
  53. if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "TypeLib", 0, KEY_READ|KEY_WRITE, &hk))
  54. {
  55. SHDeleteKey(hk, szScratch);
  56. RegCloseKey(hk);
  57. }
  58. return TRUE;
  59. }
  60. #endif
  61. #ifdef ATL_ENABLED
  62. HRESULT SHRegisterTypeLib(void)
  63. {
  64. HRESULT hr = S_OK;
  65. ITypeLib *pTypeLib;
  66. DWORD dwPathLen;
  67. WCHAR wzModuleName[MAX_PATH];
  68. // Load and register our type library.
  69. //
  70. dwPathLen = GetModuleFileName(HINST_THISDLL, wzModuleName, ARRAYSIZE(wzModuleName));
  71. #ifdef UNIX
  72. dwPathLen = ConvertModuleNameToUnix( wzModuleName );
  73. #endif
  74. hr = LoadTypeLib(wzModuleName, &pTypeLib);
  75. if (SUCCEEDED(hr))
  76. {
  77. // call the unregister type library as we had some old junk that
  78. // was registered by a previous version of OleAut32, which is now causing
  79. // the current version to not work on NT...
  80. UnregisterTypeLibrary(&LIBID_BrowseUI);
  81. hr = RegisterTypeLib(pTypeLib, wzModuleName, NULL);
  82. if (FAILED(hr))
  83. {
  84. TraceMsg(DM_WARNING, "sccls: RegisterTypeLib failed (%x)", hr);
  85. }
  86. pTypeLib->Release();
  87. }
  88. else
  89. {
  90. TraceMsg(DM_WARNING, "sccls: LoadTypeLib failed (%x)", hr);
  91. }
  92. return hr;
  93. }
  94. #endif
  95. void SetBrowseNewProcess(void)
  96. // We want to enable browse new process by default on high capacity
  97. // machines. We do this in the per user section so that people can
  98. // disable it if they want.
  99. {
  100. static const TCHAR c_szBrowseNewProcessReg[] = REGSTR_PATH_EXPLORER TEXT("\\BrowseNewProcess");
  101. static const TCHAR c_szBrowseNewProcess[] = TEXT("BrowseNewProcess");
  102. // no way if less than ~30 meg (allow some room for debuggers, checked build etc)
  103. MEMORYSTATUS ms;
  104. SYSTEM_INFO si;
  105. ms.dwLength=sizeof(MEMORYSTATUS);
  106. GlobalMemoryStatus(&ms);
  107. GetSystemInfo(&si);
  108. if (!g_fRunningOnNT && ((si.dwProcessorType == PROCESSOR_INTEL_486) ||
  109. (si.dwProcessorType == PROCESSOR_INTEL_386)))
  110. {
  111. // Bail if Win9x and 386 or 486 cpu
  112. return;
  113. }
  114. if (ms.dwTotalPhys < 30*1024*1024)
  115. return;
  116. SHRegSetUSValue(c_szBrowseNewProcessReg, c_szBrowseNewProcess, REG_SZ, TEXT("yes"), SIZEOF(TEXT("yes")), SHREGSET_FORCE_HKLM);
  117. }
  118. /*----------------------------------------------------------
  119. Purpose: Queries the registry for the location of the path
  120. of Internet Explorer and returns it in pszBuf.
  121. Returns: TRUE on success
  122. FALSE if path cannot be determined
  123. Cond: --
  124. */
  125. #define SIZE_FLAG sizeof(" -nohome")
  126. BOOL
  127. GetIEPath(
  128. OUT LPSTR pszBuf,
  129. IN DWORD cchBuf,
  130. IN BOOL bInsertQuotes)
  131. {
  132. BOOL bRet = FALSE;
  133. HKEY hkey;
  134. *pszBuf = '\0';
  135. // Get the path of Internet Explorer
  136. if (NO_ERROR != RegOpenKeyExA(HKEY_LOCAL_MACHINE, SZ_REGKEY_IEXPLOREA, 0, KEY_QUERY_VALUE, &hkey))
  137. {
  138. TraceMsg(TF_ERROR, "GetIEPath(): RegOpenKey( %s ) Failed", c_szIexploreKey) ;
  139. }
  140. else
  141. {
  142. DWORD cbBrowser;
  143. DWORD dwType;
  144. if (bInsertQuotes)
  145. lstrcatA(pszBuf, "\"");
  146. cbBrowser = CbFromCchA(cchBuf - SIZE_FLAG - 4);
  147. if (NO_ERROR != RegQueryValueExA(hkey, "", NULL, &dwType,
  148. (LPBYTE)&pszBuf[bInsertQuotes?1:0], &cbBrowser))
  149. {
  150. TraceMsg(TF_ERROR, "GetIEPath(): RegQueryValueEx() for Iexplore path failed");
  151. }
  152. else
  153. {
  154. bRet = TRUE;
  155. }
  156. if (bInsertQuotes)
  157. lstrcatA(pszBuf, "\"");
  158. RegCloseKey(hkey);
  159. }
  160. return bRet;
  161. }
  162. //
  163. // The actual functions called
  164. //
  165. /*----------------------------------------------------------
  166. Purpose: Calls the ADVPACK entry-point which executes an inf
  167. file section.
  168. */
  169. HRESULT
  170. CallRegInstall(
  171. LPSTR pszSection,
  172. BOOL bUninstall)
  173. {
  174. HRESULT hr = E_FAIL;
  175. HINSTANCE hinstAdvPack = LoadLibraryA("ADVPACK.DLL");
  176. if (hinstAdvPack)
  177. {
  178. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  179. if (pfnri)
  180. {
  181. char szIEPath[MAX_PATH];
  182. STRENTRY seReg[] = {
  183. { "MSIEXPLORE", szIEPath },
  184. // These two NT-specific entries must be at the end
  185. { "25", "%SystemRoot%" },
  186. { "11", "%SystemRoot%\\system32" },
  187. };
  188. STRTABLE stReg = { ARRAYSIZE(seReg) - 2, seReg };
  189. // Get the location of iexplore from the registry
  190. if ( !GetIEPath(szIEPath, SIZECHARS(szIEPath), TRUE) )
  191. {
  192. #ifndef UNIX
  193. // Failed, just say "iexplore"
  194. lstrcpyA(szIEPath, "iexplore.exe");
  195. AssertMsg(0, TEXT("IE.INF either hasn't run or hasn't set the AppPath key. NOT AN IE BUG. Look for changes to IE.INX."));
  196. #else
  197. lstrcpyA(szIEPath, "iexplorer");
  198. #endif
  199. }
  200. if (g_fRunningOnNT)
  201. {
  202. // If on NT, we want custom action for %25% %11%
  203. // so that it uses %SystemRoot% in writing the
  204. // path to the registry.
  205. stReg.cEntries += 2;
  206. }
  207. hr = pfnri(g_hinst, pszSection, &stReg);
  208. if (bUninstall)
  209. {
  210. // ADVPACK will return E_UNEXPECTED if you try to uninstall
  211. // (which does a registry restore) on an INF section that was
  212. // never installed. We uninstall sections that may never have
  213. // been installed, so ignore this error
  214. hr = ((E_UNEXPECTED == hr) ? S_OK : hr);
  215. }
  216. }
  217. else
  218. TraceMsg(DM_ERROR, "DLLREG CallRegInstall() calling GetProcAddress(hinstAdvPack, \"RegInstall\") failed");
  219. FreeLibrary(hinstAdvPack);
  220. }
  221. else
  222. TraceMsg(DM_ERROR, "DLLREG CallRegInstall() Failed to load ADVPACK.DLL");
  223. return hr;
  224. }
  225. const CATID * const c_InfoBandClasses[] =
  226. {
  227. &CLSID_SearchBand,
  228. &CLSID_MediaBand,
  229. NULL
  230. };
  231. void RegisterCategories(BOOL fRegister)
  232. {
  233. enum DRH_REG_MODE eRegister = fRegister ? CCR_REG : CCR_UNREG;
  234. DRH_RegisterOneCategory(&CATID_InfoBand, IDS_CATINFOBAND, c_InfoBandClasses, eRegister);
  235. }
  236. STDAPI DllRegisterServer(void)
  237. {
  238. HRESULT hr = S_OK;
  239. HRESULT hrExternal = S_OK; //used to return the first failure
  240. TraceMsg(DM_TRACE, "DLLREG DllRegisterServer() Beginning");
  241. #ifdef DEBUG
  242. if (IsFlagSet(g_dwBreakFlags, BF_ONAPIENTER))
  243. {
  244. TraceMsg(TF_ALWAYS, "Stopping in DllRegisterServer");
  245. DEBUG_BREAK;
  246. }
  247. #endif
  248. // Delete any old registration entries, then add the new ones.
  249. // Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
  250. // (The inf engine doesn't guarantee DelReg/AddReg order, that's
  251. // why we explicitly unreg and reg here.)
  252. //
  253. HINSTANCE hinstAdvPack = LoadLibraryA("ADVPACK.DLL");
  254. hr = THR(CallRegInstall("InstallControls", FALSE));
  255. if (SUCCEEDED(hrExternal))
  256. hrExternal = hr;
  257. if (hinstAdvPack)
  258. FreeLibrary(hinstAdvPack);
  259. #ifdef ATL_ENABLED
  260. // registers object, typelib and all interfaces in typelib
  261. hr = SHRegisterTypeLib();
  262. if (SUCCEEDED(hrExternal))
  263. hrExternal = hr;
  264. #endif
  265. return hrExternal;
  266. }
  267. STDAPI DllUnregisterServer(void)
  268. {
  269. HRESULT hr;
  270. TraceMsg(DM_TRACE, "DLLREG DllUnregisterServer() Beginning");
  271. // UnInstall the registry values
  272. hr = THR(CallRegInstall("UnInstallControls", TRUE));
  273. return hr;
  274. }
  275. void ImportQuickLinks();
  276. /*----------------------------------------------------------
  277. Purpose: Install/uninstall user settings
  278. Description: Note that this function has special error handling.
  279. The function will keep hrExternal with the worse error
  280. but will only stop executing util the internal error (hr)
  281. gets really bad. This is because we need the external
  282. error to catch incorrectly authored INFs but the internal
  283. error to be robust in attempting to install other INF sections
  284. even if one doesn't make it.
  285. */
  286. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  287. {
  288. HRESULT hr = S_OK;
  289. HRESULT hrExternal = S_OK;
  290. HRESULT hrInit = SHCoInitialize();
  291. if (bInstall)
  292. {
  293. // "U" means it's the per user install call
  294. if (pszCmdLine && (lstrcmpiW(pszCmdLine, L"U") == 0))
  295. {
  296. ImportQuickLinks();
  297. if (GetUIVersion() >= 5)
  298. {
  299. // don't upgrade these on XP -> XPSP#
  300. BOOL fUpgradeUserSettings = TRUE;
  301. WCHAR szVersion[50]; // plenty big for aaaa,bbbb,cccc,dddd
  302. DWORD cbVersion = sizeof(szVersion);
  303. if (ERROR_SUCCESS==SHGetValueW(HKEY_CURRENT_USER,
  304. L"Software\\Microsoft\\Active Setup\\Installed Components\\{89820200-ECBD-11cf-8B85-00AA005B4383}",L"Version", // guid is ie4uninit's Active Setup (it calls browseu's selfreg)
  305. NULL, szVersion, &cbVersion))
  306. {
  307. __int64 nverUpgradeFrom;
  308. __int64 nverWinXP;
  309. if (SUCCEEDED(GetVersionFromString64(szVersion, &nverUpgradeFrom)) &&
  310. SUCCEEDED(GetVersionFromString64(L"6,0,2600,0000", &nverWinXP)))
  311. {
  312. fUpgradeUserSettings = nverUpgradeFrom < nverWinXP;
  313. }
  314. }
  315. if (fUpgradeUserSettings)
  316. {
  317. hr = THR(CallRegInstall("InstallPerUser_BrowseUIShell", FALSE));
  318. }
  319. }
  320. }
  321. else
  322. {
  323. SetBrowseNewProcess();
  324. // Backup current associations because InstallPlatformRegItems() may overwrite.
  325. if (GetUIVersion() < 5)
  326. hr = THR(CallRegInstall("InstallBrowseUINonShell", FALSE));
  327. else
  328. hr = THR(CallRegInstall("InstallBrowseUIShell", FALSE));
  329. if (SUCCEEDED(hrExternal))
  330. hrExternal = hr;
  331. if (!IsOS(OS_WHISTLERORGREATER))
  332. {
  333. hr = THR(CallRegInstall("InstallBrowseUIPreWhistler", FALSE));
  334. if (SUCCEEDED(hrExternal))
  335. hrExternal = hr;
  336. }
  337. if (IsOS(OS_NT))
  338. {
  339. hr = THR(CallRegInstall("InstallBrowseUINTOnly", FALSE));
  340. if (SUCCEEDED(hrExternal))
  341. hrExternal = hr;
  342. }
  343. RegisterCategories(TRUE);
  344. #ifdef ATL_ENABLED
  345. SHRegisterTypeLib();
  346. #endif
  347. }
  348. // Add Notepad to the OpenWithList for .htm files
  349. AddNotepadToOpenWithList();
  350. }
  351. else
  352. {
  353. hr = THR(CallRegInstall("UnInstallBrowseUI", TRUE));
  354. if (SUCCEEDED(hrExternal))
  355. hrExternal = hr;
  356. #ifdef ATL_ENABLED
  357. UnregisterTypeLibrary(&LIBID_BrowseUI);
  358. #endif
  359. RegisterCategories(FALSE);
  360. }
  361. SHCoUninitialize(hrInit);
  362. return hrExternal;
  363. }