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.

3059 lines
90 KiB

  1. /*****************************************************************************\
  2. * MODULE: geninf.c
  3. *
  4. * The module contains routines for generating a setup INF file.
  5. *
  6. *
  7. * Needed Work
  8. * -----------
  9. * 1) look at reducing the item-list size to contiguous buffers.
  10. *
  11. *
  12. * Copyright (C) 1996-1997 Microsoft Corporation
  13. * Copyright (C) 1996-1997 Hewlett Packard
  14. *
  15. * History:
  16. * 22-Nov-1996 HWP-Guys Created.
  17. *
  18. \*****************************************************************************/
  19. #include "pch.h"
  20. /******************************************************************************
  21. ** Defines
  22. ******************************************************************************/
  23. /******************************************************************************
  24. ** Define - INF_CAT_INCREMENT
  25. ** Description - The increment in size between cat file increments
  26. ******************************************************************************/
  27. #if (!defined(INF_CAT_INCREMENT))
  28. #define INF_CAT_INCREMENT 16
  29. #endif
  30. /*****************************************************************************\
  31. * inf_NextStr (Local Routine)
  32. *
  33. * Proceeds to the next string in a section-list.
  34. *
  35. \*****************************************************************************/
  36. _inline LPTSTR inf_NextStr(
  37. LPTSTR lpszStr)
  38. {
  39. return (lpszStr + (lstrlen(lpszStr) + 1));
  40. }
  41. /*****************************************************************************\
  42. * inf_WriteInfSct (Local Routine)
  43. *
  44. * Writes a section to the 9x-generated-inf-file.
  45. *
  46. \*****************************************************************************/
  47. _inline BOOL inf_WriteInfSct(
  48. HANDLE hFile,
  49. LPCSTR lpszSct)
  50. {
  51. DWORD cbWr;
  52. return WriteFile(hFile, (LPBYTE)lpszSct, lstrlenA(lpszSct), &cbWr, NULL);
  53. }
  54. /*****************************************************************************\
  55. * inf_GetInfMfgKey (Local Routine)
  56. *
  57. * Returns the first word of the drvname which is used to denote mfg-section.
  58. *
  59. \*****************************************************************************/
  60. LPSTR inf_GetInfMfgKey(
  61. LPCTSTR lpszDrvName)
  62. {
  63. LPTSTR lpszTmp;
  64. LPSTR lpszMfg = NULL;
  65. if (lpszTmp = genFindChar((LPTSTR)lpszDrvName, TEXT(' '))) {
  66. *lpszTmp = TEXT('\0');
  67. lpszMfg = genMBFromTC(lpszDrvName);
  68. *lpszTmp = TEXT(' ');
  69. } else {
  70. lpszMfg = genMBFromTC(lpszDrvName);
  71. }
  72. return lpszMfg;
  73. }
  74. /*****************************************************************************\
  75. * inf_WriteInfMfg (Local Routine)
  76. *
  77. * Writes the manufacturer section.
  78. *
  79. \*****************************************************************************/
  80. _inline BOOL inf_WriteInfMfg(
  81. HANDLE hFile,
  82. LPCTSTR lpszDrvName)
  83. {
  84. DWORD cbWr;
  85. LPSTR lpszMfg;
  86. LPSTR lpszBuf;
  87. DWORD cbSize;
  88. DWORD cch;
  89. BOOL bRet = FALSE;
  90. if (lpszMfg = inf_GetInfMfgKey(lpszDrvName)) {
  91. cbSize = lstrlenA(g_szInfSctMfg) + lstrlenA(lpszMfg) + 1;
  92. if (lpszBuf = (LPSTR)genGAlloc(cbSize)) {
  93. cch = wsprintfA(lpszBuf, g_szInfSctMfg, lpszMfg);
  94. bRet = WriteFile(hFile, lpszBuf, cch, &cbWr, NULL);
  95. genGFree(lpszBuf, cbSize);
  96. }
  97. genGFree(lpszMfg, genGSize(lpszMfg));
  98. }
  99. return bRet;
  100. }
  101. /*****************************************************************************\
  102. * inf_WriteInfDrv (Local Routine)
  103. *
  104. * Writes the driver-section.
  105. *
  106. \*****************************************************************************/
  107. _inline BOOL inf_WriteInfDrv(
  108. HANDLE hFile,
  109. LPCTSTR lpszDrvName,
  110. LPCTSTR lpszDrvPath)
  111. {
  112. DWORD cbWr;
  113. LPTSTR lpszTmp;
  114. LPSTR lpszName;
  115. LPSTR lpszFile;
  116. LPSTR lpszMfg;
  117. LPSTR lpszBuf;
  118. DWORD cbSize;
  119. DWORD cch;
  120. BOOL bRet = FALSE;
  121. if (lpszMfg = inf_GetInfMfgKey(lpszDrvName)) {
  122. if (lpszTmp = genFindRChar((LPTSTR)lpszDrvPath, TEXT('\\'))) {
  123. if (lpszFile = genMBFromTC(++lpszTmp)) {
  124. if (lpszName = genMBFromTC(lpszDrvName)) {
  125. cbSize = lstrlenA(g_szInfSctDrv) +
  126. lstrlenA(lpszName) +
  127. lstrlenA(lpszFile) +
  128. lstrlenA(lpszMfg) +
  129. 1;
  130. if (lpszBuf = (LPSTR)genGAlloc(cbSize)) {
  131. cch = wsprintfA(lpszBuf, g_szInfSctDrv, lpszMfg, lpszName, lpszFile);
  132. bRet = WriteFile(hFile, lpszBuf, cch, &cbWr, NULL);
  133. genGFree(lpszBuf, cbSize);
  134. }
  135. genGFree(lpszName, genGSize(lpszName));
  136. }
  137. genGFree(lpszFile, genGSize(lpszFile));
  138. }
  139. }
  140. genGFree(lpszMfg, genGSize(lpszMfg));
  141. }
  142. return bRet;
  143. }
  144. /*****************************************************************************\
  145. * inf_WriteInfIns (Local Routine)
  146. *
  147. * Writes the install-section.
  148. *
  149. \*****************************************************************************/
  150. _inline BOOL inf_WriteInfIns(
  151. HANDLE hFile,
  152. LPCTSTR lpszDrvPath)
  153. {
  154. DWORD cbWr;
  155. LPTSTR lpszTmp;
  156. LPSTR lpszFile;
  157. LPSTR lpszBuf;
  158. DWORD cbSize;
  159. DWORD cch;
  160. BOOL bRet = FALSE;
  161. if (lpszTmp = genFindRChar((LPTSTR)lpszDrvPath, TEXT('\\'))) {
  162. if (lpszFile = genMBFromTC(++lpszTmp)) {
  163. cbSize = lstrlenA(g_szInfSctIns) +
  164. lstrlenA(lpszFile) +
  165. 1;
  166. if (lpszBuf = (LPSTR)genGAlloc(cbSize)) {
  167. cch = wsprintfA(lpszBuf, g_szInfSctIns, lpszFile);
  168. bRet = WriteFile(hFile, lpszBuf, cch, &cbWr, NULL);
  169. genGFree(lpszBuf, cbSize);
  170. }
  171. genGFree(lpszFile, genGSize(lpszFile));
  172. }
  173. }
  174. return bRet;
  175. }
  176. /*****************************************************************************\
  177. * inf_WrintInfDta (Local Routine)
  178. *
  179. * Writes the data-section.
  180. *
  181. \*****************************************************************************/
  182. _inline BOOL inf_WriteInfDta(
  183. HANDLE hFile,
  184. LPTSTR lpszDtaFile,
  185. LPTSTR lpszHlpFile)
  186. {
  187. DWORD cbWr;
  188. LPTSTR lpszDta;
  189. LPTSTR lpszHlp;
  190. LPSTR lpszIns;
  191. LPSTR lpszDtaName;
  192. LPSTR lpszHlpName;
  193. DWORD cbSize;
  194. DWORD cch;
  195. BOOL bRet = FALSE;
  196. if (lpszDta = genFindRChar(lpszDtaFile, TEXT('\\'))) {
  197. if (lpszHlp = genFindRChar(lpszHlpFile, TEXT('\\'))) {
  198. if (lpszDtaName = genMBFromTC(++lpszDta)) {
  199. if (lpszHlpName = genMBFromTC(++lpszHlp)) {
  200. cbSize = lstrlenA(g_szInfSctIns) +
  201. lstrlenA(lpszDtaName) +
  202. lstrlenA(lpszHlpName) +
  203. 1;
  204. if (lpszIns = (LPSTR)genGAlloc(cbSize)) {
  205. cch = wsprintfA(lpszIns, g_szInfSctDta, lpszDtaName, lpszHlpName);
  206. bRet = WriteFile(hFile, lpszIns, cch, &cbWr, NULL);
  207. genGFree(lpszIns, genGSize(lpszIns));
  208. }
  209. genGFree(lpszHlpName, genGSize(lpszHlpName));
  210. }
  211. genGFree(lpszDtaName, genGSize(lpszDtaName));
  212. }
  213. }
  214. }
  215. return bRet;
  216. }
  217. /*****************************************************************************\
  218. * inf_WriteInfFiles (Local Routine)
  219. *
  220. * Writes the file-list section.
  221. *
  222. \*****************************************************************************/
  223. BOOL inf_WriteInfFiles(
  224. HANDLE hFile,
  225. LPTSTR lpaszFiles)
  226. {
  227. LPTSTR lpszPtr;
  228. LPTSTR lpszFile;
  229. LPSTR lpszItm;
  230. DWORD cbWr;
  231. DWORD cch;
  232. CHAR szBuf[255];
  233. BOOL bRet = FALSE;
  234. // Write out the CopyFiles Section. This will take the
  235. // dependent files list and alter it to delminate the
  236. // strings with commas.
  237. //
  238. if ((lpszPtr = lpaszFiles) && *lpszPtr) {
  239. WriteFile(hFile, g_szInfSctFil, lstrlenA(g_szInfSctFil), &cbWr, NULL);
  240. while (*lpszPtr) {
  241. if (lpszFile = genFindRChar(lpszPtr, TEXT('\\'))) {
  242. if (lpszItm = genMBFromTC(++lpszFile)) {
  243. cch = wsprintfA(szBuf, "%s\r\n", lpszItm);
  244. WriteFile(hFile, szBuf, cch, &cbWr, NULL);
  245. bRet = TRUE;
  246. genGFree(lpszItm, genGSize(lpszItm));
  247. }
  248. }
  249. lpszPtr = inf_NextStr(lpszPtr);
  250. }
  251. }
  252. return bRet;
  253. }
  254. /*****************************************************************************\
  255. * inf_WriteInfSDF (Local Routine)
  256. *
  257. * Writes the file-list section.
  258. *
  259. \*****************************************************************************/
  260. BOOL inf_WriteInfSDF(
  261. HANDLE hFile,
  262. LPCTSTR lpaszFiles)
  263. {
  264. LPTSTR lpszPtr;
  265. LPTSTR lpszFile;
  266. LPSTR lpszItm;
  267. DWORD cbWr;
  268. DWORD cch;
  269. CHAR szBuf[255];
  270. BOOL bRet = FALSE;
  271. // Write out the CopyFiles Section. This will take the
  272. // dependent files list and alter it to delminate the
  273. // strings with commas.
  274. //
  275. if ((lpszPtr = (LPTSTR)lpaszFiles) && *lpszPtr) {
  276. WriteFile(hFile, g_szInfSctSDF, lstrlenA(g_szInfSctSDF), &cbWr, NULL);
  277. while (*lpszPtr) {
  278. if (lpszFile = genFindRChar(lpszPtr, TEXT('\\'))) {
  279. if (lpszItm = genMBFromTC(++lpszFile)) {
  280. cch = wsprintfA(szBuf, "%hs = 1\r\n", lpszItm);
  281. WriteFile(hFile, szBuf, cch, &cbWr, NULL);
  282. bRet = TRUE;
  283. genGFree(lpszItm, genGSize(lpszItm));
  284. }
  285. }
  286. lpszPtr = inf_NextStr(lpszPtr);
  287. }
  288. }
  289. return bRet;
  290. }
  291. /*****************************************************************************\
  292. * inf_BuildW9XInf (Local Routine)
  293. *
  294. *
  295. \*****************************************************************************/
  296. LPTSTR inf_BuildW9XInf(
  297. LPINFINFO lpInf,
  298. LPCTSTR lpszDrvName,
  299. LPDRIVER_INFO_3 lpdi3)
  300. {
  301. LPTSTR lpszInfFile;
  302. HANDLE hFile;
  303. LPTSTR lpszInfName = NULL;
  304. if (lpszInfFile = genBuildFileName(lpInf->lpszDstPath, lpInf->lpszDstName, g_szDotInf)) {
  305. hFile = CreateFile(lpszInfFile,
  306. GENERIC_READ | GENERIC_WRITE,
  307. 0,
  308. NULL,
  309. CREATE_ALWAYS,
  310. FILE_ATTRIBUTE_NORMAL,
  311. NULL);
  312. if (hFile && (hFile != INVALID_HANDLE_VALUE)) {
  313. inf_WriteInfSct(hFile, (LPCSTR)g_szInfSctVer);
  314. inf_WriteInfMfg(hFile, lpszDrvName);
  315. inf_WriteInfDrv(hFile, lpszDrvName, (LPCTSTR)lpdi3->pDriverPath);
  316. inf_WriteInfIns(hFile, (LPCTSTR)lpdi3->pDriverPath);
  317. inf_WriteInfDta(hFile, lpdi3->pDataFile, lpdi3->pHelpFile);
  318. inf_WriteInfSct(hFile, (LPSTR)g_szInfSctSDN);
  319. inf_WriteInfSDF(hFile, (LPCTSTR)lpdi3->pDependentFiles);
  320. inf_WriteInfFiles(hFile, lpdi3->pDependentFiles);
  321. inf_WriteInfSct(hFile, g_szInfSctStr);
  322. lpszInfName = lpszInfFile;
  323. CloseHandle(hFile);
  324. } else {
  325. infSetError(lpInf,GetLastError());
  326. genGFree(lpszInfFile, genGSize(lpszInfFile));
  327. }
  328. }
  329. return lpszInfName;
  330. }
  331. /*****************************************************************************\
  332. * inf_GetW9XInfo (Local Routine)
  333. *
  334. * Retrieves the files (drivers) for a 9x client. This essentially takes the
  335. * files and calls a routine to build an INF that the client will use to
  336. * install the drivers.
  337. *
  338. \*****************************************************************************/
  339. LPDRIVER_INFO_3 inf_GetW9XInfo(
  340. LPINFINFO lpInf,
  341. LPTSTR* ppszDrvName)
  342. {
  343. HANDLE hPrinter;
  344. DWORD cbBuf;
  345. DWORD cbNeed;
  346. LPDRIVER_INFO_1 lpdi1;
  347. LPDRIVER_INFO_3 lpdi3 = NULL;
  348. *ppszDrvName = NULL;
  349. if (OpenPrinter(lpInf->lpszFrnName, &hPrinter, NULL)) {
  350. // First let's see how big our buffer will need to
  351. // be in order to hold the printer-driver-name-information.
  352. //
  353. cbBuf = 0;
  354. GetPrinterDriver(hPrinter, (LPTSTR)g_szEnvW9X, 1, NULL, 0, &cbBuf);
  355. // Allocate storage for holding the driver-info structure.
  356. //
  357. if (cbBuf && (lpdi1 = (LPDRIVER_INFO_1)genGAlloc(cbBuf))) {
  358. if (GetPrinterDriver(hPrinter, (LPTSTR)g_szEnvW9X, 1, (LPBYTE)lpdi1, cbBuf, &cbNeed)) {
  359. // Get size to hold the printer-driver-files-information.
  360. //
  361. cbBuf = 0;
  362. GetPrinterDriver(hPrinter, (LPTSTR)g_szEnvW9X, 3, NULL, 0, &cbBuf);
  363. if (cbBuf && (lpdi3 = (LPDRIVER_INFO_3)genGAlloc(cbBuf))) {
  364. if (GetPrinterDriver(hPrinter, (LPTSTR)g_szEnvW9X, 3, (LPBYTE)lpdi3, cbBuf, &cbNeed)) {
  365. *ppszDrvName = genGAllocStr(lpdi1->pName);
  366. } else {
  367. genGFree(lpdi3, genGSize(lpdi3));
  368. lpdi3 = NULL;
  369. }
  370. }
  371. }
  372. genGFree(lpdi1, genGSize(lpdi1));
  373. }
  374. ClosePrinter(hPrinter);
  375. }
  376. if (lpdi3 == NULL)
  377. infSetError(lpInf,GetLastError());
  378. return lpdi3;
  379. }
  380. /*****************************************************************************\
  381. * inf_GetW9XInf (Local Routine)
  382. *
  383. *
  384. \*****************************************************************************/
  385. LPTSTR inf_GetW9XInf(
  386. LPINFINFO lpInf)
  387. {
  388. LPDRIVER_INFO_3 lpdi3;
  389. LPTSTR lpszDrvName;
  390. LPTSTR lpszInfFile = NULL;
  391. if (lpdi3 = inf_GetW9XInfo(lpInf, &lpszDrvName)) {
  392. lpszInfFile = inf_BuildW9XInf(lpInf, lpszDrvName, lpdi3);
  393. genGFree(lpszDrvName, genGSize(lpszDrvName));
  394. genGFree(lpdi3, genGSize(lpdi3));
  395. }
  396. return lpszInfFile;
  397. }
  398. /*****************************************************************************\
  399. * inf_GetIdx (Local Routine)
  400. *
  401. * Quick wrapper which returns the line in the INF file where the section/key
  402. * resides.
  403. *
  404. \*****************************************************************************/
  405. _inline BOOL inf_GetIdx(
  406. LPCTSTR lpszSct,
  407. LPCTSTR lpszKey,
  408. HINF hInfObj,
  409. PINFCONTEXT pic)
  410. {
  411. return SetupFindFirstLine(hInfObj, lpszSct, lpszKey, pic);
  412. }
  413. /*****************************************************************************\
  414. * inf_GetInfInfoFileName (Local Routine)
  415. *
  416. * Retreive the filename from the INF-INFO index.
  417. *
  418. \*****************************************************************************/
  419. LPTSTR inf_GetInfInfoFileName(
  420. PSP_INF_INFORMATION pii,
  421. DWORD idx)
  422. {
  423. DWORD cbSize, dwBufferSize;
  424. LPTSTR lpszInfFile;
  425. if (SetupQueryInfFileInformation(pii, idx, NULL, 0, &cbSize)) {
  426. dwBufferSize = (cbSize + 1) * sizeof(TCHAR);
  427. if (lpszInfFile = (LPTSTR)genGAlloc(dwBufferSize)) {
  428. if (SetupQueryInfFileInformation(pii, idx, lpszInfFile, cbSize, NULL))
  429. return lpszInfFile;
  430. genGFree(lpszInfFile, genGSize(lpszInfFile));
  431. }
  432. }
  433. return NULL;
  434. }
  435. /*****************************************************************************\
  436. * inf_GetInfInfo (Local Routine)
  437. *
  438. * Returns a pointer to an INF-INFO struct.
  439. *
  440. \*****************************************************************************/
  441. PSP_INF_INFORMATION inf_GetInfInfo(
  442. HINF hInfObj)
  443. {
  444. DWORD cbSize;
  445. BOOL bRet;
  446. PSP_INF_INFORMATION pii;
  447. cbSize = 0;
  448. bRet = SetupGetInfInformation(hInfObj,
  449. INFINFO_INF_SPEC_IS_HINF,
  450. NULL,
  451. 0,
  452. &cbSize);
  453. if (bRet && cbSize && (pii = (PSP_INF_INFORMATION)genGAlloc(cbSize))) {
  454. bRet = SetupGetInfInformation(hInfObj,
  455. INFINFO_INF_SPEC_IS_HINF,
  456. pii,
  457. cbSize,
  458. NULL);
  459. if (bRet)
  460. return pii;
  461. genGFree(pii, genGSize(pii));
  462. }
  463. return NULL;
  464. }
  465. /*****************************************************************************\
  466. * inf_AddItem (Local Routine)
  467. *
  468. * Add an INF file-item to the list. If adding the new item exceeds the
  469. * available space, then reallocate the memory and return a pointer to the
  470. * new block.
  471. *
  472. \*****************************************************************************/
  473. LPINFITEMINFO inf_AddItem(
  474. LPINFITEMINFO lpII,
  475. LPCTSTR lpszItmName,
  476. LPCTSTR lpszItmPath,
  477. BOOL bInfFile)
  478. {
  479. DWORD idx;
  480. DWORD dwOldSize;
  481. DWORD dwNewSize;
  482. LPINFITEMINFO lpNewII;
  483. idx = lpII->dwCount++;
  484. if ((lpII->dwCount % INF_ITEM_BLOCK) == 0) {
  485. dwOldSize = genGSize(lpII);
  486. dwNewSize = dwOldSize + (sizeof(INFITEM) * INF_ITEM_BLOCK);
  487. // If we can't realloc the memory, then we are going to free up
  488. // our existing block and return NULL. In our implementation, if
  489. // we can't add items, we need to fail-out.
  490. //
  491. lpNewII = (LPINFITEMINFO)genGRealloc(lpII, dwOldSize, dwNewSize);
  492. if (lpNewII == NULL) {
  493. genGFree(lpII, genGSize(lpII));
  494. DBGMSG(DBG_ERROR, ("inf_AddItem : Out of memory"));
  495. return NULL;
  496. }
  497. lpII = lpNewII;
  498. }
  499. // Add the item to the list. The (szOrd) parameter is
  500. // filled in during the writing of the source-disk-files
  501. // section. The Ord indicates which directory the file
  502. // is located in the LAYOUT.INF.
  503. //
  504. lpII->aItems[idx].bInf = bInfFile;
  505. lstrcpyn(lpII->aItems[idx].szName, lpszItmName, INF_MIN_BUFFER);
  506. lstrcpyn(lpII->aItems[idx].szPath, lpszItmPath, MAX_PATH);
  507. // Set the SOURCE name to NULL by default, if we find a source that has a different name
  508. // to the target, we'll set it to the original name
  509. lpII->aItems[idx].szSource[0] = _TEXT('\0');
  510. return lpII;
  511. }
  512. /*****************************************************************************\
  513. * inf_GetTextLine (Local Routine)
  514. *
  515. * Quick wrapper which returns the text-value of the line specified in the
  516. * inf-object.
  517. *
  518. \*****************************************************************************/
  519. LPTSTR inf_GetTextLine(
  520. HINF hInfObj,
  521. PINFCONTEXT pic)
  522. {
  523. BOOL bOK;
  524. DWORD cbSize;
  525. LPTSTR lpszTxt;
  526. cbSize = 0;
  527. if (SetupGetLineText(pic, hInfObj, NULL, NULL, NULL, 0, &cbSize)) {
  528. if (cbSize) {
  529. cbSize *= sizeof(TCHAR);
  530. if (lpszTxt = (LPTSTR)genGAlloc(cbSize)) {
  531. bOK = SetupGetLineText(pic,
  532. hInfObj,
  533. NULL,
  534. NULL,
  535. lpszTxt,
  536. cbSize,
  537. NULL);
  538. if (bOK)
  539. return lpszTxt;
  540. genGFree(lpszTxt, cbSize);
  541. }
  542. }
  543. }
  544. return NULL;
  545. }
  546. /*****************************************************************************\
  547. * inf_GetText (Local Routine)
  548. *
  549. * Quick wrapper which returns the text-value of the line specified in the
  550. * inf-object. This only returns the first string if the line contains
  551. * a field-list.
  552. *
  553. \*****************************************************************************/
  554. LPTSTR inf_GetText(
  555. HINF hInfObj,
  556. PINFCONTEXT pic)
  557. {
  558. DWORD cbSize;
  559. LPTSTR lpszTxt;
  560. cbSize = 0;
  561. if (SetupGetStringField(pic, 1, NULL, 0, &cbSize)) {
  562. if (cbSize) {
  563. cbSize *= sizeof(TCHAR);
  564. if (lpszTxt = (LPTSTR)genGAlloc(cbSize)) {
  565. if (SetupGetStringField(pic, 1, lpszTxt, cbSize, NULL))
  566. return lpszTxt;
  567. genGFree(lpszTxt, cbSize);
  568. }
  569. }
  570. }
  571. return NULL;
  572. }
  573. /******************************************************************************************
  574. ** inf_ScanSection (local routine)
  575. **
  576. ** Run through all of the members of a section that match a particular Key (possibly NULL)
  577. ** Supply the callback routine we receive with the MultiString that we get from scanning
  578. ** the section.
  579. ******************************************************************************************/
  580. BOOL inf_ScanSection(HINF hInf, // The handle to the inf file we are searching
  581. LPCTSTR lpszSection, // The section name we are scanning from
  582. LPCTSTR lpszKey, // The key to search the sections for
  583. LPVOID pCookie, // The data about the inf that we have picked up
  584. INFSCANPROC pFn // The enumeration function
  585. ) {
  586. ASSERT(pFn);
  587. DWORD dwFieldSize = MAX_PATH;
  588. LPTSTR pmszFields = (LPTSTR)genGAlloc(sizeof(TCHAR)*dwFieldSize);
  589. INFCONTEXT Context; // This is the search context we use
  590. BOOL bRet = pmszFields && SetupFindFirstLine(hInf, lpszSection, lpszKey , &Context);
  591. BOOL bScan = bRet;
  592. while(bScan) {
  593. DWORD dwRequiredSize;
  594. // Get the Scan Line from the context
  595. bScan = SetupGetMultiSzField( &Context, 1, pmszFields, dwFieldSize, &dwRequiredSize);
  596. if (!bScan && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  597. LPTSTR pmszTempFields = (LPTSTR)genGRealloc( pmszFields,
  598. sizeof(TCHAR) * dwFieldSize,
  599. sizeof(TCHAR) * dwRequiredSize );
  600. if (pmszTempFields) {
  601. pmszFields = pmszTempFields;
  602. dwFieldSize = dwRequiredSize;
  603. bRet = bScan = SetupGetMultiSzField( &Context, 1, pmszFields, dwFieldSize, &dwRequiredSize );
  604. } else
  605. bRet = bScan = FALSE;
  606. }
  607. // We find all the lpszKey Keys and then Pass the Fields through to the Enum Function
  608. if (bScan)
  609. bScan = bRet = (*pFn)( hInf, pmszFields, pCookie);
  610. if (bScan)
  611. bScan = SetupFindNextMatchLine( &Context, lpszKey, &Context );
  612. }
  613. if (pmszFields)
  614. genGFree( pmszFields, dwFieldSize * sizeof(TCHAR) );
  615. return bRet;
  616. }
  617. /******************************************************************************
  618. ** Structure - ENUMMFGS
  619. **
  620. ** This structure is used to pass info up to the enumerator function
  621. ** (inf_EnumMfgSections) and return the install sections
  622. *******************************************************************************/
  623. typedef struct _EnumMfgs {
  624. LPCTSTR lpszDrv; // The driver to find
  625. LPTSTR lpszIns; // The install section in which it is found
  626. inline _EnumMfgs(LPCTSTR lpszDrv) : lpszDrv(lpszDrv), lpszIns(NULL) {}
  627. } ENUMMFGS;
  628. typedef ENUMMFGS *PENUMMFGS;
  629. /******************************************************************************
  630. ** inf_EnumMfgSections
  631. **
  632. ** This functions is called for every manufacturer install section in an inf
  633. ** file (there may be more than one). For each one it checks to see whether the
  634. ** required driver is inside the install section. If it is, it sets the return
  635. ** string to the install section for the driver. (Subsequent calls will be ignored).
  636. ******************************************************************************/
  637. BOOL inf_EnumMfgSections(HINF hInf, LPCTSTR lpMfgSec, LPVOID pCookie) {
  638. ASSERT(pCookie); // Should not be NULL
  639. PENUMMFGS pMfgs = (PENUMMFGS)pCookie;
  640. if (lpMfgSec && pMfgs->lpszIns == NULL) { // No matching driver has been found yet
  641. INFCONTEXT Context; // This context is used to get the install section
  642. if ( inf_GetIdx( lpMfgSec, pMfgs->lpszDrv, hInf, &Context) ) {
  643. pMfgs->lpszIns = inf_GetText( hInf, &Context );
  644. }
  645. }
  646. return TRUE;
  647. }
  648. /*****************************************************************************\
  649. * inf_GetInsVal (Local Routine)
  650. *
  651. * Looks for the line indicated by section/key, and returns the text-string
  652. * for this line. This also returns an index to the line in the inf-file.
  653. *
  654. \*****************************************************************************/
  655. LPTSTR inf_GetInsVal(
  656. LPCTSTR lpszMfg,
  657. LPCTSTR lpszDrv,
  658. HINF hInfObj)
  659. {
  660. ENUMMFGS EnumMfgs(lpszDrv);
  661. LPTSTR lpszIns = NULL;
  662. if (inf_ScanSection( hInfObj, g_szMfgName, lpszMfg, (LPVOID)&EnumMfgs, inf_EnumMfgSections) )
  663. lpszIns = EnumMfgs.lpszIns;
  664. return lpszIns;
  665. }
  666. /*****************************************************************************\
  667. * inf_RealSect (Local Routine)
  668. *
  669. * Looks for the real-section-mapping. Some sections could be [.platform]
  670. * specific, so we should be able to take in the section-name and
  671. * create a real key.
  672. *
  673. \*****************************************************************************/
  674. LPTSTR inf_GetRealSect(
  675. LPINFINFO lpInf,
  676. LPCTSTR lpszKey)
  677. {
  678. BOOL bRet;
  679. DWORD cbSize;
  680. LPTSTR lpszSect;
  681. if (SetupSetPlatformPathOverride(genStrCliOverride(lpInf->idxPlt))) {
  682. cbSize = 0;
  683. bRet = SetupDiGetActualSectionToInstall(lpInf->hInfObj,
  684. lpszKey,
  685. NULL,
  686. 0,
  687. &cbSize,
  688. NULL);
  689. if (bRet && cbSize) {
  690. if (lpszSect = (LPTSTR)genGAlloc(cbSize)) {
  691. bRet = SetupDiGetActualSectionToInstall(lpInf->hInfObj,
  692. lpszKey,
  693. lpszSect,
  694. cbSize,
  695. NULL,
  696. NULL);
  697. if (bRet) {
  698. SetupSetPlatformPathOverride(NULL);
  699. return lpszSect;
  700. }
  701. genGFree(lpszSect, genGSize(lpszSect));
  702. }
  703. }
  704. SetupSetPlatformPathOverride(NULL);
  705. }
  706. return NULL;
  707. }
  708. /*****************************************************************************\
  709. * inf_GetInfFile (Local Routine)
  710. *
  711. * Return the name of the inf-file. This looks for the inf-file with the
  712. * identified (lpszSection)...if NULL is specified, the first (main) inf
  713. * file is returned.
  714. *
  715. \*****************************************************************************/
  716. LPTSTR inf_GetInfFile(
  717. HINF hInfObj,
  718. LPCTSTR lpszSct)
  719. {
  720. PSP_INF_INFORMATION pii;
  721. INFCONTEXT ic;
  722. LPTSTR lpszInfFile = NULL;
  723. if (lpszSct) {
  724. if (inf_GetIdx(lpszSct, NULL, hInfObj, &ic))
  725. lpszInfFile = inf_GetInfFile(ic.CurrentInf, NULL);
  726. } else {
  727. if (pii = inf_GetInfInfo(hInfObj)) {
  728. lpszInfFile = inf_GetInfInfoFileName(pii, 0);
  729. genGFree(pii, genGSize(pii));
  730. }
  731. }
  732. return lpszInfFile;
  733. }
  734. /*****************************************************************************\
  735. * inf_GetLayoutFile (Local Routine)
  736. *
  737. * Return the name of the Layout file.
  738. *
  739. \*****************************************************************************/
  740. LPTSTR inf_GetLayoutFile(
  741. HINF hInf )
  742. {
  743. LPTSTR lpszLayoutFile = NULL;
  744. INFCONTEXT INFContext;
  745. PINFCONTEXT pINFContext = &INFContext;
  746. DWORD dwBufferNeeded;
  747. // To get the source directories correct, we need to load all included INFs
  748. // separately. THen use their associated layout files.
  749. if ( SetupFindFirstLine( hInf, TEXT( "Version" ), TEXT( "LayoutFile" ), &INFContext ) )
  750. {
  751. // Find each INF and load it & it's LAYOUT files
  752. DWORD dwINFs = SetupGetFieldCount( &INFContext );
  753. if ( SetupGetStringField( &INFContext, 1, NULL, 0, &dwBufferNeeded ) )
  754. {
  755. if (lpszLayoutFile = (LPTSTR)genGAlloc( ( dwBufferNeeded * sizeof(TCHAR) ) )) {
  756. if ( SetupGetStringField( &INFContext, 1, lpszLayoutFile, ( dwBufferNeeded * sizeof(TCHAR) ), &dwBufferNeeded ) )
  757. return lpszLayoutFile;
  758. genGFree(lpszLayoutFile, genGSize(lpszLayoutFile));
  759. } // Allocated pszINFName
  760. } // Got the Field from the INF Line
  761. } // Found a Layout File
  762. return NULL;
  763. }
  764. /*****************************************************************************\
  765. * inf_GetSrcInf (Local Routine)
  766. *
  767. * Get the name of the src inf file given the printer friendly name. This
  768. * will return a name without the full-path to the inf-directory.
  769. *
  770. \*****************************************************************************/
  771. LPTSTR inf_GetSrcInf(
  772. LPINFINFO lpInf)
  773. {
  774. LPTSTR lpszRet = NULL;
  775. HMODULE hLib;
  776. PSETUPCREATE pSCreate;
  777. PSETUPDESTROY pSDelete;
  778. PSETUPGET pSGet;
  779. LPWSTR lpszF;
  780. HDEVINFO hDevInfo;
  781. WCHAR szTmp[MAX_PATH];
  782. DWORD cbSize = MAX_PATH;
  783. BOOL bGet;
  784. if (genIsWin9X(lpInf->idxPlt)) {
  785. lpszRet = inf_GetW9XInf(lpInf);
  786. } else {
  787. if (hLib = LoadLibraryFromSystem32(g_szNtPrintDll)) {
  788. if (pSCreate = (PSETUPCREATE)GetProcAddress(hLib, g_szSetupCreate)) {
  789. if (pSGet = (PSETUPGET)GetProcAddress(hLib, g_szSetupGet)) {
  790. if (pSDelete = (PSETUPDESTROY)GetProcAddress(hLib, g_szSetupDestroy)) {
  791. if (hDevInfo = (*pSCreate)(NULL)) {
  792. #ifdef UNICODE
  793. bGet = (*pSGet)(hDevInfo, lpInf->lpszFrnName, szTmp, &cbSize);
  794. if (bGet)
  795. lpszRet = genGAllocStr(szTmp);
  796. else
  797. infSetError(lpInf,GetLastError());
  798. #else
  799. if (lpszF = genWCFromMB(lpInf->lpszFrnName)) {
  800. bGet = (*pSGet)(hDevInfo, lpszF, szTmp, &cbSize);
  801. if (bGet)
  802. lpszRet = genMBFromWC(szTmp);
  803. genGFree(lpszF, genGSize(lpszF));
  804. }
  805. #endif
  806. (*pSDelete)(hDevInfo);
  807. }
  808. }
  809. }
  810. }
  811. FreeLibrary(hLib);
  812. }
  813. }
  814. return lpszRet;
  815. }
  816. /*****************************************************************************\
  817. * inf_CopyAndRenameInf (Local Routine)
  818. *
  819. * Opens the inf (the installed, possibly renamed inf), and queries setup for the
  820. * original name. Copies the inf to our dest directory, renaming it to the
  821. * original name, if we have one. Also saves the orignal file info so that we
  822. * can rename the .cat file to the original name later.
  823. *
  824. \*****************************************************************************/
  825. LPTSTR inf_CopyAndRenameInf(
  826. LPINFINFO lpInf,
  827. LPTSTR lpszSrcInf,
  828. LPTSTR lpszSrcInfName) {
  829. HINF hInf;
  830. PSP_INF_INFORMATION pii;
  831. LPTSTR lpszDstInf = NULL;
  832. LPTSTR lpszDstName;
  833. DWORD dwErr;
  834. // If this is a Win9x cab then simply return the passed in name
  835. if (genIsWin9X(lpInf->idxPlt)) {
  836. lpszDstInf = genGAllocStr(lpszSrcInf);
  837. } else {
  838. // Open the main-inf file.
  839. //
  840. hInf = SetupOpenInfFile(lpszSrcInf,
  841. g_szPrinterClass,
  842. INF_STYLE_WIN4,
  843. (PUINT)&dwErr);
  844. if ( hInf != INVALID_HANDLE_VALUE ) {
  845. if (pii = inf_GetInfInfo(hInf)) {
  846. // Set the dst name to default to the src name, just in case we don't
  847. // succeed in getting original file info from setup.
  848. // If we don't get original file info, we DON'T bail out, because even though
  849. // the verification will fail on the client, the user will be prompted as to whether
  850. // to install the unverified driver files, which is what we want - the user will
  851. // still be able to print.
  852. //
  853. lpszDstName = lpszSrcInfName;
  854. // Ask setupapi for the original names of the .inf and .cat file
  855. //
  856. lpInf->OriginalFileInfo.cbSize = sizeof(SP_ORIGINAL_FILE_INFO);
  857. lpInf->OriginalFileInfo.OriginalInfName[0] = TEXT('\0');
  858. lpInf->OriginalFileInfo.OriginalCatalogName[0] = TEXT('\0');
  859. if (SetupQueryInfOriginalFileInformation(pii, 0, NULL, &(lpInf->OriginalFileInfo))) {
  860. lpszDstName = (LPTSTR)&(lpInf->OriginalFileInfo.OriginalInfName);
  861. }
  862. // Build full-path to inf-file destination. This will be our
  863. // new inf-file in the .\cabinets directory.
  864. //
  865. lpszDstInf = genBuildFileName(lpInf->lpszDstPath,
  866. lpszDstName,
  867. NULL);
  868. if (lpszDstInf) {
  869. // Make a copy of our inf to the destination-directory, which will
  870. // effectively rename it if we were successful in getting original file info.
  871. //
  872. if ( !CopyFile(lpszSrcInf, lpszDstInf, FALSE) )
  873. {
  874. infSetError(lpInf,GetLastError());
  875. genGFree(lpszDstInf, genGSize(lpszDstInf));
  876. lpszDstInf = NULL;
  877. }
  878. } else {
  879. infSetError(lpInf,GetLastError());
  880. lpszDstInf = NULL;
  881. }
  882. genGFree(pii, genGSize(pii));
  883. } // if (pii = ...)
  884. else
  885. infSetError(lpInf,GetLastError());
  886. SetupCloseInfFile(hInf);
  887. hInf = NULL;
  888. } // if (hInf)
  889. else
  890. infSetError(lpInf,GetLastError());
  891. }
  892. return lpszDstInf;
  893. }
  894. /*****************************************************************************\
  895. * inf_GetInfObj (Local Routine)
  896. *
  897. * Get the INF file object handle. This utilizes fields from the lpInf
  898. * structure (lpszDstDir, lpszFriendly).
  899. *
  900. \*****************************************************************************/
  901. HINF inf_GetInfObj(
  902. LPINFINFO lpInf)
  903. {
  904. DWORD dwErr;
  905. LPTSTR lpszLayName;
  906. LPTSTR lpszInfName;
  907. LPTSTR lpszDstInf;
  908. LPTSTR lpszSrcInf;
  909. LPTSTR lpszLayFile;
  910. LPTSTR lpszLaySrc;
  911. LPTSTR lpszTmp;
  912. HINF hInf = INVALID_HANDLE_VALUE;
  913. // Get main INF file and make a copy to our destination.
  914. //
  915. if (lpszTmp = inf_GetSrcInf(lpInf)) {
  916. // Save our inf-filename.
  917. //
  918. if (lpszSrcInf = genGAllocStr(lpszTmp)) {
  919. // Split up the SrcInf file to path and name.
  920. //
  921. lpszInfName = genFindRChar(lpszTmp, TEXT('\\'));
  922. if (lpszInfName != NULL) {
  923. *lpszInfName++ = TEXT('\0');
  924. if (lpszDstInf = inf_CopyAndRenameInf(lpInf, lpszSrcInf, lpszInfName)) {
  925. // Open the main-inf file.
  926. //
  927. hInf = SetupOpenInfFile(lpszDstInf,
  928. g_szPrinterClass,
  929. INF_STYLE_WIN4,
  930. (PUINT)&dwErr);
  931. if ( hInf == INVALID_HANDLE_VALUE )
  932. infSetError(lpInf,GetLastError());
  933. genGFree(lpszDstInf, genGSize(lpszDstInf));
  934. } // if (lpszDstInf)
  935. } // if (lpszInfName != NULL)
  936. else
  937. infSetError(lpInf, ERROR_PATH_NOT_FOUND);
  938. genGFree(lpszSrcInf, genGSize(lpszSrcInf));
  939. } // if (lpszSrcInf)
  940. else
  941. infSetError(lpInf,GetLastError());
  942. genGFree(lpszTmp, genGSize(lpszTmp));
  943. } // if (lpszTmp)
  944. return hInf;
  945. }
  946. /*****************************************************************************\
  947. * inf_GetInsLine (Local Routine)
  948. *
  949. * Returns the install-line to install.
  950. *
  951. \*****************************************************************************/
  952. LPTSTR inf_GetInsLine(
  953. LPINFINFO lpInf,
  954. LPCTSTR lpszMfgName)
  955. {
  956. LPTSTR lpszSct;
  957. BOOL bRet;
  958. DWORD cbSize;
  959. LPTSTR lpszIns = NULL;
  960. // Retrieve the install-section (raw).
  961. //
  962. lpszSct = inf_GetInsVal(lpszMfgName, lpInf->lpszDrvName, lpInf->hInfObj);
  963. if (lpszSct) {
  964. // Set the platform override so that we may be specify
  965. // architecture section to install.
  966. //
  967. SetupSetPlatformPathOverride(genStrCliOverride(lpInf->idxPlt));
  968. // Determine the size necessary to hold the install-section
  969. // string.
  970. //
  971. cbSize = 0;
  972. SetupDiGetActualSectionToInstall(lpInf->hInfObj,
  973. lpszSct,
  974. NULL,
  975. 0,
  976. &cbSize,
  977. NULL);
  978. // Get the true install section string.
  979. //
  980. cbSize *= sizeof(TCHAR);
  981. if (cbSize && (lpszIns = (LPTSTR)genGAlloc(cbSize))) {
  982. bRet = SetupDiGetActualSectionToInstall(lpInf->hInfObj,
  983. lpszSct,
  984. lpszIns,
  985. cbSize,
  986. NULL,
  987. NULL);
  988. // If we failed, for some reason, then
  989. // return NULL.
  990. //
  991. if (bRet == FALSE) {
  992. genGFree(lpszIns, cbSize);
  993. lpszIns = NULL;
  994. }
  995. }
  996. SetupSetPlatformPathOverride(NULL);
  997. genGFree(lpszSct, genGSize(lpszSct));
  998. }
  999. return lpszIns;
  1000. }
  1001. /*****************************************************************************\
  1002. * inf_GetInfName (Local Routine)
  1003. *
  1004. * Returns the name of an inf-file.
  1005. *
  1006. \*****************************************************************************/
  1007. LPTSTR inf_GetInfName(
  1008. LPINFINFO lpInf)
  1009. {
  1010. PSP_INF_INFORMATION pii;
  1011. LPTSTR lpszFile;
  1012. LPTSTR lpszPtr;
  1013. LPTSTR lpszName = NULL;
  1014. if (lpszFile = inf_GetInfFile(lpInf->hInfObj, NULL)) {
  1015. // Seperate the path and file info.
  1016. //
  1017. if (lpszPtr = genFindRChar(lpszFile, TEXT('\\')))
  1018. lpszName = genGAllocStr(lpszPtr + 1);
  1019. genGFree(lpszFile, genGSize(lpszFile));
  1020. }
  1021. return lpszName;
  1022. }
  1023. /*****************************************************************************\
  1024. * inf_IsDrvSupported (Local Routine)
  1025. *
  1026. * Returns whether the driver-version is supported for the client-version.
  1027. *
  1028. \*****************************************************************************/
  1029. BOOL inf_IsDrvSupported(
  1030. DWORD idxVerCli,
  1031. DWORD idxVerSpl)
  1032. {
  1033. BOOL bSupported = FALSE;
  1034. // If the client is less than NT 4.0, then we can't support any
  1035. // drivers that are kernel-mode.
  1036. //
  1037. if ((idxVerCli < IDX_SPLVER_2) && (idxVerSpl >= IDX_SPLVER_2)) {
  1038. bSupported = FALSE;
  1039. } else {
  1040. // Determine if the requesting client can handle the
  1041. // driver-version installed for this printer. Typically,
  1042. // we can support drivers if they're within one major-version
  1043. // from each other.
  1044. //
  1045. if (abs((int)idxVerCli - (int)idxVerSpl) <= 1)
  1046. bSupported = TRUE;
  1047. }
  1048. return bSupported;
  1049. }
  1050. /*****************************************************************************\
  1051. * inf_GetDrvPath (Local Routine)
  1052. *
  1053. * Returns a string representing the requested driverpath.
  1054. *
  1055. \*****************************************************************************/
  1056. LPTSTR inf_GetDrvPath(
  1057. LPCTSTR lpszDrvName,
  1058. DWORD idxPlt,
  1059. DWORD idxVer)
  1060. {
  1061. BOOL bGet;
  1062. DWORD cbNeed;
  1063. DWORD cbSize;
  1064. LPCTSTR lpszEnv;
  1065. LPTSTR lpszPath = NULL;
  1066. #if 1
  1067. LPDRIVER_INFO_2 lpdi;
  1068. LPDRIVER_INFO_2 lpdiItem;
  1069. DWORD cRet;
  1070. DWORD idx;
  1071. BOOL bMatch = FALSE;
  1072. DWORD idxSpl;
  1073. LPTSTR lpszEnd;
  1074. if (lpszEnv = genStrCliEnvironment(idxPlt)) {
  1075. cbSize = 0;
  1076. EnumPrinterDrivers(NULL,
  1077. (LPTSTR)lpszEnv,
  1078. 2,
  1079. NULL,
  1080. 0,
  1081. &cbSize,
  1082. &cRet);
  1083. if (cbSize && (lpdi = (LPDRIVER_INFO_2)genGAlloc(cbSize))) {
  1084. cRet = 0;
  1085. bGet = EnumPrinterDrivers(NULL,
  1086. (LPTSTR)lpszEnv,
  1087. 2,
  1088. (LPBYTE)lpdi,
  1089. cbSize,
  1090. &cbNeed,
  1091. &cRet);
  1092. if (bGet && cRet) {
  1093. // The goal here is to search for the driver-version
  1094. // that matches the printer-name, then look to see if
  1095. // this version will work on the requested client. Typically,
  1096. // clients can support driver-versions that are (n) to (n-1)
  1097. //
  1098. for (idx = 0; idx < cRet; idx++) {
  1099. lpdiItem = (lpdi + idx);
  1100. // Potential match?
  1101. //
  1102. if (lstrcmpi(lpdiItem->pName, lpszDrvName) == 0) {
  1103. if (lpszPath = genGAllocStr(lpdiItem->pDriverPath)) {
  1104. if (lpszEnd = genFindRChar(lpszPath, TEXT('\\'))) {
  1105. *lpszEnd = TEXT('\0');
  1106. bMatch = FALSE;
  1107. // Find the version-directory-string.
  1108. //
  1109. if (lpszEnd = genFindRChar(lpszPath, TEXT('\\'))) {
  1110. // Get the index for the driver-version.
  1111. //
  1112. if ((idxSpl = genIdxFromStrVersion(lpszEnd)) != IDX_UNKNOWN) {
  1113. bMatch = inf_IsDrvSupported(idxVer, idxSpl);
  1114. }
  1115. }
  1116. }
  1117. // If we're not a supported driver for the
  1118. // client, then don't use this path.
  1119. //
  1120. if (bMatch == FALSE) {
  1121. genGFree(lpszPath, genGSize(lpszPath));
  1122. lpszPath = NULL;
  1123. continue;
  1124. }
  1125. }
  1126. break;
  1127. }
  1128. }
  1129. // Chek top see if we found a compatible driver
  1130. if ( (idx == cRet) && (bMatch == FALSE) )
  1131. // We went though the whole list without finding a match
  1132. SetLastError(ERROR_DRIVER_NOT_FOUND);
  1133. }
  1134. genGFree(lpdi, cbSize);
  1135. }
  1136. else if ( cbSize == 0 )
  1137. SetLastError(ERROR_DRIVER_NOT_FOUND);
  1138. }
  1139. return lpszPath;
  1140. #else
  1141. DWORD cbVer;
  1142. LPCTSTR lpszVer;
  1143. if (lpszEnv = genStrCliEnvironment(idxPlt)) {
  1144. if (lpszVer = genStrCliVersion(idxVer)) {
  1145. // Get the required size for storing the full-directory name.
  1146. //
  1147. cbSize = 0;
  1148. GetPrinterDriverDirectory(NULL, (LPTSTR)lpszEnv, 1, NULL, 0, &cbSize);
  1149. cbVer = (lstrlen(lpszVer) * sizeof(TCHAR));
  1150. // Allocate buffer for holding the string and version directory.
  1151. //
  1152. if (cbSize && (lpszPath = (LPTSTR)genGAlloc(cbSize + cbVer))) {
  1153. bGet = GetPrinterDriverDirectory(NULL,
  1154. (LPTSTR)lpszEnv,
  1155. 1,
  1156. (LPBYTE)lpszPath,
  1157. cbSize + cbVer,
  1158. &cbNeed);
  1159. if (bGet) {
  1160. lstrcat(lpszPath, lpszVer);
  1161. return lpszPath;
  1162. }
  1163. genGFree(lpszPath, cbSize + cbVer);
  1164. }
  1165. }
  1166. }
  1167. return NULL;
  1168. #endif
  1169. }
  1170. /*****************************************************************************\
  1171. * inf_GetPrcPath (Local Routine)
  1172. *
  1173. * Returns a string representing the print-processor path.
  1174. *
  1175. \*****************************************************************************/
  1176. LPTSTR inf_GetPrcPath(
  1177. DWORD idxPlt)
  1178. {
  1179. BOOL bGet;
  1180. DWORD cbNeed;
  1181. DWORD cbSize;
  1182. LPCTSTR lpszEnv;
  1183. LPTSTR lpszPath;
  1184. if (lpszEnv = genStrCliEnvironment(idxPlt)) {
  1185. // Get the required size for storing the full-directory name.
  1186. //
  1187. cbSize = 0;
  1188. GetPrintProcessorDirectory(NULL, (LPTSTR)lpszEnv, 1, NULL, 0, &cbSize);
  1189. // Allocate buffer for holding the string.
  1190. //
  1191. if (cbSize && (lpszPath = (LPTSTR)genGAlloc(cbSize))) {
  1192. bGet = GetPrintProcessorDirectory(NULL,
  1193. (LPTSTR)lpszEnv,
  1194. 1,
  1195. (LPBYTE)lpszPath,
  1196. cbSize,
  1197. &cbNeed);
  1198. if (bGet)
  1199. return lpszPath;
  1200. genGFree(lpszPath, cbSize);
  1201. }
  1202. }
  1203. return NULL;
  1204. }
  1205. /*****************************************************************************\
  1206. * inf_GetIcmPath (Local Routine)
  1207. *
  1208. * Returns a string representing the ICM color path.
  1209. *
  1210. \*****************************************************************************/
  1211. LPTSTR inf_GetIcmPath(
  1212. DWORD idxPlt)
  1213. {
  1214. DWORD cbSize;
  1215. LPTSTR lpszPath;
  1216. // Get the required size for storing the full-directory name.
  1217. //
  1218. cbSize = 0;
  1219. GetColorDirectory(NULL, NULL, &cbSize);
  1220. // Allocate buffer for holding the string.
  1221. //
  1222. if (cbSize && (lpszPath = (LPTSTR)genGAlloc(cbSize))) {
  1223. if (GetColorDirectory(NULL, lpszPath, &cbSize))
  1224. return lpszPath;
  1225. genGFree(lpszPath, cbSize);
  1226. }
  1227. return NULL;
  1228. }
  1229. /*****************************************************************************\
  1230. * inf_GetSysPath (Local Routine)
  1231. *
  1232. * Returns a string representing the system directory.
  1233. *
  1234. \*****************************************************************************/
  1235. LPTSTR inf_GetSysPath(
  1236. DWORD idxPlt)
  1237. {
  1238. DWORD cbSize;
  1239. LPTSTR lpszPath;
  1240. cbSize = (MAX_PATH * sizeof(TCHAR));
  1241. // Allocate buffer for holding the string.
  1242. //
  1243. if (lpszPath = (LPTSTR)genGAlloc(cbSize)) {
  1244. if (GetSystemDirectory(lpszPath, MAX_PATH))
  1245. return lpszPath;
  1246. genGFree(lpszPath, cbSize);
  1247. }
  1248. return NULL;
  1249. }
  1250. /*****************************************************************************\
  1251. * inf_AllocStrings (Local Routine)
  1252. *
  1253. * Initializes the fields relating to the string-fields.
  1254. *
  1255. \*****************************************************************************/
  1256. BOOL inf_AllocStrings(
  1257. LPINFINFO lpInf,
  1258. LPINFGENPARM lpParm)
  1259. {
  1260. // Initialize the driver-name field.
  1261. //
  1262. if (lpInf->lpszDrvPath = inf_GetDrvPath(lpParm->lpszDrvName, lpInf->idxPlt, lpInf->idxVer)) {
  1263. if (lpInf->lpszDrvName = genGAllocStr(lpParm->lpszDrvName)) {
  1264. if (lpInf->lpszDstName = genGAllocStr(lpParm->lpszDstName)) {
  1265. if (lpInf->lpszDstPath = genGAllocStr(lpParm->lpszDstPath)) {
  1266. if (lpInf->lpszPrtName = genGAllocStr(lpParm->lpszPortName)) {
  1267. if (lpInf->lpszShrName = genGAllocStr(lpParm->lpszShareName)) {
  1268. if (lpInf->lpszFrnName = genGAllocStr(lpParm->lpszFriendlyName))
  1269. return TRUE;
  1270. genGFree(lpInf->lpszShrName, genGSize(lpInf->lpszShrName));
  1271. }
  1272. genGFree(lpInf->lpszPrtName, genGSize(lpInf->lpszPrtName));
  1273. }
  1274. genGFree(lpInf->lpszDstPath, genGSize(lpInf->lpszDstPath));
  1275. }
  1276. genGFree(lpInf->lpszDstName, genGSize(lpInf->lpszDstName));
  1277. }
  1278. genGFree(lpInf->lpszDrvName, genGSize(lpInf->lpszDrvName));
  1279. }
  1280. genGFree(lpInf->lpszDrvPath, genGSize(lpInf->lpszDrvPath));
  1281. }
  1282. return FALSE;
  1283. }
  1284. /*****************************************************************************\
  1285. * inf_AddInfFile (Local Routine)
  1286. *
  1287. * Adds the inf-file to the list. If this fails, then the (lpII) object
  1288. * is deleted. This keeps this consistent with the inf_AddItem() routine.
  1289. *
  1290. \*****************************************************************************/
  1291. LPINFITEMINFO inf_AddInfFile(
  1292. LPINFINFO lpInf,
  1293. LPINFITEMINFO lpII)
  1294. {
  1295. LPTSTR lpszInfFile;
  1296. LPTSTR lpszFile;
  1297. LPINFITEMINFO lpIIRet = NULL;
  1298. if (lpszInfFile = inf_GetInfFile(lpInf->hInfObj, NULL)) {
  1299. // Seperate the path and file info, and add to the list.
  1300. //
  1301. if (lpszFile = genFindRChar(lpszInfFile, TEXT('\\'))) {
  1302. *lpszFile = TEXT('\0');
  1303. lpIIRet = inf_AddItem(lpII, ++lpszFile, lpszInfFile, TRUE);
  1304. }
  1305. genGFree(lpszInfFile, genGSize(lpszInfFile));
  1306. }
  1307. return lpIIRet;
  1308. }
  1309. /*****************************************************************************\
  1310. * inf_AddCATToCountArray (Local Routine)
  1311. *
  1312. * Takes a CAT filename, and adds it to our count array (if a new one), or increments
  1313. * the count if it already is in our array.
  1314. *
  1315. \*****************************************************************************/
  1316. BOOL inf_AddCATToCountArray(LPWSTR lpszCATName,
  1317. LPCATCOUNTARRAY lpCatCountArray) {
  1318. BOOL bReturn = TRUE;
  1319. BOOL bFound = FALSE;
  1320. UINT i;
  1321. // Alloc or realloc for more memory if needed. We alloc INF_CAT_INCREMENT items at a time, as needed.
  1322. //
  1323. // When we start there is no Next Available item defined
  1324. if (!lpCatCountArray->uNextAvailable) {
  1325. if (lpCatCountArray->lpArray = (LPCATCOUNT)genGAlloc(sizeof(CATCOUNT) * INF_CAT_INCREMENT) ) {
  1326. lpCatCountArray->uNextAvailable = INF_CAT_INCREMENT;
  1327. lpCatCountArray->uItems = 0;
  1328. }
  1329. else goto CATCOUNTFAIL;
  1330. }
  1331. // See if we have already encountered this CAT file name. If so, increment the count
  1332. // for this CAT. If not, add this CAT to our array.
  1333. //
  1334. for (i=0; i < lpCatCountArray->uItems; i++) {
  1335. if (!lstrcmp(lpszCATName, lpCatCountArray->lpArray[i].lpszCATName)) {
  1336. lpCatCountArray->lpArray[i].uCount++;
  1337. bFound = TRUE;
  1338. break;
  1339. }
  1340. }
  1341. if (!bFound) {
  1342. // We might need to reallocate the array, we need to do this if the new position
  1343. // becomes equal to the next available item
  1344. UINT uItem = lpCatCountArray->uItems;
  1345. if (uItem >= lpCatCountArray->uNextAvailable) {
  1346. LPCATCOUNT lpNewArray = (LPCATCOUNT)genGRealloc((LPVOID)lpCatCountArray->lpArray,
  1347. sizeof(CATCOUNT) * lpCatCountArray->uNextAvailable,
  1348. sizeof(CATCOUNT) * (uItem + INF_CAT_INCREMENT) );
  1349. if (lpNewArray) {
  1350. lpCatCountArray->lpArray = lpNewArray;
  1351. lpCatCountArray->uNextAvailable = uItem + INF_CAT_INCREMENT;
  1352. }
  1353. else goto CATCOUNTFAIL;
  1354. }
  1355. lpCatCountArray->lpArray[uItem].uCount = 1;
  1356. lpCatCountArray->lpArray[uItem].lpszCATName = genGAllocWStr(lpszCATName);
  1357. if (lpCatCountArray->lpArray[uItem].lpszCATName)
  1358. lpCatCountArray->uItems = uItem + 1;
  1359. else goto CATCOUNTFAIL;
  1360. }
  1361. return TRUE;
  1362. CATCOUNTFAIL:
  1363. return FALSE;
  1364. }
  1365. /******************************************************************************
  1366. * inf_IsIndividuallySigned (Local Routine)
  1367. *
  1368. * Returns TRUE if a driver file is individually signed
  1369. *
  1370. *******************************************************************************/
  1371. BOOL inf_IsIndividuallySigned(
  1372. LPCTSTR lpszDriverFileName) {
  1373. GUID gSubject;
  1374. SIP_DISPATCH_INFO SipDispatch;
  1375. SIP_SUBJECTINFO SubjectInfo;
  1376. DWORD cbData = 0;
  1377. BOOL bRet = FALSE;
  1378. DWORD dwEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
  1379. ASSERT(lpszDriverFileName);
  1380. if (!CryptSIPRetrieveSubjectGuid( // This GUID is used for passing to CryptSIPLoad
  1381. lpszDriverFileName, // which verifies the sig on the file
  1382. NULL,
  1383. &gSubject)) goto Failure;
  1384. ZeroMemory( &SipDispatch, sizeof(SipDispatch) );
  1385. SipDispatch.cbSize = sizeof(SipDispatch);
  1386. if (!CryptSIPLoad(
  1387. &gSubject,
  1388. 0,
  1389. &SipDispatch)) goto Failure;
  1390. // Now that we have the SIP Dispatch, fill out the subject info
  1391. ZeroMemory( &SubjectInfo, sizeof(SubjectInfo) );
  1392. SubjectInfo.cbSize = sizeof(SubjectInfo);
  1393. SubjectInfo.pgSubjectType = (GUID *)&gSubject;
  1394. SubjectInfo.hFile = INVALID_HANDLE_VALUE;
  1395. SubjectInfo.pwsFileName = lpszDriverFileName;
  1396. SubjectInfo.dwEncodingType = dwEncodingType;
  1397. if (!SipDispatch.pfGet(
  1398. &SubjectInfo,
  1399. &dwEncodingType,
  1400. 0,
  1401. &cbData,
  1402. NULL)) goto Failure;
  1403. if (cbData != 0) bRet = TRUE;
  1404. Failure:
  1405. return bRet;
  1406. }
  1407. /*****************************************************************************\
  1408. * inf_CATCountProc (Local Routine)
  1409. *
  1410. * Callback used to count up all references to CAT files by the driver files.
  1411. *
  1412. \*****************************************************************************/
  1413. BOOL CALLBACK inf_CATCountProc(LPCTSTR lpszName,
  1414. LPCTSTR lpszPath,
  1415. BOOL bInf,
  1416. LPVOID lpData) {
  1417. BOOL bReturn = TRUE;
  1418. LPCATCOUNTARRAY lpCatCountArray = (LPCATCOUNTARRAY)(lpData);
  1419. HCATADMIN hCatAdmin = lpCatCountArray->hCatAdmin;
  1420. LPTSTR lpszDriverFileName;
  1421. HCATINFO hCatInfo = NULL;
  1422. HCATINFO hCatInfoPrev = NULL;
  1423. CATALOG_INFO CatalogInfo;
  1424. BYTE * pbHash;
  1425. DWORD dwBytes;
  1426. WIN32_FIND_DATA ffd;
  1427. PFILEITEM pFileItem;
  1428. HANDLE hFind, hFile;
  1429. LPTSTR pFullPath, pPath, pName;
  1430. // Find the catalog file associated with this file.
  1431. // If we can't find one, that's OK, it's not an error, just a file
  1432. // with no associated .cat file. The user can decide on the client-end
  1433. // whether or not he wants to install without the verification a .cat file
  1434. // would provide...
  1435. //
  1436. if (INVALID_HANDLE_VALUE != (HANDLE)hCatAdmin) {
  1437. if (lpszDriverFileName = genBuildFileName(lpszPath, lpszName, NULL)) {
  1438. hFind = FindFirstFile(lpszDriverFileName, &ffd);
  1439. if (hFind && (hFind != INVALID_HANDLE_VALUE)) {
  1440. FindClose(hFind);
  1441. // The first thing we need to determine is whether the file is individually
  1442. // signed, if it is we don't look for a cat and up the individually signed
  1443. // count
  1444. if ( inf_IsIndividuallySigned(lpszDriverFileName) ) {
  1445. lpCatCountArray->dwIndivSigned++;
  1446. } else {
  1447. // Open the file in order to hash it.
  1448. //
  1449. if (INVALID_HANDLE_VALUE != (hFile = CreateFile(lpszDriverFileName,
  1450. GENERIC_READ,
  1451. FILE_SHARE_READ,
  1452. NULL,
  1453. OPEN_EXISTING,
  1454. FILE_ATTRIBUTE_NORMAL,
  1455. NULL))) {
  1456. // Determine how many bytes we need for the hash
  1457. //
  1458. dwBytes = 0;
  1459. pbHash = NULL;
  1460. CryptCATAdminCalcHashFromFileHandle(hFile, &dwBytes, pbHash, 0);
  1461. if (NULL != (pbHash = (BYTE *)genGAlloc(dwBytes))) {
  1462. // Compute the hash for this file
  1463. //
  1464. if (CryptCATAdminCalcHashFromFileHandle(hFile, &dwBytes, pbHash, 0)) {
  1465. // Get the catalog file(s) associated with this file hash
  1466. //
  1467. hCatInfo = NULL;
  1468. do {
  1469. hCatInfoPrev = hCatInfo;
  1470. hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, pbHash, dwBytes, 0, &hCatInfoPrev);
  1471. if (NULL != hCatInfo) {
  1472. CatalogInfo.cbStruct = sizeof(CATALOG_INFO);
  1473. if (CryptCATCatalogInfoFromContext(hCatInfo, &CatalogInfo, 0)) {
  1474. if (!inf_AddCATToCountArray(CatalogInfo.wszCatalogFile, lpCatCountArray)) {
  1475. bReturn = FALSE;
  1476. hCatInfo = NULL; // fail out of loop
  1477. }
  1478. }
  1479. }
  1480. } while (NULL != hCatInfo);
  1481. } // if (CryptCATAdminCalcHashFromFileHandle(hFile, &dwBytes, pbHash, 0)) {
  1482. genGFree(pbHash, dwBytes);
  1483. } // if (NULL != (pbHash = (BYTE *)genGAlloc(dwBytes))) {
  1484. CloseHandle(hFile);
  1485. } // if (INVALID_HANDLE_VALUE != (hFile = CreateFile(lpszDriverFileName,
  1486. } // if ( inf_IsIndividuallySigned(hFile, lpszDriverFileName) )
  1487. } // if (hFind && (hFind != INVALID_HANDLE_VALUE)) {
  1488. genGFree(lpszDriverFileName, genGSize(lpszDriverFileName));
  1489. } // if (lpszDriverFileName = genBuildFileName(lpszPath, lpszName, NULL)) {
  1490. } // if (INVALID_HANDLE_VALUE != (HANDLE)hCatAdmin) {
  1491. return bReturn;
  1492. }
  1493. /*****************************************************************************\
  1494. * inf_AddCATFile (Local Routine)
  1495. *
  1496. * Adds the cat-file to the list (if any).
  1497. *
  1498. \*****************************************************************************/
  1499. BOOL inf_AddCATFile(
  1500. LPINFINFO lpInf) {
  1501. LPTSTR lpszInfFile;
  1502. LPTSTR lpszFile;
  1503. LPTSTR lpszDstCAT;
  1504. LPTSTR lpszDstName;
  1505. LPTSTR lpszInstalledCATFileName;
  1506. LPINFITEMINFO lpIIRet;
  1507. // We initialize return to TRUE because we want to NOT fail out of the cab generation process
  1508. // at this point, even if we fail to find a CAT file. This will at least still return the driver cab
  1509. // package to the client and let the user accept or decline the package when it fails to
  1510. // verify.
  1511. //
  1512. BOOL bReturn = TRUE;
  1513. CATCOUNTARRAY CatCountArray;
  1514. CatCountArray.dwIndivSigned = 0; // The number of individually signed files
  1515. CatCountArray.uItems = 0;
  1516. CatCountArray.uNextAvailable = 0;
  1517. CatCountArray.lpArray = NULL;
  1518. // Initialize the catalog admin context handle
  1519. //
  1520. if (FALSE == CryptCATAdminAcquireContext(&(CatCountArray.hCatAdmin), NULL, 0)) {
  1521. CatCountArray.hCatAdmin = (HCATADMIN)INVALID_HANDLE_VALUE;
  1522. infSetError(lpInf,GetLastError());
  1523. return FALSE;
  1524. }
  1525. // Enumerate all the items in the inf. The enumeration callback (inf_CATCountProc)
  1526. // will count the number of references for each unique CAT file that is referenced by
  1527. // one of our driver files. We will add to the CAB file, the CAT file that is referenced
  1528. // the most times by the driver files - this CAT file SHOULD be referenced by ALL of the
  1529. // driver files, or there is no point in adding the CAT to the CAB, since the driver verification
  1530. // will fail on the client if not all files are verified by the CAT.
  1531. //
  1532. if (infEnumItems((HANDLE)lpInf, inf_CATCountProc, (LPVOID)&CatCountArray )) {
  1533. if (CatCountArray.uItems > 0) {
  1534. UINT uIndex;
  1535. // Search our CAT file array to find the CAT file that was referenced more than the others.
  1536. // This is the CAT file we want to package into the CAB.
  1537. //
  1538. UINT uIndexOfMostCommonCAT = 0;
  1539. for (uIndex=0; uIndex < CatCountArray.uItems; uIndex++) {
  1540. if (CatCountArray.lpArray[uIndexOfMostCommonCAT].uCount < CatCountArray.lpArray[uIndex].uCount)
  1541. uIndexOfMostCommonCAT = uIndex;
  1542. }
  1543. // Make sure that every file referenced this CAT file - if they all didn't,
  1544. // then it will fail verification on client - so no sense in sending the CAT
  1545. // to the CAB package
  1546. //
  1547. if (CatCountArray.lpArray[uIndexOfMostCommonCAT].uCount + CatCountArray.dwIndivSigned
  1548. >= (lpInf->lpInfItems->dwCount)) {
  1549. lpszInstalledCATFileName = CatCountArray.lpArray[uIndexOfMostCommonCAT].lpszCATName;
  1550. // If we have an original .cat file name, use it for the dest name,
  1551. // otherwise, just use the current (installed) name
  1552. //
  1553. if (lpInf->OriginalFileInfo.OriginalCatalogName[0] != TEXT('\0')) {
  1554. lpszDstName = (LPTSTR)&(lpInf->OriginalFileInfo.OriginalCatalogName);
  1555. }
  1556. else {
  1557. // Find the filename portion of the current (installed) .cat file name.
  1558. lpszDstName = genFindRChar(lpszInstalledCATFileName, TEXT('\\'));
  1559. lpszDstName++;
  1560. }
  1561. if (lpszDstCAT = genBuildFileName(lpInf->lpszDstPath,
  1562. lpszDstName,
  1563. NULL)) {
  1564. // Copy the CAT file into our directory, renaming it to the original name.
  1565. //
  1566. if ( CopyFile(lpszInstalledCATFileName, lpszDstCAT, FALSE) )
  1567. {
  1568. // Add this (renamed) file to our file list to be added to the cab.
  1569. //
  1570. lpIIRet = inf_AddItem(lpInf->lpInfItems, lpszDstName, lpInf->lpszDstPath, TRUE);
  1571. if (lpIIRet == NULL) {
  1572. infSetError(lpInf,GetLastError());
  1573. bReturn = FALSE;
  1574. }
  1575. lpInf->lpInfItems = lpIIRet;
  1576. }
  1577. else
  1578. {
  1579. infSetError(lpInf,GetLastError());
  1580. genGFree(lpInf->lpInfItems, genGSize(lpInf->lpInfItems));
  1581. lpInf->lpInfItems = NULL;
  1582. bReturn = FALSE;
  1583. }
  1584. genGFree(lpszDstCAT, genGSize(lpszDstCAT));
  1585. }
  1586. }
  1587. }
  1588. else {
  1589. DBGMSG(DBG_INFO, ("geninf: No CAT Files found for driver package.\n"));
  1590. }
  1591. }
  1592. // Free all our CAT array items here
  1593. //
  1594. if (CatCountArray.lpArray) {
  1595. UINT uItem = 0;
  1596. for (uItem = 0; uItem < CatCountArray.uItems; uItem++) {
  1597. genGFree(CatCountArray.lpArray[uItem].lpszCATName, genGSize(CatCountArray.lpArray[uItem].lpszCATName));
  1598. }
  1599. genGFree(CatCountArray.lpArray, genGSize(CatCountArray.lpArray));
  1600. }
  1601. // Release the Catalog Admin context handle, if we have one
  1602. //
  1603. if (INVALID_HANDLE_VALUE != (HANDLE)(CatCountArray.hCatAdmin)) {
  1604. CryptCATAdminReleaseContext(CatCountArray.hCatAdmin, 0);
  1605. }
  1606. return bReturn;
  1607. }
  1608. /*****************************************************************************\
  1609. * inf_SetDefDirIds (Local Routine)
  1610. *
  1611. * Sets the Default DRID values for the setup-process.
  1612. *
  1613. \*****************************************************************************/
  1614. BOOL inf_SetDefDirIds(
  1615. LPINFINFO lpInf)
  1616. {
  1617. LPTSTR lpszDrv;
  1618. LPTSTR lpszPrc;
  1619. LPTSTR lpszSys;
  1620. LPTSTR lpszIcm;
  1621. BOOL bRet = FALSE;
  1622. if (lpszDrv = lpInf->lpszDrvPath) {
  1623. if (lpszPrc = inf_GetPrcPath(lpInf->idxPlt)) {
  1624. if (lpszSys = inf_GetSysPath(lpInf->idxPlt)) {
  1625. if (lpszIcm = inf_GetIcmPath(lpInf->idxPlt)) {
  1626. if (SetupSetDirectoryId(lpInf->hInfObj, INF_DRV_DRID, lpszDrv) &&
  1627. SetupSetDirectoryId(lpInf->hInfObj, INF_PRC_DRID, lpszPrc) &&
  1628. SetupSetDirectoryId(lpInf->hInfObj, INF_SYS_DRID, lpszSys) &&
  1629. SetupSetDirectoryId(lpInf->hInfObj, INF_ICM_DRID, lpszIcm)) {
  1630. bRet = TRUE;
  1631. }
  1632. genGFree(lpszIcm, genGSize(lpszIcm));
  1633. }
  1634. genGFree(lpszSys, genGSize(lpszSys));
  1635. }
  1636. genGFree(lpszPrc, genGSize(lpszPrc));
  1637. }
  1638. }
  1639. return bRet;
  1640. }
  1641. /*****************************************************************************\
  1642. * inf_SetDirIds (Local Routine)
  1643. *
  1644. * Sets the DRID values for the setup-process.
  1645. *
  1646. \*****************************************************************************/
  1647. BOOL inf_SetDirIds(
  1648. LPINFINFO lpInf)
  1649. {
  1650. INFCONTEXT ic;
  1651. DWORD idx;
  1652. DWORD dwCount;
  1653. WORD wEnvCli;
  1654. WORD wEnvSrv;
  1655. DWORD dwDRID;
  1656. LPTSTR lpszDir;
  1657. BOOL bRet = FALSE;
  1658. // Initialize the default directories for DRID values.
  1659. //
  1660. inf_SetDefDirIds(lpInf);
  1661. // Look through the INF-File for any overriding DRID values and
  1662. // set these.
  1663. //
  1664. if ((dwCount = SetupGetLineCount(lpInf->hInfObj, g_szDestDirs)) != (DWORD)-1) {
  1665. for (idx = 0, bRet = TRUE; (idx < dwCount) && bRet; idx++) {
  1666. if (bRet = SetupGetLineByIndex(lpInf->hInfObj, g_szDestDirs, idx, &ic)) {
  1667. if (bRet = SetupGetIntField(&ic, 1, (PINT)&dwDRID)) {
  1668. if (dwDRID < DIRID_USER)
  1669. continue;
  1670. switch (dwDRID) {
  1671. case INF_DRV_DRID:
  1672. bRet = SetupSetDirectoryId(lpInf->hInfObj, dwDRID, lpInf->lpszDrvPath);
  1673. continue;
  1674. #if 1
  1675. // We don't necessarily need to copy the procesor and system32 files
  1676. // since they are architecture specific. In this case we will let the
  1677. // files default to the skip-dir.
  1678. //
  1679. // NOTE: if do not include these files, we might need to modify the INF
  1680. // so that they are not referenced during client-side install.
  1681. //
  1682. case INF_PRC_DRID:
  1683. wEnvCli = genValCliArchitecture(lpInf->idxPlt);
  1684. wEnvSrv = genValSvrArchitecture();
  1685. if (wEnvCli == wEnvSrv) {
  1686. lpszDir = inf_GetPrcPath(lpInf->idxPlt);
  1687. } else {
  1688. lpszDir = genGAllocStr(g_szSkipDir);
  1689. }
  1690. break;
  1691. case INF_SYS_DRID:
  1692. wEnvCli = genValCliArchitecture(lpInf->idxPlt);
  1693. wEnvSrv = genValSvrArchitecture();
  1694. if (wEnvCli == wEnvSrv) {
  1695. lpszDir = inf_GetSysPath(lpInf->idxPlt);
  1696. } else {
  1697. lpszDir = genGAllocStr(g_szSkipDir);
  1698. }
  1699. break;
  1700. #endif
  1701. case INF_ICM_DRID:
  1702. lpszDir = inf_GetIcmPath(lpInf->idxPlt);
  1703. break;
  1704. default:
  1705. lpszDir = genGAllocStr(g_szSkipDir);
  1706. }
  1707. if (lpszDir) {
  1708. bRet = SetupSetDirectoryId(lpInf->hInfObj, dwDRID, lpszDir);
  1709. genGFree(lpszDir, genGSize(lpszDir));
  1710. } else {
  1711. bRet = FALSE;
  1712. }
  1713. }
  1714. }
  1715. }
  1716. }
  1717. return bRet;
  1718. }
  1719. /*****************************************************************************\
  1720. * inf_ScanFiles (Local Routine)
  1721. *
  1722. * Callback routine which returns the items in a copyfiles list.
  1723. *
  1724. \*****************************************************************************/
  1725. UINT CALLBACK inf_ScanFiles(
  1726. LPVOID lpCtxt,
  1727. UINT uNotify,
  1728. UINT_PTR Parm1,
  1729. UINT_PTR Parm2)
  1730. {
  1731. LPINFSCAN lpScan;
  1732. LPTSTR lpszPath;
  1733. LPTSTR lpszFile;
  1734. if ((lpScan = (LPINFSCAN)lpCtxt) && (lpszPath = (LPTSTR)Parm1)) {
  1735. if (lpszFile = genFindRChar(lpszPath, TEXT('\\'))) {
  1736. *lpszFile = TEXT('\0');
  1737. // If this is a skip-dir item then do not add to our
  1738. // list. This can happen for files that are not stored
  1739. // in platform-specific directories. For example, files
  1740. // stored in the SYSTEM32 directory have no architecture
  1741. // counter-part. We do not want to download the incorrect
  1742. // file for a different architecture.
  1743. //
  1744. if (lstrcmpi(lpszPath, g_szSkipDir) != 0) {
  1745. lpScan->lpII = inf_AddItem(lpScan->lpII, lpszFile + 1, lpszPath, FALSE);
  1746. }
  1747. *lpszFile = TEXT('\\');
  1748. return (lpScan->lpII ? 0 : 1);
  1749. }
  1750. }
  1751. return 1;
  1752. }
  1753. /*****************************************************************************\
  1754. * inf_BuildW9XList (Local Routine)
  1755. *
  1756. * This enumerates the W9X dependent files and adds them to our list.
  1757. *
  1758. \*****************************************************************************/
  1759. LPINFITEMINFO inf_BuildW9XList(
  1760. LPINFINFO lpInf,
  1761. LPINFSCAN lpis)
  1762. {
  1763. LPDRIVER_INFO_3 lpdi3;
  1764. LPTSTR lpszDrvName;
  1765. LPTSTR lpszItm;
  1766. BOOL bRet = FALSE;
  1767. if (lpdi3 = inf_GetW9XInfo(lpInf, &lpszDrvName)) {
  1768. if (lpszItm = lpdi3->pDependentFiles) {
  1769. bRet = TRUE;
  1770. while (*lpszItm) {
  1771. if (inf_ScanFiles(lpis, 0, (UINT_PTR)lpszItm, 0) != 0)
  1772. break;
  1773. lpszItm = inf_NextStr(lpszItm);
  1774. }
  1775. }
  1776. genGFree(lpszDrvName, genGSize(lpszDrvName));
  1777. genGFree(lpdi3, genGSize(lpdi3));
  1778. }
  1779. if (bRet == FALSE) {
  1780. genGFree(lpis->lpII, genGSize(lpis->lpII));
  1781. lpis->lpII = NULL;
  1782. }
  1783. return lpis->lpII;
  1784. }
  1785. /*******************************************************************************************
  1786. ** inf_ScanSourceTarget (local routine)
  1787. **
  1788. ** Get the source and target, and then run through all the inf files if there is a source
  1789. ** and find the target file that matches and add the source to the database
  1790. **
  1791. *******************************************************************************************/
  1792. BOOL CALLBACK inf_ScanSourceTarget(HINF hInf,
  1793. LPCTSTR pmszFields,
  1794. LPVOID pCookie) {
  1795. ASSERT(pmszFields); // Should never be NULL, we allocate it
  1796. ASSERT(pCookie); // Should never be NULL, we pass it in after check
  1797. LPINFSCAN lpis = (LPINFSCAN)pCookie;
  1798. LPINFITEMINFO lpII = lpis->lpII;
  1799. LPCTSTR szTarget = pmszFields;
  1800. BOOL bRet = lpII != NULL;
  1801. if (*szTarget && bRet) { // There is a target file (non NULL)
  1802. LPCTSTR szSource = &pmszFields[ lstrlen(szTarget) + 1 ];
  1803. if (*szSource) {
  1804. DWORD dwIdx;
  1805. DWORD dwCount;
  1806. // We don't need to do anything if source and target name are the same, even
  1807. // if they are expressly listed in the inf file
  1808. if ( lstrcmpi ( szTarget, szSource) ) {
  1809. dwCount = lpII->dwCount;
  1810. for(dwIdx = 0; dwIdx < dwCount; ++dwIdx) {
  1811. if (!lstrcmpi( lpII->aItems[dwIdx].szName, szTarget))
  1812. // Targets match, write the source file name into the structure
  1813. lstrcpyn( lpII->aItems[dwIdx].szSource, szSource, INF_MIN_BUFFER );
  1814. }
  1815. }
  1816. }
  1817. }
  1818. return bRet;
  1819. }
  1820. /******************************************************************************************
  1821. ** inf_ScanCopyFields (local routine)
  1822. **
  1823. ** Run through the Copy Fields supplied by inf_ScanSection and Scan through those sections
  1824. ** for Source and Destination Pairs
  1825. **
  1826. ******************************************************************************************/
  1827. BOOL CALLBACK inf_ScanCopyFields(HINF hInf, LPCTSTR pmszFields, LPVOID pCookie) {
  1828. ASSERT(pmszFields);
  1829. BOOL bRet = TRUE;
  1830. while(*pmszFields && bRet) {
  1831. if (*pmszFields != TEXT('@')) // Check for an individual file install
  1832. bRet = inf_ScanSection( hInf, pmszFields, NULL, pCookie, inf_ScanSourceTarget);
  1833. pmszFields += lstrlen(pmszFields) + 1;
  1834. }
  1835. return bRet;
  1836. }
  1837. /*****************************************************************************\
  1838. * inf_BuildWNTList (Local Routine)
  1839. *
  1840. * This builds our list from the NT scan-file-queue of an inf-parser.
  1841. *
  1842. \*****************************************************************************/
  1843. LPINFITEMINFO inf_BuildWNTList(
  1844. LPINFINFO lpInf,
  1845. LPCTSTR lpszMfgName,
  1846. LPINFSCAN lpis)
  1847. {
  1848. LPTSTR lpszIns;
  1849. HSPFILEQ hFQ;
  1850. DWORD dwRet;
  1851. BOOL bRet = FALSE;
  1852. if (lpszIns = inf_GetInsLine(lpInf, lpszMfgName)) {
  1853. SetupSetPlatformPathOverride(genStrCliOverride(lpInf->idxPlt));
  1854. hFQ = SetupOpenFileQueue();
  1855. if (hFQ != INVALID_HANDLE_VALUE) {
  1856. inf_SetDirIds(lpInf);
  1857. bRet = SetupInstallFilesFromInfSection(lpInf->hInfObj,
  1858. NULL,
  1859. hFQ,
  1860. lpszIns,
  1861. NULL,
  1862. 0);
  1863. if (bRet) {
  1864. // Setup the user-defined data passed to the
  1865. // enum-callback.
  1866. //
  1867. dwRet = 0;
  1868. bRet = SetupScanFileQueue(hFQ,
  1869. SPQ_SCAN_USE_CALLBACK,
  1870. 0,
  1871. inf_ScanFiles,
  1872. (LPVOID)lpis,
  1873. &dwRet);
  1874. }
  1875. SetupCloseFileQueue(hFQ);
  1876. // Now that we have all of the files, we run through the inf file to see what the
  1877. // original file names where. If they are different, we insert them into
  1878. // the inf file
  1879. if (bRet)
  1880. bRet = inf_ScanSection(lpInf->hInfObj,
  1881. lpszIns,
  1882. g_szCopyFiles,
  1883. (PVOID)lpis,
  1884. inf_ScanCopyFields
  1885. );
  1886. }
  1887. SetupSetPlatformPathOverride(NULL);
  1888. genGFree(lpszIns, genGSize(lpszIns));
  1889. }
  1890. if (bRet == FALSE) {
  1891. genGFree(lpis->lpII, genGSize(lpis->lpII));
  1892. lpis->lpII = NULL;
  1893. }
  1894. return lpis->lpII;
  1895. }
  1896. /*****************************************************************************\
  1897. * inf_GetItemList (Local Routine)
  1898. *
  1899. * Get the items from the INF file and build our array of files from this
  1900. * search. This does quite a bit of work.
  1901. *
  1902. \*****************************************************************************/
  1903. LPINFITEMINFO inf_GetItemList(
  1904. LPINFINFO lpInf,
  1905. LPCTSTR lpszMfgName)
  1906. {
  1907. INFSCAN is;
  1908. DWORD cbSize;
  1909. BOOL bRet;
  1910. // Initialize a default-block to contain our inf-items.
  1911. //
  1912. cbSize = sizeof(INFITEMINFO) + (sizeof(INFITEM) * INF_ITEM_BLOCK);
  1913. // Setup a structure which will be utilized by either the
  1914. // setup-scan-file-queue, or our own routine to process W9X
  1915. // items.
  1916. //
  1917. if (is.lpII = (LPINFITEMINFO)genGAlloc(cbSize)) {
  1918. is.lpInf = lpInf;
  1919. // Add the inf-files to the list.
  1920. //
  1921. if (is.lpII = inf_AddInfFile(lpInf, is.lpII)) {
  1922. if (genIsWin9X(lpInf->idxPlt)) {
  1923. is.lpII = inf_BuildW9XList(lpInf, &is);
  1924. } else {
  1925. is.lpII = inf_BuildWNTList(lpInf, lpszMfgName, &is);
  1926. }
  1927. }
  1928. }
  1929. return is.lpII;
  1930. }
  1931. /*****************************************************************************\
  1932. * inf_GetSection (Local Routine)
  1933. *
  1934. * Allocate a buffer which stores either all section-names or the list of
  1935. * items specified by (lpszSection) in an INF file. Currently, we attempt
  1936. * a realloc if the buffer is not big enough.
  1937. *
  1938. \*****************************************************************************/
  1939. LPTSTR inf_GetSection(
  1940. LPINFINFO lpInf,
  1941. LPCTSTR lpszSct)
  1942. {
  1943. LPTSTR lpszInfFile;
  1944. DWORD dwCnt;
  1945. DWORD cch;
  1946. DWORD dwSize;
  1947. DWORD dwLimit;
  1948. LPTSTR lpszNames = NULL;
  1949. // Get the inf-file-name whith contains the specified section.
  1950. //
  1951. if (lpszInfFile = inf_GetInfFile(lpInf->hInfObj, lpszSct)) {
  1952. dwSize = 0;
  1953. dwLimit = 0;
  1954. while (dwLimit < INF_SECTION_LIMIT) {
  1955. // We'll start this allocation with an assumed max-size. Upon
  1956. // successive tries, this buffer is increased each time by the
  1957. // original buffer allocation.
  1958. //
  1959. dwSize += (INF_SECTION_BLOCK * sizeof(TCHAR));
  1960. dwLimit++;
  1961. // Alloc the buffer and attempt to get the names.
  1962. //
  1963. if (lpszNames = (LPTSTR)genGAlloc(dwSize)) {
  1964. // If a section-name is profided, use that. Otherwise,
  1965. // enumerate all section-names.
  1966. //
  1967. cch = dwSize / sizeof(TCHAR);
  1968. if (lpszSct) {
  1969. dwCnt = GetPrivateProfileSection(lpszSct,
  1970. lpszNames,
  1971. cch,
  1972. lpszInfFile);
  1973. } else {
  1974. dwCnt = GetPrivateProfileSectionNames(lpszNames,
  1975. cch,
  1976. lpszInfFile);
  1977. }
  1978. // If the call says the buffer was OK, then we can
  1979. // assume the names are retrieved. According to spec's,
  1980. // if the return-count is equal to size-2, then buffer
  1981. // isn't quite big-enough (two NULL chars).
  1982. //
  1983. if (dwCnt < (cch - 2))
  1984. goto GetSectDone;
  1985. genGFree(lpszNames, dwSize);
  1986. lpszNames = NULL;
  1987. }
  1988. }
  1989. GetSectDone:
  1990. SPLASSERT((dwLimit < INF_SECTION_LIMIT));
  1991. genGFree(lpszInfFile, genGSize(lpszInfFile));
  1992. }
  1993. return lpszNames;
  1994. }
  1995. /*****************************************************************************\
  1996. * inf_GetMfgName (Local Routine)
  1997. *
  1998. * Get the manufacture-name from the driver-name. Some drivers do not really
  1999. * begin with the manufacture-name. These will have to be special-cased
  2000. * to determine their cooresponding manufacturer-name.
  2001. *
  2002. \*****************************************************************************/
  2003. LPTSTR inf_GetMfgNameExe(
  2004. LPINFINFO lpInf)
  2005. {
  2006. INFCONTEXT ic;
  2007. BOOL bFind;
  2008. LPTSTR lpszNames;
  2009. LPTSTR lpszDrvCpy;
  2010. LPTSTR lpszPtr;
  2011. LPTSTR lpszMfgName = NULL;
  2012. // Make a copy for us to muck with.
  2013. //
  2014. if (lpszDrvCpy = genGAllocStr(lpInf->lpszDrvName)) {
  2015. // Let's assume the best-case and the model-name's first word
  2016. // is the Manufacturer. All we need in this case is to find
  2017. // the first <space> in the driver-name.
  2018. //
  2019. // Find the first word to use in locating the manufacturer.
  2020. //
  2021. if (lpszPtr = genFindChar(lpszDrvCpy, TEXT(' ')))
  2022. *lpszPtr = TEXT('\0');
  2023. // Take the first-word and try to get a manufacture out
  2024. // of it.
  2025. //
  2026. if (lpszMfgName = genGAllocStr(lpszDrvCpy)) {
  2027. // Look for the module-name in the manufacturers section. This
  2028. // will return us an index into the inf-file.
  2029. //
  2030. bFind = inf_GetIdx(lpszMfgName,
  2031. lpInf->lpszDrvName,
  2032. lpInf->hInfObj,
  2033. &ic);
  2034. // If the model-manufacturer lookup failed, then we
  2035. // need to look at other model-manufacturer mappings.
  2036. //
  2037. if (bFind == FALSE) {
  2038. // Free the existing string used for this test. Since,
  2039. // we could conceptually come up with another manufacturer
  2040. // name for this model.
  2041. //
  2042. genGFree(lpszMfgName, genGSize(lpszMfgName));
  2043. lpszMfgName = NULL;
  2044. // Since we were not able to find the model-name through
  2045. // conventional means, we are going to look through every
  2046. // section-name in the Inf for the model-name.
  2047. //
  2048. if (lpszNames = inf_GetSection(lpInf, NULL)) {
  2049. lpszPtr = lpszNames;
  2050. while (*lpszPtr != TEXT('\0')) {
  2051. bFind = inf_GetIdx(lpszPtr,
  2052. lpInf->lpszDrvName,
  2053. lpInf->hInfObj,
  2054. &ic);
  2055. // See if we found a match. If so, break out
  2056. // of our loop.
  2057. //
  2058. if (bFind) {
  2059. lpszMfgName = genGAllocStr(lpszPtr);
  2060. break;
  2061. }
  2062. // Goto the next section.
  2063. //
  2064. lpszPtr = inf_NextStr(lpszPtr);
  2065. }
  2066. genGFree(lpszNames, genGSize(lpszNames));
  2067. }
  2068. }
  2069. }
  2070. genGFree(lpszDrvCpy, genGSize(lpszDrvCpy));
  2071. }
  2072. return lpszMfgName;
  2073. }
  2074. /*****************************************************************************\
  2075. * inf_GetMfgName (Local Routine)
  2076. *
  2077. * Get the manufacture-name from the driver-name. Some drivers do not really
  2078. * begin with the manufacture-name. These will have to be special-cased
  2079. * to determine their cooresponding manufacturer-name.
  2080. *
  2081. \*****************************************************************************/
  2082. LPTSTR inf_GetMfgName(
  2083. LPINFINFO lpInf)
  2084. {
  2085. HANDLE hPrinter;
  2086. LPTSTR lpszMfgName = NULL;
  2087. if (OpenPrinter(lpInf->lpszFrnName, &hPrinter, NULL)) {
  2088. DWORD cbNeeded = 0;
  2089. LPTSTR lpszClientEnvironment = (LPTSTR)genStrCliEnvironment(lpInf->idxPlt);
  2090. GetPrinterDriver( hPrinter,
  2091. lpszClientEnvironment,
  2092. 6,
  2093. NULL,
  2094. 0,
  2095. &cbNeeded
  2096. );
  2097. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
  2098. LPBYTE pData;
  2099. DWORD dwSize = cbNeeded;
  2100. if ( pData = (LPBYTE) genGAlloc(cbNeeded) ) {
  2101. if (GetPrinterDriver( hPrinter,
  2102. lpszClientEnvironment,
  2103. 6,
  2104. pData,
  2105. dwSize,
  2106. &cbNeeded) ) {
  2107. PDRIVER_INFO_6 pDriverInfo = (PDRIVER_INFO_6) pData;
  2108. if (pDriverInfo->pszMfgName)
  2109. lpszMfgName = genGAllocStr(pDriverInfo->pszMfgName);
  2110. else
  2111. SetLastError(ERROR_BAD_ENVIRONMENT);
  2112. }
  2113. genGFree( pData, dwSize );
  2114. }
  2115. }
  2116. ClosePrinter(hPrinter);
  2117. }
  2118. if (NULL == lpszMfgName)
  2119. lpszMfgName = inf_GetMfgNameExe(lpInf);
  2120. return lpszMfgName;
  2121. }
  2122. /*****************************************************************************\
  2123. * inf_BuildItems (Local Routine)
  2124. *
  2125. * This routine builds a file-list of items that the INF setup requires.
  2126. *
  2127. \*****************************************************************************/
  2128. LPINFITEMINFO inf_BuildItems(
  2129. LPINFINFO lpInf)
  2130. {
  2131. LPTSTR lpszMfgName;
  2132. LPINFITEMINFO lpItems = NULL;
  2133. // Get the manufacturer-name that we will be dealing with. If
  2134. // we can't find the matching name that cooresponds with our driver,
  2135. // then no need to proceed.
  2136. //
  2137. if (lpszMfgName = inf_GetMfgName(lpInf)) {
  2138. // Build the item-list. If successful, then rewrite our new
  2139. // inf-files for a flat-install.
  2140. //
  2141. lpItems = inf_GetItemList(lpInf, lpszMfgName);
  2142. genGFree(lpszMfgName, genGSize(lpszMfgName));
  2143. }
  2144. return lpItems;
  2145. }
  2146. /*****************************************************************************\
  2147. * infCreate
  2148. *
  2149. * Creates an INF object.
  2150. *
  2151. \*****************************************************************************/
  2152. HANDLE infCreate(
  2153. LPINFGENPARM lpParm)
  2154. {
  2155. LPINFINFO lpInf;
  2156. if (lpInf = (LPINFINFO)genGAlloc(sizeof(INFINFO))) {
  2157. lpInf->dwCliInfo = lpParm->dwCliInfo;
  2158. lpInf->idxPlt = lpParm->idxPlt;
  2159. lpInf->idxVer = lpParm->idxVer;
  2160. // Allocate our parameter-strings.
  2161. //
  2162. if ( inf_AllocStrings(lpInf, lpParm) )
  2163. return (HANDLE)lpInf;
  2164. // Since the allocate Strings failed free up the Object
  2165. genGFree(lpInf, sizeof(INFINFO));
  2166. }
  2167. return NULL;
  2168. }
  2169. /*****************************************************************************\
  2170. * infProcess
  2171. *
  2172. * Uses INF object to prepare for CAB.
  2173. *
  2174. \*****************************************************************************/
  2175. BOOL infProcess(
  2176. HANDLE hInf)
  2177. {
  2178. LPINFINFO lpInf = (LPINFINFO) hInf;
  2179. // Create handle to setup-inf-object. This requires
  2180. // strings in lpInf to be allocated and correct.
  2181. //
  2182. lpInf->hInfObj = inf_GetInfObj(lpInf);
  2183. if ( lpInf->hInfObj != INVALID_HANDLE_VALUE ) {
  2184. // Retrieve the inf-name from the inf-object.
  2185. //
  2186. if (lpInf->lpszInfName = inf_GetInfName(lpInf)) {
  2187. // Build our file object-list.
  2188. //
  2189. if (lpInf->lpInfItems = inf_BuildItems(lpInf)) {
  2190. // Next, use the item list to determine the cat file and add it
  2191. // to the list. This can't be done any earlier (like in inf_BuildItems() )
  2192. // because it uses the infEnumItems callback, and so it relies on the
  2193. // item list being setup already.
  2194. //
  2195. if (genIsWin9X(lpInf->idxPlt)) {
  2196. // Do something different here for 9X?
  2197. // The server isn't caching the CAT files for 9X drivers, so
  2198. // we don't have access to them anyway.
  2199. //
  2200. return TRUE;
  2201. }
  2202. else {
  2203. if (inf_AddCATFile(lpInf)) {
  2204. return TRUE;
  2205. }
  2206. }
  2207. }
  2208. }
  2209. // Some Type of failure...
  2210. infSetError(lpInf,GetLastError());
  2211. }
  2212. return FALSE;
  2213. }
  2214. /*****************************************************************************\
  2215. * infDestroy
  2216. *
  2217. * Destroys the INF object and all resources allocated on its behalf.
  2218. *
  2219. \*****************************************************************************/
  2220. BOOL infDestroy(
  2221. HANDLE hInf)
  2222. {
  2223. LPINFINFO lpInf;
  2224. BOOL bFree = FALSE;
  2225. if (lpInf = (LPINFINFO)hInf) {
  2226. if (lpInf->hInfObj != INVALID_HANDLE_VALUE)
  2227. SetupCloseInfFile(lpInf->hInfObj);
  2228. if (lpInf->lpszInfName)
  2229. genGFree(lpInf->lpszInfName, genGSize(lpInf->lpszInfName));
  2230. if (lpInf->lpszFrnName)
  2231. genGFree(lpInf->lpszFrnName, genGSize(lpInf->lpszFrnName));
  2232. if (lpInf->lpszDrvName)
  2233. genGFree(lpInf->lpszDrvName, genGSize(lpInf->lpszDrvName));
  2234. if (lpInf->lpszDrvPath)
  2235. genGFree(lpInf->lpszDrvPath, genGSize(lpInf->lpszDrvPath));
  2236. if (lpInf->lpszDstName)
  2237. genGFree(lpInf->lpszDstName, genGSize(lpInf->lpszDstName));
  2238. if (lpInf->lpszDstPath)
  2239. genGFree(lpInf->lpszDstPath, genGSize(lpInf->lpszDstPath));
  2240. if (lpInf->lpszPrtName)
  2241. genGFree(lpInf->lpszPrtName, genGSize(lpInf->lpszPrtName));
  2242. if (lpInf->lpszShrName)
  2243. genGFree(lpInf->lpszShrName, genGSize(lpInf->lpszShrName));
  2244. if (lpInf->lpInfItems)
  2245. genGFree(lpInf->lpInfItems, genGSize(lpInf->lpInfItems));
  2246. bFree = genGFree(lpInf, sizeof(INFINFO));
  2247. }
  2248. return bFree;
  2249. }
  2250. /*****************************************************************************\
  2251. * infEnumItems
  2252. *
  2253. * Enumerates the file-items in the INF object. Enumeration will stop if the
  2254. * user-callback returns FALSE. Otherwise, it will exhaust all files in the
  2255. * list.
  2256. *
  2257. \*****************************************************************************/
  2258. BOOL infEnumItems(
  2259. HANDLE hInf,
  2260. INFENUMPROC pfnEnum,
  2261. LPVOID lpvData)
  2262. {
  2263. LPINFINFO lpInf;
  2264. LPINFITEMINFO lpII;
  2265. DWORD dwItems;
  2266. DWORD idx;
  2267. BOOL bRet = FALSE;
  2268. if ((lpInf = (LPINFINFO)hInf) && (dwItems = lpInf->lpInfItems->dwCount)) {
  2269. for (idx = 0, lpII = lpInf->lpInfItems; idx < dwItems; idx++) {
  2270. bRet = (*pfnEnum)(lpII->aItems[idx].szName,
  2271. lpII->aItems[idx].szPath,
  2272. lpII->aItems[idx].bInf,
  2273. lpvData);
  2274. if (bRet == FALSE)
  2275. return FALSE;
  2276. }
  2277. }
  2278. return bRet;
  2279. }
  2280. /*****************************************************************************\
  2281. * infGetEnvArch
  2282. *
  2283. * Returns the platform/environment type identifier.
  2284. *
  2285. \*****************************************************************************/
  2286. WORD infGetEnvArch(
  2287. HANDLE hInf)
  2288. {
  2289. LPINFINFO lpInf;
  2290. WORD wType = PROCESSOR_ARCHITECTURE_UNKNOWN;
  2291. if (lpInf = (LPINFINFO)hInf)
  2292. wType = genValCliArchitecture(lpInf->idxPlt);
  2293. return wType;
  2294. }
  2295. /*****************************************************************************\
  2296. * infGetEnvArchCurr
  2297. *
  2298. * Returns the platform/environment type for the current-architecture.
  2299. *
  2300. \*****************************************************************************/
  2301. WORD infGetEnvArchCurr(
  2302. HANDLE hInf)
  2303. {
  2304. return genValSvrArchitecture();
  2305. }