/*
//////////////////////////////////////////////////////////////
//	SNDMEM.CXX - SOUNDxD Version 2.0							
//////////////////////////////////////////////////////////////
//	Memory managing functions.
/////////////////////////////////////////////////////////////
*/

#include "SND/snddef.h"

#include "MMG.h"

#include "SND/sndmem.h"
#include "SND/snderr.h"

#ifndef NO_ACP_MEMORY
#define __DeclareGlobalVariableMmgSnd_h__
#include "SNDext/mmgsnd.h"
#include "SNDext/errsnd.h"
#endif //NO_ACP_MEMORY

#include "sndthrd.h"

typedef struct tdstBlockInfoPriv_{
        char * p_cBeginBlock;
        char * p_cEndBlock;
        char * p_cFirstFree;
        char * p_cMaxMem; 
}tdstBlockInfoPriv;

#ifdef MEMORY_ACCES_MANAGEMENT_MODE
void SND_fn_vInitMemoryAccessManagement();
void SND_fn_vDesInitMemoryAccessManagement();
LPTOP_LEVEL_EXCEPTION_FILTER g_pfnPrevExceptionHandler;
#endif

void SND_fn_vCheckMemory()
{
#if defined(DEBUG) || !defined(NDEBUG)
       unsigned char ucBlockId;
		unsigned long ulNbMalloc;
		unsigned long ulNbFree;
        tdstBlockInfoPriv *p_stMyBlockInfo;
        unitAlloc * p_uaPtr;		
        unitAlloc * p_uaFreePtr;
		unitAlloc uaTotalAllocatedSize;		
		unitAlloc uaTotalFreeSize;
		unitAlloc uaRemainSpace;
		unitAlloc uaBlockSize;
		unitAlloc uaMaxUsed;
		struct tdstBlockInfoPriv_ * a_stMyBlockInfo=g_a_p_stMmgModuleBlocksInfo[g_ucSndModuleId];
		unsigned char ucModuleMaxBlocksNb=E_ucSndMaxBlocksNb;
	     		
		Mmg_MEnterCriticalSection();

		//for (ucBlockId=0; ucBlockId<ucModuleMaxBlocksNb; ucBlockId++)
		//due to misalignement between MMG and SND, only first block is etstable
		{
		ucBlockId=0;
				p_stMyBlockInfo = a_stMyBlockInfo + ucBlockId;

				p_uaPtr=(unitAlloc *)p_stMyBlockInfo->p_cBeginBlock;
				p_uaFreePtr = (unitAlloc *)p_stMyBlockInfo->p_cFirstFree;
				uaTotalAllocatedSize = 0;
				uaTotalFreeSize = 0;
				ulNbFree = 0;
				ulNbMalloc =0;
				while (p_uaPtr < (unitAlloc *)p_stMyBlockInfo->p_cEndBlock){// scan all malloc
					if (p_uaFreePtr == p_uaPtr){// it's a free						
						if (((unitAlloc *) *(p_uaFreePtr+1)) != (unitAlloc *) 0){
							// not the last free
							p_uaFreePtr = (unitAlloc *) *(p_uaFreePtr+1); // go to the next free
							ulNbFree++;
							uaTotalFreeSize  += *p_uaPtr;
						}
					}
					else{// this is a malloc
						uaTotalAllocatedSize += *p_uaPtr;
						ulNbMalloc++;
					}
     if (*(p_uaPtr)==0)
     {
		 DebugBreak();
     }
					p_uaPtr += *(p_uaPtr);
				}//end of while

				if ((p_uaPtr != (unitAlloc *)(p_stMyBlockInfo->p_cEndBlock + 1)) && (uaTotalAllocatedSize)){
					snd_assert(FALSE);
				}
				else {
					uaBlockSize = p_stMyBlockInfo->p_cEndBlock - p_stMyBlockInfo->p_cBeginBlock +1;
					uaMaxUsed = p_stMyBlockInfo->p_cMaxMem - p_stMyBlockInfo->p_cBeginBlock +1;					
					if ( (unitAlloc *) (p_uaFreePtr) == (unitAlloc *) NULL){
						//all the space is used !!
						uaRemainSpace = 0;
					}
					else {
						uaRemainSpace = ((*p_uaFreePtr)<<C_uwShiftAllocSize);
					}

					uaTotalAllocatedSize <<= C_uwShiftAllocSize;
					uaTotalFreeSize <<= C_uwShiftAllocSize;
				}
        }// end of the for block

		Mmg_MLeaveCriticalSection();
#endif
}// Mmg_fn_vPrintUsedStaticMemory


