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.

539 lines
13 KiB

  1. /*
  2. - CLSFACT.CPP
  3. -
  4. * Microsoft NetMeeting
  5. * Network Audio Control DLL
  6. * Generic class factory
  7. *
  8. * Revision History:
  9. *
  10. * When Who What
  11. * -------- ------------------ ---------------------------------------
  12. * 2.6.97 Yoram Yaacovi Copied from qosfact.cpp
  13. * Added handling of CInstallCodecs
  14. * 2.27.97 Yoram Yaacovi Added DllRegisterServer and DllUnregisterServer
  15. *
  16. * Functions:
  17. * DllGetClassObject
  18. * DllCanUnloadNow
  19. * DllRegisterServer
  20. * DllUnregisterServer
  21. * CClassFactory::QueryInterface
  22. * CClassFactory::AddRef
  23. * CClassFactory::Release
  24. * CClassFactory::CreateInstance
  25. * CClassFactory::LockServer
  26. * CreateClassFactory
  27. *
  28. *
  29. * Object types supported:
  30. * CQoS
  31. * CInstallCodecs
  32. *
  33. * Notes:
  34. * To add support for manufacturing objects of other types, change:
  35. * DllGetClassObject
  36. * DllCanUnloadNow
  37. * Add the CLSID and description to aObjectInfo
  38. *
  39. */
  40. #include <precomp.h>
  41. int g_cObjects = 0; // A general object count. Used for LockServer.
  42. EXTERN_C int g_cQoSObjects; // QoS object count. Public in qos\qos.cpp
  43. EXTERN_C int g_cICObjects; // CInstallCodecs object count. Public in inscodec.cpp
  44. EXTERN_C HINSTANCE g_hInst; // global module instance
  45. // Untested code for registering COM objects in the NAC
  46. // when enabled, DllRegisterServer and DllUnregisterServer should be exported
  47. // in nac.def
  48. #define GUID_STR_LEN 40
  49. typedef struct
  50. {
  51. const CLSID *pclsid;
  52. char szDescription[MAX_PATH];
  53. } OBJECT_INFO;
  54. static OBJECT_INFO aObjectInfo[]=
  55. {&CLSID_QoS, TEXT("Microsoft NetMeeting Quality of Service"),
  56. &CLSID_InstallCodecs, TEXT("Microsoft NetMeeting Installable Codecs"),
  57. NULL, TEXT("")};
  58. // Internal helper functions
  59. BOOL DeleteKeyAndSubKeys(HKEY hkIn, LPTSTR pszSubKey);
  60. BOOL UnregisterUnknownObject(const CLSID *prclsid);
  61. BOOL RegisterUnknownObject(LPCTSTR pszObjectName, const CLSID *prclsid);
  62. /***************************************************************************
  63. Name : DllGetClassObject
  64. Purpose : Standard COM entry point to create a COM object
  65. Parameters:
  66. Returns : HRESULT
  67. Comment :
  68. ***************************************************************************/
  69. STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, void **ppv)
  70. {
  71. HRESULT hr;
  72. CClassFactory *pObj;
  73. *ppv = 0;
  74. // find out object of what class we need to create and instantiate
  75. // the class factory with the correct create function
  76. if (CLSID_QoS == rclsid)
  77. {
  78. DBG_SAVE_FILE_LINE
  79. pObj = new CClassFactory(CreateQoS);
  80. }
  81. else if (CLSID_InstallCodecs == rclsid)
  82. {
  83. DBG_SAVE_FILE_LINE
  84. pObj = new CClassFactory(CreateInstallCodecs);
  85. }
  86. else
  87. {
  88. hr = CLASS_E_CLASSNOTAVAILABLE;
  89. goto out;
  90. }
  91. if (!pObj)
  92. {
  93. hr = E_OUTOFMEMORY;
  94. goto out;
  95. }
  96. hr = pObj->QueryInterface(riid, ppv);
  97. if (FAILED(hr))
  98. delete pObj;
  99. out:
  100. return hr;
  101. }
  102. /***************************************************************************
  103. Name : DllCanUnloadNow
  104. Purpose : Standard COM entry point tell a DLL it can unload
  105. Parameters:
  106. Returns : HRESULT
  107. Comment :
  108. ***************************************************************************/
  109. STDAPI DllCanUnloadNow ()
  110. {
  111. HRESULT hr=S_OK;
  112. int vcObjects = g_cObjects + g_cQoSObjects + g_cICObjects;
  113. return (vcObjects == 0 ? S_OK : S_FALSE);
  114. }
  115. /***************************************************************************
  116. Name : DllRegisterServer
  117. Purpose : Standard COM entry point to register a COM server
  118. Parameters:
  119. Returns : HRESULT
  120. Comment :
  121. ***************************************************************************/
  122. STDAPI DllRegisterServer(void)
  123. {
  124. ULONG i=0;
  125. HRESULT hr=NOERROR;
  126. while ((aObjectInfo[i].pclsid != NULL) &&
  127. (lstrlen(aObjectInfo[i].szDescription) != 0))
  128. {
  129. if (!RegisterUnknownObject(aObjectInfo[i].szDescription,
  130. aObjectInfo[i].pclsid))
  131. {
  132. hr = E_FAIL;
  133. goto out;
  134. }
  135. // next server to register
  136. i++;
  137. }
  138. out:
  139. return hr;
  140. }
  141. /***************************************************************************
  142. Name : DllUnregisterServer
  143. Purpose : Standard COM entry point to unregister a COM server
  144. Parameters:
  145. Returns : HRESULT
  146. Comment :
  147. ***************************************************************************/
  148. STDAPI DllUnregisterServer(void)
  149. {
  150. ULONG i=0;
  151. HRESULT hr=NOERROR;
  152. while ((aObjectInfo[i].pclsid != NULL) &&
  153. (lstrlen(aObjectInfo[i].szDescription) != 0))
  154. {
  155. if (!UnregisterUnknownObject(aObjectInfo[i].pclsid))
  156. {
  157. hr = E_FAIL;
  158. goto out;
  159. }
  160. // next server to register
  161. i++;
  162. }
  163. out:
  164. return hr;
  165. }
  166. /***************************************************************************
  167. ClassFactory: Generic implementation
  168. ***************************************************************************/
  169. CClassFactory::CClassFactory(PFNCREATE pfnCreate)
  170. {
  171. m_cRef=0;
  172. m_pfnCreate = pfnCreate;
  173. return;
  174. }
  175. CClassFactory::~CClassFactory(void)
  176. {
  177. return;
  178. }
  179. /***************************************************************************
  180. IUnknown Methods for CClassFactory
  181. ***************************************************************************/
  182. HRESULT CClassFactory::QueryInterface (REFIID riid, void **ppv)
  183. {
  184. HRESULT hr=NOERROR;
  185. #ifdef DEBUG
  186. // parameter validation
  187. if (IsBadReadPtr(&riid, (UINT) sizeof(IID)))
  188. {
  189. hr = ResultFromScode(E_INVALIDARG);
  190. goto out;
  191. }
  192. if (IsBadWritePtr(ppv, sizeof(LPVOID)))
  193. {
  194. hr = ResultFromScode(E_INVALIDARG);
  195. goto out;
  196. }
  197. #endif // DEBUG
  198. *ppv = 0;
  199. if (IID_IUnknown == riid ||
  200. IID_IClassFactory == riid)
  201. {
  202. *ppv = this;
  203. }
  204. else
  205. {
  206. hr = ResultFromScode(E_NOINTERFACE);
  207. goto out;
  208. }
  209. ((IUnknown *)*ppv)->AddRef();
  210. out:
  211. return hr;
  212. }
  213. ULONG CClassFactory::AddRef (void)
  214. {
  215. return ++m_cRef;
  216. }
  217. ULONG CClassFactory::Release (void)
  218. {
  219. // if the cRef is already 0 (shouldn't happen), assert, but let it through
  220. ASSERT(m_cRef);
  221. if (--m_cRef == 0)
  222. {
  223. delete this;
  224. return 0;
  225. }
  226. return m_cRef;
  227. }
  228. /***************************************************************************
  229. Name : CreateInstance
  230. Purpose : Standard COM class factory entry point which creates the
  231. object that this class factory knows to create
  232. Parameters:
  233. Returns : HRESULT
  234. Comment :
  235. ***************************************************************************/
  236. HRESULT CClassFactory::CreateInstance ( IUnknown *punkOuter,
  237. REFIID riid,
  238. void **ppv)
  239. {
  240. DEBUGMSG(ZONE_VERBOSE,("CClassFactory::CreateInstance\n"));
  241. return (m_pfnCreate)(punkOuter, riid, ppv);
  242. }
  243. /***************************************************************************
  244. Name : LockServer
  245. Purpose : Standard COM class factory entry point which will prevent
  246. the server from shutting down. Necessary when the caller
  247. keeps the class factory (through CoGetClassObject) instead
  248. of calling CoCreateInstance.
  249. Parameters:
  250. Returns : HRESULT
  251. Comment :
  252. ***************************************************************************/
  253. HRESULT CClassFactory::LockServer (BOOL flock)
  254. {
  255. if (flock)
  256. ++g_cObjects;
  257. else
  258. --g_cObjects;
  259. return NOERROR;
  260. }
  261. /***************************************************************************
  262. Helper functions
  263. ***************************************************************************/
  264. /***************************************************************************
  265. Name : StringFromGuid
  266. Purpose : Creates a string out of a GUID
  267. Parameters: riid - [in] clsid to make string out of.
  268. pszBuf - [in] buffer in which to place resultant GUID
  269. Returns : int - number of chars written out
  270. Comment :
  271. ***************************************************************************/
  272. int StringFromGuid(const CLSID *priid, LPTSTR pszBuf)
  273. {
  274. return wsprintf(pszBuf, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
  275. priid->Data1,
  276. priid->Data2, priid->Data3, priid->Data4[0], priid->Data4[1], priid->Data4[2],
  277. priid->Data4[3], priid->Data4[4], priid->Data4[5], priid->Data4[6], priid->Data4[7]);
  278. }
  279. /***************************************************************************
  280. Name : RegisterUnknownObject
  281. Purpose : Registers a simple CoCreatable object
  282. We add the following information to the registry:
  283. HKEY_CLASSES_ROOT\CLSID\<CLSID> = <ObjectName> Object
  284. HKEY_CLASSES_ROOT\CLSID\<CLSID>\InprocServer32 = <path to local server>
  285. HKEY_CLASSES_ROOT\CLSID\<CLSID>\InprocServer32 @ThreadingModel = Apartment
  286. Parameters: pszObjectName - [in] Object Name
  287. prclsid - [in] pointer to the CLSID of the object
  288. Returns : BOOL - FALSE means couldn't register it all
  289. Comment :
  290. ***************************************************************************/
  291. BOOL RegisterUnknownObject(LPCTSTR pszObjectName, const CLSID *prclsid)
  292. {
  293. HKEY hk = NULL, hkSub = NULL;
  294. TCHAR szGuidStr[GUID_STR_LEN];
  295. DWORD dwPathLen, dwDummy;
  296. TCHAR szScratch[MAX_PATH];
  297. BOOL bRet = FALSE;
  298. long l;
  299. // clean out any garbage
  300. UnregisterUnknownObject(prclsid);
  301. if (!StringFromGuid(prclsid, szGuidStr))
  302. goto out;
  303. // CLSID/<class-id>
  304. wsprintf(szScratch, TEXT("CLSID\\%s"), szGuidStr);
  305. l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0, TEXT(""), REG_OPTION_NON_VOLATILE,
  306. KEY_READ | KEY_WRITE, NULL, &hk, &dwDummy);
  307. if (l != ERROR_SUCCESS)
  308. goto out;
  309. // CLSID/<class-id>: class name
  310. wsprintf(szScratch, TEXT("%s Object"), pszObjectName);
  311. l = RegSetValueEx(hk, NULL, 0, REG_SZ, (BYTE *)szScratch,
  312. (lstrlen(szScratch) + 1)*sizeof(TCHAR));
  313. if (l != ERROR_SUCCESS)
  314. goto out;
  315. // CLSID/<class-id>/InprocServer32
  316. l = RegCreateKeyEx(hk, TEXT("InprocServer32"), 0, TEXT(""), REG_OPTION_NON_VOLATILE,
  317. KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy);
  318. if (l != ERROR_SUCCESS)
  319. goto out;
  320. // CLSID/<class-id>/InprocServer32:<file name>
  321. dwPathLen = GetModuleFileName(g_hInst, szScratch, sizeof(szScratch)/sizeof(TCHAR));
  322. if (!dwPathLen)
  323. goto out;
  324. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, (dwPathLen + 1)*sizeof(TCHAR));
  325. if (l != ERROR_SUCCESS)
  326. goto out;
  327. // CLSID/<class-id>/InprocServer32: ThreadingModel = Apartment
  328. l = RegSetValueEx(hkSub, TEXT("ThreadingModel"), 0, REG_SZ, (BYTE *)TEXT("Apartment"),
  329. sizeof(TEXT("Apartment")));
  330. if (l != ERROR_SUCCESS)
  331. goto out;
  332. bRet = TRUE;
  333. out:
  334. // clean the keys if we failed somewhere
  335. if (!bRet)
  336. UnregisterUnknownObject(prclsid);
  337. if (hk)
  338. RegCloseKey(hk);
  339. if (hkSub)
  340. RegCloseKey(hkSub);
  341. return bRet;
  342. }
  343. /***************************************************************************
  344. Name : UnregisterUnknownObject
  345. Purpose : cleans up all the stuff that RegisterUnknownObject puts in the
  346. registry.
  347. Parameters: prclsid - [in] pointer to the CLSID of the object
  348. Returns : BOOL - FALSE means couldn't register it all
  349. Comment :
  350. ***************************************************************************/
  351. BOOL UnregisterUnknownObject(const CLSID *prclsid)
  352. {
  353. TCHAR szScratch[MAX_PATH];
  354. HKEY hk=NULL;
  355. BOOL f;
  356. long l;
  357. BOOL bRet = FALSE;
  358. // delete everybody of the form
  359. // HKEY_CLASSES_ROOT\CLSID\<CLSID> [\] *
  360. //
  361. if (!StringFromGuid(prclsid, szScratch))
  362. goto out;
  363. l = RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_ALL_ACCESS, &hk);
  364. if (l != ERROR_SUCCESS)
  365. goto out;
  366. // Delete the object key and subkeys
  367. bRet = DeleteKeyAndSubKeys(hk, szScratch);
  368. out:
  369. if (hk)
  370. RegCloseKey(hk);
  371. return bRet;
  372. }
  373. /***************************************************************************
  374. Name : DeleteKeyAndSubKeys
  375. Purpose : delete's a key and all of it's subkeys.
  376. Parameters: hkIn - [in] delete the descendant specified
  377. pszSubKey - [in] i'm the descendant specified
  378. Returns : BOOL - TRUE = OK
  379. Comment : Despite the win32 docs claiming it does, RegDeleteKey doesn't seem to
  380. work with sub-keys under windows 95.
  381. This function is recursive.
  382. ***************************************************************************/
  383. BOOL DeleteKeyAndSubKeys(HKEY hkIn, LPTSTR pszSubKey)
  384. {
  385. HKEY hk;
  386. TCHAR szTmp[MAX_PATH];
  387. DWORD dwTmpSize;
  388. long l;
  389. BOOL f;
  390. int x;
  391. l = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hk);
  392. if (l != ERROR_SUCCESS) return FALSE;
  393. // loop through all subkeys, blowing them away.
  394. //
  395. f = TRUE;
  396. x = 0;
  397. while (f) {
  398. dwTmpSize = MAX_PATH;
  399. l = RegEnumKeyEx(hk, x, szTmp, &dwTmpSize, 0, NULL, NULL, NULL);
  400. if (l != ERROR_SUCCESS) break;
  401. f = DeleteKeyAndSubKeys(hk, szTmp);
  402. x++;
  403. }
  404. // there are no subkeys left, [or we'll just generate an error and return FALSE].
  405. // let's go blow this dude away.
  406. //
  407. RegCloseKey(hk);
  408. l = RegDeleteKey(hkIn, pszSubKey);
  409. return (l == ERROR_SUCCESS) ? TRUE : FALSE;
  410. }