|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
JetWalk.cxx
Abstract:
Dumps a Jet database
Author:
Rajivendra Nath (RajNath) 18-Aug-1989
Revision History:
David Orbits (davidor) 6-March-1997 Revised for NTFRS database and major rework.
--*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <esent.h>
#define BUFFER_SIZE 1024
JET_ERR DbStats( JET_SESID jsesid, char * szDbName ); void TblStats( JET_SESID jsesid, JET_DBID jdbid, int iTable, char *szTblName, unsigned long *pcPages ); void DumpAttributes( JET_SESID jsesid, JET_COLUMNLIST colinfo ); void DumpIndex( JET_SESID jsesid, JET_INDEXLIST colinfo ); void DBDumpTable( JET_SESID jsesid,JET_TABLEID jtid, char* rgb); void DBDumpRecord( JET_SESID jsesid,JET_TABLEID jtid);
typedef char* SZ; typedef ULONG CCH;
typedef struct { char AttribName[64]; JET_COLUMNID colid; JET_COLTYP coltyp; JET_GRBIT grbit; BOOL Display;
}ATTRIBLIST;
typedef struct { char AttribName[64]; char key[256]; JET_COLUMNID colid; JET_COLTYP coltyp; JET_GRBIT grbit; BOOL Display;
}INDEXLIST;
DWORD List[1024]; ATTRIBLIST AList[1024]; DWORD AListUsed;
INDEXLIST IList[1024]; DWORD IListUsed; BOOL NeedShutdown = FALSE;
char *JetColumnTypeNames[] = { "coltypNil ", "coltypBit ", "coltypUnsignedByte", "coltypShort ", "coltypLong ", "coltypCurrency ", "coltypIEEESingle ", "coltypIEEEDouble ", "coltypDateTime ", "coltypBinary ", "coltypText ", "coltypLongBinary ", "coltypLongText ", "coltypMax "};
#define TIMECALL(CallX) \
{ \ DWORD start,end; \ start = GetTickCount(); \ CallX; \ end = GetTickCount(); \ printf("[%5d MilliSec] <<%s>> \n",end-start,#CallX);\ }
void ReadSzFromRegKey(SZ szKey, SZ szValue, SZ szBuf, CCH cchBuf) { HKEY hkey = NULL;
// User specified that we use the regular registry variables.
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { DWORD dwType; ULONG cb;
cb = cchBuf; if ((RegQueryValueEx(hkey, szValue, 0, &dwType, (LPBYTE) szBuf, &cb) == ERROR_SUCCESS) && cb > 0 && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) { return; } }
printf("Couldn't read value %s from registry key %s.", szValue, szKey); exit(1); }
BOOL fDumpRecords=FALSE; BOOL fDumpAll=FALSE; BOOL fDumpColId=FALSE;
ULONG _cdecl main( IN INT argc, IN PCHAR argv[] )
{ JET_ERR jerr; JET_INSTANCE jinstance; JET_SESID jsesid; char szBuffer[BUFFER_SIZE];
char * szUserName = "admin"; char * szPassword = "password";
int nTotalLen;
jerr = JetSetSystemParameter(&jinstance, 0, JET_paramRecovery, 0, "off");
if (jerr != JET_errSuccess) { printf( "jetwalk: JetSetSystemParameter returned %d\n", jerr ); return jerr; }
//
// Open JET session
//
TIMECALL(jerr = JetInit(&jinstance));
if (jerr != JET_errSuccess) { printf("JetInit error: %d\n", jerr); return jerr; }
//
// If we fail after here, our caller should go through full shutdown
// so JetTerm will be called to release any file locks
//
NeedShutdown = TRUE;
if ((jerr = JetBeginSession(jinstance, &jsesid, NULL, NULL)) != JET_errSuccess) { printf("JetBeginSession error: %d\n", jerr); return jerr; }
if (argc<2) { printf("Usage:%0 [/R] <JetDataBaseName>"); }
char* FileName="e:\\ntfrs.jdb"; for (int i=1;i<argc;i++) { if (argv[i][0]=='/') { switch(tolower(argv[i][1])) { case 'r': fDumpRecords= TRUE; if (isupper(argv[i][1])) fDumpAll=TRUE; break; case 'c': fDumpColId=TRUE;break; } } else { FileName=argv[i]; }
}
printf( "-------------------------------------\n" ); printf( "DATABASE: %s\n", FileName ); printf( "-------------------------------------\n" );
// Attach database
jerr = JetAttachDatabase(jsesid, FileName, 0); if (jerr == JET_errSuccess) {
// Dump the database
jerr = DbStats(jsesid, FileName);
jerr = JetDetachDatabase(jsesid, FileName ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetDetachDatabase returned %d\n", jerr ); }
} else { printf("jetwalk: JetAttachDatabase (%s) returned %d\n", FileName, jerr); }
TIMECALL(jerr = JetEndSession(jsesid, 0 )); if (jerr != JET_errSuccess) { printf( "jetwalk: JetEndSession returned %d\n", jerr ); }
jerr = JetTerm( jinstance ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetTerm returned %d\n", jerr ); }
return jerr; }
JET_ERR DbStats( JET_SESID jsesid, char * szDbName ) { JET_ERR jerr; JET_DBID jdbid; JET_OBJECTLIST jobjectlist; unsigned long iTable; unsigned long cTotalPages = 0; unsigned long cPages;
//
// Open database
//
jerr = JetOpenDatabase( jsesid, szDbName, "", &jdbid, JET_bitDbReadOnly ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetOpenDatabase returned %d\n", jerr ); goto CLOSEDB; }
jerr = JetGetObjectInfo( jsesid, jdbid, JET_objtypTable, NULL, NULL, &jobjectlist, sizeof(jobjectlist), JET_ObjInfoListNoStats );
if (jerr != JET_errSuccess) { printf( "jetwalk: JetGetObjectInfo returned %d\n", jerr ); goto CLOSEDB; }
printf( "Database contains %d tables\n", jobjectlist.cRecord );
iTable = 1; jerr = JetMove( jsesid, jobjectlist.tableid, JET_MoveFirst, 0 ); while( jerr == JET_errSuccess ) { unsigned long cb; unsigned char rgb[1024];
jerr = JetRetrieveColumn( jsesid, jobjectlist.tableid, jobjectlist.columnidobjectname, rgb, sizeof(rgb), &cb, 0, NULL );
if (jerr != JET_errSuccess) { printf( "jetwalk: JetMove returned %d\n", jerr ); goto CLOSEDB; } rgb[cb] = '\0';
TblStats( jsesid, jdbid, iTable++, (char *)rgb, &cPages );
if (fDumpRecords) { DBDumpTable(jsesid,jdbid,(char *)rgb); }
cTotalPages += cPages;
jerr = JetMove( jsesid, jobjectlist.tableid, JET_MoveNext, 0 ); }
if (jerr != JET_errNoCurrentRecord) { printf( "jetwalk: JetMove returned %d\n", jerr ); goto CLOSEDB; }
if ( iTable != jobjectlist.cRecord+1 ) { printf( "jetwalk: # of rows didn't match what JET said there were" ); goto CLOSEDB; }
printf( "Total pages owned in database = %d\n", cTotalPages );
CLOSEDB: jerr = JetCloseDatabase( jsesid, jdbid, 0 ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetCloseDatabase returned %d\n", jerr ); }
return jerr; }
void TblStats( JET_SESID jsesid, JET_DBID jdbid, int iTable, char *szTblName, unsigned long *pcPages ) { JET_ERR jerr; JET_TABLEID jtableid; JET_OBJECTINFO jobjectinfo; JET_COLUMNLIST jcolumnlist; JET_INDEXLIST jindexlist; unsigned char rgb[4096]; unsigned long *pul = (unsigned long *)rgb;
printf( "-------------------------------------\n" ); printf( "Table #%d: %s\n", iTable, szTblName ); printf( "-------------------------------------\n" );
jerr = JetOpenTable( jsesid, jdbid, szTblName, NULL, 0, JET_bitTableReadOnly, &jtableid ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetOpenTable returned %d\n", jerr ); goto CLOSE_TABLE; }
jerr = JetComputeStats( jsesid, jtableid ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetComputeStats returned %d\n", jerr ); //workaround goto CLOSE_TABLE;
}
jerr = JetGetTableInfo( jsesid, jtableid, &jobjectinfo, sizeof(jobjectinfo), JET_TblInfo ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetGetTableInfo returned %d\n", jerr ); goto CLOSE_TABLE; }
printf( "cRecord = %d\n", jobjectinfo.cRecord ); printf( "cPage = %d\n", jobjectinfo.cPage );
//
// bugbug - result seems wrong -- check the call.
//
jerr = JetGetTableInfo( jsesid, jtableid, rgb, sizeof(rgb), JET_TblInfoSpaceUsage ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetGetTableInfo returned %d\n", jerr ); goto CLOSE_TABLE; }
printf( "cTotalPagesOwned = %d\n", pul[0] ); printf( "cTotalPagesAvail = %d\n", pul[1] );
*pcPages = pul[0];
jerr = JetGetTableColumnInfo( jsesid, jtableid, NULL, &jcolumnlist, sizeof(jcolumnlist), JET_ColInfoList ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetGetTableColumnInfo returned %d\n", jerr ); goto CLOSE_TABLE; }
DumpAttributes( jsesid, jcolumnlist);
jerr = JetCloseTable( jsesid, jcolumnlist.tableid ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetCloseTable returned %d\n", jerr ); goto CLOSE_TABLE; }
jerr = JetGetTableIndexInfo( jsesid, jtableid, NULL, &jindexlist, sizeof(jindexlist), JET_IdxInfoList ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetGetTableIndexInfo returned %d\n", jerr ); goto CLOSE_TABLE; }
DumpIndex( jsesid, jindexlist);
jerr = JetCloseTable( jsesid, jindexlist.tableid ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetCloseTable returned %d\n", jerr ); goto CLOSE_TABLE; }
CLOSE_TABLE:
jerr = JetCloseTable( jsesid, jtableid ); if (jerr != JET_errSuccess) { printf( "jetwalk: JetCloseTable returned %d\n", jerr ); } }
void DumpIndex( JET_SESID jsesid, JET_INDEXLIST colinfo ) { JET_ERR jerr; unsigned long iRecord; JET_RETRIEVECOLUMN rcarray[5]; DWORD i=0;
/*
typedef struct { unsigned long cbStruct; JET_TABLEID tableid; unsigned long cRecord; JET_COLUMNID columnidPresentationOrder; JET_COLUMNID columnidcolumnname; JET_COLUMNID columnidcolumnid; JET_COLUMNID columnidcoltyp; JET_COLUMNID columnidCountry; JET_COLUMNID columnidLangid; JET_COLUMNID columnidCp; JET_COLUMNID columnidCollate; JET_COLUMNID columnidcbMax; JET_COLUMNID columnidgrbit; JET_COLUMNID columnidDefault; JET_COLUMNID columnidBaseTableName; JET_COLUMNID columnidBaseColumnName; JET_COLUMNID columnidDefinitionName; } JET_COLUMNLIST;
*/
/*
typedef struct { unsigned long cbStruct; JET_TABLEID tableid; unsigned long cRecord; JET_COLUMNID columnidindexname; JET_COLUMNID columnidgrbitIndex; JET_COLUMNID columnidcKey; JET_COLUMNID columnidcEntry; JET_COLUMNID columnidcPage; JET_COLUMNID columnidcColumn; JET_COLUMNID columnidiColumn; JET_COLUMNID columnidcolumnid; JET_COLUMNID columnidcoltyp; JET_COLUMNID columnidCountry; JET_COLUMNID columnidLangid; JET_COLUMNID columnidCp; JET_COLUMNID columnidCollate; JET_COLUMNID columnidgrbitColumn; JET_COLUMNID columnidcolumnname; } JET_INDEXLIST; */
printf("-------------------\n INDEXES \n-------------------\n");
jerr = JetMove( jsesid, colinfo.tableid, JET_MoveFirst, 0 );
IListUsed = 0; while( jerr == JET_errSuccess ) {
unsigned long cb;
ZeroMemory(rcarray, sizeof(rcarray));
rcarray[4].pvData = IList[IListUsed].AttribName; rcarray[4].cbData = sizeof(IList[0].AttribName); rcarray[4].columnid = colinfo.columnidindexname; rcarray[4].itagSequence = 1;
rcarray[1].pvData = &IList[IListUsed].colid; rcarray[1].cbData = sizeof(IList[0].colid); rcarray[1].columnid = colinfo.columnidcolumnid; rcarray[1].itagSequence = 1;
rcarray[2].pvData = &IList[IListUsed].coltyp; rcarray[2].cbData = sizeof(IList[0].coltyp); rcarray[2].columnid = colinfo.columnidcoltyp; rcarray[2].itagSequence = 1;
rcarray[3].pvData = &IList[IListUsed].grbit; rcarray[3].cbData = sizeof(IList[0].grbit); rcarray[3].columnid = colinfo.columnidgrbitIndex; rcarray[3].itagSequence = 1;
rcarray[0].pvData = &IList[IListUsed].key; rcarray[0].cbData = sizeof(IList[0].key); rcarray[0].columnid = colinfo.columnidcKey; rcarray[0].itagSequence = 1;
jerr = JetRetrieveColumns(jsesid, colinfo.tableid, rcarray, 5 );
jerr = JetMove( jsesid, colinfo.tableid, JET_MoveNext, 0 ); IListUsed++; }
for (i=0;i<IListUsed;i++) { printf("%25s %s %08x %3d\n", IList[i].AttribName, JetColumnTypeNames[IList[i].coltyp], IList[i].grbit, fDumpColId?IList[i].colid:0); } }
void DumpAttributes( JET_SESID jsesid, JET_COLUMNLIST colinfo ) { JET_ERR jerr; unsigned long iRecord; JET_RETRIEVECOLUMN rcarray[4]; DWORD i=0; unsigned long cb;
/*
typedef struct { unsigned long cbStruct; JET_TABLEID tableid; unsigned long cRecord; JET_COLUMNID columnidPresentationOrder; JET_COLUMNID columnidcolumnname; JET_COLUMNID columnidcolumnid; JET_COLUMNID columnidcoltyp; JET_COLUMNID columnidCountry; JET_COLUMNID columnidLangid; JET_COLUMNID columnidCp; JET_COLUMNID columnidCollate; JET_COLUMNID columnidcbMax; JET_COLUMNID columnidgrbit; JET_COLUMNID columnidDefault; JET_COLUMNID columnidBaseTableName; JET_COLUMNID columnidBaseColumnName; JET_COLUMNID columnidDefinitionName; } JET_COLUMNLIST;
*/
jerr = JetMove( jsesid, colinfo.tableid, JET_MoveFirst, 0 );
AListUsed = 0; while( jerr == JET_errSuccess ) {
ZeroMemory(rcarray, sizeof(rcarray));
rcarray[0].pvData = AList[AListUsed].AttribName; rcarray[0].cbData = sizeof(AList[0].AttribName); rcarray[0].columnid = colinfo.columnidcolumnname; rcarray[0].itagSequence = 1;
rcarray[1].pvData = &AList[AListUsed].colid; rcarray[1].cbData = sizeof(AList[0].colid); rcarray[1].columnid = colinfo.columnidcolumnid; rcarray[1].itagSequence = 1;
rcarray[2].pvData = &AList[AListUsed].coltyp; rcarray[2].cbData = sizeof(AList[0].coltyp); rcarray[2].columnid = colinfo.columnidcoltyp; rcarray[2].itagSequence = 1;
rcarray[3].pvData = &AList[AListUsed].grbit; rcarray[3].cbData = sizeof(AList[0].grbit); rcarray[3].columnid = colinfo.columnidgrbit; rcarray[3].itagSequence = 1;
jerr = JetRetrieveColumns(jsesid, colinfo.tableid, rcarray, 4);
jerr = JetMove( jsesid, colinfo.tableid, JET_MoveNext, 0 ); AListUsed++; }
int next=0; for (i=0;i<AListUsed;i++) { printf("%25s %s %08x %3d\n", AList[i].AttribName, JetColumnTypeNames[AList[i].coltyp], AList[i].grbit, fDumpColId?AList[i].colid:0);
List[next]=i; AList[i].Display=TRUE;
//
// If it's a favorite stick it out first in the record dump.
//
if (strcmp(AList[i].AttribName,"FileName")==0) { List[next] = List[0]; List[0] = i; } else if (strcmp(AList[i].AttribName,"VersionNumber")==0) { List[next] = List[1]; List[1]=i; } else if (strcmp(AList[i].AttribName,"FileGuid")==0) { List[next] = List[2]; List[2]=i; } else if (strcmp(AList[i].AttribName,"FileID")==0) { List[next] = List[3]; List[3]=i; } else if (strcmp(AList[i].AttribName,"EventTime")==0) { List[next] = List[4]; List[4]=i; } else if (strcmp(AList[i].AttribName,"FileWriteTime")==0) { List[next] = List[5]; List[5]=i; } else if (strcmp(AList[i].AttribName,"ParentGuid")==0) { List[next] = List[6]; List[6]=i; } else if (strcmp(AList[i].AttribName,"ParentFileID")==0) { List[next] = List[7]; List[7]=i; }
next += 1;
} }
void DBDumpTable( JET_SESID jsesid, JET_DBID jdbid, char * szTbName ) { JET_ERR jerr; JET_TABLEID jtid;
jerr = JetOpenTable(jsesid, jdbid, szTbName, NULL, 0, 0, &jtid); if (jerr != JET_errSuccess) { printf( "DBDumpTable: JetOpenTable returned %d\n", jerr ); goto CLOSE_TABLE; }
jerr = JetMove( jsesid, jtid, JET_MoveFirst, 0 );
while (!jerr) { DBDumpRecord( jsesid,jtid); jerr = JetMove( jsesid, jtid, JET_MoveNext, 0 ); }
CLOSE_TABLE:
jerr = JetCloseTable( jsesid, jtid ); if (jerr != JET_errSuccess) { printf( "DBDumpTable: JetCloseTable returned %d\n", jerr ); }
return; }
char* PVoidToStr( PVOID obuff, JET_COLTYP coltyp, DWORD cbActual ) { static char buff[512]; ULONG data; LONGLONG lidata;
ZeroMemory(buff,sizeof(buff));
switch (coltyp) {
case JET_coltypNil: sprintf(buff,"%s","NULL "); break;
case JET_coltypBit: data = (ULONG) *(PCHAR)obuff; sprintf(buff," %d ", data); break;
case JET_coltypUnsignedByte: sprintf(buff," %d ", *(DWORD*)obuff); break;
case JET_coltypShort: sprintf(buff," %d ", *(DWORD*)obuff); break;
case JET_coltypLong: sprintf(buff," %d ", *( DWORD *) obuff); break;
case JET_coltypCurrency: CopyMemory(&lidata, obuff, 8); sprintf(buff," %12Ld ", lidata); break;
case JET_coltypIEEESingle: sprintf(buff," %s ", "???"); break;
case JET_coltypIEEEDouble: sprintf(buff," %s ", "???"); break;
case JET_coltypDateTime: CopyMemory(&lidata, obuff, 8); sprintf(buff," %12Ld ", lidata); break;
case JET_coltypBinary: sprintf(buff," %s ", "???"); break;
case JET_coltypText: sprintf(buff," %*.*ws ",cbActual, cbActual, ( WCHAR *) obuff); //sprintf(buff," %25ws ", (WCHAR*)obuff);
break;
case JET_coltypLongBinary: sprintf(buff," %25ws ", "???"); break;
case JET_coltypLongText: sprintf(buff," %25ws ", (WCHAR*)obuff); break;
case JET_coltypMax: sprintf(buff," %s ", "???"); break;
default: sprintf(buff,"UNKNOWN %d ", coltyp); }
return buff; }
void DBDumpRecord( JET_SESID jsesid,JET_TABLEID jtid) { JET_RETINFO ri;
DWORD i; char obuff[2048]; JET_ERR jerr; DWORD cbActual; char recbuff[2048]; char* ptr=recbuff;
ZeroMemory(&ri,sizeof(ri));
for (i=0;i<AListUsed;i++) { if (!fDumpAll && !AList[List[i]].Display) { continue; }
jerr = JetRetrieveColumn ( jsesid, jtid, AList[List[i]].colid, obuff, sizeof(obuff), &cbActual, 0, NULL);
if (jerr != 0) { continue; }
ptr += sprintf(ptr,"%s = %s", AList[List[i]].AttribName, PVoidToStr(obuff,AList[List[i]].coltyp,cbActual)); }
*ptr='\0';
printf(">>%s\n",recbuff); }
|