#ifdef DEBUG_SON
#define NB_MALLOC_HISTO 10000
typedef struct {
	void* pvPtr;
	unsigned long ulSize;
} tdstMallocDescriptor;
static tdstMallocDescriptor dbg_MallocHisto[NB_MALLOC_HISTO];
static unsigned long dbg_ulNbDynMalloc=0;
static unsigned long dbg_ulSizeDynMalloc=0;
static unsigned long dbg_ulIdMaxDynMalloc=0;
static unsigned long dbg_ulMaxSizeDynMalloc=0;
static unsigned long dbg_ulNbMaxBlocs=0;

void dbg_fnMalloc(void* ptr,unsigned long size)
{
	int i=0;
	tdstMallocDescriptor *decr=&dbg_MallocHisto[0];

	while ((i<NB_MALLOC_HISTO) && (decr->pvPtr!=NULL)) {i++;decr++;};
	if (i<NB_MALLOC_HISTO)
	{
		decr->pvPtr=ptr;decr->ulSize=size;
		dbg_ulNbDynMalloc++;dbg_ulSizeDynMalloc+=size;
		if (dbg_ulSizeDynMalloc>dbg_ulMaxSizeDynMalloc)
		{
			dbg_ulMaxSizeDynMalloc=dbg_ulSizeDynMalloc;
			dbg_ulIdMaxDynMalloc=dbg_ulNbDynMalloc;
			dbg_ulNbMaxBlocs=0;decr=&dbg_MallocHisto[0];i=0;
			while (i<NB_MALLOC_HISTO) 
			{
				decr++;i++;
				if (decr->pvPtr!=NULL) dbg_ulNbMaxBlocs++;
			}
		}
	}
}

void dbg_fnReAlloc(void* oldptr,void* newptr,unsigned long size)
{
	int i=0;
	tdstMallocDescriptor *decr=&dbg_MallocHisto[0];

	while ((i<NB_MALLOC_HISTO) && (decr->pvPtr!=oldptr)) {i++;decr++;};
	if (i<NB_MALLOC_HISTO)
	{
		dbg_ulSizeDynMalloc-=decr->ulSize;dbg_ulSizeDynMalloc+=size;
		decr->pvPtr=newptr;decr->ulSize=size;
		if (dbg_ulSizeDynMalloc>dbg_ulMaxSizeDynMalloc)
		{
			dbg_ulMaxSizeDynMalloc=dbg_ulSizeDynMalloc;
			dbg_ulNbMaxBlocs=0;decr=&dbg_MallocHisto[0];i=0;
			while (i<NB_MALLOC_HISTO) 
			{
				decr++;i++;
				if (decr->pvPtr!=NULL) dbg_ulNbMaxBlocs++;
			}
		}
	}
}

void dbg_fnFree(void* ptr)
{
	int i=0;
	tdstMallocDescriptor *decr=&dbg_MallocHisto[0];

	while ((i<NB_MALLOC_HISTO) && (decr->pvPtr!=ptr)) {i++;decr++;}
	if (i<NB_MALLOC_HISTO)
	{
		dbg_ulSizeDynMalloc-=decr->ulSize;dbg_ulNbDynMalloc--;
		decr->pvPtr=NULL;decr->ulSize=0;
	}	
}

void dbg_fnReportDynMemory()
{
	FILE* hFile;
	SYSTEMTIME time;
   
	if ((hFile=fopen("sndmemrp.txt","aw"))!=NULL)
	{
		GetLocalTime(&time);
		fprintf(hFile,"--- Dynamic Memory used by SND ------------\xd\xa saved the %dth of %d, %d; at %2d:%2d:%2d\xd\xa",time.wMonth,time.wDay,time.wYear,time.wHour,time.wMinute,time.wSecond);
		fprintf(hFile,"Maximum of %d bytes segmented in %d blocks\xd\xa\xd\xa",dbg_ulMaxSizeDynMalloc,dbg_ulNbMaxBlocs);
		fclose(hFile);
	}
}
#endif

#ifndef NO_ACP_MEMORY
#define C_SND_MAINBLOCK_SIZE 100*1024
#define C_SND_MAPBLOCK_SIZE 10*1024

//----------------------------------------------------------
//	InitMallocSnd:init de la librairie MallocSnd
//----------------------------------------------------------
void SND_CALL SND_fn_vInitMallocSnd(void)
{
	#ifdef MEMORY_ACCES_MANAGEMENT_MODE
	SND_fn_vInitMemoryAccessManagement();
	#endif

	Mmg_M_InitMmg(Snd);

	Mmg_M_InitBlock(Snd,E_ucSndBlockMain,C_SND_MAINBLOCK_SIZE);
	Mmg_M_InitBlock(Snd,E_ucSndBlockMap,C_SND_MAPBLOCK_SIZE);

	SND_fn_vEnterCriticalSectionForErrorDisplay();

	if (Erm_M_uwCheckError (Snd,(unsigned long)GetCurrentThreadId()))
	{
        Erm_M_ClearLastError((unsigned long)GetCurrentThreadId());
        Erm_M_UpdateLastError(Snd,(unsigned long)GetCurrentThreadId(),E_uwSndMemoryBlockError, C_lErmNoDebugData,C_ucErmOpenInfoWindow, C_ucAllowStopForDebug,"");
	}     

	SND_fn_vQuitCriticalSectionForErrorDisplay();
}

//----------------------------------------------------------
//	InitMallocSnd:init de la librairie MallocSnd
//----------------------------------------------------------
void SND_CALL SND_fn_vDesInitMallocSnd(void)
{
#ifdef DEBUG_SON
	dbg_fnReportDynMemory();
#endif

	Mmg_M_FreeBlock(Snd,E_ucSndBlockMain);
	Mmg_M_FreeBlock(Snd,E_ucSndBlockMap);
	Mmg_M_DeleteBlock(Snd,E_ucSndBlockMain);
	Mmg_M_DeleteBlock(Snd,E_ucSndBlockMap);

	#ifdef MEMORY_ACCES_MANAGEMENT_MODE
	SND_fn_vDesInitMemoryAccessManagement();
	#endif//MEMORY_ACCES_MANAGEMENT_MODE
}

//----------------------------------------------------------
//	MallocSnd:allocation d'un bloc mémoire
//	Entrée:ulNbByte=nb d'octets à réserver
//	Sortie:pointeur sue le 1° octet reservé
//----------------------------------------------------------
void* SND_CALL SND_fn_pvMallocSnd(unsigned long ulNbBytes)
{
	void* ptr_temp;
	unsigned char ucChannel;

	ucChannel=Mmg_fn_ucGiveChannelId((unsigned long)GetCurrentThreadId(),0);

	Mmg_M_SetModeAlloc4Ch(Snd,E_ucDynamic,ucChannel );

	ptr_temp=Mmg_fn_p_vAlloc4Ch(ulNbBytes,ucChannel );
	
	SND_fn_vEnterCriticalSectionForErrorDisplay();

	if (Erm_M_uwCheckError(Mmg,(unsigned long)GetCurrentThreadId()))
	{
		SND_PrintUsedStaticMemory();
        Erm_M_ClearLastError((unsigned long)GetCurrentThreadId());
		SND_fn_vDisplayError(E_uwSndMemoryAllocError,"");
		ptr_temp=NULL;
	} 

	SND_fn_vQuitCriticalSectionForErrorDisplay();

	Mmg_fn_vReleaseChannelId(ucChannel);

#ifdef DEBUG_SON
	dbg_fnMalloc(ptr_temp,ulNbBytes);
#endif

	return ptr_temp;
}

