dllreg.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 19k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. // dllreg.c -- autmatic registration and unregistration
  2. //
  3. #include "priv.h"
  4. #include "util.h"
  5. #include "htregmng.h"
  6. #include <advpub.h>
  7. #include <comcat.h>
  8. #include <winineti.h>
  9. #include "resource.h"
  10. #include <mluisupp.h>
  11. #ifdef UNIX
  12. #include "unixstuff.h"
  13. #endif
  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. //
  22. // helper macros
  23. //
  24. //#define RegCreate(hk, psz, phk) if (ERROR_SUCCESS != RegCreateKeyEx((hk), psz, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, (phk), &dwDummy)) goto CleanUp
  25. //#define RegSetStr(hk, psz) if (ERROR_SUCCESS != RegSetValueEx((hk), NULL, 0, REG_SZ, (BYTE*)(psz), lstrlen(psz)+1)) goto CleanUp
  26. //#define RegSetStrValue(hk, pszStr, psz)    if(ERROR_SUCCESS != RegSetValueEx((hk), (const char *)(pszStr), 0, REG_SZ, (BYTE*)(psz), lstrlen(psz)+1)) goto CleanUp
  27. //#define RegCloseK(hk) RegCloseKey(hk); hk = NULL
  28. #define RegOpenK(hk, psz, phk) if (ERROR_SUCCESS != RegOpenKeyEx(hk, psz, 0, KEY_READ|KEY_WRITE, phk)) return FALSE
  29. //=--------------------------------------------------------------------------=
  30. // UnregisterTypeLibrary
  31. //=--------------------------------------------------------------------------=
  32. // blows away the type library keys for a given libid.
  33. //
  34. // Parameters:
  35. //    REFCLSID        - [in] libid to blow away.
  36. //
  37. // Output:
  38. //    BOOL            - TRUE OK, FALSE bad.
  39. //
  40. // Notes:
  41. //    - WARNING: this function just blows away the entire type library section,
  42. //      including all localized versions of the type library.  mildly anti-
  43. //      social, but not killer.
  44. //
  45. BOOL UnregisterTypeLibrary
  46. (
  47.     const CLSID* piidLibrary
  48. )
  49. {
  50.     TCHAR szScratch[GUID_STR_LEN];
  51.     HKEY hk;
  52.     BOOL f;
  53.     // convert the libid into a string.
  54.     //
  55.     SHStringFromGUID(*piidLibrary, szScratch, ARRAYSIZE(szScratch));
  56.     RegOpenK(HKEY_CLASSES_ROOT, TEXT("TypeLib"), &hk);
  57.     f = SHDeleteKey(hk, szScratch);
  58.     RegCloseKey(hk);
  59.     return f;
  60. }
  61. HRESULT SHRegisterTypeLib(void)
  62. {
  63.     HRESULT hr = S_OK;
  64.     ITypeLib *pTypeLib;
  65.     DWORD   dwPathLen;
  66.     TCHAR   szTmp[MAX_PATH];
  67.     // Load and register our type library.
  68.     //
  69.     dwPathLen = GetModuleFileName(HINST_THISDLL, szTmp, ARRAYSIZE(szTmp));
  70. #ifdef UNIX
  71.     dwPathLen = ConvertModuleNameToUnix( szTmp );
  72. #endif
  73.     hr = LoadTypeLib(szTmp, &pTypeLib);
  74.     if (SUCCEEDED(hr))
  75.     {
  76.         // call the unregister type library as we had some old junk that
  77.         // was registered by a previous version of OleAut32, which is now causing
  78.         // the current version to not work on NT...
  79.         UnregisterTypeLibrary(&LIBID_SHDocVw);
  80.         hr = RegisterTypeLib(pTypeLib, szTmp, NULL);
  81.         if (FAILED(hr))
  82.         {
  83.             TraceMsg(DM_WARNING, "sccls: RegisterTypeLib failed (%x)", hr);
  84.         }
  85.         pTypeLib->Release();
  86.     }
  87.     else
  88.     {
  89.         TraceMsg(DM_WARNING, "sccls: LoadTypeLib failed (%x)", hr);
  90.     }
  91.     return hr;
  92. }
  93. //
  94. // The actual functions called
  95. //
  96. /*----------------------------------------------------------
  97. Purpose: Calls the ADVPACK entry-point which executes an inf
  98.          file section.
  99. */
  100. HRESULT 
  101. CallRegInstall(
  102.     LPSTR pszSection,
  103.     BOOL bUninstall)
  104. {
  105.     HRESULT hr = E_FAIL;
  106.     HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  107.     if (hinstAdvPack)
  108.     {
  109.         REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  110.         if (pfnri)
  111.         {
  112.             char szIEPath[MAX_PATH];
  113.             STRENTRY seReg[] = {
  114.                 { "MSIEXPLORE", szIEPath },
  115.                 // These two NT-specific entries must be at the end
  116.                 { "25", "%SystemRoot%" },
  117.                 { "11", "%SystemRoot%\system32" },
  118.             };
  119.             STRTABLE stReg = { ARRAYSIZE(seReg) - 2, seReg };
  120.             // Get the location of iexplore from the registry
  121.             if ( !EVAL(GetIEPath(szIEPath, SIZECHARS(szIEPath))) )
  122.             {
  123.                 // Failed, just say "iexplore"
  124. #ifndef UNIX
  125.                 StrCpyNA(szIEPath, "iexplore.exe", ARRAYSIZE(szIEPath));
  126. #else
  127.                 StrCpyNA(szIEPath, "iexplorer", ARRAYSIZE(szIEPath));
  128. #endif
  129.             }
  130.             if (g_fRunningOnNT)
  131.             {
  132.                 // If on NT, we want custom action for %25% %11%
  133.                 // so that it uses %SystemRoot% in writing the
  134.                 // path to the registry.
  135.                 stReg.cEntries += 2;
  136.             }
  137.             hr = pfnri(g_hinst, pszSection, &stReg);
  138.             if (bUninstall)
  139.             {
  140.                 // ADVPACK will return E_UNEXPECTED if you try to uninstall 
  141.                 // (which does a registry restore) on an INF section that was 
  142.                 // never installed.  We uninstall sections that may never have
  143.                 // been installed, so ignore this error
  144.                 hr = ((E_UNEXPECTED == hr) ? S_OK : hr);
  145.             }
  146.         }
  147.         else
  148.             TraceMsg(TF_ERROR, "DLLREG CallRegInstall() calling GetProcAddress(hinstAdvPack, "RegInstall") failed");
  149.         FreeLibrary(hinstAdvPack);
  150.     }
  151.     else
  152.         TraceMsg(TF_ERROR, "DLLREG CallRegInstall() Failed to load ADVPACK.DLL");
  153.     return hr;
  154. }
  155. const CATID * const c_DeskBandClasses[] = 
  156. {
  157.     &CLSID_QuickLinks,
  158.     &CLSID_AddressBand,
  159.     NULL
  160. };
  161. const CATID * const c_OldDeskBandClasses[] = 
  162. {
  163.     &CLSID_QuickLinksOld,
  164.     NULL
  165. };
  166. const CATID * const c_InfoBandClasses[] =
  167. {
  168.     &CLSID_SearchBand,
  169.     &CLSID_FavBand,
  170. #ifdef ENABLE_CHANNELPANE
  171.     &CLSID_ChannelBand,
  172. #endif
  173.     &CLSID_HistBand,
  174.     &CLSID_ExplorerBand,
  175.     NULL
  176. };
  177. #ifndef ENABLE_CHANNELPANE
  178. const CATID * const c_OldInfoBandClasses[] =
  179. {
  180.     &CLSID_ChannelBand,
  181.     NULL
  182. };
  183. #endif
  184. // We don't care about any CLSIDs.
  185. // We just want to register the category so it gets a nice name
  186. const CATID * const c_CommBandClasses[] =
  187. {
  188.     NULL
  189. };
  190. #if 1 // { ALPHA BUGBUG ComCat bug work-around on alpha, nuke this eventually?
  191. //***   HasImplCat -- does "HKCR/CLSID/{clsid}/Implemented Categories" exist
  192. // NOTES
  193. //  used for ComCat bug work-around on alpha
  194. BOOL HasImplCat(const CATID *pclsid)
  195. {
  196.     HKEY hk;
  197.     TCHAR szClass[GUIDSTR_MAX];
  198.     TCHAR szImpl[MAX_PATH];      // "CLSID/{clsid}/Implemented Categories" BUGBUG size?
  199.     // "CLSID/{clsid}/Implemented Categories"
  200.     SHStringFromGUID(*pclsid, szClass, ARRAYSIZE(szClass));
  201.     ASSERT(lstrlen(szClass) == GUIDSTR_MAX - 1);
  202.     wnsprintf(szImpl, ARRAYSIZE(szImpl), TEXT("CLSID\%s\Implemented Categories"), szClass);
  203.     if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szImpl, 0, KEY_READ, &hk) == ERROR_SUCCESS) {
  204.         RegCloseKey(hk);
  205.         return TRUE;
  206.     }
  207.     else {
  208.         TraceMsg(DM_WARNING, "HasImplCat: %s: ret 0", szImpl);
  209.         return FALSE;
  210.     }
  211. }
  212. #endif // }
  213. enum { CCR_REG = 1, CCR_UNREG = 0, CCR_UNREGIMP = -1 };
  214. //***   RegisterOneCategory -- [un]register ComCat implementor(s) and category
  215. // ENTRY/EXIT
  216. //  eRegister   CCR_REG, CCR_UNREG, CCR_UNREGIMP
  217. //      CCR_REG, UNREG      reg/unreg implementor(s) and category
  218. //      CCR_UNREGIMP        unreg implementor(s) only
  219. //  pcatidCat   e.g. CATID_DeskBand
  220. //  idResCat    e.g. IDS_CATDESKBAND
  221. //  pcatidImpl  e.g. c_DeskBandClasses
  222. void RegisterOneCategory(const CATID *pcatidCat, UINT idResCat, const CATID * const *pcatidImpl, UINT eRegister)
  223. {
  224.     ICatRegister* pcr;
  225.     HRESULT hres = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL,
  226.         CLSCTX_INPROC_SERVER, IID_ICatRegister, (LPVOID*)&pcr);
  227.     
  228.     if (pcr) {
  229.         if (eRegister == CCR_REG) {
  230.             
  231.             // register the category
  232.             CATEGORYINFO catinfo;
  233.             catinfo.catid = *pcatidCat;     // e.g. CATID_DESKBAND
  234.             catinfo.lcid = LOCALE_USER_DEFAULT;
  235.             MLLoadString(idResCat, catinfo.szDescription, ARRAYSIZE(catinfo.szDescription));
  236.             hres = pcr->RegisterCategories(1, &catinfo);
  237.             
  238.             // register the classes that implement categories
  239.             for ( ; *pcatidImpl != NULL; pcatidImpl++) {
  240.                 CLSID clsid = **pcatidImpl;
  241.                 CATID catid = *pcatidCat;
  242.                 hres = pcr->RegisterClassImplCategories(clsid, 1, &catid);
  243.             }
  244.             
  245.         } else {
  246.             
  247.             // unregister the classes that implement categories
  248.             for ( ; *pcatidImpl != NULL; pcatidImpl++) {
  249.                 CLSID clsid = **pcatidImpl;
  250.                 CATID catid = *pcatidCat;
  251. #if 1 // { ALPHA BUGBUG ComCat bug work-around on alpha, nuke this eventually?
  252.                 // workaround comcat/alpha bug
  253.                 // n.b. we do this for non-alpha too to reduce testing impact
  254.                 // ie40:63004: comcat does RegCloseKey(invalid) on checked
  255.                 // nt/alpha if the clsid doesn't exist (e.g. for QuickLinksOld)
  256.                 if (!HasImplCat(&clsid))
  257.                     continue;
  258. #endif // }
  259.                 hres = pcr->UnRegisterClassImplCategories(clsid, 1, &catid);
  260.             }
  261.             
  262.             if (eRegister == CCR_UNREG) {
  263.                 // BUGBUG do we want to do this?  other classes (e.g. 3rd party
  264.                 // ones) might still be using the category.  however since we're
  265.                 // the component that added (and supports) the category, it
  266.                 // seems correct that we should remove it when we unregister.
  267.                 // unregister the category
  268.                 CATID catid = *pcatidCat;
  269.                 hres = pcr->UnRegisterCategories(1, &catid);
  270.             }
  271.             
  272.         }
  273.         pcr->Release();
  274.     }
  275. }
  276. void RegisterCategories(BOOL fRegister)
  277. {
  278.     UINT eRegister = fRegister ? CCR_REG : CCR_UNREG;
  279.     RegisterOneCategory(&CATID_DeskBand, IDS_CATDESKBAND, c_DeskBandClasses, eRegister);
  280.     RegisterOneCategory(&CATID_InfoBand, IDS_CATINFOBAND, c_InfoBandClasses, eRegister);
  281.     if (fRegister) {
  282.         // only nuke the implementor(s), not the category
  283.         RegisterOneCategory(&CATID_DeskBand, IDS_CATDESKBAND, c_OldDeskBandClasses, CCR_UNREGIMP);
  284. #ifndef ENABLE_CHANNELPANE
  285.         RegisterOneCategory(&CATID_InfoBand, IDS_CATDESKBAND, c_OldInfoBandClasses, CCR_UNREGIMP);
  286. #endif  // ENABLE_CHANNELPANE
  287.     }
  288.     RegisterOneCategory(&CATID_CommBand, IDS_CATCOMMBAND, c_CommBandClasses, eRegister);
  289. }
  290. HRESULT CreateShellFolderPath(LPCTSTR pszPath, LPCTSTR pszGUID, BOOL bUICLSID)
  291. {
  292.     if (!PathFileExists(pszPath))
  293.         CreateDirectory(pszPath, NULL);
  294.     // Mark the folder as a system directory
  295.     if (SetFileAttributes(pszPath, FILE_ATTRIBUTE_SYSTEM))
  296.     {
  297.         TCHAR szDesktopIni[MAX_PATH];
  298.         // Write in the desktop.ini the cache folder class ID
  299.         PathCombine(szDesktopIni, pszPath, TEXT("desktop.ini"));
  300.         // If the desktop.ini already exists, make sure it is writable
  301.         if (PathFileExists(szDesktopIni))
  302.             SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_NORMAL);
  303.         // (First, flush the cache to make sure the desktop.ini
  304.         // file is really created.)
  305.         WritePrivateProfileString(NULL, NULL, NULL, szDesktopIni);
  306.         WritePrivateProfileString(TEXT(".ShellClassInfo"), bUICLSID ? TEXT("UICLSID") : TEXT("CLSID"), pszGUID, szDesktopIni);
  307.         WritePrivateProfileString(NULL, NULL, NULL, szDesktopIni);
  308.         // Hide the desktop.ini since the shell does not selectively
  309.         // hide it.
  310.         SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_HIDDEN);
  311.         return NOERROR;
  312.     }
  313.     else
  314.     {
  315.         TraceMsg(TF_ERROR, "Cannot make %s a system folder", pszPath);
  316.         return E_FAIL;
  317.     }
  318. }
  319. STDAPI 
  320. DllRegisterServer(void)
  321. {
  322.     HRESULT hr = S_OK;
  323.     HRESULT hrExternal = S_OK;
  324.     TraceMsg(DM_TRACE, "DLLREG DllRegisterServer() Beginning");
  325. #ifdef DEBUG
  326.     if (IsFlagSet(g_dwBreakFlags, BF_ONAPIENTER))
  327.     {
  328.         TraceMsg(TF_ALWAYS, "Stopping in DllRegisterServer");
  329.         DEBUG_BREAK;
  330.     }
  331. #endif
  332.     // Delete any old registration entries, then add the new ones.
  333.     // Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
  334.     // (The inf engine doesn't guarantee DelReg/AddReg order, that's
  335.     // why we explicitly unreg and reg here.)
  336.     //
  337.     HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  338.     hr = THR(CallRegInstall("InstallControls", FALSE));
  339.     if (SUCCEEDED(hrExternal))
  340.         hrExternal = hr;
  341.     if (hinstAdvPack)
  342.         FreeLibrary(hinstAdvPack);
  343.     hr = THR(SHRegisterTypeLib());
  344.     if (SUCCEEDED(hrExternal))
  345.         hrExternal = hr;
  346. #ifdef UNIX
  347.     hrExternal = UnixRegisterBrowserInActiveSetup();
  348. #endif /* UNIX */
  349.     return hrExternal;
  350. }
  351. STDAPI DllUnregisterServer(void)
  352. {
  353.     HRESULT hr;
  354.     TraceMsg(DM_TRACE, "DLLREG DllUnregisterServer() Beginning");
  355.     // UnInstall the registry values
  356.     hr = THR(CallRegInstall("UnInstallControls", TRUE));
  357.     return hr;
  358. }
  359. extern HRESULT UpgradeSettings(void);
  360. /*----------------------------------------------------------
  361. Purpose: Install/uninstall user settings
  362. Description: Note that this function has special error handling.
  363.              The function will keep hrExternal with the worse error
  364.              but will only stop executing util the internal error (hr)
  365.              gets really bad.  This is because we need the external
  366.              error to catch incorrectly authored INFs but the internal
  367.              error to be robust in attempting to install other INF sections
  368.              even if one doesn't make it.
  369. */
  370. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  371. {
  372.     HRESULT hr = S_OK;
  373.     HRESULT hrExternal = S_OK;
  374.     HINSTANCE hinstAdvPack;
  375.     ASSERT(IS_VALID_STRING_PTRW(pszCmdLine, -1));
  376.     g_bInDllInstall = TRUE;
  377.     if (0 == StrCmpIW(pszCmdLine, TEXTW("ForceAssoc")))
  378.     {
  379.         InstallIEAssociations(IEA_FORCEIE);
  380.         g_bInDllInstall = FALSE;
  381.         return hr;
  382.     }
  383.     hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));    // Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
  384. #ifdef DEBUG
  385.     if (IsFlagSet(g_dwBreakFlags, BF_ONAPIENTER))
  386.     {
  387.         TraceMsg(TF_ALWAYS, "Stopping in DllInstall");
  388.         DEBUG_BREAK;
  389.     }
  390. #endif
  391.     // Assume we're installing for integrated shell unless otherwise
  392.     // noted.
  393.     BOOL bIntegrated = ((WhichPlatform() == PLATFORM_INTEGRATED) ? TRUE : FALSE);
  394.     TraceMsg(DM_TRACE, "DLLREG DllInstall(bInstall=%lx, pszCmdLine="%ls") bIntegrated=%lx", (DWORD) bInstall, pszCmdLine, (DWORD) bIntegrated);
  395.     CoInitialize(0);
  396.     if (bInstall)
  397.     {
  398.         // Backup current associations because InstallPlatformRegItems() may overwrite.
  399.         hr = THR(CallRegInstall("InstallAssociations", FALSE));
  400.         if (SUCCEEDED(hrExternal))
  401.             hrExternal = hr;
  402.         hr = THR(CallRegInstall("InstallBrowser", FALSE));
  403.         if (SUCCEEDED(hrExternal))
  404.             hrExternal = hr;
  405.         if (bIntegrated)
  406.         {
  407.             // UnInstall settings that cannot be installed with Shell Integration.
  408.             // This will be a NO-OP if it wasn't installed.
  409.             hr = THR(CallRegInstall("UnInstallOnlyBrowser", TRUE));
  410.             if (SUCCEEDED(hrExternal))
  411.                 hrExternal = hr;
  412.             // Install IE4 shell components too.
  413.             hr = THR(CallRegInstall("InstallOnlyShell", FALSE));
  414.             if (SUCCEEDED(hrExternal))
  415.                 hrExternal = hr;
  416.             if (GetUIVersion() >= 5)
  417.             {
  418.                 hr = THR(CallRegInstall("InstallWin2KShell", FALSE));
  419.                 if (SUCCEEDED(hrExternal))
  420.                     hrExternal = hr;
  421.             }
  422.             else
  423.             {
  424.                 hr = THR(CallRegInstall("InstallPreWin2KShell", FALSE));
  425.                 if (SUCCEEDED(hrExternal))
  426.                     hrExternal = hr;
  427.             }
  428.         }
  429.         else
  430.         {
  431.             // UnInstall Shell Integration settings.
  432.             // This will be a NO-OP if it wasn't installed.
  433.             hr = THR(CallRegInstall("UnInstallOnlyShell", TRUE));
  434.             if (SUCCEEDED(hrExternal))
  435.                 hrExternal = hr;
  436.             // Install IE4 shell components too.
  437.             hr = THR(CallRegInstall("InstallOnlyBrowser", FALSE));
  438.             if (SUCCEEDED(hrExternal))
  439.                 hrExternal = hr;
  440.         }
  441.         UpgradeSettings();
  442.         UninstallCurrentPlatformRegItems();
  443.         InstallIEAssociations(IEA_NORMAL);
  444.         RegisterCategories(TRUE);
  445.         SHRegisterTypeLib();
  446.     }
  447.     else
  448.     {
  449.         // Uninstall browser-only or integrated-browser?
  450.         UninstallPlatformRegItems(bIntegrated);
  451.         // Restore previous association settings that UninstallPlatformRegItems() could
  452.         // have Uninstalled.
  453.         hr = THR(CallRegInstall("UnInstallAssociations", TRUE));
  454.         if (SUCCEEDED(hrExternal))
  455.             hrExternal = hr;
  456.         // UnInstall settings that cannot be installed with Shell Integration.
  457.         // This will be a NO-OP if it wasn't installed.
  458.         hr = THR(CallRegInstall("UnInstallOnlyBrowser", TRUE));
  459.         if (SUCCEEDED(hrExternal))
  460.             hrExternal = hr;
  461.         // UnInstall Shell Integration settings.
  462.         // This will be a NO-OP if it wasn't installed.
  463.         hr = THR(CallRegInstall("UnInstallShell", TRUE));
  464.         if (SUCCEEDED(hrExternal))
  465.             hrExternal = hr;
  466.         hr = THR(CallRegInstall("UnInstallBrowser", TRUE));
  467.         if (SUCCEEDED(hrExternal))
  468.             hrExternal = hr;
  469.         UnregisterTypeLibrary(&LIBID_SHDocVw);
  470.         RegisterCategories(FALSE);
  471.     }
  472.     if (hinstAdvPack)
  473.         FreeLibrary(hinstAdvPack);
  474.     g_bInDllInstall = FALSE;
  475.     CoUninitialize();
  476.     return hrExternal;    
  477. }    
  478. /*----------------------------------------------------------
  479. Purpose: Gets a registry value that is User Specifc.  
  480.          This will open HKEY_CURRENT_USER if it exists,
  481.          otherwise it will open HKEY_LOCAL_MACHINE.  
  482. Returns: DWORD containing success or error code.
  483. Cond:    --
  484. */
  485. LONG OpenRegUSKey(LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)           
  486. {
  487.     DWORD dwRet = RegOpenKeyEx(HKEY_CURRENT_USER, lpSubKey, ulOptions, samDesired, phkResult);
  488.     if (ERROR_SUCCESS != dwRet)
  489.         dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, ulOptions, samDesired, phkResult);
  490.     return dwRet;
  491. }