Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

499 lines
15 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // inf2db.h
  8. //
  9. // SYNOPSIS
  10. // import the information stored in an INF file into a MSJet4 relational
  11. // database
  12. //
  13. //
  14. // MODIFICATION HISTORY
  15. //
  16. // 02/12/1999 Original version.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. // inf2db.cpp : Defines the entry point for the console application.
  20. //
  21. #include "precomp.hpp"
  22. #include "inf2db.h"
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //
  25. // Main
  26. //
  27. ///////////////////////////////////////////////////////////////////////////////
  28. extern "C"
  29. void __cdecl wmain(int argc, wchar_t* argv[])
  30. {
  31. HINF lHINF;
  32. HRESULT hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  33. if (FAILED(hres))
  34. {
  35. cerr << "Unable to initialize COM!\n";
  36. }
  37. else
  38. {
  39. CDatabase Database;
  40. ////////////////////////////////////////////////////////////////
  41. // Call the process command (process the command-line arguments)
  42. ////////////////////////////////////////////////////////////////
  43. hres = ProcessCommand(argc, argv, &lHINF, Database);
  44. if (FAILED(hres))
  45. {
  46. g_FatalError = true;
  47. }
  48. else
  49. {
  50. ////////////////////////////////////////////////
  51. // Call the process function to parse the file
  52. ////////////////////////////////////////////////
  53. hres = Process(lHINF, Database);
  54. if (FAILED(hres))
  55. {
  56. g_FatalError = true;
  57. }
  58. //////////////////////////
  59. // then call uninitialize
  60. //////////////////////////
  61. hres = Uninitialize(&lHINF, Database);
  62. if (g_FatalError)
  63. {
  64. cerr << "Fatal Error: check the Trace file.";
  65. cerr << "Import operation aborted.\n";
  66. }
  67. else
  68. {
  69. cerr << "Import successful.\n";
  70. }
  71. }
  72. }
  73. CoUninitialize();
  74. }
  75. //////////////////////////////////////////////////////////////////////////////
  76. //
  77. // Unitialize
  78. //
  79. //////////////////////////////////////////////////////////////////////////////
  80. HRESULT Uninitialize(HINF *phINF, CDatabase& Database)
  81. {
  82. _ASSERTE(phINF != NULL);
  83. SetupCloseInfFile(*phINF);
  84. return Database.Uninitialize(g_FatalError);
  85. }
  86. //////////////////////////////////////////////////////////////////////////////
  87. //
  88. // Process
  89. //
  90. //////////////////////////////////////////////////////////////////////////////
  91. HRESULT Process(const HINF& hINF, CDatabase& Database)
  92. {
  93. // get the number of tables
  94. LONG lTotalTableNumber = SetupGetLineCountW(
  95. // handle to the INF file
  96. hINF,
  97. // the section in which to count lines
  98. TABLE_SECTION
  99. );
  100. bool bError = false; //needs to be outside the if, loop...
  101. HRESULT hres;
  102. if (lTotalTableNumber > 0)
  103. {
  104. #ifdef DEBUG
  105. TracePrintf("Info: number of tables = %d\n",lTotalTableNumber);
  106. #endif
  107. INFCONTEXT lTableContext;
  108. // if <>0 do a loop on the tables
  109. BOOL bOK = SetupFindFirstLineW(
  110. hINF,
  111. TABLE_SECTION,
  112. NULL,
  113. &lTableContext
  114. );
  115. for (
  116. LONG lTableCounter = 0;
  117. lTableCounter < lTotalTableNumber;
  118. lTableCounter++
  119. )
  120. {
  121. // read the Table name in the Tables section
  122. WCHAR lTableName[SIZELINEMAX];
  123. bOK = SetupGetLineTextW(
  124. &lTableContext,
  125. NULL,
  126. NULL,
  127. NULL,
  128. lTableName,
  129. SIZELINEMAX,
  130. NULL
  131. );
  132. // fetch the next line's context
  133. if (!bOK)
  134. {
  135. g_FatalError = true;
  136. bError = true;
  137. break;
  138. }
  139. // Rowset pointer
  140. CComPtr<IRowset> lpRowset;
  141. //////////////////////
  142. // create one rowset
  143. //////////////////////
  144. hres = Database.InitializeRowset(lTableName, &lpRowset);
  145. if (FAILED(hres))
  146. {
  147. g_FatalError = true;
  148. bError = true;
  149. break;
  150. }
  151. else
  152. {
  153. // create the simpletable
  154. CSimpleTableEx lSimpleTable;
  155. lSimpleTable.Attach(lpRowset);
  156. lSimpleTable.MoveFirst();
  157. //////////////////////////////////////////////////////
  158. // now one table and all its columns are well known.
  159. // empty database assumed
  160. // process the rows
  161. //////////////////////////////////////////////////////
  162. hres = ProcessAllRows(
  163. hINF,
  164. lSimpleTable,
  165. lTableName
  166. );
  167. if (FAILED(hres))
  168. {
  169. // process rows should not fail, even if no rows are read
  170. bError = true;
  171. g_FatalError = true;
  172. }
  173. }
  174. //////////////////////////////////////////////////////
  175. // Read the next table's name (if any)
  176. //////////////////////////////////////////////////////
  177. bOK = SetupFindNextLine(
  178. &lTableContext,
  179. &lTableContext
  180. );
  181. if (!bOK)
  182. {
  183. if ((lTableCounter + 1) < lTotalTableNumber)
  184. {
  185. // find next line should not crash. fatal error
  186. g_FatalError = true;
  187. bError = true;
  188. break;
  189. }
  190. break;
  191. } //end of tables
  192. }
  193. }
  194. else
  195. {// no tables: do nothing
  196. TracePrintf("Info: No [tables] section in the inf file\n");
  197. // bError = true;
  198. }
  199. if (bError)
  200. {
  201. LPVOID lpMsgBuf;
  202. FormatMessageW(
  203. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  204. FORMAT_MESSAGE_FROM_SYSTEM |
  205. FORMAT_MESSAGE_IGNORE_INSERTS,
  206. NULL,
  207. GetLastError(),
  208. // Default language
  209. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  210. (LPWSTR) &lpMsgBuf,
  211. 0,
  212. NULL
  213. );
  214. // Display the string.
  215. TracePrintf("Error: %S",lpMsgBuf);
  216. // Free the buffer.
  217. LocalFree( lpMsgBuf );
  218. hres = E_FAIL;
  219. }
  220. return hres;
  221. }
  222. //////////////////////////////////////////////////////////////////////////////
  223. //
  224. // ProcessAllRows
  225. //
  226. //////////////////////////////////////////////////////////////////////////////
  227. HRESULT ProcessAllRows(
  228. const HINF& hINF,
  229. CSimpleTableEx& pSimpleTable,
  230. const WCHAR* pTableName
  231. )
  232. {
  233. _ASSERTE(pTableName != NULL);
  234. ////////////////////
  235. // process the rows.
  236. ////////////////////
  237. wstring lwsRowSection;
  238. lwsRowSection += pTableName;
  239. LONG lRowCounter = 1;
  240. INFCONTEXT lRowContext;
  241. #ifdef DEBUG
  242. TracePrintf("Info: %S",lwsRowSection.c_str());
  243. #endif
  244. ////////////////////////////////////////////////////
  245. // if <>0 do a loop on the lines (ie row names)
  246. ////////////////////////////////////////////////////
  247. BOOL bOK = SetupFindFirstLineW(
  248. hINF,
  249. // section in which to find a line
  250. lwsRowSection.c_str(),
  251. NULL, // optional, key to search for
  252. &lRowContext // context of the found line
  253. );
  254. HRESULT hres = S_OK;
  255. if (!bOK)
  256. {
  257. //no such section (end of section = end of rows)
  258. }
  259. else
  260. {
  261. LONG lTotalLinesNumber = 0; //safer
  262. //////////////////////////////////////////////////////
  263. // Get the Number of lines in that section. (& check)
  264. //////////////////////////////////////////////////////
  265. lTotalLinesNumber = SetupGetLineCountW(
  266. hINF, // handle to the INF file
  267. // the section in which to count lines
  268. lwsRowSection.c_str()
  269. );
  270. //////////////////////////////
  271. // Read eerything (loop)
  272. //////////////////////////////
  273. for (
  274. LONG lLinesCounter = 0;
  275. lLinesCounter < lTotalLinesNumber;
  276. lLinesCounter++
  277. )
  278. {
  279. #ifdef DEBUG
  280. TracePrintf("Info: for loop: %d", lLinesCounter);
  281. #endif
  282. ///////////////////////////////////////////////
  283. // read the Table name in the Tables section
  284. ///////////////////////////////////////////////
  285. WCHAR lLineName[SIZELINEMAX];
  286. bOK = SetupGetLineTextW(
  287. &lRowContext,
  288. NULL,
  289. NULL,
  290. NULL,
  291. lLineName,
  292. SIZELINEMAX,
  293. NULL
  294. );
  295. if (!bOK)
  296. {
  297. g_FatalError = true;
  298. TracePrintf("Error: SetupGetLineText Failed "
  299. "in ProcessAllRows");
  300. }
  301. else //everything is ok, process the corresponding row
  302. {
  303. ///////////////////////
  304. // process the rows
  305. ///////////////////////
  306. hres = ProcessOneRow(
  307. hINF,
  308. pSimpleTable,
  309. lLineName
  310. );
  311. if (FAILED(hres)) { g_FatalError = true; }
  312. }
  313. //////////////////////////////////
  314. // fetch the next line's context
  315. //////////////////////////////////
  316. bOK = SetupFindNextLine(
  317. // starting context in an INF file
  318. &lRowContext,
  319. // context of the next line
  320. &lRowContext
  321. );
  322. if (!bOK)
  323. {
  324. ////////////////////////////////////////////////
  325. // end of the lines
  326. // compare the counter to the max to make sure
  327. // that last line is ok
  328. ////////////////////////////////////////////////
  329. if((lLinesCounter + 1) < lTotalLinesNumber)
  330. {
  331. // too early
  332. g_FatalError = true;
  333. TracePrintf("Error: FindNext Line failed."
  334. "Not enough lines in the section %S",
  335. lwsRowSection.c_str());
  336. }
  337. }
  338. }
  339. }
  340. return hres;
  341. }
  342. //////////////////////////////////////////////////////////////////////////////
  343. //
  344. // ProcessOneRow
  345. //
  346. //////////////////////////////////////////////////////////////////////////////
  347. HRESULT
  348. WINAPI
  349. ProcessOneRow(
  350. HINF inf,
  351. CSimpleTableEx& table,
  352. PCWSTR rowName
  353. )
  354. {
  355. // Iterate through the columns in the database and see if the INF file
  356. // specifies a value for each column.
  357. for (DBORDINAL i = 0; i < table.GetColumnCount(); ++i)
  358. {
  359. // First try with a stack-based buffer.
  360. WCHAR buffer[1024];
  361. PWCHAR text = buffer;
  362. DWORD textSize = sizeof(buffer) / sizeof(buffer[0]);
  363. BOOL success = SetupGetLineTextW(
  364. NULL,
  365. inf,
  366. rowName,
  367. table.GetColumnName(i),
  368. text,
  369. textSize,
  370. &textSize
  371. );
  372. DWORD error = success ? NO_ERROR : GetLastError();
  373. if (error == ERROR_INSUFFICIENT_BUFFER)
  374. {
  375. // The stack-based buffer wasn't big enough, so allocate one on the
  376. // heap ...
  377. text = (PWCHAR)HeapAlloc(
  378. GetProcessHeap(),
  379. 0,
  380. textSize * sizeof(WCHAR)
  381. );
  382. if (!text) { return E_OUTOFMEMORY; }
  383. // ... and try again.
  384. success = SetupGetLineTextW(
  385. NULL,
  386. inf,
  387. rowName,
  388. table.GetColumnName(i),
  389. text,
  390. textSize,
  391. &textSize
  392. );
  393. error = success ? NO_ERROR : GetLastError();
  394. }
  395. // If we successfully retrieved the line text AND it has at least one
  396. // character ...
  397. if (!error && textSize > 1)
  398. {
  399. // ... then process based on the column data type.
  400. switch (table.GetColumnType(i))
  401. {
  402. case DBTYPE_I4:
  403. {
  404. table.SetValue(i, _wtol(text));
  405. break;
  406. }
  407. case DBTYPE_WSTR:
  408. {
  409. table.SetValue(i, text);
  410. break;
  411. }
  412. case DBTYPE_BOOL:
  413. {
  414. table.SetValue(i, (VARIANT_BOOL)_wtol(text));
  415. break;
  416. }
  417. }
  418. }
  419. // Free the heap-based buffer if necessary.
  420. if (text != buffer) { HeapFree(GetProcessHeap(), 0, text); }
  421. switch (error)
  422. {
  423. case NO_ERROR:
  424. // Everything succeeded.
  425. case ERROR_INVALID_PARAMETER:
  426. // SETUPAPI didn't like the column name.
  427. case ERROR_LINE_NOT_FOUND:
  428. // The INF file didn't provide a value for this column.
  429. break;
  430. default:
  431. // Something went wrong.
  432. return HRESULT_FROM_WIN32(error);
  433. }
  434. }
  435. // All the columns are populated, so insert the row.
  436. return table.Insert();
  437. }