#include "DLLDateien.h"

// Inhalt der DLLDateien Klasse aus DLLDateien.h
// Konstruktor
DLLDateien::DLLDateien()
{
	dlls = new Array< DLLDatei* >();
	InitializeCriticalSection( &cs );
	ref = 1;
}

// Destruktor
DLLDateien::~DLLDateien()
{
	EnterCriticalSection( &cs );
	int anz = dlls->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		DLLDatei *tmp = dlls->get( i );
		if( tmp )
		{
			tmp->name->release();
			FreeLibrary( tmp->handle );
		}
		delete tmp;
	}
	dlls->release();
	LeaveCriticalSection( &cs );
	DeleteCriticalSection( &cs );
}

// nicht constant
HINSTANCE DLLDateien::ladeDLL( char *name, char *pfad )
{
	EnterCriticalSection( &cs );
	int anz = dlls->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		DLLDatei *tmp = dlls->get( i );
		if( tmp && tmp->name->istGleich( name ) )
		{
			tmp->ref++;
			LeaveCriticalSection( &cs );
			return tmp->handle;
		}
	}
	HINSTANCE h = LoadLibrary( pfad );
	if( !h )
		return 0;
	DLLDatei *dll = new DLLDatei();
	dll->name = new Text( name );
	dll->handle = h;
	dll->ref = 1;
	dlls->add( dll );
	LeaveCriticalSection( &cs );
	return h;
}

void DLLDateien::releaseDLL( char *name )
{
	EnterCriticalSection( &cs );
	int anz = dlls->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		DLLDatei *tmp = dlls->get( i );
		if( tmp && tmp->name->istGleich( name ) )
		{
			tmp->ref--;
			if( !tmp->ref )
			{
				tmp->name->release();
				FreeLibrary( tmp->handle );
				delete tmp;
				dlls->lösche( i );
			}
			LeaveCriticalSection( &cs );
			return;
		}
	}
	LeaveCriticalSection( &cs );
}

// Reference Counting
DLLDateien *DLLDateien::getThis()
{
	ref++;
	return this;
}

DLLDateien *DLLDateien::release()
{
	ref--;
	if( !ref )
		delete this;
	return 0;
}