|
|
/*==========================================================================
* * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved. * * File: OSInd.cpp * Content: OS indirection functions to abstract OS specific items. * * History: * Date By Reason * ==== == ====== * 07/12/99 jtk Created * 09/21/99 rodtoll Fixed for retail builds * 09/22/99 jtk Added callstacks to memory allocations * 08/28/2000 masonb Voice Merge: Allow new and delete with size of 0 * 11/28/2000 rodtoll WinBug #206257 - Retail DPNET.DLL links to DebugBreak() * 12/22/2000 aarono ManBug # 190380 use process heap for retail * 10/16/2001 vanceo Add AssertNoCriticalSectionsTakenByThisThread capability ***************************************************************************/
#include "dncmni.h"
#define PROF_SECT _T("DirectPlay8")
//**********************************************************************
// Constant definitions
//**********************************************************************
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
//**********************************************************************
// Variable definitions
//**********************************************************************
//
// debug variable to make sure we're initialized before having any functions
// called
//
DEBUG_ONLY( static BOOL g_fOSIndirectionLayerInitialized = FALSE );
//
// OS items
//
#if ((! defined(WINCE)) && (! defined(_XBOX)))
static OSVERSIONINFO g_OSVersionInfo; #endif // ! WINCE and ! _XBOX
#ifndef DPNBUILD_NOSERIALSP
static HINSTANCE g_hApplicationInstance; #endif // ! DPNBUILD_NOSERIALSP
//
// Global Pools
//
#if ((! defined(DPNBUILD_LIBINTERFACE)) && (! defined(DPNBUILD_NOCLASSFACTORY)))
CFixedPool g_fpClassFactories; CFixedPool g_fpObjectDatas; CFixedPool g_fpInterfaceLists; #endif // ! DPNBUILD_LIBINTERFACE and ! DPNBUILD_NOCLASSFACTORY
#ifdef WINNT
PSECURITY_ATTRIBUTES g_psa = NULL; SECURITY_ATTRIBUTES g_sa; BYTE g_pSD[SECURITY_DESCRIPTOR_MIN_LENGTH]; BOOL g_fDaclInited = FALSE; PACL g_pEveryoneACL = NULL; #endif // WINNT
#ifndef DPNBUILD_LIBINTERFACE
#define CLASSFAC_POOL_INITED 0x00000001
#define OBJDATA_POOL_INITED 0x00000002
#define INTLIST_POOL_INITED 0x00000004
#endif // ! DPNBUILD_LIBINTERFACE
#ifdef DBG
#define HANDLE_TRACKING_INITED 0x00000008
#endif // DBG
#if ((defined(DBG)) || (defined(DPNBUILD_FIXEDMEMORYMODEL)))
#define MEMORY_TRACKING_INITED 0x00000010
#endif // DBG or DPNBUILD_FIXEDMEMORYMODEL
#if ((defined(DBG)) && (! defined(DPNBUILD_ONLYONETHREAD)))
#define CRITSEC_TRACKING_INITED 0x00000020
#endif // DBG and ! DPNBUILD_ONLYONETHREAD
#if !defined(DPNBUILD_LIBINTERFACE) || defined(DBG) || defined(DPNBUILD_FIXEDMEMORYMODEL)
DWORD g_dwCommonInitFlags = 0; #endif // !defined(DPNBUILD_LIBINTERFACE) || defined(DBG) || defined(DPNBUILD_FIXEDMEMORYMODEL)
//**********************************************************************
// Function prototypes
//**********************************************************************
//**********************************************************************
// Function definitions
//**********************************************************************
//**********************************************************************
// ------------------------------
// DNOSIndirectionInit - initialize the OS indirection layer
//
// Entry: Nothing
//
// Exit: Boolean indicating success
// TRUE = initialization successful
// FALSE = initialization unsuccessful
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNOSIndirectionInit"
BOOL DNOSIndirectionInit( DWORD_PTR dwpMaxMemUsage ) { BOOL fReturn;
#ifdef DBG
DNASSERT( g_fOSIndirectionLayerInitialized == FALSE ); #endif // DBG
//
// initialize
//
fReturn = TRUE;
#if ((! defined(WINCE)) && (! defined(_XBOX)))
//
// note OS version
//
memset( &g_OSVersionInfo, 0x00, sizeof( g_OSVersionInfo ) ); g_OSVersionInfo.dwOSVersionInfoSize = sizeof( g_OSVersionInfo ); if ( GetVersionEx( &g_OSVersionInfo ) == FALSE ) { goto Failure; } #endif // ! WINCE and ! _XBOX
#ifndef DPNBUILD_NOSERIALSP
//
// note application instance
//
g_hApplicationInstance = GetModuleHandle( NULL ); if ( g_hApplicationInstance == NULL ) { DWORD dwError;
dwError = GetLastError(); DPFX(DPFPREP, 0, "Failed to GetModuleHandle: 0x%x", dwError ); goto Failure; } #endif // ! DPNBUILD_NOSERIALSP
#if ((defined(DBG)) && (! defined(DPNBUILD_ONLYONETHREAD)))
//
// initialize critical section tracking code before anything else!
//
if ( DNCSTrackInitialize() == FALSE ) { DPFX(DPFPREP, 0, "Failed to initialize critsec tracking code!" ); DNASSERT( FALSE ); goto Failure; } g_dwCommonInitFlags |= CRITSEC_TRACKING_INITED; #endif // DBG and ! DPNBUILD_ONLYONETHREAD
#if ((defined(DBG)) || (defined(DPNBUILD_FIXEDMEMORYMODEL)))
//
// initialize memory tracking before creating new memory heap
//
if ( DNMemoryTrackInitialize(dwpMaxMemUsage) == FALSE ) { DPFX(DPFPREP, 0, "Failed to initialize memory tracking code!" ); DNASSERT( FALSE ); goto Failure; } g_dwCommonInitFlags |= MEMORY_TRACKING_INITED; #endif // DBG or DPNBUILD_FIXEDMEMORYMODEL
#ifdef DBG
//
// initialize handle tracking
//
if ( DNHandleTrackInitialize() == FALSE ) { DPFX(DPFPREP, 0, "Failed to initialize handle tracking code!" ); DNASSERT( FALSE ); goto Failure; } g_dwCommonInitFlags |= HANDLE_TRACKING_INITED; #endif // DBG
#if ((! defined(DPNBUILD_LIBINTERFACE)) && (! defined(DPNBUILD_NOCLASSFACTORY)))
//
// Initialize global pools
//
if (!g_fpClassFactories.Initialize( sizeof( _IDirectPlayClassFactory ), NULL, NULL, NULL, NULL)) { DPFX(DPFPREP, 0, "Failed to initialize class factory pool!" ); goto Failure; } g_dwCommonInitFlags |= CLASSFAC_POOL_INITED;
if (!g_fpObjectDatas.Initialize( sizeof( _OBJECT_DATA ), NULL, NULL, NULL, NULL)) { DPFX(DPFPREP, 0, "Failed to initialize object data pool!" ); goto Failure; } g_dwCommonInitFlags |= OBJDATA_POOL_INITED;
if (!g_fpInterfaceLists.Initialize( sizeof( _INTERFACE_LIST ), NULL, NULL, NULL, NULL)) { DPFX(DPFPREP, 0, "Failed to initialize interface list pool!" ); goto Failure; } g_dwCommonInitFlags |= INTLIST_POOL_INITED; #endif // ! DPNBUILD_LIBINTERFACE and ! DPNBUILD_NOCLASSFACTORY
srand(GETTIMESTAMP());
#if (((! defined(WINCE)) && (! defined(_XBOX))) || (! defined(DPNBUILD_NOSERIALSP)) || (defined(DBG)) || (defined(DPNBUILD_FIXEDMEMORYMODEL)) || ((! defined(DPNBUILD_LIBINTERFACE)) && (! defined(DPNBUILD_NOCLASSFACTORY))) )
Exit: #endif // (! WINCE and ! _XBOX) or ! DPNBUILD_NOSERIALSP or DBG or DPNBUILD_FIXEDMEMORYMODEL or (! DPNBUILD_LIBINTERFACE and ! DPNBUILD_NOCLASSFACTORY)
if ( fReturn != FALSE ) { DEBUG_ONLY( g_fOSIndirectionLayerInitialized = TRUE ); }
return fReturn;
#if (((! defined(WINCE)) && (! defined(_XBOX))) || (! defined(DPNBUILD_NOSERIALSP)) || (defined(DBG)) || (defined(DPNBUILD_FIXEDMEMORYMODEL)) || ((! defined(DPNBUILD_LIBINTERFACE)) && (! defined(DPNBUILD_NOCLASSFACTORY))) )
Failure: fReturn = FALSE;
DNOSIndirectionDeinit();
goto Exit; #endif // (! WINCE and ! _XBOX) or ! DPNBUILD_NOSERIALSP or DBG or DPNBUILD_FIXEDMEMORYMODEL or (! DPNBUILD_LIBINTERFACE and ! DPNBUILD_NOCLASSFACTORY)
} //**********************************************************************
//**********************************************************************
// ------------------------------
// DNOSIndirectionDeinit - deinitialize OS indirection layer
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNOSIndirectionDeinit"
void DNOSIndirectionDeinit( void ) { #if ((! defined(DPNBUILD_LIBINTERFACE)) && (! defined(DPNBUILD_NOCLASSFACTORY)))
//
// DeInitialize global pools
//
if (g_dwCommonInitFlags & CLASSFAC_POOL_INITED) { g_fpClassFactories.DeInitialize(); } if (g_dwCommonInitFlags & OBJDATA_POOL_INITED) { g_fpObjectDatas.DeInitialize(); } if (g_dwCommonInitFlags & INTLIST_POOL_INITED) { g_fpInterfaceLists.DeInitialize(); } #endif // ! DPNBUILD_LIBINTERFACE and ! DPNBUILD_NOCLASSFACTORY
#ifdef DBG
if (g_dwCommonInitFlags & HANDLE_TRACKING_INITED) { if (DNHandleTrackDumpLeaks()) { // There were leaks, break so we can look at the log
DNASSERT(0); } DNHandleTrackDeinitialize(); } #endif // DBG
#if ((defined(DBG)) && (! defined(DPNBUILD_ONLYONETHREAD)))
//
// Display CritSec leaks before displaying memory leaks, because displaying memory leaks
// may free the memory for the CritSec and corrupt the CritSec bilink
//
if (g_dwCommonInitFlags & CRITSEC_TRACKING_INITED) { if (DNCSTrackDumpLeaks()) { // There were leaks, break so we can look at the log
DNASSERT(0); } DNCSTrackDeinitialize(); } #endif // DBG and ! DPNBUILD_ONLYONETHREAD
#if ((defined(DBG)) || (defined(DPNBUILD_FIXEDMEMORYMODEL)))
if (g_dwCommonInitFlags & MEMORY_TRACKING_INITED) { #ifdef DBG
if (DNMemoryTrackDumpLeaks()) { // There were leaks, break so we can look at the log
DNASSERT(0); } #endif // DBG
DNMemoryTrackDeinitialize(); } #endif // DBG or DPNBUILD_FIXEDMEMORYMODEL
#ifdef WINNT
// This should be done after functions that use a Dacl will no longer be
// called (CreateMutex, CreateFile, etc).
if (g_pEveryoneACL) { HeapFree(GetProcessHeap(), 0, g_pEveryoneACL); g_pEveryoneACL = NULL; } #endif // WINNT
DEBUG_ONLY( g_fOSIndirectionLayerInitialized = FALSE );
#if !defined(DPNBUILD_LIBINTERFACE) || defined(DBG)
g_dwCommonInitFlags = 0; #endif // !defined(DPNBUILD_LIBINTERFACE) || defined(DBG)
} //**********************************************************************
#undef DPF_MODNAME
#define DPF_MODNAME "DNinet_ntow"
void DNinet_ntow( IN_ADDR in, WCHAR* pwsz ) { // NOTE: pwsz should be 16 characters (4 3-digit numbers + 3 '.' + \0)
swprintf(pwsz, L"%d.%d.%d.%d", in.s_net, in.s_host, in.s_lh, in.s_impno); }
#undef DPF_MODNAME
#define DPF_MODNAME "DNGetRandomNumber"
DWORD DNGetRandomNumber() { return (rand() | (rand() << 16)); }
#if ((! defined(WINCE)) && (! defined(_XBOX)))
//**********************************************************************
// ------------------------------
// DNGetOSType - get OS type
//
// Entry: Nothing
//
// Exit: OS type
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNGetOSType"
UINT_PTR DNGetOSType( void ) { #ifdef DBG
DNASSERT( g_fOSIndirectionLayerInitialized != FALSE ); #endif // DBG
return g_OSVersionInfo.dwPlatformId; } #endif // ! WINCE and ! _XBOX
#ifdef WINNT
//**********************************************************************
// ------------------------------
// DNOSIsXPOrGreater - return TRUE if OS is WindowsXP or later or NT flavor
//
// Entry: Nothing
//
// Exit: BOOL
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNOSIsXPOrGreater"
BOOL DNOSIsXPOrGreater( void ) { #ifdef DBG
DNASSERT( g_fOSIndirectionLayerInitialized != FALSE ); #endif // DBG
return ((g_OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && ((g_OSVersionInfo.dwMajorVersion > 5) || ((g_OSVersionInfo.dwMajorVersion == 5) && (g_OSVersionInfo.dwMinorVersion >= 1))) ); }
//**********************************************************************
//**********************************************************************
// ------------------------------
// DNGetNullDacl - get a SECURITY_ATTRIBUTE structure that specifies a
// NULL DACL which is accesible by all users.
//
// Entry: Nothing
//
// Exit: PSECURITY_ATTRIBUTES
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNGetNullDacl"
PSECURITY_ATTRIBUTES DNGetNullDacl() { PSID psidEveryone = NULL; SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY; DWORD dwAclSize;
// This is done to make this function independent of DNOSIndirectionInit so that the debug
// layer can call it before the indirection layer is initialized.
if (!g_fDaclInited) { if (!InitializeSecurityDescriptor((SECURITY_DESCRIPTOR*)g_pSD, SECURITY_DESCRIPTOR_REVISION)) { DPFX(DPFPREP, 0, "Failed to initialize security descriptor" ); goto Error; }
// Create SID for the Everyone group.
if (!AllocateAndInitializeSid(&siaWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidEveryone)) { DPFX(DPFPREP, 0, "Failed to allocate Everyone SID" ); goto Error; }
dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidEveryone) - sizeof(DWORD);
// Allocate the ACL, this won't be a tracked allocation and we will let process cleanup destroy it
g_pEveryoneACL = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize); if (g_pEveryoneACL == NULL) { DPFX(DPFPREP, 0, "Failed to allocate ACL buffer" ); goto Error; }
// Intialize the ACL.
if (!InitializeAcl(g_pEveryoneACL, dwAclSize, ACL_REVISION)) { DPFX(DPFPREP, 0, "Failed to initialize ACL" ); goto Error; }
// Add the ACE.
if (!AddAccessAllowedAce(g_pEveryoneACL, ACL_REVISION, GENERIC_ALL, psidEveryone)) { DPFX(DPFPREP, 0, "Failed to add ACE to ACL" ); goto Error; }
// We no longer need the SID that was allocated.
FreeSid(psidEveryone); psidEveryone = NULL;
// Add the ACL to the security descriptor..
if (!SetSecurityDescriptorDacl((SECURITY_DESCRIPTOR*)g_pSD, TRUE, g_pEveryoneACL, FALSE)) { DPFX(DPFPREP, 0, "Failed to add ACL to security descriptor" ); goto Error; }
g_sa.nLength = sizeof(SECURITY_ATTRIBUTES); g_sa.lpSecurityDescriptor = g_pSD; g_sa.bInheritHandle = FALSE;
g_psa = &g_sa;
g_fDaclInited = TRUE; } Error: if (psidEveryone) { FreeSid(psidEveryone); psidEveryone = NULL; } return g_psa; } //**********************************************************************
#endif // WINNT
#ifndef DPNBUILD_NOSERIALSP
//**********************************************************************
// ------------------------------
// DNGetApplicationInstance - application instance
//
// Entry: Nothing
//
// Exit: Application instance
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNGetApplicationInstance"
HINSTANCE DNGetApplicationInstance( void ) { #ifdef DBG
DNASSERT( g_fOSIndirectionLayerInitialized != FALSE ); #endif // DBG
return g_hApplicationInstance; } //**********************************************************************
#endif // ! DPNBUILD_NOSERIALSP
#ifndef DPNBUILD_ONLYONETHREAD
//**********************************************************************
// ------------------------------
// DNOSInitializeCriticalSection - initialize a critical section
//
// Entry: Pointer to critical section
//
// Exit: Boolean indicating success
// TRUE = success
// FALSE = failue
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNOSInitializeCriticalSection"
BOOL DNOSInitializeCriticalSection( CRITICAL_SECTION* pCriticalSection ) { BOOL fReturn;
DNASSERT( pCriticalSection != NULL ); fReturn = TRUE;
//
// attempt to enter the critical section once
//
_try { #ifdef WINNT
// Pre-allocate the critsec event by setting the high bit of the spin count and set spin to 1000
// NT converts the spin to 0 for single proc machines.
fReturn = InitializeCriticalSectionAndSpinCount( pCriticalSection , 0x80000000 | 1000); #else
InitializeCriticalSection( pCriticalSection ); #endif // WINNT
} _except( EXCEPTION_EXECUTE_HANDLER ) { fReturn = FALSE; }
_try { if (fReturn) { EnterCriticalSection( pCriticalSection ); } } _except( EXCEPTION_EXECUTE_HANDLER ) { DeleteCriticalSection(pCriticalSection); fReturn = FALSE; }
//
// if we didn't fail on entering the critical section, make sure
// we release it
//
if ( fReturn != FALSE ) { LeaveCriticalSection( pCriticalSection ); }
return fReturn; } //**********************************************************************
#endif // !DPNBUILD_ONLYONETHREAD
#ifdef DBG
#if ((defined(WINCE)) || ((defined(_XBOX)) && (! defined(XBOX_ON_DESKTOP))))
#undef DPF_MODNAME
#define DPF_MODNAME "DNGetProfileInt"
UINT DNGetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault) { DWORD dwResult; #ifndef _XBOX
CRegistry reg; #endif // ! _XBOX
DNASSERT(_tcscmp(lpszSection, _T("DirectPlay8")) == 0);
#ifdef _XBOX
#pragma TODO(vanceo, "Implement GetProfileInt functionality for Xbox")
dwResult = nDefault; #else // ! _XBOX
if (!reg.Open(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\DirectPlay8"))) { // NOTE: This will occur during DllRegisterServer for the first time
return nDefault; }
if (!reg.ReadDWORD(lpszEntry, &dwResult)) { return nDefault; } #endif // ! _XBOX
return dwResult; }
#endif // WINCE or (_XBOX and ! XBOX_ON_DESKTOP)
#endif // DBG
#if defined(WINCE) && !defined(WINCE_ON_DESKTOP)
//**********************************************************************
//**
//** Begin CE layer. Here we implement functions we need that aren't on CE.
//**
//**********************************************************************
#undef DPF_MODNAME
#define DPF_MODNAME "OpenEvent"
HANDLE WINAPI OpenEvent(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName) { HANDLE h;
h = CreateEvent(0, 1, 0, lpName); if (!h) { return NULL; } if (GetLastError() != ERROR_ALREADY_EXISTS) { CloseHandle(h); return NULL; } return h; }
#undef DPF_MODNAME
#define DPF_MODNAME "OpenFileMapping"
HANDLE WINAPI OpenFileMapping(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName) { HANDLE h; DWORD dwFlags = 0;
if (dwDesiredAccess & FILE_MAP_WRITE) { // If they ask for FILE_MAP_ALL_ACCESS or FILE_MAP_WRITE, they get read and write
dwFlags = PAGE_READWRITE; } else { // If they only ask for FILE_MAP_READ, they get read only
dwFlags = PAGE_READONLY; }
h = CreateFileMapping(INVALID_HANDLE_VALUE, 0, dwFlags, 0, 1, lpName); if (!h) { return NULL; } if (GetLastError() != ERROR_ALREADY_EXISTS) { CloseHandle(h); return NULL; } return h; }
#undef DPF_MODNAME
#define DPF_MODNAME "OpenMutex"
HANDLE WINAPI OpenMutex(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName) { HANDLE h;
h = CreateMutex(0, 0, lpName); if (!h) { return NULL; } if (GetLastError() != ERROR_ALREADY_EXISTS) { CloseHandle(h); return NULL; } return h; }
/*
#ifdef _X86_
__declspec(naked) LONG WINAPI InterlockedExchangeAdd( LPLONG Addend, LONG Increment ) { __asm { mov ecx, [esp + 4] ; get addend address mov eax, [esp + 8] ; get increment value lock xadd [ecx], eax ; exchange add} ret } } #endif // _X86
*/ #endif // WINCE
//**********************************************************************
//**
//** End CE layer. Here we implement functions we need that aren't on CE.
//**
//**********************************************************************
#if ((defined(WINCE)) || (defined(DPNBUILD_LIBINTERFACE)))
#undef DPF_MODNAME
#define DPF_MODNAME "DNCoCreateGuid"
HRESULT DNCoCreateGuid(GUID* pguid) { pguid->Data1 = (rand() << 16) | rand(); pguid->Data2 = (WORD)rand(); pguid->Data3 = (WORD)rand(); pguid->Data4[0] = (BYTE)rand(); pguid->Data4[1] = (BYTE)rand(); pguid->Data4[2] = (BYTE)rand(); pguid->Data4[3] = (BYTE)rand(); pguid->Data4[4] = (BYTE)rand(); pguid->Data4[5] = (BYTE)rand(); pguid->Data4[6] = (BYTE)rand(); pguid->Data4[7] = (BYTE)rand();
return S_OK; }
#endif // WINCE or DPNBUILD_LIBINTERFACE
#ifndef DPNBUILD_NOPARAMVAL
BOOL IsValidStringA( const CHAR * const lpsz ) { #ifndef WINCE
return (!IsBadStringPtrA( lpsz, 0xFFFF ) ); #else
const char* szTmpLoc = lpsz;
//
// If it is a NULL pointer just return FALSE, they are always bad
//
if (szTmpLoc == NULL) { return FALSE; }
_try { for( ; *szTmpLoc ; szTmpLoc++ ); } _except(EXCEPTION_EXECUTE_HANDLER) { return FALSE; } return TRUE;
#endif // WINCE
}
BOOL IsValidStringW( const WCHAR * const lpwsz ) { #ifndef WINCE
return (!IsBadStringPtrW( lpwsz, 0xFFFF ) ); #else
const wchar_t *szTmpLoc = lpwsz; //
// If it is a NULL pointer just return FALSE, they are always bad
//
if( szTmpLoc == NULL ) { return FALSE; } _try { for( ; *szTmpLoc ; szTmpLoc++ ); } _except( EXCEPTION_EXECUTE_HANDLER ) { return FALSE; }
return TRUE; #endif // WINCE
}
#endif // !DPNBUILD_NOPARAMVAL
|