int main() { char szError[cbErrMax]; EC ec; PDB* ppdb = PDB::Open("001.PDB", pdbWrite, 0, &ec, szError); assert(ppdb); DBI* pdbi = ppdb->OpenDBI(pdbWrite, "<target>"); assert(pdbi); TS ts = pdbi->OpenTpi(pdbWrite); assert(ts); struct { unsigned short len; unsigned short leaf; unsigned long signature; unsigned long age; unsigned char name[9]; } typeUseTypeServer = { 20, LF_TYPESERVER, 123456789, 1, "\x07""002.PDB" }; struct { unsigned short reclen; unsigned short rectyp; CV_uoff32_t off; unsigned short seg; CV_typ_t typind; unsigned char name[5]; } aSymbol = { 16, S_GDATA32, 0, 0, 0, "\x03""ABC" }; Mod* pmod = pdbi->OpenMod(ts, 1, "<mod>"); assert(pmod->AddTypes((PB)&typeUseTypeServer, 20)); for (TI ti = 0x1000; ti < 0x12e0; ti++) { aSymbol.typind = ti; assert(pmod->AddSymbols((PB)&aSymbol, 16)); } pmod->Commit(); pmod->Close(); ts->Commit(); ts->Close(); ppdb->Commit(); pdbi->Close(); ppdb->Commit(); ppdb->Close(); return 0; }
// Open the TypeServer referenced by *pts and initialize a TMTS from it. // Set *ptm and return TRUE if successful, FALSE otherwise. // BOOL DBI1::fOpenTmts(lfTypeServer* pts, SZ_CONST szObjFile, TM** pptm) { #pragma message("TODO - DBCS") *pptm = 0; // 0 means use 'to' PDB char szPDBTo[_MAX_PATH]; ppdb1->QueryPDBName(szPDBTo); if (_strnicmp(szPDBTo, (char*)(pts->name + 1), *(PB)pts->name) == 0) { // PDB filenames match, reference to the 'to' PDB return TRUE; } char szPDBFrom[_MAX_PATH]; strncpy(szPDBFrom, (char*)(pts->name + 1), *(PB)pts->name); szPDBFrom[*(PB)pts->name] = 0; if (pts->signature == ppdb1->QuerySignature() && pts->age <= ppdb1->QueryAge()) { // PDB signature and age match; this 'from' PDB must contain equivalent // information (even if it is a copy on some other path). However, we // may have the highly unlikely case of distinct PDBs with equal // signatures; to feel better about this case, we won't conclude // equivalence unless the PDB base names also match. In practice this // should be exactly conservative enough to avoid false positives and // yet prevent accidental reopening of the 'to' PDB. #pragma message("TODO: DBCS review") char* pchBaseFrom = strrchr(szPDBFrom, '\\'); // REVIEW: international? char* pchBaseTo = strrchr(szPDBTo, '\\'); if (_tcsicmp(pchBaseFrom, pchBaseTo) == 0) { // even the base names match; reference to the 'to' PDB return TRUE; } } // Alas, probably a reference to a different type server. Open it. EC ec; char szError[cbErrMax]; PDB* ppdbFrom; char szPathBuf[_MAX_PATH+_MAX_DRIVE]; char szFullPath[_MAX_PATH+_MAX_DRIVE]; _fullpath(szFullPath, szObjFile, _MAX_PATH+_MAX_DRIVE); _splitpath(szFullPath, szPathBuf, szPathBuf + _MAX_DRIVE, NULL, NULL); SZ szPath; if (szPathBuf[0] == 0) { // no drive spec - set up path without it szPath = szPathBuf + _MAX_DRIVE; } else { // concatenate drive and dir to form full path szPathBuf[2] = szPathBuf[1]; szPathBuf[1] = szPathBuf[0]; szPath = szPathBuf + 1; } if (!PDB::OpenValidate(szPDBFrom, szPath, ppdb1->fFullBuild ? (pdbRead pdbGetRecordsOnly pdbFullBuild) :(pdbRead pdbGetRecordsOnly), pts->signature, pts->age, &ec, szError, &ppdbFrom)) { ppdb1->setLastError(ec, szError); return FALSE; } // Check again that the PDB we found along the lib path is the same as the // target PDB. ppdbFrom->QueryPDBName(szPDBFrom); if (_tcsicmp(szPDBTo, szPDBFrom) == 0) { // PDB filenames match, reference to the 'to' PDB ppdbFrom->Close(); return TRUE; } // Create and initialize the TMTS. TMTS* ptmts = new TMTS(ppdb1, this, ppdb1->ptpi1); if (!ptmts) { ppdb1->setOOMError(); return FALSE; } if (!ptmts->fInit(ppdbFrom)) return FALSE; *pptm = ptmts; return TRUE; }