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.

527 lines
13 KiB

  1. // SnapIn.cpp : Defines the initialization routines for the DLL.
  2. //
  3. // Copyright (c) 2000 Microsoft Corporation
  4. //
  5. //
  6. // 03-14-00 v-marfin bug 58675 : Disable the "server busy.. retry, switch, etc" dialog.
  7. // 03-23-00 v-marfin bug 61680 : Added escape and unescape special chars functions.
  8. // 03/31/00 v-marfin no bug : Call AfxSetResourceHandle on resource dll handle to
  9. // enable early calls to LoadString() etc to work.
  10. // Use AfxFreeLibrary instead of FreeLibrary to use thread
  11. // protected version of function.
  12. #include "stdafx.h"
  13. #include "SnapIn.h"
  14. #include <atlbase.h>
  15. #include "WbemClassObject.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. //
  22. // Note!
  23. //
  24. // If this DLL is dynamically linked against the MFC
  25. // DLLs, any functions exported from this DLL which
  26. // call into MFC must have the AFX_MANAGE_STATE macro
  27. // added at the very beginning of the function.
  28. //
  29. // For example:
  30. //
  31. // extern "C" BOOL PASCAL EXPORT ExportedFunction()
  32. // {
  33. // AFX_MANAGE_STATE(AfxGetStaticModuleState());
  34. // // normal function body here
  35. // }
  36. //
  37. // It is very important that this macro appear in each
  38. // function, prior to any calls into MFC. This means that
  39. // it must appear as the first statement within the
  40. // function, even before any object variable declarations
  41. // as their constructors may generate calls into the MFC
  42. // DLL.
  43. //
  44. // Please see MFC Technical Notes 33 and 58 for additional
  45. // details.
  46. //
  47. CStringArray CSnapInApp::m_arrsNamespaces;
  48. /////////////////////////////////////////////////////////////////////////////
  49. // CSnapInApp
  50. BEGIN_MESSAGE_MAP(CSnapInApp, CWinApp)
  51. //{{AFX_MSG_MAP(CSnapInApp)
  52. // NOTE - the ClassWizard will add and remove mapping macros here.
  53. // DO NOT EDIT what you see in these blocks of generated code!
  54. //}}AFX_MSG_MAP
  55. END_MESSAGE_MAP()
  56. /////////////////////////////////////////////////////////////////////////////
  57. // CSnapInApp construction
  58. CSnapInApp::CSnapInApp()
  59. {
  60. // TODO: add construction code here,
  61. // Place all significant initialization in InitInstance
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // Resource Dll Members
  65. inline bool CSnapInApp::LoadDefaultResourceDll()
  66. {
  67. TRACEX(_T("CSnapInApp::LoadDefaultResourceDll\n"));
  68. // first attempt to load resources for the current locale
  69. m_hDefaultResourceDll = AfxLoadLibrary(GetDefaultResDllPath());
  70. // if that fails then load resources for english
  71. if( m_hDefaultResourceDll == NULL )
  72. {
  73. m_hDefaultResourceDll = AfxLoadLibrary(GetEnglishResDllPath());
  74. }
  75. // v-marfin
  76. AfxSetResourceHandle(m_hDefaultResourceDll);
  77. return m_hDefaultResourceDll != NULL;
  78. }
  79. inline void CSnapInApp::UnloadDefaultResourceDll()
  80. {
  81. TRACEX(_T("CSnapInApp::UnloadDefaultResourceDll\n"));
  82. if( m_hDefaultResourceDll )
  83. {
  84. // v-marfin (no bug)
  85. AfxFreeLibrary(m_hDefaultResourceDll);
  86. }
  87. }
  88. HINSTANCE CSnapInApp::LoadResourceDll(const CString& sFileName)
  89. {
  90. HINSTANCE hDllInst = NULL;
  91. if( m_ResourceDllMap.Lookup(sFileName,hDllInst) )
  92. {
  93. return hDllInst;
  94. }
  95. hDllInst = AfxLoadLibrary(GetDefaultResDllDirectory() + sFileName);
  96. if( !hDllInst )
  97. {
  98. //AfxMessageBox(IDS_STRING_RESOURCE_DLL_MISSING);
  99. return NULL;
  100. }
  101. m_ResourceDllMap.SetAt(sFileName,hDllInst);
  102. return hDllInst;
  103. }
  104. bool CSnapInApp::LoadString(const CString& sFileName, UINT uiResId, CString& sResString)
  105. {
  106. HINSTANCE hInst = LoadResourceDll(sFileName);
  107. if( ! hInst )
  108. {
  109. return false;
  110. }
  111. int iResult = ::LoadString(hInst,uiResId,sResString.GetBuffer(2048),2048);
  112. sResString.ReleaseBuffer();
  113. if( iResult == 0 || sResString.IsEmpty() )
  114. {
  115. return false;
  116. }
  117. return true;
  118. }
  119. void CSnapInApp::UnloadResourceDlls()
  120. {
  121. POSITION pos = m_ResourceDllMap.GetStartPosition();
  122. LPCTSTR lpszKey;
  123. HINSTANCE hInst;
  124. while (pos != NULL)
  125. {
  126. m_ResourceDllMap.GetNextAssoc( pos, lpszKey, hInst );
  127. AfxFreeLibrary(hInst);
  128. }
  129. }
  130. /////////////////////////////////////////////////////////////////////////////
  131. // Help System Members
  132. inline void CSnapInApp::SetHelpFilePath()
  133. {
  134. TRACEX(_T("CSnapInApp::SetHelpFilePath\n"));
  135. TCHAR szWinDir[_MAX_PATH];
  136. GetWindowsDirectory(szWinDir,_MAX_PATH);
  137. CString sHelpFilePath;
  138. sHelpFilePath.Format(IDS_STRING_HELP_FORMAT,szWinDir);
  139. if( m_pszHelpFilePath )
  140. {
  141. free((LPVOID)m_pszHelpFilePath);
  142. }
  143. m_pszHelpFilePath = _tcsdup(sHelpFilePath);
  144. }
  145. /////////////////////////////////////////////////////////////////////////////
  146. // Directory Assistance Members
  147. CString CSnapInApp::GetSnapinDllDirectory()
  148. {
  149. TCHAR szModule[_MAX_PATH];
  150. TCHAR szDrive[_MAX_PATH];
  151. TCHAR szDir[_MAX_PATH];
  152. GetModuleFileName(AfxGetInstanceHandle(), szModule, _MAX_PATH);
  153. _tsplitpath(szModule,szDrive,szDir,NULL,NULL);
  154. CString sPath;
  155. sPath += szDrive;
  156. sPath += szDir;
  157. return sPath;
  158. }
  159. CString CSnapInApp::GetDefaultResDllDirectory()
  160. {
  161. LCID lcid = GetUserDefaultLCID();
  162. CString sLocaleID;
  163. sLocaleID.Format(_T("%08x\\"),lcid);
  164. return GetSnapinDllDirectory() + sLocaleID;
  165. }
  166. CString CSnapInApp::GetDefaultResDllPath()
  167. {
  168. return GetDefaultResDllDirectory() + _T("HMSnapinRes.dll");
  169. }
  170. CString CSnapInApp::GetEnglishResDllPath()
  171. {
  172. return GetSnapinDllDirectory() + _T("00000409\\HMSnapinRes.dll");
  173. }
  174. /////////////////////////////////////////////////////////////////////////////
  175. // The one and only CSnapInApp object
  176. CSnapInApp theApp;
  177. /////////////////////////////////////////////////////////////////////////////
  178. // CSnapInApp initialization
  179. BOOL CSnapInApp::InitInstance()
  180. {
  181. SetRegistryKey(_T("Microsoft"));
  182. // Register all OLE server (factories) as running. This enables the
  183. // OLE libraries to create objects from other applications.
  184. COleObjectFactory::RegisterAll();
  185. // set the help path up
  186. SetHelpFilePath();
  187. // load the resource dll
  188. if( ! LoadDefaultResourceDll() )
  189. {
  190. AfxMessageBox(IDS_STRING_RESOURCE_DLL_MISSING);
  191. return FALSE;
  192. }
  193. //-------------------------------------------------------------------------------
  194. // v-marfin : bug 58675 : Disable the "server busy.. retry, switch, etc" dialog.
  195. //
  196. if (!AfxOleInit())
  197. {
  198. AfxMessageBox(IDS_ERR_OLE_INIT_FAILED);
  199. return FALSE;
  200. }
  201. // If an OLE message filter is already in place, remove it
  202. COleMessageFilter *pOldFilter = AfxOleGetMessageFilter();
  203. if (pOldFilter)
  204. {
  205. pOldFilter->Revoke();
  206. }
  207. // Disable the "busy" dialogs
  208. m_mfMyMessageFilter.EnableNotRespondingDialog(FALSE);
  209. m_mfMyMessageFilter.EnableBusyDialog(FALSE);
  210. if (!m_mfMyMessageFilter.Register())
  211. {
  212. AfxMessageBox(IDS_ERR_MSGFILTER_REG_FAILED);
  213. }
  214. //-------------------------------------------------------------------------------
  215. return TRUE;
  216. }
  217. int CSnapInApp::ExitInstance()
  218. {
  219. UnloadDefaultResourceDll();
  220. UnloadResourceDlls();
  221. //-------------------------------------------------------------------------------
  222. // v-marfin : bug 58675 : Disable the "server busy.. retry, switch, etc" dialog.
  223. m_mfMyMessageFilter.Revoke();
  224. return CWinApp::ExitInstance();
  225. }
  226. /////////////////////////////////////////////////////////////////////////////
  227. // Special entry points required for inproc servers
  228. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  229. {
  230. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  231. return AfxDllGetClassObject(rclsid, riid, ppv);
  232. }
  233. STDAPI DllCanUnloadNow(void)
  234. {
  235. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  236. return AfxDllCanUnloadNow();
  237. }
  238. HRESULT UpdateRegistryFromResource(LPCOLESTR lpszRes,BOOL bRegister)
  239. {
  240. HRESULT hRes = S_OK;
  241. IRegistrar* p;
  242. hRes = CoCreateInstance(CLSID_Registrar, NULL, CLSCTX_INPROC_SERVER, IID_IRegistrar, (void**)&p);
  243. if( ! CHECKHRESULT(hRes) )
  244. {
  245. AfxMessageBox(_T("Could not create CLSID_Registrar ! Updated version of ATL.DLL is needed !"));
  246. return hRes;
  247. }
  248. else
  249. {
  250. TCHAR szModule[_MAX_PATH];
  251. GetModuleFileName(AfxGetInstanceHandle(), szModule, _MAX_PATH);
  252. BSTR szTemp = CString(szModule).AllocSysString();
  253. p->AddReplacement(OLESTR("Module"), szTemp );
  254. LPCOLESTR szType = OLESTR("REGISTRY");
  255. if( HIWORD(lpszRes) == 0 )
  256. {
  257. #ifndef IA64
  258. if (bRegister)
  259. hRes = p->ResourceRegister(szModule, ((UINT)LOWORD((DWORD)lpszRes)), szType);
  260. else
  261. hRes = p->ResourceRegister(szModule, ((UINT)LOWORD((DWORD)lpszRes)), szType);
  262. #endif // IA64
  263. }
  264. else
  265. {
  266. if (bRegister)
  267. hRes = p->ResourceRegisterSz(szModule, lpszRes, szType);
  268. else
  269. hRes = p->ResourceUnregisterSz(szModule, lpszRes, szType);
  270. }
  271. ::SysFreeString(szTemp);
  272. p->Release();
  273. }
  274. return hRes;
  275. }
  276. // by exporting DllRegisterServer, you can use regsvr.exe
  277. STDAPI DllRegisterServer(void)
  278. {
  279. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  280. if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
  281. return ResultFromScode(SELFREG_E_CLASS);
  282. HRESULT hRes = UpdateRegistryFromResource((LPCOLESTR)MAKEINTRESOURCE(IDR_REGISTRY),TRUE);
  283. if( hRes != S_OK )
  284. {
  285. return hRes;
  286. }
  287. return S_OK;
  288. }
  289. STDAPI DllUnregisterServer(void)
  290. {
  291. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  292. if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
  293. return ResultFromScode(SELFREG_E_CLASS);
  294. HRESULT hRes = UpdateRegistryFromResource((LPCOLESTR)MAKEINTRESOURCE(IDR_REGISTRY_UNREG),TRUE);
  295. if( hRes != S_OK )
  296. {
  297. return hRes;
  298. }
  299. // delete the HMSnapin.ini file
  300. CString sPath;
  301. GetWindowsDirectory(sPath.GetBuffer(_MAX_PATH+1),_MAX_PATH);
  302. sPath.ReleaseBuffer();
  303. sPath += _T("\\HMSnapin.ini");
  304. try
  305. {
  306. CFile::Remove(sPath);
  307. }
  308. catch(CException* pE)
  309. {
  310. pE->Delete();
  311. }
  312. return S_OK;
  313. }
  314. //*********************************************************
  315. // EscapeSpecialChars v-marfin bug 60233
  316. //*********************************************************
  317. CString CSnapInApp::EscapeSpecialChars(CString &refString)
  318. {
  319. // Convert any single backslashes to double backslashes.
  320. // Setup our return var.
  321. CString sRet;
  322. // get size of string so we don't call GetLength repeatedly
  323. int nSize=refString.GetLength();
  324. int x=0;
  325. // for each char in passed string, inspect and convert into ret val
  326. for (x=0; x<nSize; x++)
  327. {
  328. // Does this position have a backslash?
  329. if (refString.GetAt(x) == _T('\\'))
  330. {
  331. // Yes - Add 1 more backslash to the ret string before copying the
  332. // original
  333. sRet += _T('\\');
  334. }
  335. sRet += refString.GetAt(x);
  336. }
  337. return sRet;
  338. }
  339. //*********************************************************
  340. // UnEscapeSpecialChars v-marfin bug 60233
  341. //*********************************************************
  342. CString CSnapInApp::UnEscapeSpecialChars(CString &refString)
  343. {
  344. // Convert any double backslashes read from WMI into single
  345. // Setup our return var.
  346. CString sRet;
  347. // get size of string so we don't call GetLength repeatedly
  348. int nSize=refString.GetLength();
  349. int x=0;
  350. // for each char in passed string, inspect and convert into ret val
  351. while (x < nSize)
  352. {
  353. // Does this position have a double backslash?
  354. if (refString.Mid(x,2) == _T("\\\\"))
  355. {
  356. // Yes - only write 1 to the return string and increment our index by 2
  357. sRet += _T('\\');
  358. x += 2;
  359. }
  360. else
  361. {
  362. // No, just copy the char to the return string and increment index.
  363. sRet += refString.GetAt(x++);
  364. }
  365. }
  366. return sRet;
  367. }
  368. //****************************************************
  369. // ValidNamespace
  370. //****************************************************
  371. BOOL CSnapInApp::ValidNamespace(const CString &refNamespace, const CString& sMachine)
  372. {
  373. // If namespaces are empty, load.
  374. if (m_arrsNamespaces.GetSize() < 1)
  375. {
  376. // loads only once since it is static.
  377. CWaitCursor w;
  378. LoadNamespaceArray(_T("ROOT"),sMachine);
  379. }
  380. // scan namespace array
  381. int nSize = (int)m_arrsNamespaces.GetSize();
  382. for (int x=0; x<nSize; x++)
  383. {
  384. if (m_arrsNamespaces.GetAt(x).CompareNoCase(refNamespace)==0)
  385. return TRUE;
  386. }
  387. return FALSE; // not found. invalid.
  388. }
  389. //********************************************************************
  390. // LoadNamespaceArray
  391. //********************************************************************
  392. void CSnapInApp::LoadNamespaceArray(const CString& sNamespace, const CString& sMachine)
  393. {
  394. ULONG ulReturned = 0L;
  395. int i = 0;
  396. CWbemClassObject Namespaces;
  397. Namespaces.Create(sMachine);
  398. Namespaces.SetNamespace(sNamespace);
  399. CString sTemp = IDS_STRING_MOF_NAMESPACE;
  400. BSTR bsTemp = sTemp.AllocSysString();
  401. if( ! CHECKHRESULT(Namespaces.CreateEnumerator(bsTemp)) )
  402. {
  403. ::SysFreeString(bsTemp);
  404. return;
  405. }
  406. ::SysFreeString(bsTemp);
  407. // for each namespace
  408. while( Namespaces.GetNextObject(ulReturned) == S_OK && ulReturned )
  409. {
  410. CString sName;
  411. Namespaces.GetProperty(IDS_STRING_MOF_NAME,sName);
  412. CString sTemp2;
  413. Namespaces.GetProperty(IDS_STRING_MOF_NAMESPACE,sTemp2);
  414. // build namespace string
  415. CString sNamespaceFound = sTemp2 + _T("\\") + sName;
  416. // Add the namespace to the array
  417. m_arrsNamespaces.Add(sNamespaceFound);
  418. // call ourself recursively
  419. LoadNamespaceArray(sNamespaceFound,sMachine);
  420. }
  421. }