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.

250 lines
6.2 KiB

  1. #include "pch.h"
  2. #include <advpub.h>
  3. #include <cguid.h>
  4. #include "thisguid.h"
  5. #include "thisdll.h"
  6. #include "resource.h"
  7. #include <comcat.h> // Catagory registration.
  8. #define DECL_CRTFREE
  9. #include <crtfree.h>
  10. // {0CD7A5C0-9F37-11CE-AE65-08002B2E1262}
  11. const GUID CLSID_CabFolder = {0x0CD7A5C0L, 0x9F37, 0x11CE, 0xAE, 0x65, 0x08, 0x00, 0x2B, 0x2E, 0x12, 0x62};
  12. CThisDll g_ThisDll;
  13. STDAPI_(BOOL) DllMain(HINSTANCE hDll, DWORD dwReason, void *lpRes)
  14. {
  15. switch(dwReason)
  16. {
  17. case DLL_PROCESS_ATTACH:
  18. SHFusionInitializeFromModule(hDll);
  19. g_ThisDll.SetInstance(hDll);
  20. break;
  21. case DLL_PROCESS_DETACH:
  22. SHFusionUninitialize();
  23. break;
  24. }
  25. return TRUE;
  26. }
  27. STDAPI DllCanUnloadNow()
  28. {
  29. return (g_ThisDll.m_cRef.GetRef() == 0) && (g_ThisDll.m_cLock.GetRef() == 0) ?
  30. S_OK : S_FALSE;
  31. }
  32. // Procedure for uninstalling this DLL (given an INF file)
  33. void CALLBACK Uninstall(HWND hwndStub, HINSTANCE hInstance, LPTSTR lpszCmdLine, int nCmdShow)
  34. {
  35. RUNDLLPROC pfnCheckAPI = Uninstall;
  36. TCHAR szTitle[100];
  37. TCHAR szPrompt[100 + MAX_PATH];
  38. OSVERSIONINFO osvi;
  39. LPTSTR pszSetupDll;
  40. LPTSTR pszRunDllExe;
  41. if (!lpszCmdLine || lstrlen(lpszCmdLine)>=MAX_PATH)
  42. {
  43. return;
  44. }
  45. LoadString(g_ThisDll.GetInstance(),IDS_SUREUNINST,szPrompt,ARRAYSIZE(szPrompt));
  46. LoadString(g_ThisDll.GetInstance(),IDS_THISDLL,szTitle,ARRAYSIZE(szTitle));
  47. if (MessageBox(hwndStub, szPrompt, szTitle, MB_YESNO|MB_ICONSTOP) != IDYES)
  48. {
  49. return;
  50. }
  51. memset(&osvi, 0, sizeof(OSVERSIONINFO));
  52. osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  53. GetVersionEx(&osvi);
  54. if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  55. {
  56. /* Windows 95 uses SetupX */
  57. pszRunDllExe = TEXT("rundll.exe");
  58. pszSetupDll = TEXT("setupx.dll");
  59. }
  60. else
  61. {
  62. /* Windows NT uses SetupAPI */
  63. pszRunDllExe = TEXT("rundll32.exe");
  64. pszSetupDll = TEXT("setupapi.dll");
  65. }
  66. wsprintf(szPrompt, TEXT("%s,InstallHinfSection DefaultUninstall 132 %s"), pszSetupDll, lpszCmdLine);
  67. // Try to win the race before setup finds this DLL still in use.
  68. // If we lose, a reboot will be required to get rid of the DLL.
  69. SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
  70. ShellExecute(hwndStub, NULL, pszRunDllExe, szPrompt, NULL, SW_SHOWMINIMIZED);
  71. }
  72. // Call ADVPACK for the given section of our resource based INF>
  73. // hInstance = resource instance to get REGINST section from
  74. // szSection = section name to invoke
  75. HRESULT CallRegInstall(HINSTANCE hInstance, LPCSTR szSection)
  76. {
  77. HRESULT hr = E_FAIL;
  78. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  79. if (hinstAdvPack)
  80. {
  81. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  82. if ( pfnri )
  83. {
  84. #ifdef WINNT
  85. STRENTRY seReg[] =
  86. {
  87. // These two NT-specific entries must be at the end
  88. { "25", "%SystemRoot%" },
  89. { "11", "%SystemRoot%\\system32" },
  90. };
  91. STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
  92. hr = pfnri(hInstance, szSection, &stReg);
  93. #else
  94. hr = pfnri(hInstance, szSection, NULL);
  95. #endif
  96. }
  97. FreeLibrary(hinstAdvPack);
  98. }
  99. return hr;
  100. }
  101. STDAPI DllRegisterServer(void)
  102. {
  103. CallRegInstall(g_ThisDll.GetInstance(), "RegDll");
  104. // Register as a browseable shell extension.
  105. ICatRegister *pcr;
  106. HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
  107. NULL, CLSCTX_INPROC_SERVER,
  108. IID_ICatRegister, (void**)&pcr);
  109. if (SUCCEEDED(hr))
  110. {
  111. CATID acatid[1];
  112. acatid[0] = CATID_BrowsableShellExt;
  113. pcr->RegisterClassImplCategories(CLSID_CabFolder, 1, acatid);
  114. pcr->Release();
  115. }
  116. return S_OK;
  117. }
  118. STDAPI DllUnregisterServer(void)
  119. {
  120. CallRegInstall(g_ThisDll.GetInstance(), "UnregDll");
  121. return S_OK;
  122. }
  123. class CThisDllClassFactory : public IClassFactory
  124. {
  125. public:
  126. CThisDllClassFactory(REFCLSID rclsid);
  127. // *** IUnknown methods ***
  128. STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
  129. STDMETHODIMP_(ULONG) AddRef(void);
  130. STDMETHODIMP_(ULONG) Release(void);
  131. // *** IClassFactory methods ***
  132. STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void ** ppvObject);
  133. STDMETHODIMP LockServer(BOOL fLock);
  134. private:
  135. CRefDll m_cRefDll;
  136. LONG m_cRef;
  137. CLSID m_clsid;
  138. };
  139. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppvObj)
  140. {
  141. HRESULT hres;
  142. *ppvObj = NULL;
  143. if ((rclsid == CLSID_CabFolder) || (rclsid == CLSID_CabViewDataObject))
  144. {
  145. CThisDllClassFactory *pcf = new CThisDllClassFactory(rclsid);
  146. if (pcf)
  147. {
  148. hres = pcf->QueryInterface(riid, ppvObj);
  149. pcf->Release();
  150. }
  151. else
  152. hres = E_OUTOFMEMORY;
  153. }
  154. else
  155. hres = E_FAIL;
  156. return hres;
  157. }
  158. STDMETHODIMP CThisDllClassFactory::QueryInterface(REFIID riid, void ** ppvObj)
  159. {
  160. if ((riid == IID_IUnknown) || (riid == IID_IClassFactory))
  161. {
  162. *ppvObj = (void *)(IClassFactory *)this;
  163. }
  164. else
  165. {
  166. *ppvObj = NULL;
  167. return E_NOINTERFACE;
  168. }
  169. ((IUnknown *)*ppvObj)->AddRef();
  170. return NOERROR;
  171. }
  172. CThisDllClassFactory::CThisDllClassFactory(REFCLSID rclsid) : m_cRef(1), m_clsid(rclsid)
  173. {
  174. }
  175. STDMETHODIMP_(ULONG) CThisDllClassFactory::AddRef(void)
  176. {
  177. return InterlockedIncrement(&m_cRef);
  178. }
  179. STDMETHODIMP_(ULONG) CThisDllClassFactory::Release(void)
  180. {
  181. if (InterlockedDecrement(&m_cRef))
  182. return m_cRef;
  183. delete this;
  184. return 0;
  185. }
  186. STDMETHODIMP CThisDllClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void ** ppvObj)
  187. {
  188. if (pUnkOuter)
  189. return CLASS_E_NOAGGREGATION;
  190. return (CLSID_CabFolder == m_clsid) ?
  191. ::CabFolder_CreateInstance(riid, ppvObj) :
  192. ::CabViewDataObject_CreateInstance(riid, ppvObj);
  193. }
  194. STDMETHODIMP CThisDllClassFactory::LockServer(BOOL fLock)
  195. {
  196. if (fLock)
  197. {
  198. g_ThisDll.m_cLock.AddRef();
  199. }
  200. else
  201. {
  202. g_ThisDll.m_cLock.Release();
  203. }
  204. return NOERROR;
  205. }