Leaked source code of windows server 2003
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.

1390 lines
35 KiB

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