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.

1120 lines
33 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  4. //
  5. //***************************************************************************
  6. #include "wmicom.h"
  7. #include "wmimof.h"
  8. #include "wmimap.h"
  9. #include <stdlib.h>
  10. #include <winerror.h>
  11. #include <TCHAR.h>
  12. ////////////////////////////////////////////////////////////////////////////////////////////////
  13. //**********************************************************************************************
  14. // Global Utility Functions
  15. //**********************************************************************************************
  16. ////////////////////////////////////////////////////////////////////////////////////////////////
  17. BOOL IsBinaryMofResourceEvent(LPOLESTR pGuid, GUID gGuid)
  18. {
  19. HRESULT hr;
  20. GUID Guid;
  21. hr = CLSIDFromString(pGuid,&Guid);
  22. if( SUCCEEDED(hr) )
  23. {
  24. if( gGuid == Guid)
  25. {
  26. return TRUE;
  27. }
  28. }
  29. return FALSE;
  30. }
  31. /////////////////////////////////////////////////////////////////////
  32. BOOL GetParsedPropertiesAndClass( BSTR Query,WCHAR * wcsClass )
  33. {
  34. ParsedObjectPath * pParsedPath = NULL; // stdlibrary API
  35. CObjectPathParser Parser;
  36. BOOL fRc = FALSE;
  37. if( CObjectPathParser::NoError == Parser.Parse(Query, &pParsedPath))
  38. {
  39. try
  40. {
  41. // NTRaid:136400
  42. // 07/12/00
  43. if(pParsedPath && !IsBadReadPtr( pParsedPath, sizeof(ParsedObjectPath)))
  44. {
  45. KeyRef * pKeyRef = NULL;
  46. pKeyRef = *(pParsedPath->m_paKeys);
  47. if(!IsBadReadPtr( pKeyRef, sizeof(KeyRef)))
  48. {
  49. wcscpy(wcsClass,pParsedPath->m_pClass);
  50. fRc = TRUE;
  51. }
  52. }
  53. Parser.Free(pParsedPath);
  54. }
  55. catch(...)
  56. {
  57. Parser.Free(pParsedPath);
  58. throw;
  59. }
  60. }
  61. return fRc;
  62. }
  63. ////////////////////////////////////////////////////////////////////////////////////////////////
  64. HRESULT CheckIfThisIsAValidKeyProperty(WCHAR * wcsClass, WCHAR * wcsProperty, IWbemServices * p)
  65. {
  66. HRESULT hr = WBEM_E_FAILED;
  67. IWbemClassObject * pIHCO = NULL;
  68. IWbemQualifierSet * pIWbemQualifierSet = NULL;
  69. long lType = 0L;
  70. BSTR strPath = NULL;
  71. strPath = SysAllocString(wcsClass);
  72. if(strPath == NULL)
  73. {
  74. hr = E_OUTOFMEMORY;
  75. }
  76. else
  77. {
  78. hr = p->GetObject(strPath, 0,NULL, &pIHCO, NULL);
  79. SysFreeString(strPath);
  80. if (WBEM_S_NO_ERROR != hr)
  81. return WBEM_E_INVALID_CLASS;
  82. if(wcsProperty){
  83. hr = pIHCO->GetPropertyQualifierSet(wcsProperty,&pIWbemQualifierSet);
  84. if( SUCCEEDED(hr) ){
  85. CVARIANT v;
  86. hr = pIWbemQualifierSet->Get(L"key", 0, &v, 0);
  87. SAFE_RELEASE_PTR(pIWbemQualifierSet);
  88. }
  89. else{
  90. hr = WBEM_E_INVALID_OBJECT_PATH;
  91. }
  92. }
  93. //============================================================
  94. // Cleanup
  95. //============================================================
  96. SAFE_RELEASE_PTR(pIHCO);
  97. }
  98. return hr;
  99. }
  100. //====================================================================
  101. HRESULT GetParsedPath( BSTR ObjectPath,WCHAR * wcsClass, WCHAR * wcsInstance,IWbemServices * p )
  102. {
  103. //============================================================
  104. // Get the path and instance name and check to make sure it
  105. // is valid
  106. //============================================================
  107. ParsedObjectPath * pParsedPath = NULL; // stdlibrary API
  108. CObjectPathParser Parser;
  109. HRESULT hr = WBEM_E_FAILED;
  110. if( 0 == Parser.Parse(ObjectPath, &pParsedPath))
  111. {
  112. try
  113. {
  114. // NTRaid:136395
  115. // 07/12/00
  116. if(pParsedPath && !IsBadReadPtr( pParsedPath, sizeof(ParsedObjectPath)))
  117. {
  118. KeyRef * pKeyRef = NULL;
  119. pKeyRef = *(pParsedPath->m_paKeys);
  120. if( !IsBadReadPtr( pKeyRef, sizeof(KeyRef)))
  121. {
  122. hr = CheckIfThisIsAValidKeyProperty(pParsedPath->m_pClass, pKeyRef->m_pName,p );
  123. if( SUCCEEDED(hr) )
  124. {
  125. wcscpy(wcsClass,pParsedPath->m_pClass);
  126. wcscpy(wcsInstance,pKeyRef->m_vValue.bstrVal);
  127. }
  128. }
  129. }
  130. Parser.Free(pParsedPath);
  131. }
  132. catch(...)
  133. {
  134. hr = WBEM_E_UNEXPECTED;
  135. Parser.Free(pParsedPath);
  136. throw;
  137. }
  138. }
  139. return hr;
  140. }
  141. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. BOOL GetUserThreadToken(HANDLE * phThreadTok)
  143. {
  144. BOOL fRc = FALSE;
  145. HRESULT hRes = WbemCoImpersonateClient();
  146. if (SUCCEEDED(hRes))
  147. {
  148. // Now, let's check the impersonation level. First, get the thread token
  149. if (!OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, phThreadTok))
  150. {
  151. // If the CoImpersonate works, but the OpenThreadToken fails, we are running under the
  152. // process token (either local system, or if we are running with /exe, the rights of
  153. // the logged in user). In either case, impersonation rights don't apply. We have the
  154. // full rights of that user.
  155. if(GetLastError() == ERROR_NO_TOKEN)
  156. {
  157. // Try getting the thread token. If it fails it's because we're a system thread and
  158. // we don't yet have a thread token, so just impersonate self and try again.
  159. if( ImpersonateSelf(SecurityImpersonation) )
  160. {
  161. if (!OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, phThreadTok))
  162. {
  163. fRc = FALSE;
  164. }
  165. else
  166. {
  167. fRc = TRUE;
  168. }
  169. }
  170. else
  171. {
  172. ERRORTRACE((THISPROVIDER,"ImpersonateSelf(SecurityImpersonation)failed"));
  173. }
  174. }
  175. }
  176. else
  177. {
  178. fRc = TRUE;
  179. }
  180. }
  181. if( !fRc )
  182. {
  183. ERRORTRACE((THISPROVIDER,IDS_ImpersonationFailed));
  184. }
  185. return fRc;
  186. }
  187. ////////////////////////////////////////////////////////////////////////////////////////////////
  188. SAFEARRAY * OMSSafeArrayCreate( IN VARTYPE vt, IN int iNumElements)
  189. {
  190. if(iNumElements < 1)
  191. {
  192. return NULL;
  193. }
  194. SAFEARRAYBOUND rgsabound[1];
  195. rgsabound[0].lLbound = 0;
  196. rgsabound[0].cElements = iNumElements;
  197. return SafeArrayCreate(vt,1,rgsabound);
  198. }
  199. ////////////////////////////////////////////////////////////////////////////////////////////////
  200. void TranslateAndLog( WCHAR * wcsMsg )
  201. {
  202. CAnsiUnicode XLate;
  203. char * pStr = NULL;
  204. if( SUCCEEDED(XLate.UnicodeToAnsi(wcsMsg,pStr)))
  205. {
  206. ERRORTRACE((THISPROVIDER,pStr));
  207. ERRORTRACE((THISPROVIDER,"\n"));
  208. SAFE_DELETE_ARRAY(pStr);
  209. }
  210. }
  211. /////////////////////////////////////////////////////////////////////////////////////////////////
  212. bool IsNT(void)
  213. {
  214. OSVERSIONINFO os;
  215. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  216. if(!GetVersionEx(&os))
  217. return FALSE; // should never happen
  218. return os.dwPlatformId == VER_PLATFORM_WIN32_NT;
  219. }
  220. ////////////////////////////////////////////////////////////////////
  221. BOOL SetGuid(WCHAR * pwcsGuidString, CLSID & Guid)
  222. {
  223. BOOL fRc = FALSE;
  224. CAutoWChar wcsGuid(MAX_PATH+2);
  225. if( wcsGuid.Valid() )
  226. {
  227. fRc = TRUE;
  228. swprintf(wcsGuid,L"{%s}",pwcsGuidString );
  229. if(FAILED(CLSIDFromString(wcsGuid, &Guid)))
  230. {
  231. if( FAILED(CLSIDFromString(pwcsGuidString, &Guid)))
  232. {
  233. fRc = FALSE;
  234. }
  235. }
  236. }
  237. return fRc;
  238. }
  239. ////////////////////////////////////////////////////////////////////
  240. HRESULT AllocAndCopy(WCHAR * wcsSource, WCHAR ** pwcsDest )
  241. {
  242. HRESULT hr = WBEM_E_FAILED;
  243. int nLen = wcslen(wcsSource);
  244. if( nLen > 0 )
  245. {
  246. *pwcsDest = new WCHAR[nLen + 2 ];
  247. if( *pwcsDest )
  248. {
  249. wcscpy(*pwcsDest,wcsSource);
  250. hr = S_OK;
  251. }
  252. }
  253. return hr;
  254. }
  255. ////////////////////////////////////////////////////////////////////////////////////////////////
  256. //**********************************************************************************************
  257. // Utility Classes
  258. //**********************************************************************************************
  259. ////////////////////////////////////////////////////////////////////////////////////////////////
  260. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  261. void _WMIHandleMap::AddRef()
  262. {
  263. InterlockedIncrement((long*)&RefCount);
  264. }
  265. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  266. long _WMIHandleMap::Release()
  267. {
  268. ULONG cRef = InterlockedDecrement( (long*) &RefCount);
  269. if ( !cRef ){
  270. WmiCloseBlock(WMIHandle);
  271. return 0;
  272. }
  273. return cRef;
  274. }
  275. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  276. _WMIEventRequest::_WMIEventRequest()
  277. {
  278. pwcsClass = NULL ;
  279. pHandler = NULL;
  280. pServices = NULL;
  281. pCtx = NULL;
  282. }
  283. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  284. _WMIEventRequest::~_WMIEventRequest()
  285. {
  286. SAFE_RELEASE_PTR(pServices);
  287. SAFE_RELEASE_PTR(pCtx);
  288. SAFE_DELETE_ARRAY(pwcsClass);
  289. }
  290. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  291. void _WMIEventRequest::AddPtrs( IWbemObjectSink __RPC_FAR * Handler,IWbemServices __RPC_FAR * Services,IWbemContext __RPC_FAR * Ctx)
  292. {
  293. pHandler = Handler;
  294. pServices = Services;
  295. pCtx = Ctx;
  296. if( pServices ){
  297. pServices->AddRef();
  298. }
  299. if( pCtx ){
  300. pCtx->AddRef();
  301. }
  302. return;
  303. }
  304. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  305. _AccessList::~_AccessList()
  306. {
  307. for( int i = 0; i < m_List.Size(); i++ )
  308. {
  309. IWbemObjectAccess * pPtr = (IWbemObjectAccess *)m_List[i];
  310. SAFE_RELEASE_PTR(pPtr);
  311. }
  312. m_List.Empty();
  313. }
  314. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  315. _IdList::~_IdList()
  316. {
  317. for( int i = 0; i < m_List.Size(); i++ )
  318. {
  319. ULONG_PTR* pPtr = (ULONG_PTR*)m_List[i];
  320. SAFE_DELETE_PTR(pPtr);
  321. }
  322. m_List.Empty();
  323. }
  324. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  325. _HandleList::~_HandleList()
  326. {
  327. for( int i = 0; i < m_List.Size(); i++ )
  328. {
  329. HANDLE * pPtr = (HANDLE*)m_List[i];
  330. SAFE_DELETE_PTR(pPtr);
  331. }
  332. m_List.Empty();
  333. }
  334. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  335. _InstanceList::~_InstanceList()
  336. {
  337. for( int i = 0; i < m_List.Size(); i++ )
  338. {
  339. WCHAR * p = (WCHAR*)m_List[i];
  340. SAFE_DELETE_ARRAY(p);
  341. }
  342. m_List.Empty();
  343. }
  344. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  345. _OldClassInfo::~_OldClassInfo()
  346. {
  347. SAFE_DELETE_ARRAY(m_pClass);
  348. SAFE_DELETE_ARRAY(m_pPath);
  349. m_pClass = m_pPath = NULL;
  350. }
  351. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  352. _OldClassList::~_OldClassList()
  353. {
  354. for( int i = 0; i < m_List.Size(); i++ )
  355. {
  356. OldClassInfo * p = (OldClassInfo*)m_List[i];
  357. SAFE_DELETE_PTR(p);
  358. }
  359. m_List.Empty();
  360. }
  361. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  362. _WMIHiPerfHandleMap::_WMIHiPerfHandleMap(CWMIProcessClass * p, IWbemHiPerfEnum * pEnum)
  363. {
  364. m_pEnum = pEnum;
  365. if( pEnum )
  366. {
  367. pEnum->AddRef();
  368. }
  369. m_pClass = p;
  370. m_fEnumerator = FALSE;
  371. lHiPerfId = 0;
  372. }
  373. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  374. _WMIHiPerfHandleMap::~_WMIHiPerfHandleMap()
  375. {
  376. SAFE_RELEASE_PTR(m_pEnum);
  377. lHiPerfId = 0;
  378. SAFE_DELETE_PTR(m_pClass);
  379. }
  380. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  381. // Hi Perf Handle Map = Handles are addref'd and when released, then the block is closed
  382. // Critical Sections are handled elsewhere
  383. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  384. HRESULT CHiPerfHandleMap::Add( HANDLE hCurrent, ULONG_PTR lHiPerfId, CWMIProcessClass * p, IWbemHiPerfEnum * pEnum)
  385. {
  386. HRESULT hr = S_OK;
  387. WMIHiPerfHandleMap * pWMIMap = new WMIHiPerfHandleMap(p,pEnum);
  388. if( pWMIMap )
  389. {
  390. try
  391. {
  392. pWMIMap->WMIHandle = hCurrent;
  393. pWMIMap->lHiPerfId = lHiPerfId;
  394. // 170635
  395. if(CFlexArray::out_of_memory == m_List.Add(pWMIMap))
  396. {
  397. SAFE_DELETE_PTR(pWMIMap);
  398. hr = E_OUTOFMEMORY;
  399. }
  400. }
  401. catch(...)
  402. {
  403. hr = WBEM_E_UNEXPECTED;
  404. SAFE_DELETE_PTR(pWMIMap);
  405. throw;
  406. }
  407. }
  408. return hr;
  409. }
  410. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  411. HRESULT CHiPerfHandleMap::FindHandleAndGetClassPtr( HANDLE & hCurrent, ULONG_PTR lHiPerfId,CWMIProcessClass *& p)
  412. {
  413. HRESULT hr = WBEM_E_NOT_FOUND;
  414. for( int i=0; i<m_List.Size(); i++)
  415. {
  416. //===================================================
  417. //
  418. //===================================================
  419. WMIHiPerfHandleMap * pMap = (WMIHiPerfHandleMap *) m_List[i];
  420. if( pMap->lHiPerfId == lHiPerfId )
  421. {
  422. hCurrent = pMap->WMIHandle;
  423. p = pMap->m_pClass;
  424. hr = S_OK;
  425. }
  426. }
  427. return hr;
  428. }
  429. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  430. HRESULT CHiPerfHandleMap::GetFirstHandle(HANDLE & hCurrent,CWMIProcessClass *& p, IWbemHiPerfEnum *& pEnum)
  431. {
  432. m_nIndex=0;
  433. return GetNextHandle(hCurrent,p,pEnum);
  434. }
  435. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  436. HRESULT CHiPerfHandleMap::GetNextHandle(HANDLE & hCurrent,CWMIProcessClass *& p, IWbemHiPerfEnum *& pEnum)
  437. {
  438. HRESULT hr = WBEM_S_NO_MORE_DATA;
  439. if( m_nIndex < m_List.Size() )
  440. {
  441. WMIHiPerfHandleMap * pMap = (WMIHiPerfHandleMap *) m_List[m_nIndex];
  442. hCurrent = pMap->WMIHandle;
  443. p = pMap->m_pClass;
  444. pEnum = pMap->m_pEnum;
  445. m_nIndex++;
  446. hr = S_OK;
  447. }
  448. return hr;
  449. }
  450. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  451. HRESULT CHiPerfHandleMap::Delete( HANDLE & hCurrent, ULONG_PTR lHiPerfId )
  452. {
  453. HRESULT hr = WBEM_E_NOT_FOUND;
  454. for( int i=0; i<m_List.Size(); i++)
  455. {
  456. //===================================================
  457. //
  458. //===================================================
  459. WMIHiPerfHandleMap * pMap = (WMIHiPerfHandleMap *) m_List[i];
  460. if( pMap->lHiPerfId == lHiPerfId )
  461. {
  462. hCurrent = pMap->WMIHandle;
  463. SAFE_DELETE_PTR(pMap);
  464. m_List.RemoveAt(i);
  465. hr = S_OK;
  466. break;
  467. }
  468. }
  469. return hr;
  470. }
  471. ////////////////////////////////////////////////////////////////////////////////////////////////
  472. // When this function is called, release all the handles kept
  473. // THis function is called in the destructor of the class to release all teh WMIHiPerfHandleMap
  474. // classes allocated
  475. ////////////////////////////////////////////////////////////////////////////////////////////////
  476. void CHiPerfHandleMap::CloseAndReleaseHandles()
  477. {
  478. //===================================
  479. // Go through the handles one at
  480. // a time and close them, then
  481. // delete the records from the
  482. // array
  483. //===================================
  484. CAutoBlock((CCriticalSection *)&m_HandleCs);
  485. if( m_List.Size() > 0 ){
  486. for(int i = 0; i < m_List.Size(); i++){
  487. WMIHiPerfHandleMap * pWMIMap = (WMIHiPerfHandleMap *) m_List[i];
  488. SAFE_DELETE_PTR(pWMIMap);
  489. }
  490. //==================================================
  491. // Remove it and deallocate memory
  492. //==================================================
  493. m_List.Empty();
  494. }
  495. }
  496. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  497. // Regular Handle Map = Expensize handles are always kept open - by default we, dont' know the lifetime
  498. // of these handles
  499. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  500. HRESULT CHandleMap::Add(CLSID Guid, HANDLE hCurrent, ULONG uDesiredAccess)
  501. {
  502. // Critical section is called elsewhere
  503. HRESULT hr = S_OK;
  504. WMIHandleMap * pWMIMap = new WMIHandleMap();
  505. if( pWMIMap )
  506. {
  507. try
  508. {
  509. pWMIMap->AddRef(); // Used for HiPerf counts, otherwise not referenced
  510. pWMIMap->WMIHandle = hCurrent;
  511. pWMIMap->Guid = Guid;
  512. pWMIMap->uDesiredAccess = uDesiredAccess;
  513. // 170635
  514. if(CFlexArray::out_of_memory == m_List.Add(pWMIMap))
  515. {
  516. hr = E_OUTOFMEMORY;
  517. SAFE_DELETE_PTR(pWMIMap);
  518. }
  519. }
  520. catch(...)
  521. {
  522. hr = WBEM_E_UNEXPECTED;
  523. SAFE_DELETE_PTR(pWMIMap);
  524. throw;
  525. }
  526. }
  527. return hr;
  528. }
  529. ////////////////////////////////////////////////////////////////////////////////////////////////
  530. int CHandleMap::ExistingHandleAlreadyExistsForThisGuidUseIt(CLSID Guid,
  531. HANDLE & hCurrentWMIHandle,
  532. BOOL & fCloseHandle,
  533. ULONG uDesiredAccess)
  534. {
  535. int nRc = ERROR_NOT_SUPPORTED;
  536. // Critical section is called elsewhere
  537. //=====================================================
  538. // Initialize stuff
  539. //=====================================================
  540. hCurrentWMIHandle = 0;
  541. fCloseHandle = TRUE;
  542. for(int i = 0; i < m_List.Size(); i++){
  543. WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
  544. //==================================================
  545. // Compare and see if this guid already has a
  546. // handle assigned for it with the access permissions
  547. // that we want to use
  548. //==================================================
  549. if( pWMIMap->Guid == Guid ){
  550. if( pWMIMap->uDesiredAccess == uDesiredAccess ){
  551. hCurrentWMIHandle = pWMIMap->WMIHandle;
  552. pWMIMap->AddRef(); // Used for HiPerf Handles, otherwise not needed
  553. nRc = ERROR_SUCCESS;
  554. fCloseHandle = FALSE;
  555. break;
  556. }
  557. }
  558. }
  559. return nRc;
  560. }
  561. ////////////////////////////////////////////////////////////////////////////////////////////////
  562. // When this function is called, we need to close all of the handles that may have been kept
  563. // open for accumulation purposes
  564. ////////////////////////////////////////////////////////////////////////////////////////////////
  565. void CHandleMap::CloseAllOutstandingWMIHandles()
  566. {
  567. //===================================
  568. // Go through the handles one at
  569. // a time and close them, then
  570. // delete the records from the
  571. // array
  572. //===================================
  573. CAutoBlock((CCriticalSection *)&m_HandleCs);
  574. if( m_List.Size() > 0 ){
  575. for(int i = 0; i < m_List.Size(); i++){
  576. WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
  577. //==================================================
  578. // Inform WMI we are done with this guy
  579. //==================================================
  580. try
  581. {
  582. WmiCloseBlock(pWMIMap->WMIHandle);
  583. }
  584. catch(...)
  585. {
  586. // don't throw
  587. }
  588. SAFE_DELETE_PTR(pWMIMap);
  589. }
  590. //==================================================
  591. // Remove it and deallocate memory
  592. //==================================================
  593. m_List.Empty();
  594. }
  595. }
  596. ////////////////////////////////////////////////////////////////////////////////////////////////
  597. // Used when we know the handles lifetimes
  598. ////////////////////////////////////////////////////////////////////////////////////////////////
  599. int CHandleMap::ReleaseHandle( HANDLE hCurrentWMIHandle )
  600. {
  601. int nRc = ERROR_NOT_SUPPORTED;
  602. CAutoBlock((CCriticalSection *)&m_HandleCs);
  603. for(int i = 0; i < m_List.Size(); i++){
  604. WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
  605. if( pWMIMap->WMIHandle == hCurrentWMIHandle )
  606. {
  607. long RefCount = pWMIMap->Release(); // Used for HiPerf Handles, otherwise not needed
  608. if( !RefCount )
  609. {
  610. // WmiCloseBlock(hCurrentWMIHandle);
  611. SAFE_DELETE_PTR( pWMIMap);
  612. m_List.RemoveAt(i);
  613. }
  614. nRc = ERROR_SUCCESS;
  615. break;
  616. }
  617. }
  618. return nRc;
  619. }
  620. ////////////////////////////////////////////////////////////////////////////////////////////////
  621. int CHandleMap::GetHandle(CLSID Guid, HANDLE & hCurrentWMIHandle )
  622. {
  623. int nRc = ERROR_NOT_SUPPORTED;
  624. CAutoBlock((CCriticalSection *)&m_HandleCs);
  625. //=====================================================
  626. // Initialize stuff
  627. //=====================================================
  628. hCurrentWMIHandle = 0;
  629. for(int i = 0; i < m_List.Size(); i++){
  630. WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
  631. if( pWMIMap->Guid == Guid ){
  632. hCurrentWMIHandle = pWMIMap->WMIHandle;
  633. pWMIMap->AddRef(); // Used for HiPerf Handles, otherwise not needed
  634. nRc = ERROR_SUCCESS;
  635. break;
  636. }
  637. }
  638. return nRc;
  639. }
  640. ////////////////////////////////////////////////////////////////////////////////////////////////
  641. //**********************************************************************************************
  642. // Utility Classes: CANSIUNICODE
  643. //**********************************************************************************************
  644. ////////////////////////////////////////////////////////////////////////////////////////////////
  645. HRESULT CAnsiUnicode::AllocateAndConvertAnsiToUnicode(char * pstr, WCHAR *& pszW)
  646. {
  647. HRESULT hr = WBEM_E_FAILED;
  648. pszW = NULL;
  649. int nSize = strlen(pstr);
  650. if (nSize != 0 ){
  651. // Determine number of wide characters to be allocated for the
  652. // Unicode string.
  653. nSize++;
  654. pszW = new WCHAR[nSize * 2];
  655. if (NULL != pszW){
  656. try
  657. {
  658. // Covert to Unicode.
  659. MultiByteToWideChar(CP_ACP, 0, pstr, nSize,pszW,nSize);
  660. hr = S_OK;
  661. }
  662. catch(...)
  663. {
  664. SAFE_DELETE_ARRAY(pszW);
  665. hr = WBEM_E_UNEXPECTED;
  666. throw;
  667. }
  668. }
  669. }
  670. return hr;
  671. }
  672. ////////////////////////////////////////////////////////////////////
  673. HRESULT CAnsiUnicode::UnicodeToAnsi(WCHAR * pszW, char *& pAnsi)
  674. {
  675. ULONG cbAnsi, cCharacters;
  676. HRESULT hr = WBEM_E_FAILED;
  677. pAnsi = NULL;
  678. if (pszW != NULL){
  679. cCharacters = wcslen(pszW)+1;
  680. // Determine number of bytes to be allocated for ANSI string. An
  681. // ANSI string can have at most 2 bytes per character (for Double
  682. // Byte Character Strings.)
  683. cbAnsi = cCharacters*2;
  684. pAnsi = new char[cbAnsi];
  685. if (NULL != pAnsi)
  686. {
  687. try
  688. {
  689. // Convert to ANSI.
  690. if (0 != WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, pAnsi, cbAnsi, NULL, NULL)){
  691. hr = S_OK;
  692. }
  693. }
  694. catch(...)
  695. {
  696. SAFE_DELETE_ARRAY(pAnsi);
  697. hr = WBEM_E_UNEXPECTED;
  698. throw;
  699. }
  700. }
  701. }
  702. return hr;
  703. }
  704. //************************************************************************************************************
  705. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  706. //
  707. // CWMIManagement
  708. //
  709. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  710. //************************************************************************************************************
  711. CWMIManagement::CWMIManagement( )
  712. {
  713. m_pHandler = NULL;
  714. m_pServices = NULL;
  715. m_pCtx = NULL;
  716. m_pHandleMap = NULL;
  717. }
  718. //////////////////////////////////////////////////////////////////////////////////////
  719. CWMIManagement::~CWMIManagement()
  720. {
  721. }
  722. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  723. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  724. void CWMIManagement::SendPrivilegeExtendedErrorObject( HRESULT hrToReturn,WCHAR * wcsClass)
  725. {
  726. HRESULT hr,hRes;
  727. IWbemClassObject * pClass = NULL, *pInst=NULL;
  728. BOOL fSetStatus = FALSE;
  729. if( hrToReturn == WBEM_E_ACCESS_DENIED ){
  730. TOKEN_PRIVILEGES * ptPriv = NULL;
  731. hr = GetListOfUserPrivileges(ptPriv);
  732. if( SUCCEEDED(hr ) ){
  733. BSTR strPrivelegeStat = NULL;
  734. strPrivelegeStat = SysAllocString(L"Win32_PrivilegesStatus");
  735. if(strPrivelegeStat != NULL)
  736. {
  737. hr = m_pServices->GetObject(strPrivelegeStat, 0,m_pCtx, &pClass, NULL);
  738. if( hr == S_OK){
  739. //=============================================================
  740. // Get an instance of the extended class
  741. //=============================================================
  742. hr = pClass->SpawnInstance(0,&pInst);
  743. SAFE_RELEASE_PTR(pClass);
  744. if( pInst ){
  745. CVARIANT varTmp;
  746. WCHAR * pwcsStr = NULL;
  747. CAnsiUnicode XLate;
  748. //=========================================================
  749. // Fill in description
  750. //=========================================================
  751. XLate.AllocateAndConvertAnsiToUnicode(IDS_ImpersonationFailed,pwcsStr);
  752. varTmp.SetStr(pwcsStr);
  753. hr = pInst->Put(L"Description", 0, &varTmp, NULL);
  754. SAFE_DELETE_ARRAY( pwcsStr );
  755. //======================================================
  756. // Initialize all of the necessary stuff and get the
  757. // definition of the class we are working with
  758. //======================================================
  759. CWMIProcessClass ClassInfo(0);
  760. if( SUCCEEDED(ClassInfo.Initialize()) )
  761. {
  762. ClassInfo.WMI()->SetWMIPointers(m_pHandleMap,m_pServices,m_pHandler,m_pCtx);
  763. ClassInfo.SetClass(wcsClass);
  764. SAFEARRAY *psaPrivNotHeld=NULL;
  765. SAFEARRAY *psaPrivReq=NULL;
  766. //=========================================================
  767. // Get PrivilegesRequired
  768. // The only place to get this, if possible, is from the
  769. // class
  770. //=========================================================
  771. hRes = ClassInfo.GetPrivilegesQualifer(&psaPrivReq);
  772. if( hRes == WBEM_S_NO_ERROR){
  773. //=========================================================
  774. // Get PrivilegesNotHeld
  775. //=========================================================
  776. ProcessPrivileges(ptPriv,psaPrivNotHeld,psaPrivReq);
  777. //=========================================================
  778. // Send it off
  779. //=========================================================
  780. VARIANT v;
  781. if( psaPrivReq ){
  782. VariantInit(&v);
  783. SAFEARRAY *pSafeArray = NULL;
  784. if ( SUCCEEDED ( SafeArrayCopy ((SAFEARRAY*)psaPrivReq , &pSafeArray ) ) ){
  785. v.vt = VT_BSTR | VT_ARRAY;
  786. v.parray = pSafeArray;
  787. pInst->Put(L"PrivilegesRequired", 0, &v, NULL);
  788. VariantClear(&v);
  789. }
  790. }
  791. if( psaPrivNotHeld ){
  792. VariantInit(&v);
  793. SAFEARRAY *pSafeArray = NULL;
  794. if ( SUCCEEDED ( SafeArrayCopy ((SAFEARRAY*)psaPrivNotHeld , &pSafeArray ) ) ){
  795. v.vt = VT_BSTR | VT_ARRAY;
  796. v.parray = pSafeArray;
  797. pInst->Put(L"PrivilegesNotHeld", 0, &v, NULL);
  798. VariantClear(&v);
  799. }
  800. }
  801. }
  802. //=========================================================
  803. // Now, send this guy off...
  804. //=========================================================
  805. fSetStatus = TRUE;
  806. hr = m_pHandler->SetStatus(0,hrToReturn,NULL,pInst);
  807. if (psaPrivNotHeld)
  808. SafeArrayDestroy(psaPrivNotHeld);
  809. if (psaPrivReq)
  810. SafeArrayDestroy(psaPrivReq);
  811. }
  812. }
  813. SAFE_RELEASE_PTR(pInst);
  814. }
  815. SysFreeString(strPrivelegeStat);
  816. }
  817. }
  818. SAFE_DELETE_ARRAY(ptPriv);
  819. }
  820. if( !fSetStatus ){
  821. hr = m_pHandler->SetStatus(0,hrToReturn,NULL,NULL);
  822. }
  823. }
  824. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  825. HRESULT CWMIManagement::SetErrorMessage(HRESULT hrToReturn,WCHAR * wcsClass,WCHAR * wcsMsg)
  826. {
  827. HRESULT hr;
  828. IWbemClassObject * pClass = NULL, *pInst=NULL;
  829. BOOL fSetStatus = FALSE;
  830. if( m_pHandler )
  831. {
  832. BSTR strExtendedStat = NULL;
  833. switch( hrToReturn ){
  834. case WBEM_E_ACCESS_DENIED:
  835. SendPrivilegeExtendedErrorObject(hrToReturn,wcsClass);
  836. break;
  837. case S_OK :
  838. hr = m_pHandler->SetStatus(0,hrToReturn,NULL,NULL);
  839. break;
  840. default:
  841. strExtendedStat = SysAllocString(L"__ExtendedStatus");
  842. if(strExtendedStat != NULL)
  843. {
  844. hr = m_pServices->GetObject(strExtendedStat, 0,m_pCtx, &pClass, NULL);
  845. if( hr == S_OK){
  846. hr = pClass->SpawnInstance(0,&pInst);
  847. if( pInst ){
  848. CVARIANT varTmp;
  849. varTmp.SetStr(wcsMsg);
  850. hr = pInst->Put(L"Description", 0, &varTmp, NULL);
  851. hr = m_pHandler->SetStatus(0,hrToReturn,NULL,pInst);
  852. fSetStatus = TRUE;
  853. // Now log the error in the error log
  854. if( hrToReturn != S_OK ){
  855. TranslateAndLog(varTmp.GetStr());
  856. }
  857. }
  858. }
  859. if( !fSetStatus ){
  860. hr = m_pHandler->SetStatus(0,hrToReturn,NULL,NULL);
  861. }
  862. SAFE_RELEASE_PTR(pClass);
  863. SAFE_RELEASE_PTR(pInst);
  864. SysFreeString(strExtendedStat);
  865. }
  866. else
  867. {
  868. hr = E_OUTOFMEMORY;
  869. }
  870. break;
  871. }
  872. }
  873. return hrToReturn;
  874. }
  875. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  876. HRESULT CWMIManagement::GetListOfUserPrivileges(TOKEN_PRIVILEGES *& ptPriv)
  877. {
  878. HRESULT hr = WBEM_E_FAILED;
  879. // Get the privileges this user has
  880. DWORD dwTokenInfoLength = 0;
  881. DWORD dwSize = 0;
  882. HANDLE hThreadTok;
  883. if (IsNT()){
  884. if( GetUserThreadToken(&hThreadTok) ){
  885. // get information
  886. if (!GetTokenInformation(hThreadTok, TokenPrivileges, NULL, dwTokenInfoLength, &dwSize)){
  887. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER){
  888. ptPriv = new TOKEN_PRIVILEGES[dwSize+2];
  889. if( ptPriv )
  890. {
  891. try
  892. {
  893. dwTokenInfoLength = dwSize;
  894. if(GetTokenInformation(hThreadTok, TokenPrivileges, (LPVOID)ptPriv, dwTokenInfoLength, &dwSize))
  895. {
  896. hr = WBEM_NO_ERROR;
  897. }
  898. }
  899. catch(...)
  900. {
  901. SAFE_DELETE_ARRAY(ptPriv);
  902. hr = WBEM_E_UNEXPECTED;
  903. throw;
  904. }
  905. }
  906. }
  907. }
  908. // Done with this handle
  909. CloseHandle(hThreadTok);
  910. }
  911. }
  912. return hr;
  913. }
  914. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  915. void CWMIManagement::ProcessPrivileges(TOKEN_PRIVILEGES *ptPriv, SAFEARRAY *& psaPrivNotHeld, SAFEARRAY * psaPrivReq )
  916. {
  917. CAnsiUnicode XLate;
  918. BOOL fFound = FALSE;
  919. //==============================================================
  920. // Create a temporary working array, we know the MAX can be
  921. // the number of priv held + the number of priv req, so
  922. // allocate it for that
  923. //==============================================================
  924. CSAFEARRAY PrivReq( psaPrivReq );
  925. long lMax = PrivReq.GetNumElements()+ptPriv->PrivilegeCount;
  926. psaPrivNotHeld = OMSSafeArrayCreate(VT_BSTR,lMax);
  927. long nCurrentIndex = 0;
  928. //==============================================================
  929. // Get how many privs are not held
  930. //==============================================================
  931. for( long n = 0; n < PrivReq.GetNumElements(); n++ ){
  932. //==============================================================
  933. // Now, get the privileges held array ready to put stuff in
  934. //==============================================================
  935. TCHAR * pPrivReq = NULL;
  936. CBSTR bstr;
  937. if( S_OK != PrivReq.Get(n, &bstr)){
  938. return;
  939. }
  940. fFound = FALSE;
  941. #ifndef UNICODE
  942. XLate.UnicodeToAnsi(bstr,pPrivReq);
  943. #else
  944. pPrivReq = (TCHAR *)bstr;
  945. #endif
  946. // NTRaid:136384
  947. // 07/12/00
  948. if(pPrivReq)
  949. {
  950. for(int i=0;i < (int)ptPriv->PrivilegeCount;i++){
  951. DWORD dwPriv=128;
  952. TCHAR szPriv[NAME_SIZE*2];
  953. if( LookupPrivilegeName( NULL, &ptPriv->Privileges[i].Luid, szPriv, &dwPriv)){
  954. //==============================================
  955. // If we found the privilege, then the user has
  956. // it. break out
  957. //==============================================
  958. if( _tcscmp( pPrivReq,pPrivReq ) == 0 ){
  959. fFound = TRUE;
  960. break;
  961. }
  962. }
  963. //==================================================
  964. // If we didn't find it, then we need to add it to
  965. // the list so we can notify the user
  966. //==================================================
  967. if( !fFound ){
  968. if( S_OK == SafeArrayPutElement(psaPrivNotHeld, &nCurrentIndex, bstr))
  969. {
  970. nCurrentIndex++;
  971. }
  972. }
  973. }
  974. }
  975. #ifndef UNICODE
  976. SAFE_DELETE_ARRAY(pPrivReq);
  977. #else
  978. pPrivReq = NULL;
  979. #endif
  980. }
  981. SAFEARRAYBOUND rgsabound[1];
  982. rgsabound[0].lLbound = 0;
  983. rgsabound[0].cElements = nCurrentIndex;
  984. HRESULT hr = SafeArrayRedim(psaPrivNotHeld, rgsabound);
  985. PrivReq.Unbind();
  986. }