|
|
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999, Microsoft Corp. All rights reserved.
//
// FILE
//
// inf2db.h
//
// SYNOPSIS
// import the information stored in an INF file into a MSJet4 relational
// database
//
//
// MODIFICATION HISTORY
//
// 02/12/1999 Original version.
//
///////////////////////////////////////////////////////////////////////////////
// inf2db.cpp : Defines the entry point for the console application.
//
#include "precomp.hpp"
#include "inf2db.h"
///////////////////////////////////////////////////////////////////////////////
//
// Main
//
///////////////////////////////////////////////////////////////////////////////
extern "C" void __cdecl wmain(int argc, wchar_t* argv[]) { HINF lHINF;
HRESULT hres = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hres)) { cerr << "Unable to initialize COM!\n"; } else { CDatabase Database;
////////////////////////////////////////////////////////////////
// Call the process command (process the command-line arguments)
////////////////////////////////////////////////////////////////
hres = ProcessCommand(argc, argv, &lHINF, Database); if (FAILED(hres)) { g_FatalError = true; } else { ////////////////////////////////////////////////
// Call the process function to parse the file
////////////////////////////////////////////////
hres = Process(lHINF, Database); if (FAILED(hres)) { g_FatalError = true; }
//////////////////////////
// then call uninitialize
//////////////////////////
hres = Uninitialize(&lHINF, Database);
if (g_FatalError) { cerr << "Fatal Error: check the Trace file."; cerr << "Import operation aborted.\n"; } else { cerr << "Import successful.\n"; } } } CoUninitialize(); }
//////////////////////////////////////////////////////////////////////////////
//
// Unitialize
//
//////////////////////////////////////////////////////////////////////////////
HRESULT Uninitialize(HINF *phINF, CDatabase& Database) { _ASSERTE(phINF != NULL);
SetupCloseInfFile(*phINF);
return Database.Uninitialize(g_FatalError); }
//////////////////////////////////////////////////////////////////////////////
//
// Process
//
//////////////////////////////////////////////////////////////////////////////
HRESULT Process(const HINF& hINF, CDatabase& Database) {
// get the number of tables
LONG lTotalTableNumber = SetupGetLineCountW( // handle to the INF file
hINF, // the section in which to count lines
TABLE_SECTION );
bool bError = false; //needs to be outside the if, loop...
HRESULT hres;
if (lTotalTableNumber > 0) { #ifdef DEBUG
TracePrintf("Info: number of tables = %d\n",lTotalTableNumber); #endif
INFCONTEXT lTableContext; // if <>0 do a loop on the tables
BOOL bOK = SetupFindFirstLineW( hINF, TABLE_SECTION, NULL, &lTableContext );
for ( LONG lTableCounter = 0; lTableCounter < lTotalTableNumber; lTableCounter++ ) { // read the Table name in the Tables section
WCHAR lTableName[SIZELINEMAX];
bOK = SetupGetLineTextW( &lTableContext, NULL, NULL, NULL, lTableName, SIZELINEMAX, NULL );
// fetch the next line's context
if (!bOK) { g_FatalError = true; bError = true; break; }
// Rowset pointer
CComPtr<IRowset> lpRowset;
//////////////////////
// create one rowset
//////////////////////
hres = Database.InitializeRowset(lTableName, &lpRowset);
if (FAILED(hres)) { g_FatalError = true; bError = true; break; } else { // create the simpletable
CSimpleTableEx lSimpleTable;
lSimpleTable.Attach(lpRowset); lSimpleTable.MoveFirst();
//////////////////////////////////////////////////////
// now one table and all its columns are well known.
// empty database assumed
// process the rows
//////////////////////////////////////////////////////
hres = ProcessAllRows( hINF, lSimpleTable, lTableName );
if (FAILED(hres)) { // process rows should not fail, even if no rows are read
bError = true; g_FatalError = true; } }
//////////////////////////////////////////////////////
// Read the next table's name (if any)
//////////////////////////////////////////////////////
bOK = SetupFindNextLine( &lTableContext, &lTableContext ); if (!bOK) { if ((lTableCounter + 1) < lTotalTableNumber) { // find next line should not crash. fatal error
g_FatalError = true; bError = true; break; } break; } //end of tables
} } else {// no tables: do nothing
TracePrintf("Info: No [tables] section in the inf file\n"); // bError = true;
}
if (bError) { LPVOID lpMsgBuf; FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), // Default language
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &lpMsgBuf, 0, NULL );
// Display the string.
TracePrintf("Error: %S",lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf ); hres = E_FAIL; }
return hres; }
//////////////////////////////////////////////////////////////////////////////
//
// ProcessAllRows
//
//////////////////////////////////////////////////////////////////////////////
HRESULT ProcessAllRows( const HINF& hINF, CSimpleTableEx& pSimpleTable, const WCHAR* pTableName ) { _ASSERTE(pTableName != NULL);
////////////////////
// process the rows.
////////////////////
wstring lwsRowSection; lwsRowSection += pTableName;
LONG lRowCounter = 1;
INFCONTEXT lRowContext;
#ifdef DEBUG
TracePrintf("Info: %S",lwsRowSection.c_str()); #endif
////////////////////////////////////////////////////
// if <>0 do a loop on the lines (ie row names)
////////////////////////////////////////////////////
BOOL bOK = SetupFindFirstLineW( hINF, // section in which to find a line
lwsRowSection.c_str(), NULL, // optional, key to search for
&lRowContext // context of the found line
);
HRESULT hres = S_OK;
if (!bOK) { //no such section (end of section = end of rows)
} else {
LONG lTotalLinesNumber = 0; //safer
//////////////////////////////////////////////////////
// Get the Number of lines in that section. (& check)
//////////////////////////////////////////////////////
lTotalLinesNumber = SetupGetLineCountW( hINF, // handle to the INF file
// the section in which to count lines
lwsRowSection.c_str() );
//////////////////////////////
// Read eerything (loop)
//////////////////////////////
for ( LONG lLinesCounter = 0; lLinesCounter < lTotalLinesNumber; lLinesCounter++ ) {
#ifdef DEBUG
TracePrintf("Info: for loop: %d", lLinesCounter); #endif
///////////////////////////////////////////////
// read the Table name in the Tables section
///////////////////////////////////////////////
WCHAR lLineName[SIZELINEMAX];
bOK = SetupGetLineTextW( &lRowContext, NULL, NULL, NULL, lLineName, SIZELINEMAX, NULL );
if (!bOK) { g_FatalError = true; TracePrintf("Error: SetupGetLineText Failed " "in ProcessAllRows"); } else //everything is ok, process the corresponding row
{ ///////////////////////
// process the rows
///////////////////////
hres = ProcessOneRow( hINF, pSimpleTable, lLineName ); if (FAILED(hres)) { g_FatalError = true; }
}
//////////////////////////////////
// fetch the next line's context
//////////////////////////////////
bOK = SetupFindNextLine( // starting context in an INF file
&lRowContext, // context of the next line
&lRowContext ); if (!bOK) { ////////////////////////////////////////////////
// end of the lines
// compare the counter to the max to make sure
// that last line is ok
////////////////////////////////////////////////
if((lLinesCounter + 1) < lTotalLinesNumber) { // too early
g_FatalError = true; TracePrintf("Error: FindNext Line failed." "Not enough lines in the section %S", lwsRowSection.c_str());
} } } }
return hres; }
//////////////////////////////////////////////////////////////////////////////
//
// ProcessOneRow
//
//////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI ProcessOneRow( HINF inf, CSimpleTableEx& table, PCWSTR rowName ) { // Iterate through the columns in the database and see if the INF file
// specifies a value for each column.
for (DBORDINAL i = 0; i < table.GetColumnCount(); ++i) { // First try with a stack-based buffer.
WCHAR buffer[1024]; PWCHAR text = buffer; DWORD textSize = sizeof(buffer) / sizeof(buffer[0]); BOOL success = SetupGetLineTextW( NULL, inf, rowName, table.GetColumnName(i), text, textSize, &textSize ); DWORD error = success ? NO_ERROR : GetLastError();
if (error == ERROR_INSUFFICIENT_BUFFER) { // The stack-based buffer wasn't big enough, so allocate one on the
// heap ...
text = (PWCHAR)HeapAlloc( GetProcessHeap(), 0, textSize * sizeof(WCHAR) ); if (!text) { return E_OUTOFMEMORY; }
// ... and try again.
success = SetupGetLineTextW( NULL, inf, rowName, table.GetColumnName(i), text, textSize, &textSize ); error = success ? NO_ERROR : GetLastError(); }
// If we successfully retrieved the line text AND it has at least one
// character ...
if (!error && textSize > 1) { // ... then process based on the column data type.
switch (table.GetColumnType(i)) { case DBTYPE_I4: { table.SetValue(i, _wtol(text)); break; }
case DBTYPE_WSTR: { table.SetValue(i, text); break; }
case DBTYPE_BOOL: { table.SetValue(i, (VARIANT_BOOL)_wtol(text)); break; } } }
// Free the heap-based buffer if necessary.
if (text != buffer) { HeapFree(GetProcessHeap(), 0, text); }
switch (error) { case NO_ERROR: // Everything succeeded.
case ERROR_INVALID_PARAMETER: // SETUPAPI didn't like the column name.
case ERROR_LINE_NOT_FOUND: // The INF file didn't provide a value for this column.
break;
default: // Something went wrong.
return HRESULT_FROM_WIN32(error); } }
// All the columns are populated, so insert the row.
return table.Insert(); }
|