windows-nt/Source/XPSP1/NT/sdktools/iasinfdb/inf2db.cpp
2020-09-26 16:20:57 +08:00

500 lines
15 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// 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();
}