0001: //-----------------------------------------------------------------------------
0002: // File: DXUtil.cpp
0003: //
0004: // Desc: Shortcut macros and functions for using DX objects
0005: //-----------------------------------------------------------------------------
0006: #ifndef STRICT
0007: #define STRICT
0008: #endif // !STRICT
0009: #include <windows.h>
0010: #include <mmsystem.h>
0011: #include <tchar.h>
0012: #include <stdio.h> 
0013: #include <stdarg.h>
0014: #include "DXUtil.h"
0015: 
0016: 
0017: #ifdef UNICODE
0018:     typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
0019: #else
0020:     typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd);
0021: #endif
0022: 
0023: 
0024: #ifndef UNDER_CE
0025: //-----------------------------------------------------------------------------
0026: // Name: DXUtil_GetDXSDKMediaPathCch()
0027: // Desc: Returns the DirectX SDK media path
0028: //       cchDest is the size in TCHARs of strDest.  Be careful not to 
0029: //       pass in sizeof(strDest) on UNICODE builds.
0030: //-----------------------------------------------------------------------------
0031: HRESULT DXUtil_GetDXSDKMediaPathCch( TCHAR* strDest, int cchDest )
0032: {
0033:     if( strDest == NULL || cchDest < 1 )
0034:         return E_INVALIDARG;
0035: 
0036:     lstrcpy( strDest, TEXT("") );
0037: 
0038:     // Open the appropriate registry key
0039:     HKEY  hKey;
0040:     LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
0041:                                 _T("Software\\Microsoft\\DirectX SDK"),
0042:                                 0, KEY_READ, &hKey );
0043:     if( ERROR_SUCCESS != lResult )
0044:         return E_FAIL;
0045: 
0046:     DWORD dwType;
0047:     DWORD dwSize = cchDest * sizeof(TCHAR);
0048:     lResult = RegQueryValueEx( hKey, _T("DX9SDK Samples Path"), NULL,
0049:                               &dwType, (BYTE*)strDest, &dwSize );
0050:     strDest[cchDest-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
0051:     RegCloseKey( hKey );
0052: 
0053:     if( ERROR_SUCCESS != lResult )
0054:         return E_FAIL;
0055: 
0056:     const TCHAR* strMedia = _T("\\Media\\");
0057:     if( lstrlen(strDest) + lstrlen(strMedia) < cchDest )
0058:         _tcscat( strDest, strMedia );
0059:     else
0060:         return E_INVALIDARG;
0061: 
0062:     return S_OK;
0063: }
0064: #endif // !UNDER_CE
0065: 
0066: 
0067: 
0068: #ifndef UNDER_CE
0069: //-----------------------------------------------------------------------------
0070: // Name: DXUtil_FindMediaFileCch()
0071: // Desc: Returns a valid path to a DXSDK media file
0072: //       cchDest is the size in TCHARs of strDestPath.  Be careful not to 
0073: //       pass in sizeof(strDest) on UNICODE builds.
0074: //-----------------------------------------------------------------------------
0075: HRESULT DXUtil_FindMediaFileCch( TCHAR* strDestPath, int cchDest, TCHAR* strFilename )
0076: {
0077:     HRESULT hr;
0078:     HANDLE file;
0079:     TCHAR* strShortNameTmp = NULL;
0080:     TCHAR strShortName[MAX_PATH];
0081:     int cchPath;
0082: 
0083:     if( NULL==strFilename || NULL==strDestPath || cchDest < 1 )
0084:         return E_INVALIDARG;
0085: 
0086:     lstrcpy( strDestPath, TEXT("") );
0087:     lstrcpy( strShortName, TEXT("") );
0088: 
0089:     // Build full path name from strFileName (strShortName will be just the leaf filename)
0090:     cchPath = GetFullPathName(strFilename, cchDest, strDestPath, &strShortNameTmp);
0091:     if ((cchPath == 0) || (cchDest <= cchPath))
0092:         return E_FAIL;
0093:     if( strShortNameTmp )
0094:         lstrcpyn( strShortName, strShortNameTmp, MAX_PATH );
0095: 
0096:     // first try to find the filename given a full path
0097:     file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
0098:                        OPEN_EXISTING, 0, NULL );
0099:     if( INVALID_HANDLE_VALUE != file )
0100:     {
0101:         CloseHandle( file );
0102:         return S_OK;
0103:     }
0104:     
0105:     // next try to find the filename in the current working directory (path stripped)
0106:     file = CreateFile( strShortName, GENERIC_READ, FILE_SHARE_READ, NULL, 
0107:                        OPEN_EXISTING, 0, NULL );
0108:     if( INVALID_HANDLE_VALUE != file )
0109:     {
0110:         _tcsncpy( strDestPath, strShortName, cchDest );
0111:         strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
0112:         CloseHandle( file );
0113:         return S_OK;
0114:     }
0115:     
0116:     // last, check if the file exists in the media directory
0117:     if( FAILED( hr = DXUtil_GetDXSDKMediaPathCch( strDestPath, cchDest ) ) )
0118:         return hr;
0119: 
0120:     if( lstrlen(strDestPath) + lstrlen(strShortName) < cchDest )
0121:         lstrcat( strDestPath, strShortName );
0122:     else
0123:         return E_INVALIDARG;
0124: 
0125:     file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
0126:                        OPEN_EXISTING, 0, NULL );
0127:     if( INVALID_HANDLE_VALUE != file )
0128:     {
0129:         CloseHandle( file );
0130:         return S_OK;
0131:     }
0132: 
0133:     // On failure, just return the file as the path
0134:     _tcsncpy( strDestPath, strFilename, cchDest );
0135:     strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
0136:     return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
0137: }
0138: #endif // !UNDER_CE
0139: 
0140: 
0141: 
0142: 
0143: //-----------------------------------------------------------------------------
0144: // Name: DXUtil_ReadStringRegKeyCch()
0145: // Desc: Helper function to read a registry key string
0146: //       cchDest is the size in TCHARs of strDest.  Be careful not to 
0147: //       pass in sizeof(strDest) on UNICODE builds.
0148: //-----------------------------------------------------------------------------
0149: HRESULT DXUtil_ReadStringRegKeyCch( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, 
0150:                                     DWORD cchDest, TCHAR* strDefault )
0151: {
0152:     DWORD dwType;
0153:     DWORD cbDest = cchDest * sizeof(TCHAR);
0154: 
0155:     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
0156:                                           (BYTE*)strDest, &cbDest ) )
0157:     {
0158:         _tcsncpy( strDest, strDefault, cchDest );
0159:         strDest[cchDest-1] = 0;
0160: 
0161:         if( dwType != REG_SZ )
0162:             return E_FAIL;
0163: 
0164:         return S_OK;
0165:     }
0166: 
0167:     return E_FAIL;
0168: }
0169: 
0170: 
0171: 
0172: 
0173: //-----------------------------------------------------------------------------
0174: // Name: DXUtil_WriteStringRegKey()
0175: // Desc: Helper function to write a registry key string
0176: //-----------------------------------------------------------------------------
0177: HRESULT DXUtil_WriteStringRegKey( HKEY hKey, TCHAR* strRegName,
0178:                                   TCHAR* strValue )
0179: {
0180:     if( NULL == strValue )
0181:         return E_INVALIDARG;
0182:         
0183:     DWORD cbValue = ((DWORD)_tcslen(strValue)+1) * sizeof(TCHAR);
0184: 
0185:     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_SZ, 
0186:                                         (BYTE*)strValue, cbValue ) )
0187:         return E_FAIL;
0188: 
0189:     return S_OK;
0190: }
0191: 
0192: 
0193: 
0194: 
0195: //-----------------------------------------------------------------------------
0196: // Name: DXUtil_ReadIntRegKey()
0197: // Desc: Helper function to read a registry key int
0198: //-----------------------------------------------------------------------------
0199: HRESULT DXUtil_ReadIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD* pdwDest, 
0200:                               DWORD dwDefault )
0201: {
0202:     DWORD dwType;
0203:     DWORD dwLength = sizeof(DWORD);
0204: 
0205:     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
0206:                                           (BYTE*)pdwDest, &dwLength ) )
0207:     {
0208:         *pdwDest = dwDefault;
0209:         if( dwType != REG_DWORD )
0210:             return E_FAIL;
0211: 
0212:         return S_OK;
0213:     }
0214: 
0215:     return E_FAIL;
0216: }
0217: 
0218: 
0219: 
0220: 
0221: //-----------------------------------------------------------------------------
0222: // Name: DXUtil_WriteIntRegKey()
0223: // Desc: Helper function to write a registry key int
0224: //-----------------------------------------------------------------------------
0225: HRESULT DXUtil_WriteIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD dwValue )
0226: {
0227:     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
0228:                                         (BYTE*)&dwValue, sizeof(DWORD) ) )
0229:         return E_FAIL;
0230: 
0231:     return S_OK;
0232: }
0233: 
0234: 
0235: 
0236: 
0237: //-----------------------------------------------------------------------------
0238: // Name: DXUtil_ReadBoolRegKey()
0239: // Desc: Helper function to read a registry key BOOL
0240: //-----------------------------------------------------------------------------
0241: HRESULT DXUtil_ReadBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL* pbDest, 
0242:                               BOOL bDefault )
0243: {
0244:     DWORD dwType;
0245:     DWORD dwLength = sizeof(BOOL);
0246: 
0247:     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
0248:                                           (BYTE*)pbDest, &dwLength ) )
0249:     {
0250:         *pbDest = bDefault;
0251:         if( dwType != REG_DWORD )
0252:             return E_FAIL;
0253: 
0254:         return S_OK;
0255:     }
0256: 
0257:     return E_FAIL;
0258: }
0259: 
0260: 
0261: 
0262: 
0263: //-----------------------------------------------------------------------------
0264: // Name: DXUtil_WriteBoolRegKey()
0265: // Desc: Helper function to write a registry key BOOL
0266: //-----------------------------------------------------------------------------
0267: HRESULT DXUtil_WriteBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL bValue )
0268: {
0269:     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
0270:                                         (BYTE*)&bValue, sizeof(BOOL) ) )
0271:         return E_FAIL;
0272: 
0273:     return S_OK;
0274: }
0275: 
0276: 
0277: 
0278: 
0279: //-----------------------------------------------------------------------------
0280: // Name: DXUtil_ReadGuidRegKey()
0281: // Desc: Helper function to read a registry key guid
0282: //-----------------------------------------------------------------------------
0283: HRESULT DXUtil_ReadGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID* pGuidDest, 
0284:                                GUID& guidDefault )
0285: {
0286:     DWORD dwType;
0287:     DWORD dwLength = sizeof(GUID);
0288: 
0289:     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
0290:                                           (LPBYTE) pGuidDest, &dwLength ) )
0291:     {
0292:         *pGuidDest = guidDefault;
0293:         if( dwType != REG_BINARY )
0294:             return E_FAIL;
0295: 
0296:         return S_OK;
0297:     }
0298: 
0299:     return E_FAIL;
0300: }
0301: 
0302: 
0303: 
0304: 
0305: //-----------------------------------------------------------------------------
0306: // Name: DXUtil_WriteGuidRegKey()
0307: // Desc: Helper function to write a registry key guid
0308: //-----------------------------------------------------------------------------
0309: HRESULT DXUtil_WriteGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID guidValue )
0310: {
0311:     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_BINARY, 
0312:                                         (BYTE*)&guidValue, sizeof(GUID) ) )
0313:         return E_FAIL;
0314: 
0315:     return S_OK;
0316: }
0317: 
0318: 
0319: 
0320: 
0321: //-----------------------------------------------------------------------------
0322: // Name: DXUtil_Timer()
0323: // Desc: Performs timer opertations. Use the following commands:
0324: //          TIMER_RESET           - to reset the timer
0325: //          TIMER_START           - to start the timer
0326: //          TIMER_STOP            - to stop (or pause) the timer
0327: //          TIMER_ADVANCE         - to advance the timer by 0.1 seconds
0328: //          TIMER_GETABSOLUTETIME - to get the absolute system time
0329: //          TIMER_GETAPPTIME      - to get the current time
0330: //          TIMER_GETELAPSEDTIME  - to get the time that elapsed between 
0331: //                                  TIMER_GETELAPSEDTIME calls
0332: //-----------------------------------------------------------------------------
0333: FLOAT __stdcall DXUtil_Timer( TIMER_COMMAND command )
0334: {
0335:     static BOOL     m_bTimerInitialized = FALSE;
0336:     static BOOL     m_bUsingQPF         = FALSE;
0337:     static BOOL     m_bTimerStopped     = TRUE;
0338:     static LONGLONG m_llQPFTicksPerSec  = 0;
0339: 
0340:     // Initialize the timer
0341:     if( FALSE == m_bTimerInitialized )
0342:     {
0343:         m_bTimerInitialized = TRUE;
0344: 
0345:         // Use QueryPerformanceFrequency() to get frequency of timer.  If QPF is
0346:         // not supported, we will timeGetTime() which returns milliseconds.
0347:         LARGE_INTEGER qwTicksPerSec;
0348:         m_bUsingQPF = QueryPerformanceFrequency( &qwTicksPerSec );
0349:         if( m_bUsingQPF )
0350:             m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;
0351:     }
0352: 
0353:     if( m_bUsingQPF )
0354:     {
0355:         static LONGLONG m_llStopTime        = 0;
0356:         static LONGLONG m_llLastElapsedTime = 0;
0357:         static LONGLONG m_llBaseTime        = 0;
0358:         double fTime;
0359:         double fElapsedTime;
0360:         LARGE_INTEGER qwTime;
0361:         
0362:         // Get either the current time or the stop time, depending
0363:         // on whether we're stopped and what command was sent
0364:         if( m_llStopTime != 0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
0365:             qwTime.QuadPart = m_llStopTime;
0366:         else
0367:             QueryPerformanceCounter( &qwTime );
0368: 
0369:         // Return the elapsed time
0370:         if( command == TIMER_GETELAPSEDTIME )
0371:         {
0372:             fElapsedTime = (double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec;
0373:             m_llLastElapsedTime = qwTime.QuadPart;
0374:             return (FLOAT) fElapsedTime;
0375:         }
0376:     
0377:         // Return the current time
0378:         if( command == TIMER_GETAPPTIME )
0379:         {
0380:             double fAppTime = (double) ( qwTime.QuadPart - m_llBaseTime ) / (double) m_llQPFTicksPerSec;
0381:             return (FLOAT) fAppTime;
0382:         }
0383:     
0384:         // Reset the timer
0385:         if( command == TIMER_RESET )
0386:         {
0387:             m_llBaseTime        = qwTime.QuadPart;
0388:             m_llLastElapsedTime = qwTime.QuadPart;
0389:             m_llStopTime        = 0;
0390:             m_bTimerStopped     = FALSE;
0391:             return 0.0f;
0392:         }
0393:     
0394:         // Start the timer
0395:         if( command == TIMER_START )
0396:         {
0397:             if( m_bTimerStopped )
0398:                 m_llBaseTime += qwTime.QuadPart - m_llStopTime;
0399:             m_llStopTime = 0;
0400:             m_llLastElapsedTime = qwTime.QuadPart;
0401:             m_bTimerStopped = FALSE;
0402:             return 0.0f;
0403:         }
0404:     
0405:         // Stop the timer
0406:         if( command == TIMER_STOP )
0407:         {
0408:             if( !m_bTimerStopped )
0409:             {
0410:                 m_llStopTime = qwTime.QuadPart;
0411:                 m_llLastElapsedTime = qwTime.QuadPart;
0412:                 m_bTimerStopped = TRUE;
0413:             }
0414:             return 0.0f;
0415:         }
0416:     
0417:         // Advance the timer by 1/10th second
0418:         if( command == TIMER_ADVANCE )
0419:         {
0420:             m_llStopTime += m_llQPFTicksPerSec/10;
0421:             return 0.0f;
0422:         }
0423: 
0424:         if( command == TIMER_GETABSOLUTETIME )
0425:         {
0426:             fTime = qwTime.QuadPart / (double) m_llQPFTicksPerSec;
0427:             return (FLOAT) fTime;
0428:         }
0429: 
0430:         return -1.0f; // Invalid command specified
0431:     }
0432:     else
0433:     {
0434:         // Get the time using timeGetTime()
0435:         static double m_fLastElapsedTime  = 0.0;
0436:         static double m_fBaseTime         = 0.0;
0437:         static double m_fStopTime         = 0.0;
0438:         double fTime;
0439:         double fElapsedTime;
0440:         
0441:         // Get either the current time or the stop time, depending
0442:         // on whether we're stopped and what command was sent
0443:         if( m_fStopTime != 0.0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
0444:             fTime = m_fStopTime;
0445:         else
0446:             fTime = GETTIMESTAMP() * 0.001;
0447:     
0448:         // Return the elapsed time
0449:         if( command == TIMER_GETELAPSEDTIME )
0450:         {   
0451:             fElapsedTime = (double) (fTime - m_fLastElapsedTime);
0452:             m_fLastElapsedTime = fTime;
0453:             return (FLOAT) fElapsedTime;
0454:         }
0455:     
0456:         // Return the current time
0457:         if( command == TIMER_GETAPPTIME )
0458:         {
0459:             return (FLOAT) (fTime - m_fBaseTime);
0460:         }
0461:     
0462:         // Reset the timer
0463:         if( command == TIMER_RESET )
0464:         {
0465:             m_fBaseTime         = fTime;
0466:             m_fLastElapsedTime  = fTime;
0467:             m_fStopTime         = 0;
0468:             m_bTimerStopped     = FALSE;
0469:             return 0.0f;
0470:         }
0471:     
0472:         // Start the timer
0473:         if( command == TIMER_START )
0474:         {
0475:             if( m_bTimerStopped )
0476:                 m_fBaseTime += fTime - m_fStopTime;
0477:             m_fStopTime = 0.0f;
0478:             m_fLastElapsedTime  = fTime;
0479:             m_bTimerStopped = FALSE;
0480:             return 0.0f;
0481:         }
0482:     
0483:         // Stop the timer
0484:         if( command == TIMER_STOP )
0485:         {
0486:             if( !m_bTimerStopped )
0487:             {
0488:                 m_fStopTime = fTime;
0489:                 m_fLastElapsedTime  = fTime;
0490:                 m_bTimerStopped = TRUE;
0491:             }
0492:             return 0.0f;
0493:         }
0494:     
0495:         // Advance the timer by 1/10th second
0496:         if( command == TIMER_ADVANCE )
0497:         {
0498:             m_fStopTime += 0.1f;
0499:             return 0.0f;
0500:         }
0501: 
0502:         if( command == TIMER_GETABSOLUTETIME )
0503:         {
0504:             return (FLOAT) fTime;
0505:         }
0506: 
0507:         return -1.0f; // Invalid command specified
0508:     }
0509: }
0510: 
0511: 
0512: 
0513: 
0514: //-----------------------------------------------------------------------------
0515: // Name: DXUtil_ConvertAnsiStringToWideCch()
0516: // Desc: This is a UNICODE conversion utility to convert a CHAR string into a
0517: //       WCHAR string. 
0518: //       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
0519: //       pass in sizeof(strDest) 
0520: //-----------------------------------------------------------------------------
0521: HRESULT DXUtil_ConvertAnsiStringToWideCch( WCHAR* wstrDestination, const CHAR* strSource, 
0522:                                      int cchDestChar )
0523: {
0524:     if( wstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
0525:         return E_INVALIDARG;
0526: 
0527:     int nResult = MultiByteToWideChar( CP_ACP, 0, strSource, -1, 
0528:                                        wstrDestination, cchDestChar );
0529:     wstrDestination[cchDestChar-1] = 0;
0530:     
0531:     if( nResult == 0 )
0532:         return E_FAIL;
0533:     return S_OK;
0534: }
0535: 
0536: 
0537: 
0538: 
0539: //-----------------------------------------------------------------------------
0540: // Name: DXUtil_ConvertWideStringToAnsi()
0541: // Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
0542: //       CHAR string. 
0543: //       cchDestChar is the size in TCHARs of strDestination
0544: //-----------------------------------------------------------------------------
0545: HRESULT DXUtil_ConvertWideStringToAnsiCch( CHAR* strDestination, const WCHAR* wstrSource, 
0546:                                      int cchDestChar )
0547: {
0548:     if( strDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
0549:         return E_INVALIDARG;
0550: 
0551:     int nResult = WideCharToMultiByte( CP_ACP, 0, wstrSource, -1, strDestination, 
0552:                                        cchDestChar*sizeof(CHAR), NULL, NULL );
0553:     strDestination[cchDestChar-1] = 0;
0554:     
0555:     if( nResult == 0 )
0556:         return E_FAIL;
0557:     return S_OK;
0558: }
0559: 
0560: 
0561: 
0562: 
0563: //-----------------------------------------------------------------------------
0564: // Name: DXUtil_ConvertGenericStringToAnsi()
0565: // Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
0566: //       CHAR string. 
0567: //       cchDestChar is the size in TCHARs of strDestination
0568: //-----------------------------------------------------------------------------
0569: HRESULT DXUtil_ConvertGenericStringToAnsiCch( CHAR* strDestination, const TCHAR* tstrSource, 
0570:                                            int cchDestChar )
0571: {
0572:     if( strDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
0573:         return E_INVALIDARG;
0574: 
0575: #ifdef _UNICODE
0576:     return DXUtil_ConvertWideStringToAnsiCch( strDestination, tstrSource, cchDestChar );
0577: #else
0578:     strncpy( strDestination, tstrSource, cchDestChar );
0579:     strDestination[cchDestChar-1] = '\0';
0580:     return S_OK;
0581: #endif   
0582: }
0583: 
0584: 
0585: 
0586: 
0587: //-----------------------------------------------------------------------------
0588: // Name: DXUtil_ConvertGenericStringToWide()
0589: // Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
0590: //       WCHAR string. 
0591: //       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
0592: //       pass in sizeof(strDest) 
0593: //-----------------------------------------------------------------------------
0594: HRESULT DXUtil_ConvertGenericStringToWideCch( WCHAR* wstrDestination, const TCHAR* tstrSource, 
0595:                                            int cchDestChar )
0596: {
0597:     if( wstrDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
0598:         return E_INVALIDARG;
0599: 
0600: #ifdef _UNICODE
0601:     wcsncpy( wstrDestination, tstrSource, cchDestChar );
0602:     wstrDestination[cchDestChar-1] = L'\0';
0603:     return S_OK;
0604: #else
0605:     return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, tstrSource, cchDestChar );
0606: #endif    
0607: }
0608: 
0609: 
0610: 
0611: 
0612: //-----------------------------------------------------------------------------
0613: // Name: DXUtil_ConvertAnsiStringToGeneric()
0614: // Desc: This is a UNICODE conversion utility to convert a CHAR string into a
0615: //       TCHAR string. 
0616: //       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
0617: //       pass in sizeof(strDest) on UNICODE builds
0618: //-----------------------------------------------------------------------------
0619: HRESULT DXUtil_ConvertAnsiStringToGenericCch( TCHAR* tstrDestination, const CHAR* strSource, 
0620:                                            int cchDestChar )
0621: {
0622:     if( tstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
0623:         return E_INVALIDARG;
0624:         
0625: #ifdef _UNICODE
0626:     return DXUtil_ConvertAnsiStringToWideCch( tstrDestination, strSource, cchDestChar );
0627: #else
0628:     strncpy( tstrDestination, strSource, cchDestChar );
0629:     tstrDestination[cchDestChar-1] = '\0';
0630:     return S_OK;
0631: #endif    
0632: }
0633: 
0634: 
0635: 
0636: 
0637: //-----------------------------------------------------------------------------
0638: // Name: DXUtil_ConvertAnsiStringToGeneric()
0639: // Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
0640: //       TCHAR string. 
0641: //       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
0642: //       pass in sizeof(strDest) on UNICODE builds
0643: //-----------------------------------------------------------------------------
0644: HRESULT DXUtil_ConvertWideStringToGenericCch( TCHAR* tstrDestination, const WCHAR* wstrSource, 
0645:                                            int cchDestChar )
0646: {
0647:     if( tstrDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
0648:         return E_INVALIDARG;
0649: 
0650: #ifdef _UNICODE
0651:     wcsncpy( tstrDestination, wstrSource, cchDestChar );
0652:     tstrDestination[cchDestChar-1] = L'\0';    
0653:     return S_OK;
0654: #else
0655:     return DXUtil_ConvertWideStringToAnsiCch( tstrDestination, wstrSource, cchDestChar );
0656: #endif
0657: }
0658: 
0659: 
0660: 
0661: 
0662: 
0663: //-----------------------------------------------------------------------------
0664: // Name: DXUtil_LaunchReadme()
0665: // Desc: Finds and opens the readme.txt for this sample
0666: //-----------------------------------------------------------------------------
0667: VOID DXUtil_LaunchReadme( HWND hWnd, TCHAR* strLoc )
0668: {
0669: 
0670: #ifdef UNDER_CE
0671:     // This is not available on PocketPC
0672:     MessageBox( hWnd, TEXT("For operating instructions, please open the ")
0673:                       TEXT("readme.txt file included with the project."),
0674:                 TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
0675: 
0676:     return;
0677: #else 
0678: 
0679:     bool bSuccess = false;
0680:     bool bFound = false;
0681:     TCHAR strReadmePath[1024];
0682:     TCHAR strExeName[MAX_PATH];
0683:     TCHAR strExePath[MAX_PATH];
0684:     TCHAR strSamplePath[MAX_PATH];
0685:     TCHAR* strLastSlash = NULL;
0686: 
0687:     lstrcpy( strReadmePath, TEXT("") );
0688:     lstrcpy( strExePath, TEXT("") );
0689:     lstrcpy( strExeName, TEXT("") );
0690:     lstrcpy( strSamplePath, TEXT("") );
0691: 
0692:     // If the user provided a location for the readme, check there first.
0693:     if( strLoc )
0694:     {
0695:         HKEY  hKey;
0696:         LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
0697:                                     _T("Software\\Microsoft\\DirectX SDK"),
0698:                                     0, KEY_READ, &hKey );
0699:         if( ERROR_SUCCESS == lResult )
0700:         {
0701:             DWORD dwType;
0702:             DWORD dwSize = MAX_PATH * sizeof(TCHAR);
0703:             lResult = RegQueryValueEx( hKey, _T("DX9SDK Samples Path"), NULL,
0704:                                       &dwType, (BYTE*)strSamplePath, &dwSize );
0705:             strSamplePath[MAX_PATH-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
0706:             
0707:             if( ERROR_SUCCESS == lResult )
0708:             {
0709:                 _sntprintf( strReadmePath, 1023, TEXT("%s\\C++\\%s\\readme.txt"), 
0710:                             strSamplePath, strLoc );
0711:                 strReadmePath[1023] = 0;
0712: 
0713:                 if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
0714:                     bFound = TRUE;
0715:             }
0716:         }
0717: 
0718:         RegCloseKey( hKey );
0719:     }
0720: 
0721:     // Get the exe name, and exe path
0722:     GetModuleFileName( NULL, strExePath, MAX_PATH );
0723:     strExePath[MAX_PATH-1]=0;
0724: 
0725:     strLastSlash = _tcsrchr( strExePath, TEXT('\\') );
0726:     if( strLastSlash )
0727:     {
0728:         _tcsncpy( strExeName, &strLastSlash[1], MAX_PATH );
0729:         strExeName[MAX_PATH-1]=0;
0730: 
0731:         // Chop the exe name from the exe path
0732:         *strLastSlash = 0;
0733: 
0734:         // Chop the .exe from the exe name
0735:         strLastSlash = _tcsrchr( strExeName, TEXT('.') );
0736:         if( strLastSlash )
0737:             *strLastSlash = 0;
0738:     }
0739: 
0740:     if( !bFound )
0741:     {
0742:         // Search in "%EXE_DIR%\..\%EXE_NAME%".  This matchs the DirectX SDK layout
0743:         _tcscpy( strReadmePath, strExePath );
0744: 
0745:         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
0746:         if( strLastSlash )
0747:             *strLastSlash = 0;
0748:         lstrcat( strReadmePath, TEXT("\\") );
0749:         lstrcat( strReadmePath, strExeName );
0750:         lstrcat( strReadmePath, TEXT("\\readme.txt") );
0751:         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
0752:             bFound = TRUE;
0753:     }
0754: 
0755:     if( !bFound )
0756:     {
0757:         // Search in "%EXE_DIR%\"
0758:         _tcscpy( strReadmePath, strExePath );
0759:         lstrcat( strReadmePath, TEXT("\\readme.txt") );
0760:         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
0761:             bFound = TRUE;
0762:     }
0763: 
0764:     if( !bFound )
0765:     {
0766:         // Search in "%EXE_DIR%\.."
0767:         _tcscpy( strReadmePath, strExePath );
0768:         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
0769:         if( strLastSlash )
0770:             *strLastSlash = 0;
0771:         lstrcat( strReadmePath, TEXT("\\readme.txt") );
0772:         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
0773:             bFound = TRUE;
0774:     }
0775: 
0776:     if( !bFound )
0777:     {
0778:         // Search in "%EXE_DIR%\..\.."
0779:         _tcscpy( strReadmePath, strExePath );
0780:         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
0781:         if( strLastSlash )
0782:             *strLastSlash = 0;
0783:         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
0784:         if( strLastSlash )
0785:             *strLastSlash = 0;
0786:         lstrcat( strReadmePath, TEXT("\\readme.txt") );
0787:         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
0788:             bFound = TRUE;
0789:     }
0790: 
0791:     if( bFound )
0792:     {
0793:         // GetProcAddress for ShellExecute, so we don't have to include shell32.lib 
0794:         // in every project that uses dxutil.cpp
0795:         LPShellExecute pShellExecute = NULL;
0796:         HINSTANCE hInstShell32 = LoadLibrary(TEXT("shell32.dll"));
0797:         if (hInstShell32 != NULL)
0798:         {
0799: #ifdef UNICODE
0800:             pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteW"));
0801: #else
0802:             pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteA"));
0803: #endif
0804:             if( pShellExecute != NULL )
0805:             {
0806:                 if( pShellExecute( hWnd, TEXT("open"), strReadmePath, NULL, NULL, SW_SHOW ) > (HINSTANCE) 32 )
0807:                     bSuccess = true;
0808:             }
0809: 
0810:             FreeLibrary(hInstShell32);
0811:         }
0812:     }
0813: 
0814:     if( !bSuccess )
0815:     {
0816:         // Tell the user that the readme couldn't be opened
0817:         MessageBox( hWnd, TEXT("Could not find readme.txt"), 
0818:                     TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
0819:     }
0820: 
0821: #endif // UNDER_CE
0822: }
0823: 
0824: 
0825: 
0826: 
0827: 
0828: //-----------------------------------------------------------------------------
0829: // Name: DXUtil_Trace()
0830: // Desc: Outputs to the debug stream a formatted string with a variable-
0831: //       argument list.
0832: //-----------------------------------------------------------------------------
0833: VOID DXUtil_Trace( TCHAR* strMsg, ... )
0834: {
0835: #if defined(DEBUG) | defined(_DEBUG)
0836:     TCHAR strBuffer[512];
0837:     
0838:     va_list args;
0839:     va_start(args, strMsg);
0840:     _vsntprintf( strBuffer, 512, strMsg, args );
0841:     va_end(args);
0842: 
0843:     OutputDebugString( strBuffer );
0844: #else
0845:     UNREFERENCED_PARAMETER(strMsg);
0846: #endif
0847: }
0848: 
0849: 
0850: 
0851: 
0852: //-----------------------------------------------------------------------------
0853: // Name: DXUtil_ConvertStringToGUID()
0854: // Desc: Converts a string to a GUID
0855: //-----------------------------------------------------------------------------
0856: HRESULT DXUtil_ConvertStringToGUID( const TCHAR* strSrc, GUID* pGuidDest )
0857: {
0858:     UINT aiTmp[10];
0859: 
0860:     if( _stscanf( strSrc, TEXT("{%8X-%4X-%4X-%2X%2X-%2X%2X%2X%2X%2X%2X}"),
0861:                     &pGuidDest->Data1, 
0862:                     &aiTmp[0], &aiTmp[1], 
0863:                     &aiTmp[2], &aiTmp[3],
0864:                     &aiTmp[4], &aiTmp[5],
0865:                     &aiTmp[6], &aiTmp[7],
0866:                     &aiTmp[8], &aiTmp[9] ) != 11 )
0867:     {
0868:         ZeroMemory( pGuidDest, sizeof(GUID) );
0869:         return E_FAIL;
0870:     }
0871:     else
0872:     {
0873:         pGuidDest->Data2       = (USHORT) aiTmp[0];
0874:         pGuidDest->Data3       = (USHORT) aiTmp[1];
0875:         pGuidDest->Data4[0]    = (BYTE) aiTmp[2];
0876:         pGuidDest->Data4[1]    = (BYTE) aiTmp[3];
0877:         pGuidDest->Data4[2]    = (BYTE) aiTmp[4];
0878:         pGuidDest->Data4[3]    = (BYTE) aiTmp[5];
0879:         pGuidDest->Data4[4]    = (BYTE) aiTmp[6];
0880:         pGuidDest->Data4[5]    = (BYTE) aiTmp[7];
0881:         pGuidDest->Data4[6]    = (BYTE) aiTmp[8];
0882:         pGuidDest->Data4[7]    = (BYTE) aiTmp[9];
0883:         return S_OK;
0884:     }
0885: }
0886: 
0887: 
0888: 
0889: 
0890: //-----------------------------------------------------------------------------
0891: // Name: DXUtil_ConvertGUIDToStringCch()
0892: // Desc: Converts a GUID to a string 
0893: //       cchDestChar is the size in TCHARs of strDest.  Be careful not to 
0894: //       pass in sizeof(strDest) on UNICODE builds
0895: //-----------------------------------------------------------------------------
0896: HRESULT DXUtil_ConvertGUIDToStringCch( const GUID* pGuidSrc, TCHAR* strDest, int cchDestChar )
0897: {
0898:     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}"),
0899:                pGuidSrc->Data1, pGuidSrc->Data2, pGuidSrc->Data3,
0900:                pGuidSrc->Data4[0], pGuidSrc->Data4[1],
0901:                pGuidSrc->Data4[2], pGuidSrc->Data4[3],
0902:                pGuidSrc->Data4[4], pGuidSrc->Data4[5],
0903:                pGuidSrc->Data4[6], pGuidSrc->Data4[7] );
0904: 
0905:     if( nResult < 0 )
0906:         return E_FAIL;
0907:     return S_OK;
0908: }
0909: 
0910: 
0911: 
0912: 
0913: //-----------------------------------------------------------------------------
0914: // Name: CArrayList constructor
0915: // Desc: 
0916: //-----------------------------------------------------------------------------
0917: CArrayList::CArrayList( ArrayListType Type, UINT BytesPerEntry )
0918: {
0919:     if( Type == AL_REFERENCE )
0920:         BytesPerEntry = sizeof(void*);
0921:     m_ArrayListType = Type;
0922:     m_pData = NULL;
0923:     m_BytesPerEntry = BytesPerEntry;
0924:     m_NumEntries = 0;
0925:     m_NumEntriesAllocated = 0;
0926: }
0927: 
0928: 
0929: 
0930: //-----------------------------------------------------------------------------
0931: // Name: CArrayList destructor
0932: // Desc: 
0933: //-----------------------------------------------------------------------------
0934: CArrayList::~CArrayList( void )
0935: {
0936:     if( m_pData != NULL )
0937:         delete[] m_pData;
0938: }
0939: 
0940: 
0941: 
0942: 
0943: //-----------------------------------------------------------------------------
0944: // Name: CArrayList::Add
0945: // Desc: Adds pEntry to the list.
0946: //-----------------------------------------------------------------------------
0947: HRESULT CArrayList::Add( void* pEntry )
0948: {
0949:     if( m_BytesPerEntry == 0 )
0950:         return E_FAIL;
0951:     if( m_pData == NULL || m_NumEntries + 1 > m_NumEntriesAllocated )
0952:     {
0953:         void* pDataNew;
0954:         UINT NumEntriesAllocatedNew;
0955:         if( m_NumEntriesAllocated == 0 )
0956:             NumEntriesAllocatedNew = 16;
0957:         else
0958:             NumEntriesAllocatedNew = m_NumEntriesAllocated * 2;
0959:         pDataNew = new BYTE[NumEntriesAllocatedNew * m_BytesPerEntry];
0960:         if( pDataNew == NULL )
0961:             return E_OUTOFMEMORY;
0962:         if( m_pData != NULL )
0963:         {
0964:             CopyMemory( pDataNew, m_pData, m_NumEntries * m_BytesPerEntry );
0965:             delete[] m_pData;
0966:         }
0967:         m_pData = pDataNew;
0968:         m_NumEntriesAllocated = NumEntriesAllocatedNew;
0969:     }
0970: 
0971:     if( m_ArrayListType == AL_VALUE )
0972:         CopyMemory( (BYTE*)m_pData + (m_NumEntries * m_BytesPerEntry), pEntry, m_BytesPerEntry );
0973:     else
0974:         *(((void**)m_pData) + m_NumEntries) = pEntry;
0975:     m_NumEntries++;
0976: 
0977:     return S_OK;
0978: }
0979: 
0980: 
0981: 
0982: 
0983: //-----------------------------------------------------------------------------
0984: // Name: CArrayList::Remove
0985: // Desc: Remove the item at Entry in the list, and collapse the array. 
0986: //-----------------------------------------------------------------------------
0987: void CArrayList::Remove( UINT Entry )
0988: {
0989:     // Decrement count
0990:     m_NumEntries--;
0991: 
0992:     // Find the entry address
0993:     BYTE* pData = (BYTE*)m_pData + (Entry * m_BytesPerEntry);
0994: 
0995:     // Collapse the array
0996:     MoveMemory( pData, pData + m_BytesPerEntry, ( m_NumEntries - Entry ) * m_BytesPerEntry );
0997: }
0998: 
0999: 
1000: 
1001: 
1002: //-----------------------------------------------------------------------------
1003: // Name: CArrayList::GetPtr
1004: // Desc: Returns a pointer to the Entry'th entry in the list.
1005: //-----------------------------------------------------------------------------
1006: void* CArrayList::GetPtr( UINT Entry )
1007: {
1008:     if( m_ArrayListType == AL_VALUE )
1009:         return (BYTE*)m_pData + (Entry * m_BytesPerEntry);
1010:     else
1011:         return *(((void**)m_pData) + Entry);
1012: }
1013: 
1014: 
1015: 
1016: 
1017: //-----------------------------------------------------------------------------
1018: // Name: CArrayList::Contains
1019: // Desc: Returns whether the list contains an entry identical to the 
1020: //       specified entry data.
1021: //-----------------------------------------------------------------------------
1022: bool CArrayList::Contains( void* pEntryData )
1023: {
1024:     for( UINT iEntry = 0; iEntry < m_NumEntries; iEntry++ )
1025:     {
1026:         if( m_ArrayListType == AL_VALUE )
1027:         {
1028:             if( memcmp( GetPtr(iEntry), pEntryData, m_BytesPerEntry ) == 0 )
1029:                 return true;
1030:         }
1031:         else
1032:         {
1033:             if( GetPtr(iEntry) == pEntryData )
1034:                 return true;
1035:         }
1036:     }
1037:     return false;
1038: }
1039: 
1040: 
1041: 
1042: 
1043: //-----------------------------------------------------------------------------
1044: // Name: BYTE helper functions
1045: // Desc: cchDestChar is the size in BYTEs of strDest.  Be careful not to 
1046: //       pass use sizeof() if the strDest is a string pointer.  
1047: //       eg.
1048: //       TCHAR* sz = new TCHAR[100]; // sizeof(sz)  == 4
1049: //       TCHAR sz2[100];             // sizeof(sz2) == 200
1050: //-----------------------------------------------------------------------------
1051: HRESULT DXUtil_ConvertAnsiStringToWideCb( WCHAR* wstrDestination, const CHAR* strSource, int cbDestChar )
1052: {
1053:     return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, strSource, cbDestChar / sizeof(WCHAR) );
1054: }
1055: 
1056: HRESULT DXUtil_ConvertWideStringToAnsiCb( CHAR* strDestination, const WCHAR* wstrSource, int cbDestChar )
1057: {
1058:     return DXUtil_ConvertWideStringToAnsiCch( strDestination, wstrSource, cbDestChar / sizeof(CHAR) );
1059: }
1060: 
1061: HRESULT DXUtil_ConvertGenericStringToAnsiCb( CHAR* strDestination, const TCHAR* tstrSource, int cbDestChar )
1062: {
1063:     return DXUtil_ConvertGenericStringToAnsiCch( strDestination, tstrSource, cbDestChar / sizeof(CHAR) );
1064: }
1065: 
1066: HRESULT DXUtil_ConvertGenericStringToWideCb( WCHAR* wstrDestination, const TCHAR* tstrSource, int cbDestChar )
1067: {
1068:     return DXUtil_ConvertGenericStringToWideCch( wstrDestination, tstrSource, cbDestChar / sizeof(WCHAR) );
1069: }
1070: 
1071: HRESULT DXUtil_ConvertAnsiStringToGenericCb( TCHAR* tstrDestination, const CHAR* strSource, int cbDestChar )
1072: {
1073:     return DXUtil_ConvertAnsiStringToGenericCch( tstrDestination, strSource, cbDestChar / sizeof(TCHAR) );
1074: }
1075: 
1076: HRESULT DXUtil_ConvertWideStringToGenericCb( TCHAR* tstrDestination, const WCHAR* wstrSource, int cbDestChar )
1077: {
1078:     return DXUtil_ConvertWideStringToGenericCch( tstrDestination, wstrSource, cbDestChar / sizeof(TCHAR) );
1079: }
1080: 
1081: HRESULT DXUtil_ReadStringRegKeyCb( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, DWORD cbDest, TCHAR* strDefault )
1082: {
1083:     return DXUtil_ReadStringRegKeyCch( hKey, strRegName, strDest, cbDest / sizeof(TCHAR), strDefault );
1084: }
1085: 
1086: HRESULT DXUtil_ConvertGUIDToStringCb( const GUID* pGuidSrc, TCHAR* strDest, int cbDestChar )
1087: {
1088:     return DXUtil_ConvertGUIDToStringCch( pGuidSrc, strDest, cbDestChar / sizeof(TCHAR) );
1089: }
1090: 
1091: #ifndef UNDER_CE
1092: HRESULT DXUtil_GetDXSDKMediaPathCb( TCHAR* szDest, int cbDest )
1093: {
1094:     return DXUtil_GetDXSDKMediaPathCch( szDest, cbDest / sizeof(TCHAR) );
1095: }
1096: 
1097: HRESULT DXUtil_FindMediaFileCb( TCHAR* szDestPath, int cbDest, TCHAR* strFilename )
1098: {
1099:     return DXUtil_FindMediaFileCch( szDestPath, cbDest / sizeof(TCHAR), strFilename );
1100: }
1101: #endif // !UNDER_CE
1102: