#ifndef _UTILW32_H #define _UTILW32_H // Redirect Asserts in inline code to seem to fire from this file #define szAssertFilename __FILE__ #ifdef DEBUG ERR ErrERRCheck( ERR err ); #else #define ErrERRCheck( err ) ( err ) #endif // Init / Term ERR ErrUtilInit(void); VOID UtilTerm(void); // Miscellaneous STATIC INLINE DWORD DwUtilGetLastError( void ) { return GetLastError(); } STATIC INLINE ULONG UlUtilGetTickCount( VOID ) { return GetTickCount(); } STATIC INLINE QWORD QwUtilPerfCount( VOID ) { QWORDX qwx; if ( !QueryPerformanceCounter( (LARGE_INTEGER *) &qwx.qw ) ) { qwx.h = GetTickCount(); qwx.l = 0; } return qwx.qw; } STATIC INLINE QWORD QwUtilPerfCountFrq( VOID ) { QWORDX qwx; if ( !QueryPerformanceFrequency( (LARGE_INTEGER *) &qwx.qw ) ) { qwx.h = 1000; qwx.l = 0; } return qwx.qw; } STATIC INLINE double DblUtilPerfElapsedTime( QWORD qwStartCount ) { return (signed __int64) ( QwUtilPerfCount() - qwStartCount ) / (double) (signed __int64) QwUtilPerfCountFrq(); } STATIC INLINE double DblUtilPerfElapsedTime2( QWORD qwStartCount, QWORD qwEndCount ) { return (signed __int64) ( qwEndCount - qwStartCount ) / (double) (signed __int64) QwUtilPerfCountFrq(); } CHAR *GetDebugEnvValue( CHAR *szEnvVar ); ERR ErrUtilCloseHandle( HANDLE hf ); // for system information such as virtual page size and malloc granularity extern SYSTEM_INFO siSystemConfig; // Event Logging typedef unsigned long MessageId; #include "jetmsg.h" extern int fNoWriteAssertEvent; VOID UtilReportEvent( WORD fwEventType, WORD fwCategory, DWORD IDEvent, WORD cStrings, LPCTSTR *plpszStrings ); VOID UtilReportEventOfError( WORD fwCategory, DWORD IDEvent, ERR err ); // Registry Support ERR ErrUtilRegInit(void); ERR ErrUtilRegTerm(void); ERR ErrUtilRegReadConfig(void); extern HKEY hkeyHiveRoot; ERR ErrUtilRegOpenKeyEx( HKEY hkeyRoot, LPCTSTR lpszSubKey, PHKEY phkResult ); ERR ErrUtilRegCloseKeyEx( HKEY hkey ); ERR ErrUtilRegCreateKeyEx( HKEY hkeyRoot, LPCTSTR lpszSubKey, PHKEY phkResult, LPDWORD lpdwDisposition ); ERR ErrUtilRegDeleteKeyEx( HKEY hkeyRoot, LPCTSTR lpszSubKey ); ERR ErrUtilRegDeleteValueEx( HKEY hkey, LPTSTR lpszValue ); ERR ErrUtilRegSetValueEx( HKEY hkey, LPCTSTR lpszValue, DWORD fdwType, CONST BYTE *lpbData, DWORD cbData ); ERR ErrUtilRegQueryValueEx( HKEY hkey, LPTSTR lpszValue, LPDWORD lpdwType, LPBYTE *lplpbData ); // DLL Support STATIC INLINE BOOL FUtilLoadLibrary(const char *pszLibrary, ULONG_PTR *phmod) { HANDLE hmod; hmod = LoadLibrary((LPTSTR) pszLibrary); // restore original error mode *phmod = (ULONG_PTR) hmod; return(hmod != NULL); } STATIC INLINE PFN PfnUtilGetProcAddress(ULONG_PTR hmod, unsigned ordinal) { return((PFN) GetProcAddress((HANDLE) hmod, MAKEINTRESOURCE(ordinal))); } STATIC INLINE void UtilFreeLibrary( unsigned hmod ) { FreeLibrary( LongToHandle(hmod)); } // Date and Time void UtilGetDateTime(DATESERIAL *pdt); void UtilGetDateTime2(_JET_DATETIME *pdt); char *SzUtilSerialToDate(JET_DATESERIAL dt); // File Operations typedef OVERLAPPED OLP; ERR ErrUtilCreateDirectory( char *szDirName ); ERR ErrUtilRemoveDirectory( char *szDirName ); ERR ErrUtilGetFileAttributes( CHAR *szFileName, BOOL *pfReadOnly ); ERR ErrUtilFindFirstFile( CHAR *szFind, HANDLE *phandleFind, CHAR *szFound ); ERR ErrUtilFindNextFile( HANDLE handleFind, CHAR *szFound ); VOID UtilFindClose( HANDLE handleFind ); BOOL FUtilFileExists( CHAR *szFilePathName ); ERR ErrUtilOpenFile( char *szFileName, HANDLE *phf, ULONG ulFileSize, BOOL fReadOnly, BOOL fOverlapped ); ERR ErrUtilOpenReadFile( char *szFileName, HANDLE *phf ); ERR ErrUtilDeleteFile( char *szFileName ); ERR ErrUtilNewSize( HANDLE hf, ULONG ulFileSize, ULONG ulFileSizeHigh, BOOL fOverlapped ); ERR ErrUtilMove( char *szFrom, char *szTo ); ERR ErrUtilCopy( char *szFrom, char *szTo, BOOL fFailIfExists ); ERR ErrUtilReadFile( HANDLE hf, VOID *pvBuf, UINT cbBuf, UINT *pcbRead ); ERR ErrUtilReadBlock( HANDLE hf, VOID *pvBuf, UINT cbBuf, UINT *pcbRead ); ERR ErrUtilReadBlockOverlapped( HANDLE hf, VOID *pvBuf, UINT cbBuf, DWORD *pcbRead, OLP *polp ); ERR ErrUtilReadBlockEx( HANDLE hf, VOID *pvBuf, UINT cbBuf, OLP *polp, VOID *pfnCompletion); ERR ErrUtilWriteBlock( HANDLE hf, VOID *pvBuf, UINT cbBuf, UINT *pcbWritten ); ERR ErrUtilWriteBlockOverlapped( HANDLE hf, VOID *pvBuf, UINT cbBuf, DWORD *pcbWrite, OLP *polp ); ERR ErrUtilWriteBlockEx( HANDLE hf, VOID *pvBuf, UINT cbBuf, OLP *polp, VOID *pfnCompletion); ERR ErrUtilGetOverlappedResult( HANDLE hf, OLP *polp, UINT *pcb, BOOL fWait ); STATIC INLINE ERR ErrUtilCloseFile( HANDLE hf ) { return ErrUtilCloseHandle( hf ); } ERR ErrUtilReadShadowedHeader( CHAR *szFileName, BYTE *pbHeader, INT cbHeader ); ERR ErrUtilWriteShadowedHeader( CHAR *szFileName, BYTE *pbHeader, INT cbHeader ); #define ulChecksumMagicNumber 0x89abcdef ULONG UlUtilChecksum( const BYTE *pb, INT cb ); //+api------------------------------------------------------ // // VOID UtilChgFilePtr( HANDLE hf, LONG lRel, LONG *plRelHigh, ULONG ulRef, ULONG *pul ) // ========================================================= // // Changes file hf pointer to position lRef relative to position : // // wRef FILE_BEGIN file beginnging // //---------------------------------------------------------- STATIC INLINE VOID UtilChgFilePtr( HANDLE hf, LONG lRel, LONG *plRelHigh, ULONG ulRef, ULONG *pul ) { Assert( sizeof(HANDLE) == sizeof(HFILE) ); *pul = SetFilePointer( (HANDLE)hf, lRel, plRelHigh, ulRef ); Assert( ulRef != FILE_BEGIN || *pul == (ULONG)lRel ); return; } STATIC INLINE ERR ErrUtilGetDiskFreeSpace( char *szRoot, ULONG *pSecPerClust, ULONG *pcbSec, ULONG *pcFreeClust, ULONG *pcTotClust ) { if ( GetDiskFreeSpace( szRoot, pSecPerClust, pcbSec, pcFreeClust, pcTotClust ) ) return JET_errSuccess; else return ErrERRCheck( JET_errDiskIO ); } VOID UtilDebugBreak(); // Physical Memory Allocation #if defined( DEBUG ) || defined( RFS2 ) void *SAlloc( unsigned long ); void OSSFree( void * ); void *LAlloc( unsigned long, unsigned short ); void OSLFree( void * ); STATIC INLINE VOID SFree( void *pv ) { OSSFree( pv ); } STATIC INLINE VOID LFree( void *pv ) { OSLFree( pv ); } #else // !DEBUG && !RFS2 #include STATIC INLINE VOID *SAlloc( ULONG cb ) { return GlobalAlloc( 0, cb ); } STATIC INLINE VOID SFree( VOID *pv ) { GlobalFree( pv ); } STATIC INLINE VOID *LAlloc( ULONG c, USHORT cb ) { return GlobalAlloc( 0, c * cb ); } STATIC INLINE VOID LFree( VOID *pv ) { GlobalFree( pv ); } #endif // DEBUG || RFS2 // Virtual Memory Allocation #if defined( DEBUG ) || defined( RFS2 ) VOID *PvUtilAlloc( ULONG dwSize ); VOID *PvUtilCommit( VOID *pv, ULONG dwSize ); VOID UtilFree( VOID *pv ); VOID UtilDecommit( VOID *pv, ULONG dwSize ); #else // !DEBUG && !RFS2 STATIC INLINE VOID *PvUtilAlloc( ULONG dwSize ) { return VirtualAlloc( NULL, dwSize, MEM_RESERVE, PAGE_READWRITE ); } STATIC INLINE VOID *PvUtilCommit( VOID *pv, ULONG ulSize ) { return VirtualAlloc( pv, ulSize, MEM_COMMIT, PAGE_READWRITE ); } STATIC INLINE VOID UtilFree( VOID *pv ) { VirtualFree( pv, 0, MEM_RELEASE ); } STATIC INLINE VOID UtilDecommit( VOID *pv, ULONG dwSize ) { VirtualFree( pv, dwSize, MEM_DECOMMIT ); } #endif // DEBUG || RFS2 VOID *PvUtilAllocAndCommit( ULONG dwSize ); // Critical Sections #ifdef SPIN_LOCK void UtilEnterNestableCriticalSection(void *pv); void UtilLeaveNestableCriticalSection(void *pv); void UtilEnterCriticalSection(void *pv); void UtilLeaveCriticalSection(void *pv); ERR ErrUtilInitializeCriticalSection(void **ppv); void UtilDeleteCriticalSection(void *pv); #else // !SPIN_LOCK #ifdef DEBUG void UtilEnterNestableCriticalSection(void *pv); void UtilLeaveNestableCriticalSection(void *pv); void UtilEnterCriticalSection(void *pv); void UtilLeaveCriticalSection(void *pv); ERR ErrUtilInitializeCriticalSection(void **ppv); void UtilDeleteCriticalSection(void *pv); #else // !DEBUG STATIC INLINE ERR ErrUtilInitializeCriticalSection(void **ppv) { if ( !( *ppv = SAlloc( sizeof( CRITICAL_SECTION ) ) ) ) return ErrERRCheck( JET_errOutOfMemory ); InitializeCriticalSection( (LPCRITICAL_SECTION) *ppv ); return JET_errSuccess; } STATIC INLINE VOID UtilDeleteCriticalSection(void *pv) { DeleteCriticalSection( (LPCRITICAL_SECTION) pv ); SFree( pv ); } STATIC INLINE VOID UtilEnterCriticalSection(void *pv) { EnterCriticalSection( (LPCRITICAL_SECTION) pv ); } STATIC INLINE VOID UtilLeaveCriticalSection(void *pv) { LeaveCriticalSection( (LPCRITICAL_SECTION) pv ); } STATIC INLINE VOID UtilEnterNestableCriticalSection( void *pv ) { UtilEnterCriticalSection( pv ); } STATIC INLINE VOID UtilLeaveNestableCriticalSection( void *pv ) { UtilLeaveCriticalSection( pv ); } #endif // !DEBUG #endif // !SPIN_LOCK #ifdef RETAIL #define UtilAssertCrit( pv ) 0 #define UtilAssertNotInCrit( pv ) 0 #define UtilHoldCriticalSection( pv ) 0 #define UtilReleaseCriticalSection( pv ) 0 #else // !RETAIL void UtilAssertCrit(void *pv); void UtilAssertNotInCrit(void *pv); void UtilHoldCriticalSection(void *pv); void UtilReleaseCriticalSection(void *pv); #endif // !RETAIL // Signals typedef HANDLE SIG; #define sigNil ( (SIG) 0 ) STATIC INLINE ERR ErrUtilSignalCreate( void **ppv, const char *szSig ) { *((SIG *) ppv) = CreateEvent( NULL, fTrue, fFalse, szSig ); return ( *ppv == sigNil ) ? ErrERRCheck( JET_errOutOfMemory ) : JET_errSuccess; } STATIC INLINE ERR ErrUtilSignalCreateAutoReset( void **ppv, const char *szSig ) { *((SIG *) ppv) = CreateEvent( NULL, fFalse, fFalse, szSig ); return ( *ppv == sigNil ) ? ErrERRCheck( JET_errOutOfMemory ) : JET_errSuccess; } STATIC INLINE void UtilSignalReset( void *pv ) { BOOL rc; rc = ResetEvent( (SIG) pv ); Assert( rc != FALSE ); } STATIC INLINE void UtilSignalSend( void *pv ) { BOOL rc; rc = SetEvent( (SIG) pv ); Assert( rc != FALSE ); } STATIC INLINE DWORD UtilSignalWait( void *pv, long lTimeOut ) { DWORD rc; UtilAssertNotInCrit( critJet ); rc = WaitForSingleObject( (SIG) pv, lTimeOut < 0 ? -1L : lTimeOut ); return rc; } STATIC INLINE DWORD UtilSignalWaitEx( void *pv, long lTimeOut, BOOL fAlertable ) { DWORD rc; UtilAssertNotInCrit( critJet ); rc = WaitForSingleObjectEx( (SIG) pv, lTimeOut < 0 ? -1L : lTimeOut, fAlertable ); return rc; } STATIC INLINE void UtilMultipleSignalWait( int csig, void *pv, BOOL fWaitAll, long lTimeOut ) { DWORD rc; UtilAssertNotInCrit( critJet ); rc = WaitForMultipleObjects( csig, (SIG*) pv, fWaitAll, lTimeOut < 0 ? -1L : lTimeOut ); } void UtilCloseSignal(void *pv); // Semaphore typedef HANDLE SEM; #define semNil ( (SEM) 0 ) STATIC INLINE ERR ErrUtilSemaphoreCreate( SEM *psem, LONG lInitialCount, LONG lMaximumCount ) { *psem = ( SEM ) CreateSemaphore( NULL, lInitialCount, lMaximumCount, NULL ); return ( *psem == semNil ) ? ErrERRCheck( JET_errOutOfMemory ) : JET_errSuccess; } STATIC INLINE DWORD UtilSemaphoreWait( SEM sem, long lTimeOut ) { DWORD rc; rc = WaitForSingleObject( (HANDLE) sem, lTimeOut < 0 ? -1L : lTimeOut ); return rc; } STATIC INLINE DWORD UtilSemaphoreRelease( SEM sem, LONG cReleaseCount ) { DWORD rc; rc = ReleaseSemaphore( (HANDLE) sem, cReleaseCount, NULL ); Assert( rc != 0 ); return rc; } void UtilCloseSemaphore(void *pv); // Threads and Processes #define cmsecSleepMax (60*1000) VOID UtilSleepEx( ULONG ulTime, BOOL fAlert ); VOID UtilSleep( ULONG ulTime ); ERR ErrUtilCreateThread( ULONG (*pulfn)(), ULONG cbStack, LONG lThreadPriority, HANDLE *phandle ); ULONG UtilEndThread( HANDLE hThread, SIG sigEnd ); #define lThreadPriorityNormal 0 #define lThreadPriorityHigh 1 void UtilSetThreadPriority( HANDLE hThread, LONG lThreadPriority ); STATIC INLINE HANDLE UtilGetCurrentTask( VOID ) { return LongToHandle(GetCurrentProcessId()); } STATIC INLINE DWORD DwUtilGetCurrentThreadId( VOID ) { return GetCurrentThreadId(); } // text normalization ERR ErrUtilCheckLangid( LANGID *plangid ); VOID UtilNormText( char *rgchText, INT cchText, BYTE *rgchNorm, INT cbNorm, INT *pbNorm ); ERR ErrUtilNormText( const BYTE *pbField, INT cbField, INT cbKeyBufLeft, BYTE *pbSeg, INT *pcbSeg ); #define BINARY_NAMES 1 #ifdef BINARY_NAMES #define UtilCmpName( sz1, sz2 ) \ ( _stricmp( sz1, sz2 ) ) #define UtilStringCompare( pb1, cb1, pb2, cb2, sort, plResult ) \ { \ *plResult = strncmp( pb1, pb2, min( cb1, cb2 ) ); \ if ( !*plResult ) \ *plResult = cb1 > cb2; \ } #else INT UtilCmpName( const char *sz1, const char *sz2 ); VOID UtilStringCompare( char *pb1, unsigned long cb1, char *pb2, unsigned long cb2, unsigned long sort, long *plResult ); #endif // Unicode Support ERR ErrUtilMapString(LANGID langid, BYTE *pbField, INT cbField, BYTE *rgbSeg, int cbBufLeft, int *cbSeg); ERR ErrUtilWideCharToMultiByte(LPCWSTR lpcwStr, LPSTR *lplpOutStr); // RFS functions #ifdef RFS2 int UtilRFSAlloc( const char *szType, int Type ); int UtilRFSLog(const char *szType,int fPermitscritted); void UtilRFSLogJETCall(const char *szFunc,ERR err,const char *szFile,unsigned Line); void UtilRFSLogJETErr(ERR err,const char *szLabel,const char *szFile,unsigned szLine); #endif /* RFS2 */ /* ** UtilInterlockedIncrement and UtilInterlockedDecrement are wrapper functions ** to increment or decrement a value in a thread-safe manner. ** ** Return values are: ** ** > 0 if resulting value > 0 ** = 0 if resulting value = 0 ** < 0 if resulting value < 0 ** ** Note that the return value isn't necessary the resulting value; it may be ** different than the resulting value, but sign is guarenteed to be the same. */ STATIC INLINE long UtilInterlockedIncrement( long *lpValue ) { return InterlockedIncrement( lpValue ); } STATIC INLINE long UtilInterlockedDecrement( long *lpValue ) { return InterlockedDecrement( lpValue ); } /* ** UtilInterlockedExchange is a wrapper function to assign a value to a ** variable in a thread-safe manner. ** ** This function returns the prior value of the variable (before the ** assignment was done). */ STATIC INLINE long UtilInterlockedExchange( long *lpValue1, long lValue2 ) { return InterlockedExchange( lpValue1, lValue2 ); } // Debug output #ifdef DEBUG extern void * critDBGPrint; VOID JET_API DBGFPrintF( char *sz ); void VARARG DebugWriteString(BOOL fHeader, const char *szFormat, ...); #else #define DBGFPrintF( sz ) 0 #endif void UtilPerfDumpStats(char *szText); // End Assert redirection #undef szAssertFilename #endif // _UTILW32_H