Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1512 lines
40 KiB

//
// implementation of no compile browser API
//
#include "pdbimpl.h"
#include "ncbrowse.h"
#include "ncwrap.h"
Array <NcbInfo> *Ncb::ms_prgNcbInfo = new Array<NcbInfo>;
NameMap * Ncb::m_pnmStatic = NULL;
///////////////////////
// Constructor
///////////////////////
Ncb::Ncb()
{
m_pdb = NULL;
m_pnm = NULL;
m_fIOwnThePdb = FALSE;
m_bGraphBuilt = FALSE;
m_cTargets = 0;
m_iReadLock = NCB_MOD_BUF_SIZE;
// InitializeCriticalSection (&m_cs);
m_hMutexNCB = CreateMutex (NULL, FALSE, NULL);
m_hMutex = CreateMutex (NULL, FALSE, NULL);
};
Ncb::~Ncb()
{
// DeleteCriticalSection (&m_cs);
CloseHandle (m_hMutexNCB);
CloseHandle (m_hMutex);
};
/////////////////////////////////////////////////////////
// Initialization
//
// 1) Open the target header stream and read in all the
// target information.
// 2) Open the module header information for each header
// as well.
/////////////////////////////////////////////////////////
BOOL Ncb::init(PDB * pdb)
{
// assign to current pdb file opened
_ASSERT(pdb);
m_pdb = pdb;
m_bNotifyNow = TRUE;
m_rgNotify.setSize(0);
// open the name map (hash table)
// in the pdb for read and write (TRUE)
if (!NameMap::open (m_pdb, TRUE, &m_pnm))
return FALSE;
// if we have some target to read:
if (!LoadTargetsToMem (m_pdb))
return FALSE;
// load the module headers
if (!LoadModHdrsToMem (m_pdb))
return FALSE;
// initialize arrays:
USHORT i;
for (i = 0; i <NCB_MOD_BUF_SIZE; i++)
{
m_rgContBuf[i].m_prio = NCB_MOD_BUF_SIZE;
m_rgContBuf[i].m_rgProp = NULL;
m_rgContBuf[i].m_rgUse = NULL;
m_rgContBuf[i].m_rgParam = NULL;
m_rgContBuf[i].m_iModHdr = (USHORT)-1;
}
return TRUE;
};
/////////////////////////////////////////////////////////////
// LoadTargetToMem
// loading targets from stream into memory
/////////////////////////////////////////////////////////////
BOOL Ncb::LoadTargetsToMem(PDB * pdb)
{
Stream * pstmTargetInfo; // stream for target headers info
Stream * pstmTarget;
NCB_TARGET * rgTargets = NULL; // temporary array to store target hdr
Array<NCB_MODINFO> rgModInfo;
int i;
USHORT j;
char buf[512];
USHORT iMin;
// Open the stream contains target information
// and it should get all the information in there:
if (!pdb->OpenStream (SZ_NCB_TARGET_INFO, &pstmTargetInfo))
goto fail;
// count the number of target we have in the pdb file
m_cTargets = pstmTargetInfo->QueryCb()/ sizeof(NCB_TARGET);
_ASSERT(pstmTargetInfo);
if (m_cTargets)
{
// should read all the info into the memory:
rgTargets = new NCB_TARGET[m_cTargets];
if (!rgTargets)
goto fail;
if (!pstmTargetInfo->Read2(0, rgTargets, m_cTargets*sizeof (NCB_TARGET)))
goto fail;
// set the size for target information
m_rgTargetInfo.setSize (m_cTargets);
// for each target, load the file list information:
for (i = 0; i < m_cTargets; i++)
{
m_rgTargetInfo[i].m_ni = rgTargets[i].m_ni;
// get the name of the target and open
// the target stream
Buffer buffer;
CB cbStream;
PB pBuffer;
SZ szTarget = szFrNi (rgTargets[i].m_ni);
strcpy (buf, SZ_NCB_TARGET_PREFIX);
strcat (buf, szTarget);
if (!pdb->OpenStream (buf, &pstmTarget))
goto fail;
// REVIEW: must convert from sztarget to htarget
m_rgTargetInfo[i].m_hTarget = (HTARGET)-1;
// find out the size of the stream and
// allocate the necessary buffer size
cbStream = pstmTarget->QueryCb();
buffer.SetInitAlloc(cbStream);
pBuffer = buffer.Start();
// now must load stream information in:
if (!pstmTarget->Read2(0, pBuffer, cbStream))
goto fail;
// loading the corresponding arrays
if (!rgModInfo.reload (&pBuffer))
goto fail;
if (!m_rgTargetInfo[i].m_rgModInfo.setSize(rgModInfo.size()))
goto fail;
iMin = 0;
for (j = 0; j < rgModInfo.size(); j++)
{
m_rgTargetInfo[i].m_rgModInfo[j].m_iModHdr = rgModInfo[j].m_iModHdr;
m_rgTargetInfo[i].m_rgModInfo[j].m_bMember = FALSE;
m_rgTargetInfo[i].m_rgModInfo[j].m_bDel = FALSE;
m_rgTargetInfo[i].m_rgModInfo[j].m_bInit = FALSE;
}
pstmTarget->Release();
pstmTarget = NULL;
}
}
// deleting the target headers
delete []rgTargets;
return TRUE;
fail:
delete []rgTargets;
// need to close the stream since it is not needed anymore.
pstmTarget->Release();
pstmTarget = NULL;
pstmTargetInfo->Release();
pstmTargetInfo = NULL;
return FALSE;
};
////////////////////////////////////////////////////////////////
//
// SaveTargetsToStream(pdb)
// save target information to stream
/////////////////////////////////////////////////////////////////
BOOL Ncb::SaveTargetsToStream (PDB * pdb)
{
NCB_TARGET * rgTargets; // temporary array to store target info
Stream * pstmTarget;
char buf[512];
int i;
Array<NCB_MODINFO> rgModInfo;
USHORT cSize;
rgTargets = new NCB_TARGET[m_cTargets];
if (!rgTargets)
goto fail;
// for each target, save two arrays
// array of modules (m_rgModInfo)
for (i = 0 ; i < m_cTargets; i++)
{
Buffer buffer;
PB pBuffer;
SZ szTarget;
if (m_rgTargetInfo[i].m_ni == (NI)-1)
return FALSE;
szTarget = szFrNi (m_rgTargetInfo[i].m_ni);
strcpy (buf, SZ_NCB_TARGET_PREFIX);
strcat (buf, szTarget);
// REVIEW: should we compress it here or
// do this before compressing the modules
if (!CompressTarget (&m_rgTargetInfo[i], rgModInfo))
goto fail;
rgTargets[i].m_ni = m_rgTargetInfo[i].m_ni;
// store each target in a separate stream:
if (!pdb->OpenStream (buf, &pstmTarget))
goto fail;
if (!pstmTarget->Truncate(0))
goto fail;
cSize = 0;
// save the arrays in the buffer and write the content
// of the buffer to the stream
if (!rgModInfo.save (&buffer))
goto fail;
pBuffer = buffer.Start();
if (!pstmTarget->Append (pBuffer, buffer.Size()))
goto fail;
pstmTarget->Release();
pstmTarget = NULL;
}
if (!pdb->OpenStream (SZ_NCB_TARGET_INFO, &pstmTarget))
goto fail;
// store rgTargets
if (!pstmTarget->Truncate(0)) // delete previous information
goto fail;
if (!pstmTarget->Append (rgTargets, m_cTargets * sizeof (NCB_TARGET)))
goto fail;
pstmTarget->Release();
delete [] rgTargets;
return TRUE;
fail:
delete [] rgTargets;
pstmTarget->Release();
pstmTarget = NULL;
return FALSE;
};
///////////////////////////////////////////////////////////////
// DelUnreachable()
// check for unreachable nodes and mark it as m_bDel == TRUE
///////////////////////////////////////////////////////////////
BOOL Ncb::DelUnreachable(NCB_TARGETINFO * ti)
{
USHORT i;
for (i = 0; i < ti->m_rgModInfo.size(); i++)
{
ti->m_rgModInfo[i].m_bDel = TRUE;
}
for (i = 0; i < ti->m_rgModInfo.size(); i++)
{
if (ti->m_rgModInfo[i].m_bMember)
DelUnreachable (ti, i);
}
return TRUE;
};
BOOL Ncb::DelUnreachable (NCB_TARGETINFO * ti, USHORT i)
{
USHORT j;
if (ti->m_rgModInfo[i].m_bDel == FALSE) // node has been visited, return
return TRUE;
ti->m_rgModInfo[i].m_bDel = FALSE;
for (j = 0; j < ti->m_rgModInfo[i].m_rgIncl.size() ; j++)
{
DelUnreachable (ti, ti->m_rgModInfo[i].m_rgIncl[j].m_iModInfo);
}
return TRUE;
};
////////////////////////////////////////////////////////////////
// Compress Target
// Compress target information:
// Basically removing dead information in list of modules
// and list of includes
/////////////////////////////////////////////////////////////////
BOOL Ncb::CompressTarget(NCB_TARGETINFO * ti, Array<NCB_MODINFO> &rgModInfo)
{
USHORT * rgMapIndex;
USHORT iModInfo = 0;
USHORT i,j;
USHORT cModSize; // size for ModInfo array
USHORT cInclSize; // size of Include array
_ASSERT (ti);
if (m_bGraphBuilt)
DelUnreachable(ti);
// get the initial size of the ModInfo array
cModSize = ti->m_rgModInfo.size();
rgMapIndex = new USHORT[cModSize];
if (cModSize && !rgMapIndex)
return FALSE;
// Loop thru the array of modules and use the rgMapIndex
// for mapping the old->new position for each item
for (i = 0; i < cModSize; i++)
{
// if module has 0 ref count, then we should mark to delete
if (m_bGraphBuilt && ti->m_rgModInfo[i].m_bDel)
{
rgMapIndex[i] = (USHORT)-1; // should mark it as invalid
}
else
{
rgMapIndex[i] = iModInfo;
iModInfo++;
}
}
if (!rgModInfo.setSize (iModInfo))
return FALSE;
// now delete the "dead item" in the rgModInfo
// ie: compression for m_rgModInfo array
cInclSize = 0;
for (i = 0; i < cModSize; i++)
{
if (rgMapIndex[i] != (USHORT)-1)
{
// rgMapIndex[i] is always <= i so this is save
ti->m_rgModInfo[rgMapIndex[i]].m_iModHdr = ti->m_rgModInfo[i].m_iModHdr;
ti->m_rgModInfo[rgMapIndex[i]].m_bMember = ti->m_rgModInfo[i].m_bMember;
ti->m_rgModInfo[rgMapIndex[i]].m_bDel = ti->m_rgModInfo[i].m_bDel;
// fix up references before copying:
for (j = 0; j < ti->m_rgModInfo[i].m_rgIncl.size() ; j++)
{
_ASSERT (rgMapIndex[ti->m_rgModInfo[i].m_rgIncl[j].m_iModInfo] != (USHORT)-1);
ti->m_rgModInfo[i].m_rgIncl[j].m_iModInfo =
rgMapIndex[ti->m_rgModInfo[i].m_rgIncl[j].m_iModInfo];
}
ti->m_rgModInfo[rgMapIndex[i]].m_rgIncl.setSize(ti->m_rgModInfo[i].m_rgIncl.size());
// copy array to new location:
if (ti->m_rgModInfo[i].m_rgIncl.size() > 0)
memcpy (&ti->m_rgModInfo[rgMapIndex[i]].m_rgIncl[0], &ti->m_rgModInfo[i].m_rgIncl[0],
ti->m_rgModInfo[i].m_rgIncl.size() * sizeof (NCB_INCL));
rgModInfo[rgMapIndex[i]].m_iModHdr = ti->m_rgModInfo[i].m_iModHdr;
}
}
// setting the new size of m_rgModInfo
ti->m_rgModInfo.setSize(iModInfo);
delete [] rgMapIndex;
return TRUE;
};
////////////////////////////////////////////////////////////////
//
// CompressModHdr()
//
// compressing module header array (m_rgModHdr) and do
// a consistency check.
// If the header has a 0 reference, it will remove the stream
// NOTE:
// It is STRONGLY recommended to do a CompressTarget (for
// all targets) before calling this function, since
// it can substantially speed up the function
/////////////////////////////////////////////////////////////////
BOOL Ncb::CompressModHdr(PDB * pdb)
{
BOOL * rgModRef;
USHORT * rgMap;
unsigned i,j;
unsigned cModHdr = m_rgModHdr.size();
unsigned cNewModHdr;
unsigned cTarget;
unsigned cMod;
Stream * pstmMod;
rgModRef = new BOOL [cModHdr];
rgMap = new USHORT [cModHdr];
if (!rgModRef)
return FALSE;
if (!rgMap)
return FALSE;
for (i = 0; i < cModHdr; i++)
rgModRef[i] = FALSE; // initialize values to FALSE
// iterate every target array to count the
// total number of reference of each module
cTarget = m_rgTargetInfo.size();
for (i = 0; i < cTarget; i++)
{
cMod = m_rgTargetInfo[i].m_rgModInfo.size();
// check every module in a target
for (j = 0; j < cMod; j++)
rgModRef[m_rgTargetInfo[i].m_rgModInfo[j].m_iModHdr] = TRUE;
}
// now build the map from old index to new index
cNewModHdr = 0;
for (i = 0; i < cModHdr; i++)
{
if (rgModRef[i] == FALSE)
{
// remove the info from the stream
char buf[512];
SZ szMod = szFrNi (m_rgModHdr[i].m_ni);
strcpy (buf, SZ_NCB_MODULE_PREFIX);
strcat (buf, szMod);
// REVIEW: is this how to delete a stream??
if (pdb->OpenStream (buf, &pstmMod))
{
pstmMod->Delete();
pstmMod->Release();
pstmMod = NULL;
}
// mark the map as invalid
rgMap[i] = (USHORT)-1;
}
else // ref. count is greater than 0
{
// set a new map to use
rgMap[i] = cNewModHdr;
// copy the information to the new position
if (i != cNewModHdr)
m_rgModHdr[cNewModHdr] = m_rgModHdr[i];
// increment the counter
cNewModHdr++;
}
}
// set the new size for module header:
m_rgModHdr.setSize (cNewModHdr+1);
// now fix up the module list for each target
for (i = 0; i < cTarget; i++)
{
cMod = m_rgTargetInfo[i].m_rgModInfo.size();
// check every module in a target
for (j = 0; j < cMod; j++)
{
_ASSERT (rgMap[m_rgTargetInfo[i].m_rgModInfo[j].m_iModHdr] != (USHORT)-1);
m_rgTargetInfo[i].m_rgModInfo[j].m_iModHdr =
rgMap[m_rgTargetInfo[i].m_rgModInfo[j].m_iModHdr];
}
}
return TRUE;
};
/////////////////////////////////////////////////////////////////
// LoadModHdrsToMem
// load module headers to memory
/////////////////////////////////////////////////////////////////
BOOL Ncb::LoadModHdrsToMem (PDB * pdb)
{
Stream * pstmModInfo; // stream for module headers info
Buffer buffer;
PB pBuffer;
CB cbStream;
USHORT i;
if (!pdb->OpenStream (SZ_NCB_MODULE_INFO, &pstmModInfo))
return FALSE;
cbStream = pstmModInfo->QueryCb(); // get stream size
if (cbStream)
{
buffer.SetInitAlloc(cbStream);
pBuffer = buffer.Start();
// load the stream info to buffer:
if (!pstmModInfo->Read2(0, pBuffer, cbStream))
goto fail;
// load information to the array
if (!m_rgModHdr.reload(&pBuffer))
goto fail;
// initialize status array
if (!m_rgStat.setSize(m_rgModHdr.size()))
goto fail;
if (!m_rgNotifyBuild.setSize (m_rgModHdr.size()))
goto fail;
}
for (i =0; i < m_rgStat.size(); i++)
{
m_rgStat[i] = NCB_STATMOD_UNLOADED;
m_rgNotifyBuild[i] = FALSE;
}
pstmModInfo->Release();
return TRUE;
fail:
pstmModInfo->Release();
return FALSE;
};
/////////////////////////////////////////////////////////////////
// SaveModHdrsToStream ()
// save module headers to stream w/o compressing the array
// first. Compression should be done outside this function
/////////////////////////////////////////////////////////////////
BOOL Ncb::SaveModHdrsToStream(PDB * pdb)
{
Stream * pstmMod;
Buffer buffer;
PB pBuffer;
// open stream for module hdrs
if (!pdb->OpenStream (SZ_NCB_MODULE_INFO, &pstmMod))
return FALSE;
if (!pstmMod->Truncate (0))
goto fail;
// save the array to the buffer
if (!m_rgModHdr.save (&buffer))
goto fail;
// find where the buffer starts
pBuffer = buffer.Start();
// start writing the buffer to the stream
if (!pstmMod->Append (pBuffer, buffer.Size()))
goto fail;
m_rgModHdr.setSize(0); // clean up arrays
m_rgStat.setSize(0);
m_rgNotifyBuild.setSize (0);
pstmMod->Release();
return TRUE;
fail:
pstmMod->Release();
return FALSE;
};
/////////////////////////////////////////////////////////////////
// LoadModForRead()
// Loading module content for read-only (ie: query only)
// Contents will not be resaved to the pdb file when discarded.
// parameter: USHORT index to module header to get the info
/////////////////////////////////////////////////////////////////
BOOL Ncb::LoadModForRead(PDB * pdb, USHORT iModHdr, OUT USHORT * pindex)
{
USHORT i;
int iOldest = 0;
Stream * pstmMod = NULL;
char buf[512];
SZ szMod;
int offset;
_ASSERT (iModHdr < m_rgModHdr.size());
// check if it is already loaded for read or not
for (i = 0; i < NCB_MOD_BUF_SIZE; i++)
{
if (m_rgContBuf[i].m_iModHdr == iModHdr)
{
*pindex = i;
m_rgStat[iModHdr] = NCB_STATMOD_LOAD_READ;
return TRUE;
}
}
// update the priority ordering of the buffer and
// find the 'oldest' one.
// 0 - newest
// NCB_MOD_BUF_SIZE - oldest
// NCB_MOD_BUF_SIZE must be > 1 since we can lock
// one module buffer
iOldest = m_iReadLock == 0 ? 1 : 0;
for (i = iOldest ;i < NCB_MOD_BUF_SIZE; i++)
{
m_rgContBuf[i].m_prio++;
if (m_rgContBuf[i].m_prio >= m_rgContBuf[iOldest].m_prio &&
m_iReadLock != i)
iOldest = i;
}
_ASSERT (iOldest < NCB_MOD_BUF_SIZE);
// set the appropriate flag for this module.
// first, mark the previous content as unloaded
if (m_rgContBuf[iOldest].m_iModHdr != (USHORT)-1 &&
m_rgStat[m_rgContBuf[iOldest].m_iModHdr] == NCB_STATMOD_LOAD_READ)
m_rgStat[m_rgContBuf[iOldest].m_iModHdr] = NCB_STATMOD_UNLOADED;
m_rgContBuf[iOldest].m_iModHdr = (USHORT)-1;
// delete the old information from the buffer
delete [] m_rgContBuf[iOldest].m_rgProp;
delete [] m_rgContBuf[iOldest].m_rgUse;
delete [] m_rgContBuf[iOldest].m_rgParam;
m_rgContBuf[iOldest].m_rgProp = NULL;
m_rgContBuf[iOldest].m_rgUse = NULL;
m_rgContBuf[iOldest].m_rgParam = NULL;
// allocate space for the module content;
m_rgContBuf[iOldest].m_rgProp = new NCB_PROP[m_rgModHdr[iModHdr].m_cProp];
m_rgContBuf[iOldest].m_rgUse = new NCB_USE[m_rgModHdr[iModHdr].m_cUse];
m_rgContBuf[iOldest].m_rgParam = new NI [m_rgModHdr[iModHdr].m_cParam];
// if file content is empty, then we don't have to worry
// loading anything:
if (m_rgModHdr[iModHdr].m_cProp != 0)
{
// check if everything is ok or not
if ((m_rgContBuf[iOldest].m_rgProp == NULL &&
m_rgModHdr[iModHdr].m_cProp != 0) ||
(m_rgContBuf[iOldest].m_rgUse == NULL &&
m_rgModHdr[iModHdr].m_cUse != 0) ||
(m_rgContBuf[iOldest].m_rgParam == NULL &&
m_rgModHdr[iModHdr].m_cParam != 0))
goto fail;
// get the name of the module and open the module:
szMod = szFrNi (m_rgModHdr[iModHdr].m_ni);
strcpy (buf, SZ_NCB_MODULE_PREFIX);
strcat (buf, szMod);
if (!pdb->OpenStream (buf, & pstmMod))
goto fail;
if (!pstmMod->Read2 (0, m_rgContBuf[iOldest].m_rgProp,
m_rgModHdr[iModHdr].m_cProp * sizeof (NCB_PROP)))
goto fail;
offset = m_rgModHdr[iModHdr].m_cProp * sizeof (NCB_PROP);
if (m_rgModHdr[iModHdr].m_cUse > 0)
{
if (!pstmMod->Read2 (offset, m_rgContBuf[iOldest].m_rgUse,
m_rgModHdr[iModHdr].m_cUse * sizeof (NCB_USE)))
goto fail;
}
if (m_rgModHdr[iModHdr].m_cParam > 0)
{
offset += m_rgModHdr[iModHdr].m_cUse * sizeof (NCB_USE);
if (!pstmMod->Read2 (offset, m_rgContBuf[iOldest].m_rgParam,
m_rgModHdr[iModHdr].m_cParam * sizeof (NI)))
goto fail;
}
pstmMod->Release();
}
m_rgContBuf[iOldest].m_prio = 0; // set to be the newest one
m_rgContBuf[iOldest].m_iModHdr = iModHdr;
// then set the new content to loaded for read
m_rgStat[iModHdr] = NCB_STATMOD_LOAD_READ;
*pindex = iOldest;
return TRUE;
fail:
if (pstmMod)
pstmMod->Release();
// delete the from the buffer
delete [] m_rgContBuf[iOldest].m_rgProp;
delete [] m_rgContBuf[iOldest].m_rgUse;
delete [] m_rgContBuf[iOldest].m_rgParam;
m_rgContBuf[iOldest].m_rgProp = NULL;
m_rgContBuf[iOldest].m_rgUse = NULL;
m_rgContBuf[iOldest].m_rgParam = NULL;
return FALSE;
};
/////////////////////////////////////////////////////////////////
// SaveReadModToStream()
// given the module index (iBuf), we want to save it back to stream
// This is typically called after we LoadFrWriteToRead(), so we need
// to save its content to the stream.
/////////////////////////////////////////////////////////////////
BOOL Ncb::SaveReadModToStream (PDB * pdb, USHORT iBuf)
{
_ASSERT (iBuf < NCB_MOD_BUF_SIZE);
Stream * pstmMod;
char buf[512];
SZ szMod;
unsigned iHdr;
iHdr = m_rgContBuf[iBuf].m_iModHdr;
szMod = szFrNi (m_rgModHdr[iHdr].m_ni);
strcpy (buf, SZ_NCB_MODULE_PREFIX);
strcat (buf, szMod);
if (!pdb->OpenStream (buf, & pstmMod))
return FALSE;
if (!pstmMod->Truncate(0))
goto fail;
if (!pstmMod->Append (m_rgContBuf[iBuf].m_rgProp,
m_rgModHdr[iHdr].m_cProp * sizeof (NCB_PROP)))
goto fail;
if (!pstmMod->Append (m_rgContBuf[iBuf].m_rgUse,
m_rgModHdr[iHdr].m_cUse * sizeof (NCB_USE)))
goto fail;
if (!pstmMod->Append (m_rgContBuf[iBuf].m_rgParam,
m_rgModHdr[iHdr].m_cParam * sizeof (NI)))
goto fail;
// set buffer to be the oldest one:
pstmMod->Release();
m_rgContBuf[iBuf].m_prio = NCB_MOD_BUF_SIZE;
return TRUE;
fail:
pstmMod->Release();
return FALSE;
};
//////////////////////////////////////////////////////////////////
// LoadFrReadToWrite
// Convert from read-only format to read/write format
//////////////////////////////////////////////////////////////////
BOOL Ncb::LoadFrReadToWrite(USHORT iBuf, USHORT * piBuf)
{
_ASSERT (iBuf < NCB_MOD_BUF_SIZE);
unsigned i;
unsigned iCur = 0;
// check if we already open this for write before:
for (i = 0; i < m_rgRWBuf.size(); i++)
{
if (m_rgContBuf[iBuf].m_iModHdr == m_rgRWBuf[i].m_iModHdr)
break;
iCur++;
}
// the file is not in the buffer yet, so
// must extend the size of the array.
if (iCur == m_rgRWBuf.size())
{
if (!m_rgRWBuf.setSize (iCur+1))
return FALSE;
}
m_rgRWBuf[iCur].m_iModHdr = m_rgContBuf[iBuf].m_iModHdr;
USHORT cUse;
USHORT cParam;
if (!m_rgRWBuf[iCur].m_rgProp.setSize(m_rgModHdr[m_rgContBuf[iBuf].m_iModHdr].m_cProp))
return FALSE;
for (i = 0; i < m_rgModHdr[m_rgContBuf[iBuf].m_iModHdr].m_cProp; i++)
{
m_rgRWBuf[iCur].m_rgProp[i].m_en = m_rgContBuf[iBuf].m_rgProp[i].m_en;
m_rgRWBuf[iCur].m_rgProp[i].m_lnStart = m_rgContBuf[iBuf].m_rgProp[i].m_lnStart;
if (i == 0)
{
cUse = m_rgContBuf[iBuf].m_rgProp[i].m_iUse;
cParam = m_rgContBuf[iBuf].m_rgProp[i].m_iParam;
if (!DupArray (m_rgRWBuf[iCur].m_rgProp[i].m_rgUse,
(ULONG)cUse, m_rgContBuf[iBuf].m_rgUse))
return FALSE;
if (!DupArray (m_rgRWBuf[iCur].m_rgProp[i].m_rgParam,
(ULONG)cParam, m_rgContBuf[iBuf].m_rgParam))
return FALSE;
}
else
{
cUse = m_rgContBuf[iBuf].m_rgProp[i].m_iUse -
m_rgContBuf[iBuf].m_rgProp[i-1].m_iUse;
cParam = m_rgContBuf[iBuf].m_rgProp[i].m_iParam -
m_rgContBuf[iBuf].m_rgProp[i-1].m_iParam;
if (!DupArray (m_rgRWBuf[iCur].m_rgProp[i].m_rgUse, (ULONG)cUse,
&m_rgContBuf[iBuf].m_rgUse[m_rgContBuf[iBuf].m_rgProp[i-1].m_iUse]))
return FALSE;
if (!DupArray (m_rgRWBuf[iCur].m_rgProp[i].m_rgParam, (ULONG)cParam,
&m_rgContBuf[iBuf].m_rgParam[m_rgContBuf[iBuf].m_rgProp[i-1].m_iParam]))
return FALSE;
}
}
// set the read/write flag in the file status
m_rgStat[m_rgRWBuf[iCur].m_iModHdr] = NCB_STATMOD_LOAD_WRITE;
// set the read only buffer to the oldest, so we can reuse
// it right away.
m_rgContBuf[iBuf].m_prio = NCB_MOD_BUF_SIZE;
*piBuf = iCur;
return TRUE;
};
/////////////////////////////////////////////////////////////////
// CmpIProp ()
// used by qsort to compare two NCB_PROP
////////////////////////////////////////////////////////////////
int CmpIProp (const void * p1, const void * p2)
{
NCB_PROP * prop1 = (NCB_PROP *)p1;
NCB_PROP * prop2 = (NCB_PROP *)p2;
if (prop1->m_en.m_ni < prop2->m_en.m_ni)
return -1;
else if (prop1->m_en.m_ni == prop2->m_en.m_ni)
return 0;
return 1;
}
/////////////////////////////////////////////////////////////////
// CmpStr (SZ, SZ)
// compare two strings
// think of sz1 and sz2 being in a list of things that are sorted
// case insensitively and then case sensitively within that. This is
// the case for browser symbols
//
// return -1, 0, or 1 if sz1 before, at, or after sz2 in the list
/////////////////////////////////////////////////////////////////
int CmpStr (SZ_CONST sz1, SZ_CONST sz2)
{
return _tcscmp (sz1, sz2);
}
/////////////////////////////////////////////////////////////////
// CmpStrFrIProp ( const void * p1, const void *p2)
/////////////////////////////////////////////////////////////////
int CmpStrFrIProp (const void * p1, const void *p2)
{
NCB_PROP * prop1 = (NCB_PROP *)p1;
NCB_PROP * prop2 = (NCB_PROP *)p2;
SZ sz1 = szFrNi (Ncb::m_pnmStatic, prop1->m_en.m_ni);
SZ sz2 = szFrNi (Ncb::m_pnmStatic, prop2->m_en.m_ni);
return CmpStr (sz1, sz2);
}
/////////////////////////////////////////////////////////////////
// LoadFrWriteToRead ()
// Convert from read/write format to read-only format
// Invalid information in the R/W format will be deleted
// before writing to the read-only format.
// After writing it out to read format, it should
// also update the cache in the header.
// WARNING: at this time IINSTs are changing since we need
// to sort the NIs and put all the classes in the beginning
// of the IPROP, so any other
// component storing IINSTs must be notified
/////////////////////////////////////////////////////////////////
BOOL Ncb::LoadFrWriteToRead (USHORT iBuf, OUT USHORT * piBuf)
{
unsigned i;
USHORT iOldest = 0;
USHORT iModHdr = m_rgRWBuf[iBuf].m_iModHdr;
BYTE index;
_ASSERT (iModHdr < m_rgModHdr.size());
// check if it is already loaded for read or not
index = 0;
for (i = 0; i < NCB_MOD_BUF_SIZE; i++)
{
if (m_rgContBuf[i].m_iModHdr == iModHdr)
break;
index++;
}
if (index == NCB_MOD_BUF_SIZE) // it is not loaded for read yet
{
// update the priority ordering of the buffer and
// find the 'oldest' one.
// 0 - newest
// NCB_MOD_BUF_SIZE - oldest
iOldest = m_iReadLock == 0 ? 1 : 0;
for (i = iOldest ;i < NCB_MOD_BUF_SIZE; i++)
{
m_rgContBuf[i].m_prio++;
if (m_rgContBuf[i].m_prio >= m_rgContBuf[iOldest].m_prio &&
m_iReadLock != i)
iOldest = i;
}
}
else
iOldest = index;
_ASSERT (iOldest < NCB_MOD_BUF_SIZE);
if (m_rgContBuf[iOldest].m_iModHdr != (USHORT)-1 &&
m_rgStat[m_rgContBuf[iOldest].m_iModHdr] == NCB_STATMOD_LOAD_READ)
m_rgStat[m_rgContBuf[iOldest].m_iModHdr] = NCB_STATMOD_UNLOADED;
m_rgContBuf[iOldest].m_iModHdr = (USHORT)-1;
// delete the old information from the buffer
delete [] m_rgContBuf[iOldest].m_rgProp;
delete [] m_rgContBuf[iOldest].m_rgUse;
delete [] m_rgContBuf[iOldest].m_rgParam;
m_rgContBuf[iOldest].m_rgProp = NULL;
m_rgContBuf[iOldest].m_rgUse = NULL;
m_rgContBuf[iOldest].m_rgParam = NULL;
// allocate space for the module content:
NCB_PROP * rgProp = NULL;
USHORT * rgMap = NULL; // used to map from old iprop to new iprop
NCB_USE * rgUse = NULL;
NI * rgParam = NULL;
USHORT cArr = m_rgRWBuf[iBuf].m_rgProp.size();
USHORT cClass = 0;
USHORT cCurUse = 0, cCurParam = 0;
USHORT cParam =0, cUse = 0;
USHORT cProp = 0;
unsigned j;
// 0th step) find out if the entry has been deleted (also follow
// the m_rgUse array.
for (i = 0; i< cArr; i++)
{
// deleted item is represented by m_typ == 0xff
// there should not be an index to lower number, so one iteration is fine
if (m_rgRWBuf[iBuf].m_rgProp[i].m_en.m_typ == (BYTE)-1)
{
for (j = 0; j < m_rgRWBuf[iBuf].m_rgProp[i].m_rgUse.size(); j++)
{
_ASSERT (m_rgRWBuf[iBuf].m_rgProp[i].m_rgUse[j].m_iProp > i);
m_rgRWBuf[iBuf].m_rgProp[m_rgRWBuf[iBuf].m_rgProp[i].m_rgUse[j].m_iProp].m_en.m_typ = (BYTE)-1;
}
}
else
cProp++;
}
// there is something in the write buffer:
if (cProp != 0)
{
rgProp = new NCB_PROP[cProp];
rgMap = new USHORT[cArr];
if (rgProp == NULL ||
rgMap == NULL)
goto fail;
// 1st step) copy out the ENTITY to the new array
// and separate into two groups (ie: Class group and then
// non class group)
//
i = 0;
j = cArr - 1;
BOOL bStop = FALSE;
USHORT iCLoc; // current location for class
USHORT iNCLoc; // current location for non-class
iCLoc = 0;
iNCLoc = cProp - 1;
NI nimax;
while (iCLoc <= iNCLoc && i <= j && !bStop)
{
// going downward, stop when we find a non-class type or
// pass 'j'
while ((m_rgRWBuf[iBuf].m_rgProp[i].m_en.m_typ == INST_TYP_CLASSNAM ||
m_rgRWBuf[iBuf].m_rgProp[i].m_en.m_typ == (BYTE)-1)&&
iCLoc < iNCLoc && i < j)
{
if (m_rgRWBuf[iBuf].m_rgProp[i].m_en.m_typ == INST_TYP_CLASSNAM)
{
rgProp[iCLoc].m_en = m_rgRWBuf[iBuf].m_rgProp[i].m_en;
rgProp[iCLoc].m_lnStart = m_rgRWBuf[iBuf].m_rgProp[i].m_lnStart;
rgProp[iCLoc].m_iUse = i; // temporarily used for storing the mapping
iCLoc++; // between the old & new index, since
// we need this to fix the m_iUse array.
}
i++;
}
// going upward, stop when we find a class type or pass 'i'
while (m_rgRWBuf[iBuf].m_rgProp[j].m_en.m_typ != INST_TYP_CLASSNAM &&
i < j &&
iCLoc < iNCLoc)
{
if (m_rgRWBuf[iBuf].m_rgProp[j].m_en.m_typ != (BYTE)-1)
{
rgProp[iNCLoc].m_en = m_rgRWBuf[iBuf].m_rgProp[j].m_en;
rgProp[iNCLoc].m_lnStart = m_rgRWBuf[iBuf].m_rgProp[j].m_lnStart;
rgProp[iNCLoc].m_iUse = j;
iNCLoc--;
}
j--;
}
// swap this info:
if (iCLoc <= iNCLoc)
{
rgProp[iCLoc].m_en = m_rgRWBuf[iBuf].m_rgProp[j].m_en;
rgProp[iCLoc].m_lnStart = m_rgRWBuf[iBuf].m_rgProp[j].m_lnStart;
rgProp[iCLoc].m_iUse = j;
if (iCLoc < iNCLoc)
{
rgProp[iNCLoc].m_en = m_rgRWBuf[iBuf].m_rgProp[i].m_en;
rgProp[iNCLoc].m_lnStart = m_rgRWBuf[iBuf].m_rgProp[i].m_lnStart;
rgProp[iNCLoc].m_iUse = i;
iCLoc++; iNCLoc--;
i++; j--;
}
else
{
if (m_rgRWBuf[iBuf].m_rgProp[j].m_en.m_typ == INST_TYP_CLASSNAM)
iCLoc++;
bStop = TRUE;
}
}
}
cClass = iCLoc; // the number of classProp
// 2nd step) do a quicksort on both arrays:
// array of classes
m_pnmStatic = m_pnm;
qsort (rgProp, cClass, sizeof (NCB_PROP), CmpStrFrIProp);
// array of non classes
qsort (&rgProp[cClass], cProp - cClass, sizeof (NCB_PROP), CmpStrFrIProp);
// now setup a map from old iprop to new iprop:
for (i = 0; i < cProp; i++)
rgMap[rgProp[i].m_iUse] = (USHORT)i;
// 3rd step) fix up the IPROP in the NCB_USE:
// also get the size of NI (for param) and NCB_USE arrays:
cParam = 0;
cUse = 0;
for (i = 0 ; i < cArr; i++)
{
if (m_rgRWBuf[iBuf].m_rgProp[i].m_en.m_typ != (BYTE)-1)
{
cCurUse = m_rgRWBuf[iBuf].m_rgProp[i].m_rgUse.size();
for (j = 0; j < cCurUse; j++)
{
m_rgRWBuf[iBuf].m_rgProp[i].m_rgUse[j].m_iProp =
rgMap[m_rgRWBuf[iBuf].m_rgProp[i].m_rgUse[j].m_iProp];
}
cCurParam = m_rgRWBuf[iBuf].m_rgProp[i].m_rgParam.size();
cUse += cCurUse;
cParam += cCurParam;
}
}
// allocate array for NCB_PARAM and NCB_USE
rgParam = new NI[cParam];
rgUse = new NCB_USE[cUse];
if ((rgParam == NULL && cParam != 0)||
(rgUse == NULL && cUse != 0))
goto fail;
cUse = 0;
cParam = 0;
nimax = 0;
// copy the Param and Use array to the new place:
for (i = 0; i < cProp; i++)
{
_ASSERT (m_rgRWBuf[iBuf].m_rgProp[rgProp[i].m_iUse].m_en.m_typ != (BYTE)-1);
cCurUse = m_rgRWBuf[iBuf].m_rgProp[rgProp[i].m_iUse].m_rgUse.size();
cCurParam = m_rgRWBuf[iBuf].m_rgProp[rgProp[i].m_iUse].m_rgParam.size();
if (cCurUse > 0)
memcpy (&rgUse[cUse], &m_rgRWBuf[iBuf].m_rgProp[rgProp[i].m_iUse].m_rgUse[0],
cCurUse * sizeof (NCB_USE));
if (cCurParam > 0)
memcpy (&rgParam[cParam], &m_rgRWBuf[iBuf].m_rgProp[rgProp[i].m_iUse].m_rgParam[0],
cCurParam * sizeof (NI));
cUse += cCurUse;
cParam += cCurParam;
rgProp[i].m_iUse = cUse;
rgProp[i].m_iParam = cParam;
// find the max ni
if (nimax < rgProp[i].m_en.m_ni)
nimax = rgProp[i].m_en.m_ni;
}
m_rgModHdr[iModHdr].m_niMax = nimax;
}
// set headers:
int iByte;
BYTE bMask;
m_rgModHdr[iModHdr].m_cProp = cProp;
m_rgModHdr[iModHdr].m_cClassProp = cClass;
m_rgModHdr[iModHdr].m_cUse = cUse;
m_rgModHdr[iModHdr].m_cParam = cParam;
// clear cache:
for (i=0; i< CB_BITS_NI; i++)
m_rgModHdr[iModHdr].m_bitsNi[i] = 0;
// set new cache:
for (i = 0; i < cProp; i++)
{
MaskFrNi (rgProp[i].m_en.m_ni, m_rgModHdr[iModHdr].m_niMax, CB_BITS_NI, &iByte, &bMask);
m_rgModHdr[iModHdr].m_bitsNi[iByte] |= bMask;
}
// set the buffer:
if (cProp > 0)
m_rgContBuf[iOldest].m_rgProp = rgProp;
if (cUse > 0)
m_rgContBuf[iOldest].m_rgUse = rgUse;
if (cParam > 0)
m_rgContBuf[iOldest].m_rgParam = rgParam;
m_rgContBuf[iOldest].m_iModHdr = iModHdr;
m_rgContBuf[iOldest].m_prio = 0;
m_rgStat[iModHdr] = NCB_STATMOD_LOAD_READ;
// finally delete write information:
m_rgRWBuf.deleteAt(iBuf);
delete []rgMap;
*piBuf = iOldest;
return TRUE;
fail:
delete []rgProp;
delete []rgMap;
delete []rgParam;
delete []rgUse;
return FALSE;
};
/////////////////////////////////////////////////////////
// Ncb::FindWriteIndex()
// find the corresponding write index module in
// R/W buffer array.
/////////////////////////////////////////////////////////
BOOL Ncb::FindWriteIndex (USHORT iModHdr, OUT USHORT *pindex)
{
USHORT index = 0;
while (index < m_rgRWBuf.size())
{
if (m_rgRWBuf[index].m_iModHdr == iModHdr)
break;
index++;
}
if (index < m_rgRWBuf.size())
{
*pindex = index;
return TRUE;
}
return FALSE;
};
////////////////////////////////////////////////////////
// OpenNcb
////////////////////////////////////////////////////////
BOOL Ncb::OpenNcb (SZ szName, BOOL bOverwrite, Ncb ** ppNcb)
{
USHORT i;
BOOL bFound = FALSE;
Ncb * pNcb;
i = 0;
USHORT cSize;
while (i < ms_prgNcbInfo->size() && !bFound)
{
if (_tcsicmp (szName, (*ms_prgNcbInfo)[i].m_szName) == 0)
{
bFound = TRUE;
break;
}
i++;
}
if (bFound)
{
*ppNcb = (*ms_prgNcbInfo)[i].m_pNcb;
(*ms_prgNcbInfo)[i].m_count++;
return TRUE;
}
else
{
EC ec;
char szError[cbErrMax];
PDB *pdb;
if (!PDB::Open(szName, "w", (SIG)0, &ec, szError, &pdb)) {
// 1st try is unsuccessful, so try to delete it and recreate it:
if (!bOverwrite)
return FALSE;
if (_unlink (szName) == -1)
return FALSE;
if (!PDB::Open (szName, "w", (SIG)0, &ec, szError, &pdb))
return FALSE;
}
pNcb = new Ncb;
if (!pNcb || !pNcb->init (pdb))
return FALSE;
cSize = ms_prgNcbInfo->size();
if (!ms_prgNcbInfo->setSize(cSize+1))
{
delete pNcb;
return FALSE;
}
(*ms_prgNcbInfo)[cSize].m_pNcb = pNcb;
_tcscpy ((*ms_prgNcbInfo)[cSize].m_szName, szName);
(*ms_prgNcbInfo)[cSize].m_pPdb = pdb;
(*ms_prgNcbInfo)[cSize].m_count = 1;
(*ms_prgNcbInfo)[cSize].m_bIOwnPdb = TRUE;
*ppNcb = pNcb;
}
return TRUE;
};
////////////////////////////////////////////////////////
// OpenNcb
////////////////////////////////////////////////////////
BOOL Ncb::OpenNcb (PDB * ppdb, Ncb ** ppNcb)
{
USHORT i;
BOOL bFound = FALSE;
Ncb * pNcb;
i = 0;
USHORT cSize;
while (i < ms_prgNcbInfo->size() && !bFound)
{
if ((*ms_prgNcbInfo)[i].m_pPdb == ppdb)
{
bFound = TRUE;
break;
}
i++;
}
if (bFound)
{
*ppNcb = (*ms_prgNcbInfo)[i].m_pNcb;
(*ms_prgNcbInfo)[i].m_count++;
return TRUE;
}
else
{
pNcb = new Ncb;
if (!pNcb || !pNcb->init (ppdb))
return FALSE;
cSize = ms_prgNcbInfo->size();
if (!ms_prgNcbInfo->setSize(cSize+1))
{
delete pNcb;
return FALSE;
}
(*ms_prgNcbInfo)[cSize].m_pNcb = pNcb;
(*ms_prgNcbInfo)[cSize].m_szName[0] = 0;
(*ms_prgNcbInfo)[cSize].m_pPdb = ppdb;
(*ms_prgNcbInfo)[cSize].m_count = 1;
(*ms_prgNcbInfo)[cSize].m_bIOwnPdb = FALSE;
*ppNcb = pNcb;
}
return TRUE;
};
////////////////////////////////////////////////////////
// EnumNi()
////////////////////////////////////////////////////////
EnumNi::EnumNi (HTARGET hTarget, NI ni, Ncb * pncb)
{
m_ni = ni;
m_sz = NULL;
m_pncb = pncb;
m_BufType = NCB_STATMOD_LOAD_READ; // start with the read buffer:
m_iModHdr = (USHORT)-1;
m_i = 0;
m_rgProp = NULL;
m_cProp = 0;
m_index = (USHORT)-1;
m_hTarget = hTarget;
};
EnumNi::EnumNi (HTARGET hTarget, SZ sz, Ncb * pncb)
{
m_ni = (NI)-1;
m_sz = sz;
m_pncb = pncb;
m_BufType = NCB_STATMOD_LOAD_READ;
m_iModHdr = (USHORT)-1;
m_i = 0;
m_rgProp = NULL;
m_cProp = 0;
m_index = (USHORT)-1;
m_hTarget = hTarget;
};
////////////////////////////////////////////////////////
// ~EnumNi()
////////////////////////////////////////////////////////
EnumNi::~EnumNi()
{
m_pncb->disposeArray(m_rgProp);
};
////////////////////////////////////////////////////////
// GetNext()
////////////////////////////////////////////////////////
BOOL EnumNi::GetNext()
{
int ib;
BYTE bMask;
// start searching the Read Buffer:
if (m_BufType == NCB_STATMOD_LOAD_READ)
{
if (m_i < m_cProp)
{
m_iProp = m_rgProp[m_i];
m_i++;
return TRUE;
}
// increment m_index
if (m_index == (USHORT)-1)
m_index = 0;
else
m_index++;
// checking the read buffer:
while (m_index < NCB_MOD_BUF_SIZE)
{
m_iModHdr = m_pncb->m_rgContBuf[m_index].m_iModHdr;
if ((m_hTarget != (HTARGET)-1) && !m_pncb->isModInTarget (m_hTarget, m_iModHdr))
{
m_index++;
continue;
}
if (!(m_pncb->m_rgStat[m_iModHdr] & NCB_STATMOD_LOAD_READ))
{
m_index++;
continue;
}
// get the byte index and byte mask for a particular ni
// given the max ni in the module:
if (m_ni != (NI)-1)
{
MaskFrNi (m_ni, m_pncb->m_rgModHdr[m_iModHdr].m_niMax, CB_BITS_NI, &ib, &bMask);
if (!(m_pncb->m_rgModHdr[m_iModHdr].m_bitsNi[ib] & bMask))
{
m_index++;
continue;
}
// if there is a match:
m_pncb->disposeArray(m_rgProp);
m_rgProp = NULL;
m_pncb->GetIPropFrMod (m_ni, m_iModHdr, &m_index, &m_rgProp, &m_cProp);
}
else
{
m_pncb->disposeArray(m_rgProp);
m_rgProp = NULL;
m_pncb->GetIPropFrMod (m_sz, m_iModHdr, &m_index, &m_rgProp, &m_cProp);
}
if (!m_cProp)
{
m_index++;
continue;
}
else
{
m_iProp = m_rgProp[0];
m_i = 1;
return TRUE;
}
}
// if nothing in the read buffer:
m_BufType = NCB_STATMOD_LOAD_WRITE;
m_i = (USHORT)-1;
m_index = 0;
}
// now checking the write module
if (m_BufType == NCB_STATMOD_LOAD_WRITE)
{
while (m_index < m_pncb->m_rgRWBuf.size())
{
m_iModHdr = m_pncb->m_rgRWBuf[m_index].m_iModHdr;
if ((m_hTarget != (HTARGET)-1) && !m_pncb->isModInTarget (m_hTarget, m_iModHdr))
{
m_index++;
m_i = (USHORT)-1;
continue;
}
if (!(m_pncb->m_rgStat[m_iModHdr] & NCB_STATMOD_LOAD_WRITE))
{
m_index++;
m_i = (USHORT)-1;
continue;
}
if (m_i == (USHORT)-1)
m_i = 0;
else
m_i++;
while (m_i < m_pncb->m_rgRWBuf[m_index].m_rgProp.size())
{
if (m_ni != (NI)-1)
{
if (m_pncb->m_rgRWBuf[m_index].m_rgProp[m_i].m_en.m_ni == m_ni)
{
m_iProp = m_i;
return TRUE;
}
}
else
{
if (_tcscmp (szFrNi (m_pncb->m_pnm, m_pncb->m_rgRWBuf[m_index].m_rgProp[m_i].m_en.m_ni), m_sz) == 0)
{
m_iProp = m_i;
return TRUE;
}
}
m_i++;
}
m_index++;
m_i = (USHORT)-1;
}
m_BufType = NCB_STATMOD_UNLOADED;
m_cProp = 0;
m_iModHdr = (USHORT)-1;
}
// now check the unloaded module:
if (m_BufType == NCB_STATMOD_UNLOADED)
{
if (m_i < m_cProp)
{
m_iProp = m_rgProp[m_i];
m_i++;
return TRUE;
}
if (m_iModHdr == (USHORT)-1)
m_iModHdr = 0;
else
m_iModHdr++;
while (m_iModHdr < m_pncb->m_rgModHdr.size())
{
// skip if it is loaded since we have
// check this already:
if (!(m_pncb->m_rgStat[m_iModHdr] & NCB_STATMOD_UNLOADED))
{
m_iModHdr++;
continue;
}
if ((m_hTarget != (HTARGET)-1) && !m_pncb->isModInTarget (m_hTarget, m_iModHdr))
{
m_iModHdr++;
continue;
}
if (m_ni != (NI)-1)
{
MaskFrNi (m_ni, m_pncb->m_rgModHdr[m_iModHdr].m_niMax, CB_BITS_NI, &ib, &bMask);
if (!(m_pncb->m_rgModHdr[m_iModHdr].m_bitsNi[ib] & bMask))
{
m_iModHdr++;
continue;
}
m_index = NCB_MOD_BUF_SIZE;
m_pncb->disposeArray (m_rgProp);
m_rgProp = NULL;
m_pncb->GetIPropFrMod (m_ni, m_iModHdr, &m_index, &m_rgProp, &m_cProp);
}
else
{
m_index = NCB_MOD_BUF_SIZE;
m_pncb->disposeArray (m_rgProp);
m_rgProp = NULL;
m_pncb->GetIPropFrMod (m_sz, m_iModHdr, &m_index, &m_rgProp, &m_cProp);
}
if (!m_cProp)
{
m_iModHdr++;
continue;
}
else
{
m_iProp = m_rgProp[0];
m_i = 1;
return TRUE;
}
}
}
return FALSE;
};
////////////////////////////////////////////////////////
// SkipNi()
////////////////////////////////////////////////////////
void EnumNi::SkipNi()
{
if (m_BufType != NCB_STATMOD_LOAD_WRITE)
m_i = (USHORT) m_cProp;
else
m_i = m_pncb->m_rgRWBuf[m_index].m_rgProp.size();
};
//////////////////////////////////////////////////////
// OpenNcb(SZ szName, Bsc ** ppBsc)
//////////////////////////////////////////////////////
PDBAPI (BOOL) OpenNcb (SZ szName, HTARGET hTarget, SZ szTarget, BOOL bOverwrite, Bsc ** ppBsc)
{
Ncb * pNcb;
NcbWrap * pNcbWrap;
if (!Ncb::OpenNcb(szName, bOverwrite, &pNcb))
return FALSE;
_ASSERT (pNcb);
pNcbWrap = new NcbWrap;
if (!pNcbWrap)
return FALSE;
if (!pNcb->mapTargetToSz (hTarget, szTarget))
pNcb->mapSzToTarget (szTarget, hTarget);
pNcbWrap->init (hTarget, pNcb);
*ppBsc = (Bsc *)pNcbWrap;
return TRUE;
};
////////////////////////////////////////////////////////////////////////////
PDBAPI (BOOL) OpenNcb (PDB * ppdb, HTARGET hTarget, SZ szTarget, Bsc **ppBsc)
{
Ncb * pNcb;
NcbWrap * pNcbWrap;
if (!Ncb::OpenNcb(ppdb, &pNcb))
return FALSE;
_ASSERT (pNcb);
pNcbWrap = new NcbWrap;
if (!pNcbWrap)
return FALSE;
if (!pNcb->mapTargetToSz (hTarget, szTarget))
pNcb->mapSzToTarget (szTarget, hTarget);
pNcbWrap->init (hTarget, pNcb);
*ppBsc = (Bsc *)pNcbWrap;
return TRUE;
};
///////////////////////////////////////////////////////
PDBAPI (BOOL) OpenNcb (SZ szName, BOOL bOverwrite, NcbParse ** ppNcParse)
{
Ncb * pNcb;
if (!Ncb::OpenNcb (szName, bOverwrite, &pNcb))
return FALSE;
_ASSERT (pNcb);
*ppNcParse = (NcbParse *)pNcb;
return TRUE;
};
////////////////////////////////////////////////////////
PDBAPI (BOOL) OpenNcb (PDB * ppdb, NcbParse ** ppNcParse)
{
Ncb * pNcb;
if (!Ncb::OpenNcb (ppdb, &pNcb))
return FALSE;
_ASSERT (pNcb);
*ppNcParse = (NcbParse *)pNcb;
return TRUE;
};