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.

804 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. oleutil.cpp
  5. Abstract:
  6. Provides Useful functions for dealing with OLE.
  7. Author:
  8. Magnus Hedlund (MagnusH) --
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "iadm.h"
  13. #include "oleutil.h"
  14. #include "cmultisz.h"
  15. #include "resource.h"
  16. //$-------------------------------------------------------------------
  17. //
  18. // UpdateChangedMask
  19. //
  20. // Description:
  21. //
  22. // Marks a field as changed in the given bit vector
  23. //
  24. // Parameters:
  25. //
  26. // pbvChangedProps - points to the bit vector
  27. // dwBitMask - Bit to turn on. (must have only one bit on)
  28. //
  29. //--------------------------------------------------------------------
  30. static void UpdateChangedMask ( DWORD * pbvChangedProps, DWORD dwBitMask )
  31. {
  32. if ( pbvChangedProps == NULL ) {
  33. // Legal, means that the caller doesn't want change tracking.
  34. return;
  35. }
  36. _ASSERT ( dwBitMask != 0 );
  37. *pbvChangedProps |= dwBitMask;
  38. }
  39. HRESULT LongArrayToVariantArray ( SAFEARRAY * psaLongs, SAFEARRAY ** ppsaVariants )
  40. {
  41. _ASSERT ( psaLongs );
  42. HRESULT hr = NOERROR;
  43. long lLBound = 0;
  44. long lUBound = 0;
  45. long i;
  46. SAFEARRAYBOUND bounds;
  47. SAFEARRAY * psaVariants;
  48. *ppsaVariants = NULL;
  49. _ASSERT ( SafeArrayGetDim ( psaLongs ) == 1 );
  50. SafeArrayGetLBound ( psaLongs, 1, &lLBound );
  51. SafeArrayGetUBound ( psaLongs, 1, &lUBound );
  52. bounds.lLbound = lLBound;
  53. bounds.cElements = lUBound - lLBound + 1;
  54. psaVariants = SafeArrayCreate ( VT_VARIANT, 1, &bounds );
  55. for ( i = lLBound; i <= lUBound; i++ ) {
  56. VARIANT var;
  57. long lTemp;
  58. VariantInit ( &var );
  59. hr = SafeArrayGetElement ( psaLongs, &i, &lTemp );
  60. if ( FAILED(hr) ) {
  61. goto Exit;
  62. }
  63. V_VT (&var) = VT_I4;
  64. V_I4 (&var) = lTemp;
  65. hr = SafeArrayPutElement ( psaVariants, &i, &var );
  66. if ( FAILED(hr) ) {
  67. goto Exit;
  68. }
  69. VariantClear ( &var );
  70. }
  71. *ppsaVariants = psaVariants;
  72. Exit:
  73. return hr;
  74. }
  75. HRESULT StringArrayToVariantArray ( SAFEARRAY * psaStrings, SAFEARRAY ** ppsaVariants )
  76. {
  77. _ASSERT ( psaStrings );
  78. HRESULT hr = NOERROR;
  79. long lLBound = 0;
  80. long lUBound = 0;
  81. long i;
  82. SAFEARRAYBOUND bounds;
  83. SAFEARRAY * psaVariants;
  84. *ppsaVariants = NULL;
  85. _ASSERT ( SafeArrayGetDim ( psaStrings ) == 1 );
  86. SafeArrayGetLBound ( psaStrings, 1, &lLBound );
  87. SafeArrayGetUBound ( psaStrings, 1, &lUBound );
  88. bounds.lLbound = lLBound;
  89. bounds.cElements = lUBound - lLBound + 1;
  90. psaVariants = SafeArrayCreate ( VT_VARIANT, 1, &bounds );
  91. for ( i = lLBound; i <= lUBound; i++ ) {
  92. VARIANT var;
  93. CComBSTR strTemp;
  94. VariantInit ( &var );
  95. hr = SafeArrayGetElement ( psaStrings, &i, &strTemp );
  96. if ( FAILED(hr) ) {
  97. goto Exit;
  98. }
  99. V_VT (&var) = VT_BSTR;
  100. V_BSTR (&var) = ::SysAllocString ( strTemp );
  101. hr = SafeArrayPutElement ( psaVariants, &i, &var );
  102. if ( FAILED(hr) ) {
  103. goto Exit;
  104. }
  105. VariantClear ( &var );
  106. }
  107. *ppsaVariants = psaVariants;
  108. Exit:
  109. return hr;
  110. }
  111. HRESULT VariantArrayToStringArray ( SAFEARRAY * psaVariants, SAFEARRAY ** ppsaStrings )
  112. {
  113. _ASSERT ( psaVariants );
  114. HRESULT hr = NOERROR;
  115. long lLBound = 0;
  116. long lUBound = 0;
  117. long i;
  118. SAFEARRAYBOUND bounds;
  119. SAFEARRAY * psaStrings;
  120. _ASSERT ( SafeArrayGetDim ( psaVariants ) == 1 );
  121. *ppsaStrings = NULL;
  122. SafeArrayGetLBound ( psaVariants, 1, &lLBound );
  123. SafeArrayGetUBound ( psaVariants, 1, &lUBound );
  124. bounds.lLbound = lLBound;
  125. bounds.cElements = lUBound - lLBound + 1;
  126. psaStrings = SafeArrayCreate ( VT_BSTR, 1, &bounds );
  127. for ( i = lLBound; i <= lUBound; i++ ) {
  128. VARIANT var;
  129. CComBSTR strTemp;
  130. VariantInit ( &var );
  131. hr = SafeArrayGetElement ( psaVariants, &i, &var );
  132. if ( FAILED(hr) ) {
  133. goto Exit;
  134. }
  135. strTemp = V_BSTR (&var);
  136. hr = SafeArrayPutElement ( psaStrings, &i, strTemp );
  137. if ( FAILED(hr) ) {
  138. goto Exit;
  139. }
  140. VariantClear (&var);
  141. }
  142. *ppsaStrings = psaStrings;
  143. Exit:
  144. return hr;
  145. }
  146. //$-------------------------------------------------------------------
  147. //
  148. // StdPropertyGet < BSTR, long, DWORD, DATE >
  149. //
  150. // Description:
  151. //
  152. // Performs a default Property Get on a BSTR, long, DWORD or
  153. // Ole DATE.
  154. //
  155. // Parameters:
  156. //
  157. // Property - The property to get.
  158. // pOut - The resulting copy.
  159. //
  160. // Returns:
  161. //
  162. // E_POINTER - invalid arguments
  163. // E_OUTOFMEMORY - Not enough memory to copy
  164. // NOERROR - success.
  165. //
  166. //--------------------------------------------------------------------
  167. HRESULT StdPropertyGet ( const BSTR strProperty, BSTR * pstrOut )
  168. {
  169. TraceQuietEnter ( "StdPropertyGet <BSTR>" );
  170. _ASSERT ( pstrOut != NULL );
  171. _ASSERT ( IS_VALID_OUT_PARAM ( pstrOut ) );
  172. if ( pstrOut == NULL ) {
  173. FatalTrace ( 0, "Bad return pointer" );
  174. return E_POINTER;
  175. }
  176. *pstrOut = NULL;
  177. if ( strProperty == NULL ) {
  178. // If the property is NULL, use a blank string:
  179. *pstrOut = ::SysAllocString ( _T("") );
  180. }
  181. else {
  182. _ASSERT ( IS_VALID_STRING ( strProperty ) );
  183. // Copy the property into the result:
  184. *pstrOut = ::SysAllocString ( strProperty );
  185. }
  186. if ( *pstrOut == NULL ) {
  187. // Allocation failed.
  188. FatalTrace ( 0, "Out of memory" );
  189. return E_OUTOFMEMORY;
  190. }
  191. return NOERROR;
  192. }
  193. HRESULT StdPropertyGet ( long lProperty, long * plOut )
  194. {
  195. TraceQuietEnter ( "StdPropertyGet <long>" );
  196. _ASSERT ( plOut != NULL );
  197. _ASSERT ( IS_VALID_OUT_PARAM ( plOut ) );
  198. if ( plOut == NULL ) {
  199. FatalTrace ( 0, "Bad return pointer" );
  200. return E_POINTER;
  201. }
  202. *plOut = lProperty;
  203. return NOERROR;
  204. }
  205. HRESULT StdPropertyGet ( DATE dateProperty, DATE * pdateOut )
  206. {
  207. TraceQuietEnter ( "StdPropertyGet <DATE>" );
  208. _ASSERT ( pdateOut != NULL );
  209. _ASSERT ( IS_VALID_OUT_PARAM ( pdateOut ) );
  210. if ( pdateOut == NULL ) {
  211. FatalTrace ( 0, "Bad return pointer" );
  212. return E_POINTER;
  213. }
  214. *pdateOut = dateProperty;
  215. return NOERROR;
  216. }
  217. HRESULT StdPropertyGet ( const CMultiSz * pmszProperty, SAFEARRAY ** ppsaStrings )
  218. {
  219. TraceFunctEnter ( "StdPropertyGet <MULTI_SZ>" );
  220. _ASSERT ( pmszProperty );
  221. _ASSERT ( IS_VALID_OUT_PARAM ( ppsaStrings ) );
  222. HRESULT hr = NOERROR;
  223. *ppsaStrings = pmszProperty->ToSafeArray ( );
  224. if ( *ppsaStrings == NULL ) {
  225. hr = E_OUTOFMEMORY;
  226. goto Exit;
  227. }
  228. Exit:
  229. TraceFunctLeave ();
  230. return hr;
  231. }
  232. HRESULT StdPropertyGetBit ( DWORD bvBitVector, DWORD dwBit, BOOL * pfOut )
  233. {
  234. _ASSERT ( IS_VALID_OUT_PARAM ( pfOut ) );
  235. if ( !pfOut ) {
  236. return E_POINTER;
  237. }
  238. *pfOut = GetBitFlag ( bvBitVector, dwBit );
  239. return NOERROR;
  240. }
  241. //$-------------------------------------------------------------------
  242. //
  243. // StdPropertyPut <BSTR, long, DWORD or DATE>
  244. //
  245. // Description:
  246. //
  247. // Performs a default Property Put on a BSTR, long, DWORD or
  248. // Ole date.
  249. //
  250. // Parameters:
  251. //
  252. // pProperty - The property to put.
  253. // New - The new value.
  254. // pbvChangedProps [optional] - Bit Vector which holds which
  255. // properties have changed.
  256. // dwBitMask [optional] - This property's bitmask for the
  257. // changed bit vector.
  258. //
  259. // Returns:
  260. //
  261. // E_POINTER - invalid arguments
  262. // E_OUTOFMEMORY - Not enough memory to copy
  263. // NOERROR - success.
  264. //
  265. //--------------------------------------------------------------------
  266. HRESULT StdPropertyPut (
  267. BSTR * pstrProperty,
  268. const BSTR strNew,
  269. DWORD * pbvChangedProps, // = NULL
  270. DWORD dwBitMask // = 0
  271. )
  272. {
  273. TraceQuietEnter ( "StdPropertyPut <BSTR>" );
  274. // Validate Parameters:
  275. _ASSERT ( pstrProperty != NULL );
  276. _ASSERT ( IS_VALID_OUT_PARAM ( pstrProperty ) );
  277. _ASSERT ( strNew != NULL );
  278. _ASSERT ( IS_VALID_STRING ( strNew ) );
  279. if ( pstrProperty == NULL ) {
  280. FatalTrace ( 0, "Bad property pointer" );
  281. return E_POINTER;
  282. }
  283. if ( strNew == NULL ) {
  284. FatalTrace ( 0, "Bad pointer" );
  285. return E_POINTER;
  286. }
  287. HRESULT hr = NOERROR;
  288. BSTR strCopy = NULL;
  289. // Copy the new string:
  290. strCopy = ::SysAllocString ( strNew );
  291. if ( strCopy == NULL ) {
  292. hr = E_OUTOFMEMORY;
  293. FatalTrace ( 0, "Out of memory" );
  294. goto Error;
  295. }
  296. // Update the changed bit, if necessary:
  297. if ( *pstrProperty && lstrcmp ( *pstrProperty, strCopy ) != 0 ) {
  298. UpdateChangedMask ( pbvChangedProps, dwBitMask );
  299. }
  300. // Replace the old property with the new one.
  301. SAFE_FREE_BSTR ( *pstrProperty );
  302. *pstrProperty = strCopy;
  303. Error:
  304. return hr;
  305. }
  306. HRESULT StdPropertyPut (
  307. long * plProperty,
  308. long lNew,
  309. DWORD * pbvChangedProps, // = NULL
  310. DWORD dwBitMask // = 0
  311. )
  312. {
  313. TraceQuietEnter ( "StdPropertyPut <long>" );
  314. _ASSERT ( plProperty != NULL );
  315. _ASSERT ( IS_VALID_OUT_PARAM ( plProperty ) );
  316. if ( plProperty == NULL ) {
  317. FatalTrace ( 0, "Bad pointer" );
  318. return E_POINTER;
  319. }
  320. if ( *plProperty != lNew ) {
  321. UpdateChangedMask ( pbvChangedProps, dwBitMask );
  322. }
  323. *plProperty = lNew;
  324. return NOERROR;
  325. }
  326. HRESULT StdPropertyPut (
  327. DATE * pdateProperty,
  328. DATE dateNew,
  329. DWORD * pbvChangedProps, // = NULL
  330. DWORD dwBitMask // = 0
  331. )
  332. {
  333. TraceQuietEnter ( "StdPropertyPut <DATE>" );
  334. _ASSERT ( pdateProperty != NULL );
  335. _ASSERT ( IS_VALID_OUT_PARAM ( pdateProperty ) );
  336. if ( pdateProperty == NULL ) {
  337. FatalTrace ( 0, "Bad pointer" );
  338. return E_POINTER;
  339. }
  340. if ( *pdateProperty != dateNew ) {
  341. UpdateChangedMask ( pbvChangedProps, dwBitMask );
  342. }
  343. *pdateProperty = dateNew;
  344. return NOERROR;
  345. }
  346. HRESULT StdPropertyPut ( CMultiSz * pmszProperty, SAFEARRAY * psaStrings, DWORD * pbvChangedProps, DWORD dwBitMask )
  347. {
  348. TraceFunctEnter ( "StdPropertyPut <MULTI_SZ>" );
  349. _ASSERT ( IS_VALID_IN_PARAM ( psaStrings ) );
  350. _ASSERT ( IS_VALID_OUT_PARAM ( pmszProperty ) );
  351. if ( psaStrings == NULL ) {
  352. FatalTrace ( 0, "Bad return pointer" );
  353. TraceFunctLeave ();
  354. return E_POINTER;
  355. }
  356. HRESULT hr = NOERROR;
  357. pmszProperty->FromSafeArray ( psaStrings );
  358. if ( !*pmszProperty ) {
  359. hr = E_OUTOFMEMORY;
  360. goto Exit;
  361. }
  362. // Don't want to deal with comparing these properties:
  363. UpdateChangedMask ( pbvChangedProps, dwBitMask );
  364. Exit:
  365. TraceFunctLeave ();
  366. return hr;
  367. }
  368. HRESULT StdPropertyPutBit ( DWORD * pbvBitVector, DWORD dwBit, BOOL fIn )
  369. {
  370. _ASSERT ( IS_VALID_OUT_PARAM ( pbvBitVector ) );
  371. _ASSERT ( dwBit );
  372. SetBitFlag ( pbvBitVector, dwBit, fIn );
  373. return NOERROR;
  374. }
  375. //$-------------------------------------------------------------------
  376. //
  377. // PV_MaxChars
  378. //
  379. // Description:
  380. //
  381. // Validates a string to make sure it's not too long.
  382. //
  383. // Parameters:
  384. //
  385. // strProperty - the string to check
  386. // nMaxChars - the maximum number of characters in the string,
  387. // not including the NULL terminator.
  388. //
  389. // Returns:
  390. //
  391. // FALSE if the string is too long.
  392. //
  393. //--------------------------------------------------------------------
  394. BOOL PV_MaxChars ( const BSTR strProperty, DWORD nMaxChars )
  395. {
  396. TraceQuietEnter ( "PV_MaxChars" );
  397. _ASSERT ( strProperty != NULL );
  398. _ASSERT ( IS_VALID_STRING ( strProperty ) );
  399. _ASSERT ( nMaxChars > 0 );
  400. if ( strProperty == NULL ) {
  401. // This error should be caught somewhere else.
  402. return TRUE;
  403. }
  404. if ( (DWORD) lstrlen ( strProperty ) > nMaxChars ) {
  405. ErrorTrace ( 0, "String too long" );
  406. return FALSE;
  407. }
  408. return TRUE;
  409. }
  410. //$-------------------------------------------------------------------
  411. //
  412. // PV_MinMax <int, dword>
  413. //
  414. // Description:
  415. //
  416. // Makes sure a property is within a given range.
  417. //
  418. // Parameters:
  419. //
  420. // nProperty - the value to test
  421. // nMin - The minimum value the property could have
  422. // nMax - The maximum value the property could have
  423. //
  424. // Returns:
  425. //
  426. // TRUE if the property is in the range (inclusive).
  427. //
  428. //--------------------------------------------------------------------
  429. BOOL PV_MinMax ( int nProperty, int nMin, int nMax )
  430. {
  431. TraceQuietEnter ( "PV_MinMax" );
  432. _ASSERT ( nMin <= nMax );
  433. if ( nProperty < nMin || nProperty > nMax ) {
  434. ErrorTrace ( 0, "Integer out of range" );
  435. return FALSE;
  436. }
  437. return TRUE;
  438. }
  439. BOOL PV_MinMax ( DWORD dwProperty, DWORD dwMin, DWORD dwMax )
  440. {
  441. TraceQuietEnter ( "PV_MinMax" );
  442. _ASSERT ( dwMin <= dwMax );
  443. if ( dwProperty < dwMin || dwProperty > dwMax ) {
  444. ErrorTrace ( 0, "Dword out of range" );
  445. return FALSE;
  446. }
  447. return TRUE;
  448. }
  449. BOOL PV_Boolean ( BOOL fProperty )
  450. {
  451. TraceQuietEnter ( "PV_Boolean" );
  452. if ( fProperty != TRUE && fProperty != FALSE ) {
  453. ErrorTrace ( 0, "Boolean property is not true or false" );
  454. return FALSE;
  455. }
  456. return TRUE;
  457. }
  458. //$-------------------------------------------------------------------
  459. //
  460. // StdPropertyGetIDispatch
  461. //
  462. // Description:
  463. //
  464. // Gets a IDispatch pointer for the given cLSID
  465. //
  466. // Parameters:
  467. //
  468. // clsid - OLE CLSID of the object
  469. // ppIDipsatch - the IDispatch pointer to that object.
  470. //
  471. // Returns:
  472. //
  473. // E_POINTER - invalid argument
  474. // NOERROR - Success
  475. // Others - defined by CoCreateInstance.
  476. //
  477. //--------------------------------------------------------------------
  478. HRESULT StdPropertyGetIDispatch (
  479. REFCLSID clsid,
  480. IDispatch ** ppIDispatch
  481. )
  482. {
  483. TraceFunctEnter ( "StdPropertyGetIDispatch" );
  484. CComPtr<IDispatch> pNewIDispatch;
  485. HRESULT hr = NOERROR;
  486. _ASSERT ( ppIDispatch );
  487. if ( ppIDispatch == NULL ) {
  488. FatalTrace ( 0, "Bad return pointer" );
  489. TraceFunctLeave ();
  490. return E_POINTER;
  491. }
  492. *ppIDispatch = NULL;
  493. hr = ::CoCreateInstance (
  494. clsid,
  495. NULL,
  496. CLSCTX_ALL,
  497. IID_IDispatch,
  498. (void **) &pNewIDispatch
  499. );
  500. if ( FAILED (hr) ) {
  501. DebugTraceX ( 0, "CoCreate(IDispatch) failed %x", hr );
  502. FatalTrace ( 0, "Failed to create IDispatch" );
  503. goto Exit;
  504. }
  505. *ppIDispatch = pNewIDispatch;
  506. pNewIDispatch->AddRef ();
  507. Exit:
  508. TraceFunctLeave ();
  509. return hr;
  510. // Destructor releases pNewIDispatch
  511. }
  512. //$-------------------------------------------------------------------
  513. //
  514. // InetAddressToString
  515. //
  516. // Description:
  517. //
  518. // Converts a DWORD with an ip address to a string in the form
  519. // "xxx.xxx.xxx.xxx"
  520. //
  521. // Parameters:
  522. //
  523. // dwAddress - The address to convert
  524. // wszAddress - The resulting string
  525. // cAddress - The maximum size of the resulting string
  526. //
  527. // Returns:
  528. //
  529. // TRUE if succeeded, FALSE otherwise.
  530. //
  531. //--------------------------------------------------------------------
  532. BOOL InetAddressToString ( DWORD dwAddress, LPWSTR wszAddress, DWORD cAddress )
  533. {
  534. TraceFunctEnter ( "InetAddressToString" );
  535. _ASSERT ( wszAddress );
  536. if ( wszAddress == NULL ) {
  537. FatalTrace ( 0, "Bad pointer" );
  538. TraceFunctLeave ();
  539. return FALSE;
  540. }
  541. struct in_addr addr;
  542. LPSTR szAnsiAddress;
  543. DWORD cchCopied;
  544. addr.s_addr = dwAddress;
  545. szAnsiAddress = inet_ntoa ( addr );
  546. if ( szAnsiAddress == NULL ) {
  547. ErrorTraceX ( 0, "inet_ntoa failed: %x", GetLastError() );
  548. TraceFunctLeave ();
  549. return FALSE;
  550. }
  551. cchCopied = MultiByteToWideChar (
  552. CP_ACP,
  553. MB_PRECOMPOSED,
  554. szAnsiAddress,
  555. -1,
  556. wszAddress,
  557. cAddress
  558. );
  559. if ( cchCopied == 0 ) {
  560. ErrorTraceX ( 0, "MultiByteToWideChar failed: %x", GetLastError() );
  561. TraceFunctLeave ();
  562. return FALSE;
  563. }
  564. TraceFunctLeave ();
  565. return TRUE;
  566. }
  567. //$-------------------------------------------------------------------
  568. //
  569. // StringToInetAddress
  570. //
  571. // Description:
  572. //
  573. // Converts a string in the form "xxx.xxx.xxx.xxx" to a DWORD
  574. // IP Address.
  575. //
  576. // Parameters:
  577. //
  578. // wszAddress - The string to convert
  579. // pdwAddress - The resulting address
  580. //
  581. // Returns:
  582. //
  583. // TRUE if succeeded, FALSE otherwise.
  584. //
  585. //--------------------------------------------------------------------
  586. BOOL StringToInetAddress ( LPCWSTR wszAddress, DWORD * pdwAddress )
  587. {
  588. TraceFunctEnter ( "StringToInetAddress" );
  589. _ASSERT ( wszAddress );
  590. _ASSERT ( pdwAddress );
  591. if ( wszAddress == NULL ) {
  592. FatalTrace ( 0, "Bad pointer" );
  593. TraceFunctLeave ();
  594. return FALSE;
  595. }
  596. if ( pdwAddress == NULL ) {
  597. FatalTrace ( 0, "Bad return pointer" );
  598. TraceFunctLeave ();
  599. return FALSE;
  600. }
  601. char szAnsiAddress[100];
  602. DWORD cchCopied;
  603. *pdwAddress = 0;
  604. cchCopied = WideCharToMultiByte (
  605. CP_ACP,
  606. 0,
  607. wszAddress,
  608. -1,
  609. szAnsiAddress,
  610. sizeof ( szAnsiAddress ),
  611. NULL,
  612. NULL
  613. );
  614. if ( cchCopied == 0 ) {
  615. ErrorTraceX ( 0, "MultiByteToWideChar failed: %x", GetLastError() );
  616. TraceFunctLeave ();
  617. return FALSE;
  618. }
  619. *pdwAddress = inet_addr ( szAnsiAddress );
  620. if ( !*pdwAddress ) {
  621. ErrorTraceX ( 0, "inet_addr failed: %x", GetLastError () );
  622. }
  623. TraceFunctLeave ();
  624. return TRUE;
  625. }