/*

The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is a portion of the Path Development API developed
by CygnaCom Solutions, Inc.

Portions created by CygnaCom Solutions, Inc. are Copyright (C) CygnaCom 
Solutions, Inc. All Rights Reserved.

Contributor(s): ______________________________________.

http://www.cygnacom.com

*/

/*------------------------------------------------------------------------*\
|  Project Name  :   Path Development API
|  File Name     :   PathCache.cpp
|  Creation Date :   May 17, 1999
|  Author        :   Matt Cooper (mcooper@cygnacom.com)
|  Last Mode Date:   May 17, 1999
|  Modification History:
|--------------------------------------------------------------------------
|
|     Known Bugs:   None
|                   
|--------------------------------------------------------------------------
| Cryptographic devices and technical data regarding them are subject to
| Federal Government export controls as specified in Title 22, Code of
| Federal Regulations, Parts 121 through 128.  Cryptographic devices
| implementing the Data Encryption Standard (DES) and technical data
| regarding them must comply with these Federal regulations
|--------------------------------------------------------------------------
| Copyright (c) 1999, CygnaCom Solutions, Inc.
| All Rights Reserved.
\*------------------------------------------------------------------------*/

// PathCache.cpp: implementation of the CPathCache class.
//
//////////////////////////////////////////////////////////////////////

#if defined(_WIN32)
	#if defined(_AFXDLL)
		#include "stdafx.h"
	#else
		#include "windows.h"
	#endif
#endif

#ifdef VX /* Added by Masanori Satake. */
#include "vxWorks.h"
#include "vxdbg.h"
#endif

#include "stdio.h"

#include "PathCache.h"
#include "Defines.h"
#include <stdio.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//#define _DEBUG_VERBOSE

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

/* Used for searching by all functions, prevents
alloc, construction, and destruction for every call */

CPathCache::CPathCache()
{
  /*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::CPathCache()\n";
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::CPathCache()\n");
        #endif /* #ifdef _WIN32 */
	#endif

	m_lpPathTable = NULL;
	m_entryCount = 0;
	m_lastEntryNum = 0;
	m_diskPath = NULL;
}

CPathCache::~CPathCache()
{
  /*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::~CPathCache()\n";
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::~CPathCache()\n");
        #endif /* #ifdef _WIN32 */
	#endif

	if( NULL != m_lpPathTable )
	{
		delete m_lpPathTable;
		m_lpPathTable = NULL;
	}
	if( NULL != m_diskPath )
	{
		delete []m_diskPath;
		m_diskPath = NULL;
	}


}

CPathRec* CPathCache::FindEntry(const char *subjectIssuer,Bytes_struct *subjectSerial)
{
	long rv = 0;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::FindEntry(" << subjectIssuer << ", <serial ptr>" << subjectSerial << " )\n";
		Sleep(1);
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::FindEntry(");
		PRINTERR(subjectIssuer);
		PRINTERR(", <serial ptr>");
		PRINTERR(subjectSerial);
		PRINTERR(" )\n");
        #endif /* #ifdef _WIN32 */
	#endif
	
	if( !IsValid() )
		return NULL;

	rv = tmpPathRec.set_entry(subjectIssuer,subjectSerial,NULL,NULL,0);
	if( 0 != rv )
		return NULL;

	CPathRec* p = NULL;
	p = m_lpPathTable->Search(tmpPathRec);

	if( NULL != p )
		p->m_entryNumber = ++m_lastEntryNum;

	return p;

}



/*-------------------------------------------------------------------------*\
|  Function Name :   IsValid()
|  Creation Date :   March 23, 1999
|  Author        :   Matt Cooper
|  Last Mode Date:   March 23, 1999
|---------------------------------------------------------------------------
|	        
|  Purpose:	Checks for class validity
|  Exception Handling: None
|---------------------------------------------------------------------------
|  Return values:  1 if Valid, else 0
\*-------------------------------------------------------------------------*/
long CPathCache::IsValid()
{
	if( NULL == m_lpPathTable )
		return 0;

	if( m_lastEntryNum >= ( 2*PATHCACHE_MAX_ENTRY_COUNT ) )
	{
		ReindexEntryNums();
	}

	return 1;
}

CPathRec* CPathCache::FindEntry(Cert_struct *subjectCert)
{

	if( !IsValid() )
		return NULL;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::FindEntry(<Cert_struct*>" << subjectCert << ")\n";
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::FindEntry(<Cert_struct*>");
		PRINTERR(subjectCert);
		PRINTERR(")\n");
        #endif /* #ifdef _WIN32 */
	#endif

	if( 0 != CPLI_CreatePathRecFromCerts(tmpPathRec,subjectCert) )
		return NULL;

	CPathRec* p = NULL;
	p = m_lpPathTable->Search(tmpPathRec);

	if( NULL != p )
		p->m_entryNumber = ++m_lastEntryNum;

	return p;
}

CPathRec* CPathCache::FindEntry(CPathRec &pathRec)
{
	if( !IsValid() )
		return NULL;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::FindEntry(<CPathRec& for>\"" << pathRec.m_lpszKey << "\")\n";
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::FindEntry(<CPathRec& for>\"");
		PRINTERR(pathRec.m_lpszKey);
		PRINTERR("\")\n");
        #endif /* #ifdef _WIN32 */
	#endif

	CPathRec* p = NULL;
	p = m_lpPathTable->Search(pathRec);

	if( NULL != p )
		p->m_entryNumber = ++m_lastEntryNum;

	return p;
}


long CPathCache::AddEntry(Cert_struct *subject, Cert_struct *issuer, CPathRec **newRecord)
{
	long rv = 0;

	if( !IsValid() )
		return PATHCACHE_NOT_INITIALIZED;

	/* 	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Deleted by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::AddEntry(" << subject << ", " << issuer << ", rec ptr)\n";
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::AddEntry(");
		PRINTERR(subject);
		PRINTERR(", ");
		PRINTERR(issuer);
		PRINTERR(", rec ptr)\n");
        #endif /* #ifdef _WIN32 */
	#endif

	if( m_entryCount > PATHCACHE_MAX_ENTRY_FLUX + PATHCACHE_MAX_ENTRY_COUNT )
	{
		rv = RemoveOldItems();
		if( 0 != rv )
			return rv;
	}

	rv = CPLI_CreatePathRecFromCerts(tmpPathRec,subject,issuer);
	if( 0 != rv )
		return PATHCACHE_INVALID_CERT_DATA;

	CPathRec *pRec = m_lpPathTable->Search(tmpPathRec);
	if( NULL != pRec )
	{
		if( !m_lpPathTable->Delete(*pRec) )
			return PATHCACHE_DELETE_ERROR;

		m_entryCount--;
	}

	tmpPathRec.m_entryNumber = ++m_lastEntryNum;

	if( !m_lpPathTable->Insert(tmpPathRec) )
		return PATHCACHE_INSERT_ERROR;
	
	m_entryCount++;

	if( NULL != newRecord )
	{
		*newRecord = m_lpPathTable->Search(tmpPathRec);
		if( NULL == *newRecord )
			return PATHCACHE_INSERT_ERROR;	
	}

	return 0;
}



/*-------------------------------------------------------------------------*\
|  Function Name :   Initialize(const char *diskPath)
|  Creation Date :   March 23, 1999
|  Author        :   Matt Cooper
|  Last Mode Date:   March 23, 1999
|---------------------------------------------------------------------------
|	        
|  Purpose:	Inits the path cache class and reads the disk cache into mem
|  Exception Handling: file i/o
|---------------------------------------------------------------------------
|  Inputs Params:   directory disk cache resides in
|	                
|  Pre-Conditions:  None
|  Post-Conditions: Initialization complete
|  Return values:   0 on success
|	                
\*-------------------------------------------------------------------------*/
long CPathCache::Initialize(const char *diskPath)
{
	long rv = 0;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::Initialize(" << diskPath << ")\n";
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::Initialize(");
		PRINTERR(diskPath);
		PRINTERR(")\n");
        #endif /* #ifdef _WIN32 */
	#endif

	if( NULL != m_lpPathTable )
	{
		delete m_lpPathTable;
		m_lpPathTable = NULL;
	}

	if( NULL == m_lpPathTable )
	{
		m_lpPathTable = new CMemCache<CPathRec>(PATHCACHE_TABLE_SIZE);
		if( NULL == m_lpPathTable )
			return PATHCACHE_ALLOC_FAIL;
	}

	if( NULL != diskPath )
	{
		if( NULL != m_diskPath )
		{
#ifndef VX /* Added by Masanori Satake. */
			try{ delete []m_diskPath; }	catch(...){}
#else
			delete []m_diskPath;
#endif
		}

		m_diskPath = new char[strlen(diskPath)+4];
		if( NULL == diskPath )
			return PATHCACHE_ALLOC_FAIL;

		strcpy(m_diskPath,diskPath);

		rv = ReadCacheFile();
	}

	return rv;
}



long CPathCache::RemoveOldItems()
{

	#if defined(_WIN32) && defined (_DEBUG)
	DWORD startt = GetTickCount();
	#endif

	CPathRec *pRec = NULL;
	long vPos = 0;
	long doubleFlux = 0;
	CPathRec *pRecList = NULL;
	CPathRec *pListEnd = NULL;
	long errVal = 0;
	long delCount = 0;
	CPathRec **pRecs = NULL;
	long nullCount = 0;
	long entryCount = 0;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::RemoveOldItems()\n";
        #else /* _UNIX or VX */
		PRINTERR("CPathCache::RemoveOldItems()\n");
        #endif /* #ifdef _WIN32 */
	#endif

#undef RETURN
#ifndef VX /* Added by Masanori Satake. */
#define RETURN(r){if( NULL != pRecList ) {	try{ delete pRecList; pRecList = NULL; }catch(...){} } if( NULL != pRecs ) {	try{ delete []pRecs; pRecs = NULL; }catch(...){} } return r; }	
#else
#define RETURN(r){if( NULL != pRecList ) { delete pRecList; pRecList = NULL;} if( NULL != pRecs ) {delete []pRecs; pRecs = NULL;} return r;}
#endif
	if( m_entryCount < PATHCACHE_MAX_ENTRY_COUNT + PATHCACHE_MAX_ENTRY_FLUX)
		return 0;

	/*	#if defined(_WIN32) && defined (_DEBUG) */ /* Deleted by Masanori Satake. */
        #if defined (_DEBUG) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "Dumping old path entries..\n";
        #else /* _UNIX or VX */
		PRINTERR("Dumping old path entries..\n");
        #endif /* #ifdef _WIN32 */
	#endif

	doubleFlux = 2 * PATHCACHE_MAX_ENTRY_FLUX;

	pRecList = new CPathRec;
	if( NULL == pRecList )
	{	return PATHCACHE_ALLOC_FAIL; }

	pRecs = new CPathRec*[m_lastEntryNum + 8];
	if( NULL == pRecs )
		RETURN(PATHCACHE_ALLOC_FAIL);

	memset(pRecs,0,sizeof(CPathRec*)*(m_lastEntryNum + 8));

/*
	pRecs = new CPathRec*[PATHCACHE_MAX_ENTRY_COUNT+PATHCACHE_MAX_ENTRY_FLUX+8];
	if( NULL == pRecs )
		RETURN(PATHCACHE_ALLOC_FAIL);

	memset(pRecs,0,sizeof(CPathRec*)*(PATHCACHE_MAX_ENTRY_COUNT+PATHCACHE_MAX_ENTRY_FLUX+8));
*/
	pListEnd = pRecList;


	do
	{

		for( ; vPos < PATHCACHE_TABLE_SIZE; vPos++ )
		{
			pRec = m_lpPathTable->HashVector[vPos];
			while( NULL != pRec )
			{
				if( pRec->m_entryNumber <= doubleFlux )
				{
				  /*		#if defined(_WIN32) && defined (_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                                        #if defined (_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
					afxDump << pRec->m_entryNumber << " tagged for deletion.\n";
					Sleep(5);
					afxDump.Flush();
                                        #else /* _UNIX or VX */
					PRINTERR(" tagged for deletion.\n");
                                        #endif /* #ifdef _WIN32 */

					//pRec->m_entryNumber = 0;
					delCount++;

					pListEnd->CopyFrom(pRec);
					pListEnd->NextRec = new CPathRec;
					pListEnd = pListEnd->NextRec;

					if( NULL == pListEnd)
					{
						vPos = PATHCACHE_TABLE_SIZE + 100;
						errVal = PATHCACHE_ALLOC_FAIL;
						break;
					}
				}
				else
				{

				  /*		#if defined(_WIN32) && defined (_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                                        #if defined (_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
                                        #ifdef _WIN32 /* Added by Masanori Satake. */
					afxDump << "EntryNumber " << pRec->m_entryNumber;
                                        #else /* _UNIX or VX */
					PRINTERR("EntryNumber ");
					PRINTERR(pRec->m_entryNumber);
                                        #endif /* #ifdef _WIN32 */
					#endif

					pRec->m_entryNumber -= doubleFlux;

					/*		#if defined(_WIN32) && defined (_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                                        #if defined (_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
                                        #ifdef _WIN32 /* Added by Masanori Satake. */
					afxDump << " to " << pRec->m_entryNumber << "\n";
					Sleep(5);
					afxDump.Flush();
                                        #else /* _UNIX or VX */
					PRINTERR(" to ");
					PRINTERR(pRec->m_entryNumber);
					PRINTERR("\n");
                                        #endif /* #ifdef _WIN32 */
					#endif

					if( pRec->m_entryNumber <= m_lastEntryNum  )
					{
						#if defined(_WIN32) && defined (_DEBUG)
						if( NULL != pRecs[pRec->m_entryNumber] )
						{
							ASSERT(FALSE);
						}
						#endif

						pRecs[pRec->m_entryNumber] = pRec;
					}
					/*		#if defined(_WIN32) && defined (_DEBUG) */ /* Deleted by Masanori Satake. */
                                        #ifdef _DEBUG /* Added by Masanori Satake. */
					else
					{
                                                #ifdef _WIN32 /* Added by Masanori Satake. */
						afxDump << "**** ERROR: pRec->m_entryNumber > m_lastEntryNum!\n"; 
						afxDump << "pRec->m_entryNumber == " << pRec->m_entryNumber << "\n";
						Sleep(5);
						afxDump.Flush();
                                                #else /* _UNIX or VX */
						PRINTERR("**** ERROR: pRec->m_entryNumber > m_lastEntryNum!\n");
						PRINTERR("pRec->m_entryNumber == ");
						PRINTERR(pRec->m_entryNumber);
						PRINTERR("\n");
                                                #endif /* #ifdef _WIN32 */
					}
					#endif

				}

				pRec = pRec->NextRec;
			}
		}

		if( 0 != errVal )
			RETURN(errVal);
	}
	while(FALSE);

	#if defined(_WIN32) && defined(_DEBUG)
	/* Mark by Masanori Satake. */
	int lf = 8;
	afxDump << delCount << " entries tagged for deletion..\nDeleting";
	#endif

	pListEnd = pRecList;
	for( vPos = 0; vPos < delCount; vPos++ )
	{
		if( NULL == pListEnd )
		{
		  /*		#if defined(_WIN32) && defined(_DEBUG) */ /* Deleted by Masanori Satake. */
                        #if defined(_DEBUG) /* Added by Masanori Satake. */
                        #ifdef _WIN32 /* Added by Masanori Satake. */
			afxDump << "**** Error: pListEnd == NULL ****\n****   vPos == " << vPos << "\n****   delCount == " << delCount << "\n";
                        #else /* _UNIX or VX */
			PRINTERR("**** Error: pListEnd == NULL ****\n****   vPos == ");
			PRINTERR(vPos);
			PRINTERR("\n****   delCount == ");
			PRINTERR(delCount);
			PRINTERR("\n");
                        #endif /* #ifdef _WIN32 */
			#endif
			break;
		}

		/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
                #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << ".";
		if( ++lf >= 60 )
		{
			afxDump << "\n";
			lf = 0;
		}
		afxDump.Flush();
                #else /* _UNIX or VX */
		PRINTERR(".");
		if( ++lf >= 60 )
		{
		  PRINTERR("\n");
		  lf = 0;
		}
                #endif /* #ifdef _WIN32 */
		#endif

		m_lpPathTable->Delete(*pListEnd);

		pListEnd = pListEnd->NextRec;

	}

	/*	#if defined(_WIN32) && defined(_DEBUG) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "\nDone deleting entries, beginning time re-index\n";
        #else /* _UNIX or VX */
	PRINTERR("\nDone deleting entries, beginning time re-index\n");
        #endif /* #ifdef _WIN32 */
	#endif

	for( vPos = 1; vPos <= m_lastEntryNum; vPos++ )
	{
		if( NULL == pRecs[vPos] )
			nullCount++;
		else
		{

		  /*		#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
                        #ifdef _WIN32 /* Added by Masanori Satake. */
			afxDump << "Index " << pRecs[vPos]->m_entryNumber << " to " << pRecs[vPos]->m_entryNumber - nullCount << "\n";
			Sleep(5);
			afxDump.Flush();
			Sleep(0);
                        #else /* _UNIX or VX */
			PRINTERR("Index ");
			PRINTERR(pRecs[vPos]->m_entryNumber);
			PRINTERR(" to ");
			PRINTERR(pRecs[vPos]->m_entryNumber - nullCount);
			PRINTERR("\n");
                        #endif /* #ifdef _WIN32 */
			#endif
			pRecs[vPos]->m_entryNumber -= nullCount;
			entryCount++;
		}

	}

	m_lastEntryNum = entryCount;
	m_entryCount = entryCount;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "-------------------------------------------\nReturning from CPathCache::RemoveOldItems()\n";
        #else /* _UNIX or VX */
	PRINTERR("-------------------------------------------\nReturning from CPathCache::RemoveOldItems()\n");
        #endif /* #ifdef _WIN32 */
	#endif

	#if defined(_WIN32) && defined (_DEBUG)
	DWORD stopt = GetTickCount();
	stopt -= startt;
	afxDump << "Elapsed: " << stopt << " milliseconds.\n-------------------------------------------\n";
	#endif

	RETURN(0);
}

  

long CPathCache::Serialize()
{

	if( !IsValid()  )
		return PATHCACHE_NOT_INITIALIZED;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "CPathCache::Serialize()\n";
        #else /* _UNIX or VX */
	PRINTERR("CPathCache::Serialize()\n");
        #endif /* #ifdef _WIN32 */
	#endif

	if( NULL == m_diskPath )
	{
	  /*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
                #ifdef _WIN32 /* Added by Masanori Satake. */
		afxDump << "CPathCache::Serialize() - m_diskPath == NULL, so returning\n";
                #else /* _UNIX or VX */
		PRINTERR("CPathCache::Serialize() - m_diskPath == NULL, so returning\n");
                #endif /* #ifdef _WIN32 */
		#endif
		return PATH_CACHE_NO_DISK_PATH;
	}
		

	char *pFileName = NULL;
	FILE* pOutFile = NULL;
	CPathRec *pRec = NULL;
	long vPos = 0;
	long rv = 0;
	char *pEntryData = NULL;
	unsigned int entryLength = 0;
	unsigned int bytesWritten = 0;
	unsigned int entryStringLength = 512;

#undef RETURN
#ifndef VX /* Added by Masanori Satake. */
#define RETURN(r){if( NULL != pFileName ) 	{	try{ delete []pFileName; pFileName = NULL; }catch(...){} } if( NULL != pEntryData ) 	{	try{ delete []pEntryData; pEntryData = NULL; }catch(...){} } if( NULL != pOutFile ) { try{ fclose(pOutFile); pOutFile = NULL; }catch(...){} } 	return r; }		
#else
#define RETURN(r){if( NULL != pFileName ) { delete []pFileName; pFileName = NULL; } if( NULL != pEntryData ) {delete []pEntryData; pEntryData = NULL; } if( NULL != pOutFile ){ fclose(pOutFile); pOutFile = NULL;} return r; }		
#endif

	ReindexEntryNums();

	pFileName = new char[strlen(m_diskPath) + strlen(PATHCACHE_FILE_NAME) + 8];
	if( NULL == pFileName )
	{
		RETURN(PATHCACHE_ALLOC_FAIL);
	}
	pEntryData = new char[entryStringLength];
	if( NULL == pEntryData )
	{
		RETURN(PATHCACHE_ALLOC_FAIL);
	}

	strcpy(pFileName,m_diskPath);

	/*	#ifdef _UNIX */ /* Deleted by Masanori Satake. */
        #if defined(_UNIX) || defined(VX) /* Added by Masanori Satake. */
	if( pFileName[strlen(pFileName)-1] != '/' )
	{
		strcat(pFileName,"/");
	}
	#else
	if( pFileName[strlen(pFileName)-1] != '\\' )
	{
		strcat(pFileName,"\\");
	}
	#endif

	strcat(pFileName,PATHCACHE_FILE_NAME);

	pOutFile = fopen(pFileName,"wb");

	if( NULL == pOutFile )
	{
		RETURN(PATHCACHE_OUTPUTFILE_FAIL); 
	}	

	rv = MakeHeaderString(pEntryData,entryStringLength,&entryLength);
	if( 0 != rv )
	{
		RETURN(rv); 
	}

	if( entryLength != (unsigned int)fwrite(pEntryData,1,entryLength,pOutFile) )
	{
		RETURN(PATHCACHE_OUTPUTFILE_FAIL);
	}

	for( ; vPos < PATHCACHE_TABLE_SIZE; vPos++ )
	{
		pRec = m_lpPathTable->HashVector[vPos];
		while( NULL != pRec )
		{

			rv = MakeSerialString(pRec,vPos,pEntryData,entryStringLength,&entryLength);
			if( 0 != rv )
			{
				while( PATHCACHE_BUFF_TOO_SHORT == rv )
				{
					delete []pEntryData;
					entryStringLength += 64;
					pEntryData = new char[entryStringLength+2];
					if( NULL == pEntryData )
					{
						RETURN(PATHCACHE_ALLOC_FAIL);
					}
					rv = MakeSerialString(pRec,vPos,pEntryData,entryStringLength,&entryLength);
				}

				if( 0 != rv )
				{
					RETURN(rv);
				}
			}

			if( 0 != entryLength )
			{
				bytesWritten = fwrite(pEntryData,1,entryLength,pOutFile);
				if( bytesWritten != entryLength )
				{
					RETURN(PATHCACHE_OUTPUTFILE_FAIL);
				}
			}

			pRec = pRec->NextRec;
		}
	}




	RETURN(0);
}

long CPathCache::AddEntry(const char *subjectIssuer, 
						  Bytes_struct *subjectSerial, 
						  const char *issuerCA, 
						  Bytes_struct *issuerSerial, 
						  const unsigned long flag, 
						  CPathRec** newRecord )
{
	long rv = 0;

	if( !IsValid() )
		return PATHCACHE_NOT_INITIALIZED;

	if( m_entryCount > PATHCACHE_MAX_ENTRY_FLUX + PATHCACHE_MAX_ENTRY_COUNT )
	{
		rv = RemoveOldItems();
		if( 0 != rv )
			return rv;
	}

	rv = tmpPathRec.set_entry( subjectIssuer,subjectSerial,issuerCA,issuerSerial,flag );
	if( 0 != rv )
		return PATHCACHE_INVALID_CERT_DATA;


	CPathRec *pRec = m_lpPathTable->Search(tmpPathRec);
	if( NULL != pRec )
	{
		if( !m_lpPathTable->Delete(*pRec) )
			return PATHCACHE_DELETE_ERROR;

		m_entryCount--;
	}

	tmpPathRec.m_entryNumber = ++m_lastEntryNum;

	if( !m_lpPathTable->Insert(tmpPathRec) )
		return PATHCACHE_INSERT_ERROR;

	m_entryCount++;
	
	if( NULL != newRecord )
	{
		*newRecord = m_lpPathTable->Search(tmpPathRec);
		if( NULL == *newRecord )
			return PATHCACHE_INSERT_ERROR;	
	}

	return 0;

}

long CPathCache::ReindexEntryNums()
{

	#if defined(_WIN32) && defined (_DEBUG)
	DWORD startt = GetTickCount();
	#endif

	CPathRec *pRec = NULL;
	long vPos = 0;
	CPathRec **pRecs = NULL;
	long nullCount = 0;
	long entryCount = 0;

#undef RETURN
#ifndef VX /* Added by Masanori Satake. */
#define RETURN(r){if( NULL != pRecs ) {	try{ delete []pRecs; pRecs = NULL; }catch(...){} } return r; }	
#else
#define RETURN(r){if( NULL != pRecs ){ delete []pRecs; pRecs = NULL; } return r; }	
#endif
	if( m_entryCount >= PATHCACHE_MAX_ENTRY_COUNT + PATHCACHE_MAX_ENTRY_FLUX)
	{
		return RemoveOldItems();
	}

	/*	#if defined(_WIN32) && defined (_DEBUG) */ /* Deleted by Masanori Satake. */
        #if defined (_DEBUG) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "Reindexing path entry numbers..\n";
        #else /* _UNIX or VX */
	PRINTERR("Reindexing path entry numbers..\n");
        #endif /* #ifdef _WIN32 */
	#endif

	pRecs = new CPathRec*[m_lastEntryNum + 8];
	if( NULL == pRecs )
		RETURN(PATHCACHE_ALLOC_FAIL);

	memset(pRecs,0,sizeof(CPathRec*)*(m_lastEntryNum + 8));


	/*	#if defined(_WIN32) && defined (_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined (_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "Adding entries to index vector:\n";
	int col = 0;
        #else /* _UNIX or VX */
	PRINTERR("Adding entries to index vector:\n");
        #endif /* #ifdef _WIN32 */
	#endif

	for( ; vPos < PATHCACHE_TABLE_SIZE; vPos++ )
	{
		pRec = m_lpPathTable->HashVector[vPos];
		while( NULL != pRec )
		{
		  /*	#if defined(_WIN32) && defined (_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                        #if defined (_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
                        #ifdef _WIN32 /* Added by Masanori Satake. */
			afxDump << pRec->m_entryNumber << ", ";
			if( ++col > 20 )
			{
				afxDump << "\n";
				col = 0;
			}
			Sleep(3);
			afxDump.Flush();
                        #else /* _UNIX or VX */
			PRINTERR(pRec->m_entryNumber);
			PRINTERR(", ");
                        #endif /* #ifdef _WIN32 */
			#endif

			if( pRec->m_entryNumber <= m_lastEntryNum )
			{
				#if defined(_WIN32) && defined (_DEBUG)
				if( NULL != pRecs[pRec->m_entryNumber] )
				{
					ASSERT(FALSE);
				}
				#endif

				pRecs[pRec->m_entryNumber] = pRec;
			}
			/*	#if defined(_WIN32) && defined (_DEBUG) */ /* Deleted by Masanori Satake. */
                        #if defined (_DEBUG) /* Added by Masanori Satake. */
			else
                        #ifdef _WIN32 /* Added by Masanori Satake. */
			{	afxDump << "**** ERROR: pRec->m_entryNumber > m_lastEntryNum!\n"; }
                        #else /* _UNIX or VX */
			{       PRINTERR("**** ERROR: pRec->m_entryNumber > m_lastEntryNum!\n"); }
                        #endif /* #ifdef _WIN32 */
			#endif

			pRec = pRec->NextRec;
		}
	}

	/*	#if defined(_WIN32) && defined (_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_WIN32) && defined (_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "\n";
        #else /* _UNIX or VX */
	PRINTERR("\n");
        #endif /* #ifdef _WIN32 */
	#endif

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	int lf = 17;
	afxDump << "Vector completed.\nAssigning numbers";
        #else /* _UNIX or VX */
	PRINTERR("Vector completed.\nAssigning numbers");
        #endif /* #ifdef _WIN32 */
	#endif

	for( vPos = 1; vPos <= m_lastEntryNum; vPos++ )
	{
		if( NULL == pRecs[vPos] )
			nullCount++;
		else
		{
			pRecs[vPos]->m_entryNumber -= nullCount;
			entryCount++;
			/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
                        #if defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
                        #ifdef _WIN32 /* Added by Masanori Satake. */
			afxDump << ".";
			if( ++lf == 60 )
			{
				afxDump << "\n";
				lf = 0;
			}
                        #else /* _UNIX or VX */
			PRINTERR(".");
                        #endif /* #ifdef _WIN32 */
			#endif
		}

	}

	m_lastEntryNum = entryCount;
	m_entryCount = entryCount;

	/*	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) */ /* Deleted by Masanori Satake. */
        #if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE) /* Added by Masanori Satake. */
        #ifdef _WIN32 /* Added by Masanori Satake. */
	afxDump << "\nReturning from CPathCache::ReindexEntryNums()\n";
        #else /* _UNIX or VX */
	PRINTERR("\nReturning from CPathCache::ReindexEntryNums()\n");
        #endif /* #ifdef _WIN32 */
	#endif

	#if defined(_WIN32) && defined (_DEBUG)
	DWORD stopt = GetTickCount();
	stopt -= startt;
	afxDump << "\nElapsed: " << stopt << " milliseconds.\n";
	#endif


	RETURN(0);
}




long CPathCache::DeleteEntry(CPathRec &pathRec)
{
	CPathRec* pRec = NULL;
	
	/* Note that FindEntry sets the entry number 
		to ++m_lastEntryNum when found */
	pRec = FindEntry(pathRec);

	if( NULL == pRec )
	{
		return PATHCACHE_NO_SUCH_ENTRY;
	}

	if( true != m_lpPathTable->Delete(*pRec) )
	{
		#if defined(_WIN32) && defined (_DEBUG)
		ASSERT(FALSE); /* Should NEVER happen! */
		#endif
		return PATHCACHE_DEL_ERROR;
	}

	m_lastEntryNum--;
	m_entryCount--;

	return 0;
}

long CPathCache::DeleteEntry(const char *subjectIssuer, Bytes_struct *subjectSerial)
{
	CPathRec* pRec = NULL;
	
	/* Note that FindEntry sets the entry number 
		to ++m_lastEntryNum when found */
	pRec = FindEntry(subjectIssuer,subjectSerial);

	if( NULL == pRec )
	{
		return PATHCACHE_NO_SUCH_ENTRY;
	}

	if( true != m_lpPathTable->Delete(*pRec) )
	{
		#if defined(_WIN32) && defined (_DEBUG)
		ASSERT(FALSE); /* Should NEVER happen! */
		#endif
		return PATHCACHE_DEL_ERROR;
	}

	m_lastEntryNum--;
	m_entryCount--;

	return 0;
}

long CPathCache::DeleteEntry(Cert_struct *subjectCert)
{
	CPathRec* pRec = NULL;
	
	/* Note that FindEntry sets the entry number 
		to ++m_lastEntryNum when found */
	pRec = FindEntry(subjectCert);

	if( NULL == pRec )
	{
		return PATHCACHE_NO_SUCH_ENTRY;
	}

	if( true != m_lpPathTable->Delete(*pRec) )
	{
		#if defined(_WIN32) && defined (_DEBUG)
		ASSERT(FALSE); /* Should NEVER happen! */
		#endif
		return PATHCACHE_DEL_ERROR;
	}

	m_lastEntryNum--;
	m_entryCount--;

	return 0;
}


long CPathCache::MakeSerialString( CPathRec* pathRec, long vectorPos, char* pStr, unsigned int strLength, unsigned int *dataLen )
{
	if( NULL == pStr || NULL == dataLen )
		return PATHCACHE_REQUIRED_PARAM;

	*dataLen = 0;

	if( vectorPos >= PATHCACHE_TABLE_SIZE )
		return PATHCACHE_PARAM_INVALID;

	LPPATH_ENTRY_STRUCT pEntry = pathRec->get_entry_pointer();

	if( NULL == pEntry )
		return PATHCACHE_REQUIRED_PARAM;

	#if defined(_WIN32)
		if( IsBadWritePtr(pStr,strLength) )
			return PATHCACHE_PARAM_INVALID;
	#endif

	unsigned int totLength = 0;
	long recLength = 0;
	long tmpLen = 0;
	unsigned int pos = 0;
	unsigned int longSize = sizeof(long);

	/* Record Format:
		
	long: rec length
	long: vector position
	long: entry number
	string: subjectIssuerDN
	NULL
	long: length of subjectSerial
	binary: subjectSerial
	string: issuerCADN
	NULL
    long: length of issuerSerial
	binary: issuerSerial
	LF

	*/

	/* Lengths of serial numbers */
	totLength = pEntry->subjectSerial.num +
				pEntry->issuerSerial.num;

	/* Add the remainder of the lengths */
	totLength += (5 * longSize) +
				 strlen(pEntry->subjectIssuerDN) +
				 strlen(pEntry->issuerCADN);

	/* Add LF(1),NULLS(2) */
	totLength += 3;
				
	if( strLength < totLength + 1 )
		return PATHCACHE_BUFF_TOO_SHORT;

	#if defined(_DEBUG)
		memset(pStr,0xFF,totLength);
	#endif

	recLength = totLength - longSize;
	
	/* record length */
	memcpy( &(pStr[pos]),&recLength,longSize );
	pos += longSize;

	/* vector postition */
	memcpy( &(pStr[pos]),&vectorPos, longSize );
	pos += longSize;

	/* entry number */
	memcpy( &(pStr[pos]),&(pathRec->m_entryNumber), longSize );
	pos += longSize;

	/* subject dn */
	strcpy( &(pStr[pos]),pEntry->subjectIssuerDN );
	pos += strlen(pEntry->subjectIssuerDN);

	/* length of subject serial */
	tmpLen = (long)pEntry->subjectSerial.num;
	memcpy( &(pStr[++pos]),&(tmpLen), longSize );
	pos += longSize;

	/* subject serial number */
	memcpy(&(pStr[pos]),pEntry->subjectSerial.data, tmpLen);
	pos += tmpLen;

	/* issuers CA dn */
	strcpy(&(pStr[pos]),pEntry->issuerCADN);
	pos += strlen(pEntry->issuerCADN);

	/* issuers serial num length */
	tmpLen = (long)pEntry->issuerSerial.num;
	memcpy( &(pStr[++pos]),&(tmpLen), longSize );
	pos += longSize;

	/* issuers serial num */
	memcpy(&(pStr[pos]),pEntry->issuerSerial.data, tmpLen);
	pos += tmpLen;

	pStr[pos] = '\n';

	#if defined(_WIN32) && defined(_DEBUG)
		ASSERT( ++pos == totLength );
	#endif

	*dataLen = totLength;
	//void CPLI_btoa(char* byteval, char* ascval, unsigned int blength);


	return 0;
	

}

long CPathCache::ReadCacheFile()
{

	if( !IsValid() || NULL == m_diskPath )
		return PATHCACHE_NOT_INITIALIZED;

	char *pFileName = NULL;
	FILE* pInFile = NULL;
	CPathRec *pRec = NULL;
	CPathRec *pVectorRec = NULL;
	long vPos = 0;
	int pos = 0;
	long rv = 0;
	char *pEntryData = NULL;
	int entryLength = 0;
	int bytesRead = 0;
	int entryStringLength = PATHCACHE_MAX_ENTRY_SIZE + 8;
	int longSize = sizeof(long);
	long entryNumber = 0;

	PATH_ENTRY_STRUCT entryStruct;

#undef RETURN
#ifndef VX /* Added by Masanori Satake. */
#define RETURN(r){if( NULL != pFileName ) 	{	try{ delete []pFileName; pFileName = NULL; }catch(...){} } if( NULL != pEntryData ) 	{	try{ delete []pEntryData; pEntryData = NULL; }catch(...){} } if( NULL != pInFile ) 	{ try{ fclose(pInFile); pInFile = NULL; }catch(...){} } 	return r; }		
#else
#define RETURN(r){if( NULL != pFileName ) {delete []pFileName; pFileName = NULL;} if( NULL != pEntryData ){delete []pEntryData; pEntryData = NULL;} if( NULL != pInFile ){fclose(pInFile); pInFile = NULL;} 	return r; }		
#endif
	pFileName = new char[strlen(m_diskPath) + strlen(PATHCACHE_FILE_NAME) + 8];
	if( NULL == pFileName )
	{
		RETURN(PATHCACHE_ALLOC_FAIL);
	}
	pEntryData = new char[entryStringLength+2];
	if( NULL == pEntryData )
	{
		RETURN(PATHCACHE_ALLOC_FAIL);
	}

	strcpy(pFileName,m_diskPath);

	#ifdef _UNIX
	if( pFileName[strlen(pFileName)-1] != '/' )
	{
		strcat(pFileName,"/");
	}
	#else
	if( pFileName[strlen(pFileName)-1] != '\\' )
	{
		strcat(pFileName,"\\");
	}
	#endif

	strcat(pFileName,PATHCACHE_FILE_NAME);

	pInFile = fopen(pFileName,"rb");

	if( NULL == pInFile )
	{
		/* Not necessarily an error - no cache file found.. */
		RETURN(PATHCACHE_FILENOTFOUND); 
	}	

	bytesRead = fread(pEntryData,1,PATHCACHE_HEADER_LENGTH,pInFile);
	if( bytesRead != PATHCACHE_HEADER_LENGTH )
	{
		RETURN(PATHCACHE_INPUTFILE_FAIL);
	}

	/* Header ---
	1 byte - integer == sizeof(long)
	long - PATHCACHE_VERSION
	long - PATHCACHE_TABLE_SIZE
	long - PATHCACHE_MAX_ENTRY_COUNT
	string - PATH_CACHE_HEADER_STR
	PADDING - to PATHCACHE_HEADER_LENGTH chars
	*/

	if( pEntryData[pos++] != (char)longSize )
	{
		RETURN(PATHCACHE_CACHEFILE_WRONG_OS);
	}
#ifdef SOLARIS
	long templong;
	memcpy (&templong, &pEntryData[pos], 4);
	if( templong != PATHCACHE_VERSION )
#else
	if( *(long *)&(pEntryData[pos]) != PATHCACHE_VERSION )
#endif
	{
		RETURN(PATHCACHE_INCOMPATABLE_VER);
	}
	pos += longSize;
#ifdef SOLARIS
        templong = 0;
        memcpy (&templong, &pEntryData[pos], 4);
	long templong1;
	memcpy (&templong1, &(pEntryData[pos + longSize]), 4);
	if( templong != PATHCACHE_TABLE_SIZE ||
	    templong1 != PATHCACHE_MAX_ENTRY_COUNT    )
#else
	if( *(long*)&(pEntryData[pos]) != PATHCACHE_TABLE_SIZE ||
		*(long*)&(pEntryData[pos + longSize]) != PATHCACHE_MAX_ENTRY_COUNT    )
#endif
	{
		RETURN(PATHCACHE_INCOMPATABLE_VER);
	}
/*	pos += 2*longSize;*/

	m_lastEntryNum = 0;
	m_entryCount = 0;

#ifndef VX /* Added by Masanori Satake. */
	try
	{
#endif
	do
	{
		bytesRead = fread(pEntryData,1,longSize,pInFile);
		if( bytesRead != longSize  )
		{	
			break;		
		}

		entryLength = *(long*)&(pEntryData[0]);

		if( entryLength > PATHCACHE_MAX_ENTRY_SIZE )
		{
			rv = PATHCACHE_FILE_CORRUPT;
			break;
		}

		bytesRead = fread(pEntryData,1,entryLength,pInFile);
		if( bytesRead != entryLength  )
		{	
			break;		
		}

		if( pEntryData[entryLength-1] != '\n' )
		{
			rv = PATHCACHE_FILE_CORRUPT;
			break;
		}

		/* Record Format:	
		long: rec length
		long: vector position
		long: entry number
		string: subjectIssuerDN
		NULL
		long: length of subjectSerial
		binary: subjectSerial
		string: issuerCADN
		NULL
		long: length of issuerSerial
		binary: issuerSerial
		LF
		*/

		pos = 0;

		/* Get vector position */
		vPos = *(long*)&(pEntryData[pos]);
		pos += longSize;

		if( vPos >= PATHCACHE_TABLE_SIZE || 0 > vPos )
		{
			rv = PATHCACHE_FILE_CORRUPT;
			break;
		}

		/* Get entry number */
		entryNumber = *(long*)&(pEntryData[pos]);
		pos += longSize;

		if( entryNumber > PATHCACHE_MAX_ENTRY_COUNT || 0 > entryNumber )
		{
			rv = PATHCACHE_FILE_CORRUPT;
			break;
		}

		/* Pointer to subject issuer */
		entryStruct.subjectIssuerDN = &(pEntryData[pos]);
		pos += strlen(entryStruct.subjectIssuerDN) + 1;

		/* Subject Serial Length */
		entryStruct.subjectSerial.num = *(long*)&(pEntryData[pos]);
		pos += longSize;

		if( PATHCACHE_MAX_SERIAL < entryStruct.subjectSerial.num )
		{
			rv = PATHCACHE_FILE_CORRUPT;
			break;
		}

		/* Subject Serial Num */
		entryStruct.subjectSerial.data = (unsigned char*)&(pEntryData[pos]);
		pos += entryStruct.subjectSerial.num;

		/* Pointer to issuerCADN */
		entryStruct.issuerCADN = &(pEntryData[pos]);
		pos += strlen(entryStruct.issuerCADN) + 1;

		/* Subject Issuer Serial Length */
		entryStruct.issuerSerial.num = *(long*)&(pEntryData[pos]);
		pos += longSize;


		if( PATHCACHE_MAX_SERIAL < entryStruct.issuerSerial.num )
		{
			rv = PATHCACHE_FILE_CORRUPT;
			break;
		}


		/* Subject Serial Num */
		entryStruct.issuerSerial.data = (unsigned char*)&(pEntryData[pos]);
		pos += entryStruct.issuerSerial.num;

		/* Verify EORecord */
		if( pEntryData[pos] != '\n' )
		{
			#if defined(_WIN32) && defined(_DEBUG)
				ASSERT(FALSE);
			#endif
			rv = PATHCACHE_FILE_CORRUPT;
			break;
		}

		/* Allocate entry */
		pRec = new CPathRec;
		if( NULL == pRec )
		{
			rv = PATHCACHE_ALLOC_FAIL;
			break;
		}

		/* Set entry data */
		rv = pRec->set_entry(&entryStruct);
		if( 0 != rv )
		{
			break;
		}

		pVectorRec = m_lpPathTable->HashVector[vPos];
		if( NULL != pVectorRec )
		{
			while( pVectorRec->NextRec != NULL )
			{
				pVectorRec = pVectorRec->NextRec;
			}

			pVectorRec->NextRec = pRec;
		}
		else
		{
			m_lpPathTable->HashVector[vPos] = pRec;
		}

		pRec->m_entryNumber = entryNumber;

		/* Marked by Masanori Satake. */
		#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE)
			static int sdf = 0;

			if( ++sdf == 20 )
			{
				afxDump << entryNumber << "\r\n";
				sdf = 0;
			}
			else
			{
				afxDump << entryNumber << ", ";
			}
			Sleep(3);
			if( entryNumber == m_lastEntryNum )
			{
				ASSERT(FALSE);
			}
		#endif

		if( entryNumber > m_lastEntryNum )
			m_lastEntryNum = entryNumber;

		m_entryCount++;

		pRec->NextRec = NULL;

		if( 0 != feof(pInFile) )
		{
			break;
		}
	}
	while(TRUE);

#ifndef VX /* Added by Masanori Satake. */
	}
	catch(...)
	{
		rv = PATHCACHE_EXCEPTION;
	}
#endif
	/* Marked by Masanori Satake. */
	#if defined(_WIN32) && defined(_DEBUG) && defined(_DEBUG_VERBOSE)
		afxDump << "\n";
	#endif

	RETURN(rv);
}

long CPathCache::MakeHeaderString(char *pStr, unsigned int strLength, unsigned int *headerLength)
{
	
	if( NULL == pStr || NULL == headerLength )
		return PATHCACHE_REQUIRED_PARAM;

	*headerLength = 0;

	if( PATHCACHE_HEADER_LENGTH >= strLength )
		return PATHCACHE_PARAM_INVALID;

	#if defined(_WIN32)
		if(IsBadWritePtr(pStr,PATHCACHE_HEADER_LENGTH))
			return PATHCACHE_PARAM_INVALID;
	#endif
	
	int longSize = sizeof(long);
	char lsize = (char)longSize;
	long tmpVal = 0;
	int pos = 0;

	/* Header ---
	1 byte - integer == sizeof(long)
	long - PATHCACHE_VERSION
	long - PATHCACHE_TABLE_SIZE
	long - PATHCACHE_MAX_ENTRY_COUNT
	string - PATH_CACHE_HEADER_STR
	PADDING - to PATHCACHE_HEADER_LENGTH chars
	*/

	lsize = (char)sizeof(long);
	pStr[pos++] = lsize;

	tmpVal = PATHCACHE_VERSION;
	memcpy(&(pStr[pos]),&tmpVal,longSize);
	pos += longSize;

	tmpVal = PATHCACHE_TABLE_SIZE;
	memcpy(&(pStr[pos]),&tmpVal,longSize);
	pos += longSize;

	tmpVal = PATHCACHE_MAX_ENTRY_COUNT;
	memcpy(&(pStr[pos]),&tmpVal,longSize);
	pos += longSize;

	strcpy(&(pStr[pos]),PATHCACHE_HEADER_STR);
	pos += strlen(PATHCACHE_HEADER_STR);

	memset(&(pStr[pos]),0x00,PATHCACHE_HEADER_LENGTH - pos);

	pStr[PATHCACHE_HEADER_LENGTH-1] = '\n';

	*headerLength = PATHCACHE_HEADER_LENGTH;

	return 0;
}


#ifdef _DEBUG_VERBOSE
#undef _DEBUG_VERBOSE
#endif

