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.

486 lines
13 KiB

  1. // This is a part of the Microsoft Management Console.
  2. // Copyright (C) Microsoft Corporation, 1995 - 1999
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Management Console and related
  7. // electronic documentation provided with the interfaces.
  8. #include "stdafx.h"
  9. #include "resource.h"
  10. #include "initguid.h"
  11. #include "misc.h"
  12. CComModule _Module;
  13. HINSTANCE g_hInstance = NULL;
  14. BEGIN_OBJECT_MAP(ObjectMap)
  15. OBJECT_ENTRY(CLSID_Snapin, CComponentDataPrimaryImpl)
  16. OBJECT_ENTRY(CLSID_About, CSnapinAboutImpl)
  17. END_OBJECT_MAP()
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. void CreateRegEntries();
  23. void RemoveRegEntries();
  24. void CreateProgramGroupLink();
  25. void RemoveProgramGroupLink();
  26. // #define CERTMMC_DEBUG_REGSVR
  27. BOOL WINAPI DllMain(
  28. HINSTANCE hinstDLL, // handle to DLL module
  29. DWORD dwReason, // reason for calling function
  30. LPVOID lpvReserved)
  31. {
  32. switch (dwReason)
  33. {
  34. case DLL_PROCESS_ATTACH:
  35. {
  36. g_hInstance = hinstDLL;
  37. _Module.Init(ObjectMap, hinstDLL);
  38. DisableThreadLibraryCalls(hinstDLL);
  39. csiLogOpen("+certmmc.log");
  40. break;
  41. }
  42. case DLL_PROCESS_DETACH:
  43. {
  44. // last call process should do this
  45. myFreeColumnDisplayNames();
  46. _Module.Term();
  47. csiLogClose();
  48. DEBUG_VERIFY_INSTANCE_COUNT(CSnapin);
  49. DEBUG_VERIFY_INSTANCE_COUNT(CComponentDataImpl);
  50. break;
  51. }
  52. default:
  53. break;
  54. }
  55. return TRUE;
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. // Used to determine whether the DLL can be unloaded by OLE
  59. STDAPI DllCanUnloadNow(void)
  60. {
  61. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  62. return (_Module.GetLockCount() == 0) ? S_OK : S_FALSE;
  63. }
  64. /////////////////////////////////////////////////////////////////////////////
  65. // Returns a class factory to create an object of the requested type
  66. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  67. {
  68. return _Module.GetClassObject(rclsid, riid, ppv);
  69. }
  70. /////////////////////////////////////////////////////////////////////////////
  71. // DllRegisterServer - Adds entries to the system registry
  72. STDAPI DllRegisterServer(void)
  73. {
  74. CreateRegEntries();
  75. CreateProgramGroupLink();
  76. // registers object, typelib and all interfaces in typelib
  77. return _Module.RegisterServer(FALSE);
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. // DllUnregisterServer - Removes entries from the system registry
  81. STDAPI DllUnregisterServer(void)
  82. {
  83. _Module.UnregisterServer();
  84. RemoveRegEntries();
  85. RemoveProgramGroupLink();
  86. return S_OK;
  87. }
  88. /////////////////////////////////////////////////////////////////////////////
  89. // Register/UnRegister nodetypes, etc
  90. typedef struct _REGVALUE
  91. {
  92. DWORD dwFlags;
  93. WCHAR const *pwszKeyName; // NULL implies place value under CA name key
  94. WCHAR const *pwszValueName;
  95. WCHAR const *pwszValueString; // NULL implies use REG_DWORD value (dwValue)
  96. DWORD dwValue;
  97. } REGVALUE;
  98. // Flags
  99. #define CERTMMC_REG_DELKEY 1 // delete this key on removal
  100. // Values Under "HKLM" from base to leaves
  101. REGVALUE g_arvCA[] =
  102. {
  103. // main snapin uuid
  104. #define IREG_SNAPINNAME 0
  105. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1, NULL, NULL, 0},
  106. #define IREG_SNAPINNAMESTRING 1
  107. { 0, wszREGKEYMGMTSNAPINUUID1, wszSNAPINNAMESTRING, NULL, 0},
  108. #define IREG_SNAPINNAMESTRINGINDIRECT 2
  109. { 0, wszREGKEYMGMTSNAPINUUID1, wszSNAPINNAMESTRINGINDIRECT, NULL, 0},
  110. { 0, wszREGKEYMGMTSNAPINUUID1, wszSNAPINABOUT, wszSNAPINNODETYPE_ABOUT, 0},
  111. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_STANDALONE, NULL, NULL, 0}
  112. ,
  113. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES, NULL, NULL, 0},
  114. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_1, NULL, NULL, 0},
  115. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_2, NULL, NULL, 0},
  116. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_3, NULL, NULL, 0},
  117. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_4, NULL, NULL, 0},
  118. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_5, NULL, NULL, 0},
  119. // register each snapin nodetype
  120. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_1, NULL, wszREGCERTSNAPIN_NODETYPES_1, 0},
  121. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_2, NULL, wszREGCERTSNAPIN_NODETYPES_2, 0},
  122. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_3, NULL, wszREGCERTSNAPIN_NODETYPES_3, 0},
  123. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_4, NULL, wszREGCERTSNAPIN_NODETYPES_4, 0},
  124. { CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_5, NULL, wszREGCERTSNAPIN_NODETYPES_5, 0},
  125. { 0, NULL, NULL, NULL, 0 }
  126. };
  127. HRESULT
  128. InitRegEntries(
  129. OPTIONAL IN OUT CString *pcstrName,
  130. OPTIONAL IN OUT CString *pcstrNameString,
  131. OPTIONAL IN OUT CString *pcstrNameStringIndirect)
  132. {
  133. HRESULT hr = S_OK;
  134. WCHAR const *pwsz;
  135. pwsz = NULL;
  136. if (NULL != pcstrName)
  137. {
  138. pcstrName->LoadString(IDS_CERTMMC_SNAPINNAME);
  139. if (pcstrName->IsEmpty())
  140. {
  141. hr = myHLastError();
  142. _PrintError(hr, "LoadString");
  143. }
  144. else
  145. {
  146. pwsz = (LPCWSTR) *pcstrName;
  147. }
  148. }
  149. g_arvCA[IREG_SNAPINNAME].pwszValueString = pwsz;
  150. pwsz = NULL;
  151. if (NULL != pcstrNameString)
  152. {
  153. pcstrNameString->LoadString(IDS_CERTMMC_SNAPINNAMESTRING);
  154. if (pcstrNameString->IsEmpty())
  155. {
  156. hr = myHLastError();
  157. _PrintError(hr, "LoadString");
  158. }
  159. else
  160. {
  161. pwsz = (LPCWSTR) *pcstrNameString;
  162. }
  163. }
  164. g_arvCA[IREG_SNAPINNAMESTRING].pwszValueString = pwsz;
  165. pwsz = NULL;
  166. if (NULL != pcstrNameStringIndirect)
  167. {
  168. pcstrNameStringIndirect->Format(wszSNAPINNAMESTRINGINDIRECT_TEMPLATE, L"CertMMC.dll", IDS_CERTMMC_SNAPINNAMESTRING);
  169. if (pcstrNameStringIndirect->IsEmpty())
  170. {
  171. hr = myHLastError();
  172. _PrintError(hr, "LoadString");
  173. }
  174. else
  175. {
  176. pwsz = (LPCWSTR) *pcstrNameStringIndirect;
  177. }
  178. }
  179. g_arvCA[IREG_SNAPINNAMESTRINGINDIRECT].pwszValueString = pwsz;
  180. //error:
  181. return(hr);
  182. }
  183. void CreateRegEntries()
  184. {
  185. DWORD err;
  186. HKEY hKeyThisValue = NULL;
  187. REGVALUE const *prv;
  188. CString cstrName;
  189. CString cstrNameString;
  190. CString cstrNameStringIndirect;
  191. InitRegEntries(&cstrName, &cstrNameString, &cstrNameStringIndirect);
  192. // run until not creating key or value
  193. for ( prv=g_arvCA;
  194. !(NULL == prv->pwszValueName && NULL == prv->pwszKeyName);
  195. prv++ )
  196. {
  197. DWORD dwDisposition;
  198. ASSERT(NULL != prv->pwszKeyName);
  199. if (NULL == prv->pwszKeyName)
  200. continue;
  201. #ifdef CERTMMC_DEBUG_REGSVR
  202. CString cstr;
  203. cstr.Format(L"RegCreateKeyEx: %s\n", prv->pwszKeyName);
  204. OutputDebugString((LPCWSTR)cstr);
  205. #endif
  206. err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  207. prv->pwszKeyName,
  208. 0,
  209. NULL,
  210. REG_OPTION_NON_VOLATILE,
  211. KEY_ALL_ACCESS,
  212. NULL,
  213. &hKeyThisValue,
  214. &dwDisposition);
  215. if (err != ERROR_SUCCESS)
  216. goto error;
  217. // for now, don't set any value if unnamed, unvalued string
  218. // UNDONE: can't set unnamed dword!
  219. if (NULL != prv->pwszValueName || NULL != prv->pwszValueString)
  220. {
  221. if (NULL != prv->pwszValueString)
  222. {
  223. #ifdef CERTMMC_DEBUG_REGSVR
  224. CString cstr;
  225. cstr.Format(L"RegSetValueEx: %s : %s\n", prv->pwszValueName, prv->pwszValueString);
  226. OutputDebugString((LPCWSTR)cstr);
  227. #endif
  228. err = RegSetValueEx(
  229. hKeyThisValue,
  230. prv->pwszValueName,
  231. 0,
  232. REG_SZ,
  233. (const BYTE *) prv->pwszValueString,
  234. WSZ_BYTECOUNT(prv->pwszValueString));
  235. }
  236. else
  237. {
  238. #ifdef CERTMMC_DEBUG_REGSVR
  239. CString cstr;
  240. cstr.Format(L"RegSetValueEx: %s : %ul\n", prv->pwszValueName, prv->dwValue);
  241. OutputDebugString((LPCWSTR)cstr);
  242. #endif
  243. err = RegSetValueEx(
  244. hKeyThisValue,
  245. prv->pwszValueName,
  246. 0,
  247. REG_DWORD,
  248. (const BYTE *) &prv->dwValue,
  249. sizeof(prv->dwValue));
  250. }
  251. if (err != ERROR_SUCCESS)
  252. goto error;
  253. }
  254. if (NULL != hKeyThisValue)
  255. {
  256. RegCloseKey(hKeyThisValue);
  257. hKeyThisValue = NULL;
  258. }
  259. }
  260. error:
  261. if (hKeyThisValue)
  262. RegCloseKey(hKeyThisValue);
  263. InitRegEntries(NULL, NULL, NULL);
  264. return;
  265. }
  266. void RemoveRegEntries()
  267. {
  268. DWORD err;
  269. REGVALUE const *prv;
  270. // walk backwards through array until hit array start
  271. for ( prv= (&g_arvCA[ARRAYLEN(g_arvCA)]) - 2; // goto zero-based end AND skip {NULL}
  272. prv >= g_arvCA; // until we walk past beginning
  273. prv-- ) // walk backwards
  274. {
  275. if (prv->dwFlags & CERTMMC_REG_DELKEY)
  276. {
  277. ASSERT(prv->pwszKeyName != NULL);
  278. #ifdef CERTMMC_DEBUG_REGSVR
  279. CString cstr;
  280. cstr.Format(L"RegDeleteKey: %s\n", prv->pwszKeyName);
  281. OutputDebugString((LPCWSTR)cstr);
  282. #endif
  283. RegDeleteKey(
  284. HKEY_LOCAL_MACHINE,
  285. prv->pwszKeyName);
  286. }
  287. }
  288. //error:
  289. return;
  290. }
  291. #include <shlobj.h> // CSIDL_ #defines
  292. #include <userenv.h>
  293. #include <userenvp.h> // CreateLinkFile API
  294. typedef struct _PROGRAMENTRY
  295. {
  296. UINT uiLinkName;
  297. UINT uiDescription;
  298. DWORD csidl; // special folder index
  299. WCHAR const *pwszExeName;
  300. WCHAR const *pwszArgs;
  301. } PROGRAMENTRY;
  302. PROGRAMENTRY const g_aProgramEntry[] = {
  303. {
  304. IDS_STARTMENU_CERTMMC_LINKNAME, // uiLinkName
  305. IDS_STARTMENU_CERTMMC_DESCRIPTION, // uiDescription
  306. CSIDL_COMMON_ADMINTOOLS, // "All Users\Start Menu\Programs\Administrative Tools"
  307. L"certsrv.msc", // pwszExeName
  308. L" /s", // pwszArgs
  309. },
  310. };
  311. #define CPROGRAMENTRY ARRAYSIZE(g_aProgramEntry)
  312. BOOL FFileExists(LPCWSTR szFile)
  313. {
  314. WIN32_FILE_ATTRIBUTE_DATA data;
  315. return(
  316. GetFileAttributesEx(szFile, GetFileExInfoStandard, &data) &&
  317. !(FILE_ATTRIBUTE_DIRECTORY & data.dwFileAttributes)
  318. );
  319. }
  320. void CreateProgramGroupLink()
  321. {
  322. HRESULT hr = S_OK;
  323. PROGRAMENTRY const *ppe;
  324. for (ppe = g_aProgramEntry; ppe < &g_aProgramEntry[CPROGRAMENTRY]; ppe++)
  325. {
  326. CString cstrLinkName, cstrDescr, cstrPath;
  327. LPWSTR pszTmp;
  328. if (NULL == (pszTmp = cstrPath.GetBuffer(MAX_PATH)))
  329. {
  330. hr = E_OUTOFMEMORY;
  331. _JumpError(hr, error, "GetBuffer");
  332. }
  333. GetSystemDirectory(pszTmp, MAX_PATH);
  334. cstrPath += L"\\";
  335. cstrPath += ppe->pwszExeName;
  336. // don't create link for file that doesn't exist
  337. if (!FFileExists(cstrPath))
  338. continue;
  339. cstrPath += ppe->pwszArgs;
  340. cstrLinkName.LoadString(ppe->uiLinkName);
  341. if (cstrLinkName.IsEmpty())
  342. {
  343. hr = myHLastError();
  344. _JumpError(hr, error, "LoadString");
  345. }
  346. cstrDescr.LoadString(ppe->uiDescription);
  347. if (cstrDescr.IsEmpty())
  348. {
  349. hr = myHLastError();
  350. _JumpError(hr, error, "LoadString");
  351. }
  352. if (!CreateLinkFile(
  353. ppe->csidl, // CSIDL_*
  354. NULL, // IN LPCSTR lpSubDirectory
  355. (LPCWSTR)cstrLinkName, // IN LPCSTR lpFileName
  356. (LPCWSTR)cstrPath, // IN LPCSTR lpCommandLine
  357. NULL, // IN LPCSTR lpIconPath
  358. 0, // IN INT iIconIndex
  359. NULL, // IN LPCSTR lpWorkingDirectory
  360. 0, // IN WORD wHotKey
  361. SW_SHOWNORMAL, // IN INT iShowCmd
  362. (LPCWSTR)cstrDescr)) // IN LPCSTR lpDescription
  363. {
  364. hr = myHLastError();
  365. _JumpErrorStr(hr, error, "CreateLinkFile", (LPCWSTR)cstrLinkName);
  366. }
  367. }
  368. error:
  369. _PrintIfError(hr, "CreateProgramGroupLink");
  370. return;
  371. }
  372. void RemoveProgramGroupLink()
  373. {
  374. HRESULT hr = S_OK;
  375. PROGRAMENTRY const *ppe;
  376. for (ppe = g_aProgramEntry; ppe < &g_aProgramEntry[CPROGRAMENTRY]; ppe++)
  377. {
  378. CString cstrLinkName;
  379. cstrLinkName.LoadString(ppe->uiLinkName);
  380. if (cstrLinkName.IsEmpty())
  381. {
  382. hr = myHLastError();
  383. _PrintError(hr, "LoadString");
  384. continue;
  385. }
  386. if (!DeleteLinkFile(
  387. ppe->csidl, // CSIDL_*
  388. NULL, // IN LPCSTR lpSubDirectory
  389. (LPCWSTR)cstrLinkName, // IN LPCSTR lpFileName
  390. FALSE)) // IN BOOL fDeleteSubDirectory
  391. {
  392. hr = myHLastError();
  393. _PrintError2(hr, "DeleteLinkFile", hr);
  394. }
  395. }
  396. //error:
  397. _PrintIfError2(hr, "RemoveProgramGroupLink", hr);
  398. return;
  399. }