home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / adsi / sampprov / cprops.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-29  |  16.6 KB  |  801 lines

  1. /*++
  2.  
  3. Copyright (c) 1996 Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     CProps.cpp
  8.  
  9. Abstract:
  10.  
  11.     Property Cache functionality 
  12.  
  13. Author:
  14.  
  15. Environment:
  16.  
  17.     User mode
  18.  
  19. Revision History :
  20.  
  21. --*/
  22. #include "adssmp.h"
  23. #pragma hdrstop
  24.  
  25.  
  26. //+------------------------------------------------------------------------
  27. //
  28. //  Function:   CPropertyCache::addproperty
  29. //
  30. //  Synopsis:
  31. //
  32. //
  33. //
  34. //  Arguments:  [szPropertyName]    --
  35. //              [vt]                --
  36. //              [vaData]            --
  37. //
  38. //
  39. //-------------------------------------------------------------------------
  40. HRESULT
  41. CPropertyCache::
  42. addproperty(
  43.     LPWSTR szPropertyName,
  44.     DWORD  dwSyntaxId,
  45.     DWORD  dwNumValues,
  46.     PSampleDSOBJECT pSampleDSObject
  47.     )
  48. {
  49.     HRESULT hr = S_OK;
  50.     PPROPERTY pNewProperty = NULL;
  51.  
  52.     //
  53.     //  extend the property cache by adding a new property entry
  54.     //
  55.  
  56.     _pProperties = (PPROPERTY)ReallocProvMem(
  57.                                 _pProperties,
  58.                                 _cb,
  59.                                 _cb + sizeof(PROPERTY)
  60.                                 );
  61.     if (!_pProperties) {
  62.         hr = E_OUTOFMEMORY;
  63.         BAIL_ON_FAILURE(hr);
  64.     }
  65.  
  66.  
  67.     pNewProperty = (PPROPERTY)((LPBYTE)_pProperties + _cb);
  68.  
  69.     wcscpy(pNewProperty->szPropertyName, szPropertyName);
  70.  
  71.     //
  72.     // Update the index
  73.     //
  74.  
  75.     _dwMaxProperties++;
  76.     _cb += sizeof(PROPERTY);
  77.  
  78. error:
  79.     RRETURN(hr);
  80. }
  81.  
  82.  
  83. //+------------------------------------------------------------------------
  84. //
  85. //  Function:   CPropertyCache::updateproperty
  86. //
  87. //  Synopsis:
  88. //
  89. //
  90. //
  91. //  Arguments:  [szPropertyName]    --
  92. //              [vaData]    --
  93. //
  94. //-------------------------------------------------------------------------
  95. HRESULT
  96. CPropertyCache::
  97. updateproperty(
  98.     LPWSTR szPropertyName,
  99.     DWORD  dwSyntaxId,
  100.     DWORD  dwNumValues,
  101.     PSampleDSOBJECT pSampleDSObject,
  102.     BOOL fExplicit
  103.     )
  104. {
  105.     HRESULT hr;
  106.     DWORD dwIndex;
  107.     PSampleDSOBJECT pNdsTempObject = NULL;
  108.     PPROPERTY pThisProperty = NULL;
  109.  
  110.     hr = findproperty(
  111.             szPropertyName,
  112.             &dwIndex
  113.             );
  114.     BAIL_ON_FAILURE(hr);
  115.  
  116.     pThisProperty = _pProperties + dwIndex;
  117.  
  118.     if (!fExplicit) {
  119.         if (PROPERTY_FLAGS(pThisProperty) & CACHE_PROPERTY_MODIFIED) {
  120.             hr = S_OK;
  121.             goto error;
  122.         }
  123.     }
  124.  
  125.  
  126.     if (PROPERTY_SampleDSOBJECT(pThisProperty)) {
  127.  
  128.         SampleDSTypeFreeSampleDSObjects(
  129.                 PROPERTY_SampleDSOBJECT(pThisProperty),
  130.                 PROPERTY_NUMVALUES(pThisProperty)
  131.                 );
  132.         PROPERTY_SampleDSOBJECT(pThisProperty) = NULL;
  133.     }
  134.     PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  135.     PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  136.  
  137.     hr = SampleDSTypeCopyConstruct(
  138.             pSampleDSObject,
  139.             dwNumValues,
  140.             &pNdsTempObject
  141.             );
  142.     BAIL_ON_FAILURE(hr);
  143.  
  144.     PROPERTY_SampleDSOBJECT(pThisProperty) = pNdsTempObject;
  145.  
  146.     PROPERTY_FLAGS(pThisProperty)  &= ~CACHE_PROPERTY_MODIFIED;
  147.  
  148. error:
  149.  
  150.     RRETURN(hr);
  151.  
  152. }
  153.  
  154.  
  155. //+------------------------------------------------------------------------
  156. //
  157. //  Function:   CPropertyCache::findproperty
  158. //
  159. //  Synopsis:
  160. //
  161. //
  162. //
  163. //  Arguments:  [szPropertyName] --
  164. //              [pdwIndex]       --
  165. //
  166. //-------------------------------------------------------------------------
  167. HRESULT
  168. CPropertyCache::
  169. findproperty(
  170.     LPWSTR szPropertyName,
  171.     PDWORD pdwIndex
  172.     )
  173.  
  174. {
  175.     DWORD i = 0;
  176.     PPROPERTY pThisProperty = NULL;
  177.  
  178.     for (i = 0; i < _dwMaxProperties; i++) {
  179.  
  180.         pThisProperty = _pProperties + i;
  181.  
  182.         if (!_wcsicmp(pThisProperty->szPropertyName, szPropertyName)) {
  183.             *pdwIndex = i;
  184.             RRETURN(S_OK);
  185.         }
  186.     }
  187.     *pdwIndex = 0;
  188.     RRETURN(E_ADS_PROPERTY_NOT_FOUND);
  189. }
  190.  
  191. //+------------------------------------------------------------------------
  192. //
  193. //  Function:   CPropertyCache::getproperty
  194. //
  195. //  Synopsis:
  196. //
  197. //
  198. //
  199. //  Arguments:  [szPropertyName]    --  Property to retrieve from the cache
  200. //              [pvaData]           --  Data returned in a variant
  201. //
  202. //-------------------------------------------------------------------------
  203. HRESULT
  204. CPropertyCache::
  205. getproperty(
  206.     LPWSTR szPropertyName,
  207.     PDWORD  pdwSyntaxId,
  208.     PDWORD  pdwNumValues,
  209.     PSampleDSOBJECT * ppSampleDSObject
  210.     )
  211. {
  212.     HRESULT hr;
  213.     DWORD dwIndex = 0L;
  214.     PPROPERTY pThisProperty = NULL;
  215.  
  216.     hr = findproperty(
  217.             szPropertyName,
  218.             &dwIndex
  219.             );
  220.  
  221.     if (hr == E_ADS_PROPERTY_NOT_FOUND) {
  222.  
  223.         //
  224.         // Now call the GetInfo function
  225.         //
  226.  
  227.         hr = _pCoreADsObject->GetInfo(
  228.                     FALSE
  229.                     );
  230.         BAIL_ON_FAILURE(hr);
  231.  
  232.         hr = findproperty(
  233.                     szPropertyName,
  234.                     &dwIndex
  235.                     );
  236.  
  237.     }
  238.     BAIL_ON_FAILURE(hr);
  239.  
  240.     pThisProperty = _pProperties + dwIndex;
  241.  
  242.     if (PROPERTY_SampleDSOBJECT(pThisProperty)) {
  243.  
  244.         *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  245.         *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  246.  
  247.         hr = SampleDSTypeCopyConstruct(
  248.                 PROPERTY_SampleDSOBJECT(pThisProperty),
  249.                 PROPERTY_NUMVALUES(pThisProperty),
  250.                 ppSampleDSObject
  251.                 );
  252.         BAIL_ON_FAILURE(hr);
  253.  
  254.     }else {
  255.  
  256.         *ppSampleDSObject = NULL;
  257.         *pdwNumValues = 0;
  258.         *pdwSyntaxId = 0;
  259.         hr = E_FAIL;
  260.  
  261.     }
  262.  
  263. error:
  264.  
  265.    RRETURN(hr);
  266. }
  267.  
  268. //+------------------------------------------------------------------------
  269. //
  270. //  Function:   CPropertyCache::putproperty
  271. //
  272. //  Synopsis:
  273. //
  274. //
  275. //
  276. //  Arguments:  [szPropertyName]    --  Clsid index
  277. //              [vaData]    --  Matching clsid returned in *pclsid
  278. //
  279. //-------------------------------------------------------------------------
  280. HRESULT
  281. CPropertyCache::
  282. putproperty(
  283.     LPWSTR szPropertyName,
  284.     DWORD  dwSyntaxId,
  285.     DWORD  dwNumValues,
  286.     PSampleDSOBJECT pSampleDSOBJECT
  287.     )
  288. {
  289.     HRESULT hr;
  290.     DWORD dwIndex = 0L;
  291.     PSampleDSOBJECT pSampleDSTempObject = NULL;
  292.     PPROPERTY pThisProperty = NULL;
  293.  
  294.     hr = findproperty(
  295.             szPropertyName,
  296.             &dwIndex
  297.             );
  298.     BAIL_ON_FAILURE(hr);
  299.  
  300.     pThisProperty = _pProperties + dwIndex;
  301.  
  302.     if (PROPERTY_SampleDSOBJECT(pThisProperty)) {
  303.  
  304.         SampleDSTypeFreeSampleDSObjects(
  305.                 PROPERTY_SampleDSOBJECT(pThisProperty),
  306.                 PROPERTY_NUMVALUES(pThisProperty)
  307.                 );
  308.         PROPERTY_SampleDSOBJECT(pThisProperty) = NULL;
  309.     }
  310.  
  311.     PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  312.     PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  313.  
  314.     hr = SampleDSTypeCopyConstruct(
  315.             pSampleDSOBJECT,
  316.             dwNumValues,
  317.             &pSampleDSTempObject
  318.             );
  319.     BAIL_ON_FAILURE(hr);
  320.  
  321.     PROPERTY_SampleDSOBJECT(pThisProperty) = pSampleDSTempObject;
  322.  
  323.     PROPERTY_FLAGS(pThisProperty) |= CACHE_PROPERTY_MODIFIED;
  324.  
  325. error:
  326.     RRETURN(hr);
  327. }
  328.  
  329.  
  330.  
  331. //+------------------------------------------------------------------------
  332. //
  333. //  Function:   CPropertyCache
  334. //
  335. //  Synopsis:
  336. //
  337. //
  338. //
  339. //  Arguments:
  340. //
  341. //
  342. //-------------------------------------------------------------------------
  343. CPropertyCache::
  344. CPropertyCache():
  345.         _dwMaxProperties(0),
  346.         _pProperties(NULL),
  347.         _cb(0),
  348.         _pCoreADsObject(NULL)
  349. {
  350.  
  351. }
  352.  
  353. //+------------------------------------------------------------------------
  354. //
  355. //  Function:   ~CPropertyCache
  356. //
  357. //  Synopsis:
  358. //
  359. //
  360. //
  361. //  Arguments:
  362. //
  363. //
  364. //-------------------------------------------------------------------------
  365. CPropertyCache::
  366. ~CPropertyCache()
  367. {
  368.     DWORD i = 0;
  369.     PPROPERTY pThisProperty = NULL;
  370.  
  371.     if (_pProperties) {
  372.  
  373.         for (i = 0; i < _dwMaxProperties; i++) {
  374.  
  375.             pThisProperty = _pProperties + i;
  376.  
  377.             if (PROPERTY_SampleDSOBJECT(pThisProperty)) {
  378.  
  379.                 SampleDSTypeFreeSampleDSObjects(
  380.                         PROPERTY_SampleDSOBJECT(pThisProperty),
  381.                         PROPERTY_NUMVALUES(pThisProperty)
  382.                         );
  383.                 PROPERTY_SampleDSOBJECT(pThisProperty) = NULL;
  384.             }
  385.         }
  386.  
  387.         FreeProvMem(_pProperties);
  388.     }
  389. }
  390.  
  391. //+------------------------------------------------------------------------
  392. //
  393. //  Function:
  394. //
  395. //  Synopsis:
  396. //
  397. //
  398. //
  399. //  Arguments:
  400. //
  401. //
  402. //-------------------------------------------------------------------------
  403. HRESULT
  404. CPropertyCache::
  405. createpropertycache(
  406.     CCoreADsObject FAR * pCoreADsObject,
  407.     CPropertyCache FAR *FAR * ppPropertyCache
  408.     )
  409. {
  410.     CPropertyCache FAR * pPropertyCache = NULL;
  411.  
  412.     pPropertyCache = new CPropertyCache();
  413.  
  414.     if (!pPropertyCache) {
  415.         RRETURN(E_FAIL);
  416.     }
  417.  
  418.     pPropertyCache->_pCoreADsObject = pCoreADsObject;
  419.  
  420.     *ppPropertyCache = pPropertyCache;
  421.  
  422.     RRETURN(S_OK);
  423. }
  424.  
  425.  
  426. //+------------------------------------------------------------------------
  427. //
  428. //  Function:   CPropertyCache::getproperty
  429. //
  430. //  Synopsis:
  431. //
  432. //
  433. //
  434. //  Arguments:  [szPropertyName]    --  Property to retrieve from the cache
  435. //              [pvaData]           --  Data returned in a variant
  436. //
  437. //-------------------------------------------------------------------------
  438. HRESULT
  439. CPropertyCache::
  440. unboundgetproperty(
  441.     LPWSTR szPropertyName,
  442.     PDWORD  pdwSyntaxId,
  443.     PDWORD  pdwNumValues,
  444.     PSampleDSOBJECT * ppSampleDSOBJECT
  445.     )
  446. {
  447.     HRESULT hr;
  448.     DWORD dwIndex = 0L;
  449.     PPROPERTY pThisProperty = NULL;
  450.  
  451.     hr = findproperty(
  452.             szPropertyName,
  453.             &dwIndex
  454.             );
  455.     BAIL_ON_FAILURE(hr);
  456.  
  457.     pThisProperty = _pProperties + dwIndex;
  458.  
  459.     if (PROPERTY_SampleDSOBJECT(pThisProperty)) {
  460.  
  461.         *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  462.         *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  463.  
  464.         hr = SampleDSTypeCopyConstruct(
  465.                 PROPERTY_SampleDSOBJECT(pThisProperty),
  466.                 PROPERTY_NUMVALUES(pThisProperty),
  467.                 ppSampleDSOBJECT
  468.                 );
  469.         BAIL_ON_FAILURE(hr);
  470.  
  471.     }else {
  472.  
  473.         *ppSampleDSOBJECT = NULL;
  474.         *pdwNumValues = 0;
  475.         *pdwSyntaxId = 0;
  476.         hr = E_FAIL;
  477.  
  478.     }
  479.  
  480. error:
  481.  
  482.    RRETURN(hr);
  483. }
  484.  
  485.  
  486.  
  487. HRESULT
  488. CPropertyCache::
  489. SampleDSMarshallProperties(
  490.     HANDLE hOperationData
  491.     )
  492. {
  493.     LPSampleDS_ATTRS_INFO pAttrsInfo = (LPSampleDS_ATTRS_INFO)hOperationData;
  494.     HRESULT hr = S_OK;
  495.     DWORD i = 0;
  496.     PPROPERTY pThisProperty = NULL;
  497.     BYTE lpBuffer[2048];
  498.     DWORD cProperty = 0;
  499.     LPSampleDS_ATTR_INFO pAttrInfoMemStart = NULL; 
  500.     LPSampleDS_ATTR_INFO pAttrInfoMem = NULL; 
  501.     pAttrInfoMemStart = (LPSampleDS_ATTR_INFO)AllocProvMem(
  502.                                      sizeof(SampleDS_ATTR_INFO)*_dwMaxProperties);
  503.     if (!pAttrInfoMemStart)
  504.         goto Error;
  505.  
  506.     pAttrInfoMem = pAttrInfoMemStart;
  507.  
  508.     for (i = 0; i < _dwMaxProperties ; i++) {
  509.  
  510.         pThisProperty = _pProperties + i;
  511.  
  512.         //
  513.         // Bypass any property that has not been
  514.         // modified
  515.         //
  516.  
  517.         if (PROPERTY_FLAGS(pThisProperty) == 0) {
  518.  
  519.             continue;
  520.         }
  521.  
  522.         hr = MarshallSampleDSSynIdToSampleDS(
  523.                 PROPERTY_SYNTAX(pThisProperty),
  524.                 PROPERTY_SampleDSOBJECT(pThisProperty),
  525.                 PROPERTY_NUMVALUES(pThisProperty),
  526.                 lpBuffer
  527.                 );
  528.         CONTINUE_ON_FAILURE(hr);
  529.  
  530.  
  531.         hr = marshallproperty(
  532.                 pAttrInfoMem,
  533.                 PROPERTY_NAME(pThisProperty),
  534.                 lpBuffer,
  535.                 PROPERTY_NUMVALUES(pThisProperty),
  536.                 PROPERTY_SYNTAX(pThisProperty)
  537.                 );
  538.         CONTINUE_ON_FAILURE(hr);
  539.         cProperty++;
  540.         pAttrInfoMem++;
  541.     }
  542.  
  543.     if (cProperty != _dwMaxProperties) {
  544.         LPSampleDS_ATTR_INFO pAttrInfoNew; 
  545.         pAttrInfoNew = (LPSampleDS_ATTR_INFO)AllocProvMem(
  546.                                          sizeof(SampleDS_ATTR_INFO)*cProperty);
  547.         if (!pAttrInfoNew) {
  548.             hr = E_FAIL;
  549.             goto Error;
  550.         }
  551.         memcpy( (void*)pAttrInfoNew,
  552.                 (void*)pAttrInfoMemStart,
  553.                 sizeof(SampleDS_ATTR_INFO)*cProperty);
  554.         FreeProvMem(pAttrInfoMemStart);
  555.         pAttrInfoMemStart = pAttrInfoNew;
  556.     }
  557.     pAttrsInfo->pAttrInfo = pAttrInfoMemStart;
  558.     pAttrsInfo->dwAttr = cProperty;
  559.     RRETURN(hr);
  560.  
  561. Error:
  562.     if (pAttrInfoMem)
  563.         FreeProvMem(pAttrInfoMem);
  564.     RRETURN(hr);
  565.  
  566. }
  567.  
  568. HRESULT
  569. CPropertyCache::
  570. marshallproperty(
  571.     LPSampleDS_ATTR_INFO pAttrInfo,
  572.     LPWSTR szPropertyName,
  573.     LPBYTE lpValues,
  574.     DWORD  dwNumValues,
  575.     DWORD  dwSyntaxId
  576.     )
  577. {
  578.     pAttrInfo->lpAttributeName = (LPWSTR)AllocProvStr(szPropertyName);
  579.     if (!pAttrInfo->lpAttributeName)
  580.         RRETURN(E_FAIL);
  581.     
  582.     DWORD dwMemSize;
  583.     switch (dwSyntaxId) {
  584.         case SampleDS_DATATYPE_1:
  585.             dwMemSize = sizeof(SampleDS_TYPE_1);
  586.             break;
  587.         case SampleDS_DATATYPE_2:
  588.             dwMemSize = sizeof(SampleDS_TYPE_2);
  589.             break;
  590.         default:
  591.             goto Error;
  592.     }
  593.     pAttrInfo->lpValue = (BYTE*)AllocProvMem(dwMemSize);
  594.     if (!pAttrInfo->lpValue)
  595.         goto Error;
  596.     memcpy( (void*)pAttrInfo->lpValue,
  597.             (void*)lpValues,
  598.             dwMemSize);
  599.     
  600.     pAttrInfo->dwSyntaxId = dwSyntaxId;
  601.     pAttrInfo->dwNumberOfValues = dwNumValues;
  602.     RRETURN(S_OK);
  603. Error:
  604.     if (pAttrInfo->lpAttributeName)
  605.         FreeProvMem(pAttrInfo->lpAttributeName);
  606.     if (pAttrInfo->lpValue)
  607.         FreeProvMem(pAttrInfo->lpValue);
  608.     RRETURN(E_FAIL);
  609. }
  610.  
  611. HRESULT
  612. CPropertyCache::
  613. SampleDSUnMarshallProperties(
  614.     HANDLE hOperationData,
  615.     BOOL fExplicit
  616.     )
  617.  
  618. {
  619.     LPSampleDS_ATTRS_INFO pAttrsInfo = (LPSampleDS_ATTRS_INFO)hOperationData;
  620.     
  621.     DWORD dwNumberOfEntries = 0L;
  622.     LPSampleDS_ATTR_INFO lpEntries = pAttrsInfo->pAttrInfo;
  623.     DWORD dwEntry = pAttrsInfo->dwAttr;
  624.     HRESULT hr = S_OK;
  625.     DWORD i = 0;
  626.     DWORD dwStatus = 0L;
  627.  
  628.     for (i = 0; i < dwEntry; i++) {
  629.  
  630.         //
  631.         // unmarshall this property into the
  632.         // property cache
  633.         //
  634.         
  635.         hr = unmarshallproperty(
  636.                     lpEntries[i].lpAttributeName,
  637.                     lpEntries[i].lpValue,
  638.                     lpEntries[i].dwNumberOfValues,
  639.                     lpEntries[i].dwSyntaxId,
  640.                     fExplicit
  641.                     );
  642.  
  643.         CONTINUE_ON_FAILURE(hr);
  644.  
  645.     }
  646.  
  647.     RRETURN(hr);
  648.  
  649. }
  650.  
  651. //+------------------------------------------------------------------------
  652. //
  653. //  Function:
  654. //
  655. //  Synopsis:
  656. //
  657. //
  658. //
  659. //  Arguments:
  660. //
  661. //
  662. //-------------------------------------------------------------------------
  663.  
  664. HRESULT
  665. CPropertyCache::
  666. unmarshallproperty(
  667.     LPWSTR szPropertyName,
  668.     LPBYTE lpValue,
  669.     DWORD  dwNumValues,
  670.     DWORD  dwSyntaxId,
  671.     BOOL fExplicit
  672.     )
  673. {
  674.  
  675.     DWORD dwIndex = 0;
  676.     HRESULT hr = S_OK;
  677.     PSampleDSOBJECT pSampleDSObject = NULL;
  678.  
  679.     hr = UnMarshallSampleDSToSampleDSSynId(
  680.                 dwSyntaxId,
  681.                 dwNumValues,
  682.                 lpValue,
  683.                 &pSampleDSObject 
  684.                 );
  685.     BAIL_ON_FAILURE(hr);
  686.  
  687.     //
  688.     // Find this property in the cache
  689.     //
  690.  
  691.     hr = findproperty(
  692.                 szPropertyName,
  693.                 &dwIndex
  694.                 );
  695.  
  696.     //
  697.     // If this property does not exist in the
  698.     // cache, add this property into the cache.
  699.     //
  700.  
  701.  
  702.     if (FAILED(hr)) {
  703.         hr = addproperty(
  704.                     szPropertyName,
  705.                     dwSyntaxId,
  706.                     dwNumValues,
  707.                     pSampleDSObject 
  708.                     );
  709.  
  710.         //
  711.         // If the operation fails for some reason
  712.         // move on to the next property
  713.         //
  714.         BAIL_ON_FAILURE(hr);
  715.  
  716.     }
  717.  
  718.     //
  719.     // Now update the property in the cache
  720.     //
  721.  
  722.     hr = updateproperty(
  723.                     szPropertyName,
  724.                     dwSyntaxId,
  725.                     dwNumValues,
  726.                     pSampleDSObject,
  727.                     fExplicit
  728.                     );
  729.     BAIL_ON_FAILURE(hr);
  730.  
  731.  
  732.     if (pSampleDSObject) {
  733.         SampleDSTypeFreeSampleDSObjects(
  734.                 pSampleDSObject,
  735.                 dwNumValues
  736.                 );
  737.  
  738.     }
  739.  
  740.  
  741. error:
  742.     RRETURN(hr);
  743. }
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.