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.

347 lines
6.5 KiB

  1. // Copyright (C) 1999 Microsoft Corporation
  2. //
  3. // DllMain and COM DllXxx functions
  4. //
  5. // sburns 5-3-99
  6. #include "headers.hxx"
  7. #include "implmain.hpp"
  8. HINSTANCE hResourceModuleHandle = 0;
  9. const wchar_t* HELPFILE_NAME = 0;
  10. const wchar_t* RUNTIME_NAME = L"clonepr";
  11. DWORD DEFAULT_LOGGING_OPTIONS = OUTPUT_MUTE;
  12. TCHAR g_szFileName[MAX_PATH];
  13. struct REG_DATA
  14. {
  15. const wchar_t *keyName;
  16. const wchar_t *valueName;
  17. const wchar_t *value;
  18. };
  19. const REG_DATA g_rgEntries[] =
  20. {
  21. {
  22. L"CLSID\\" CLSID_STRING,
  23. 0,
  24. CLASSNAME_STRING
  25. },
  26. {
  27. L"CLSID\\" CLSID_STRING L"\\InprocServer32",
  28. 0,
  29. g_szFileName
  30. },
  31. {
  32. L"CLSID\\" CLSID_STRING L"\\InprocServer32",
  33. L"ThreadingModel",
  34. L"Apartment"
  35. },
  36. {
  37. L"CLSID\\" CLSID_STRING L"\\ProgID",
  38. 0,
  39. PROGID_VERSION_STRING
  40. },
  41. {
  42. L"CLSID\\" CLSID_STRING L"\\VersionIndependentProgID",
  43. 0,
  44. PROGID_STRING
  45. },
  46. {
  47. PROGID_VERSION_STRING,
  48. 0,
  49. CLASSNAME_STRING
  50. },
  51. {
  52. PROGID_VERSION_STRING L"\\CLSID",
  53. 0,
  54. CLSID_STRING
  55. },
  56. {
  57. PROGID_STRING,
  58. 0,
  59. CLASSNAME_STRING
  60. },
  61. {
  62. PROGID_STRING L"\\CLSID",
  63. 0,
  64. CLSID_STRING
  65. },
  66. {
  67. PROGID_STRING L"\\CurVer",
  68. 0,
  69. PROGID_VERSION_STRING
  70. },
  71. // register for IADsSID
  72. {
  73. PROGID_VERSION_STRING_ADSSID,
  74. 0,
  75. CLASSNAME_STRING
  76. },
  77. {
  78. PROGID_VERSION_STRING_ADSSID L"\\CLSID",
  79. 0,
  80. CLSID_STRING
  81. },
  82. {
  83. PROGID_STRING_ADSSID,
  84. 0,
  85. CLASSNAME_STRING
  86. },
  87. {
  88. PROGID_STRING_ADSSID L"\\CLSID",
  89. 0,
  90. CLSID_STRING
  91. },
  92. {
  93. PROGID_STRING_ADSSID L"\\CurVer",
  94. 0,
  95. PROGID_VERSION_STRING_ADSSID
  96. },
  97. // register for IADsError
  98. {
  99. PROGID_VERSION_STRING_ADSERROR,
  100. 0,
  101. CLASSNAME_STRING
  102. },
  103. {
  104. PROGID_VERSION_STRING_ADSERROR L"\\CLSID",
  105. 0,
  106. CLSID_STRING
  107. },
  108. {
  109. PROGID_STRING_ADSERROR,
  110. 0,
  111. CLASSNAME_STRING
  112. },
  113. {
  114. PROGID_STRING_ADSERROR L"\\CLSID",
  115. 0,
  116. CLSID_STRING
  117. },
  118. {
  119. PROGID_STRING_ADSERROR L"\\CurVer",
  120. 0,
  121. PROGID_VERSION_STRING_ADSERROR
  122. }
  123. };
  124. const int g_cEntries = sizeof(g_rgEntries)/sizeof(*g_rgEntries);
  125. static
  126. HRESULT
  127. Unregister(const REG_DATA *rgEntries, int cEntries)
  128. {
  129. LOG_FUNCTION(Unregister);
  130. LOG(L"Calling UnRegisterTypeLib");
  131. HRESULT hr =
  132. ::UnRegisterTypeLib(LIBID_CloneSecurityPrincipalLib, 1, 0, 0, SYS_WIN32);
  133. LOG_HRESULT(hr);
  134. // don't break: continue on attempting to remove as much as possible
  135. // of our registration
  136. bool success = SUCCEEDED(hr);
  137. for (int i = cEntries - 1; i >= 0; i--)
  138. {
  139. LONG err = ::RegDeleteKey(HKEY_CLASSES_ROOT, rgEntries[i].keyName);
  140. if (err != ERROR_SUCCESS)
  141. {
  142. success = false;
  143. }
  144. }
  145. return success ? S_OK : S_FALSE;
  146. }
  147. static HRESULT Register(const REG_DATA *rgEntries, int cEntries)
  148. {
  149. BOOL bSuccess = TRUE;
  150. HRESULT hr = S_OK; // 447822 prefix warning
  151. const REG_DATA *pEntry = rgEntries;
  152. while (pEntry < rgEntries + cEntries)
  153. {
  154. HKEY hkey;
  155. LONG err = RegCreateKey(HKEY_CLASSES_ROOT,
  156. pEntry->keyName,
  157. &hkey);
  158. if (err == ERROR_SUCCESS)
  159. {
  160. if (pEntry->value)
  161. err = RegSetValueEx(hkey,
  162. pEntry->valueName,
  163. 0, REG_SZ,
  164. (const BYTE*)pEntry->value,
  165. (lstrlen(pEntry->value) + 1) * sizeof(TCHAR));
  166. if (err != ERROR_SUCCESS)
  167. {
  168. bSuccess = FALSE;
  169. Unregister(rgEntries, static_cast<int>(1 + pEntry - rgEntries));
  170. }
  171. RegCloseKey(hkey);
  172. }
  173. if (err != ERROR_SUCCESS)
  174. {
  175. bSuccess = FALSE;
  176. if (pEntry != rgEntries)
  177. Unregister(rgEntries, static_cast<int>(pEntry - rgEntries));
  178. }
  179. pEntry++;
  180. };
  181. if (bSuccess)
  182. {
  183. OLECHAR g_wszFileName[MAX_PATH];
  184. lstrcpy(g_wszFileName, g_szFileName);
  185. ITypeLib *ptl = 0;
  186. hr = LoadTypeLib(g_wszFileName, &ptl);
  187. if (SUCCEEDED(hr))
  188. {
  189. hr = RegisterTypeLib(ptl, g_wszFileName, 0);
  190. ptl->Release();
  191. }
  192. if (bSuccess)
  193. hr = S_OK;
  194. else
  195. hr = E_FAIL;
  196. }
  197. return hr ;//bSuccess ? S_OK : E_FAIL;
  198. }
  199. BOOL
  200. APIENTRY
  201. DllMain(HINSTANCE h, DWORD dwReason, void *)
  202. {
  203. switch (dwReason)
  204. {
  205. case DLL_PROCESS_ATTACH:
  206. {
  207. hResourceModuleHandle = h;
  208. LOG(L"DLL_PROCESS_ATTACH");
  209. // @@ remove this
  210. GetModuleFileName(h, g_szFileName, MAX_PATH);
  211. break;
  212. }
  213. case DLL_PROCESS_DETACH:
  214. {
  215. #ifdef DEBUG_BUILD
  216. LOG(TEXT("DLL_PROCESS_DETACH"));
  217. if (!ComServerLockState::CanUnloadNow())
  218. {
  219. LOG(L"server locks and/or outstanding object instances exit");
  220. }
  221. else
  222. {
  223. LOG(L"server can unload now.");
  224. }
  225. #endif
  226. break;
  227. }
  228. case DLL_THREAD_ATTACH:
  229. case DLL_THREAD_DETACH:
  230. default:
  231. {
  232. break;
  233. }
  234. }
  235. return TRUE;
  236. }
  237. STDAPI
  238. DllRegisterServer()
  239. {
  240. LOG_FUNCTION(DllRegisterServer);
  241. return Register(g_rgEntries, g_cEntries);
  242. }
  243. STDAPI
  244. DllUnregisterServer()
  245. {
  246. LOG_FUNCTION(DllUnregisterServer);
  247. return Unregister(g_rgEntries, g_cEntries);
  248. }
  249. STDAPI
  250. DllCanUnloadNow()
  251. {
  252. LOG_FUNCTION(DllCanUnloadNow);
  253. if (ComServerLockState::CanUnloadNow())
  254. {
  255. return S_OK;
  256. }
  257. return S_FALSE;
  258. }
  259. STDAPI
  260. DllGetClassObject(
  261. const CLSID& classID,
  262. const IID& interfaceID,
  263. void** interfaceDesired)
  264. {
  265. LOG_FUNCTION(DllGetClassObject);
  266. IClassFactory* factory = 0;
  267. // The class objects are instances of ClassFactory<>, which are ref-counted
  268. // in the usual fashion (i.e. they track their ref counts, and
  269. // self-destruct on final Release). I could have used static instances of
  270. // a C++ class that ignored the refcounting (ala Don Box's examples in
  271. // Essential COM)
  272. if (classID == CLSID_CloneSecurityPrincipal)
  273. {
  274. factory = new ClassFactory<CloneSecurityPrincipal>;
  275. }
  276. else
  277. {
  278. *interfaceDesired = 0;
  279. return CLASS_E_CLASSNOTAVAILABLE;
  280. }
  281. // the class factory instance starts with a ref count of 1. If the QI
  282. // fails, then it self-destructs upon Release.
  283. HRESULT hr = factory->QueryInterface(interfaceID, interfaceDesired);
  284. factory->Release();
  285. return hr;
  286. }