void* SND_CALL SND_fn_pvMallocSndEx(unsigned char id_block,unsigned long ulNbBytes)
{
	void* ptr_temp;
#ifdef MEMORY_ACCES_MANAGEMENT_MODE
	ptr_temp=VirtualAlloc(NULL,ulNbBytes,MEM_COMMIT,PAGE_READWRITE);

	if (id_block & MEMORY_ACCES_MANAGEMENT_FLAG)
	{

	}
#else
	unsigned char ucChannel;

	SND_fn_vCheckMemory();

	ucChannel=Mmg_fn_ucGiveChannelId((unsigned long)GetCurrentThreadId(),0);

	Mmg_M_SetModeAlloc4Ch(Snd,id_block,ucChannel );

	ptr_temp=Mmg_fn_p_vAlloc4Ch(ulNbBytes,ucChannel );
	
	SND_fn_vEnterCriticalSectionForErrorDisplay();

	if (Erm_M_uwCheckError(Mmg,(unsigned long)GetCurrentThreadId()))
	{
		SND_PrintUsedStaticMemory();
        Erm_M_ClearLastError((unsigned long)GetCurrentThreadId());
		SND_fn_vDisplayError(E_uwSndMemoryAllocError,"");
		ptr_temp=NULL;
	} 

	SND_fn_vQuitCriticalSectionForErrorDisplay();

	Mmg_fn_vReleaseChannelId(ucChannel);

	SND_fn_vCheckMemory();
#endif //MEMORY_ACCES_MANAGEMENT_MODE

	return ptr_temp;
}


//----------------------------------------------------------
//	ReAllocSnd:ré-allocation d'un bloc mémoire
//	Entrée:pvPtr=pointeur sur le 1° octet de la zone à réallouer
//		ulNbByte=nouveau nb d'octets à réserver
//	Sortie:pointeur sue le 1° octet reservé
//----------------------------------------------------------
void* SND_CALL SND_fn_pvReAllocSnd(void* pvPtr,unsigned long ulNbBytes)
{
	void * p_vPtr;
	unsigned char ucChannel;

	ucChannel=Mmg_fn_ucGiveChannelId((unsigned long)GetCurrentThreadId(),0);

	Mmg_M_SetModeAlloc4Ch(Snd,E_ucDynamic,ucChannel);
	
	p_vPtr = Mmg_fn_p_vRealloc4Ch(pvPtr,ulNbBytes,ucChannel);

	SND_fn_vEnterCriticalSectionForErrorDisplay();

	if (Erm_M_uwCheckError(Mmg,(unsigned long)GetCurrentThreadId()))
	{
		SND_PrintUsedStaticMemory();
        Erm_M_ClearLastError((unsigned long)GetCurrentThreadId());
		SND_fn_vDisplayError(E_uwSndMemoryAllocError,"");
	} 

	SND_fn_vQuitCriticalSectionForErrorDisplay();

	Mmg_fn_vReleaseChannelId(ucChannel);

#ifdef DEBUG_SON
	dbg_fnReAlloc(pvPtr,p_vPtr,ulNbBytes);
#endif

	return p_vPtr;
}

