Leaked source code of windows server 2003
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.

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