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.

456 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. com.c
  5. Abstract:
  6. Implements the required code for a COM server. This module is specific to
  7. the COM interfaces exposed by osuninst.dll
  8. Author:
  9. Jim Schmidt (jimschm) 21-Feb-2001
  10. Revision History:
  11. <alias> <date> <comments>
  12. --*/
  13. #include "pch.h"
  14. #include "compguid.h"
  15. #include "com.h"
  16. #include "undop.h"
  17. //
  18. // Globals
  19. //
  20. INT g_DllObjects;
  21. INT g_DllLocks;
  22. //
  23. // Implementation
  24. //
  25. STDAPI
  26. DllGetClassObject (
  27. IN REFCLSID ClassId,
  28. IN REFIID InterfaceIdRef,
  29. OUT PVOID *InterfacePtr
  30. )
  31. /*++
  32. Routine Description:
  33. DllGetClassObject is the DLL-to-COM connection. It is exported from the DLL,
  34. so that COM can call it with CoGetClassObject. COM is the only one who calls
  35. this entry point, and finds the dll through registration of the CLSID in
  36. HKCR.
  37. Arguments:
  38. ClassId - Specifies the class factory desired. This arg allows a single DLL
  39. to implement multiple interfaces.
  40. InterfaceIdRef - Specifies the interface the caller wants on the class
  41. object, usually IID_ClassFactory.
  42. InterfacePtr - Receives the interface pointer, or NULL if an error occurs.
  43. Return Value:
  44. E_INVALIDARG - The caller specified an invalid argument
  45. E_OUTOFMEMORY - Failed to alloc memory for interface
  46. E_UNEXPECTED - Some random problem
  47. S_OK - Success
  48. CLASS_E_CLASSNOTAVAILABLE - Requested class is not supported
  49. --*/
  50. {
  51. BOOL result = FALSE;
  52. HRESULT hr = S_OK;
  53. PUNINSTALLCLASSFACTORY uninstallClassFactory = NULL;
  54. __try {
  55. DeferredInit();
  56. //
  57. // Initialize out arg
  58. //
  59. __try {
  60. *InterfacePtr = NULL;
  61. }
  62. __except(1) {
  63. hr = E_INVALIDARG;
  64. }
  65. if (hr != S_OK) {
  66. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Invalid InterfacePtr arg"));
  67. __leave;
  68. }
  69. //
  70. // Is this a request for a disk cleanup class? If not, fail with
  71. // CLASS_E_CLASSNOTAVAILABLE.
  72. //
  73. if (!IsEqualCLSID (ClassId, CLSID_UninstallCleaner)) {
  74. DEBUGMSG ((DBG_ERROR, "Uninstall: Requested class not supported"));
  75. hr = CLASS_E_CLASSNOTAVAILABLE;
  76. __leave;
  77. }
  78. //
  79. // Return our IClassFactory for making CCompShellExt objects
  80. //
  81. uninstallClassFactory = new CUninstallClassFactory ();
  82. if (!uninstallClassFactory) {
  83. hr = E_OUTOFMEMORY;
  84. __leave;
  85. }
  86. //
  87. // Test if our class factory support the requested interface
  88. //
  89. hr = uninstallClassFactory->QueryInterface (InterfaceIdRef, InterfacePtr);
  90. }
  91. __finally {
  92. if (FAILED (hr) && uninstallClassFactory) {
  93. //
  94. // failure -- clean up object
  95. //
  96. delete uninstallClassFactory;
  97. }
  98. }
  99. return hr;
  100. }
  101. STDAPI
  102. DllCanUnloadNow (
  103. VOID
  104. )
  105. /*++
  106. Routine Description:
  107. Indicatates if this DLL is in use or not. If it is not in use, COM will
  108. unload it.
  109. Arguments:
  110. None.
  111. Return Value:
  112. S_OK - The DLL is not in use
  113. S_FALSE - The DLL is used at least once
  114. --*/
  115. {
  116. if (g_DllObjects || g_DllLocks) {
  117. return S_FALSE;
  118. }
  119. return S_OK;
  120. }
  121. /*++
  122. Routine Descriptions:
  123. This constructor is a generic class factory that supports multiple object
  124. types. Upon creation, the object interface pointer ref count is set to zero,
  125. and the global number of objects for the dll is incremented.
  126. The destructor simply decrements the DLL object count.
  127. Arguments:
  128. None.
  129. Return Value:
  130. None.
  131. --*/
  132. CUninstallClassFactory::CUninstallClassFactory (
  133. VOID
  134. )
  135. {
  136. //
  137. // -Initialize the interface pointer count
  138. // -Increment the DLL's global count of objects
  139. //
  140. _References = 0;
  141. g_DllObjects++;
  142. }
  143. CUninstallClassFactory::~CUninstallClassFactory (
  144. VOID
  145. )
  146. {
  147. g_DllObjects--;
  148. }
  149. STDMETHODIMP
  150. CUninstallClassFactory::QueryInterface (
  151. IN REFIID InterfaceIdRef,
  152. OUT PVOID *InterfacePtr
  153. )
  154. {
  155. HRESULT hr = S_OK;
  156. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Entering"));
  157. __try {
  158. //
  159. // Initialize out arg
  160. //
  161. __try {
  162. *InterfacePtr = NULL;
  163. }
  164. __except(1) {
  165. hr = E_INVALIDARG;
  166. }
  167. if (hr != S_OK) {
  168. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Invalid InterfacePtr arg"));
  169. __leave;
  170. }
  171. //
  172. // Test for the supported interface
  173. //
  174. if (IsEqualIID (InterfaceIdRef, IID_IUnknown)) {
  175. DEBUGMSG ((DBG_VERBOSE, "Caller requested IUnknown"));
  176. *InterfacePtr = (LPUNKNOWN)(LPCLASSFACTORY) this;
  177. AddRef();
  178. __leave;
  179. }
  180. if (IsEqualIID (InterfaceIdRef, IID_IClassFactory)) {
  181. DEBUGMSG ((DBG_VERBOSE, "Caller requested IClassFactory"));
  182. *InterfacePtr = (LPCLASSFACTORY)this;
  183. AddRef();
  184. __leave;
  185. }
  186. DEBUGMSG ((DBG_WARNING, "Caller requested unknown interface"));
  187. hr = E_NOINTERFACE;
  188. }
  189. __finally {
  190. }
  191. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Leaving"));
  192. return hr;
  193. }
  194. /*++
  195. Routine Description:
  196. AddRef is the standard IUnknown member function that increments the object
  197. reference count.
  198. Release is the standard IUnknown member function that decrements the object
  199. reference count.
  200. Arguments:
  201. None.
  202. Return Value:
  203. The number of interface references.
  204. --*/
  205. STDMETHODIMP_(ULONG)
  206. CUninstallClassFactory::AddRef (
  207. VOID
  208. )
  209. {
  210. return ++_References;
  211. }
  212. STDMETHODIMP_(ULONG)
  213. CUninstallClassFactory::Release (
  214. VOID
  215. )
  216. {
  217. if (!_References) {
  218. DEBUGMSG ((DBG_ERROR, "Can't release because there are no references"));
  219. } else {
  220. _References--;
  221. if (!_References) {
  222. delete this;
  223. return 0;
  224. }
  225. }
  226. return _References;
  227. }
  228. STDMETHODIMP
  229. CUninstallClassFactory::CreateInstance (
  230. IN LPUNKNOWN IUnknownOuterInterfacePtr,
  231. IN REFIID InterfaceIdRef,
  232. OUT PVOID * InterfacePtr
  233. )
  234. /*++
  235. Routine Description:
  236. CreateInstance establishes an object.
  237. Arguments:
  238. IUnknownOuterInterfacePtr - Specifies the IUnknown interface that
  239. is the outer layer in objects derrived from us. This happens only when
  240. additional objects inherit out interfaces.
  241. InterfaceIdRef - Specifies the interface that the caller wants to
  242. instantiate
  243. InterfacePtr - Receives the pointer to the interface, or NULL on an error
  244. Return Value:
  245. S_OK - The object was created and its reference is returned in InterfacePtr
  246. E_OUTOFMEMORY - Not enough memory available to instantiate the object
  247. E_INVALIDARG - The caller specified an invalid InterfacePtr arg
  248. E_UNEXPECTED - Some random error condition was encountered
  249. E_NOINTERFACE - InterfaceIdRef is not supported
  250. --*/
  251. {
  252. HRESULT hr = S_OK;
  253. PUNINSTALLDISKCLEANER uninstallDiskCleaner = NULL;
  254. __try {
  255. //
  256. // Initialize out arg
  257. //
  258. __try {
  259. *InterfacePtr = NULL;
  260. }
  261. __except(1) {
  262. hr = E_INVALIDARG;
  263. }
  264. if (hr != S_OK) {
  265. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Invalid InterfacePtr arg"));
  266. __leave;
  267. }
  268. //
  269. // Shell extensions typically don't support aggregation (inheritance)
  270. //
  271. if (IUnknownOuterInterfacePtr) {
  272. hr = CLASS_E_NOAGGREGATION;
  273. __leave;
  274. }
  275. //
  276. // Create the disk cleaner object
  277. //
  278. if (IsEqualIID (InterfaceIdRef, IID_IEmptyVolumeCache)) {
  279. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Creating CUninstallDiskCleaner"));
  280. uninstallDiskCleaner = new CUninstallDiskCleaner();
  281. if (!uninstallDiskCleaner) {
  282. hr = E_OUTOFMEMORY;
  283. __leave;
  284. }
  285. hr = uninstallDiskCleaner->QueryInterface (InterfaceIdRef, InterfacePtr);
  286. __leave;
  287. }
  288. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Unknown InterfaceIdRef"));
  289. hr = E_NOINTERFACE;
  290. }
  291. __finally {
  292. if (FAILED(hr)) {
  293. if (uninstallDiskCleaner) {
  294. delete uninstallDiskCleaner;
  295. }
  296. }
  297. }
  298. return hr;
  299. }
  300. STDMETHODIMP
  301. CUninstallClassFactory::LockServer (
  302. IN BOOL Lock
  303. )
  304. /*++
  305. Routine Description:
  306. LockServer is the standard IUnknown interface that is used to keep a server
  307. in memory. Its implementation tracks the lock count in a global.
  308. Arguments:
  309. Lock - Specifies TRUE to increment the loc count, or FALSE to decrement it.
  310. Return Value:
  311. S_OK - Server was locked (or unlocked)
  312. E_FAIL - No locks exist/can't unlock
  313. --*/
  314. {
  315. HRESULT hr = S_OK;
  316. if (Lock) {
  317. g_DllLocks++;
  318. } else {
  319. if (g_DllLocks) {
  320. g_DllLocks--;
  321. } else {
  322. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Attempt to unlock when no locks exist"));
  323. hr = E_FAIL;
  324. }
  325. }
  326. return hr;
  327. }