dxutil.cpp
上传用户:fengshi120
上传日期:2014-07-17
资源大小:6155k
文件大小:37k
源码类别:

3D图形编程

开发平台:

C/C++

  1. //-----------------------------------------------------------------------------
  2. // File: DXUtil.cpp
  3. //
  4. // Desc: Shortcut macros and functions for using DX objects
  5. //-----------------------------------------------------------------------------
  6. #ifndef STRICT
  7. #define STRICT
  8. #endif // !STRICT
  9. #include "stdafx.h"
  10. #include <windows.h>
  11. #include <mmsystem.h>
  12. #include <tchar.h>
  13. #include <stdio.h> 
  14. #include <stdarg.h>
  15. #include "DXUtil.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. #ifdef UNICODE
  22.     typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
  23. #else
  24.     typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd);
  25. #endif
  26. #ifndef UNDER_CE
  27. //-----------------------------------------------------------------------------
  28. // Name: DXUtil_GetDXSDKMediaPathCch()
  29. // Desc: Returns the DirectX SDK media path
  30. //       cchDest is the size in TCHARs of strDest.  Be careful not to 
  31. //       pass in sizeof(strDest) on UNICODE builds.
  32. //-----------------------------------------------------------------------------
  33. HRESULT DXUtil_GetDXSDKMediaPathCch( TCHAR* strDest, int cchDest )
  34. {
  35.     if( strDest == NULL || cchDest < 1 )
  36.         return E_INVALIDARG;
  37.     lstrcpy( strDest, TEXT("") );
  38.     // Open the appropriate registry key
  39.     HKEY  hKey;
  40.     LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  41.                                 _T("Software\Microsoft\DirectX SDK"),
  42.                                 0, KEY_READ, &hKey );
  43.     if( ERROR_SUCCESS != lResult )
  44.         return E_FAIL;
  45.     DWORD dwType;
  46.     DWORD dwSize = cchDest * sizeof(TCHAR);
  47.     lResult = RegQueryValueEx( hKey, _T("DX9J3SDK Samples Path"), NULL,
  48.                               &dwType, (BYTE*)strDest, &dwSize );
  49.     strDest[cchDest-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
  50.     RegCloseKey( hKey );
  51.     if( ERROR_SUCCESS != lResult )
  52.         return E_FAIL;
  53.     const TCHAR* strMedia = _T("\Media\");
  54.     if( lstrlen(strDest) + lstrlen(strMedia) < cchDest )
  55.         _tcscat( strDest, strMedia );
  56.     else
  57.         return E_INVALIDARG;
  58.     return S_OK;
  59. }
  60. #endif // !UNDER_CE
  61. #ifndef UNDER_CE
  62. //-----------------------------------------------------------------------------
  63. // Name: DXUtil_FindMediaFileCch()
  64. // Desc: Returns a valid path to a DXSDK media file
  65. //       cchDest is the size in TCHARs of strDestPath.  Be careful not to 
  66. //       pass in sizeof(strDest) on UNICODE builds.
  67. //-----------------------------------------------------------------------------
  68. HRESULT DXUtil_FindMediaFileCch( TCHAR* strDestPath, int cchDest, TCHAR* strFilename )
  69. {
  70.     HRESULT hr;
  71.     HANDLE file;
  72.     TCHAR* strShortNameTmp = NULL;
  73.     TCHAR strShortName[MAX_PATH];
  74.     int cchPath;
  75.     if( NULL==strFilename || NULL==strDestPath || cchDest < 1 )
  76.         return E_INVALIDARG;
  77.     lstrcpy( strDestPath, TEXT("") );
  78.     lstrcpy( strShortName, TEXT("") );
  79.     // Build full path name from strFileName (strShortName will be just the leaf filename)
  80.     cchPath = GetFullPathName(strFilename, cchDest, strDestPath, &strShortNameTmp);
  81.     if ((cchPath == 0) || (cchDest <= cchPath))
  82.         return E_FAIL;
  83.     if( strShortNameTmp )
  84.         lstrcpyn( strShortName, strShortNameTmp, MAX_PATH );
  85.     // first try to find the filename given a full path
  86.     file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  87.                        OPEN_EXISTING, 0, NULL );
  88.     if( INVALID_HANDLE_VALUE != file )
  89.     {
  90.         CloseHandle( file );
  91.         return S_OK;
  92.     }
  93.     
  94.     // next try to find the filename in the current working directory (path stripped)
  95.     file = CreateFile( strShortName, GENERIC_READ, FILE_SHARE_READ, NULL, 
  96.                        OPEN_EXISTING, 0, NULL );
  97.     if( INVALID_HANDLE_VALUE != file )
  98.     {
  99.         _tcsncpy( strDestPath, strShortName, cchDest );
  100.         strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
  101.         CloseHandle( file );
  102.         return S_OK;
  103.     }
  104.     
  105.     // last, check if the file exists in the media directory
  106.     if( FAILED( hr = DXUtil_GetDXSDKMediaPathCch( strDestPath, cchDest ) ) )
  107.         return hr;
  108.     if( lstrlen(strDestPath) + lstrlen(strShortName) < cchDest )
  109.         lstrcat( strDestPath, strShortName );
  110.     else
  111.         return E_INVALIDARG;
  112.     file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  113.                        OPEN_EXISTING, 0, NULL );
  114.     if( INVALID_HANDLE_VALUE != file )
  115.     {
  116.         CloseHandle( file );
  117.         return S_OK;
  118.     }
  119.     // On failure, just return the file as the path
  120.     _tcsncpy( strDestPath, strFilename, cchDest );
  121.     strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
  122.     return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  123. }
  124. #endif // !UNDER_CE
  125. //-----------------------------------------------------------------------------
  126. // Name: DXUtil_ReadStringRegKeyCch()
  127. // Desc: Helper function to read a registry key string
  128. //       cchDest is the size in TCHARs of strDest.  Be careful not to 
  129. //       pass in sizeof(strDest) on UNICODE builds.
  130. //-----------------------------------------------------------------------------
  131. HRESULT DXUtil_ReadStringRegKeyCch( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, 
  132.                                     DWORD cchDest, TCHAR* strDefault )
  133. {
  134.     DWORD dwType;
  135.     DWORD cbDest = cchDest * sizeof(TCHAR);
  136.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  137.                                           (BYTE*)strDest, &cbDest ) )
  138.     {
  139.         _tcsncpy( strDest, strDefault, cchDest );
  140.         strDest[cchDest-1] = 0;
  141.         if( dwType != REG_SZ )
  142.             return E_FAIL;
  143.         return S_OK;
  144.     }
  145.     return E_FAIL;
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Name: DXUtil_WriteStringRegKey()
  149. // Desc: Helper function to write a registry key string
  150. //-----------------------------------------------------------------------------
  151. HRESULT DXUtil_WriteStringRegKey( HKEY hKey, TCHAR* strRegName,
  152.                                   TCHAR* strValue )
  153. {
  154.     if( NULL == strValue )
  155.         return E_INVALIDARG;
  156.         
  157.     DWORD cbValue = ((DWORD)_tcslen(strValue)+1) * sizeof(TCHAR);
  158.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_SZ, 
  159.                                         (BYTE*)strValue, cbValue ) )
  160.         return E_FAIL;
  161.     return S_OK;
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Name: DXUtil_ReadIntRegKey()
  165. // Desc: Helper function to read a registry key int
  166. //-----------------------------------------------------------------------------
  167. HRESULT DXUtil_ReadIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD* pdwDest, 
  168.                               DWORD dwDefault )
  169. {
  170.     DWORD dwType;
  171.     DWORD dwLength = sizeof(DWORD);
  172.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  173.                                           (BYTE*)pdwDest, &dwLength ) )
  174.     {
  175.         *pdwDest = dwDefault;
  176.         if( dwType != REG_DWORD )
  177.             return E_FAIL;
  178.         return S_OK;
  179.     }
  180.     return E_FAIL;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Name: DXUtil_WriteIntRegKey()
  184. // Desc: Helper function to write a registry key int
  185. //-----------------------------------------------------------------------------
  186. HRESULT DXUtil_WriteIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD dwValue )
  187. {
  188.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
  189.                                         (BYTE*)&dwValue, sizeof(DWORD) ) )
  190.         return E_FAIL;
  191.     return S_OK;
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Name: DXUtil_ReadBoolRegKey()
  195. // Desc: Helper function to read a registry key BOOL
  196. //-----------------------------------------------------------------------------
  197. HRESULT DXUtil_ReadBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL* pbDest, 
  198.                               BOOL bDefault )
  199. {
  200.     DWORD dwType;
  201.     DWORD dwLength = sizeof(BOOL);
  202.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  203.                                           (BYTE*)pbDest, &dwLength ) )
  204.     {
  205.         *pbDest = bDefault;
  206.         if( dwType != REG_DWORD )
  207.             return E_FAIL;
  208.         return S_OK;
  209.     }
  210.     return E_FAIL;
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Name: DXUtil_WriteBoolRegKey()
  214. // Desc: Helper function to write a registry key BOOL
  215. //-----------------------------------------------------------------------------
  216. HRESULT DXUtil_WriteBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL bValue )
  217. {
  218.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
  219.                                         (BYTE*)&bValue, sizeof(BOOL) ) )
  220.         return E_FAIL;
  221.     return S_OK;
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Name: DXUtil_ReadGuidRegKey()
  225. // Desc: Helper function to read a registry key guid
  226. //-----------------------------------------------------------------------------
  227. HRESULT DXUtil_ReadGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID* pGuidDest, 
  228.                                GUID& guidDefault )
  229. {
  230.     DWORD dwType;
  231.     DWORD dwLength = sizeof(GUID);
  232.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  233.                                           (LPBYTE) pGuidDest, &dwLength ) )
  234.     {
  235.         *pGuidDest = guidDefault;
  236.         if( dwType != REG_BINARY )
  237.             return E_FAIL;
  238.         return S_OK;
  239.     }
  240.     return E_FAIL;
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Name: DXUtil_WriteGuidRegKey()
  244. // Desc: Helper function to write a registry key guid
  245. //-----------------------------------------------------------------------------
  246. HRESULT DXUtil_WriteGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID guidValue )
  247. {
  248.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_BINARY, 
  249.                                         (BYTE*)&guidValue, sizeof(GUID) ) )
  250.         return E_FAIL;
  251.     return S_OK;
  252. }
  253. //-----------------------------------------------------------------------------
  254. // Name: DXUtil_Timer()
  255. // Desc: Performs timer opertations. Use the following commands:
  256. //          TIMER_RESET           - to reset the timer
  257. //          TIMER_START           - to start the timer
  258. //          TIMER_STOP            - to stop (or pause) the timer
  259. //          TIMER_ADVANCE         - to advance the timer by 0.1 seconds
  260. //          TIMER_GETABSOLUTETIME - to get the absolute system time
  261. //          TIMER_GETAPPTIME      - to get the current time
  262. //          TIMER_GETELAPSEDTIME  - to get the time that elapsed between 
  263. //                                  TIMER_GETELAPSEDTIME calls
  264. //-----------------------------------------------------------------------------
  265. FLOAT __stdcall DXUtil_Timer( TIMER_COMMAND command )
  266. {
  267.     static BOOL     m_bTimerInitialized = FALSE;
  268.     static BOOL     m_bUsingQPF         = FALSE;
  269.     static BOOL     m_bTimerStopped     = TRUE;
  270.     static LONGLONG m_llQPFTicksPerSec  = 0;
  271.     // Initialize the timer
  272.     if( FALSE == m_bTimerInitialized )
  273.     {
  274.         m_bTimerInitialized = TRUE;
  275.         // Use QueryPerformanceFrequency() to get frequency of timer.  If QPF is
  276.         // not supported, we will timeGetTime() which returns milliseconds.
  277.         LARGE_INTEGER qwTicksPerSec;
  278.         m_bUsingQPF = QueryPerformanceFrequency( &qwTicksPerSec );
  279.         if( m_bUsingQPF )
  280.             m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;
  281.     }
  282.     if( m_bUsingQPF )
  283.     {
  284.         static LONGLONG m_llStopTime        = 0;
  285.         static LONGLONG m_llLastElapsedTime = 0;
  286.         static LONGLONG m_llBaseTime        = 0;
  287.         double fTime;
  288.         double fElapsedTime;
  289.         LARGE_INTEGER qwTime;
  290.         
  291.         // Get either the current time or the stop time, depending
  292.         // on whether we're stopped and what command was sent
  293.         if( m_llStopTime != 0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
  294.             qwTime.QuadPart = m_llStopTime;
  295.         else
  296.             QueryPerformanceCounter( &qwTime );
  297.         // Return the elapsed time
  298.         if( command == TIMER_GETELAPSEDTIME )
  299.         {
  300.             fElapsedTime = (double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec;
  301.             m_llLastElapsedTime = qwTime.QuadPart;
  302.             return (FLOAT) fElapsedTime;
  303.         }
  304.     
  305.         // Return the current time
  306.         if( command == TIMER_GETAPPTIME )
  307.         {
  308.             double fAppTime = (double) ( qwTime.QuadPart - m_llBaseTime ) / (double) m_llQPFTicksPerSec;
  309.             return (FLOAT) fAppTime;
  310.         }
  311.     
  312.         // Reset the timer
  313.         if( command == TIMER_RESET )
  314.         {
  315.             m_llBaseTime        = qwTime.QuadPart;
  316.             m_llLastElapsedTime = qwTime.QuadPart;
  317.             m_llStopTime        = 0;
  318.             m_bTimerStopped     = FALSE;
  319.             return 0.0f;
  320.         }
  321.     
  322.         // Start the timer
  323.         if( command == TIMER_START )
  324.         {
  325.             if( m_bTimerStopped )
  326.                 m_llBaseTime += qwTime.QuadPart - m_llStopTime;
  327.             m_llStopTime = 0;
  328.             m_llLastElapsedTime = qwTime.QuadPart;
  329.             m_bTimerStopped = FALSE;
  330.             return 0.0f;
  331.         }
  332.     
  333.         // Stop the timer
  334.         if( command == TIMER_STOP )
  335.         {
  336.             if( !m_bTimerStopped )
  337.             {
  338.                 m_llStopTime = qwTime.QuadPart;
  339.                 m_llLastElapsedTime = qwTime.QuadPart;
  340.                 m_bTimerStopped = TRUE;
  341.             }
  342.             return 0.0f;
  343.         }
  344.     
  345.         // Advance the timer by 1/10th second
  346.         if( command == TIMER_ADVANCE )
  347.         {
  348.             m_llStopTime += m_llQPFTicksPerSec/10;
  349.             return 0.0f;
  350.         }
  351.         if( command == TIMER_GETABSOLUTETIME )
  352.         {
  353.             fTime = qwTime.QuadPart / (double) m_llQPFTicksPerSec;
  354.             return (FLOAT) fTime;
  355.         }
  356.         return -1.0f; // Invalid command specified
  357.     }
  358.     else
  359.     {
  360.         // Get the time using timeGetTime()
  361.         static double m_fLastElapsedTime  = 0.0;
  362.         static double m_fBaseTime         = 0.0;
  363.         static double m_fStopTime         = 0.0;
  364.         double fTime;
  365.         double fElapsedTime;
  366.         
  367.         // Get either the current time or the stop time, depending
  368.         // on whether we're stopped and what command was sent
  369.         if( m_fStopTime != 0.0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
  370.             fTime = m_fStopTime;
  371.         else
  372.             fTime = GETTIMESTAMP() * 0.001;
  373.     
  374.         // Return the elapsed time
  375.         if( command == TIMER_GETELAPSEDTIME )
  376.         {   
  377.             fElapsedTime = (double) (fTime - m_fLastElapsedTime);
  378.             m_fLastElapsedTime = fTime;
  379.             return (FLOAT) fElapsedTime;
  380.         }
  381.     
  382.         // Return the current time
  383.         if( command == TIMER_GETAPPTIME )
  384.         {
  385.             return (FLOAT) (fTime - m_fBaseTime);
  386.         }
  387.     
  388.         // Reset the timer
  389.         if( command == TIMER_RESET )
  390.         {
  391.             m_fBaseTime         = fTime;
  392.             m_fLastElapsedTime  = fTime;
  393.             m_fStopTime         = 0;
  394.             m_bTimerStopped     = FALSE;
  395.             return 0.0f;
  396.         }
  397.     
  398.         // Start the timer
  399.         if( command == TIMER_START )
  400.         {
  401.             if( m_bTimerStopped )
  402.                 m_fBaseTime += fTime - m_fStopTime;
  403.             m_fStopTime = 0.0f;
  404.             m_fLastElapsedTime  = fTime;
  405.             m_bTimerStopped = FALSE;
  406.             return 0.0f;
  407.         }
  408.     
  409.         // Stop the timer
  410.         if( command == TIMER_STOP )
  411.         {
  412.             if( !m_bTimerStopped )
  413.             {
  414.                 m_fStopTime = fTime;
  415.                 m_fLastElapsedTime  = fTime;
  416.                 m_bTimerStopped = TRUE;
  417.             }
  418.             return 0.0f;
  419.         }
  420.     
  421.         // Advance the timer by 1/10th second
  422.         if( command == TIMER_ADVANCE )
  423.         {
  424.             m_fStopTime += 0.1f;
  425.             return 0.0f;
  426.         }
  427.         if( command == TIMER_GETABSOLUTETIME )
  428.         {
  429.             return (FLOAT) fTime;
  430.         }
  431.         return -1.0f; // Invalid command specified
  432.     }
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Name: DXUtil_ConvertAnsiStringToWideCch()
  436. // Desc: This is a UNICODE conversion utility to convert a CHAR string into a
  437. //       WCHAR string. 
  438. //       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
  439. //       pass in sizeof(strDest) 
  440. //-----------------------------------------------------------------------------
  441. HRESULT DXUtil_ConvertAnsiStringToWideCch( WCHAR* wstrDestination, const CHAR* strSource, 
  442.                                      int cchDestChar )
  443. {
  444.     if( wstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
  445.         return E_INVALIDARG;
  446.     int nResult = MultiByteToWideChar( CP_ACP, 0, strSource, -1, 
  447.                                        wstrDestination, cchDestChar );
  448.     wstrDestination[cchDestChar-1] = 0;
  449.     
  450.     if( nResult == 0 )
  451.         return E_FAIL;
  452.     return S_OK;
  453. }
  454. //-----------------------------------------------------------------------------
  455. // Name: DXUtil_ConvertWideStringToAnsi()
  456. // Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
  457. //       CHAR string. 
  458. //       cchDestChar is the size in TCHARs of strDestination
  459. //-----------------------------------------------------------------------------
  460. HRESULT DXUtil_ConvertWideStringToAnsiCch( CHAR* strDestination, const WCHAR* wstrSource, 
  461.                                      int cchDestChar )
  462. {
  463.     if( strDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
  464.         return E_INVALIDARG;
  465.     int nResult = WideCharToMultiByte( CP_ACP, 0, wstrSource, -1, strDestination, 
  466.                                        cchDestChar*sizeof(CHAR), NULL, NULL );
  467.     strDestination[cchDestChar-1] = 0;
  468.     
  469.     if( nResult == 0 )
  470.         return E_FAIL;
  471.     return S_OK;
  472. }
  473. //-----------------------------------------------------------------------------
  474. // Name: DXUtil_ConvertGenericStringToAnsi()
  475. // Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
  476. //       CHAR string. 
  477. //       cchDestChar is the size in TCHARs of strDestination
  478. //-----------------------------------------------------------------------------
  479. HRESULT DXUtil_ConvertGenericStringToAnsiCch( CHAR* strDestination, const TCHAR* tstrSource, 
  480.                                            int cchDestChar )
  481. {
  482.     if( strDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
  483.         return E_INVALIDARG;
  484. #ifdef _UNICODE
  485.     return DXUtil_ConvertWideStringToAnsiCch( strDestination, tstrSource, cchDestChar );
  486. #else
  487.     strncpy( strDestination, tstrSource, cchDestChar );
  488.     strDestination[cchDestChar-1] = '';
  489.     return S_OK;
  490. #endif   
  491. }
  492. //-----------------------------------------------------------------------------
  493. // Name: DXUtil_ConvertGenericStringToWide()
  494. // Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
  495. //       WCHAR string. 
  496. //       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
  497. //       pass in sizeof(strDest) 
  498. //-----------------------------------------------------------------------------
  499. HRESULT DXUtil_ConvertGenericStringToWideCch( WCHAR* wstrDestination, const TCHAR* tstrSource, 
  500.                                            int cchDestChar )
  501. {
  502.     if( wstrDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
  503.         return E_INVALIDARG;
  504. #ifdef _UNICODE
  505.     wcsncpy( wstrDestination, tstrSource, cchDestChar );
  506.     wstrDestination[cchDestChar-1] = L'';
  507.     return S_OK;
  508. #else
  509.     return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, tstrSource, cchDestChar );
  510. #endif    
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Name: DXUtil_ConvertAnsiStringToGeneric()
  514. // Desc: This is a UNICODE conversion utility to convert a CHAR string into a
  515. //       TCHAR string. 
  516. //       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
  517. //       pass in sizeof(strDest) on UNICODE builds
  518. //-----------------------------------------------------------------------------
  519. HRESULT DXUtil_ConvertAnsiStringToGenericCch( TCHAR* tstrDestination, const CHAR* strSource, 
  520.                                            int cchDestChar )
  521. {
  522.     if( tstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
  523.         return E_INVALIDARG;
  524.         
  525. #ifdef _UNICODE
  526.     return DXUtil_ConvertAnsiStringToWideCch( tstrDestination, strSource, cchDestChar );
  527. #else
  528.     strncpy( tstrDestination, strSource, cchDestChar );
  529.     tstrDestination[cchDestChar-1] = '';
  530.     return S_OK;
  531. #endif    
  532. }
  533. //-----------------------------------------------------------------------------
  534. // Name: DXUtil_ConvertAnsiStringToGeneric()
  535. // Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
  536. //       TCHAR string. 
  537. //       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
  538. //       pass in sizeof(strDest) on UNICODE builds
  539. //-----------------------------------------------------------------------------
  540. HRESULT DXUtil_ConvertWideStringToGenericCch( TCHAR* tstrDestination, const WCHAR* wstrSource, 
  541.                                            int cchDestChar )
  542. {
  543.     if( tstrDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
  544.         return E_INVALIDARG;
  545. #ifdef _UNICODE
  546.     wcsncpy( tstrDestination, wstrSource, cchDestChar );
  547.     tstrDestination[cchDestChar-1] = L'';    
  548.     return S_OK;
  549. #else
  550.     return DXUtil_ConvertWideStringToAnsiCch( tstrDestination, wstrSource, cchDestChar );
  551. #endif
  552. }
  553. //-----------------------------------------------------------------------------
  554. // Name: DXUtil_LaunchReadme()
  555. // Desc: Finds and opens the readme.txt for this sample
  556. //-----------------------------------------------------------------------------
  557. VOID DXUtil_LaunchReadme( HWND hWnd, TCHAR* strLoc )
  558. {
  559. #ifdef UNDER_CE
  560.     // This is not available on PocketPC
  561.     MessageBox( hWnd, TEXT("For operating instructions, please open the ")
  562.                       TEXT("readme.txt file included with the project."),
  563.                 TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
  564.     return;
  565. #else 
  566.     bool bSuccess = false;
  567.     bool bFound = false;
  568.     TCHAR strReadmePath[1024];
  569.     TCHAR strExeName[MAX_PATH];
  570.     TCHAR strExePath[MAX_PATH];
  571.     TCHAR strSamplePath[MAX_PATH];
  572.     TCHAR* strLastSlash = NULL;
  573.     lstrcpy( strReadmePath, TEXT("") );
  574.     lstrcpy( strExePath, TEXT("") );
  575.     lstrcpy( strExeName, TEXT("") );
  576.     lstrcpy( strSamplePath, TEXT("") );
  577.     // If the user provided a location for the readme, check there first.
  578.     if( strLoc )
  579.     {
  580.         HKEY  hKey;
  581.         LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  582.                                     _T("Software\Microsoft\DirectX SDK"),
  583.                                     0, KEY_READ, &hKey );
  584.         if( ERROR_SUCCESS == lResult )
  585.         {
  586.             DWORD dwType;
  587.             DWORD dwSize = MAX_PATH * sizeof(TCHAR);
  588.             lResult = RegQueryValueEx( hKey, _T("DX9J3SDK Samples Path"), NULL,
  589.                                       &dwType, (BYTE*)strSamplePath, &dwSize );
  590.             strSamplePath[MAX_PATH-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
  591.             
  592.             if( ERROR_SUCCESS == lResult )
  593.             {
  594.                 _sntprintf( strReadmePath, 1023, TEXT("%s\C++\%s\readme.txt"), 
  595.                             strSamplePath, strLoc );
  596.                 strReadmePath[1023] = 0;
  597.                 if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  598.                     bFound = TRUE;
  599.             }
  600.         }
  601.         RegCloseKey( hKey );
  602.     }
  603.     // Get the exe name, and exe path
  604.     GetModuleFileName( NULL, strExePath, MAX_PATH );
  605.     strExePath[MAX_PATH-1]=0;
  606.     strLastSlash = _tcsrchr( strExePath, TEXT('\') );
  607.     if( strLastSlash )
  608.     {
  609.         _tcsncpy( strExeName, &strLastSlash[1], MAX_PATH );
  610.         strExeName[MAX_PATH-1]=0;
  611.         // Chop the exe name from the exe path
  612.         *strLastSlash = 0;
  613.         // Chop the .exe from the exe name
  614.         strLastSlash = _tcsrchr( strExeName, TEXT('.') );
  615.         if( strLastSlash )
  616.             *strLastSlash = 0;
  617.     }
  618.     if( !bFound )
  619.     {
  620.         // Search in "%EXE_DIR%..%EXE_NAME%".  This matchs the DirectX SDK layout
  621.         _tcscpy( strReadmePath, strExePath );
  622.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\') );
  623.         if( strLastSlash )
  624.             *strLastSlash = 0;
  625.         lstrcat( strReadmePath, TEXT("\") );
  626.         lstrcat( strReadmePath, strExeName );
  627.         lstrcat( strReadmePath, TEXT("\readme.txt") );
  628.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  629.             bFound = TRUE;
  630.     }
  631.     if( !bFound )
  632.     {
  633.         // Search in "%EXE_DIR%"
  634.         _tcscpy( strReadmePath, strExePath );
  635.         lstrcat( strReadmePath, TEXT("\readme.txt") );
  636.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  637.             bFound = TRUE;
  638.     }
  639.     if( !bFound )
  640.     {
  641.         // Search in "%EXE_DIR%.."
  642.         _tcscpy( strReadmePath, strExePath );
  643.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\') );
  644.         if( strLastSlash )
  645.             *strLastSlash = 0;
  646.         lstrcat( strReadmePath, TEXT("\readme.txt") );
  647.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  648.             bFound = TRUE;
  649.     }
  650.     if( !bFound )
  651.     {
  652.         // Search in "%EXE_DIR%...."
  653.         _tcscpy( strReadmePath, strExePath );
  654.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\') );
  655.         if( strLastSlash )
  656.             *strLastSlash = 0;
  657.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\') );
  658.         if( strLastSlash )
  659.             *strLastSlash = 0;
  660.         lstrcat( strReadmePath, TEXT("\readme.txt") );
  661.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  662.             bFound = TRUE;
  663.     }
  664.     if( bFound )
  665.     {
  666.         // GetProcAddress for ShellExecute, so we don't have to include shell32.lib 
  667.         // in every project that uses dxutil.cpp
  668.         LPShellExecute pShellExecute = NULL;
  669.         HINSTANCE hInstShell32 = LoadLibrary(TEXT("shell32.dll"));
  670.         if (hInstShell32 != NULL)
  671.         {
  672. #ifdef UNICODE
  673.             pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteW"));
  674. #else
  675.             pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteA"));
  676. #endif
  677.             if( pShellExecute != NULL )
  678.             {
  679.                 if( pShellExecute( hWnd, TEXT("open"), strReadmePath, NULL, NULL, SW_SHOW ) > (HINSTANCE) 32 )
  680.                     bSuccess = true;
  681.             }
  682.             FreeLibrary(hInstShell32);
  683.         }
  684.     }
  685.     if( !bSuccess )
  686.     {
  687.         // Tell the user that the readme couldn't be opened
  688.         MessageBox( hWnd, TEXT("Could not find readme.txt"), 
  689.                     TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
  690.     }
  691. #endif // UNDER_CE
  692. }
  693. //-----------------------------------------------------------------------------
  694. // Name: DXUtil_Trace()
  695. // Desc: Outputs to the debug stream a formatted string with a variable-
  696. //       argument list.
  697. //-----------------------------------------------------------------------------
  698. VOID DXUtil_Trace( TCHAR* strMsg, ... )
  699. {
  700. #if defined(DEBUG) | defined(_DEBUG)
  701.     TCHAR strBuffer[512];
  702.     
  703.     va_list args;
  704.     va_start(args, strMsg);
  705.     _vsntprintf( strBuffer, 512, strMsg, args );
  706.     va_end(args);
  707.     OutputDebugString( strBuffer );
  708. #else
  709.     UNREFERENCED_PARAMETER(strMsg);
  710. #endif
  711. }
  712. //-----------------------------------------------------------------------------
  713. // Name: DXUtil_ConvertStringToGUID()
  714. // Desc: Converts a string to a GUID
  715. //-----------------------------------------------------------------------------
  716. HRESULT DXUtil_ConvertStringToGUID( const TCHAR* strSrc, GUID* pGuidDest )
  717. {
  718.     UINT aiTmp[10];
  719.     if( _stscanf( strSrc, TEXT("{%8X-%4X-%4X-%2X%2X-%2X%2X%2X%2X%2X%2X}"),
  720.                     &pGuidDest->Data1, 
  721.                     &aiTmp[0], &aiTmp[1], 
  722.                     &aiTmp[2], &aiTmp[3],
  723.                     &aiTmp[4], &aiTmp[5],
  724.                     &aiTmp[6], &aiTmp[7],
  725.                     &aiTmp[8], &aiTmp[9] ) != 11 )
  726.     {
  727.         ZeroMemory( pGuidDest, sizeof(GUID) );
  728.         return E_FAIL;
  729.     }
  730.     else
  731.     {
  732.         pGuidDest->Data2       = (USHORT) aiTmp[0];
  733.         pGuidDest->Data3       = (USHORT) aiTmp[1];
  734.         pGuidDest->Data4[0]    = (BYTE) aiTmp[2];
  735.         pGuidDest->Data4[1]    = (BYTE) aiTmp[3];
  736.         pGuidDest->Data4[2]    = (BYTE) aiTmp[4];
  737.         pGuidDest->Data4[3]    = (BYTE) aiTmp[5];
  738.         pGuidDest->Data4[4]    = (BYTE) aiTmp[6];
  739.         pGuidDest->Data4[5]    = (BYTE) aiTmp[7];
  740.         pGuidDest->Data4[6]    = (BYTE) aiTmp[8];
  741.         pGuidDest->Data4[7]    = (BYTE) aiTmp[9];
  742.         return S_OK;
  743.     }
  744. }
  745. //-----------------------------------------------------------------------------
  746. // Name: DXUtil_ConvertGUIDToStringCch()
  747. // Desc: Converts a GUID to a string 
  748. //       cchDestChar is the size in TCHARs of strDest.  Be careful not to 
  749. //       pass in sizeof(strDest) on UNICODE builds
  750. //-----------------------------------------------------------------------------
  751. HRESULT DXUtil_ConvertGUIDToStringCch( const GUID* pGuidSrc, TCHAR* strDest, int cchDestChar )
  752. {
  753.     int nResult = _sntprintf( strDest, cchDestChar, TEXT("{%0.8X-%0.4X-%0.4X-%0.2X%0.2X-%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X}"),
  754.                pGuidSrc->Data1, pGuidSrc->Data2, pGuidSrc->Data3,
  755.                pGuidSrc->Data4[0], pGuidSrc->Data4[1],
  756.                pGuidSrc->Data4[2], pGuidSrc->Data4[3],
  757.                pGuidSrc->Data4[4], pGuidSrc->Data4[5],
  758.                pGuidSrc->Data4[6], pGuidSrc->Data4[7] );
  759.     if( nResult < 0 )
  760.         return E_FAIL;
  761.     return S_OK;
  762. }
  763. //-----------------------------------------------------------------------------
  764. // Name: CArrayList constructor
  765. // Desc: 
  766. //-----------------------------------------------------------------------------
  767. CArrayList::CArrayList( ArrayListType Type, UINT BytesPerEntry )
  768. {
  769.     if( Type == AL_REFERENCE )
  770.         BytesPerEntry = sizeof(void*);
  771.     m_ArrayListType = Type;
  772.     m_pData = NULL;
  773.     m_BytesPerEntry = BytesPerEntry;
  774.     m_NumEntries = 0;
  775.     m_NumEntriesAllocated = 0;
  776. }
  777. //-----------------------------------------------------------------------------
  778. // Name: CArrayList destructor
  779. // Desc: 
  780. //-----------------------------------------------------------------------------
  781. CArrayList::~CArrayList( void )
  782. {
  783.     if( m_pData != NULL )
  784.         delete[] m_pData;
  785. }
  786. //-----------------------------------------------------------------------------
  787. // Name: CArrayList::Add
  788. // Desc: Adds pEntry to the list.
  789. //-----------------------------------------------------------------------------
  790. HRESULT CArrayList::Add( void* pEntry )
  791. {
  792.     if( m_BytesPerEntry == 0 )
  793.         return E_FAIL;
  794.     if( m_pData == NULL || m_NumEntries + 1 > m_NumEntriesAllocated )
  795.     {
  796.         void* pDataNew;
  797.         UINT NumEntriesAllocatedNew;
  798.         if( m_NumEntriesAllocated == 0 )
  799.             NumEntriesAllocatedNew = 16;
  800.         else
  801.             NumEntriesAllocatedNew = m_NumEntriesAllocated * 2;
  802.         pDataNew = new BYTE[NumEntriesAllocatedNew * m_BytesPerEntry];
  803.         if( pDataNew == NULL )
  804.             return E_OUTOFMEMORY;
  805.         if( m_pData != NULL )
  806.         {
  807.             CopyMemory( pDataNew, m_pData, m_NumEntries * m_BytesPerEntry );
  808.             delete[] m_pData;
  809.         }
  810.         m_pData = pDataNew;
  811.         m_NumEntriesAllocated = NumEntriesAllocatedNew;
  812.     }
  813.     if( m_ArrayListType == AL_VALUE )
  814.         CopyMemory( (BYTE*)m_pData + (m_NumEntries * m_BytesPerEntry), pEntry, m_BytesPerEntry );
  815.     else
  816.         *(((void**)m_pData) + m_NumEntries) = pEntry;
  817.     m_NumEntries++;
  818.     return S_OK;
  819. }
  820. //-----------------------------------------------------------------------------
  821. // Name: CArrayList::Remove
  822. // Desc: Remove the item at Entry in the list, and collapse the array. 
  823. //-----------------------------------------------------------------------------
  824. void CArrayList::Remove( UINT Entry )
  825. {
  826.     // Decrement count
  827.     m_NumEntries--;
  828.     // Find the entry address
  829.     BYTE* pData = (BYTE*)m_pData + (Entry * m_BytesPerEntry);
  830.     // Collapse the array
  831.     MoveMemory( pData, pData + m_BytesPerEntry, ( m_NumEntries - Entry ) * m_BytesPerEntry );
  832. }
  833. //-----------------------------------------------------------------------------
  834. // Name: CArrayList::GetPtr
  835. // Desc: Returns a pointer to the Entry'th entry in the list.
  836. //-----------------------------------------------------------------------------
  837. void* CArrayList::GetPtr( UINT Entry )
  838. {
  839.     if( m_ArrayListType == AL_VALUE )
  840.         return (BYTE*)m_pData + (Entry * m_BytesPerEntry);
  841.     else
  842.         return *(((void**)m_pData) + Entry);
  843. }
  844. //-----------------------------------------------------------------------------
  845. // Name: CArrayList::Contains
  846. // Desc: Returns whether the list contains an entry identical to the 
  847. //       specified entry data.
  848. //-----------------------------------------------------------------------------
  849. bool CArrayList::Contains( void* pEntryData )
  850. {
  851.     for( UINT iEntry = 0; iEntry < m_NumEntries; iEntry++ )
  852.     {
  853.         if( m_ArrayListType == AL_VALUE )
  854.         {
  855.             if( memcmp( GetPtr(iEntry), pEntryData, m_BytesPerEntry ) == 0 )
  856.                 return true;
  857.         }
  858.         else
  859.         {
  860.             if( GetPtr(iEntry) == pEntryData )
  861.                 return true;
  862.         }
  863.     }
  864.     return false;
  865. }
  866. //-----------------------------------------------------------------------------
  867. // Name: BYTE helper functions
  868. // Desc: cchDestChar is the size in BYTEs of strDest.  Be careful not to 
  869. //       pass use sizeof() if the strDest is a string pointer.  
  870. //       eg.
  871. //       TCHAR* sz = new TCHAR[100]; // sizeof(sz)  == 4
  872. //       TCHAR sz2[100];             // sizeof(sz2) == 200
  873. //-----------------------------------------------------------------------------
  874. HRESULT DXUtil_ConvertAnsiStringToWideCb( WCHAR* wstrDestination, const CHAR* strSource, int cbDestChar )
  875. {
  876.     return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, strSource, cbDestChar / sizeof(WCHAR) );
  877. }
  878. HRESULT DXUtil_ConvertWideStringToAnsiCb( CHAR* strDestination, const WCHAR* wstrSource, int cbDestChar )
  879. {
  880.     return DXUtil_ConvertWideStringToAnsiCch( strDestination, wstrSource, cbDestChar / sizeof(CHAR) );
  881. }
  882. HRESULT DXUtil_ConvertGenericStringToAnsiCb( CHAR* strDestination, const TCHAR* tstrSource, int cbDestChar )
  883. {
  884.     return DXUtil_ConvertGenericStringToAnsiCch( strDestination, tstrSource, cbDestChar / sizeof(CHAR) );
  885. }
  886. HRESULT DXUtil_ConvertGenericStringToWideCb( WCHAR* wstrDestination, const TCHAR* tstrSource, int cbDestChar )
  887. {
  888.     return DXUtil_ConvertGenericStringToWideCch( wstrDestination, tstrSource, cbDestChar / sizeof(WCHAR) );
  889. }
  890. HRESULT DXUtil_ConvertAnsiStringToGenericCb( TCHAR* tstrDestination, const CHAR* strSource, int cbDestChar )
  891. {
  892.     return DXUtil_ConvertAnsiStringToGenericCch( tstrDestination, strSource, cbDestChar / sizeof(TCHAR) );
  893. }
  894. HRESULT DXUtil_ConvertWideStringToGenericCb( TCHAR* tstrDestination, const WCHAR* wstrSource, int cbDestChar )
  895. {
  896.     return DXUtil_ConvertWideStringToGenericCch( tstrDestination, wstrSource, cbDestChar / sizeof(TCHAR) );
  897. }
  898. HRESULT DXUtil_ReadStringRegKeyCb( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, DWORD cbDest, TCHAR* strDefault )
  899. {
  900.     return DXUtil_ReadStringRegKeyCch( hKey, strRegName, strDest, cbDest / sizeof(TCHAR), strDefault );
  901. }
  902. HRESULT DXUtil_ConvertGUIDToStringCb( const GUID* pGuidSrc, TCHAR* strDest, int cbDestChar )
  903. {
  904.     return DXUtil_ConvertGUIDToStringCch( pGuidSrc, strDest, cbDestChar / sizeof(TCHAR) );
  905. }
  906. #ifndef UNDER_CE
  907. HRESULT DXUtil_GetDXSDKMediaPathCb( TCHAR* szDest, int cbDest )
  908. {
  909.     return DXUtil_GetDXSDKMediaPathCch( szDest, cbDest / sizeof(TCHAR) );
  910. }
  911. HRESULT DXUtil_FindMediaFileCb( TCHAR* szDestPath, int cbDest, TCHAR* strFilename )
  912. {
  913.     return DXUtil_FindMediaFileCch( szDestPath, cbDest / sizeof(TCHAR), strFilename );
  914. }
  915. #endif // !UNDER_CE