void* SND_CALL SND_fn_pvReAllocSndEx(unsigned char id_block,void* pvPtr,unsigned long ulNbBytes)
{
	void * newPtr;
#ifdef MEMORY_ACCES_MANAGEMENT_MODE
	MEMORY_BASIC_INFORMATION mem_info;
	DWORD ret,prev_size,prev_protect;

	newPtr=VirtualAlloc(0,ulNbBytes,MEM_COMMIT,PAGE_READWRITE);
	if (!newPtr) 
		ret=GetLastError();
	else
	{
		VirtualQuery(pvPtr,&mem_info,sizeof(MEMORY_BASIC_INFORMATION));
		prev_size=mem_info.RegionSize;
		if (!(mem_info.Protect & PAGE_READWRITE))
			VirtualProtect(pvPtr,prev_size,PAGE_READWRITE,&prev_protect);
		CopyMemory(newPtr,pvPtr,min(ulNbBytes,prev_size));
		if (!VirtualFree(pvPtr,0,MEM_RELEASE))
			ret=GetLastError();
	}

	if (id_block & MEMORY_ACCES_MANAGEMENT_FLAG)
		VirtualProtect(newPtr,ulNbBytes,PAGE_READONLY,&prev_protect);

	snd_assert(newPtr);
#else
	unsigned char ucChannel;

	SND_fn_vCheckMemory();

	ucChannel=Mmg_fn_ucGiveChannelId((unsigned long)GetCurrentThreadId(),0);

	Mmg_M_SetModeAlloc4Ch(Snd,id_block,ucChannel);
	
	newPtr = Mmg_fn_p_vRealloc4Ch(pvPtr,ulNbBytes,ucChannel );

	SND_fn_vEnterCriticalSectionForErrorDisplay();

	if (Erm_M_uwCheckError(Mmg,(unsigned long)GetCurrentThreadId()))
	{
		SND_PrintUsedStaticMemory();
        Erm_M_ClearLastError((unsigned long)GetCurrentThreadId());
		SND_fn_vDisplayError(E_uwSndMemoryAllocError,"");
	} 

	SND_fn_vQuitCriticalSectionForErrorDisplay();

	Mmg_fn_vReleaseChannelId(ucChannel);

	SND_fn_vCheckMemory();
#endif //MEMORY_ACCES_MANAGEMENT_MODE

	return newPtr;
}

//----------------------------------------------------------
//	FreeSnd:libération d'un bloc mémoire
//	Entrée:pvPtr=pointeur sur le 1° octet de la zone à libérer
//----------------------------------------------------------
void SND_CALL SND_fn_vFreeSnd(void* pvPtr)
{
	unsigned char ucChannel;

	ucChannel=Mmg_fn_ucGiveChannelId((unsigned long)GetCurrentThreadId(),0);

	Mmg_M_SetModeAlloc4Ch(Snd,E_ucDynamic,ucChannel);

	Mmg_fn_vTestMallocIntegrityAt (pvPtr);

	Mmg_fn_vFree4Ch(pvPtr,ucChannel);

	SND_fn_vEnterCriticalSectionForErrorDisplay();

	if (Erm_M_uwCheckError(Mmg, (unsigned long)GetCurrentThreadId()))
	{
		Erm_M_ClearLastError((unsigned long)GetCurrentThreadId());
		SND_fn_vDisplayError(E_uwSndMemoryAllocError,"");
	}

	SND_fn_vQuitCriticalSectionForErrorDisplay();

	Mmg_fn_vReleaseChannelId(ucChannel);

#ifdef DEBUG_SON
	dbg_fnFree(pvPtr);
#endif
}

