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.

643 lines
16 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: cumicurs.cxx
  7. //
  8. // Contents: Contains the UMI cursor object implementation
  9. //
  10. // History: 03-16-00 SivaramR Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "winnt.hxx"
  14. //----------------------------------------------------------------------------
  15. // Function: CreateCursor
  16. //
  17. // Synopsis: Creates a cursor object. Called by IUmiContainer::CreateEnum().
  18. //
  19. // Arguments:
  20. //
  21. // pCredentials Credentials of the UMI object creating the cursor
  22. // pCont Pointer to container on which CreateEnum was called
  23. // iid Interface requested. Only interface supported is IUmiCursor.
  24. // ppInterface Returns pointer to interface requested
  25. //
  26. // Returns: S_OK on success. Error code otherwise.
  27. //
  28. // Modifies: *ppInterface to return a pointer to the interface requested
  29. //
  30. //----------------------------------------------------------------------------
  31. HRESULT CUmiCursor::CreateCursor(
  32. CWinNTCredentials *pCredentials,
  33. IUnknown *pCont,
  34. REFIID iid,
  35. LPVOID *ppInterface
  36. )
  37. {
  38. CUmiCursor *pCursor = NULL;
  39. HRESULT hr = S_OK;
  40. ADsAssert(ppInterface != NULL);
  41. ADsAssert(pCont != NULL);
  42. pCursor = new CUmiCursor();
  43. if(NULL == pCursor)
  44. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  45. // initialize cursor object
  46. hr = pCursor->FInit(pCont, pCredentials);
  47. BAIL_ON_FAILURE(hr);
  48. hr = pCursor->QueryInterface(iid, ppInterface);
  49. BAIL_ON_FAILURE(hr);
  50. pCursor->Release();
  51. RRETURN(S_OK);
  52. error:
  53. if(pCursor != NULL)
  54. delete pCursor;
  55. RRETURN(hr);
  56. }
  57. //----------------------------------------------------------------------------
  58. // Function: CUmiCursor
  59. //
  60. // Synopsis: Constructor. Initializes all member variables
  61. //
  62. // Arguments:
  63. //
  64. // None
  65. //
  66. // Returns: Nothing.
  67. //
  68. // Modifies: Nothing.
  69. //
  70. //----------------------------------------------------------------------------
  71. CUmiCursor::CUmiCursor(void)
  72. {
  73. m_pIUmiPropList = NULL;
  74. m_ulErrorStatus = 0;
  75. m_pUnkInner = NULL;
  76. m_pIID = NULL;
  77. m_pEnumerator = NULL;
  78. }
  79. //----------------------------------------------------------------------------
  80. // Function: ~CUmiCursor
  81. //
  82. // Synopsis: Destructor. Frees member variables
  83. //
  84. // Arguments:
  85. //
  86. // None
  87. //
  88. // Returns: Nothing.
  89. //
  90. // Modifies: Nothing.
  91. //
  92. //----------------------------------------------------------------------------
  93. CUmiCursor::~CUmiCursor(void)
  94. {
  95. if(m_pIUmiPropList != NULL)
  96. m_pIUmiPropList->Release();
  97. if(m_pUnkInner != NULL)
  98. m_pUnkInner->Release();
  99. if(m_pIID != NULL)
  100. FreeADsMem(m_pIID);
  101. if(m_pEnumerator != NULL)
  102. m_pEnumerator->Release();
  103. }
  104. //----------------------------------------------------------------------------
  105. // Function: FInit
  106. //
  107. // Synopsis: Initializes cursor object.
  108. //
  109. // Arguments:
  110. //
  111. // pCont Pointer to UMI container that created this cursor.
  112. // pCredentials Credentials of UMI object creating the cursor
  113. //
  114. // Returns: S_OK on success. Error code otherwise.
  115. //
  116. // Modifies: Nothing.
  117. //
  118. //----------------------------------------------------------------------------
  119. HRESULT CUmiCursor::FInit(
  120. IUnknown *pCont,
  121. CWinNTCredentials *pCredentials
  122. )
  123. {
  124. HRESULT hr = S_OK;
  125. CUmiPropList *pPropList = NULL;
  126. ADsAssert(pCont != NULL);
  127. pPropList = new CUmiPropList(CursorClass, g_dwCursorTableSize);
  128. if(NULL == pPropList)
  129. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  130. hr = pPropList->FInit(NULL, NULL);
  131. BAIL_ON_FAILURE(hr);
  132. hr = pPropList->QueryInterface(
  133. IID_IUmiPropList,
  134. (void **) &m_pIUmiPropList
  135. );
  136. BAIL_ON_FAILURE(hr);
  137. // DECLARE_STD_REFCOUNTING initializes the refcount to 1. Call Release()
  138. // on the created object, so that releasing the interface pointer will
  139. // free the object.
  140. pPropList->Release();
  141. m_pUnkInner = pCont;
  142. pCont->AddRef();
  143. m_pCreds = pCredentials;
  144. RRETURN(S_OK);
  145. error:
  146. if(m_pIUmiPropList != NULL) {
  147. m_pIUmiPropList->Release();
  148. m_pIUmiPropList = NULL;
  149. }
  150. if(pPropList != NULL)
  151. delete pPropList;
  152. RRETURN(hr);
  153. }
  154. //----------------------------------------------------------------------------
  155. // Function: QueryInterface
  156. //
  157. // Synopsis: Queries cursor object for supported interfaces. Only
  158. // IUmiCursor is supported.
  159. //
  160. // Arguments:
  161. //
  162. // iid interface requested
  163. // ppInterface Returns pointer to interface requested. NULL if interface
  164. // is not supported.
  165. //
  166. // Returns: S_OK on success. Error code otherwise.
  167. //
  168. // Modifies: *ppInterface to return interface pointer
  169. //
  170. //----------------------------------------------------------------------------
  171. STDMETHODIMP CUmiCursor::QueryInterface(
  172. REFIID iid,
  173. LPVOID *ppInterface
  174. )
  175. {
  176. if(NULL == ppInterface)
  177. RRETURN(E_INVALIDARG);
  178. *ppInterface = NULL;
  179. if(IsEqualIID(iid, IID_IUnknown))
  180. *ppInterface = (IUmiCursor *) this;
  181. else if(IsEqualIID(iid, IID_IUmiCursor))
  182. *ppInterface = (IUmiCursor *) this;
  183. else if(IsEqualIID(iid, IID_IUmiBaseObject))
  184. *ppInterface = (IUmiBaseObject *) this;
  185. else if(IsEqualIID(iid, IID_IUmiPropList))
  186. *ppInterface = (IUmiPropList *) this;
  187. else
  188. RRETURN(E_NOINTERFACE);
  189. AddRef();
  190. RRETURN(S_OK);
  191. }
  192. //----------------------------------------------------------------------------
  193. // Function: GetLastStatus
  194. //
  195. // Synopsis: Returns status or error code from the last operation. Currently
  196. // only numeric status is returned i.e, no error objects are
  197. // returned. Implements IUmiBaseObject::GetLastStatus().
  198. //
  199. // Arguments:
  200. //
  201. // uFlags Reserved. Must be 0 for now.
  202. // puSpecificStatus Returns status code
  203. // riid IID requested. Ignored currently.
  204. // pStatusObj Returns interface requested. Always returns NULL currently.
  205. //
  206. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  207. //
  208. // Modifies: *puSpecificStatus to return status code.
  209. //
  210. //----------------------------------------------------------------------------
  211. STDMETHODIMP CUmiCursor::GetLastStatus(
  212. ULONG uFlags,
  213. ULONG *puSpecificStatus,
  214. REFIID riid,
  215. LPVOID *pStatusObj
  216. )
  217. {
  218. if(pStatusObj != NULL)
  219. *pStatusObj = NULL;
  220. if(puSpecificStatus != NULL)
  221. *puSpecificStatus = 0;
  222. if(uFlags != 0)
  223. RRETURN(UMI_E_INVALID_FLAGS);
  224. if(NULL == puSpecificStatus)
  225. RRETURN(UMI_E_INVALIDARG);
  226. *puSpecificStatus = m_ulErrorStatus;
  227. RRETURN(UMI_S_NO_ERROR);
  228. }
  229. //----------------------------------------------------------------------------
  230. // Function: GetInterfacePropList
  231. //
  232. // Synopsis: Returns a pointer to the interface property list implementation
  233. // for the connection object. Implements
  234. // IUmiBaseObject::GetInterfacePropList().
  235. //
  236. // Arguments:
  237. //
  238. // uFlags Reserved. Must be 0 for now.
  239. // pPropList Returns pointer to IUmiPropertyList interface
  240. //
  241. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  242. //
  243. // Modifies: *pPropList to return interface pointer
  244. //
  245. //----------------------------------------------------------------------------
  246. STDMETHODIMP CUmiCursor::GetInterfacePropList(
  247. ULONG uFlags,
  248. IUmiPropList **pPropList
  249. )
  250. {
  251. HRESULT hr = UMI_S_NO_ERROR;
  252. SetLastStatus(0);
  253. if(uFlags != 0)
  254. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  255. if(NULL == pPropList)
  256. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  257. ADsAssert(m_pIUmiPropList != NULL);
  258. hr = m_pIUmiPropList->QueryInterface(IID_IUmiPropList, (void **)pPropList);
  259. error:
  260. if(FAILED(hr))
  261. SetLastStatus(hr);
  262. RRETURN(MapHrToUmiError(hr));
  263. }
  264. //----------------------------------------------------------------------------
  265. // Function: SetLastStatus
  266. //
  267. // Synopsis: Sets the status of the last operation.
  268. //
  269. // Arguments:
  270. //
  271. // ulStatus Status to be set
  272. //
  273. // Returns: Nothing
  274. //
  275. // Modifies: Nothing
  276. //
  277. //----------------------------------------------------------------------------
  278. void CUmiCursor::SetLastStatus(ULONG ulStatus)
  279. {
  280. m_ulErrorStatus = ulStatus;
  281. return;
  282. }
  283. //----------------------------------------------------------------------------
  284. // Function: SetIID
  285. //
  286. // Synopsis: Sets the interface to be requested off each item returned by
  287. // the enumerator. Default is IID_IUmiObject.
  288. //
  289. // Arguments:
  290. //
  291. // riid IID of interface to request
  292. //
  293. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  294. //
  295. // Modifies: Nothing.
  296. //
  297. //----------------------------------------------------------------------------
  298. STDMETHODIMP CUmiCursor::SetIID(
  299. REFIID riid
  300. )
  301. {
  302. SetLastStatus(0);
  303. if(NULL == m_pIID)
  304. {
  305. m_pIID = (IID *) AllocADsMem(sizeof(IID));
  306. if(NULL == m_pIID) {
  307. SetLastStatus(UMI_E_OUT_OF_MEMORY);
  308. RRETURN(UMI_E_OUT_OF_MEMORY);
  309. }
  310. }
  311. memcpy(m_pIID, &riid, sizeof(IID));
  312. RRETURN(UMI_S_NO_ERROR);
  313. }
  314. //----------------------------------------------------------------------------
  315. // Function: Reset
  316. //
  317. // Synopsis: Resets the enumerator to start from the beginning
  318. //
  319. // Arguments:
  320. //
  321. // None
  322. //
  323. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  324. //
  325. // Modifies: Nothing.
  326. //
  327. //----------------------------------------------------------------------------
  328. STDMETHODIMP CUmiCursor::Reset(void)
  329. {
  330. HRESULT hr = UMI_S_NO_ERROR;
  331. SetLastStatus(0);
  332. // WinNT doesn't support Reset(). Keep the code below in case WinNT
  333. // Reset() gets implemented in the future.
  334. BAIL_ON_FAILURE(hr = UMI_E_NOTIMPL);
  335. // it is possible that m_pEnumerator may be NULL here if the user
  336. // called Reset before calling Next()
  337. if(NULL == m_pEnumerator)
  338. RRETURN(UMI_S_NO_ERROR);
  339. hr = m_pEnumerator->Reset();
  340. BAIL_ON_FAILURE(hr);
  341. RRETURN(UMI_S_NO_ERROR);
  342. error:
  343. SetLastStatus(hr);
  344. RRETURN(MapHrToUmiError(hr));
  345. }
  346. //----------------------------------------------------------------------------
  347. // Function: GetFilter
  348. //
  349. // Synopsis: Gets the filter from the interface property cache. If the
  350. // interface property was not set, an emty variant is returned.
  351. //
  352. // Arguments:
  353. //
  354. // pvFilter Returns variant containing the filter
  355. //
  356. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  357. //
  358. // Modifies: *pvFilter to return the filter.
  359. //
  360. //----------------------------------------------------------------------------
  361. HRESULT CUmiCursor::GetFilter(VARIANT *pvFilter)
  362. {
  363. HRESULT hr = UMI_S_NO_ERROR;
  364. UMI_PROPERTY_VALUES *pUmiProp = NULL;
  365. LPWSTR *ppszFilters = NULL;
  366. DWORD dwNumFilters = 0;
  367. ADsAssert(pvFilter != NULL);
  368. VariantInit(pvFilter);
  369. hr = m_pIUmiPropList->Get(
  370. TEXT(CURSOR_INTF_PROP_FILTER),
  371. 0,
  372. &pUmiProp
  373. );
  374. if(UMI_E_PROPERTY_NOT_FOUND == hr)
  375. // interface property was not set. Return empty variant.
  376. RRETURN(UMI_S_NO_ERROR);
  377. // check if there was some other error on Get()
  378. BAIL_ON_FAILURE(hr);
  379. ADsAssert(UMI_TYPE_LPWSTR == pUmiProp->pPropArray->uType);
  380. ADsAssert(pUmiProp->pPropArray->pUmiValue != NULL);
  381. ppszFilters = pUmiProp->pPropArray->pUmiValue->pszStrValue;
  382. dwNumFilters = pUmiProp->pPropArray->uCount;
  383. hr = ADsBuildVarArrayStr(ppszFilters, dwNumFilters, pvFilter);
  384. BAIL_ON_FAILURE(hr);
  385. error:
  386. if(pUmiProp != NULL)
  387. m_pIUmiPropList->FreeMemory(0, pUmiProp); // ignore error return
  388. RRETURN(hr);
  389. }
  390. //----------------------------------------------------------------------------
  391. // Function: Next
  392. //
  393. // Synopsis: Returns the next item(s) in the enumeration sequence.
  394. //
  395. // Arguments:
  396. //
  397. // uNumRequested Number of items requested
  398. // pNumReturned Returns actual number of objects returned
  399. // ppObjects Array of interface pointers of size *pNumReturned
  400. //
  401. // None
  402. //
  403. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  404. //
  405. // Modifies: *pNumReturned to return the number of objects returned
  406. // *ppObjects to return the interface pointers
  407. //
  408. //----------------------------------------------------------------------------
  409. STDMETHODIMP CUmiCursor::Next(
  410. ULONG uNumRequested,
  411. ULONG *puNumReturned,
  412. LPVOID *ppObjects
  413. )
  414. {
  415. HRESULT hr = UMI_S_NO_ERROR;
  416. VARIANT vFilter, *pvResults = NULL;
  417. ULONG ulIndex = 0, uNumReturned = 0, uNumResults = 0;
  418. IDispatch *pDisp = NULL;
  419. IUnknown **pUnkArr = NULL, *pTmpUnk = NULL;
  420. IADsContainer *pIADsContainer = NULL;
  421. SetLastStatus(0);
  422. if( (NULL == puNumReturned) || (NULL == ppObjects) )
  423. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  424. *puNumReturned = 0;
  425. *ppObjects = NULL;
  426. VariantInit(&vFilter);
  427. if(NULL == m_pEnumerator) {
  428. // first call to Next()
  429. ADsAssert(m_pUnkInner != NULL);
  430. hr = m_pUnkInner->QueryInterface(
  431. IID_IADsContainer,
  432. (void **) &pIADsContainer
  433. );
  434. BAIL_ON_FAILURE(hr);
  435. // check if the user set a filter on the cursor
  436. hr = GetFilter(&vFilter);
  437. BAIL_ON_FAILURE(hr);
  438. hr = pIADsContainer->put_Filter(vFilter);
  439. BAIL_ON_FAILURE(hr);
  440. m_pCreds->SetUmiFlag();
  441. hr = pIADsContainer->get__NewEnum((IUnknown **) &m_pEnumerator);
  442. m_pCreds->ResetUmiFlag();
  443. BAIL_ON_FAILURE(hr);
  444. }
  445. // allocate memory for variants to return objects
  446. pvResults = (VARIANT *) AllocADsMem(uNumRequested * sizeof(VARIANT));
  447. if(NULL == pvResults)
  448. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  449. hr = m_pEnumerator->Next(
  450. uNumRequested,
  451. pvResults,
  452. &uNumReturned
  453. );
  454. BAIL_ON_FAILURE(hr);
  455. // allocate memory for array of interface pointers to return
  456. pUnkArr = (IUnknown **) AllocADsMem(uNumReturned * sizeof(IUnknown *));
  457. if(NULL == pUnkArr)
  458. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  459. // convert the V_DISPATCH variants to the requested interface properties
  460. for(ulIndex = 0; ulIndex < uNumReturned; ulIndex++) {
  461. pDisp = V_DISPATCH(&pvResults[ulIndex]);
  462. ADsAssert(pDisp != NULL);
  463. if(m_pIID != NULL)
  464. hr = pDisp->QueryInterface(*m_pIID, (void **) &pTmpUnk);
  465. else
  466. hr = pDisp->QueryInterface(IID_IUmiObject, (void **) &pTmpUnk);
  467. if(FAILED(hr))
  468. continue;
  469. pUnkArr[uNumResults] = pTmpUnk;
  470. uNumResults++;
  471. }
  472. *puNumReturned = uNumResults;
  473. if(uNumResults > 0)
  474. *ppObjects = pUnkArr;
  475. else
  476. FreeADsMem(pUnkArr);
  477. error:
  478. VariantClear(&vFilter);
  479. if(pvResults != NULL) {
  480. for(ulIndex = 0; ulIndex < uNumReturned; ulIndex++)
  481. VariantClear(&pvResults[ulIndex]);
  482. FreeADsMem(pvResults);
  483. }
  484. if(pIADsContainer != NULL)
  485. pIADsContainer->Release();
  486. if(FAILED(hr))
  487. SetLastStatus(hr);
  488. RRETURN(MapHrToUmiError(hr));
  489. }
  490. //----------------------------------------------------------------------------
  491. // Function: Count
  492. //
  493. // Synopsis: Counts the number of results returned by the enumerator.
  494. // Not implemented currently.
  495. //
  496. // Arguments:
  497. //
  498. // None
  499. //
  500. // Returns: UMI_E_NOTIMPL for now.
  501. //
  502. // Modifies: Nothing.
  503. //
  504. //----------------------------------------------------------------------------
  505. STDMETHODIMP CUmiCursor::Count(
  506. ULONG *puNumObjects
  507. )
  508. {
  509. SetLastStatus(UMI_E_NOTIMPL);
  510. RRETURN(UMI_E_NOTIMPL);
  511. }
  512. //----------------------------------------------------------------------------
  513. // Function: Previous
  514. //
  515. // Synopsis: Returnss the previous object returned by the enumerator.
  516. // Not implemented currently.
  517. //
  518. // Arguments:
  519. //
  520. // None
  521. //
  522. // Returns: UMI_E_NOTIMPL for now.
  523. //
  524. // Modifies: Nothing.
  525. //
  526. //----------------------------------------------------------------------------
  527. STDMETHODIMP CUmiCursor::Previous(
  528. ULONG uFlags,
  529. LPVOID *pObj
  530. )
  531. {
  532. SetLastStatus(UMI_E_NOTIMPL);
  533. RRETURN(UMI_E_NOTIMPL);
  534. }