/*
	CVSNT Generic API
    Copyright (C) 2004-5 Tony Hoyle and March-Hare Software Ltd

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License version 2.1 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/* Win32 specific */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include <DelayImp.h>
#include "apiloader.h"

static FARPROC CALLBACK delayHook(unsigned dliNotify, PDelayLoadInfo pdli);
static TCHAR cvsntLibPath[MAX_PATH];
static TCHAR cvsntInstallPath[MAX_PATH];

static int GetGlobalValue(LPCTSTR value, LPTSTR buf, DWORD len)
{
	static const LPCTSTR regkey = _T("Software\\CVS\\PServer");
	HKEY hKey;
	DWORD dwType,dwLen;

	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,regkey,0,KEY_READ,&hKey))
		return -1; // Couldn't open or create key

	dwType=REG_SZ;
	dwLen=len;
	if(RegQueryValueEx(hKey,value,NULL,&dwType,(LPBYTE)buf,&dwLen))
	{
		RegCloseKey(hKey);
		return -1;
	}
	RegCloseKey(hKey);
	return 0;
}	

static int GetUserValue(LPCTSTR value, LPTSTR buf, DWORD len)
{
	static const LPCTSTR regkey = _T("Software\\Cvsnt\\PServer");
	HKEY hKey;
	DWORD dwType,dwLen;

	if(RegOpenKeyEx(HKEY_CURRENT_USER,regkey,0,KEY_READ,&hKey))
		return -1; // Couldn't open or create key

	dwType=REG_SZ;
	dwLen=len;
	if(RegQueryValueEx(hKey,value,NULL,&dwType,(LPBYTE)buf,&dwLen))
	{
		RegCloseKey(hKey);
		return -1;
	}
	RegCloseKey(hKey);
	return 0;
}	

void __apiloadHookDelayFunctions(void **notify, void **failure)
{
	*(PfnDliHook*)notify = delayHook;
	*(PfnDliHook*)failure = delayHook;

	if(GetGlobalValue(_T("LibraryPath"), cvsntLibPath, sizeof(cvsntLibPath)/sizeof(cvsntLibPath[0])) &&
		GetUserValue(_T("LibraryPath"), cvsntLibPath, sizeof(cvsntLibPath)/sizeof(cvsntLibPath[0])))
	{
		cvsntLibPath[0]='\0';
	}

	if(GetGlobalValue(_T("InstallPath"), cvsntInstallPath, sizeof(cvsntInstallPath)/sizeof(cvsntInstallPath[0])) &&
		GetGlobalValue(_T("InstallPath"), cvsntInstallPath, sizeof(cvsntInstallPath)/sizeof(cvsntInstallPath[0])))
	{
		cvsntInstallPath[0]='\0';
	}
}

static FARPROC CALLBACK delayHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
	switch (dliNotify)
	{
		case dliStartProcessing:
			break;
		case dliNotePreLoadLibrary:
			{
				HMODULE hLib = NULL;
				TCHAR fn[MAX_PATH],path[MAX_PATH];
				MultiByteToWideChar(CP_ACP,0,pdli->szDll,-1,fn,sizeof(fn)/sizeof(fn[0]));
				GetCurrentDirectory(sizeof(path),path);

				// LOAD_WITH_ALTERED_SEARCH_PATH seems to be broken, or at
				// least not working as specified in the documentation... need
				// to verify what this means for the control panel

				if(cvsntLibPath[0])
				{
					SetCurrentDirectory(cvsntLibPath);
					hLib = LoadLibrary(fn);
					SetCurrentDirectory(path);
				}

				if(!hLib && cvsntInstallPath[0])
				{
					SetCurrentDirectory(cvsntInstallPath);
					hLib = LoadLibrary(fn);
					SetCurrentDirectory(path);
				}

				/* If hLib is NULL here standard searches are used */
				return (FARPROC)hLib;
			}
		case dliNotePreGetProcAddress:
			break;
		case dliFailLoadLib: 
//			CServerIo::trace(1,"Delayload of %s failed!",pdli->szDll);
			break;
		case dliFailGetProc:
//			CServerIo::trace(1,"Missing function %s!",pdli->dlp.szProcName);
			break;
		case dliNoteEndProcessing: 
			break;
		default:
			break;
	}

	return NULL;
}


syntax highlighted by Code2HTML, v. 0.9.1