void  SND_CALL SND_fn_vFreeSndEx(unsigned char id_block,void* pvPtr)
{
#ifdef MEMORY_ACCES_MANAGEMENT_MODE
	VirtualFree(pvPtr,0,MEM_RELEASE);
#else
	unsigned char ucChannel;
	long toto=(long)GetCurrentThreadId();

	SND_fn_vCheckMemory();

	ucChannel=Mmg_fn_ucGiveChannelId((unsigned long)GetCurrentThreadId(),0);

	Mmg_M_SetModeAlloc4Ch(Snd,id_block,ucChannel );

	Mmg_fn_vTestMallocIntegrityAt (pvPtr);

	Mmg_fn_vFree4Ch(pvPtr,ucChannel);

	SND_fn_vEnterCriticalSectionForErrorDisplay();

	if (Erm_M_uwCheckError(Mmg, (unsigned long)GetCurrentThreadId()))
	{
		Erm_M_ClearLastError((unsigned long)GetCurrentThreadId());
		SND_fn_vDisplayError(E_uwSndMemoryAllocError,"");
	}

	SND_fn_vQuitCriticalSectionForErrorDisplay();

	Mmg_fn_vReleaseChannelId(ucChannel);

	SND_fn_vCheckMemory();
#endif //MEMORY_ACCES_MANAGEMENT_MODE
}

void  SND_CALL SND_fn_vResizeMemoryBlockSnd(unsigned char id,unsigned long size)
{
	Mmg_M_InitBlock(Snd,id,size);
}

void SND_PrintUsedStaticMemory(void)
{
	Mmg_M_PrintUsedStaticMemoryInModule(Snd);
}

