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.

680 lines
21 KiB

  1. // COMDLL.CPP -- Component Object Model plumbing for this DLL.
  2. #include "stdafx.h"
  3. /*
  4. This module implements the lowest level of COM interface. It defines
  5. DllMain, DllRegisterServer, DllUnregisterServer, DllCanUnloadNow, and
  6. DllGetClassObject.
  7. DllMain initials the DLL and creates the CServerState object which
  8. is used to keep counts for the active objects and locks.
  9. DllRegisterServer adjusts the system registry to insert a mapping from
  10. our Class ID to the DLL's path and file name.
  11. DllUnregisterServer removes that mapping from the registry.
  12. DllCanUnloadNow tells the OLE environment whether this DLL can safely
  13. be unloaded.
  14. DllGetClassObject returns the Class Factory for the MVStorage class.
  15. */
  16. UINT cInterfaces_CStorageMoniker ; // = 0; // Not necessary in Win32
  17. UINT cInterfaces_CPathManager ; // = 0; // Not necessary in Win32
  18. UINT cInterfaces_CIOITnetProtocol; // = 0; // Not necessary in Win32
  19. UINT cInterfaces_CStorage ; // = 0; // Not necessary in Win32
  20. UINT cInterfaces_CStream ; // = 0; // Not necessary in Win32
  21. UINT cInterfaces_CFreeList ; // = 0; // Not necessary in Win32
  22. UINT cInterfaces_CITStorage ;
  23. GUID aIID_CStorageMoniker[3];
  24. GUID aIID_CPathManager[2];
  25. GUID aIID_CIOITnetProtocol[3];
  26. GUID aIID_CStorage[2];
  27. GUID aIID_CStream[3];
  28. GUID aIID_CFreeList[4];
  29. GUID aIID_CITStorage[2];
  30. void Init_IID_Arrays()
  31. {
  32. aIID_CStorageMoniker[cInterfaces_CStorageMoniker++] = IID_IMoniker;
  33. aIID_CStorageMoniker[cInterfaces_CStorageMoniker++] = IID_IPersist;
  34. aIID_CStorageMoniker[cInterfaces_CStorageMoniker++] = IID_IPersistStream;
  35. RonM_ASSERT(sizeof(aIID_CStorageMoniker) / sizeof(GUID) == cInterfaces_CStorageMoniker);
  36. aIID_CPathManager[cInterfaces_CPathManager++] = IID_IPersist;
  37. aIID_CPathManager[cInterfaces_CPathManager++] = IID_PathManager;
  38. RonM_ASSERT(sizeof(aIID_CPathManager) / sizeof(GUID) == cInterfaces_CPathManager);
  39. aIID_CIOITnetProtocol[cInterfaces_CIOITnetProtocol++] = IID_IOInetProtocolRoot;
  40. aIID_CIOITnetProtocol[cInterfaces_CIOITnetProtocol++] = IID_IOInetProtocol;
  41. aIID_CIOITnetProtocol[cInterfaces_CIOITnetProtocol++] = IID_IOInetProtocolInfo;
  42. RonM_ASSERT(sizeof(aIID_CIOITnetProtocol) / sizeof(GUID) == cInterfaces_CIOITnetProtocol);
  43. aIID_CStorage[cInterfaces_CStorage++] = IID_IStorageITEx;
  44. aIID_CStorage[cInterfaces_CStorage++] = IID_IStorage;
  45. RonM_ASSERT(sizeof(aIID_CStorage) / sizeof(GUID) == cInterfaces_CStorage);
  46. aIID_CStream[cInterfaces_CStream++] = IID_ISequentialStream;
  47. aIID_CStream[cInterfaces_CStream++] = IID_IStream;
  48. aIID_CStream[cInterfaces_CStream++] = IID_IStreamITEx;
  49. RonM_ASSERT(sizeof(aIID_CStream) / sizeof(GUID) == cInterfaces_CStream);
  50. aIID_CFreeList[cInterfaces_CFreeList++] = IID_IFreeListManager;
  51. aIID_CFreeList[cInterfaces_CFreeList++] = IID_IPersistStreamInit;
  52. aIID_CFreeList[cInterfaces_CFreeList++] = IID_IPersistStream;
  53. aIID_CFreeList[cInterfaces_CFreeList++] = IID_IPersist;
  54. RonM_ASSERT(sizeof(aIID_CFreeList) / sizeof(GUID) == cInterfaces_CFreeList);
  55. aIID_CITStorage[cInterfaces_CITStorage++] = IID_ITStorage;
  56. aIID_CITStorage[cInterfaces_CITStorage++] = IID_ITStorageEx;
  57. RonM_ASSERT(sizeof(aIID_CITStorage) / sizeof(GUID) == cInterfaces_CITStorage);
  58. }
  59. CImpITUnknown *g_pImpITFileSystemList ; // = NULL; // Not necessary in Win32
  60. CImpITUnknown *g_pFSLockBytesFirstActive ; // = NULL; // Not necessary in Win32
  61. CImpITUnknown *g_pStrmLockBytesFirstActive; // = NULL; // Not necessary in Win32
  62. CImpITUnknown *g_pImpIFSStorageList ; // = NULL; // Not necessary in Win32
  63. CITCriticalSection g_csITFS;
  64. CServerState *pDLLServerState; // = NULL; // Not necessary in Win32
  65. UINT iSystemType = Unknown_System;
  66. static int g_cProcessAttatches;
  67. UINT cp_Default; // Defaults to NULL in Win32.
  68. BOOL g_fDBCSSystem;
  69. void InitLocaleInfo()
  70. {
  71. g_fDBCSSystem = (BOOL) GetSystemMetrics(SM_DBCSENABLED);
  72. char szCP[20];
  73. LCID lcid = GetUserDefaultLCID();
  74. GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, szCP, sizeof(szCP));
  75. char *pch;
  76. for (cp_Default = 0, pch = szCP; ;)
  77. {
  78. char ch = *pch++;
  79. if (!ch) break;
  80. RonM_ASSERT(ch >= '0' && ch <= '9');
  81. cp_Default = (cp_Default * 10) + (ch - '0');
  82. }
  83. }
  84. HMODULE hmodUrlMon = NULL;
  85. PFindMimeFromData pFindMimeFromData = NULL;
  86. void SetUpIE4APIs()
  87. {
  88. hmodUrlMon = LoadLibrary("UrlMon.dll");
  89. if (hmodUrlMon)
  90. pFindMimeFromData = (PFindMimeFromData) GetProcAddress(hmodUrlMon, "FindMimeFromData");
  91. }
  92. extern "C" BOOL WINAPI DllMain(HMODULE hModule, ULONG ul_reason_for_call, LPVOID lpReserved)
  93. {
  94. switch(ul_reason_for_call)
  95. {
  96. case DLL_PROCESS_ATTACH:
  97. g_cProcessAttatches++;
  98. if (!pDLLServerState) // We can get several attach calls for the same process.
  99. // One for each LoadLibrary call.
  100. {
  101. Init_IID_Arrays();
  102. InitLocaleInfo();
  103. SetUpIE4APIs();
  104. pDLLServerState = CServerState::CreateServerState(hModule);
  105. iSystemType = (GetVersion() >> 30) & 3;
  106. pBufferForCompressedData = New CBuffer;
  107. RonM_ASSERT(pBufferForCompressedData);
  108. }
  109. #ifdef _DEBUG
  110. CITUnknown::OpenReferee(); // Set up concurrency control
  111. #endif // _DEBUG
  112. if (!pDLLServerState) return FALSE;
  113. return TRUE;
  114. case DLL_THREAD_ATTACH: // BugBug: Need to mark the DLL so that the
  115. // thread attach/detach calls aren't made.
  116. return TRUE;
  117. case DLL_THREAD_DETACH:
  118. return TRUE;
  119. case DLL_PROCESS_DETACH:
  120. RonM_ASSERT(g_cProcessAttatches > 0);
  121. if (--g_cProcessAttatches > 0)
  122. return TRUE;
  123. #ifdef _DEBUG
  124. CITUnknown::CloseReferee(); // Delete concurrency resources
  125. #endif // _DEBUG
  126. if (pDLLServerState)
  127. {
  128. CITUnknown::CloseActiveObjects();
  129. delete pDLLServerState;
  130. pDLLServerState = NULL;
  131. }
  132. #ifdef _DEBUG
  133. DumpLZXCounts();
  134. #endif // _DEBUG
  135. if (pBufferForCompressedData) delete pBufferForCompressedData;
  136. LiberateHeap();
  137. if (hmodUrlMon)
  138. FreeLibrary(hmodUrlMon);
  139. return TRUE;
  140. default:
  141. return FALSE;
  142. }
  143. }
  144. LONG SetRegClassKeyValue(LPSTR pszKey, LPSTR pszSubkey, LPSTR pszValueName, LPSTR pszValue)
  145. {
  146. // This routine creates a registry key and sets its value.
  147. // The key is created relative to HKEY_CLASSES_ROOT. The name
  148. // of the new key is constructed by combining the names denoted
  149. // by pszKey and pszSubkey. The pszSubkey parameter can be null.
  150. // If pszValue is non-null, the value which it denotes will
  151. // bound to the key
  152. LONG ec;
  153. HKEY hKey;
  154. RonM_ASSERT(pszKey != NULL);
  155. // The lines below allocate a stack buffer large enough to construct
  156. // the complete key string. It is automatically discarded at function exit
  157. // time.
  158. UINT cbKey = lstrlenA(pszKey) + (pszSubkey? lstrlenA(pszSubkey) + 1 : 0);
  159. RonM_ASSERT(cbKey < 0x1000); // To catch outlandishly big strings.
  160. PCHAR pacKeyBuffer = PCHAR(_alloca(cbKey + 1));
  161. lstrcpyA(pacKeyBuffer, pszKey);
  162. if (pszSubkey)
  163. {
  164. lstrcatA(pacKeyBuffer, "\\");
  165. lstrcatA(pacKeyBuffer, pszSubkey);
  166. }
  167. ec = RegCreateKeyEx(HKEY_CLASSES_ROOT, pacKeyBuffer, 0, NULL,
  168. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  169. &hKey, NULL
  170. );
  171. if (ec != ERROR_SUCCESS) return ec;
  172. if (pszValue)
  173. ec = RegSetValueEx(hKey, (const char *) pszValueName, 0, REG_SZ,
  174. PBYTE(pszValue), lstrlenA(pszValue)+1
  175. );
  176. RegCloseKey(hKey);
  177. return ec;
  178. }
  179. const UINT CBMAX_SUBKEY = 128;
  180. BOOL DeleteKey(HKEY hkey, LPSTR pszSubkey)
  181. {
  182. // This routine deletes a key heirarchy from the registry. The base of the
  183. // heirarchy is a key denoted by pszSubkey relative to the key denoted by
  184. // hkey. Since the NT registry implementation does not allow a key to be
  185. // deleted when it has subkeys, this routine will look for subkeys and
  186. // recursively delete them before attempting to delete the key at the
  187. // base of the heirarchy.
  188. LONG ec;
  189. HKEY hkeyBase;
  190. ec= RegOpenKeyEx(hkey, pszSubkey, 0, KEY_ALL_ACCESS, &hkeyBase);
  191. if (ec != ERROR_SUCCESS) return FALSE;
  192. char szSubkey[CBMAX_SUBKEY + 1];
  193. for (; ; )
  194. {
  195. DWORD cbSubkey= CBMAX_SUBKEY + 1;
  196. ec= RegEnumKeyEx(hkeyBase, 0, szSubkey, &cbSubkey, NULL, NULL, NULL, NULL);
  197. if (ec != ERROR_SUCCESS)
  198. {
  199. if (ec == ERROR_NO_MORE_ITEMS) break;
  200. RonM_ASSERT(FALSE);
  201. RegCloseKey(hkeyBase);
  202. return FALSE;
  203. }
  204. if (!DeleteKey(hkeyBase, szSubkey))
  205. {
  206. RegCloseKey(hkeyBase);
  207. return FALSE;
  208. }
  209. }
  210. RegCloseKey(hkeyBase);
  211. ec= RegDeleteKey(hkey, pszSubkey);
  212. return (ec == ERROR_SUCCESS);
  213. }
  214. LONG RegisterClass(CHAR *szClassKey, CHAR *szTitle, CHAR *szModulePath,
  215. CHAR *szVersion, CHAR *szClass, BOOL fForceApartment
  216. )
  217. {
  218. LONG ec;
  219. ec= SetRegClassKeyValue(szClassKey, NULL, NULL, szTitle);
  220. if (ec != ERROR_SUCCESS) return ec;
  221. ec= SetRegClassKeyValue(szClassKey, "ProgID", NULL, CURRENT_VERSION);
  222. if (ec != ERROR_SUCCESS) return ec;
  223. ec= SetRegClassKeyValue(szClassKey, "VersionIndependentProgID", NULL, CLASS_NAME);
  224. if (ec != ERROR_SUCCESS) return ec;
  225. ec= SetRegClassKeyValue(szClassKey, "NotInsertable", NULL, NULL);
  226. if (ec != ERROR_SUCCESS) return ec;
  227. ec= SetRegClassKeyValue(szClassKey, "InprocServer32", NULL, szModulePath);
  228. if (ec != ERROR_SUCCESS) return ec;
  229. ec= SetRegClassKeyValue(szClassKey, "InprocServer32", "ThreadingModel", "Both");
  230. if (ec != ERROR_SUCCESS) return ec;
  231. return ERROR_SUCCESS;
  232. }
  233. const UINT GUID_SIZE = 38;
  234. void CopyClassGuidString(REFGUID rguid, CHAR *pchBuff)
  235. {
  236. WCHAR wszCLSID[GUID_SIZE + 1];
  237. INT cchResult=
  238. StringFromGUID2(rguid, wszCLSID, GUID_SIZE + 1);
  239. RonM_ASSERT(cchResult && cchResult == GUID_SIZE + 1);
  240. #ifdef _DEBUG
  241. cchResult=
  242. #endif // _DEBUG
  243. WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, wszCLSID, cchResult,
  244. pchBuff, GUID_SIZE + 1, NULL, NULL
  245. );
  246. RonM_ASSERT(cchResult && cchResult == GUID_SIZE + 1);
  247. }
  248. extern "C" STDAPI DllRegisterServer(void)
  249. {
  250. LONG ec;
  251. HKEY hKey = NULL;
  252. // First we turn on the MK protocol by installing the variable "MkEnabled"
  253. // in the registry options for Internet Explorer.
  254. ec = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Internet Explorer", 0, NULL,
  255. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  256. &hKey, NULL
  257. );
  258. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  259. ec = RegSetValueEx(hKey, (const char *)"MkEnabled", 0, REG_SZ,
  260. (const unsigned char *)"Yes", 4
  261. );
  262. RegCloseKey(hKey); hKey = NULL;
  263. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  264. CHAR *pszPrefix = "CLSID";
  265. const UINT cbPrefix = 5;
  266. RonM_ASSERT(cbPrefix == lstrlenA(pszPrefix));
  267. CHAR szModulePath[MAX_PATH + 2];
  268. GetModuleFileName(pDLLServerState->ModuleInstance(), szModulePath, MAX_PATH);
  269. /* Note: We're going to use the szKeyCLSID buffer to hold two overlapping
  270. strings. One is an embedded class id string. The other is a key
  271. string of the form CLSID/{ class-id string }.
  272. */
  273. CHAR szKeyCLSID[GUID_SIZE + cbPrefix + 2];
  274. lstrcpyA(szKeyCLSID, pszPrefix);
  275. szKeyCLSID[cbPrefix] = '\\';
  276. PCHAR pszCLSID = szKeyCLSID + cbPrefix + 1;
  277. CopyClassGuidString(CLSID_ITStorage, pszCLSID);
  278. ec= SetRegClassKeyValue(CLASS_NAME, NULL, NULL, "Microsoft InfoTech IStorage System");
  279. ec= SetRegClassKeyValue(CLASS_NAME, "CurVer", NULL, CURRENT_VERSION);
  280. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  281. ec= SetRegClassKeyValue(CLASS_NAME, pszPrefix, NULL, pszCLSID);
  282. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  283. ec = RegisterClass(szKeyCLSID, "Microsoft InfoTech IStorage System",
  284. szModulePath, CURRENT_VERSION, CLASS_NAME, FALSE
  285. );
  286. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  287. CopyClassGuidString(CLSID_IFSStorage, pszCLSID);
  288. ec= SetRegClassKeyValue(CLASS_NAME_FS, NULL, NULL,
  289. "Microsoft InfoTech IStorage for Win32 Files"
  290. );
  291. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  292. ec= SetRegClassKeyValue(CLASS_NAME_FS, "CurVer", NULL, CURRENT_VERSION_FS);
  293. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  294. ec= SetRegClassKeyValue(CLASS_NAME_FS, pszPrefix, NULL, pszCLSID);
  295. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  296. ec = RegisterClass(szKeyCLSID, "Microsoft InfoTech IStorage for Win32 Files",
  297. szModulePath, CURRENT_VERSION_FS, CLASS_NAME_FS, FALSE
  298. );
  299. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  300. CopyClassGuidString(CLSID_PARSE_URL, pszCLSID);
  301. ec= SetRegClassKeyValue(CLASS_NAME_MK, NULL, NULL,
  302. "Microsoft InfoTech Protocol for IE 3.0"
  303. );
  304. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  305. ec= SetRegClassKeyValue(CLASS_NAME_MK, "CurVer", NULL, CURRENT_VERSION_MK);
  306. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  307. ec= SetRegClassKeyValue(CLASS_NAME_MK, pszPrefix, NULL, pszCLSID);
  308. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  309. ec = RegisterClass(szKeyCLSID, "Microsoft InfoTech Protocol for IE 3.0",
  310. szModulePath, CURRENT_VERSION_MK, CLASS_NAME_MK, TRUE
  311. );
  312. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  313. CopyClassGuidString(CLSID_IE4_PROTOCOLS, pszCLSID);
  314. ec= SetRegClassKeyValue(CLASS_NAME_ITS, NULL, NULL,
  315. "Microsoft InfoTech Protocols for IE 4.0"
  316. );
  317. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  318. ec= SetRegClassKeyValue(CLASS_NAME_ITS, "CurVer", NULL, CURRENT_VERSION_ITS);
  319. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  320. ec= SetRegClassKeyValue(CLASS_NAME_ITS, pszPrefix, NULL, pszCLSID);
  321. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  322. ec = RegisterClass(szKeyCLSID, "Microsoft InfoTech Protocols for IE 4.0",
  323. szModulePath, CURRENT_VERSION_ITS, CLASS_NAME_ITS, TRUE
  324. );
  325. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  326. ec= SetRegClassKeyValue("PROTOCOLS\\Name-Space Handler\\mk", NULL, NULL,
  327. "NameSpace Filter for MK:@MSITStore:..."
  328. );
  329. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  330. ec= SetRegClassKeyValue("PROTOCOLS\\Handler\\its",
  331. NULL, NULL, "its: Asychronous Pluggable Protocol Handler"
  332. );
  333. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  334. ec= SetRegClassKeyValue("PROTOCOLS\\Handler\\its",
  335. NULL, "CLSID", pszCLSID
  336. );
  337. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  338. ec= SetRegClassKeyValue("PROTOCOLS\\Handler\\ms-its",
  339. NULL, NULL, "ms-its: Asychronous Pluggable Protocol Handler"
  340. );
  341. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  342. ec= SetRegClassKeyValue("PROTOCOLS\\Handler\\ms-its",
  343. NULL, "CLSID", pszCLSID
  344. );
  345. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  346. ec= SetRegClassKeyValue("PROTOCOLS\\Name-Space Handler\\mk\\*",
  347. NULL, "CLSID", pszCLSID
  348. );
  349. if (ec != ERROR_SUCCESS) return SELFREG_E_CLASS;
  350. {
  351. HKEY hkeyIEPATH = NULL;
  352. DWORD dwType;
  353. PCHAR pchData = NULL;
  354. DWORD cchData = 0;
  355. PSZ pszSuffix = IS_IE4()? " ms-its:%1::/" : " mk:@MSITStore:%1::/";
  356. DWORD cbSuffix = lstrlen(pszSuffix);
  357. if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT,
  358. "htmlfile\\shell\\open\\command",
  359. 0, KEY_QUERY_VALUE, &hkeyIEPATH
  360. )
  361. && ERROR_SUCCESS == RegQueryValueEx(hkeyIEPATH, "", NULL, &dwType, NULL, &cchData)
  362. && (pchData = PCHAR(_alloca(cchData += cbSuffix+1)))
  363. && ERROR_SUCCESS == RegQueryValueEx(hkeyIEPATH, "", NULL, &dwType,
  364. PBYTE(pchData), &cchData
  365. )
  366. )
  367. {
  368. RegCloseKey(hkeyIEPATH);
  369. lstrcat(pchData, pszSuffix);
  370. lstrcat(szModulePath, ",0");
  371. if ( ERROR_SUCCESS == SetRegClassKeyValue("ITS FILE", NULL, NULL,
  372. "Internet Document Set"
  373. )
  374. && ERROR_SUCCESS == SetRegClassKeyValue("ITS File\\shell\\open\\command",
  375. NULL, NULL, pchData
  376. )
  377. && ERROR_SUCCESS == SetRegClassKeyValue("ITS FILE\\DefaultIcon", NULL,
  378. NULL, szModulePath
  379. )
  380. && ERROR_SUCCESS == SetRegClassKeyValue(".its", NULL, NULL, "ITS File")
  381. ) return S_OK;
  382. }
  383. }
  384. return S_OK;
  385. }
  386. extern "C" STDAPI DllUnregisterServer(void)
  387. {
  388. {
  389. DeleteKey(HKEY_CLASSES_ROOT, ".its");
  390. DeleteKey(HKEY_CLASSES_ROOT, "ITS File");
  391. }
  392. CHAR *pszPrefix = "CLSID";
  393. const UINT cbPrefix = 5;
  394. RonM_ASSERT(cbPrefix == lstrlenA(pszPrefix));
  395. CHAR szKeyCLSID[GUID_SIZE + cbPrefix + 2];
  396. lstrcpyA(szKeyCLSID, pszPrefix);
  397. szKeyCLSID[5] = '\\';
  398. PCHAR pszCLSID = szKeyCLSID + cbPrefix + 1;
  399. CopyClassGuidString(CLSID_ITStorage, pszCLSID);
  400. if (!DeleteKey(HKEY_CLASSES_ROOT, CLASS_NAME)) return SELFREG_E_CLASS;
  401. if (!DeleteKey(HKEY_CLASSES_ROOT, szKeyCLSID)) return SELFREG_E_CLASS;
  402. CopyClassGuidString(CLSID_IFSStorage, pszCLSID);
  403. if (!DeleteKey(HKEY_CLASSES_ROOT, CLASS_NAME_FS)) return SELFREG_E_CLASS;
  404. if (!DeleteKey(HKEY_CLASSES_ROOT, szKeyCLSID)) return SELFREG_E_CLASS;
  405. CopyClassGuidString(CLSID_PARSE_URL, pszCLSID);
  406. if (!DeleteKey(HKEY_CLASSES_ROOT, CLASS_NAME_MK)) return SELFREG_E_CLASS;
  407. if (!DeleteKey(HKEY_CLASSES_ROOT, szKeyCLSID)) return SELFREG_E_CLASS;
  408. CopyClassGuidString(CLSID_IE4_PROTOCOLS, pszCLSID);
  409. if (!DeleteKey(HKEY_CLASSES_ROOT, CLASS_NAME_ITS)) return SELFREG_E_CLASS;
  410. if (!DeleteKey(HKEY_CLASSES_ROOT, szKeyCLSID)) return SELFREG_E_CLASS;
  411. if (!DeleteKey(HKEY_CLASSES_ROOT, "PROTOCOLS\\Handler\\its"))
  412. return SELFREG_E_CLASS;
  413. if (!DeleteKey(HKEY_CLASSES_ROOT, "PROTOCOLS\\Handler\\ms-its"))
  414. return SELFREG_E_CLASS;
  415. if (!DeleteKey(HKEY_CLASSES_ROOT, "PROTOCOLS\\Name-Space Handler\\mk"))
  416. return SELFREG_E_CLASS;
  417. return NOERROR;
  418. }
  419. extern "C" STDAPI DllCanUnloadNow()
  420. {
  421. if (!pDLLServerState)
  422. return S_OK; // we're already unloaded
  423. return pDLLServerState->CanUnloadNow()? S_OK : S_FALSE;
  424. }
  425. #ifndef PathMgrOnly
  426. extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
  427. {
  428. return CFactory::Create(rclsid, riid, ppv);
  429. }
  430. #endif // ndef PathMgrOnly
  431. // Member functions for the CServerState class:
  432. CServerState *CServerState::CreateServerState(HMODULE hModule)
  433. {
  434. CServerState *pss = New CServerState(hModule);
  435. if (!pss || pss->InitServerState())
  436. return pss;
  437. delete pss;
  438. return NULL;
  439. }
  440. BOOL CServerState::InitServerState()
  441. {
  442. RonM_ASSERT(!m_pIMalloc);
  443. return SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &m_pIMalloc));
  444. }
  445. BOOL CServerState::CanUnloadNow()
  446. {
  447. // BugBug: Does the critical section below do anything useful?
  448. // The issue is that CanUnloadNow is called by the OLE system to find
  449. // out whether it can unload this DLL. Immediately after we return
  450. // a thread could call into DllGetClassObject before OLE makes the
  451. // call to FreeLibrary. So either Ole prevents that situation by
  452. // single threading all calls to DllGetClassObject, or the DetachProcess
  453. // call to DllMain ought to fail.
  454. CSyncWith sw(m_cs);
  455. BOOL fResult = (!m_cObjectsActive) && (!m_cLocksActive);
  456. return fResult;
  457. }
  458. INT CServerState::ObjectAdded()
  459. {
  460. return InterlockedIncrement(PLONG(&m_cObjectsActive));
  461. }
  462. INT CServerState::ObjectReleased()
  463. {
  464. INT uResult= InterlockedDecrement(PLONG(&m_cObjectsActive));
  465. RonM_ASSERT(uResult >= 0);
  466. return uResult;
  467. }
  468. INT CServerState::LockServer()
  469. {
  470. return InterlockedIncrement(PLONG(&m_cLocksActive));
  471. }
  472. INT CServerState::UnlockServer()
  473. {
  474. INT uResult= InterlockedDecrement(PLONG(&m_cLocksActive));
  475. RonM_ASSERT(uResult >= 0);
  476. return uResult;
  477. }