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.

1297 lines
30 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // LoadString.cpp
  7. //
  8. // Description:
  9. // LoadStringIntoBSTR implementation.
  10. //
  11. // Maintained By:
  12. // David Potter (DavidP) 01-FEB-2001
  13. // Geoffrey Pease (GPease) 22-MAY-2000
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #include "Pch.h"
  17. #include "LoadString.h"
  18. //////////////////////////////////////////////////////////////////////////////
  19. // Global Variables
  20. //////////////////////////////////////////////////////////////////////////////
  21. const WCHAR g_szWbemClientDLL[] = L"\\WBEM\\WMIUTILS.DLL";
  22. //////////////////////////////////////////////////////////////////////////////
  23. //++
  24. //
  25. // HrLoadStringIntoBSTR
  26. //
  27. // Description:
  28. // Retrieves the string resource idsIn from the string table and makes it
  29. // into a BSTR. If the BSTR is not NULL coming it, it will assume that
  30. // you are trying reuse an existing BSTR.
  31. //
  32. // Arguments:
  33. // hInstanceIn
  34. // Handle to an instance of the module whose executable file
  35. // contains the string resource. If not specified, defaults to
  36. // g_hInstance.
  37. //
  38. // langidIn
  39. // Language ID of string table resource.
  40. //
  41. // idsIn
  42. // Specifies the integer identifier of the string to be loaded.
  43. //
  44. // pbstrInout
  45. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  46. // may be the same or NULL.
  47. //
  48. // Return Values:
  49. // S_OK
  50. // The call succeeded.
  51. //
  52. // E_OUTOFMEMORY
  53. // Out of memory.
  54. //
  55. // E_POINTER
  56. // pbstrInout is NULL.
  57. //
  58. // Other HRESULTs
  59. // The call failed.
  60. //
  61. // Remarks:
  62. // This routine uses LoadResource so that it can get the actual length
  63. // of the string resource. If we didn't do this, we would need to call
  64. // LoadString and allocate memory in a loop. Very inefficient!
  65. //
  66. //--
  67. //////////////////////////////////////////////////////////////////////////////
  68. HRESULT
  69. HrLoadStringIntoBSTR(
  70. HINSTANCE hInstanceIn
  71. , LANGID langidIn
  72. , UINT idsIn
  73. , BSTR * pbstrInout
  74. )
  75. {
  76. TraceFunc1( "idsIn = %d", idsIn );
  77. HRESULT hr = S_OK;
  78. HRSRC hrsrc = NULL;
  79. HGLOBAL hgbl = NULL;
  80. PBYTE pbStringData;
  81. PBYTE pbStringDataMax;
  82. PBYTE pbStringTable;
  83. int cbStringTable;
  84. int nTable;
  85. int nOffset;
  86. int idxString;
  87. int iRet;
  88. int cch = 0;
  89. Assert( idsIn != 0 );
  90. Assert( pbstrInout != NULL );
  91. if ( pbstrInout == NULL )
  92. {
  93. goto InvalidPointer;
  94. }
  95. if ( hInstanceIn == NULL )
  96. {
  97. hInstanceIn = g_hInstance;
  98. }
  99. // The resource Id specified must be converted to an index into
  100. // a Windows StringTable.
  101. nTable = idsIn / 16;
  102. nOffset = idsIn - (nTable * 16);
  103. // Internal Table Id's start at 1 not 0.
  104. nTable++;
  105. //
  106. // Find the part of the string table where the string resides.
  107. //
  108. // Find the table containing the string.
  109. // First try to load the language specified. If we can't find it we
  110. // try the "neutral" language.
  111. hrsrc = FindResourceEx( hInstanceIn, RT_STRING, MAKEINTRESOURCE( nTable ), langidIn );
  112. if ( ( hrsrc == NULL ) && ( GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND ) )
  113. {
  114. hrsrc = FindResourceEx(
  115. hInstanceIn
  116. , RT_STRING
  117. , MAKEINTRESOURCE( nTable )
  118. , MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL )
  119. );
  120. }
  121. if ( hrsrc == NULL )
  122. {
  123. goto Win32Error;
  124. }
  125. // Load the table.
  126. hgbl = LoadResource( hInstanceIn, hrsrc );
  127. if ( hgbl == NULL )
  128. {
  129. goto Win32Error;
  130. }
  131. // Lock the table so we access its data.
  132. pbStringTable = reinterpret_cast< PBYTE >( LockResource( hgbl ) );
  133. if ( pbStringTable == NULL )
  134. {
  135. goto Win32Error;
  136. }
  137. cbStringTable = SizeofResource( hInstanceIn, hrsrc );
  138. Assert( cbStringTable != 0 );
  139. TraceFlow3( "HrLoadStringIntoBSTR() - Table = %#.08x, cb = %d, offset = %d", pbStringTable, cbStringTable, nOffset );
  140. // Set the data pointer to the beginning of the table.
  141. pbStringData = pbStringTable;
  142. pbStringDataMax = pbStringTable + cbStringTable;
  143. //
  144. // Skip strings in the block of 16 which are before the desired string.
  145. //
  146. for ( idxString = 0 ; idxString <= nOffset ; idxString++ )
  147. {
  148. Assert( pbStringData != NULL );
  149. Assert( pbStringData < pbStringDataMax );
  150. // Get the number of characters excluding the '\0'.
  151. cch = * ( (USHORT *) pbStringData );
  152. TraceFlow3( "HrLoadStringIntoBSTR() - pbStringData[ %d ] = %#.08x, cch = %d", idxString, pbStringData, cch );
  153. // Found the string.
  154. if ( idxString == nOffset )
  155. {
  156. if ( cch == 0 )
  157. {
  158. goto NotFound;
  159. }
  160. // Skip over the string length to get the string.
  161. pbStringData += sizeof( WCHAR );
  162. break;
  163. } // if: found the string
  164. // Add one to account for the string length.
  165. // A string length of 0 still takes 1 WCHAR for the length portion.
  166. cch++;
  167. // Skip over this string to get to the next string.
  168. pbStringData += ( cch * sizeof( WCHAR ) );
  169. } // for: each string in the block of 16 strings in the table
  170. // Note: nStringLen is the number of characters in the string not including the '\0'.
  171. AssertMsg( cch > 0, "Length of string in resource file cannot be zero." );
  172. //
  173. // Allocate a BSTR for the string.
  174. //
  175. if ( *pbstrInout == NULL )
  176. {
  177. //
  178. // BUGBUG: 23-FEB-2001 GalenB
  179. //
  180. // The memory tracking is complaining bitterly, and often, about this allocation leaking.
  181. //
  182. *pbstrInout = TraceSysAllocStringLen( (OLECHAR *) pbStringData, cch );
  183. if ( *pbstrInout == NULL )
  184. {
  185. goto OutOfMemory;
  186. }
  187. } // if: no string allocated previously
  188. else
  189. {
  190. iRet = TraceSysReAllocStringLen( pbstrInout, (OLECHAR *) pbStringData, cch );
  191. if ( ! iRet )
  192. {
  193. goto OutOfMemory;
  194. }
  195. } // else: string was allocated previously
  196. TraceFlow1( "HrLoadStringIntoBSTR() - Loaded string = '%ws'", *pbstrInout );
  197. goto Cleanup;
  198. Win32Error:
  199. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  200. goto Cleanup;
  201. NotFound:
  202. hr = HRESULT_FROM_WIN32( TW32( ERROR_RESOURCE_NAME_NOT_FOUND ) );
  203. goto Cleanup;
  204. OutOfMemory:
  205. hr = E_OUTOFMEMORY;
  206. goto Cleanup;
  207. InvalidPointer:
  208. hr = THR( E_POINTER );
  209. goto Cleanup;
  210. Cleanup:
  211. HRETURN( hr );
  212. } //*** HrLoadStringIntoBSTR( langidIn )
  213. //////////////////////////////////////////////////////////////////////////////
  214. //++
  215. //
  216. // HrFormatStringIntoBSTR
  217. //
  218. // Description:
  219. // Format a string (specified by idsIn, a string resource ID) and
  220. // variable arguments into a BSTR using the FormatMessage() Win32 API.
  221. // If the BSTR is not NULL on entry, the BSTR will be reused.
  222. //
  223. // Calls HrFormatStringWithVAListIntoBSTR to perform the actual work.
  224. //
  225. // Arguments:
  226. // hInstanceIn
  227. // Handle to an instance of the module whose executable file
  228. // contains the string resource.
  229. //
  230. // langidIn
  231. // Language ID of string table resource.
  232. //
  233. // idsIn
  234. // Specifies the integer identifier of the string to be loaded.
  235. //
  236. // pbstrInout
  237. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  238. // may be the same or NULL.
  239. //
  240. // ...
  241. // Arguments for substitution points in the status text message.
  242. // The FormatMessage() API is used for formatting the string, so
  243. // substitution points must of the form %1!ws! and not %ws.
  244. //
  245. // Return Values:
  246. // S_OK
  247. // The call succeeded.
  248. //
  249. // Other HRESULTs
  250. // The call failed.
  251. //
  252. //--
  253. //////////////////////////////////////////////////////////////////////////////
  254. HRESULT
  255. HrFormatStringIntoBSTR(
  256. HINSTANCE hInstanceIn
  257. , LANGID langidIn
  258. , UINT idsIn
  259. , BSTR * pbstrInout
  260. , ...
  261. )
  262. {
  263. TraceFunc1( "ids = %d", idsIn );
  264. HRESULT hr;
  265. va_list valist;
  266. va_start( valist, pbstrInout );
  267. hr = HrFormatStringWithVAListIntoBSTR(
  268. hInstanceIn
  269. , langidIn
  270. , idsIn
  271. , pbstrInout
  272. , valist
  273. );
  274. va_end( valist );
  275. HRETURN( hr );
  276. } //*** HrFormatStringIntoBSTR( langidIn, idsIn )
  277. //////////////////////////////////////////////////////////////////////////////
  278. //++
  279. //
  280. // HrFormatStringWithVAListIntoBSTR
  281. //
  282. // Description:
  283. // Format a string (specified by idsIn, a string resource ID) and
  284. // variable arguments into a BSTR using the FormatMessage() Win32 API.
  285. // If the BSTR is not NULL on entry, the BSTR will be reused.
  286. //
  287. // Arguments:
  288. // hInstanceIn
  289. // Handle to an instance of the module whose executable file
  290. // contains the string resource.
  291. //
  292. // langidIn
  293. // Language ID of string table resource.
  294. //
  295. // idsIn
  296. // Specifies the integer identifier of the string to be loaded.
  297. //
  298. // pbstrInout
  299. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  300. // may be the same or NULL.
  301. //
  302. // valistIn
  303. // Arguments for substitution points in the status text message.
  304. // The FormatMessage() API is used for formatting the string, so
  305. // substitution points must of the form %1!ws! and not %ws.
  306. //
  307. // Return Values:
  308. // S_OK
  309. // The call succeeded.
  310. //
  311. // E_OUTOFMEMORY
  312. // Out of memory.
  313. //
  314. // E_POINTER
  315. // pbstrInout is NULL.
  316. //
  317. // Other HRESULTs
  318. // The call failed.
  319. //
  320. //--
  321. //////////////////////////////////////////////////////////////////////////////
  322. HRESULT
  323. HrFormatStringWithVAListIntoBSTR(
  324. HINSTANCE hInstanceIn
  325. , LANGID langidIn
  326. , UINT idsIn
  327. , BSTR * pbstrInout
  328. , va_list valistIn
  329. )
  330. {
  331. TraceFunc1( "ids = %d", idsIn );
  332. HRESULT hr = S_OK;
  333. BSTR bstrStringResource = NULL;
  334. DWORD cch;
  335. INT iRet;
  336. LPWSTR psz = NULL;
  337. Assert( pbstrInout != NULL );
  338. if ( pbstrInout == NULL )
  339. {
  340. goto InvalidPointer;
  341. }
  342. //
  343. // Load the string resource.
  344. //
  345. hr = HrLoadStringIntoBSTR( hInstanceIn, langidIn, idsIn, &bstrStringResource );
  346. if ( FAILED( hr ) )
  347. {
  348. goto Cleanup;
  349. }
  350. //
  351. // Format the message with the arguments.
  352. //
  353. cch = FormatMessage(
  354. ( FORMAT_MESSAGE_ALLOCATE_BUFFER
  355. | FORMAT_MESSAGE_FROM_STRING )
  356. , bstrStringResource
  357. , 0
  358. , 0
  359. , (LPWSTR) &psz
  360. , 0
  361. , &valistIn
  362. );
  363. AssertMsg( cch != 0, "Missing string??" );
  364. if ( cch == 0 )
  365. {
  366. goto Win32Error;
  367. }
  368. //
  369. // Copy the string to a BSTR.
  370. //
  371. if ( *pbstrInout == NULL )
  372. {
  373. *pbstrInout = TraceSysAllocStringLen( psz, cch );
  374. if ( *pbstrInout == NULL )
  375. {
  376. goto OutOfMemory;
  377. }
  378. }
  379. else
  380. {
  381. iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
  382. if ( ! iRet )
  383. {
  384. goto OutOfMemory;
  385. }
  386. }
  387. goto Cleanup;
  388. Win32Error:
  389. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  390. goto Cleanup;
  391. OutOfMemory:
  392. hr = E_OUTOFMEMORY;
  393. goto Cleanup;
  394. InvalidPointer:
  395. hr = THR( E_POINTER );
  396. goto Cleanup;
  397. Cleanup:
  398. TraceSysFreeString( bstrStringResource );
  399. LocalFree( psz );
  400. HRETURN( hr );
  401. } //*** HrFormatStringWithVAListIntoBSTR( langidIn, idsIn, valistIn )
  402. //////////////////////////////////////////////////////////////////////////////
  403. //++
  404. //
  405. // HrFormatStringIntoBSTR
  406. //
  407. // Description:
  408. // Format a string (specified by pcwszFmtIn) and variable arguments into
  409. // a BSTR using the FormatMessage() Win32 API. If the BSTR is not NULL
  410. // on entry, the BSTR will be reused.
  411. //
  412. // Calls HrFormatStringWithVAListIntoBSTR to perform the actual work.
  413. //
  414. // Arguments:
  415. // pcwszFmtIn
  416. // Specifies the format string.
  417. //
  418. // pbstrInout
  419. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  420. // may be the same or NULL.
  421. //
  422. // ...
  423. // Arguments for substitution points in the status text message.
  424. // The FormatMessage() API is used for formatting the string, so
  425. // substitution points must of the form %1!ws! and not %ws.
  426. //
  427. // Return Values:
  428. // S_OK
  429. // The call succeeded.
  430. //
  431. // Other HRESULTs
  432. // The call failed.
  433. //
  434. //--
  435. //////////////////////////////////////////////////////////////////////////////
  436. HRESULT
  437. HrFormatStringIntoBSTR(
  438. LPCWSTR pcwszFmtIn
  439. , BSTR * pbstrInout
  440. , ...
  441. )
  442. {
  443. TraceFunc1( "pcwszFmtIn = %ws", pcwszFmtIn );
  444. HRESULT hr;
  445. va_list valist;
  446. va_start( valist, pbstrInout );
  447. hr = HrFormatStringWithVAListIntoBSTR( pcwszFmtIn, pbstrInout, valist );
  448. va_end( valist );
  449. HRETURN( hr );
  450. } //*** HrFormatStringIntoBSTR( pcwszFmtIn )
  451. //////////////////////////////////////////////////////////////////////////////
  452. //++
  453. //
  454. // HrFormatStringWithVAListIntoBSTR
  455. //
  456. // Description:
  457. // Format a string (specified by pcwszFmtIn) and variable arguments into
  458. // a BSTR using the FormatMessage() Win32 API. If the BSTR is not NULL
  459. // on entry, the BSTR will be reused.
  460. //
  461. // Arguments:
  462. // pcwszFmtIn
  463. // Specifies the format string.
  464. //
  465. // pbstrInout
  466. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  467. // may be the same or NULL.
  468. //
  469. // valistIn
  470. // Arguments for substitution points in the status text message.
  471. // The FormatMessage() API is used for formatting the string, so
  472. // substitution points must of the form %1!ws! and not %ws.
  473. //
  474. // Return Values:
  475. // S_OK
  476. // The call succeeded.
  477. //
  478. // E_OUTOFMEMORY
  479. // Out of memory.
  480. //
  481. // E_POINTER
  482. // pcwszFmtIn or pbstrInout is NULL.
  483. //
  484. // Other HRESULTs
  485. // The call failed.
  486. //
  487. //--
  488. //////////////////////////////////////////////////////////////////////////////
  489. HRESULT
  490. HrFormatStringWithVAListIntoBSTR(
  491. LPCWSTR pcwszFmtIn
  492. , BSTR * pbstrInout
  493. , va_list valistIn
  494. )
  495. {
  496. TraceFunc1( "pcwszFmtIn = %ws", pcwszFmtIn );
  497. HRESULT hr = S_OK;
  498. DWORD cch;
  499. INT iRet;
  500. LPWSTR psz = NULL;
  501. if ( ( pbstrInout == NULL )
  502. || ( pcwszFmtIn == NULL ) )
  503. {
  504. goto InvalidPointer;
  505. }
  506. //
  507. // Format the message with the arguments.
  508. //
  509. cch = FormatMessage(
  510. ( FORMAT_MESSAGE_ALLOCATE_BUFFER
  511. | FORMAT_MESSAGE_FROM_STRING )
  512. , pcwszFmtIn
  513. , 0
  514. , 0
  515. , (LPWSTR) &psz
  516. , 0
  517. , &valistIn
  518. );
  519. AssertMsg( cch != 0, "Missing string??" );
  520. if ( cch == 0 )
  521. {
  522. goto Win32Error;
  523. }
  524. if ( *pbstrInout == NULL )
  525. {
  526. *pbstrInout = TraceSysAllocStringLen( psz, cch );
  527. if ( *pbstrInout == NULL )
  528. {
  529. goto OutOfMemory;
  530. }
  531. }
  532. else
  533. {
  534. iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
  535. if ( ! iRet )
  536. {
  537. goto OutOfMemory;
  538. }
  539. }
  540. goto Cleanup;
  541. Win32Error:
  542. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  543. goto Cleanup;
  544. OutOfMemory:
  545. hr = E_OUTOFMEMORY;
  546. goto Cleanup;
  547. InvalidPointer:
  548. hr = THR( E_POINTER );
  549. goto Cleanup;
  550. Cleanup:
  551. LocalFree( psz );
  552. HRETURN( hr );
  553. } //*** HrFormatStringWithVAListIntoBSTR( pcwszFmtIn, valistIn )
  554. //////////////////////////////////////////////////////////////////////////////
  555. //++
  556. //
  557. // HRESULT
  558. // HrFormatMessageIntoBSTR(
  559. // HINSTANCE hInstanceIn,
  560. // UINT uIDIn,
  561. // BSTR * pbstrInout,
  562. // ...
  563. // )
  564. //
  565. // Description:
  566. // Retrieves the format string from the string resource uIDIn using
  567. // FormatMessage.
  568. //
  569. // Arguments:
  570. // hInstanceIn
  571. // Handle to an instance of the module whose executable file
  572. // contains the string resource.
  573. //
  574. // uIDIn
  575. // Specifies the integer identifier of the string to be loaded.
  576. //
  577. // pbstrInout
  578. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  579. // may be the same or NULL.
  580. //
  581. // Return Values:
  582. // S_OK
  583. // The call succeeded.
  584. //
  585. // E_OUTOFMEMORY
  586. // Out of memory.
  587. //
  588. // E_POINTER
  589. // pbstrInout is NULL.
  590. //
  591. // other HRESULTs
  592. // The call failed.
  593. //
  594. //--
  595. //////////////////////////////////////////////////////////////////////////////
  596. HRESULT
  597. HrFormatMessageIntoBSTR(
  598. HINSTANCE hInstanceIn,
  599. UINT uIDIn,
  600. BSTR * pbstrInout,
  601. ...
  602. )
  603. {
  604. TraceFunc( "" );
  605. va_list valist;
  606. DWORD cch;
  607. INT iRet;
  608. LPWSTR psz = NULL;
  609. HRESULT hr = S_OK;
  610. DWORD dw;
  611. WCHAR szBuf[ 255 ];
  612. if ( pbstrInout == NULL )
  613. goto InvalidPointer;
  614. va_start( valist, pbstrInout );
  615. dw = LoadString( g_hInstance, uIDIn, szBuf, ARRAYSIZE( szBuf ) );
  616. AssertMsg( dw != 0, "Missing string??" );
  617. cch = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
  618. | FORMAT_MESSAGE_FROM_STRING,
  619. szBuf,
  620. 0,
  621. 0,
  622. (LPWSTR) &psz,
  623. 0,
  624. &valist
  625. );
  626. va_end( valist );
  627. AssertMsg( cch != 0, "Missing string??" );
  628. if ( cch == 0 )
  629. goto Win32Error;
  630. if ( *pbstrInout == NULL )
  631. {
  632. *pbstrInout = TraceSysAllocStringLen( psz, cch );
  633. if ( *pbstrInout == NULL )
  634. goto OutOfMemory;
  635. }
  636. else
  637. {
  638. iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
  639. if ( !iRet )
  640. goto OutOfMemory;
  641. }
  642. Cleanup:
  643. LocalFree( psz );
  644. HRETURN( hr );
  645. InvalidPointer:
  646. hr = THR( E_POINTER );
  647. goto Cleanup;
  648. Win32Error:
  649. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  650. goto Cleanup;
  651. OutOfMemory:
  652. hr = E_OUTOFMEMORY;
  653. goto Cleanup;
  654. } //*** HrFormatMessageIntoBSTR()
  655. //////////////////////////////////////////////////////////////////////////////
  656. //++
  657. //
  658. // HrFormatErrorIntoBSTR
  659. //
  660. // Description:
  661. // Retrieves the system error message associated with the HRESULT. If
  662. // additional arguments are specified, it will use them in the formatting
  663. // of the error string.
  664. //
  665. // Arguments:
  666. // hrIn
  667. // Error code to lookup the message for.
  668. //
  669. // pbstrInout
  670. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  671. // may be the same or NULL.
  672. //
  673. // ...
  674. // Arguments for substitution points in the status text message.
  675. // The FormatMessage() API is used for formatting the string, so
  676. // substitution points must of the form %1!ws! and not %ws.
  677. //
  678. // Return Values:
  679. // S_OK
  680. // The call succeeded.
  681. //
  682. // E_OUTOFMEMORY
  683. // Out of memory.
  684. //
  685. // E_POINTER
  686. // pbstrInout is NULL.
  687. //
  688. // other HRESULTs
  689. // The call failed.
  690. //
  691. //--
  692. //////////////////////////////////////////////////////////////////////////////
  693. HRESULT
  694. HrFormatErrorIntoBSTR(
  695. HRESULT hrIn
  696. , BSTR * pbstrInout
  697. , ...
  698. )
  699. {
  700. TraceFunc1( "hrIn = 0x%08x", hrIn );
  701. HRESULT hr = S_OK;
  702. va_list valist;
  703. va_start( valist, pbstrInout );
  704. hr = HrFormatErrorWithVAListIntoBSTR( hrIn, pbstrInout, valist );
  705. va_end( valist );
  706. HRETURN( hr );
  707. } //*** HrFormatErrorIntoBSTR()
  708. //////////////////////////////////////////////////////////////////////////////
  709. //++
  710. //
  711. // HrFormatErrorWithVAListIntoBSTR
  712. //
  713. // Description:
  714. // Retrieves the system error message associated with the HRESULT. If
  715. // additional arguments are specified, it will use them in the formatting
  716. // of the error string.
  717. //
  718. // Arguments:
  719. // hrIn
  720. // Error code to lookup the message for.
  721. //
  722. // pbstrInout
  723. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  724. // may be the same or NULL.
  725. //
  726. // valistIn
  727. // Arguments for substitution points in the status text message.
  728. // The FormatMessage() API is used for formatting the string, so
  729. // substitution points must of the form %1!ws! and not %ws.
  730. //
  731. // Return Values:
  732. // S_OK
  733. // The call succeeded.
  734. //
  735. // E_OUTOFMEMORY
  736. // Out of memory.
  737. //
  738. // E_POINTER
  739. // pbstrInout is NULL.
  740. //
  741. // other HRESULTs
  742. // The call failed.
  743. //
  744. //--
  745. //////////////////////////////////////////////////////////////////////////////
  746. HRESULT
  747. HrFormatErrorWithVAListIntoBSTR(
  748. HRESULT hrIn
  749. , BSTR * pbstrInout
  750. , va_list valistIn
  751. )
  752. {
  753. TraceFunc1( "hrIn = 0x%08x", hrIn );
  754. HRESULT hr = S_OK;
  755. DWORD sc = 0;
  756. DWORD cch;
  757. INT iRet;
  758. LPWSTR psz = NULL;
  759. HMODULE hModule = NULL;
  760. LPWSTR pszSysDir = NULL;
  761. UINT cchSysDir = MAX_PATH + 1;
  762. LPWSTR pszModule = NULL;
  763. size_t cchModule = 0;
  764. Assert( pbstrInout != NULL );
  765. if ( pbstrInout == NULL )
  766. {
  767. goto InvalidPointer;
  768. } // if:
  769. cch = FormatMessageW(
  770. ( FORMAT_MESSAGE_ALLOCATE_BUFFER
  771. | FORMAT_MESSAGE_FROM_SYSTEM
  772. /*| FORMAT_MESSAGE_IGNORE_INSERTS*/ )
  773. , NULL
  774. , hrIn
  775. , MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL )
  776. , (LPWSTR) &psz
  777. , 0
  778. , &valistIn
  779. );
  780. //
  781. // If the error message was not found then try WMIUtils since we know
  782. // that their error messages are not propertly located for a system lookup.
  783. //
  784. if ( cch == 0 )
  785. {
  786. pszSysDir = new WCHAR[ cchSysDir ];
  787. if ( pszSysDir == NULL )
  788. {
  789. goto OutOfMemory;
  790. } // if:
  791. sc = GetSystemDirectoryW( pszSysDir, cchSysDir );
  792. if ( sc > ( cchSysDir - 1 ) )
  793. {
  794. delete [] pszSysDir;
  795. pszSysDir = NULL;
  796. cchSysDir = sc + 1;
  797. pszSysDir = new WCHAR[ cchSysDir ];
  798. if ( pszSysDir == NULL )
  799. {
  800. goto OutOfMemory;
  801. } // if:
  802. sc = GetSystemDirectoryW( pszSysDir, cchSysDir );
  803. } // if:
  804. if ( sc == 0 )
  805. {
  806. sc = TW32( GetLastError() );
  807. goto Win32Error;
  808. } // if:
  809. cchModule = wcslen( pszSysDir ) + wcslen( g_szWbemClientDLL ) + 1;
  810. pszModule = new WCHAR[ cchModule ];
  811. if ( pszModule == NULL )
  812. {
  813. goto OutOfMemory;
  814. } // if:
  815. wcscpy( pszModule, pszSysDir );
  816. wcscat( pszModule, g_szWbemClientDLL );
  817. hModule = LoadLibraryExW( pszModule, NULL, DONT_RESOLVE_DLL_REFERENCES );
  818. if ( hModule == NULL )
  819. {
  820. sc = TW32( GetLastError() );
  821. goto Win32Error;
  822. } // if:
  823. cch = FormatMessageW(
  824. ( FORMAT_MESSAGE_FROM_HMODULE
  825. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  826. /*| FORMAT_MESSAGE_IGNORE_INSERTS*/ )
  827. , hModule
  828. , hrIn
  829. , MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL )
  830. , (LPWSTR) &psz
  831. , 0
  832. , &valistIn
  833. );
  834. if ( cch == 0 )
  835. {
  836. sc = TW32( GetLastError() );
  837. } // if:
  838. } // if:
  839. AssertMsg( cch != 0, "Missing string??" );
  840. if ( cch == 0 )
  841. {
  842. goto Win32Error;
  843. }
  844. if ( *pbstrInout == NULL )
  845. {
  846. *pbstrInout = TraceSysAllocStringLen( psz, cch );
  847. if ( *pbstrInout == NULL )
  848. {
  849. goto OutOfMemory;
  850. }
  851. }
  852. else
  853. {
  854. iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
  855. if ( ! iRet )
  856. {
  857. goto OutOfMemory;
  858. }
  859. }
  860. //
  861. // Remove CR's and LF's since they aren't printable and usually mess up
  862. // the text when displayed.
  863. //
  864. for( cch = 0 ; cch < SysStringLen( *pbstrInout ) ; cch ++ )
  865. {
  866. if ( ( (*pbstrInout)[ cch ] == L'\n' )
  867. || ( (*pbstrInout)[ cch ] == L'\r' ) )
  868. {
  869. (*pbstrInout)[ cch ] = L' ';
  870. } // if:
  871. } // for:
  872. goto Cleanup;
  873. Win32Error:
  874. hr = HRESULT_FROM_WIN32( sc );
  875. goto Cleanup;
  876. OutOfMemory:
  877. hr = E_OUTOFMEMORY;
  878. goto Cleanup;
  879. InvalidPointer:
  880. hr = THR( E_POINTER );
  881. goto Cleanup;
  882. Cleanup:
  883. if ( psz != NULL )
  884. {
  885. LocalFree( psz );
  886. }
  887. delete [] pszModule;
  888. delete [] pszSysDir;
  889. if ( hModule != NULL )
  890. {
  891. FreeLibrary( hModule );
  892. } // if:
  893. HRETURN( hr );
  894. } //*** HrFormatErrorWithVAListIntoBSTR( valistIn )
  895. //////////////////////////////////////////////////////////////////////////////
  896. //++
  897. //
  898. // HrAnsiStringToBSTR
  899. //
  900. // Description:
  901. // Convert and ANSI string into a BSTR.
  902. //
  903. // Arguments:
  904. // pcszAnsiIn
  905. // Pointer to the ANSI string to convert.
  906. //
  907. // pbstrOut
  908. // Pointer to the BSTR to receive the string.HrAnsiStringToBSTR
  909. //
  910. // Return Values:
  911. // S_OK
  912. // The call succeeded.
  913. //
  914. // S_FALSE
  915. // The input string was NULL.
  916. //
  917. // E_OUTOFMEMORY
  918. // Out of memory.
  919. //
  920. // E_POINTER
  921. // pbstrOut is NULL.
  922. //
  923. // other HRESULTs
  924. // The call failed.
  925. //
  926. //--
  927. //////////////////////////////////////////////////////////////////////////////
  928. HRESULT
  929. HrAnsiStringToBSTR( LPCSTR pcszAnsiIn, BSTR * pbstrOut )
  930. {
  931. TraceFunc( "" );
  932. HRESULT hr = S_OK;
  933. BSTR bstr = NULL;
  934. DWORD cch;
  935. DWORD sc;
  936. int nRet;
  937. if ( pbstrOut == NULL )
  938. {
  939. hr = THR( E_POINTER );
  940. goto Cleanup;
  941. } // if:
  942. if ( pcszAnsiIn == NULL )
  943. {
  944. *pbstrOut = NULL;
  945. hr = S_FALSE;
  946. goto Cleanup;
  947. } // if:
  948. //
  949. // Determine number of wide characters to be allocated for the
  950. // Unicode string.
  951. //
  952. cch = (DWORD) strlen( pcszAnsiIn ) + 1;
  953. bstr = TraceSysAllocStringLen( NULL, cch );
  954. if ( bstr == NULL )
  955. {
  956. hr = THR( E_OUTOFMEMORY );
  957. goto Cleanup;
  958. } // if:
  959. nRet = MultiByteToWideChar( CP_ACP, 0, pcszAnsiIn, cch, bstr, cch );
  960. if ( nRet == 0 )
  961. {
  962. sc = TW32( GetLastError() );
  963. hr = HRESULT_FROM_WIN32( sc );
  964. goto Cleanup;
  965. } // if:
  966. *pbstrOut = bstr;
  967. Cleanup:
  968. HRETURN( hr );
  969. } //*** HrAnsiStringToBSTR()
  970. //////////////////////////////////////////////////////////////////////////////
  971. //++
  972. //
  973. // HrConcatenateBSTRs
  974. //
  975. // Description:
  976. // Concatenate one BSTR onto another one.
  977. //
  978. // Arguments:
  979. // pbstrDstInout
  980. // Specifies the destination BSTR.
  981. //
  982. // bstrSrcIn
  983. // Specifies the source BSTR whose contents will be concatenated
  984. // onto pbstrDstInout.
  985. //
  986. // Return Values:
  987. // S_OK
  988. // The call succeeded.
  989. //
  990. // Other HRESULTs
  991. // The call failed.
  992. //
  993. //--
  994. //////////////////////////////////////////////////////////////////////////////
  995. HRESULT
  996. HrConcatenateBSTRs(
  997. BSTR * pbstrDstInout
  998. , BSTR bstrSrcIn
  999. )
  1000. {
  1001. TraceFunc1( "bstrSrcIn = %ws", bstrSrcIn );
  1002. HRESULT hr = S_OK;
  1003. Assert( pbstrDstInout != NULL );
  1004. Assert( bstrSrcIn != NULL );
  1005. if ( *pbstrDstInout == NULL )
  1006. {
  1007. *pbstrDstInout = TraceSysAllocString( bstrSrcIn );
  1008. if ( pbstrDstInout == NULL )
  1009. {
  1010. hr = E_OUTOFMEMORY;
  1011. goto Cleanup;
  1012. }
  1013. } // if: no destination string specified
  1014. else
  1015. {
  1016. UINT cchSrc;
  1017. UINT cchDst;
  1018. BSTR bstr = NULL;
  1019. cchSrc = SysStringLen( bstrSrcIn );
  1020. cchDst = SysStringLen( *pbstrDstInout );
  1021. bstr = TraceSysAllocStringLen( NULL, cchSrc + cchDst + 1 );
  1022. if ( bstr == NULL )
  1023. {
  1024. hr = E_OUTOFMEMORY;
  1025. goto Cleanup;
  1026. }
  1027. wcscpy( bstr, *pbstrDstInout );
  1028. wcscat( bstr, bstrSrcIn );
  1029. SysFreeString( *pbstrDstInout );
  1030. *pbstrDstInout = bstr;
  1031. } // else: destination string was specified
  1032. Cleanup:
  1033. HRETURN( hr );
  1034. } //*** HrConcatenateBSTRs()
  1035. //////////////////////////////////////////////////////////////////////////////
  1036. //++
  1037. //
  1038. // HrFormatGuidIntoBSTR
  1039. //
  1040. // Description:
  1041. // Format a GUID into a BSTR. If the BSTR is not NULL on entry,
  1042. // the BSTR will be reused.
  1043. //
  1044. // Arguments:
  1045. // pguidIn
  1046. // Specifies the GUID to format into a string.
  1047. //
  1048. // pbstrInout
  1049. // Pointer to the BSTR to receive the string. On a failure, the BSTR
  1050. // may be the same or NULL.
  1051. //
  1052. // Return Values:
  1053. // S_OK
  1054. // The call succeeded.
  1055. //
  1056. // Other HRESULTs
  1057. // The call failed.
  1058. //
  1059. //--
  1060. //////////////////////////////////////////////////////////////////////////////
  1061. HRESULT
  1062. HrFormatGuidIntoBSTR(
  1063. GUID * pguidIn
  1064. , BSTR * pbstrInout
  1065. )
  1066. {
  1067. TraceFunc( "" );
  1068. HRESULT hr = S_OK;
  1069. WCHAR wszGuid[ 64 ];
  1070. DWORD cch;
  1071. INT iRet;
  1072. if ( ( pbstrInout == NULL )
  1073. || ( pguidIn == NULL ) )
  1074. {
  1075. goto InvalidPointer;
  1076. }
  1077. cch = _snwprintf(
  1078. wszGuid
  1079. , ARRAYSIZE( wszGuid )
  1080. , L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"
  1081. , pguidIn->Data1
  1082. , pguidIn->Data2
  1083. , pguidIn->Data3
  1084. , pguidIn->Data4[ 0 ]
  1085. , pguidIn->Data4[ 1 ]
  1086. , pguidIn->Data4[ 2 ]
  1087. , pguidIn->Data4[ 3 ]
  1088. , pguidIn->Data4[ 4 ]
  1089. , pguidIn->Data4[ 5 ]
  1090. , pguidIn->Data4[ 6 ]
  1091. , pguidIn->Data4[ 7 ]
  1092. );
  1093. if ( *pbstrInout == NULL )
  1094. {
  1095. *pbstrInout = TraceSysAllocStringLen( wszGuid, cch );
  1096. if ( *pbstrInout == NULL )
  1097. {
  1098. goto OutOfMemory;
  1099. }
  1100. }
  1101. else
  1102. {
  1103. iRet = TraceSysReAllocStringLen( pbstrInout, wszGuid, cch );
  1104. if ( ! iRet )
  1105. {
  1106. goto OutOfMemory;
  1107. }
  1108. }
  1109. goto Cleanup;
  1110. OutOfMemory:
  1111. hr = E_OUTOFMEMORY;
  1112. goto Cleanup;
  1113. InvalidPointer:
  1114. hr = THR( E_POINTER );
  1115. goto Cleanup;
  1116. Cleanup:
  1117. HRETURN( hr );
  1118. } //*** HrFormatGuidIntoBSTR()