#ifdef MEMORY_ACCES_MANAGEMENT_MODE
//Exception filter for SND acces viloation management
LONG WINAPI SND_fn_lUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
	char texte[128];

	if (ExceptionInfo->ExceptionRecord->ExceptionCode==EXCEPTION_ACCESS_VIOLATION)
	{
		sprintf(texte,"Tentative d'écrasement mémoire en %x",ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
		if (MessageBox(NULL,"Do you want to (attempt to) modify bloc attributs ?",texte,MB_YESNO)==IDYES)
			SND_fn_vLockMemoryWriteSnd_((void*)ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
	}
	else
		MessageBox(NULL,"ça va mal","ouîlle",MB_OK);

	return EXCEPTION_CONTINUE_SEARCH;
}

void SND_fn_vInitMemoryAccessManagement()
{
	g_pfnPrevExceptionHandler=SetUnhandledExceptionFilter(SND_fn_lUnhandledExceptionFilter);
}

void SND_fn_vDesInitMemoryAccessManagement()
{
	SetUnhandledExceptionFilter(g_pfnPrevExceptionHandler);
}

void SND_CALL SND_fn_vLockMemoryWriteSnd_(void* ptr)
{
	MEMORY_BASIC_INFORMATION mem_info;
	DWORD prev_protect;

	VirtualQuery(ptr,&mem_info,sizeof(MEMORY_BASIC_INFORMATION));
	snd_assert(mem_info.RegionSize);
	snd_assert(mem_info.Protect==PAGE_READONLY);

	VirtualProtect(ptr,mem_info.RegionSize,PAGE_READWRITE,&prev_protect);
}

void SND_CALL SND_fn_vLockMemoryReadSnd_(void* ptr)
{
	MEMORY_BASIC_INFORMATION mem_info;
	DWORD prev_protect;

	VirtualQuery(ptr,&mem_info,sizeof(MEMORY_BASIC_INFORMATION));
	snd_assert(mem_info.RegionSize);
	snd_assert(mem_info.Protect==PAGE_READONLY);

	VirtualProtect(ptr,mem_info.RegionSize,PAGE_READONLY,&prev_protect);
}

void SND_CALL SND_fn_vUnLockMemoryWriteSnd_(void* ptr)
{
	MEMORY_BASIC_INFORMATION mem_info;
	DWORD prev_protect;

	VirtualQuery(ptr,&mem_info,sizeof(MEMORY_BASIC_INFORMATION));
	snd_assert(mem_info.RegionSize);
	snd_assert(mem_info.Protect==PAGE_READWRITE);

	VirtualProtect(ptr,mem_info.RegionSize,PAGE_READONLY,&prev_protect);
}

void SND_CALL SND_fn_vUnLockMemoryReadSnd_(void* ptr)
{
	MEMORY_BASIC_INFORMATION mem_info;
	DWORD prev_protect;

	VirtualQuery(ptr,&mem_info,sizeof(MEMORY_BASIC_INFORMATION));
	snd_assert(mem_info.RegionSize);
	snd_assert(mem_info.Protect==PAGE_READONLY);

	VirtualProtect(ptr,mem_info.RegionSize,PAGE_READONLY,&prev_protect);
}
#endif //MEMORY_ACCES_MANAGEMENT_MODE

#else //NO_ACP_MEMORY
//----------------------------------------------------------
//	InitMallocSnd:init de la librairie MallocSnd
//----------------------------------------------------------
void SND_CALL SND_fn_vInitMallocSnd(void)
{
}

//----------------------------------------------------------
//	InitMallocSnd:init de la librairie MallocSnd
//----------------------------------------------------------
void SND_CALL SND_fn_vDesInitMallocSnd(void)
{
}

//----------------------------------------------------------
//	MallocSnd:allocation d'un bloc mémoire
//	Entrée:ulNbByte=nb d'octets à réserver
//	Sortie:pointeur sue le 1° octet reservé
//----------------------------------------------------------
void* SND_CALL SND_fn_pvMallocSnd(unsigned long ulNbBytes)
{
	return VirtualAlloc(0,ulNbBytes,MEM_COMMIT,PAGE_READWRITE);
}

void* SND_CALL SND_fn_pvMallocSndEx(unsigned char id,unsigned long ulNbBytes)
{
	return SND_fn_pvMallocSnd(ulNbBytes);
}

//----------------------------------------------------------
//	ReAllocSnd:ré-allocation d'un bloc mémoire
//	Entrée:pvPtr=pointeur sur le 1° octet de la zone à réallouer
//		ulNbByte=nouveau nb d'octets à réserver
//	Sortie:pointeur sue le 1° octet reservé
//----------------------------------------------------------
void* SND_CALL SND_fn_pvReAllocSnd(void* pvPtr,unsigned long ulNbBytes)
{
	void *new_pvPtr;
	DWORD ret;
	MEMORY_BASIC_INFORMATION mem_info;
	DWORD prev_size;

	if (pvPtr != NULL)
	{
		new_pvPtr=VirtualAlloc(0,ulNbBytes,MEM_COMMIT,PAGE_READWRITE);
		if (!new_pvPtr) 
			ret=GetLastError();
		else
		{
			VirtualQuery(pvPtr,&mem_info,sizeof(MEMORY_BASIC_INFORMATION));
			prev_size=mem_info.RegionSize;
			CopyMemory(new_pvPtr,pvPtr,min(ulNbBytes,prev_size));
			if (!VirtualFree(pvPtr,0,MEM_RELEASE))
				ret=GetLastError();
		}
	}
	else
		new_pvPtr=NULL;

	return new_pvPtr;
}

void* SND_CALL SND_fn_pvReAllocSndEx(unsigned char id,void* pvPtr,unsigned long ulNbBytes)
{
	return SND_fn_pvReAllocSnd(pvPtr,ulNbBytes);
}

//----------------------------------------------------------
//	FreeSnd:libération d'un bloc mémoire
//	Entrée:pvPtr=pointeur sur le 1° octet de la zone à libérer
//----------------------------------------------------------
void SND_CALL SND_fn_vFreeSnd(void* pvPtr)
{
	DWORD ret;

	if (pvPtr != NULL)
			if (!VirtualFree(pvPtr,0,MEM_RELEASE))
				ret=GetLastError();
}

void SND_CALL SND_fn_vFreeSndEx(unsigned char id,void* pvPtr)
{
	SND_fn_vFreeSnd(pvPtr);
}

void  SND_CALL SND_fn_vResizestaticBlockSnd(int id,long size)
{
}

void SND_PrintUsedStaticMemory (void)
{
}

#endif //NO_ACP_MEMORY

