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.

706 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. minetmgr.cpp
  5. Abstract:
  6. Snapin object
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "inetmgr.h"
  18. #include "initguid.h"
  19. #include "cinetmgr.h"
  20. #include "constr.h"
  21. #include "mycomput.h"
  22. //
  23. // Registry Definitions
  24. //
  25. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  26. const LPCTSTR g_cszCLSID = _T("CLSID");
  27. const LPCTSTR g_cszLS32 = _T("LocalServer32");
  28. const LPCTSTR g_cszIPS32 = _T("InprocServer32");
  29. const LPCTSTR g_cszMMCBasePath = _T("Software\\Microsoft\\MMC");
  30. const LPCTSTR g_cszSnapins = _T("Snapins");
  31. const LPCTSTR g_cszNameString = _T("NameString");
  32. const LPCTSTR g_cszNameStringInd = _T("NameStringIndirect");
  33. const LPCTSTR g_cszProvider = _T("Provider");
  34. const LPCTSTR g_cszVersion = _T("Version");
  35. const LPCTSTR g_cszStandAlone = _T("StandAlone");
  36. const LPCTSTR g_cszNodeTypes = _T("NodeTypes");
  37. const LPCTSTR g_cszAbout = _T("About");
  38. const LPCTSTR g_cszExtensions = _T("Extensions");
  39. const LPCTSTR g_cszNameSpace = _T("NameSpace");
  40. const LPCTSTR g_cszDynamicExt = _T("Dynamic Extensions");
  41. const LPCTSTR g_cszValProvider = _T("Microsoft");
  42. const LPCTSTR g_cszValVersion = _T("5.0");
  43. const LPCTSTR g_cszMyCompMsc = _T("%SystemRoot%\\system32\\compmgmt.msc");
  44. const LPCTSTR g_cszServerAppsLoc = _T("System\\CurrentControlSet\\Control\\Server Applications");
  45. CFlexComModule _Module;
  46. HRESULT WINAPI
  47. CFlexComModule::UpdateRegistryClass(
  48. IN const CLSID & clsid,
  49. IN LPCTSTR lpszProgID,
  50. IN LPCTSTR lpszVerIndProgID,
  51. IN UINT nDescID,
  52. IN DWORD dwFlags,
  53. IN BOOL bRegister
  54. )
  55. /*++
  56. Routine Description:
  57. Override of UpdateRegistry to change the path to a path that uses
  58. a %systemroot%\... EXPAND_SZ path
  59. Arguments:
  60. const CLSID& clsid : GUID
  61. LPCTSTR lpszProgID : Program ID
  62. LPCTSTR lpszVerIndProgID : Version independent program ID
  63. UINT nDescID : Description resource ID
  64. DWORD dwFlags : Flags
  65. BOOL bRegister : TRUE for register, FALSE for unregister
  66. Return Value:
  67. HRESULT
  68. --*/
  69. {
  70. //
  71. // Call base class as normal
  72. //
  73. CError err = CComModule::UpdateRegistryClass(
  74. clsid,
  75. lpszProgID,
  76. lpszVerIndProgID,
  77. nDescID,
  78. dwFlags,
  79. bRegister
  80. );
  81. if (bRegister && err.Succeeded())
  82. {
  83. CString str, strKey, strCLSID;
  84. GUIDToCString(clsid, strCLSID);
  85. //
  86. // Change the path in InProcServer32/LocalServer32 to a
  87. // REG_EXPAND_SZ path
  88. //
  89. strKey.Format(_T("%s\\%s"),
  90. g_cszCLSID,
  91. strCLSID
  92. );
  93. CRMCRegKey rkCLSID(HKEY_CLASSES_ROOT, strKey, KEY_ENUMERATE_SUB_KEYS);
  94. if (!rkCLSID.Ok())
  95. {
  96. //
  97. // This should have been created by
  98. // _Module.RegisterServer
  99. //
  100. err.GetLastWinError();
  101. return err;
  102. }
  103. //
  104. // Look for inproc32 or local32
  105. //
  106. CRMCRegKey rkInProc(rkCLSID, g_cszIPS32);
  107. CRMCRegKey rkLocProc(rkCLSID, g_cszLS32);
  108. CRMCRegKey * prk = rkInProc.Ok()
  109. ? &rkInProc
  110. : rkLocProc.Ok()
  111. ? &rkLocProc
  112. : NULL;
  113. if (prk == NULL)
  114. {
  115. err.GetLastWinError();
  116. return err;
  117. }
  118. //
  119. // Rewrite entry as an REG_EXPAND_SZ
  120. //
  121. err = prk->QueryValue(NULL, str);
  122. if (err.Succeeded())
  123. {
  124. err = prk->SetValue(NULL, str, TRUE);
  125. }
  126. }
  127. return err;
  128. }
  129. BEGIN_OBJECT_MAP(ObjectMap)
  130. OBJECT_ENTRY(CLSID_Snapin, CComponentDataImpl)
  131. OBJECT_ENTRY(CLSID_About, CSnapinAboutImpl)
  132. END_OBJECT_MAP()
  133. #ifdef _DEBUG
  134. #define new DEBUG_NEW
  135. #undef THIS_FILE
  136. static char THIS_FILE[] = __FILE__;
  137. #endif
  138. //
  139. // Message Map
  140. //
  141. BEGIN_MESSAGE_MAP(CSnapinApp, CWinApp)
  142. //{{AFX_MSG_MAP(CConfigDll)
  143. //}}AFX_MSG_MAP
  144. //
  145. // Global help commands
  146. //
  147. ON_COMMAND(ID_HELP, CWinApp::OnHelp)
  148. ON_COMMAND(ID_CONTEXT_HELP, CWinApp::OnContextHelp)
  149. END_MESSAGE_MAP()
  150. #ifdef _DEBUG
  151. //
  152. // Allocation tracker
  153. //
  154. BOOL
  155. TrackAllocHook(
  156. IN size_t nSize,
  157. IN BOOL bObject,
  158. IN LONG lRequestNumber
  159. )
  160. {
  161. //
  162. // Track lRequestNumber here
  163. //
  164. //TRACEEOLID("allocation # " << lRequestNumber);
  165. return TRUE;
  166. }
  167. #endif // _DEBUG
  168. CSnapinApp::CSnapinApp()
  169. /*++
  170. Routine Description:
  171. Constructor
  172. Arguments:
  173. None
  174. Return Value:
  175. N/A
  176. --*/
  177. : CWinApp()
  178. {
  179. #ifdef _DEBUG
  180. afxMemDF |= checkAlwaysMemDF;
  181. AfxSetAllocHook(TrackAllocHook);
  182. #endif // _DEBUG
  183. }
  184. void
  185. CSnapinApp::SetHelpPath(
  186. IN CServerInfo * pItem OPTIONAL
  187. )
  188. /*++
  189. Routine Description:
  190. Change the default help path
  191. Arguments:
  192. CServerInfo * pItem : New help path owner or NULL to reset the help path
  193. Return Value:
  194. None
  195. Notes:
  196. A call to SetHelpPath() without parameters restores the help path.
  197. The help handler for the snapin is used to support help for down-level
  198. inetmgr extensions that do not have their own help handler. Since many
  199. of these extensions are MFC-based, help is expected to be provided in the
  200. CWinApp object.
  201. --*/
  202. {
  203. if (pItem == NULL)
  204. {
  205. //
  206. // Restore help path back to the inetmgr app
  207. //
  208. ASSERT(m_lpOriginalHelpPath != NULL);
  209. m_pszHelpFilePath = m_strInetMgrHelpPath;
  210. return;
  211. }
  212. //
  213. // Set the current help path equal to the one expected
  214. // from the config dll name
  215. //
  216. LPTSTR lpPath = m_strHelpPath.GetBuffer(MAX_PATH + 1);
  217. ::GetModuleFileName(pItem->QueryInstanceHandle(), lpPath, MAX_PATH);
  218. LPTSTR lp2 = _tcsrchr(lpPath, _T('.'));
  219. ASSERT(lp2 != NULL);
  220. if (lp2 != NULL)
  221. *lp2 = '\0';
  222. m_strHelpPath.ReleaseBuffer();
  223. m_strHelpPath += _T(".HLP");
  224. m_pszHelpFilePath = m_strHelpPath;
  225. }
  226. BOOL
  227. CSnapinApp::InitInstance()
  228. /*++
  229. Routine Description
  230. Instance initiation handler
  231. Arguments:
  232. None
  233. Return Value:
  234. TRUE for success, FALSE for failure
  235. --*/
  236. {
  237. _Module.Init(ObjectMap, m_hInstance);
  238. //
  239. // Save a pointer to the old help file
  240. //
  241. m_lpOriginalHelpPath = m_pszHelpFilePath;
  242. //
  243. // Build up inetmgr help path, expanding
  244. // the help path if necessary.
  245. //
  246. CRMCRegKey rk(REG_KEY, SZ_PARAMETERS, KEY_READ);
  247. rk.QueryValue(SZ_HELPPATH, m_strInetMgrHelpPath, EXPANSION_ON);
  248. m_strInetMgrHelpPath += _T("\\inetmgr.hlp");
  249. TRACEEOLID("Initialized help file " << m_strInetMgrHelpPath);
  250. m_pszHelpFilePath = m_strInetMgrHelpPath;
  251. return CWinApp::InitInstance();
  252. }
  253. int
  254. CSnapinApp::ExitInstance()
  255. /*++
  256. Routine Description:
  257. Exit instance handler
  258. Arguments:
  259. None
  260. Return Value:
  261. 0 for success
  262. --*/
  263. {
  264. _Module.Term();
  265. //
  266. // Restore original help file path so it can be deleted
  267. //
  268. ASSERT(m_lpOriginalHelpPath != NULL);
  269. m_pszHelpFilePath = m_lpOriginalHelpPath;
  270. return CWinApp::ExitInstance();
  271. }
  272. //
  273. // Instantiate the app object
  274. //
  275. CSnapinApp theApp;
  276. STDAPI
  277. DllCanUnloadNow()
  278. /*++
  279. Routine Description:
  280. Used to determine whether the DLL can be unloaded by OLE
  281. Arguments:
  282. None
  283. Return Value:
  284. HRESULT
  285. --*/
  286. {
  287. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  288. #ifdef _DEBUG
  289. HRESULT hr = ::AfxDllCanUnloadNow();
  290. LONG l = _Module.GetLockCount();
  291. TRACEEOLID("Module lock count " << l);
  292. BOOL fCanUnLoad = (l == 0 && hr == S_OK);
  293. #endif // _DEBUG
  294. return (::AfxDllCanUnloadNow() == S_OK
  295. && _Module.GetLockCount() == 0) ? S_OK : S_FALSE;
  296. }
  297. STDAPI
  298. DllGetClassObject(
  299. IN REFCLSID rclsid,
  300. IN REFIID riid,
  301. IN LPVOID * ppv
  302. )
  303. /*++
  304. Routine Description:
  305. Returns a class factory to create an object of the requested type
  306. Arguments:
  307. REFCLSID rclsid
  308. REFIID riid
  309. LPVOID * ppv
  310. Return Value:
  311. HRESULT
  312. --*/
  313. {
  314. return _Module.GetClassObject(rclsid, riid, ppv);
  315. }
  316. STDAPI
  317. DllRegisterServer()
  318. /*++
  319. Routine Description:
  320. DllRegisterServer - Adds entries to the system registry
  321. Arguments:
  322. None.
  323. Return Value:
  324. HRESULT
  325. --*/
  326. {
  327. //
  328. // Registers object, typelib and all interfaces in typelib
  329. //
  330. CError err(_Module.RegisterServer(FALSE));
  331. if (err.Failed())
  332. {
  333. return err;
  334. }
  335. CString str, strKey, strExtKey;
  336. try
  337. {
  338. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  339. //
  340. // Create the primary snapin nodes
  341. //
  342. CString strNameString((LPCTSTR)IDS_NODENAME);
  343. CString strNameStringInd;
  344. // Fix for bug 96801: moving strings from the Registry to resources (MUI requirement)
  345. TCHAR path[MAX_PATH];
  346. GetModuleFileName(_Module.GetResourceInstance(), path, MAX_PATH - 1);
  347. strNameStringInd.Format(_T("@%s,-%d"), path, IDS_NODENAME);
  348. TRACEEOLID("MUI-lized snapin name: " << strNameStringInd);
  349. CString strProvider(g_cszValProvider);
  350. CString strVersion(g_cszValVersion);
  351. CString str;
  352. strKey.Format(
  353. _T("%s\\%s\\%s"),
  354. g_cszMMCBasePath,
  355. g_cszSnapins,
  356. GUIDToCString(CLSID_Snapin, str)
  357. );
  358. TRACEEOLID(strKey);
  359. CString strAbout;
  360. GUIDToCString(CLSID_About, strAbout);
  361. CRMCRegKey rkSnapins(NULL, HKEY_LOCAL_MACHINE, strKey);
  362. rkSnapins.SetValue(g_cszAbout, strAbout);
  363. rkSnapins.SetValue(g_cszNameString, strNameString);
  364. rkSnapins.SetValue(g_cszNameStringInd, strNameStringInd);
  365. rkSnapins.SetValue(g_cszProvider, strProvider);
  366. rkSnapins.SetValue(g_cszVersion, strVersion);
  367. CRMCRegKey rkStandAlone(NULL, rkSnapins, g_cszStandAlone);
  368. CRMCRegKey rkNodeTypes (NULL, rkSnapins, g_cszNodeTypes);
  369. //
  370. // Create the nodetype GUIDS
  371. //
  372. CRMCRegKey rkN1(NULL, rkNodeTypes, GUIDToCString(cInternetRootNode, str));
  373. CRMCRegKey rkN2(NULL, rkNodeTypes, GUIDToCString(cMachineNode, str));
  374. CRMCRegKey rkN3(NULL, rkNodeTypes, GUIDToCString(cInstanceNode, str));
  375. CRMCRegKey rkN4(NULL, rkNodeTypes, GUIDToCString(cChildNode, str));
  376. CRMCRegKey rkN5(NULL, rkNodeTypes, GUIDToCString(cFileNode, str));
  377. {
  378. //
  379. // Register as a dynamic extension to computer management
  380. //
  381. strExtKey.Format(
  382. _T("%s\\%s\\%s\\%s"),
  383. g_cszMMCBasePath,
  384. g_cszNodeTypes,
  385. lstruuidNodetypeServerApps,
  386. g_cszDynamicExt
  387. );
  388. TRACEEOLID(strExtKey);
  389. CRMCRegKey rkMMCNodeTypes(NULL, HKEY_LOCAL_MACHINE, strExtKey);
  390. rkMMCNodeTypes.SetValue(
  391. GUIDToCString(CLSID_Snapin, str),
  392. strNameString
  393. );
  394. }
  395. {
  396. //
  397. // Register as a namespace extension to computer management
  398. //
  399. strExtKey.Format(
  400. _T("%s\\%s\\%s\\%s\\%s"),
  401. g_cszMMCBasePath,
  402. g_cszNodeTypes,
  403. lstruuidNodetypeServerApps,
  404. g_cszExtensions,
  405. g_cszNameSpace
  406. );
  407. TRACEEOLID(strExtKey);
  408. CRMCRegKey rkMMCNodeTypes(NULL, HKEY_LOCAL_MACHINE, strExtKey);
  409. rkMMCNodeTypes.SetValue(
  410. GUIDToCString(CLSID_Snapin, str),
  411. strNameString
  412. );
  413. }
  414. //
  415. // This key indicates that the service in question is available
  416. // on the local machine
  417. //
  418. CRMCRegKey rkCompMgmt(
  419. NULL,
  420. HKEY_LOCAL_MACHINE,
  421. g_cszServerAppsLoc
  422. );
  423. GUIDToCString(CLSID_Snapin, str);
  424. rkCompMgmt.SetValue(
  425. GUIDToCString(CLSID_Snapin, str),
  426. strNameString
  427. );
  428. }
  429. catch(CMemoryException * e)
  430. {
  431. e->Delete();
  432. err = ERROR_NOT_ENOUGH_MEMORY;
  433. }
  434. catch(COleException * e)
  435. {
  436. e->Delete();
  437. err = SELFREG_E_CLASS;
  438. }
  439. return err;
  440. }
  441. STDAPI
  442. DllUnregisterServer()
  443. /*++
  444. Routine Description:
  445. DllUnregisterServer - Removes entries from the system registry
  446. Arguments:
  447. None.
  448. Return Value:
  449. HRESULT
  450. --*/
  451. {
  452. CError err;
  453. try
  454. {
  455. CString strKey(g_cszMMCBasePath);
  456. strKey += _T("\\");
  457. strKey += g_cszSnapins;
  458. TRACEEOLID(strKey);
  459. CRMCRegKey rkBase(HKEY_LOCAL_MACHINE, strKey);
  460. CString str, strExtKey;
  461. {
  462. CRMCRegKey rkCLSID(rkBase, GUIDToCString(CLSID_Snapin, str));
  463. ::RegDeleteKey(rkCLSID, g_cszStandAlone);
  464. {
  465. CRMCRegKey rkNodeTypes(rkCLSID, g_cszNodeTypes);
  466. ::RegDeleteKey(rkNodeTypes, GUIDToCString(cInternetRootNode, str));
  467. ::RegDeleteKey(rkNodeTypes, GUIDToCString(cMachineNode, str));
  468. ::RegDeleteKey(rkNodeTypes, GUIDToCString(cInstanceNode, str));
  469. ::RegDeleteKey(rkNodeTypes, GUIDToCString(cChildNode, str));
  470. ::RegDeleteKey(rkNodeTypes, GUIDToCString(cFileNode, str));
  471. }
  472. ::RegDeleteKey(rkCLSID, g_cszNodeTypes);
  473. }
  474. ::RegDeleteKey(rkBase, GUIDToCString(CLSID_Snapin, str));
  475. {
  476. //
  477. // Delete a dynamic extension to computer management
  478. //
  479. strExtKey.Format(
  480. _T("%s\\%s\\%s\\%s"),
  481. g_cszMMCBasePath,
  482. g_cszNodeTypes,
  483. lstruuidNodetypeServerApps,
  484. g_cszDynamicExt
  485. );
  486. CRMCRegKey rkMMCNodeTypes(HKEY_LOCAL_MACHINE, strExtKey);
  487. ::RegDeleteValue(rkMMCNodeTypes, GUIDToCString(CLSID_Snapin, str));
  488. }
  489. {
  490. //
  491. // Delete the namespace extension to computer management
  492. //
  493. strExtKey.Format(
  494. _T("%s\\%s\\%s\\%s\\%s"),
  495. g_cszMMCBasePath,
  496. g_cszNodeTypes,
  497. lstruuidNodetypeServerApps,
  498. g_cszExtensions,
  499. g_cszNameSpace
  500. );
  501. CRMCRegKey rkMMCNodeTypes(HKEY_LOCAL_MACHINE, strExtKey);
  502. ::RegDeleteValue(rkMMCNodeTypes, GUIDToCString(CLSID_Snapin, str));
  503. }
  504. //
  505. // And the service itself no longer available on the local
  506. // computer
  507. //
  508. CRMCRegKey rkCompMgmt(
  509. HKEY_LOCAL_MACHINE,
  510. g_cszServerAppsLoc
  511. );
  512. ::RegDeleteValue(rkCompMgmt, GUIDToCString(CLSID_Snapin, str));
  513. }
  514. catch(CException * e)
  515. {
  516. err.GetLastWinError();
  517. e->Delete();
  518. }
  519. if (err.Failed())
  520. {
  521. return err.Failed();
  522. }
  523. return _Module.UnregisterServer();
  524. }