|
|
/*++
Copyright (C) 1999 Microsoft Coporation
Module Name:
db2file.c
Abstract:
This module reads the database records and writes them into a file format.
--*/
#include <precomp.h>
enum { RecordTypeDbEntry, RecordTypeMcastDbEntry, };
//
// database table and field names.
//
#define IPADDRESS_INDEX 0
#define HARDWARE_ADDRESS_INDEX 1
#define STATE_INDEX 2
#define MACHINE_INFO_INDEX 3
#define MACHINE_NAME_INDEX 4
#define LEASE_TERMINATE_INDEX 5
#define SUBNET_MASK_INDEX 6
#define SERVER_IP_ADDRESS_INDEX 7
#define SERVER_NAME_INDEX 8
#define CLIENT_TYPE_INDEX 9
#define MAX_INDEX 10
#define SAVE_THRESHOLD (1000000L)
//
// Globals
//
DWORD JetVersion; CHAR DatabaseName[1024], DatabasePath[1024]; HMODULE hJet; JET_INSTANCE JetInstance; JET_SESID JetSession; JET_DBID JetDb; JET_TABLEID JetTbl; PUCHAR SaveBuf; ULONG SaveBufSize; HANDLE hTextFile, hMapping; PVOID FileView; WCHAR Winnt32Path[MAX_PATH*2]; CHAR System32Path[MAX_PATH*2];
JET_ERR (JET_API *pJetSetCurrentIndex)( JET_SESID sesid, JET_TABLEID tableid, const char *szIndexName ); JET_ERR (JET_API *pJetRetrieveColumn)( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, void *pvData, unsigned long cbData, unsigned long *pcbActual, JET_GRBIT grbit, JET_RETINFO *pretinfo );
JET_ERR (JET_API *pJetSetColumn)( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, const void *pvData, unsigned long cbData, JET_GRBIT grbit, JET_SETINFO *psetinfo );
JET_ERR (JET_API *pJetMove)( JET_SESID sesid, JET_TABLEID tableid, long cRow, JET_GRBIT grbit );
JET_ERR (JET_API *pJetSetSystemParameter)( JET_INSTANCE *pinstance, JET_SESID sesid, unsigned long paramid, ULONG_PTR lParam, const char *sz );
JET_ERR (JET_API *pJetBeginTransaction)( JET_SESID sesid ); JET_ERR (JET_API *pJetPrepareUpdate)( JET_SESID sesid, JET_TABLEID tableid, unsigned long prep );
JET_ERR (JET_API *pJetUpdate)( JET_SESID sesid, JET_TABLEID tableid, void *pvBookmark, unsigned long cbBookmark, unsigned long *pcbActual);
JET_ERR (JET_API *pJetCommitTransaction)( JET_SESID sesid, JET_GRBIT grbit );
JET_ERR (JET_API *pJetRollback)( JET_SESID sesid, JET_GRBIT grbit );
JET_ERR (JET_API *pJetTerm)( JET_INSTANCE instance );
JET_ERR (JET_API *pJetTerm2)( JET_INSTANCE instance, JET_GRBIT grbit );
JET_ERR (JET_API *pJetEndSession)( JET_SESID sesid, JET_GRBIT grbit );
JET_ERR (JET_API *pJetBeginSession)( JET_INSTANCE instance, JET_SESID *psesid, const char *szUserName, const char *szPassword );
JET_ERR (JET_API *pJetInit)( JET_INSTANCE *pinstance);
JET_ERR (JET_API *pJetDetachDatabase)( JET_SESID sesid, const char *szFilename );
JET_ERR (JET_API *pJetAttachDatabase)( JET_SESID sesid, const char *szFilename, JET_GRBIT grbit );
JET_ERR (JET_API *pJetOpenDatabase)( JET_SESID sesid, const char *szFilename, const char *szConnect, JET_DBID *pdbid, JET_GRBIT grbit );
JET_ERR (JET_API *pJetCloseDatabase)( JET_SESID sesid, JET_DBID dbid, JET_GRBIT grbit );
JET_ERR (JET_API *pJetOpenTable)( JET_SESID sesid, JET_DBID dbid, const char *szTableName, const void *pvParameters, unsigned long cbParameters, JET_GRBIT grbit, JET_TABLEID *ptableid );
JET_ERR (JET_API *pJetCloseTable)( JET_SESID sesid, JET_TABLEID tableid );
JET_ERR (JET_API *pJetGetTableColumnInfo)( JET_SESID sesid, JET_TABLEID tableid, const char *szColumnName, void *pvResult, unsigned long cbMax, unsigned long InfoLevel );
JET_ERR (JET_API *pJetGetIndexInfo)( JET_SESID sesid, JET_DBID dbid, const char *szTableName, const char *szIndexName, void *pvResult, unsigned long cbResult, unsigned long InfoLevel );
#define DB_FUNC(F,I,S) \
{#F, TEXT(#F), #F "@" #S, I, (FARPROC *)& p ## F }
typedef struct _DB_FUNC_ENTRY { LPSTR FuncName; LPWSTR FuncNameW; LPSTR AltName; DWORD Index; FARPROC *FuncPtr; } DB_FUNC_ENTRY;
DB_FUNC_ENTRY FuncTable[] = { DB_FUNC(JetSetCurrentIndex, 164, 12), DB_FUNC(JetRetrieveColumn, 157, 32), DB_FUNC(JetSetColumn, 162, 28), DB_FUNC(JetMove, 147, 16), DB_FUNC(JetSetSystemParameter, 165, 20), DB_FUNC(JetTerm, 167, 4), DB_FUNC(JetTerm2, 0, 8), DB_FUNC(JetEndSession, 124, 8), DB_FUNC(JetBeginSession, 104, 16), DB_FUNC(JetInit, 145, 4), DB_FUNC(JetDetachDatabase, 121, 8), DB_FUNC(JetAttachDatabase, 102, 12), DB_FUNC(JetOpenDatabase, 148, 20), DB_FUNC(JetOpenTable, 149, 28), DB_FUNC(JetGetTableColumnInfo, 137, 24), DB_FUNC(JetCloseTable,108, 8), DB_FUNC(JetCloseDatabase, 107, 12), DB_FUNC(JetGetIndexInfo, 131, 28), DB_FUNC(JetBeginTransaction, 105, 4), DB_FUNC(JetPrepareUpdate, 151, 12), DB_FUNC(JetUpdate, 168, 20), DB_FUNC(JetCommitTransaction, 109, 8), DB_FUNC(JetRollback, 160, 8), };
#define JetSetCurrentIndex pJetSetCurrentIndex
#define JetRetrieveColumn pJetRetrieveColumn
#define JetSetColumn pJetSetColumn
#define JetMove pJetMove
#define JetSetSystemParameter pJetSetSystemParameter
#define JetTerm pJetTerm
#define JetTerm2 pJetTerm2
#define JetEndSession pJetEndSession
#define JetBeginSession pJetBeginSession
#define JetInit pJetInit
#define JetDetachDatabase pJetDetachDatabase
#define JetAttachDatabase pJetAttachDatabase
#define JetOpenDatabase pJetOpenDatabase
#define JetOpenTable pJetOpenTable
#define JetGetTableColumnInfo pJetGetTableColumnInfo
#define JetCloseTable pJetCloseTable
#define JetCloseDatabase pJetCloseDatabase
#define JetGetIndexInfo pJetGetIndexInfo
#define JetBeginTransaction pJetBeginTransaction
#define JetPrepareUpdate pJetPrepareUpdate
#define JetUpdate pJetUpdate
#define JetCommitTransaction pJetCommitTransaction
#define JetRollback pJetRollback
typedef struct _TABLE_INFO { CHAR *ColName; JET_COLUMNID ColHandle; BOOL fPresent; JET_COLTYP ColType; } TABLE_INFO, *LPTABLE_INFO;
#define IPADDRESS_STRING "IpAddress"
#define HARDWARE_ADDRESS_STRING "HardwareAddress"
#define STATE_STRING "State"
#define MACHINE_INFO_STRING "MachineInformation"
#define MACHINE_NAME_STRING "MachineName"
#define LEASE_TERMINATE_STRING "LeaseTerminates"
#define SUBNET_MASK_STRING "SubnetMask"
#define SERVER_IP_ADDRESS_STRING "ServerIpAddress"
#define SERVER_NAME_STRING "ServerName"
#define CLIENT_TYPE "ClientType"
static TABLE_INFO ClientTable[] = { { IPADDRESS_STRING , 0, 1, JET_coltypLong }, { HARDWARE_ADDRESS_STRING , 0, 1, JET_coltypBinary }, { STATE_STRING , 0, 1, JET_coltypUnsignedByte }, { MACHINE_INFO_STRING , 0, 1, JET_coltypBinary }, // must modify MACHINE_INFO_SIZE if this changes
{ MACHINE_NAME_STRING , 0, 1, JET_coltypLongBinary }, { LEASE_TERMINATE_STRING , 0, 1, JET_coltypCurrency }, { SUBNET_MASK_STRING , 0, 1, JET_coltypLong }, { SERVER_IP_ADDRESS_STRING, 0, 1, JET_coltypLong }, { SERVER_NAME_STRING , 0, 1, JET_coltypLongBinary }, { CLIENT_TYPE , 0, 1, JET_coltypUnsignedByte } };
#define MAGIC_COOKIE_NT4 'NT4 '
#define MAGIC_COOKIE_NT5 'W2K '
#define MAGIC_COOKIE_NT5_PLUS 'W2K1'
DWORD GetCurrentMagicCookie( VOID ) { OSVERSIONINFO Ver;
Ver.dwOSVersionInfoSize = sizeof(Ver); if( FALSE == GetVersionEx(&Ver) ) return MAGIC_COOKIE_NT5_PLUS; if( Ver.dwMajorVersion == 4 ) return MAGIC_COOKIE_NT4; else if( Ver.dwMajorVersion == 5 ) { if( Ver.dwBuildNumber >= 2200 ) return MAGIC_COOKIE_NT5_PLUS; else return MAGIC_COOKIE_NT5; } return MAGIC_COOKIE_NT4; }
DWORD OpenTextFile( IN LPWSTR FileName, IN BOOL fRead, OUT HANDLE *hFile, OUT LPBYTE *Mem, OUT ULONG *MemSize ) { DWORD Error, Flags, LoSize, HiSize;
Flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
hTextFile = CreateFileW( FileName, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, fRead ? OPEN_EXISTING : CREATE_ALWAYS, Flags, NULL );
if( hTextFile == INVALID_HANDLE_VALUE ) { hTextFile = NULL; Error = GetLastError(); if( !fRead || ERROR_FILE_NOT_FOUND != Error ) { Tr("CreateFile<%ws>: %ld\n", FileName, Error ); } return Error; }
(*hFile) = hTextFile; if( !fRead ) { //
// Write the magic cookie
//
Flags = GetCurrentMagicCookie(); if( FALSE == WriteFile( hTextFile, (LPBYTE)&Flags, sizeof(Flags), &LoSize, NULL ) ) { Error = GetLastError(); CloseHandle(hTextFile); return Error; } return NO_ERROR; }
LoSize = GetFileSize( hTextFile, &HiSize ); if( -1 == LoSize && NO_ERROR != GetLastError() ) { return GetLastError(); }
if( LoSize <= sizeof(DWORD) ) { CloseHandle(hTextFile); return ERROR_INVALID_DATA; } (*MemSize) = LoSize; (*Mem) = NULL; hMapping = CreateFileMapping( hTextFile, NULL, PAGE_READONLY | SEC_COMMIT, HiSize, LoSize, NULL ); if( NULL == hMapping ) { Error = GetLastError(); Tr("Can't map file: %ld\n", Error ); return Error; }
FileView = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
if( NULL == FileView ) { Error = GetLastError(); Tr("Can't create view: %ld\n", Error ); CloseHandle( hMapping ); CloseHandle( hTextFile ); hTextFile = NULL; hMapping = NULL; return Error; }
(*Mem) = FileView;
//
// Before okaying, check if the version of the file is
// greater than current version
//
Error = NO_ERROR; CopyMemory(&Flags, *Mem, sizeof(Flags)); switch(GetCurrentMagicCookie()) { case MAGIC_COOKIE_NT5_PLUS : if( Flags != MAGIC_COOKIE_NT5 && Flags != MAGIC_COOKIE_NT5_PLUS && Flags != MAGIC_COOKIE_NT4 ) { Error = ERROR_NOT_SUPPORTED; } break; case MAGIC_COOKIE_NT5 : if( Flags != MAGIC_COOKIE_NT5 && Flags != MAGIC_COOKIE_NT4 ) { Error = ERROR_NOT_SUPPORTED; } break; case MAGIC_COOKIE_NT4 : if( Flags != MAGIC_COOKIE_NT4 ) { Error = ERROR_NOT_SUPPORTED; } break; }
if( NO_ERROR != Error ) { UnmapViewOfFile(FileView); CloseHandle( hMapping ); CloseHandle( hTextFile ); hTextFile = NULL; hMapping = NULL; FileView = NULL; return Error; } *MemSize -= sizeof(DWORD); (*Mem) += sizeof(DWORD); return NO_ERROR; }
VOID CloseTextFile( IN OUT HANDLE hFile, IN OUT LPBYTE Mem ) { ASSERT( hFile == hTextFile ); if( NULL != FileView ) UnmapViewOfFile( FileView ); FileView = NULL;
if( NULL != hMapping ) CloseHandle( hMapping ); hMapping = NULL;
if( NULL != hTextFile ) CloseHandle( hTextFile ); hTextFile = NULL; }
ULONG ByteSwap( IN ULONG Source ) { ULONG swapped;
swapped = ((Source) << (8 * 3)) | ((Source & 0x0000FF00) << (8 * 1)) | ((Source & 0x00FF0000) >> (8 * 1)) | ((Source) >> (8 * 3));
return swapped; }
LPSTR IpAddressToString( IN ULONG Address ) { static CHAR Buffer[30]; PUCHAR pAddress;
pAddress = (PUCHAR)&Address; sprintf(Buffer, "%d.%d.%d.%d", pAddress[0], pAddress[1], pAddress[2], pAddress[3] ); return Buffer; }
VOID static CleanupDatabase( VOID ) { if( JetTbl != 0 ) { JetCloseTable( JetSession, JetTbl ); JetTbl = 0; }
if( JetSession != 0 ) { JetEndSession( JetSession, 0 ); JetSession = 0; }
if( NULL != hJet ) { if( NULL != JetTerm2 ) { JetTerm2( JetInstance, JET_bitTermComplete ); } else { JetTerm( JetInstance ); } FreeLibrary( hJet ); hJet = NULL; }
JetInstance = 0; }
DWORD LoadAndLinkRoutines( IN DWORD JetVersion ) { DWORD Error, i; LPTSTR Module; LPSTR FuncName; Module = NULL; switch( JetVersion ) { case LoadJet2001 : Module = TEXT("esent.dll"); break; case LoadJet97 : Module = TEXT("esent.dll"); break; case LoadJet500 : Module = TEXT("jet500.dll"); break; case LoadJet200 : Module = TEXT("jet.dll"); break; default: Module = TEXT("esent.dll"); break; }
hJet = LoadLibrary( Module ); if( NULL == hJet ) { Error = GetLastError(); } else { Error = NO_ERROR; }
Tr( "Loading %ws: %ld\n", Module, Error ); if( NO_ERROR != Error ) return Error;
for( i = 0; i < sizeof(FuncTable)/sizeof(FuncTable[0]); i ++ ) { (*FuncTable[i].FuncPtr) = NULL; } for( i = 0; i < sizeof(FuncTable)/sizeof(FuncTable[0]); i ++ ) { if( LoadJet200 != JetVersion ) { FuncName = FuncTable[i].FuncName; } else { if( 0 == FuncTable[i].Index ) { (*FuncTable[i].FuncPtr) = NULL; continue; }
FuncName = (LPSTR)ULongToPtr(FuncTable[i].Index); }
Error = NO_ERROR; (*FuncTable[i].FuncPtr) = GetProcAddress(hJet, FuncName); if( NULL == FuncTable[i].FuncPtr ) { Error = GetLastError();
if( LoadJet97 == JetVersion || LoadJet2001 == JetVersion ) { (*FuncTable[i].FuncPtr) = GetProcAddress( hJet, FuncTable[i].AltName ); if( NULL != FuncTable[i].FuncPtr ) continue;
Error = GetLastError(); } }
Tr("GetProcAddr[%ws]: %ld\n", FuncTable[i].FuncNameW, Error ); if( NO_ERROR != Error ) break; }
//
// if erred out, cleanup
//
if( NO_ERROR != Error ) { FreeLibrary( hJet ); hJet = NULL; }
return Error; }
DWORD SetJetParams( IN DWORD JetVersion, IN LPSTR DbName, IN LPSTR DbPath ) { DWORD Error, JetParam, LogFileSize; CHAR Temp[2048]; LPSTR DbSysFile = "\\system.mdb"; LPSTR DbBaseName = "j50";
JetInstance = 0; LogFileSize = 1000;
if( JetVersion == LoadJet2001 ) LogFileSize = 1024;
memcpy( Temp, DbPath, (( sizeof( Temp ) - 1 ) < strlen( DbPath )) ? sizeof( Temp ) : strlen( DbPath ) + 1 ); Temp[ sizeof( Temp ) - 2 ] = '\0';
if( LoadJet200 == JetVersion ) { strcat(Temp, DbSysFile); JetParam = JET_paramSysDbPath_OLD; } else { strcat(Temp, "\\"); if( LoadJet97 > JetVersion ) { JetParam = JET_paramSystemPath_OLD; } else { JetParam = JET_paramSystemPath; } }
Error = JetSetSystemParameter( &JetInstance, (JET_SESID)0, JetParam, 0, Temp );
Tr("SetDbParam %ld: %ld\n", JetParam, Error ); if( NO_ERROR != Error ) return Error;
if( LoadJet200 != JetVersion ) { if( LoadJet97 > JetVersion ) { JetParam = JET_paramBaseName_OLD; } else { JetParam = JET_paramBaseName; }
Error = JetSetSystemParameter( &JetInstance, (JET_SESID)0, JetParam, 0, DbBaseName );
Tr("SetDbParam %ld: %ld\n", JetParam, Error ); if( NO_ERROR != Error ) return Error; }
if( LoadJet200 != JetVersion ) { if( LoadJet97 <= JetVersion ) { JetParam = JET_paramLogFileSize; } else { JetParam = JET_paramLogFileSize_OLD; }
Error = JetSetSystemParameter( &JetInstance, (JET_SESID)0, JetParam, LogFileSize, NULL ); Tr("SetDbParam %ld: %ld\n", JetParam, Error ); if( NO_ERROR != Error ) return Error; } if( LoadJet200 != JetVersion ) { Error = JetSetSystemParameter( &JetInstance, (JET_SESID)0, JET_paramCheckFormatWhenOpenFail, 1, NULL );
JetParam = JET_paramCheckFormatWhenOpenFail; Tr("SetDbParam %ld: %ld\n", JetParam, Error ); if( NO_ERROR != Error ) return Error; }
if( LoadJet200 != JetVersion ) { if( LoadJet97 > JetVersion ) { JetParam = JET_paramRecovery_OLD; } else { JetParam = JET_paramRecovery; }
Error = JetSetSystemParameter( &JetInstance, (JET_SESID)0, JetParam, 0, "on");
Tr("SetDbParam %ld: %ld\n", JetParam, Error ); if( NO_ERROR != Error ) return Error; }
//
// Note: Ideally, the log files should never exist. Even
// if the database is opened in readonly mode, they seem to
// exist. Not sure what else can be done
//
if( LoadJet97 <= JetVersion ) { JetParam = JET_paramLogFilePath; } else { JetParam = JET_paramLogFilePath_OLD; }
strcpy(Temp, DbPath); strcat( Temp, "\\");
Error = JetSetSystemParameter( &JetInstance, (JET_SESID)0, JetParam, 0, Temp ); Tr("SetDbParam %ld: %ld\n", JetParam, Error );
return Error; }
DWORD OpenDatabase( IN DWORD JetVersion, IN LPSTR DbName, IN LPSTR DbPath ) { LONG Error; DWORD i; CHAR FilePath[2048]; JET_INDEXLIST TmpIdxList; DWORD Len, Len1;
JetSession = 0; JetDb = 0; JetTbl = 0;
Error = JetInit( &JetInstance );
Tr("JetInit: %ld\n", Error ); if( NO_ERROR != Error ) return Error;
Error = JetBeginSession( JetInstance, &JetSession, "admin", "" );
Tr("JetBeginSession: %ld\n", Error); if( Error < 0 ) return Error;
Error = JetDetachDatabase( JetSession, NULL );
Tr("JetDetachDatabase:%ld\n", Error ); if( Error < 0 ) return Error;
// Create the filename
Len = strlen( DbName ); Len1 = strlen( DbPath ); if ( sizeof( FilePath ) < ( Len + Len1 + 2 )) { // 2 for '\\' and '\0'
return ERROR_INVALID_PARAMETER; }
memcpy( FilePath, DbPath, Len1 ); FilePath[ Len1 ] = '\\'; memcpy( FilePath + Len1 + 1, DbName, Len ); FilePath[ Len + Len1 + 1 ] = '\0';
Error = JetAttachDatabase( JetSession, FilePath, JET_bitDbExclusive );
Tr("JetAttachDatabase:%ld\n", Error ); if( Error < 0 ) return Error;
Error = JetOpenDatabase( JetSession, FilePath, NULL, &JetDb, JET_bitDbSingleExclusive );
Tr("JetOpenDatabase: %ld\n", Error); if( Error < 0 ) return Error;
Error = JetOpenTable( JetSession, JetDb, (LPSTR)"ClientTable", NULL, 0, 0,&JetTbl );
Tr("JetOpenTable: %ld\n", Error ); if( Error < 0 ) return Error;
for( i = 0; i < sizeof(ClientTable)/sizeof(ClientTable[0]); i ++ ) { JET_COLUMNDEF ColDef;
Error = JetGetTableColumnInfo( JetSession, JetTbl, ClientTable[i].ColName, &ColDef, sizeof(ColDef), 0 );
if(Error && JET_errColumnNotFound != Error ) { Tr("JetGetCol: %ld\n", Error ); }
if( Error < 0 ) { if( JET_errColumnNotFound == Error ) { ClientTable[i].fPresent = FALSE; continue; } else { return Error; } }
if( ColDef.coltyp != ClientTable[i].ColType ) { ASSERT( FALSE ); Error = ERROR_BAD_FORMAT; return Error; }
ClientTable[i].ColHandle = ColDef.columnid; }
return NO_ERROR; }
DWORD LoadAndInitializeDatabase( IN DWORD JetVersion, IN LPSTR DbName, IN LPSTR DbPath ) { DWORD Error;
//
// Attempt to load DLL and retrieve function pointers
//
Tr("Loading %ld jet version\n", JetVersion ); Error = LoadAndLinkRoutines( JetVersion ); if( NO_ERROR != Error ) return Error;
//
// set standard jet params
//
Error = SetJetParams( JetVersion, DbName, DbPath ); if( NO_ERROR != Error ) { FreeLibrary( hJet ); hJet = NULL; return Error; }
//
// Attempt to open database
//
Error = OpenDatabase( JetVersion, DbName, DbPath ); if( NO_ERROR != Error ) { CleanupDatabase(); return Error; } return NO_ERROR; }
DWORD LoadAndLinkSecurityRoutines( OUT FARPROC *pGetInfo, OUT FARPROC *pSetInfo ) { HMODULE hAdvapi32;
hAdvapi32 = GetModuleHandle(TEXT("ADVAPI32.DLL")); if( NULL == hAdvapi32 ) return GetLastError();
(*pGetInfo) = GetProcAddress(hAdvapi32, "GetNamedSecurityInfoA"); if( NULL == *pGetInfo ) return GetLastError();
(*pSetInfo) = GetProcAddress(hAdvapi32, "SetNamedSecurityInfoA"); if( NULL == *pSetInfo ) return GetLastError();
return NO_ERROR; }
DWORD ConvertPermissionsOnDbFiles( VOID ) { DWORD Error, dwVersion = GetVersion(); PSECURITY_DESCRIPTOR pSec; PACL pAcl; HANDLE hSearch = INVALID_HANDLE_VALUE; WIN32_FIND_DATAA FileData; CHAR FileName[1024]; FARPROC pGetInfo, pSetInfo; CHAR DriversDirPath[MAX_PATH *2 +1]; DWORD PathLen = sizeof(DriversDirPath)-1; //
// Check if version is atleast NT5.
//
dwVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); if( dwVersion < 5 ) return NO_ERROR; //
// First get the requried function pointers..
//
Error = LoadAndLinkSecurityRoutines( &pGetInfo, &pSetInfo ); if( NO_ERROR != Error ) return Error;
ZeroMemory(DriversDirPath, PathLen+1); PathLen = ExpandEnvironmentStringsA( "%SystemRoot%\\system32\\drivers", DriversDirPath, PathLen ); if( PathLen == 0 ) { Error = GetLastError(); return Error; } pSec = NULL; pAcl = NULL; Error = (DWORD)pGetInfo( DriversDirPath, //"MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer",
SE_FILE_OBJECT, // SE_REGISTRY_KEY
DACL_SECURITY_INFORMATION, NULL, NULL, &pAcl, NULL, &pSec );
if( NO_ERROR != Error ) return Error;
Error = (DWORD)pSetInfo( DatabasePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pAcl, NULL ); if( NO_ERROR != Error ) return Error;
strcpy(FileName, DatabasePath); if( FileName[strlen(FileName)-1] != '\\' ) { strcat(FileName, "\\"); } strcat(FileName, DatabaseName);
Error = (DWORD)pSetInfo( FileName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pAcl, NULL ); if( NO_ERROR != Error ) goto Cleanup;
//
// Now for all files matching "*.log", repeat above operation
//
strcpy(FileName, DatabasePath); if( FileName[strlen(FileName)-1] != '\\' ) { strcat(FileName, "\\"); } strcat(FileName, "*.*"); hSearch = FindFirstFileA( FileName, &FileData ); if( INVALID_HANDLE_VALUE == hSearch ) { Error = GetLastError(); goto Cleanup; }
do {
if( 0 != strcmp(FileData.cFileName, ".") && 0 != strcmp(FileData.cFileName, "..") ) { strcpy(FileName, DatabasePath); if( FileName[strlen(FileName)-1] != '\\' ) { strcat(FileName, "\\"); } strcat(FileName, FileData.cFileName); Error = (DWORD)pSetInfo( FileName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pAcl, NULL ); if( NO_ERROR != Error ) break; }
Error = FindNextFileA( hSearch, &FileData ); if( FALSE != Error ) Error = NO_ERROR; else Error = GetLastError();
} while( NO_ERROR == Error );
FindClose( hSearch ); Cleanup:
LocalFree( pSec );
if( ERROR_FILE_NOT_FOUND == Error ) return NO_ERROR; if( ERROR_NO_MORE_FILES == Error ) return NO_ERROR; return Error; }
DWORD ReadString( IN HKEY hKey, IN LPSTR KeyName, IN LPSTR Buffer, IN ULONG BufSize ) { DWORD Error, Size, Type; CHAR Str[1024];
Size = sizeof(Str); Error = RegQueryValueExA( hKey, KeyName, NULL, &Type, (LPSTR)Str, &Size ); if( NO_ERROR == Error ) { if( 0 == Size || 1 == Size ) Error = ERROR_NOT_FOUND; if( Type != REG_SZ && Type != REG_EXPAND_SZ && Type != REG_MULTI_SZ ) Error = ERROR_BAD_FORMAT; }
if( NO_ERROR != Error ) return Error;
Size = ExpandEnvironmentStringsA( (LPSTR)Str, Buffer, BufSize ); if( Size == 0 || Size > BufSize ) { Error = ERROR_META_EXPANSION_TOO_LONG; }
Tr("Expansion failed for %s\n", KeyName ); return Error; }
DWORD ReadRegistry( VOID ) { HKEY hKey; DWORD Error, Size, Use351Db, DbType; CHAR Str[1024];
//
// Open dhcp server parameters key
//
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Parameters"), 0, KEY_READ, &hKey );
Tr("Open Params key failed %ld\n", Error ); if( NO_ERROR != Error ) return Error;
//
// Read database details
//
do { Error = ReadString( hKey, "DatabasePath", (LPSTR)DatabasePath, sizeof(DatabasePath) );
if( NO_ERROR != Error ) { Tr(" Read DatabasePath failed: %ld\n", Error ); break; }
Error = ReadString( hKey, "DatabaseName", (LPSTR)DatabaseName, sizeof(DatabaseName) );
if( NO_ERROR != Error ) { Tr("Read DatabaseName failed %ld\n", Error ); break; }
strcpy(DhcpEximOemDatabaseName, DatabaseName); strcpy(DhcpEximOemDatabasePath, DatabasePath); CharToOemA(DhcpEximOemDatabaseName, DhcpEximOemDatabaseName); CharToOemA(DhcpEximOemDatabasePath, DhcpEximOemDatabasePath); if( !IsNT5() && !IsNT4() ) JetVersion = LoadJet2001; else { if( IsNT5() ) JetVersion = LoadJet97; else JetVersion = LoadJet500; Size = sizeof(DWORD); Error = RegQueryValueExA( hKey, "Use351Db", NULL, NULL, (LPBYTE)&Use351Db, &Size ); if( NO_ERROR == Error ) { JetVersion = LoadJet200; } else { Size = sizeof(DWORD); Error = RegQueryValueExA( hKey, "DbType", NULL, NULL, (LPBYTE)&DbType, &Size ); if( NO_ERROR == Error ) { switch(DbType) { case 3: JetVersion = LoadJet200; break; case 4: JetVersion = LoadJet500; break; } } } } Error = NO_ERROR;
} while( 0 );
#if DBG
DbgPrint("JetVersion: %ld\n", JetVersion); #endif
RegCloseKey( hKey ); return Error; }
DWORD InitializeDatabase( VOID ) { DWORD Error;
if( FALSE == SetCurrentDirectoryA(DatabasePath) ) { Error = GetLastError(); if( ERROR_FILE_NOT_FOUND == Error || ERROR_PATH_NOT_FOUND == Error ) { return ERROR_SERVICE_DOES_NOT_EXIST; } return Error; }
Error = LoadAndInitializeDatabase( JetVersion, (LPSTR)DatabaseName, (LPSTR)DatabasePath );
if( NO_ERROR != Error ) { Tr("LoadAndInitializeDatabase(%ld):%ld\n", JetVersion, Error ); } return Error; }
JET_ERR GetColumnValue( IN DWORD Index, IN LPSTR Buffer, IN OUT ULONG *BufSize ) { JET_ERR Error = NO_ERROR; DWORD Size;
if( ClientTable[Index].fPresent == FALSE ) { (*BufSize) = 0; return NO_ERROR; } Error = JetRetrieveColumn( JetSession, JetTbl, ClientTable[Index].ColHandle, Buffer, *BufSize, &Size, 0, NULL );
if( JET_errColumnNotFound == Error ) { Error = NO_ERROR; Size = 0; }
Tr("JetRetrieveColumn(%ld): %ld\n", Index, Error ); if( Error < 0 ) return Error;
(*BufSize) = Size; return NO_ERROR; }
JET_ERR SetColumnValue( IN DWORD Index, IN LPSTR Buffer, IN ULONG BufSize ) { JET_ERR Error = NO_ERROR;
if( ClientTable[Index].fPresent == FALSE ) { return ERROR_CAN_NOT_COMPLETE; } Error = JetSetColumn( JetSession, JetTbl, ClientTable[Index].ColHandle, Buffer, BufSize, 0, NULL );
Tr("JetSetColumn(%ld): %ld\n", Index, Error ); if( Error < 0 ) return Error;
return NO_ERROR; }
#define CLIENT_TYPE_UNSPECIFIED 0x0 // for backward compatibility
#define CLIENT_TYPE_DHCP 0x1
#define CLIENT_TYPE_BOOTP 0x2
#define CLIENT_TYPE_BOTH ( CLIENT_TYPE_DHCP | CLIENT_TYPE_BOOTP )
#define ADDRESS_STATE_OFFERED 0
#define ADDRESS_STATE_ACTIVE 1
#define ADDRESS_STATE_DECLINED 2
#define ADDRESS_STATE_DOOM 3
#define ADDRESS_BIT_DELETED 0x80
#define ADDRESS_BIT_UNREGISTERED 0x40
#define ADDRESS_BIT_BOTH_REC 0x20
#define ADDRESS_BIT_CLEANUP 0x10
#define ADDRESS_BITS_MASK 0xF0
DWORD AddRecord( IN LPSTR Buffer, IN ULONG BufSize );
DWORD AddScannedClient( IN DWORD IpAddressNetOrder, IN DWORD SubnetMaskNetOrder, IN LPBYTE HwAddr, IN ULONG HwLen, IN LPWSTR MachineName, IN LPWSTR MachineInfo, IN ULONGLONG ExpirationFileTime, IN BYTE State, IN BYTE ClientType ) { DWORD i; CHAR Buffer[1024]; ULONG Length, Size;
Length = 0; Buffer[Length++] = (BYTE)RecordTypeDbEntry; CopyMemory( &Buffer[Length], (PVOID)&IpAddressNetOrder, sizeof(DWORD) ); Length += sizeof(DWORD); CopyMemory( &Buffer[Length], (PVOID)&SubnetMaskNetOrder, sizeof(DWORD) ); Length += sizeof(DWORD);
Buffer[Length++] = (BYTE)HwLen; CopyMemory(&Buffer[Length], HwAddr, HwLen ); Length += HwLen; if( NULL == MachineName || 0 == *MachineName ) Size = 0; else Size = sizeof(WCHAR)*(1+wcslen(MachineName));
CopyMemory(&Buffer[Length], (PVOID)&Size, sizeof(DWORD)); Length += sizeof(DWORD); if ( NULL != MachineName ) { CopyMemory(&Buffer[Length], (PVOID)MachineName, Size ); Length += Size; }
if( NULL == MachineInfo || 0 == *MachineInfo ) Size = 0; else Size = sizeof(WCHAR)*(1+wcslen(MachineInfo));
CopyMemory(&Buffer[Length], (PVOID)&Size, sizeof(DWORD)); Length += sizeof(DWORD); if ( NULL != MachineInfo ) { CopyMemory(&Buffer[Length], (PVOID)MachineInfo, Size ); Length += Size; }
CopyMemory(&Buffer[Length], (PVOID)&ExpirationFileTime, sizeof(ULONGLONG)); Length += sizeof(ULONGLONG); Buffer[Length++] = State; Buffer[Length++] = ClientType;
return AddRecord( Buffer, Length ); }
BOOL SubnetNotSelected( IN ULONG Subnet, IN PULONG Subnets, IN ULONG nSubnets ) { if( nSubnets == 0 ) return FALSE; while( nSubnets -- ) { if( Subnet == *Subnets++ ) return FALSE; } return TRUE; }
DWORD static ScanDatabase( IN PULONG Subnets, IN ULONG nSubnets ) { LONG Error; DWORD Count; Error = JetSetCurrentIndex( JetSession, JetTbl, NULL );
Tr("JetSetCurrentIndex: %ld\n", Error ); if( Error < 0 ) return Error;
Error = JetMove( JetSession, JetTbl, JET_MoveFirst, 0 );
for( Count = 0 ; Error >= 0 ; Count ++, Error = JetMove(JetSession, JetTbl, JET_MoveNext, 0) ) { DWORD IpAddress, SubnetMask, Size, HwLen; FILETIME Expiration; CHAR HwAddress[256]; WCHAR MachineName[300], MachineInfo[300]; BYTE Type, State; //
// Get current client's info.
//
Size = sizeof(IpAddress); Error = GetColumnValue( IPADDRESS_INDEX, (PVOID)&IpAddress, &Size );
if( NO_ERROR != Error ) break; if( Size != sizeof(IpAddress) ) { Tr("Invalid Ip size\n"); continue; } Size = sizeof(SubnetMask); Error = GetColumnValue( SUBNET_MASK_INDEX, (PVOID)&SubnetMask, &Size );
if( NO_ERROR != Error ) break; if( Size != sizeof(SubnetMask) ) { Tr("Invalid mask size\n"); continue; }
//
// Check if the subnet specified matches the specific
// subnet
//
if( SubnetNotSelected( IpAddress&SubnetMask, Subnets, nSubnets ) ) { continue; } HwLen = sizeof(HwAddress); Error = GetColumnValue( HARDWARE_ADDRESS_INDEX, (PVOID)HwAddress, &HwLen ); if( NO_ERROR != Error ) break;
Size = sizeof(MachineName); Error = GetColumnValue( MACHINE_NAME_INDEX, (PVOID)MachineName, &Size ); if( NO_ERROR != Error ) break;
if( (Size % 2) != 0 ) { Tr("Invalid name size\n"); continue; }
MachineName[Size/2] = L'\0';
Size = sizeof(MachineInfo); Error = GetColumnValue( MACHINE_INFO_INDEX, (PVOID)MachineInfo, &Size ); if( NO_ERROR != Error ) break;
if( (Size % 2) != 0 ) { Tr("Invalid Info size\n"); continue; }
MachineInfo[Size/2] = L'\0';
Size = sizeof(Expiration); Error = GetColumnValue( LEASE_TERMINATE_INDEX, (PVOID)&Expiration, &Size ); if( NO_ERROR != Error ) break;
if( Size != sizeof(Expiration) ) { Tr("Invalid expiration\n"); Error = ERROR_INVALID_DATA; break; }
Size = sizeof(Type); Error = GetColumnValue( CLIENT_TYPE_INDEX, (PVOID)&Type, &Size );
if( NO_ERROR != Error || 0 == Size ) { Type = CLIENT_TYPE_DHCP; }
Size = sizeof(State); Error = GetColumnValue( STATE_INDEX, (PVOID)&State, &Size );
if( NO_ERROR != Error || 0 == Size ) { State = ADDRESS_STATE_ACTIVE; }
if( ADDRESS_STATE_OFFERED == State ) { continue; } //
// Try to add the client
//
Error = AddScannedClient( ByteSwap(IpAddress), ByteSwap(SubnetMask), HwAddress, HwLen, MachineName, MachineInfo, *(PULONGLONG)&Expiration, State, Type ); if( NO_ERROR != Error ) break; }
Tr("Scanned %ld clients\n", Count ); if( JET_errNoCurrentRecord == Error ) return NO_ERROR; if( Error < 0 ) return Error; return NO_ERROR; }
DWORD DumpData( IN LPSTR Buffer, IN ULONG BufSize ) { return NO_ERROR; }
DWORD AddRecord( IN LPSTR Buffer, IN ULONG BufSize ) { DWORD Written, Error = NO_ERROR;
if( NULL != Buffer ) { CopyMemory(&SaveBuf[SaveBufSize], (PVOID)&BufSize, sizeof(DWORD)); CopyMemory(&SaveBuf[SaveBufSize+sizeof(DWORD)], Buffer, BufSize ); } else { if( 0 == SaveBufSize ) return NO_ERROR; if( FALSE == WriteFile( hTextFile, SaveBuf, SaveBufSize, &Written, NULL ) ) { return GetLastError(); }
if( Written != SaveBufSize ) { ASSERT(FALSE); return ERROR_CAN_NOT_COMPLETE; }
return NO_ERROR; } if( SaveBufSize <= SAVE_THRESHOLD ) { SaveBufSize += BufSize + sizeof(DWORD); } else { if( FALSE == WriteFile( hTextFile, SaveBuf, SaveBufSize + BufSize + sizeof(DWORD), &Written, NULL )) { return GetLastError(); }
if( Written != SaveBufSize + BufSize + sizeof(DWORD) ) { ASSERT(FALSE); return ERROR_CAN_NOT_COMPLETE; } SaveBufSize = 0; }
return Error; }
DWORD AddRecordNoSize( IN LPSTR Buffer, IN ULONG BufSize ) { DWORD Written, Error = NO_ERROR;
if( NULL != Buffer ) { CopyMemory(&SaveBuf[SaveBufSize], Buffer, BufSize ); } else { if( 0 == SaveBufSize ) return NO_ERROR; if( FALSE == WriteFile( hTextFile, SaveBuf, SaveBufSize, &Written, NULL ) ) { return GetLastError(); }
if( Written != SaveBufSize ) { ASSERT(FALSE); return ERROR_CAN_NOT_COMPLETE; }
return NO_ERROR; } if( SaveBufSize <= SAVE_THRESHOLD ) { SaveBufSize += BufSize; } else { if( FALSE == WriteFile( hTextFile, SaveBuf, SaveBufSize + BufSize, &Written, NULL )) { return GetLastError(); }
if( Written != SaveBufSize + BufSize ) { ASSERT(FALSE); return ERROR_CAN_NOT_COMPLETE; } SaveBufSize = 0; }
return Error; }
DWORD StopDhcpService( VOID ) { SC_HANDLE hSc, hSvc; DWORD Error;
Error = NO_ERROR; hSc = NULL; hSvc = NULL; do { hSc = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ | GENERIC_WRITE ); if( NULL == hSc ) { Error = GetLastError();
Tr("OpenSCManager: %ld\n", Error ); break; }
hSvc = OpenService( hSc, TEXT("DHCPServer"), SERVICE_STOP| SERVICE_QUERY_STATUS ); if( NULL == hSvc ) { Error = GetLastError();
Tr("OpenService: %ld\n", Error ); break; }
while( NO_ERROR == Error ) { SERVICE_STATUS Status;
if( FALSE == QueryServiceStatus( hSvc, &Status ) ) { Error = GetLastError(); Tr( "QueryServiceStatus: %ld\n", Error ); break; }
if( Status.dwCurrentState == SERVICE_STOPPED ) break; if( Status.dwCurrentState != SERVICE_RUNNING && Status.dwCurrentState != SERVICE_PAUSED ) { Tr( "Waiting, state = %ld\n", Status.dwCurrentState );
if( Status.dwWaitHint < 1000 ) { Status.dwWaitHint = 1000; } if( Status.dwWaitHint > 5000 ) { Status.dwWaitHint = 1000; } Sleep(Status.dwWaitHint); } else { Error = ControlService( hSvc, SERVICE_CONTROL_STOP, &Status ); if( FALSE != Error ) Error = NO_ERROR; else { Error = GetLastError(); Tr("ControlService: %ld\n", Error ); break; } } } } while( 0 );
if( NULL != hSvc ) CloseServiceHandle( hSvc ); if( NULL != hSc ) CloseServiceHandle( hSc ); return Error; }
DWORD StartDhcpService( VOID ) { SC_HANDLE hSc, hSvc; DWORD Error;
Error = NO_ERROR; hSc = NULL; hSvc = NULL; do { hSc = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ | GENERIC_WRITE ); if( NULL == hSc ) { Error = GetLastError();
Tr("OpenSCManager: %ld\n", Error ); break; }
hSvc = OpenService( hSc, TEXT("DHCPServer"), SERVICE_START| SERVICE_QUERY_STATUS ); if( NULL == hSvc ) { Error = GetLastError();
Tr("OpenService: %ld\n", Error ); break; }
Error = StartService( hSvc, 0, NULL ); if( FALSE == Error ) Error = GetLastError(); else Error = NO_ERROR; if( NO_ERROR != Error ) break; while( NO_ERROR == Error ) { SERVICE_STATUS Status;
if( FALSE == QueryServiceStatus( hSvc, &Status ) ) { Error = GetLastError(); Tr("QueryServiceStatus: %ld\n", Error ); break; }
if( Status.dwCurrentState == SERVICE_RUNNING ) break; if( Status.dwCurrentState == SERVICE_START_PENDING ) { Tr("Sleeping %ld\n", Status.dwWaitHint ); if( Status.dwWaitHint < 1000 ) { Status.dwWaitHint = 1000; } if( Status.dwWaitHint > 5000 ) { Status.dwWaitHint = 5000; } Sleep(Status.dwWaitHint); } else { Error = ERROR_CAN_NOT_COMPLETE; break; } } } while( 0 );
if( NULL != hSvc ) CloseServiceHandle( hSvc ); if( NULL != hSc ) CloseServiceHandle( hSc ); return Error; }
DWORD __stdcall PrintRecord( IN PDHCP_RECORD Recx ) { DWORD i; DHCP_RECORD Rec = *Recx; if( Rec.fMcast ) { printf("Mcast Record\n" ); printf("Address: %s\n", IpAddressToString( Rec.Info.Mcast.Address )); printf("ScopeId: %s\n", IpAddressToString( Rec.Info.Mcast.ScopeId ));
printf("ClientId:"); for( i = 0 ; i < (DWORD)Rec.Info.Mcast.HwLen; i ++ ) { printf(" %02X", Rec.Info.Mcast.ClientId[i]); } printf("\nState = %02X\n", Rec.Info.Mcast.State); } else { printf("DHCP Record\n" ); printf("Address: %s\n", IpAddressToString( Rec.Info.Dhcp.Address )); printf("Mask: %s\n", IpAddressToString( Rec.Info.Dhcp.Mask ));
printf("ClientId:"); for( i = 0 ; i < (DWORD)Rec.Info.Dhcp.HwLen; i ++ ) { printf(" %02X", Rec.Info.Dhcp.HwAddr[i]); } printf("\nState = %02X\n", Rec.Info.Dhcp.State); printf("\nType = %02X\n", Rec.Info.Dhcp.Type); if( Rec.Info.Dhcp.Name ) { printf("Name = %ws\n", Rec.Info.Dhcp.Name ); }
if( Rec.Info.Dhcp.Info ) { printf("Comment = %ws\n", Rec.Info.Dhcp.Info ); } }
return NO_ERROR; }
DWORD StringLen( IN WCHAR UNALIGNED *Str ) { DWORD Size = sizeof(WCHAR);
if( NULL == Str ) return 0; while( *Str ++ != L'\0' ) Size += sizeof(WCHAR);
return Size; }
DWORD __stdcall AddRecordToDatabase( IN PDHCP_RECORD Recx ) { DWORD Index; JET_ERR Error; DHCP_RECORD Rec = *Recx; WCHAR Address[30], HwAddress[300];
IpAddressToStringW(Rec.Info.Dhcp.Address, Address); DhcpHexToString( HwAddress, Rec.Info.Dhcp.HwAddr, Rec.Info.Dhcp.HwLen ); Error = JetBeginTransaction( JetSession ); Tr( "JetBeginTransaction: %ld\n", Error ); if( Error < 0 ) return Error;
do { Error = JetPrepareUpdate( JetSession, JetTbl, JET_prepInsert ); if( Error ) Tr( "JetPrepareUpdate: %ld\n", Error ); if( Error < 0 ) break;
Index = IPADDRESS_INDEX; Error = SetColumnValue( Index, (LPBYTE)&Rec.Info.Dhcp.Address, sizeof(DWORD) ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break; Index = SUBNET_MASK_INDEX; Error = SetColumnValue( Index, (LPBYTE)&Rec.Info.Dhcp.Mask, sizeof(DWORD) ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = HARDWARE_ADDRESS_INDEX; Error = SetColumnValue( Index, Rec.Info.Dhcp.HwAddr, Rec.Info.Dhcp.HwLen ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = STATE_INDEX; Error = SetColumnValue( Index, &Rec.Info.Dhcp.State, sizeof(BYTE) ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = CLIENT_TYPE_INDEX; Error = SetColumnValue( Index, &Rec.Info.Dhcp.Type, sizeof(BYTE) ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = MACHINE_INFO_INDEX; Error = SetColumnValue( Index, (LPBYTE)Rec.Info.Dhcp.Info, StringLen(Rec.Info.Dhcp.Info) ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = MACHINE_NAME_INDEX; Error = SetColumnValue( Index, (LPBYTE)Rec.Info.Dhcp.Name, StringLen(Rec.Info.Dhcp.Name) ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = LEASE_TERMINATE_INDEX; Error = SetColumnValue( Index, (LPBYTE)&Rec.Info.Dhcp.ExpTime, sizeof(FILETIME) ); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = SERVER_IP_ADDRESS_INDEX; Rec.Info.Dhcp.Address = INADDR_LOOPBACK; Error = SetColumnValue( Index, (LPBYTE)&Rec.Info.Dhcp.Address, sizeof(DWORD)); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Index = SERVER_NAME_INDEX; Rec.Info.Dhcp.Name = L""; Error = SetColumnValue( Index, (LPBYTE)Rec.Info.Dhcp.Name, StringLen(Rec.Info.Dhcp.Name)); if( Error ) Tr( "SetColumnValue(%ld): %ld\n", Index, Error ); if( Error < 0 ) break;
Error = JetUpdate( JetSession, JetTbl, NULL, 0, NULL ); if( Error ) Tr( "JetUpdate: %ld\n", Error ); if( Error < 0 ) break;
} while ( 0 );
if( Error < 0 ) { BOOL fAbort;
JetRollback( JetSession, 0 );
fAbort = TRUE; DhcpEximErrorDatabaseEntryFailed( Address, HwAddress, Error, &fAbort );
if( fAbort ) return ERROR_CAN_NOT_COMPLETE; } else { JetCommitTransaction( JetSession, 0 ); }
return NO_ERROR; }
DWORD ProcessDbEntries( IN LPSTR Buffer, IN ULONG BufSize, IN PULONG Subnets, IN ULONG nSubnets, IN DHCP_ADD_RECORD_ROUTINE AddRec ) { DWORD Size, ThisSize, DbEntry; LPSTR Buf; DWORD Address, i, Error; FILETIME Time; DHCP_RECORD Rec;
Error = NO_ERROR; while( BufSize > sizeof(DWORD) ) { CopyMemory(&ThisSize, Buffer, sizeof(DWORD)); Buffer += sizeof(DWORD); BufSize -= sizeof(DWORD);
if( ThisSize > BufSize ) return ERROR_INVALID_DATA; if( ThisSize == 0 ) continue; DbEntry = *Buffer; Buf = Buffer+1; Buffer += ThisSize; BufSize -= ThisSize;
ZeroMemory( &Rec, sizeof(Rec));
switch(DbEntry) { default : return ERROR_INVALID_DATA; case RecordTypeDbEntry : Rec.fMcast = FALSE; CopyMemory( &Rec.Info.Dhcp.Address, Buf, sizeof(DWORD)); Rec.Info.Dhcp.Address = ByteSwap(Rec.Info.Dhcp.Address); Buf += sizeof(DWORD);
CopyMemory( &Rec.Info.Dhcp.Mask, Buf, sizeof(DWORD)); Rec.Info.Dhcp.Mask = ByteSwap(Rec.Info.Dhcp.Mask); Buf += sizeof(DWORD);
Size = Rec.Info.Dhcp.HwLen = *Buf++; Rec.Info.Dhcp.HwAddr = Buf; Buf += Size;
CopyMemory(&Size, Buf, sizeof(DWORD)); Buf += sizeof(DWORD); if( Size ) { Rec.Info.Dhcp.Name = (PVOID)Buf; Buf += Size; }
CopyMemory(&Size, Buf, sizeof(DWORD)); Buf += sizeof(DWORD); if( Size ) { Rec.Info.Dhcp.Info = (PVOID)Buf; Buf += Size; }
CopyMemory(&Rec.Info.Dhcp.ExpTime, Buf, sizeof(FILETIME)); Buf += sizeof(FILETIME);
Rec.Info.Dhcp.State = Buf[0]; Rec.Info.Dhcp.Type = Buf[1];
//
// Add the subnet only if it is selected
//
if( !SubnetNotSelected( Rec.Info.Dhcp.Address & Rec.Info.Dhcp.Mask, Subnets, nSubnets ) ) { Error = AddRec( &Rec ); } break; case RecordTypeMcastDbEntry : Rec.fMcast = TRUE; CopyMemory( &Rec.Info.Mcast.Address, Buf, sizeof(DWORD)); Buf += sizeof(DWORD);
CopyMemory( &Rec.Info.Mcast.ScopeId, Buf, sizeof(DWORD)); Buf += sizeof(DWORD);
Size = Rec.Info.Mcast.HwLen = *Buf++; Rec.Info.Mcast.ClientId = Buf; Buf += Size;
CopyMemory(&Size, Buf, sizeof(DWORD)); Buf += sizeof(DWORD); if( Size ) { Rec.Info.Mcast.Info = (PVOID)Buf; Buf += Size; }
CopyMemory(&Rec.Info.Mcast.End, Buf, sizeof(FILETIME)); Buf += sizeof(FILETIME);
CopyMemory(&Rec.Info.Mcast.Start, Buf, sizeof(FILETIME)); Buf += sizeof(FILETIME);
Rec.Info.Mcast.State = Buf[0];
Error = AddRec( &Rec ); break; }
if( NO_ERROR != Error ) return Error; }
return NO_ERROR; }
DWORD SaveDatabaseEntriesToFile( IN PULONG Subnets, IN ULONG nSubnets ) { DWORD Error; Error = InitializeDatabase(); if( NO_ERROR != Error ) { Tr("InitializeDatabase: %ld\n", Error ); return Error; }
Error = ScanDatabase(Subnets, nSubnets); if( NO_ERROR != Error ) { Tr("ScanDatabase: %ld\n", Error); } else { AddRecord( NULL, 0 ); }
CleanupDatabase();
return Error; } DWORD SaveFileEntriesToDatabase( IN LPBYTE Mem, IN ULONG MemSize, IN PULONG Subnets, IN ULONG nSubnets ) { DWORD Error;
Error = InitializeDatabase(); if( NO_ERROR != Error ) { Tr("InitializeDatabase: %ld\n", Error ); return Error; }
Error = ProcessDbEntries( Mem, MemSize, Subnets, nSubnets, AddRecordToDatabase ); if( NO_ERROR != Error ) { Tr("ProcessDbEntries: %ld\n", Error ); }
CleanupDatabase();
return Error; }
DWORD InitializeDatabaseParameters( VOID ) { DWORD Error; //
// Stop the service
//
Error = StopDhcpService(); if( NO_ERROR != Error ) { Tr("StopDhcpService: %ld\n", Error ); return Error; }
//
// Read the registry and otherwise initialize the database
// parameters, without actually opening the database.
//
Error = ReadRegistry(); Tr("ReadRegistry: %ld\n", Error ); if( NO_ERROR != Error ) return Error;
Error = ConvertPermissionsOnDbFiles(); Tr("ConvertPermissionsOnDbFiles: %ld\n", Error ); // ignore error and try best effort
if( FALSE == SetCurrentDirectoryA(DatabasePath) ) { Error = GetLastError(); if( ERROR_FILE_NOT_FOUND == Error || ERROR_PATH_NOT_FOUND == Error ) { return ERROR_SERVICE_DOES_NOT_EXIST; }
return Error; }
return NO_ERROR; }
DWORD CleanupDatabaseParameters( VOID ) { DWORD Error; Error = StartDhcpService(); if( NO_ERROR != Error ) { Tr("StartDhcpService: %ld\n", Error ); }
return Error; }
|