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.

1772 lines
49 KiB

  1. /***************************************************************************
  2. *
  3. * File Name: WPNPIN16.C
  4. *
  5. * Copyright 1997 Hewlett-Packard Company.
  6. * All rights reserved.
  7. *
  8. * 11311 Chinden Blvd.
  9. * Boise, Idaho 83714
  10. *
  11. *
  12. * Description: Source code for WPNPIN16.DLL
  13. *
  14. * Author: Garth Schmeling
  15. *
  16. *
  17. * Modification history:
  18. *
  19. * Date Initials Change description
  20. *
  21. * 10-10-97 GFS Initial checkin
  22. *
  23. *
  24. *
  25. ***************************************************************************/
  26. #include "wpnpin16.h"
  27. /*--------------- For Debug -------------------------*/
  28. //#define GARTH_DEBUG 1
  29. /*****************************************************************************\
  30. * strFree
  31. *
  32. * Free allocated string.
  33. *
  34. \*****************************************************************************/
  35. VOID strFree(
  36. HANDLE hszStr,
  37. LPSTR pszStr)
  38. {
  39. if (hszStr && pszStr)
  40. GlobalUnlock(hszStr);
  41. if (hszStr)
  42. GlobalFree(hszStr);
  43. }
  44. /*****************************************************************************\
  45. * strAlloc
  46. *
  47. * Allocates a string from the heap. This pointer must be freed with
  48. * a call to strFree().
  49. *
  50. \*****************************************************************************/
  51. LPSTR strAlloc(
  52. LPHANDLE phSrc,
  53. LPCSTR pszSrc)
  54. {
  55. DWORD cbSize;
  56. LPSTR pszDst = NULL;
  57. *phSrc = NULL;
  58. cbSize = (pszSrc ? (lstrlen(pszSrc) + 1) : 0);
  59. if (cbSize && (*phSrc = GlobalAlloc(GPTR, cbSize))) {
  60. if (pszDst = (LPSTR)GlobalLock(*phSrc))
  61. lstrcpy(pszDst, pszSrc);
  62. }
  63. return pszDst;
  64. }
  65. /*****************************************************************************\
  66. * strLoad
  67. *
  68. * Get string from resource based upon the ID passed in.
  69. *
  70. \*****************************************************************************/
  71. LPSTR strLoad(
  72. LPHANDLE phszStr,
  73. UINT ids)
  74. {
  75. char szStr[_MAX_RESBUF];
  76. if (LoadString(g_hInst, ids, szStr, sizeof(szStr)) == 0)
  77. szStr[0] = '\0';
  78. return strAlloc(phszStr, szStr);
  79. }
  80. /*****************************************************************************\
  81. * InitStrings
  82. *
  83. *
  84. \*****************************************************************************/
  85. BOOL InitStrings(VOID)
  86. {
  87. cszDefaultPrintProcessor = strLoad(&hszDefaultPrintProcessor, IDS_DEFAULT_PRINTPROCESSOR);
  88. cszMSDefaultDataType = strLoad(&hszMSDefaultDataType , IDS_DEFAULT_DATATYPE);
  89. cszDefaultColorPath = strLoad(&hszDefaultColorPath , IDS_COLOR_PATH);
  90. cszFileInUse = strLoad(&hszFileInUse , IDS_ERR_FILE_IN_USE);
  91. return (cszDefaultPrintProcessor &&
  92. cszMSDefaultDataType &&
  93. cszDefaultColorPath &&
  94. cszFileInUse);
  95. }
  96. /*****************************************************************************\
  97. * FreeeStrings
  98. *
  99. *
  100. \*****************************************************************************/
  101. VOID FreeStrings(VOID)
  102. {
  103. strFree(hszDefaultPrintProcessor, cszDefaultPrintProcessor);
  104. strFree(hszMSDefaultDataType , cszMSDefaultDataType);
  105. strFree(hszDefaultColorPath , cszDefaultColorPath);
  106. strFree(hszFileInUse , cszFileInUse);
  107. }
  108. /*****************************************************************************\
  109. * DllEntryPoint
  110. *
  111. *
  112. \*****************************************************************************/
  113. BOOL FAR PASCAL DllEntryPoint(
  114. DWORD dwReason,
  115. WORD hInst,
  116. WORD wDS,
  117. WORD wHeapSize,
  118. DWORD dwReserved1,
  119. WORD wReserved2)
  120. {
  121. if (g_hInst == NULL) {
  122. g_hInst = (HINSTANCE)hInst;
  123. if (InitStrings() == FALSE)
  124. return FALSE;
  125. }
  126. return thk_ThunkConnect16(cszDll16, cszDll32, hInst, dwReason);
  127. }
  128. //-----------------------------------------------------------------------
  129. // Function: lstrpbrk(lpSearch,lpTargets)
  130. //
  131. // Action: DBCS-aware version of strpbrk.
  132. //
  133. // Return: Pointer to the first character that in lpSearch that is also
  134. // in lpTargets. NULL if not found.
  135. //
  136. // Comment: Use nested loops to avoid allocating memory for DBCS stuff.
  137. //-----------------------------------------------------------------------
  138. LPSTR WINAPI lstrpbrk(LPSTR lpSearch,
  139. LPSTR lpTargets)
  140. {
  141. LPSTR lpOneTarget;
  142. if (lpSearch AND lpTargets)
  143. {
  144. for (;
  145. *lpSearch;
  146. lpSearch=AnsiNext(lpSearch))
  147. {
  148. for (lpOneTarget=lpTargets;
  149. *lpOneTarget;
  150. lpOneTarget=AnsiNext(lpOneTarget))
  151. {
  152. if (*lpSearch==*lpOneTarget)
  153. {
  154. // First byte matches--see if we need to check
  155. // second byte
  156. if (IsDBCSLeadByte(*lpOneTarget))
  157. {
  158. if (*(lpSearch+1) == *(lpOneTarget+1))
  159. return lpSearch;
  160. }
  161. else
  162. return lpSearch;
  163. }
  164. }
  165. }
  166. }
  167. return NULL;
  168. }
  169. //-----------------------------------------------------------------------
  170. // Function: lstrtok(lpSearch,lpTargets)
  171. //
  172. // Action: DBCS-aware version of strtok.
  173. //
  174. // Return: Pointer to next non-NULL token if found, NULL if not.
  175. //-----------------------------------------------------------------------
  176. LPSTR WINAPI lstrtok(LPSTR lpSearch,
  177. LPSTR lpTargets)
  178. {
  179. static LPSTR lpLastSearch;
  180. LPSTR lpFound;
  181. LPSTR lpReturn=NULL;
  182. if (lpSearch)
  183. lpLastSearch=lpSearch;
  184. for (;
  185. lpLastSearch AND *lpLastSearch;
  186. lpLastSearch=AnsiNext(lpLastSearch))
  187. {
  188. // Skip leading white space
  189. while (' '==*lpLastSearch OR '\t'==*lpLastSearch)
  190. lpLastSearch++;
  191. if (lpFound=lstrpbrk(lpLastSearch,lpTargets))
  192. {
  193. if (lpFound==lpLastSearch) // Ignore NULL tokens
  194. continue;
  195. lpReturn=lpLastSearch;
  196. *lpFound='\0';
  197. lpLastSearch=lpFound+1;
  198. break;
  199. }
  200. else
  201. {
  202. lpReturn=lpLastSearch;
  203. lpLastSearch=NULL;
  204. break;
  205. }
  206. }
  207. return lpReturn;
  208. }
  209. //--------------------------------------------------------------------
  210. // Function: FindCorrectSection(szInfFile,szManufacturer,szModel,szSection)
  211. //
  212. // Action: Find the install section in the inf file that corresponds
  213. // to the model name. This may require several different approaches.
  214. // Try the most likely first and then try others.
  215. //
  216. // Side effect: Put the section name in szSection.
  217. //
  218. // Return: TRUE if the section was found, FALSE if not.
  219. //
  220. //--------------------------------------------------------------------
  221. BOOL WINAPI FindCorrectSection(
  222. LPSTR szInfFile,
  223. LPSTR szManufacturer,
  224. LPSTR szModel,
  225. LPSTR szSection)
  226. {
  227. HINF hInf = 0;
  228. HINFLINE hInfLine = 0;
  229. int i = 0;
  230. int nCount = 0;
  231. int nCopied = 0;
  232. int nFields = 0;
  233. BOOL bHaveManu = FALSE;
  234. char lpszBuf[_MAX_LINE];
  235. char lpszTemp[_MAX_LINE];
  236. char lpszTemp2[_MAX_LINE];
  237. // Open the INF file.
  238. if (OK != IpOpen(szInfFile, &hInf))
  239. {
  240. return FALSE;
  241. }
  242. lstrcpy(lpszBuf, cszNull);
  243. lstrcpy(lpszTemp, cszNull);
  244. lstrcpy(lpszTemp2, cszNull);
  245. // Try # 1 to get the manufacturer's section name
  246. // Look for a section corresponding to the manufacturer's
  247. // name. Copy it to lpszBuf. Open that section below.
  248. if (OK == IpFindFirstLine(hInf, szManufacturer, NULL, &hInfLine))
  249. {
  250. lstrcpy(lpszBuf, szManufacturer);
  251. bHaveManu = TRUE;
  252. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #1, Main [HP] Section"));
  253. } // Try # 1
  254. // Try # 2 to get the manufacturer's section name
  255. // Try the main [Manufacturer] section.
  256. // Cycle through each name expecting the name to be in the
  257. // Strings section.
  258. if (!bHaveManu AND
  259. (OK == IpFindFirstLine(hInf, "Manufacturer", NULL, &hInfLine)))
  260. {
  261. // Get the number of lines
  262. if (OK == IpGetLineCount(hInf, "Manufacturer", &nCount))
  263. {
  264. for (i = 0; i < nCount; i++)
  265. {
  266. lpszBuf[0] = '\0';
  267. lpszTemp[0] = '\0';
  268. if (OK == IpGetStringField(hInf, hInfLine, 0, lpszTemp, _MAX_LINE, &nCopied))
  269. {
  270. GenFormStrWithoutPlaceHolders(lpszBuf,lpszTemp,hInf);
  271. // Garth: Use CompareString with the
  272. // IGNORE_CASE, IGNORE_KANATYPE, and IGNORE_WIDTH flags
  273. if (lstrcmpi(szManufacturer, lpszBuf) == 0)
  274. {
  275. // We have found the manufacturer name, see if
  276. // there is a key on the right
  277. nFields = 0;
  278. if ( (OK == IpGetFieldCount(hInf, hInfLine, &nFields)) AND
  279. (nFields > 0) )
  280. {
  281. if (OK == IpGetStringField(hInf, hInfLine, 1, lpszBuf, _MAX_LINE, &nCopied))
  282. {
  283. // There was a value on the right. It is stored in lpszBuf.
  284. // Just try to use it below as the name of the main section.
  285. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #2 Before NULL, lpszTemp = %s", lpszTemp));
  286. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Manual Install = %s", lpszBuf));
  287. lpszTemp[0] = '\0';
  288. }
  289. }
  290. else
  291. {
  292. // There was no value on the right, use the name from
  293. // lpszTemp
  294. lpszBuf[0] = '\0';
  295. lstrcpy(lpszBuf, lpszTemp);
  296. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #3 Manual"));
  297. }
  298. bHaveManu = TRUE;
  299. break;
  300. }
  301. }
  302. if (OK != IpFindNextLine(hInf, &hInfLine))
  303. {
  304. break;
  305. }
  306. }
  307. }
  308. } // Try # 2
  309. // Try # 3 to get the manufacturer's section name
  310. // Try the main [Manufacturer] section.
  311. // The printer manufacturer name does not match the
  312. // driver manufacturer name. (IE Canon and Epson with GCA)
  313. // Check to see if there is only one name in the manufacturer section.
  314. if (!bHaveManu AND
  315. (OK == IpFindFirstLine(hInf, "Manufacturer", NULL, &hInfLine)))
  316. {
  317. // Get the number of lines
  318. if (OK == IpGetLineCount(hInf, "Manufacturer", &nCount))
  319. {
  320. if (nCount IS 1)
  321. {
  322. // Only one line in manufaturer section.
  323. // This has to be our guy.
  324. // See if there is a key on the right
  325. nFields = 0;
  326. lpszBuf[0] = '\0';
  327. IpGetFieldCount(hInf, hInfLine, &nFields);
  328. if (nFields > 0)
  329. {
  330. if (OK == IpGetStringField(hInf, hInfLine, 1, lpszBuf, _MAX_LINE, &nCopied))
  331. {
  332. // There was a value on the right. It is stored in lpszBuf.
  333. // Try to use it below as the name of the main section.
  334. //
  335. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Before NULL <%s>", lpszTemp));
  336. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #4 One Manual <%s>", lpszBuf));
  337. lpszTemp[0] = '\0';
  338. bHaveManu = TRUE;
  339. }
  340. }
  341. else
  342. {
  343. // There was no value on the right. Get the key on the left.
  344. if (OK == IpGetStringField(hInf, hInfLine, 0, lpszBuf, _MAX_LINE, &nCopied))
  345. {
  346. lpszTemp[0] = '\0';
  347. bHaveManu = TRUE;
  348. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #6 One Manual"));
  349. }
  350. }
  351. }
  352. }
  353. } // Try # 3
  354. // Try # 4 to get the manufacturer's section name
  355. // Try a [PnP] section.
  356. if (!bHaveManu AND (OK == IpFindFirstLine(hInf, "PnP", NULL, &hInfLine)))
  357. {
  358. lpszBuf[0] = '\0';
  359. lstrcpy(lpszBuf, "PnP");
  360. bHaveManu = TRUE;
  361. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #6 [Pnp]"));
  362. } // Try # 4
  363. // Try # 6. Get the install section associated with this
  364. // manufacturer and model.
  365. //
  366. // Look for a manufacturer's section with a profile key
  367. // corresponding to the model name. The first key on the RHS
  368. // should be the model section name.
  369. //
  370. if (bHaveManu AND (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine)))
  371. {
  372. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Found first line <%s>", lpszBuf));
  373. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Search for this model <%s>", szModel));
  374. lstrcpy(lpszTemp, cszNull);
  375. if (OK == IpGetProfileString(hInf,lpszBuf,szModel,lpszTemp,_MAX_LINE))
  376. {
  377. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Profile string before lstrtok"));
  378. lstrtok(lpszTemp, cszComma);
  379. // quick check of model section name
  380. //
  381. if (OK == IpFindFirstLine(hInf, lpszTemp, NULL, &hInfLine))
  382. {
  383. if (
  384. (OK == IpGetProfileString(hInf,lpszTemp,"CopyFiles",lpszTemp2,_MAX_LINE))
  385. OR (OK == IpGetProfileString(hInf,lpszTemp,"DataSection",lpszTemp2,_MAX_LINE))
  386. OR (OK == IpGetProfileString(hInf,lpszTemp,"DriverFile",lpszTemp2,_MAX_LINE))
  387. OR (OK == IpGetProfileString(hInf,lpszTemp,"DataFile",lpszTemp2,_MAX_LINE)))
  388. {
  389. lstrcpyn(szSection, lpszTemp, _MAX_PATH_);
  390. IpClose(hInf);
  391. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #7 Found Correct Section"));
  392. return TRUE;
  393. }
  394. // We have a bad INF file:
  395. // We have the manufacturer name and the model name and an
  396. // install section, but it doesn't have any of the keys we need.
  397. // bail.
  398. //
  399. IpClose(hInf);
  400. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #8 Bad INF file"));
  401. return FALSE;
  402. }
  403. }
  404. // The model name doesn't appear as a profile string.
  405. // Perhaps a variable from the Strings sections appears in its place.
  406. // Try that.
  407. if ( (OK == IpGetLineCount(hInf, lpszBuf, &nCount)) AND
  408. (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine)) )
  409. {
  410. for (i = 0; i < nCount; i++)
  411. {
  412. lstrcpy(lpszTemp, cszNull);
  413. if (OK == IpGetStringField(hInf, hInfLine, 0, lpszTemp, _MAX_LINE, &nCopied))
  414. {
  415. GenFormStrWithoutPlaceHolders(lpszTemp2,lpszTemp,hInf);
  416. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : lpszTemp2=%s, lpszTemp=%s", lpszTemp2, lpszTemp));
  417. if (lstrcmpi(szModel, lpszTemp2) == 0)
  418. {
  419. // The model name has a string var on the left
  420. // Get field 1. This is the install section name.
  421. if (OK == IpGetStringField(hInf, hInfLine, 1, lpszTemp, _MAX_LINE, &nCopied))
  422. {
  423. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Before lstrtok comma"));
  424. lstrtok(lpszTemp, cszComma);
  425. // quick check of model section name
  426. //
  427. if (OK == IpFindFirstLine(hInf, lpszTemp, NULL, &hInfLine))
  428. {
  429. if ((OK == IpGetProfileString(hInf,lpszTemp,"CopyFiles",lpszTemp2,_MAX_LINE))
  430. OR (OK == IpGetProfileString(hInf,lpszTemp,"DataSection",lpszTemp2,_MAX_LINE))
  431. OR (OK == IpGetProfileString(hInf,lpszTemp,"DriverFile",lpszTemp2,_MAX_LINE))
  432. OR (OK == IpGetProfileString(hInf,lpszTemp,"DataFile",lpszTemp2,_MAX_LINE)))
  433. {
  434. lstrcpyn(szSection, lpszTemp, _MAX_PATH_);
  435. IpClose(hInf);
  436. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #9 Strings Found Correct Section"));
  437. return TRUE;
  438. }
  439. // We have a bad INF file:
  440. // We have the manufacturer name and the model name and an
  441. // install section, but it doesn't have any of the keys we need.
  442. // bail.
  443. //
  444. IpClose(hInf);
  445. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #10 Strings Bad INF File"));
  446. return FALSE;
  447. }
  448. }
  449. }
  450. }
  451. if (OK != IpFindNextLine(hInf, &hInfLine))
  452. {
  453. break;
  454. }
  455. }
  456. }
  457. } // Try # 6
  458. // Try # 7
  459. // Check to see if there is a valid InstallSection.
  460. //
  461. if (OK == IpFindFirstLine(hInf, "InstallSection", NULL, &hInfLine))
  462. {
  463. // quick check of InstallSection
  464. if (OK == IpFindFirstLine(hInf, "InstallSection", NULL, &hInfLine))
  465. {
  466. if ((OK == IpGetProfileString(hInf,"InstallSection","CopyFiles",lpszTemp2,_MAX_LINE))
  467. OR (OK == IpGetProfileString(hInf,"InstallSection","DataSection",lpszTemp2,_MAX_LINE))
  468. OR (OK == IpGetProfileString(hInf,"InstallSection","DriverFile",lpszTemp2,_MAX_LINE))
  469. OR (OK == IpGetProfileString(hInf,"InstallSection","DataFile",lpszTemp2,_MAX_LINE)))
  470. {
  471. lstrcpyn(szSection, "InstallSection", _MAX_PATH_);
  472. IpClose(hInf);
  473. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #11 Found correct InstallSection"));
  474. return TRUE;
  475. }
  476. }
  477. } // Try # 7
  478. // Try # 8.
  479. // Try the [Strings] section.
  480. if (OK == IpFindFirstLine(hInf, "Strings", NULL, &hInfLine))
  481. {
  482. // Get the number of lines
  483. if (OK == IpGetLineCount(hInf, "Strings", &nCount))
  484. {
  485. for (i = 0; i < nCount; i++)
  486. {
  487. lpszBuf[0] = '\0';
  488. lpszTemp[0] = '\0';
  489. if (OK == IpGetStringField(hInf, hInfLine, 1, lpszTemp, _MAX_LINE, &nCopied))
  490. {
  491. // Garth: Use CompareString with the
  492. // IGNORE_CASE, IGNORE_KANATYPE, and IGNORE_WIDTH flags
  493. if (lstrcmpi(szModel, lpszTemp) == 0)
  494. {
  495. // The model name has a string var on the left
  496. if (OK == IpGetStringField(hInf, hInfLine, 0, lpszBuf, _MAX_LINE, &nCopied))
  497. {
  498. // There was a value on the left, try to use it
  499. if (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine))
  500. {
  501. // quick check of Strings
  502. if (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine))
  503. {
  504. if ((OK == IpGetProfileString(hInf,lpszBuf,"CopyFiles",lpszTemp2,_MAX_LINE))
  505. OR (OK == IpGetProfileString(hInf,lpszBuf,"DataSection",lpszTemp2,_MAX_LINE))
  506. OR (OK == IpGetProfileString(hInf,lpszBuf,"DriverFile",lpszTemp2,_MAX_LINE))
  507. OR (OK == IpGetProfileString(hInf,lpszBuf,"DataFile",lpszTemp2,_MAX_LINE)))
  508. {
  509. lstrcpyn(szSection, lpszBuf, _MAX_PATH_);
  510. IpClose(hInf);
  511. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #12 Found String = Model Section"));
  512. return TRUE;
  513. }
  514. }
  515. }
  516. }
  517. }
  518. }
  519. }
  520. }
  521. } // Try # 8
  522. // No more ideas, Give up.
  523. //
  524. IpClose(hInf);
  525. DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #13 Failed to find section"));
  526. return FALSE;
  527. }
  528. //-----------------------------------------------------------------------
  529. // Function: GetInfOption(hInf,lpszSection,bDataSection,bLocalize,
  530. // lpszDataSection,lpszKeyName,lpszBuffer,wBufSize)
  531. //
  532. // Action: Get the specified keyword from the INF file. Look in the
  533. // appropriate section(s)
  534. //
  535. // Note: Keys may always appear in lpszSection, and may appear in
  536. // lpszDataSection if bDataSection is TRUE. If the key appears
  537. // in both sections, the value from lpszSection takes precedence.
  538. //
  539. // Return: TRUE if we got the option, FALSE if not
  540. //-----------------------------------------------------------------------
  541. BOOL NEAR PASCAL GetInfOption(HINF hInf,
  542. LPSTR lpszSection,
  543. BOOL bDataSection,
  544. BOOL bLocalize,
  545. LPSTR lpszDataSection,
  546. LPSTR lpszKeyName,
  547. LPSTR lpszBuffer,
  548. WORD wBufSize)
  549. {
  550. LPSTR lpszTemp;
  551. BOOL bAllocated;
  552. BOOL bSuccess;
  553. if (bLocalize && wBufSize &&
  554. (lpszTemp=(LPSTR)(HP_GLOBAL_ALLOC_DLL(max(wBufSize,_MAX_PATH_)))))
  555. {
  556. bAllocated=TRUE;
  557. }
  558. else
  559. {
  560. lpszTemp=lpszBuffer;
  561. bAllocated=FALSE;
  562. }
  563. if (OK == IpGetProfileString(hInf,lpszSection,lpszKeyName,lpszTemp,wBufSize))
  564. {
  565. bSuccess=TRUE;
  566. }
  567. else if (bDataSection &&
  568. (OK == IpGetProfileString(hInf,lpszDataSection,
  569. lpszKeyName,lpszTemp,wBufSize)))
  570. {
  571. bSuccess=TRUE;
  572. }
  573. else
  574. bSuccess=FALSE;
  575. if (bAllocated)
  576. {
  577. if (bSuccess)
  578. GenFormStrWithoutPlaceHolders(lpszBuffer,lpszTemp,hInf);
  579. HP_GLOBAL_FREE(lpszTemp);
  580. }
  581. return bSuccess;
  582. }
  583. //-----------------------------------------------------------------------
  584. // Function: myatoi(pszInt)
  585. //
  586. // Yup, the first function that everyone writes!
  587. //-----------------------------------------------------------------------
  588. int WINAPI myatoi(
  589. LPSTR pszInt)
  590. {
  591. int nRet;
  592. char cSave;
  593. for (nRet = 0; ; ++pszInt) {
  594. if ((cSave = (*pszInt - (char)'0')) > 9)
  595. break;
  596. nRet = (nRet * 10) + cSave;
  597. }
  598. return nRet;
  599. }
  600. //------------------------------------------------------------------------
  601. // Function: ZeroMem(lpData,wCount)
  602. //
  603. // Action: Zero-initialize wCount bytes at lpData (duh)
  604. //
  605. // Return: VOID
  606. //------------------------------------------------------------------------
  607. VOID WINAPI ZeroMem(LPVOID lpData,
  608. WORD wCount)
  609. {
  610. LPBYTE lpBuf=(LPBYTE)lpData;
  611. while (wCount--)
  612. {
  613. *lpBuf='\0';
  614. lpBuf++;
  615. }
  616. }
  617. //--------------------------------------------------------------------
  618. // Function: FlushCachedPrinterFiles(void)
  619. //
  620. // Action: Flush printer driver files that might be cached by the
  621. // system. Two caches exist--one maintained by USER, and one
  622. // maintained by winspl16.drv (for old drivers)
  623. //
  624. // Return: Void
  625. //--------------------------------------------------------------------
  626. VOID WINAPI FlushCachedPrinterFiles()
  627. {
  628. HWND hWndMsgSvr;
  629. HMODULE hModWinspl16;
  630. // Send a message to MSGSVR32 to flush the default printer's cached DC.
  631. if (hWndMsgSvr = FindWindow(cszMsgSvr, NULL))
  632. SendMessage(hWndMsgSvr, WM_USER+0x010A, 0, 0L);
  633. // If WINSPL16 is in memory, force it to flush its cache
  634. if (hModWinspl16 = GetModuleHandle(cszWinspl16))
  635. {
  636. WEPPROC fpWep;
  637. if (fpWep = (WEPPROC)GetProcAddress(hModWinspl16, "WEP"))
  638. {
  639. fpWep(0);
  640. }
  641. }
  642. }
  643. //------------------------------------------------------------------
  644. // Function: RenameFailed(lpsi,lpFileSpec)
  645. //
  646. // Action: Handle the case where the rename failed. Give the user a
  647. // chance to close existing apps and shut down printers.
  648. //
  649. // Return: 0 if the file isn't loaded (use default handling)
  650. // VCPN_ABORT if file is in use & user cancelled
  651. // VCPN_RETRY if file is in use & user wants to retry
  652. //------------------------------------------------------------------
  653. LRESULT NEAR PASCAL RenameFailed(LPSI lpsi,
  654. LPVCPFILESPEC lpFileSpec)
  655. {
  656. char szFile[_MAX_PATH_];
  657. if (vsmGetStringName(lpFileSpec->vhstrFileName,szFile,sizeof(szFile)) &&
  658. GetModuleHandle(szFile))
  659. {
  660. char Message[_MAX_PATH_];
  661. // File is in use by the system--give the user the chance to shut
  662. // down existing applications, then continue.
  663. if ( LoadString(g_hInst, IDS_ERR_FILE_IN_USE, Message, _MAX_PATH_) IS 0)
  664. {
  665. DBG_MSG(DBG_LEV_INFO, ("RenameFailed : Could not load string, file in use"));
  666. lstrcpy(Message, cszFileInUse);
  667. }
  668. if (IDCANCEL IS MessageBox(NULL, Message, szFile,
  669. MB_ICONEXCLAMATION|MB_RETRYCANCEL|MB_DEFBUTTON2))
  670. {
  671. return VCPN_ABORT;
  672. }
  673. else
  674. {
  675. // Flush any cached printers & retry
  676. FlushCachedPrinterFiles();
  677. return VCPN_RETRY;
  678. }
  679. }
  680. return 0;
  681. }
  682. //------------------------------------------------------------------
  683. // Function: MyVcpCallbackProc(lpvObj,uMsg,wParam,lParam,lparamRef)
  684. //
  685. // Action: This simply passes through to vcpUICallbackProc, with one
  686. // exception: If a file is in use in the system, we warn the
  687. // user and give them a chance to close existing apps.
  688. //
  689. // Return: Whatever RenameFailed or vcpUICallbackProc return.
  690. //------------------------------------------------------------------
  691. LRESULT CALLBACK MyVcpCallbackProc(LPVOID lpvObj,
  692. UINT uMsg,
  693. WPARAM wParam,
  694. LPARAM lParam,
  695. LPSI lpsi)
  696. {
  697. LRESULT lResult = 0;
  698. if ((VCPM_FILERENAME + VCPM_ERRORDELTA) IS uMsg)
  699. lResult = RenameFailed(lpsi,(LPVCPFILESPEC)lpvObj);
  700. if (! lResult)
  701. {
  702. lResult = vcpUICallbackProc(lpvObj,uMsg,wParam,lParam,
  703. (LPARAM)lpsi->lpVcpInfo);
  704. }
  705. return lResult;
  706. }
  707. //-------------------------------------------------------------------
  708. // Function: OpenQueue(lpsi, lpVcpInfo, lpbOpened)
  709. //
  710. // Action: Initialize lpVcpInfo and open the queue. *lpbOpened reflects
  711. // whether or not we actually opened the queue.
  712. //
  713. // Return: TRUE if successful, FALSE if not.
  714. //-------------------------------------------------------------------
  715. BOOL NEAR PASCAL OpenQueue(LPSI lpsi,
  716. LPVCPUIINFO lpVcpInfo,
  717. BOOL FAR *lpbOpened)
  718. {
  719. BOOL bSuccess = FALSE;
  720. // Initialize the structure
  721. ZeroMem(lpVcpInfo, sizeof(VCPUIINFO));
  722. lpVcpInfo->flags = VCPUI_CREATEPROGRESS;
  723. lpVcpInfo->hwndParent = NULL;
  724. lpsi->lpVcpInfo = (LPBYTE) lpVcpInfo;
  725. // Open the queue
  726. if (RET_OK IS VcpOpen((VIFPROC)MyVcpCallbackProc, (LPARAM)lpsi))
  727. {
  728. bSuccess = TRUE;
  729. *lpbOpened = TRUE;
  730. }
  731. else
  732. {
  733. // Couldn't open the queue, so clear lpVcpInfo
  734. lpsi->lpVcpInfo = NULL;
  735. *lpbOpened = FALSE;
  736. }
  737. return bSuccess;
  738. }
  739. //-------------------------------------------------------------------
  740. // Function: GenInstallCallback(lpGenInfo,lpsi)
  741. //
  742. // Action: This gets called for each file to be queued. Add it to
  743. // the list identified by lpsi->lpFiles, then queue it
  744. // to be copied to the system directory
  745. //
  746. // Return: GENN_SKIP if it's a copy (we queue it ourselves),
  747. // GENN_OK otherwise.
  748. //-------------------------------------------------------------------
  749. LRESULT WINAPI GenInstallCallback(LPGENCALLBACKINFO lpGenInfo,
  750. LPSI lpsi)
  751. {
  752. int wLength;
  753. int wMaxLength;
  754. int wChunk;
  755. if (GENO_COPYFILE != lpGenInfo->wOperation)
  756. return GENN_OK;
  757. // Save the dependent file in lpsi->lpFiles. wFilesAllocated and
  758. // wFilesUsed are used to keep track of memory usage.
  759. wLength = lstrlen(lpGenInfo->pszDstFileName);
  760. // Pad the length if it's going to LDID_COLOR
  761. if (LDID_COLOR IS lpGenInfo->ldidDst)
  762. wMaxLength = wLength + MAX_COLOR_PATH;
  763. else
  764. wMaxLength = wLength;
  765. wChunk = max(256,wMaxLength);
  766. // This is where we allocate lpFiles the first time
  767. if (! lpsi->lpFiles)
  768. {
  769. if (lpsi->lpFiles = (unsigned char *)HP_GLOBAL_ALLOC_DLL(wChunk))
  770. {
  771. lpsi->wFilesAllocated = wChunk;
  772. }
  773. else
  774. {
  775. return GENN_SKIP;
  776. }
  777. }
  778. // double NULL terminated
  779. if ((lpsi->wFilesUsed + wMaxLength + 2) > lpsi->wFilesAllocated)
  780. {
  781. LPSTR lpNew;
  782. lpNew = (unsigned char *)HP_GLOBAL_REALLOC_DLL(lpsi->lpFiles,
  783. lpsi->wFilesAllocated + wChunk, GMEM_ZEROINIT);
  784. if (lpNew)
  785. {
  786. lpsi->wFilesAllocated += wChunk;
  787. lpsi->lpFiles = (unsigned char *) lpNew;
  788. }
  789. else
  790. {
  791. return GENN_SKIP;
  792. }
  793. }
  794. // Add this file to the list && ensure that it's doubly-NULL
  795. // terminated. If it's going to LDID_COLOR, prepend "COLOR\"
  796. // to the string
  797. if (LDID_COLOR IS lpGenInfo->ldidDst)
  798. {
  799. char ColorPath[MAX_COLOR_PATH];
  800. if ( LoadString(g_hInst, IDS_COLOR_PATH, ColorPath, MAX_COLOR_PATH) IS 0)
  801. {
  802. strcpy(ColorPath, "COLOR\\");
  803. }
  804. strcpy((LPSTR)(lpsi->lpFiles + lpsi->wFilesUsed), ColorPath);
  805. lpsi->wFilesUsed += strlen(ColorPath);
  806. }
  807. strcpy((LPSTR)(lpsi->lpFiles + lpsi->wFilesUsed), lpGenInfo->pszDstFileName);
  808. lpsi->wFilesUsed += (wLength + 1);
  809. lpsi->lpFiles[lpsi->wFilesUsed] = '\0';
  810. return GENN_SKIP;
  811. }
  812. //-------------------------------------------------------------------
  813. // Function: QueueNewInf(lpsi, lpdn)
  814. //
  815. // Action: Call GenInstallEx to queue up the files we need to copy.
  816. //
  817. // Return: TRUE if we should continue, FALSE if not.
  818. //-------------------------------------------------------------------
  819. BOOL WINAPI QueueNewInf(LPSI lpsi, LPDRIVER_NODE lpdn)
  820. {
  821. if (lpdn)
  822. {
  823. return (RET_OK == GenInstallEx((HINF)lpsi->hModelInf,
  824. lpdn->lpszSectionName, GENINSTALL_DO_FILES, NULL,
  825. (GENCALLBACKPROC)GenInstallCallback, (LPARAM)lpsi));
  826. }
  827. return FALSE;
  828. }
  829. //-------------------------------------------------------------------
  830. // Function: CloseQueue(lpsi, bSuccessSoFar, bOpened)
  831. //
  832. // Action: Close the VCP queue and report any errors to the user.
  833. // If bSuccessSoFar is FALSE, abandon the queue & return FALSE
  834. //
  835. // Return: TRUE if the copy was successful, FALSE if not.
  836. //-------------------------------------------------------------------
  837. BOOL NEAR PASCAL CloseQueue(LPSI lpsi,
  838. BOOL bSuccessSoFar,
  839. BOOL bOpened)
  840. {
  841. BOOL bSuccess = FALSE;
  842. if (! bOpened)
  843. bSuccess = bSuccessSoFar;
  844. else
  845. {
  846. if (! bSuccessSoFar)
  847. VcpClose(VCPFL_ABANDON, NULL);
  848. else if (lpsi->bDontQueueFiles)
  849. {
  850. VcpClose(VCPFL_ABANDON, NULL);
  851. bSuccess=TRUE;
  852. }
  853. // The queue is now closed, so clear lpsi->lpVcpInfo
  854. if (lpsi->lpVcpInfo)
  855. lpsi->lpVcpInfo = NULL;
  856. }
  857. return bSuccess;
  858. }
  859. //-----------------------------------------------------------------------
  860. // Function: WrapVcpCopy(lpsi,lpfnQueueFunction,lpdn)
  861. //
  862. // Action: Wrap lpfnQueueFunction inside calls to open & close the
  863. // queue. If lpsi->bDontCopyFiles is TRUE, we'll close the
  864. // queue without copying anything.
  865. //
  866. // Return: TRUE if everything went smoothly, FALSE if not.
  867. //-----------------------------------------------------------------------
  868. BOOL WINAPI WrapVcpCopy(LPSI lpsi,
  869. LPQUEUEPROC lpfnQueueFunction,
  870. LPDRIVER_NODE lpdn)
  871. {
  872. VCPUIINFO VcpInfo;
  873. BOOL bSuccess=FALSE;
  874. BOOL bOpened=FALSE;
  875. if (OpenQueue(lpsi, &VcpInfo, &bOpened))
  876. {
  877. BOOL bQueuedOK;
  878. bQueuedOK = lpfnQueueFunction(lpsi, lpdn);
  879. bSuccess = CloseQueue(lpsi, bQueuedOK, bOpened);
  880. }
  881. return bSuccess;
  882. }
  883. //--------------------------------------------------------------------
  884. // Function: PrintLPSI(lpsi)
  885. //
  886. // Action: Print out the contents of the LPSI
  887. //
  888. // Side effect: None
  889. //
  890. // Return: VOID
  891. //
  892. //--------------------------------------------------------------------
  893. VOID PrintLPSI(LPSI lpsi)
  894. {
  895. DBG_MSG(DBG_LEV_INFO, ("LPSI : dwDriverVersion : %#lX", (DWORD)lpsi->dwDriverVersion));
  896. DBG_MSG(DBG_LEV_INFO, ("LPSI : dwUniqueID : %d" , lpsi->dwUniqueID));
  897. DBG_MSG(DBG_LEV_INFO, ("LPSI : bNetPrinter : %d" , lpsi->bNetPrinter));
  898. DBG_MSG(DBG_LEV_INFO, ("LPSI : wFilesUsed : %d" , lpsi->wFilesUsed));
  899. DBG_MSG(DBG_LEV_INFO, ("LPSI : wFilesAllocated : %d" , lpsi->wFilesAllocated));
  900. DBG_MSG(DBG_LEV_INFO, ("LPSI : wRetryTimeout : %d" , lpsi->wRetryTimeout));
  901. DBG_MSG(DBG_LEV_INFO, ("LPSI : wDNSTimeout : %d" , lpsi->wDNSTimeout));
  902. DBG_MSG(DBG_LEV_INFO, ("LPSI : bDontQueueFiles : %d" , lpsi->bDontQueueFiles));
  903. DBG_MSG(DBG_LEV_INFO, ("LPSI : bNoTestPage : %d" , lpsi->bNoTestPage));
  904. DBG_MSG(DBG_LEV_INFO, ("LPSI : hModelInf : %0X" , lpsi->hModelInf));
  905. DBG_MSG(DBG_LEV_INFO, ("LPSI : lpPrinterInfo2 : %d" , lpsi->lpPrinterInfo2));
  906. DBG_MSG(DBG_LEV_INFO, ("LPSI : lpDriverInfo3 : %d" , lpsi->lpDriverInfo3));
  907. DBG_MSG(DBG_LEV_INFO, ("LPSI : szFriendly : %s" , lpsi->szFriendly));
  908. DBG_MSG(DBG_LEV_INFO, ("LPSI : szModel : %s" , lpsi->szModel));
  909. DBG_MSG(DBG_LEV_INFO, ("LPSI : szDefaultDataType : %s" , lpsi->szDefaultDataType));
  910. DBG_MSG(DBG_LEV_INFO, ("LPSI : szBinName : %s" , lpsi->BinName));
  911. DBG_MSG(DBG_LEV_INFO, ("LPSI : szShareName : %s" , lpsi->ShareName));
  912. DBG_MSG(DBG_LEV_INFO, ("LPSI : INFfileName : %s" , lpsi->INFfileName));
  913. DBG_MSG(DBG_LEV_INFO, ("LPSI : szPort : %s" , lpsi->szPort));
  914. DBG_MSG(DBG_LEV_INFO, ("LPSI : szDriverFile : %s" , lpsi->szDriverFile));
  915. DBG_MSG(DBG_LEV_INFO, ("LPSI : szDataFile : %s" , lpsi->szDataFile));
  916. DBG_MSG(DBG_LEV_INFO, ("LPSI : szConfigFile : %s" , lpsi->szConfigFile));
  917. DBG_MSG(DBG_LEV_INFO, ("LPSI : szHelpFile : %s" , lpsi->szHelpFile));
  918. DBG_MSG(DBG_LEV_INFO, ("LPSI : szPrintProcessor : %s" , lpsi->szPrintProcessor));
  919. DBG_MSG(DBG_LEV_INFO, ("LPSI : szVendorSetup : %s" , lpsi->szVendorSetup));
  920. DBG_MSG(DBG_LEV_INFO, ("LPSI : szVendorInstaller : %s" , lpsi->szVendorInstaller));
  921. }
  922. //-----------------------------------------------------------------------
  923. // Function: FindSelectedDriver(lpsi, lpdn)
  924. //
  925. // Action: Try to find the install section associated with the specified
  926. // model. If the currently selected driver matches the model, we
  927. // get all the required info from it.
  928. //
  929. // Note: Upon entry
  930. // lpdn->lpszSectionName
  931. // has the name of the correct section in the INF file.
  932. //
  933. // Return: TRUE is successful, FALSE if not.
  934. //-----------------------------------------------------------------------
  935. BOOL WINAPI FindSelectedDriver(
  936. LPSI lpsi,
  937. LPDRIVER_NODE lpdn)
  938. {
  939. HINFLINE hInfDummy;
  940. HINF myHINF;
  941. WORD wTest;
  942. BOOL bDataSection=FALSE;
  943. BOOL bQueuedOK;
  944. char szData[_MAX_PATH_];
  945. char szTimeout[10];
  946. char lpSection[_MAX_PATH_];
  947. // Extract all of our information from the INF file.
  948. // Open the INF file.
  949. if (OK != IpOpen(lpsi->INFfileName, &myHINF))
  950. {
  951. return FALSE;
  952. }
  953. lstrcpyn(lpSection, lpdn->lpszSectionName, _MAX_PATH_);
  954. if (OK != IpFindFirstLine(myHINF, lpSection, NULL, &hInfDummy))
  955. {
  956. IpClose(myHINF);
  957. return FALSE;
  958. }
  959. lpsi->hModelInf = (int) myHINF;
  960. // Build the dependent file list now.
  961. lpsi->bDontQueueFiles=TRUE;
  962. bQueuedOK = WrapVcpCopy(lpsi,QueueNewInf,lpdn);
  963. lpsi->bDontQueueFiles = FALSE;
  964. if (!bQueuedOK)
  965. {
  966. IpClose(myHINF);
  967. lpsi->hModelInf = 0;
  968. return FALSE;
  969. }
  970. if (!lpsi->wFilesUsed)
  971. {
  972. IpClose(myHINF);
  973. lpsi->hModelInf = 0;
  974. return FALSE;
  975. }
  976. // Check for a data section. If none is specified, then the
  977. // data section is the section associated with this device.
  978. // The DataSection key can only appear in the installer section
  979. // (for obvious reasons).
  980. bDataSection=GetInfOption(myHINF,lpSection,FALSE,FALSE,NULL,
  981. cszDataSection,szData,sizeof(szData));
  982. // Don't change szData below this line! (It may contain the
  983. // data section name)
  984. // Get the driver name (default is the primary section name)
  985. if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  986. cszDriverFile,lpsi->szDriverFile,sizeof(lpsi->szDriverFile)))
  987. {
  988. lstrcpyn(lpsi->szDriverFile,lpSection,sizeof(lpsi->szDriverFile));
  989. }
  990. // Get the data file name (default is the primary section name)
  991. if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  992. cszDataFile,lpsi->szDataFile,sizeof(lpsi->szDataFile)))
  993. {
  994. lstrcpyn(lpsi->szDataFile,lpSection,sizeof(lpsi->szDataFile));
  995. }
  996. // Get the config file name (default is the driver name)
  997. if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  998. cszConfigFile,lpsi->szConfigFile,sizeof(lpsi->szConfigFile)))
  999. {
  1000. lstrcpyn(lpsi->szConfigFile,lpsi->szDriverFile,
  1001. sizeof(lpsi->szConfigFile));
  1002. }
  1003. // Get the help file (default is none)
  1004. GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  1005. cszHelpFile,lpsi->szHelpFile,sizeof(lpsi->szHelpFile));
  1006. // Get the Print Processor (default comes from resources)
  1007. if (!GetInfOption(myHINF,lpSection,bDataSection,TRUE,szData,
  1008. cszPrintProcessor,lpsi->szPrintProcessor,
  1009. sizeof(lpsi->szPrintProcessor)))
  1010. {
  1011. if (LoadString(g_hInst,IDS_DEFAULT_PRINTPROCESSOR,
  1012. lpsi->szPrintProcessor,sizeof(lpsi->szPrintProcessor)) IS 0)
  1013. {
  1014. DBG_MSG(DBG_LEV_INFO, ("FindSelectedDriver : Could not load string, default print processor"));
  1015. lstrcpy(lpsi->szPrintProcessor, cszDefaultPrintProcessor);
  1016. }
  1017. }
  1018. // Get the Default Data Type (default comes from resources)
  1019. if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  1020. cszDefaultDataType,lpsi->szDefaultDataType,
  1021. sizeof(lpsi->szDefaultDataType)))
  1022. {
  1023. if ( LoadString(g_hInst,IDS_DEFAULT_DATATYPE,
  1024. lpsi->szDefaultDataType,sizeof(lpsi->szDefaultDataType)) IS 0)
  1025. {
  1026. DBG_MSG(DBG_LEV_INFO, ("FindSelectedDriver : Could not load string, default data type"));
  1027. lstrcpy(lpsi->szDefaultDataType, cszMSDefaultDataType);
  1028. }
  1029. }
  1030. // Get the Vendor Setup (default is none)
  1031. GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  1032. cszVendorSetup,lpsi->szVendorSetup,sizeof(lpsi->szVendorSetup));
  1033. // Get the Vendor Installer (default is none)
  1034. GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  1035. cszVendorInstaller,lpsi->szVendorInstaller,
  1036. sizeof(lpsi->szVendorInstaller));
  1037. // Get the device timeouts (ClearPrinterInfo defaults to 15 & 45)
  1038. if (GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  1039. cszRetryTimeout,szTimeout,sizeof(szTimeout)))
  1040. {
  1041. if (wTest=myatoi(szTimeout))
  1042. lpsi->wRetryTimeout=wTest;
  1043. }
  1044. if (GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData,
  1045. cszNotSelectedTimeout,szTimeout,sizeof(szTimeout)))
  1046. {
  1047. if (wTest=myatoi(szTimeout))
  1048. lpsi->wDNSTimeout=wTest;
  1049. }
  1050. // Decide whether or not we should use the test page. Test page is
  1051. // skipped if the INF specifically requests it, if we have a
  1052. // vendor-supplied DLL, or if the port is in conflict.
  1053. if ( (lpsi->szVendorSetup[0]) ||
  1054. (lpsi->szVendorInstaller[0]) ||
  1055. GetInfOption(myHINF, lpSection, bDataSection, FALSE, szData,
  1056. cszNoTestPage, szTimeout, sizeof(szTimeout)))
  1057. {
  1058. lpsi->bNoTestPage=TRUE;
  1059. }
  1060. IpClose(myHINF);
  1061. lpsi->hModelInf = 0;
  1062. return TRUE;
  1063. }
  1064. //--------------------------------------------------------------------
  1065. // Function: CreateDriverNode()
  1066. //
  1067. // Action: Create a driver node and initialize it..
  1068. //
  1069. // Side effect: Allocates memory that must be freed by caller..
  1070. //
  1071. // Return: RET_OK on success.
  1072. //
  1073. //--------------------------------------------------------------------
  1074. RETERR WINAPI CreateDriverNode(
  1075. LPLPDRIVER_NODE lplpdn,
  1076. UINT Rank,
  1077. UINT InfType,
  1078. unsigned InfDate,
  1079. LPCSTR lpszDevDescription,
  1080. LPCSTR lpszDrvDescription,
  1081. LPCSTR lpszProviderName,
  1082. LPCSTR lpszMfgName,
  1083. LPCSTR lpszInfFileName,
  1084. LPCSTR lpszSectionName,
  1085. DWORD dwPrivateData)
  1086. {
  1087. int DrvDescLen = 0;
  1088. int DevDescLen = 0;
  1089. int SectionLen = 0;
  1090. LPSTR lpszTemp;
  1091. // Compute a allocate space for the variable part of the DRIVER node
  1092. //
  1093. DrvDescLen = lstrlen(lpszDrvDescription);
  1094. DevDescLen = lstrlen(lpszDevDescription);
  1095. SectionLen = lstrlen(lpszSectionName);
  1096. *lplpdn = (LPDRIVER_NODE) HP_GLOBAL_ALLOC_DLL(sizeof(DRIVER_NODE) +
  1097. DrvDescLen + DevDescLen + SectionLen +
  1098. (2 * MAX_DEVICE_ID_LEN) + _MAX_PATH_ + NSTRINGS);
  1099. if (*lplpdn == NULL)
  1100. {
  1101. return(ERR_DI_LOW_MEM);
  1102. }
  1103. else
  1104. {
  1105. (*lplpdn)->Rank = Rank;
  1106. (*lplpdn)->InfType = InfType;
  1107. (*lplpdn)->InfDate = InfDate;
  1108. // For compatibility copy the DevDescription into lpszDescription
  1109. lpszTemp = (LPSTR)((DWORD)(*lplpdn) + sizeof(DRIVER_NODE));
  1110. lstrcpy(lpszTemp, lpszDevDescription);
  1111. (*lplpdn)->lpszDescription = lpszTemp;
  1112. // New. Copy the Drv description into the lpszDrvDescription
  1113. lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(DevDescLen + 1));
  1114. lstrcpy(lpszTemp, lpszDevDescription);
  1115. (*lplpdn)->lpszDrvDescription = lpszTemp;
  1116. lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(DrvDescLen + 1));
  1117. lstrcpy(lpszTemp, lpszSectionName);
  1118. (*lplpdn)->lpszSectionName = lpszTemp;
  1119. // Init HardwareID and CompatIDs buffers to empty strings
  1120. lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(SectionLen + 1));
  1121. *lpszTemp = '\0';
  1122. (*lplpdn)->lpszHardwareID = lpszTemp;
  1123. lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(MAX_DEVICE_ID_LEN + 1));
  1124. *lpszTemp = '\0';
  1125. (*lplpdn)->lpszCompatIDs = lpszTemp;
  1126. (*lplpdn)->atInfFileName = GlobalAddAtom(lpszInfFileName);
  1127. if (lpszMfgName != NULL) {
  1128. (*lplpdn)->atMfgName = GlobalAddAtom(lpszMfgName);
  1129. }
  1130. if (lpszProviderName != NULL) {
  1131. (*lplpdn)->atProviderName = GlobalAddAtom(lpszProviderName);
  1132. }
  1133. return(RET_OK);
  1134. }
  1135. }
  1136. //--------------------------------------------------------------------
  1137. //
  1138. // Function: HaveAllFiles(lpsi)
  1139. //
  1140. // Action: Do we have all printer driver dependent files in this directory?
  1141. //
  1142. // Return: TRUE if all found, FALSE if not
  1143. //
  1144. //--------------------------------------------------------------------
  1145. BOOL WINAPI HaveAllFiles(LPSI lpsi, LPSTR cszPath)
  1146. {
  1147. int result;
  1148. LPSTR lpThisFile;
  1149. struct stat statBuf;
  1150. char fileSpec[_MAX_PATH_];
  1151. BOOL fileNotFound = FALSE;
  1152. // Verify that all the dependent files are in the directory
  1153. // pointed to by cszPath.
  1154. //
  1155. for (lpThisFile = (char *)lpsi->lpFiles; *lpThisFile;
  1156. lpThisFile += (lstrlen(lpThisFile) + 1))
  1157. {
  1158. // Get data associated with file
  1159. lstrcpy(fileSpec, cszPath);
  1160. lstrcat(fileSpec, cszBackslash);
  1161. lstrcat(fileSpec, lpThisFile);
  1162. result = stat( fileSpec, (struct stat *)&statBuf);
  1163. // Check if statistics are valid:
  1164. if ( result ISNT 0 )
  1165. {
  1166. DBG_MSG(DBG_LEV_INFO, ("HaveAllFiles : File not found <%s>", fileSpec));
  1167. fileNotFound = TRUE;
  1168. break;
  1169. }
  1170. }
  1171. return !fileNotFound;
  1172. }
  1173. //--------------------------------------------------------------------
  1174. //
  1175. // Function: CopyNeededFiles(lpsi, cszPath)
  1176. //
  1177. // Action: Copy all printer driver files for this printer from the
  1178. // source directory to the requied printer driver directory.
  1179. //
  1180. // Return: RET_OK on success.
  1181. // RET_FILE_COPY_ERROR is there is a file copy error
  1182. //
  1183. //--------------------------------------------------------------------
  1184. DWORD WINAPI CopyNeededFiles(LPSI lpsi, LPSTR cszPath)
  1185. {
  1186. DWORD dwResult = RET_OK;
  1187. LONG lResult;
  1188. LPSTR lpThisFile;
  1189. OFSTRUCT ofStrSrc;
  1190. OFSTRUCT ofStrDest;
  1191. HFILE hfSrcFile, hfDstFile;
  1192. char fileSource[_MAX_PATH_];
  1193. char fileDest[_MAX_PATH_];
  1194. char destDir[_MAX_PATH_];
  1195. DBG_MSG(DBG_LEV_INFO, ("CopyNeededFiles : About to flush printer files"));
  1196. lstrcpy(destDir, lpsi->szDriverDir);
  1197. if (lstrcmpi(destDir, cszPath) IS 0) {
  1198. // all required files are in the destination directory
  1199. //
  1200. return RET_OK;
  1201. }
  1202. // Flush any cached files the system may be holding
  1203. //
  1204. FlushCachedPrinterFiles();
  1205. LZStart();
  1206. for (lpThisFile = (char *)lpsi->lpFiles; *lpThisFile;
  1207. lpThisFile += (lstrlen(lpThisFile) + 1)) {
  1208. lstrcpy(fileSource, cszNull);
  1209. lstrcat(fileSource, cszPath);
  1210. lstrcat(fileSource, cszBackslash);
  1211. lstrcat(fileSource, lpThisFile);
  1212. lstrcpy(fileDest, cszNull);
  1213. lstrcat(fileDest, destDir);
  1214. lstrcat(fileDest, cszBackslash);
  1215. lstrcat(fileDest, lpThisFile);
  1216. lResult = -1;
  1217. if (hfSrcFile = LZOpenFile(fileSource, &ofStrSrc, OF_READ)) {
  1218. if (hfDstFile = LZOpenFile(fileDest, &ofStrDest, OF_CREATE)) {
  1219. #if 0
  1220. lResult = CopyLZFile(hfSrcFile, hfDstFile);
  1221. #else
  1222. // Hack. If spooler has a file locked, then this call
  1223. // would fail resulting in the class-installer being called
  1224. // to copy the files. But for some reason, the class-installer
  1225. // prompts a path-dialog wanting to know where the files
  1226. // are. Several attempts at fixing up the device-info
  1227. // struct with path-information failed to remedy this
  1228. // situation. Therefore, for now, we will prevent this
  1229. // CopyLZFile() from returning error to keep away from
  1230. // the class-installer until this problem can be figured
  1231. // out.
  1232. //
  1233. // See the caller of this routine to see how the class-
  1234. // installer is called.
  1235. //
  1236. CopyLZFile(hfSrcFile, hfDstFile);
  1237. lResult = 0;
  1238. #endif
  1239. LZClose(hfDstFile);
  1240. } else {
  1241. DBG_MSG(DBG_LEV_INFO, ("CopyNeededFiles : Could not create dst-file <%s>", fileDest));
  1242. }
  1243. LZClose(hfSrcFile);
  1244. } else {
  1245. DBG_MSG(DBG_LEV_INFO, ("CopyNeededFiles : Could not create src-file <%s>", fileSource));
  1246. }
  1247. if (lResult < 0) {
  1248. dwResult = RET_FILE_COPY_ERROR;
  1249. break;
  1250. }
  1251. }
  1252. LZDone();
  1253. return dwResult;
  1254. }
  1255. //--------------------------------------------------------------------
  1256. // Function: ParseINF16(LPSI)
  1257. //
  1258. // Action: Parse the INF file and store required info in LPSI.
  1259. //
  1260. // Return: RET_OK on success.
  1261. // RET_SECT_NOT_FOUND if no install section for this model
  1262. // RET_DRIVER_NODE_ERROR if memory error
  1263. // RET_INVALID_INFFILE other problem with INF file
  1264. //
  1265. //--------------------------------------------------------------------
  1266. RETERR FAR PASCAL ParseINF16(LPSI lpsi)
  1267. {
  1268. RETERR ret = RET_OK;
  1269. LPDRIVER_NODE lpdn = NULL;
  1270. char szManufacturer[_MAX_PATH_];
  1271. char szSection[_MAX_PATH_];
  1272. char cszPath[_MAX_PATH_];
  1273. // Get the manufacturer
  1274. //
  1275. lstrcpyn(szManufacturer,lpsi->szModel,sizeof(szManufacturer));
  1276. lstrtok(szManufacturer,cszSpace);
  1277. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : Search inf<%s> mfg<%s> model<%s>", lpsi->INFfileName, szManufacturer, lpsi->szModel));
  1278. // Get the correct section name
  1279. if (!FindCorrectSection(lpsi->INFfileName, szManufacturer, lpsi->szModel, szSection))
  1280. {
  1281. if (lstrcmpi(szManufacturer, "HP") IS 0)
  1282. {
  1283. lstrcpy(szManufacturer, "Hewlett-Packard");
  1284. if (!FindCorrectSection(lpsi->INFfileName, szManufacturer, lpsi->szModel, szSection))
  1285. {
  1286. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Failed"));
  1287. return RET_SECT_NOT_FOUND;
  1288. } else {
  1289. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Succeeded"));
  1290. }
  1291. } else {
  1292. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Failed"));
  1293. return RET_SECT_NOT_FOUND;
  1294. }
  1295. } else {
  1296. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Succeeded"));
  1297. }
  1298. // Create a driver node
  1299. //
  1300. if (RET_OK != CreateDriverNode(&lpdn,
  1301. 0,
  1302. INFTYPE_TEXT,
  1303. NULL,
  1304. lpsi->szModel,
  1305. cszNull,
  1306. cszNull,
  1307. szManufacturer,
  1308. lpsi->INFfileName,
  1309. szSection,
  1310. 0))
  1311. {
  1312. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : CreateDriverNode Failed"));
  1313. return RET_DRIVER_NODE_ERROR;
  1314. } else {
  1315. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : CreateDriverNode Succeeded"));
  1316. }
  1317. // Find the selected driver and dependent files in the INF. Store in lpsi.
  1318. //
  1319. if (! FindSelectedDriver(lpsi, lpdn)) {
  1320. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindSelectedDriver Failed"));
  1321. if (lpdn->atInfFileName ISNT 0)
  1322. GlobalDeleteAtom(lpdn->atInfFileName);
  1323. if (lpdn->atMfgName ISNT 0)
  1324. GlobalDeleteAtom(lpdn->atMfgName);
  1325. if (lpdn->atProviderName ISNT 0)
  1326. GlobalDeleteAtom(lpdn->atProviderName);
  1327. HP_GLOBAL_FREE(lpdn);
  1328. return RET_INVALID_INFFILE;
  1329. } else {
  1330. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindSelectedDriver Succeeded"));
  1331. }
  1332. // If there is not a driver already installed for this printer,
  1333. // Copy the driver files to the driver directory.
  1334. if (lpsi->wCommand IS CMD_INSTALL_DRIVER)
  1335. {
  1336. if ( getcwd(cszPath, _MAX_PATH_) IS NULL)
  1337. lstrcpy(cszPath, ".");
  1338. if ((HaveAllFiles(lpsi, cszPath) IS TRUE)
  1339. AND
  1340. (CopyNeededFiles(lpsi, cszPath) IS RET_OK)
  1341. )
  1342. {
  1343. // We have all the needed files in the directory pointed to by cszPath.
  1344. // They have been copied to the printer driver directory.
  1345. ret = RET_OK;
  1346. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : All files copied to final directory"));
  1347. } else {
  1348. #define HKEY_LOCAL_MACHINE (( HKEY ) 0x80000002 )
  1349. DEVICE_INFO *lpdi;
  1350. ret = DiCreateDeviceInfo(&lpdi,
  1351. lpsi->szModel,
  1352. 0,
  1353. HKEY_LOCAL_MACHINE,
  1354. NULL,
  1355. "Printer",
  1356. NULL);
  1357. // Install the driver files. This will only copy files that
  1358. // need to be copied.
  1359. //
  1360. if (ret IS OK) {
  1361. LPDRIVER_NODE oldDN = NULL;
  1362. oldDN = lpdi->lpSelectedDriver;
  1363. lpdi->lpSelectedDriver = lpdn;
  1364. ret = DiCallClassInstaller(DIF_INSTALLDEVICEFILES, lpdi);
  1365. lpdi->lpSelectedDriver = oldDN;
  1366. oldDN = NULL;
  1367. DiDestroyDeviceInfoList(lpdi);
  1368. lpdi = NULL;
  1369. }
  1370. switch (ret) {
  1371. case OK:
  1372. case ERR_DI_NOFILECOPY:
  1373. ret = RET_OK;
  1374. break;
  1375. case ERR_DI_USER_CANCEL:
  1376. ret = RET_USER_CANCEL;
  1377. break;
  1378. case ERR_DI_LOW_MEM:
  1379. ret = RET_ALLOC_ERR;
  1380. break;
  1381. case ERR_DI_BAD_INF:
  1382. ret = RET_INVALID_INFFILE;
  1383. break;
  1384. case ERR_DI_INVALID_DEVICE_ID:
  1385. case ERR_DI_INVALID_COMP_DEVICE_LIST:
  1386. case ERR_DI_REG_API: // Error returned by Reg API.
  1387. case ERR_DI_BAD_DEV_INFO: // Device Info struct invalid
  1388. case ERR_DI_INVALID_CLASS_INSTALLER: // Registry entry / DLL invalid
  1389. case ERR_DI_DO_DEFAULT: // Take default action
  1390. case ERR_DI_BAD_CLASS_INFO: // Class Info Struct invalid
  1391. case ERR_DI_BAD_MOVEDEV_PARAMS: // Bad Move Device Params struct
  1392. case ERR_DI_NO_INF: // No INF found on OEM disk
  1393. case ERR_DI_BAD_PROPCHANGE_PARAMS: // Bad property change param struct
  1394. case ERR_DI_BAD_SELECTDEVICE_PARAMS: // Bad Select Device Parameters
  1395. case ERR_DI_BAD_REMOVEDEVICE_PARAMS: // Bad Remove Device Parameters
  1396. case ERR_DI_BAD_ENABLECLASS_PARAMS: // Bad Enable Class Parameters
  1397. case ERR_DI_FAIL_QUERY: // Fail the Enable Class query
  1398. case ERR_DI_API_ERROR: // DI API called incorrectly
  1399. case ERR_DI_BAD_PATH: // An OEM path was specified incorrectly
  1400. default:
  1401. ret = RET_BROWSE_ERROR;
  1402. break;
  1403. }
  1404. DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : DiCallClassInstaller %s", (ret IS OK ? "succeded" : "failed")));
  1405. }
  1406. } // if wCommand IS CMD_INSTALL_DRIVER
  1407. // We don't need the driver node anymore
  1408. // Clean up and delete
  1409. //
  1410. if (lpdn->atInfFileName ISNT 0)
  1411. GlobalDeleteAtom(lpdn->atInfFileName);
  1412. if (lpdn->atMfgName ISNT 0)
  1413. GlobalDeleteAtom(lpdn->atMfgName);
  1414. if (lpdn->atProviderName ISNT 0)
  1415. GlobalDeleteAtom(lpdn->atProviderName);
  1416. HP_GLOBAL_FREE(lpdn);
  1417. return ret;
  1418. }
  1419. /*****************************************************************************\
  1420. * LibMain
  1421. *
  1422. * Entry-point initialization.
  1423. *
  1424. \*****************************************************************************/
  1425. #if 0
  1426. int CALLBACK LibMain(HANDLE hModule,
  1427. WORD wDataSeg,
  1428. WORD cbHeapSize,
  1429. LPSTR lpszCmdLine)
  1430. {
  1431. g_hInst = NULL;
  1432. g_hInst = (HINSTANCE) hModule;
  1433. return 1;
  1434. }
  1435. #else
  1436. BOOL FAR PASCAL LibMain(
  1437. HANDLE hInst,
  1438. int nAttach,
  1439. LPVOID pContext)
  1440. {
  1441. if (g_hInst == NULL) {
  1442. g_hInst = (HINSTANCE)hInst;
  1443. if (InitStrings())
  1444. return thk_ThunkConnect16(cszDll16, cszDll32, hInst, 1);
  1445. }
  1446. return FALSE;
  1447. }
  1448. #endif
  1449. /*****************************************************************************\
  1450. * Windows Exit Proceedure (WEP)
  1451. *
  1452. *
  1453. \*****************************************************************************/
  1454. int CALLBACK WEP(int exportType)
  1455. {
  1456. FreeStrings();
  1457. return 1;
  1458. }