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.

4942 lines
132 KiB

  1. /*++
  2. Copyright (c) 1995-97 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Util.c
  6. Abstract:
  7. Driver Setup UI Utility functions
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 06-Sep-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include "splcom.h"
  14. #define MAX_DWORD_LENGTH 11
  15. //
  16. // Keys to search for in ntprint.inf
  17. //
  18. TCHAR cszDataSection[] = TEXT("DataSection");
  19. TCHAR cszDriverFile[] = TEXT("DriverFile");
  20. TCHAR cszConfigFile[] = TEXT("ConfigFile");
  21. TCHAR cszDataFile[] = TEXT("DataFile");
  22. TCHAR cszHelpFile[] = TEXT("HelpFile");
  23. TCHAR cszDefaultDataType[] = TEXT("DefaultDataType");
  24. TCHAR cszLanguageMonitor[] = TEXT("LanguageMonitor");
  25. TCHAR cszPrintProcessor[] = TEXT("PrintProcessor");
  26. TCHAR cszCopyFiles[] = TEXT("CopyFiles");
  27. TCHAR cszVendorSetup[] = TEXT("VendorSetup");
  28. TCHAR cszVendorInstaller[] = TEXT("VendorInstaller");
  29. TCHAR cszPreviousNamesSection[] = TEXT("Previous Names");
  30. TCHAR cszOEMUrlSection[] = TEXT("OEM URLS");
  31. TCHAR cszWebNTPrintPkg[] = TEXT("3FBF5B30-DEB4-11D1-AC97-00A0C903492B");
  32. TCHAR cszAllInfs[] = TEXT("*.inf");
  33. TCHAR cszInfExt[] = TEXT("\\*.inf");
  34. TCHAR sComma = TEXT(',');
  35. TCHAR sHash = TEXT('@');
  36. TCHAR sZero = TEXT('\0');
  37. TCHAR cszSystemSetupKey[] = TEXT("System\\Setup");
  38. TCHAR cszSystemUpgradeValue[] = TEXT("UpgradeInProgress");
  39. TCHAR cszSystemSetupInProgress[] = TEXT("SystemSetupInProgress");
  40. TCHAR cszMonitorKey[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\");
  41. //
  42. // Native environment name used by spooler
  43. //
  44. SPLPLATFORMINFO PlatformEnv[] = {
  45. { TEXT("Windows NT Alpha_AXP") },
  46. { TEXT("Windows NT x86") },
  47. { TEXT("Windows NT R4000") },
  48. { TEXT("Windows NT PowerPC") },
  49. { TEXT("Windows 4.0") },
  50. { TEXT("Windows IA64") },
  51. { TEXT("Windows Alpha_AXP64") }
  52. };
  53. //
  54. // Platform override strings to be used to upgrade non-native architecture
  55. // printer drivers
  56. //
  57. SPLPLATFORMINFO PlatformOverride[] = {
  58. { TEXT("alpha") },
  59. { TEXT("i386") },
  60. { TEXT("mips") },
  61. { TEXT("ppc") },
  62. { NULL }, // Win95
  63. { TEXT("ia64") },
  64. { TEXT("axp64") }
  65. };
  66. DWORD PlatformArch[][2] =
  67. {
  68. { VER_PLATFORM_WIN32_NT, PROCESSOR_ARCHITECTURE_ALPHA },
  69. { VER_PLATFORM_WIN32_NT, PROCESSOR_ARCHITECTURE_INTEL },
  70. { VER_PLATFORM_WIN32_NT, PROCESSOR_ARCHITECTURE_MIPS },
  71. { VER_PLATFORM_WIN32_NT, PROCESSOR_ARCHITECTURE_PPC },
  72. { VER_PLATFORM_WIN32_WINDOWS, PROCESSOR_ARCHITECTURE_INTEL },
  73. { VER_PLATFORM_WIN32_NT, PROCESSOR_ARCHITECTURE_IA64 },
  74. { VER_PLATFORM_WIN32_NT, PROCESSOR_ARCHITECTURE_ALPHA64 }
  75. };
  76. PLATFORM MyPlatform =
  77. #if defined(_ALPHA_)
  78. PlatformAlpha;
  79. #elif defined(_MIPS_)
  80. PlatformMIPS;
  81. #elif defined(_PPC_)
  82. PlatformPPC;
  83. #elif defined(_X86_)
  84. PlatformX86;
  85. #elif defined(_IA64_)
  86. PlatformIA64;
  87. #elif defined(_AXP64_)
  88. PlatformAlpha64;
  89. #elif defined(_AMD64_)
  90. 0; // ****** fixfix ****** amd64
  91. #else
  92. #error "No Target Architecture"
  93. #endif
  94. // Declare the CritSec for CDM
  95. CRITICAL_SECTION CDMCritSect;
  96. #define SKIP_DIR TEXT("\\__SKIP_")
  97. CRITICAL_SECTION SkipCritSect;
  98. LPTSTR gpszSkipDir = NULL;
  99. PVOID
  100. LocalAllocMem(
  101. IN UINT cbSize
  102. )
  103. {
  104. return LocalAlloc( LPTR, cbSize );
  105. }
  106. VOID
  107. LocalFreeMem(
  108. IN PVOID p
  109. )
  110. {
  111. LocalFree(p);
  112. }
  113. //
  114. // For some reason these are needed by spllib when you use StrNCatBuf.
  115. // This doesn't make any sense, but just implement them.
  116. //
  117. LPVOID
  118. DllAllocSplMem(
  119. DWORD cbSize
  120. )
  121. {
  122. return LocalAllocMem(cbSize);
  123. }
  124. BOOL
  125. DllFreeSplMem(
  126. LPVOID pMem
  127. )
  128. {
  129. LocalFreeMem(pMem);
  130. return TRUE;
  131. }
  132. VOID
  133. PSetupFreeMem(
  134. IN PVOID p
  135. )
  136. {
  137. LocalFreeMem(p);
  138. }
  139. LPTSTR
  140. AllocStr(
  141. LPCTSTR pszStr
  142. )
  143. /*++
  144. Routine Description:
  145. Allocate memory and make a copy of a string field
  146. Arguments:
  147. pszStr : String to copy
  148. Return Value:
  149. Pointer to the copied string. Memory is allocated.
  150. --*/
  151. {
  152. LPTSTR pszRet = NULL;
  153. if ( pszStr && *pszStr ) {
  154. pszRet = LocalAllocMem((lstrlen(pszStr) + 1) * sizeof(*pszRet));
  155. if ( pszRet )
  156. lstrcpy(pszRet, pszStr);
  157. }
  158. return pszRet;
  159. }
  160. LPTSTR
  161. AllocStrWCtoTC(LPWSTR lpStr)
  162. /*++
  163. Routine Description:
  164. Allocate memory and make a copy of a string field, convert it from a WCHAR *
  165. to a TCHAR *
  166. Arguments:
  167. pszStr : String to copy
  168. Return Value:
  169. Pointer to the copied string. Memory is allocated.
  170. --*/
  171. {
  172. #ifdef UNICODE
  173. return AllocStr(lpStr);
  174. #else
  175. LPSTR pszRet = NULL;
  176. INT iSize;
  177. iSize = WideCharToMultiByte( CP_ACP, 0, lpStr, -1, NULL, 0, NULL, NULL);
  178. if (iSize <= 0)
  179. goto Cleanup;
  180. pszRet = LocalAllocMem( iSize );
  181. if (!pszRet)
  182. goto Cleanup;
  183. iSize = WideCharToMultiByte( CP_ACP, 0, lpStr, -1, pszRet, iSize, NULL, NULL);
  184. if (!iSize) {
  185. LocalFreeMem( pszRet );
  186. pszRet = NULL;
  187. }
  188. Cleanup:
  189. return pszRet;
  190. #endif
  191. }
  192. LPTSTR
  193. AllocAndCatStr(
  194. LPCTSTR pszStr1,
  195. LPCTSTR pszStr2
  196. )
  197. /*++
  198. Routine Description:
  199. Allocate memory and make a copy of two string fields, cancatenate the second to
  200. the first
  201. Arguments:
  202. pszStr1 : String to copy
  203. pszStr2 : String to CAT
  204. Return Value:
  205. Pointer to the copied string. Memory is allocated.
  206. --*/
  207. {
  208. LPTSTR pszRet = NULL;
  209. if ( pszStr1 && *pszStr1 &&
  210. pszStr2 && *pszStr2 ) {
  211. pszRet = LocalAllocMem((lstrlen(pszStr1) + lstrlen(pszStr2) + 1) * sizeof(*pszRet));
  212. if ( pszRet ) {
  213. lstrcpy( pszRet, pszStr1 );
  214. lstrcat( pszRet, pszStr2 );
  215. }
  216. }
  217. return pszRet;
  218. }
  219. LPTSTR
  220. AllocAndCatStr2(
  221. LPCTSTR pszStr1,
  222. LPCTSTR pszStr2,
  223. LPCTSTR pszStr3
  224. )
  225. /*++
  226. Routine Description:
  227. Allocate memory and make a copy of two string fields, cancatenate the second to
  228. the first
  229. Arguments:
  230. pszStr1 : String to copy
  231. pszStr2 : String to CAT
  232. pszStr3 : Second string to CAT
  233. Return Value:
  234. Pointer to the copied string. Memory is allocated.
  235. --*/
  236. {
  237. LPTSTR pszRet = NULL;
  238. DWORD cSize = 0;
  239. if ( pszStr1 &&
  240. pszStr2 &&
  241. pszStr3 ) {
  242. if(*pszStr1)
  243. {
  244. cSize += lstrlen(pszStr1);
  245. }
  246. if(*pszStr2)
  247. {
  248. cSize += lstrlen(pszStr2);
  249. }
  250. if(*pszStr3)
  251. {
  252. cSize += lstrlen(pszStr3);
  253. }
  254. pszRet = LocalAllocMem((cSize+1)*sizeof(*pszRet));
  255. if ( pszRet ) {
  256. if(*pszStr1)
  257. {
  258. lstrcpy( pszRet, pszStr1 );
  259. if(*pszStr2)
  260. {
  261. lstrcat( pszRet, pszStr2 );
  262. }
  263. if(*pszStr3)
  264. {
  265. lstrcat( pszRet, pszStr3 );
  266. }
  267. }
  268. else
  269. {
  270. if(*pszStr2)
  271. {
  272. lstrcpy( pszRet, pszStr2 );
  273. if(*pszStr3)
  274. {
  275. lstrcat( pszRet, pszStr3 );
  276. }
  277. }
  278. else
  279. {
  280. if(*pszStr3)
  281. {
  282. lstrcpy( pszRet, pszStr3 );
  283. }
  284. }
  285. }
  286. }
  287. }
  288. return pszRet;
  289. }
  290. VOID
  291. FreeStructurePointers(
  292. LPBYTE pStruct,
  293. PULONG_PTR pOffsets,
  294. BOOL bFreeStruct
  295. )
  296. /*++
  297. Routine Description:
  298. Frees memory allocated to fields given by the pointers in a structure.
  299. Also optionally frees the memory allocated for the structure itself.
  300. Arguments:
  301. pStruct : Pointer to the structure
  302. pOffsets : Array of DWORDS (terminated by -1) givings offsets
  303. bFreeStruct : If TRUE structure is also freed
  304. Return Value:
  305. nothing
  306. --*/
  307. {
  308. INT i;
  309. if ( pStruct ) {
  310. for( i = 0 ; pOffsets[i] != -1; ++i )
  311. LocalFreeMem(*(LPBYTE *) (pStruct+pOffsets[i]));
  312. if ( bFreeStruct )
  313. LocalFreeMem(pStruct);
  314. }
  315. }
  316. VOID
  317. DestroyLocalData(
  318. IN PPSETUP_LOCAL_DATA pLocalData
  319. )
  320. {
  321. if ( pLocalData ) {
  322. if ( pLocalData->Flags & VALID_INF_INFO )
  323. FreeStructurePointers((LPBYTE)&pLocalData->InfInfo,
  324. InfInfoOffsets,
  325. FALSE);
  326. if ( pLocalData->Flags & VALID_PNP_INFO )
  327. FreeStructurePointers((LPBYTE)&pLocalData->PnPInfo,
  328. PnPInfoOffsets,
  329. FALSE);
  330. FreeStructurePointers((LPBYTE)pLocalData, LocalDataOffsets, TRUE);
  331. }
  332. }
  333. VOID
  334. InfGetString(
  335. IN PINFCONTEXT pInfContext,
  336. IN DWORD dwFieldIndex,
  337. OUT LPTSTR *ppszField,
  338. IN OUT LPDWORD pcchCopied,
  339. IN OUT LPBOOL pbFail
  340. )
  341. /*++
  342. Routine Description:
  343. Allocates memory and gets a string field from an Inf file
  344. Arguments:
  345. lpInfContext : Inf context for the line
  346. dwFieldIndex : Index of the field within the specified line
  347. ppszField : Pointer to the field to allocate memory and copy
  348. pcchCopied : On success number of charaters copied is added
  349. pbFail : Set on error, could be TRUE when called
  350. Return Value:
  351. Nothing; If *pbFail is not TRUE memory is allocated and the field is copied
  352. --*/
  353. {
  354. TCHAR Buffer[MAX_PATH];
  355. DWORD dwNeeded;
  356. if ( *pbFail )
  357. return;
  358. if ( SetupGetStringField(pInfContext,
  359. dwFieldIndex,
  360. Buffer,
  361. SIZECHARS(Buffer),
  362. &dwNeeded) ) {
  363. *ppszField = AllocStr(Buffer);
  364. *pcchCopied += dwNeeded;
  365. return;
  366. }
  367. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  368. !(*ppszField = LocalAllocMem(dwNeeded*sizeof(Buffer[0]))) ) {
  369. *pbFail = TRUE;
  370. return;
  371. }
  372. if ( !SetupGetStringField(pInfContext,
  373. dwFieldIndex,
  374. *ppszField,
  375. dwNeeded,
  376. &dwNeeded) ) {
  377. *pbFail = TRUE;
  378. return;
  379. }
  380. *pcchCopied += dwNeeded;
  381. }
  382. VOID
  383. InfGetMultiSz(
  384. IN PINFCONTEXT pInfContext,
  385. IN DWORD dwFieldIndex,
  386. OUT LPTSTR *ppszField,
  387. IN OUT LPDWORD pcchCopied,
  388. IN OUT LPBOOL pbFail
  389. )
  390. /*++
  391. Routine Description:
  392. Allocates memory and gets a multi-sz field from an Inf file
  393. Arguments:
  394. lpInfContext : Inf context for the line
  395. dwFieldIndex : Index of the field within the specified line
  396. ppszField : Pointer to the field to allocate memory and copy
  397. pcchCopied : On success number of charaters copied is added
  398. pbFail : Set on error, could be TRUE when called
  399. Return Value:
  400. Nothing; If *pbFail is not TRUE memory is allocated and the field is copied
  401. --*/
  402. {
  403. TCHAR Buffer[MAX_PATH];
  404. DWORD dwNeeded;
  405. if ( *pbFail )
  406. return;
  407. if ( SetupGetMultiSzField(pInfContext,
  408. dwFieldIndex,
  409. Buffer,
  410. SIZECHARS(Buffer),
  411. &dwNeeded) ) {
  412. if ( *ppszField = LocalAllocMem(dwNeeded*sizeof(Buffer[0])) ) {
  413. CopyMemory(*ppszField, Buffer, dwNeeded * sizeof(Buffer[0]));
  414. *pcchCopied += dwNeeded;
  415. } else {
  416. *pbFail = TRUE;
  417. }
  418. return;
  419. }
  420. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  421. !(*ppszField = LocalAllocMem(dwNeeded * sizeof(Buffer[0]))) ) {
  422. *pbFail = TRUE;
  423. return;
  424. }
  425. if ( !SetupGetMultiSzField(pInfContext,
  426. dwFieldIndex,
  427. *ppszField,
  428. dwNeeded,
  429. &dwNeeded) ) {
  430. *pbFail = TRUE;
  431. return;
  432. }
  433. *pcchCopied += dwNeeded;
  434. }
  435. VOID
  436. InfGetDriverInfoString(
  437. IN HINF hInf,
  438. IN LPCTSTR pszDriverSection,
  439. IN LPCTSTR pszDataSection, OPTIONAL
  440. IN BOOL bDataSection,
  441. IN LPCTSTR pszKey,
  442. OUT LPTSTR *ppszData,
  443. IN LPCTSTR pszDefaultData,
  444. IN OUT LPDWORD pcchCopied,
  445. IN OUT LPBOOL pbFail
  446. )
  447. /*++
  448. Routine Description:
  449. Allocates memory and gets a driver info field from an inf file
  450. Arguments:
  451. hInf : Handle to the Inf file
  452. pszDriverSection : Section name for the driver
  453. pszDataSection : Data section for the driver (optional)
  454. bDataSection : Specifies if there is a data section
  455. pszKey : Key value of the field to look for
  456. *ppszData : Pointer to allocate memory and copy the data field
  457. pszDefaultData : If key found this is the default value, coule be NULL
  458. pcchCopied : On success number of charaters copied is added
  459. *pbFail : Set on error, could be TRUE when called
  460. Return Value:
  461. Nothing; If *pbFail is not TRUE memory is allocated and the field is copied
  462. --*/
  463. {
  464. INFCONTEXT InfContext;
  465. if ( *pbFail )
  466. return;
  467. if ( SetupFindFirstLine(hInf, pszDriverSection,
  468. pszKey, &InfContext) ||
  469. (bDataSection && SetupFindFirstLine(hInf,
  470. pszDataSection,
  471. pszKey,
  472. &InfContext)) ) {
  473. InfGetString(&InfContext, 1, ppszData, pcchCopied, pbFail);
  474. } else if ( pszDefaultData && *pszDefaultData ) {
  475. if ( !(*ppszData = AllocStr(pszDefaultData)) )
  476. *pbFail = TRUE;
  477. else
  478. *pcchCopied += lstrlen(pszDefaultData) + 1;
  479. } else
  480. *ppszData = NULL;
  481. }
  482. VOID
  483. InfGet2PartString(
  484. IN HINF hInf,
  485. IN LPCTSTR pszDriverSection,
  486. IN LPCTSTR pszDataSection, OPTIONAL
  487. IN BOOL bDataSection,
  488. IN LPCTSTR pszKey,
  489. OUT LPTSTR *ppszData,
  490. IN OUT LPBOOL pbFail
  491. )
  492. /*++
  493. Routine Description:
  494. Allocates memory and gets a 2 part string field from an inf file
  495. Arguments:
  496. hInf : Handle to the Inf file
  497. pszDriverSection : Section name for the driver
  498. pszDataSection : Data section for the driver (optional)
  499. bDataSection : Specifies if there is a data section
  500. pszKey : Key value of the field to look for
  501. *ppszData : Pointer to allocate memory and copy the data field
  502. *pbFail : Set on error, could be TRUE when called
  503. Return Value:
  504. Nothing; If *pbFail is not TRUE memory is allocated and the field is copied
  505. --*/
  506. {
  507. INFCONTEXT InfContext;
  508. LPTSTR psz = NULL,
  509. psz2 = NULL;
  510. DWORD dwLen = 0;
  511. if ( *pbFail )
  512. return;
  513. if ( SetupFindFirstLine(hInf, pszDriverSection,
  514. pszKey, &InfContext) ||
  515. (bDataSection && SetupFindFirstLine(hInf,
  516. pszDriverSection = pszDataSection,
  517. pszKey,
  518. &InfContext)) ) {
  519. InfGetString(&InfContext, 1, ppszData, &dwLen, pbFail);
  520. if ( *pbFail || !*ppszData )
  521. return; //Success, field is NULL
  522. //
  523. // Usual case : field is of the form "Description, DLL-Name"
  524. //
  525. if ( psz = lstrchr(*ppszData, sComma) ) {
  526. *psz = sZero;
  527. return; // Success, field is not NULL
  528. } else {
  529. //
  530. // This is for the case "Description", DLL-Name
  531. //
  532. InfGetString(&InfContext, 2, &psz, &dwLen, pbFail);
  533. if ( *pbFail || !psz )
  534. goto Fail;
  535. dwLen = lstrlen(*ppszData) + lstrlen(psz) + 2;
  536. if ( psz2 = LocalAllocMem(dwLen * sizeof(*psz2)) ) {
  537. lstrcpy(psz2, *ppszData);
  538. LocalFreeMem(*ppszData);
  539. *ppszData = psz2;
  540. psz2 += lstrlen(psz2) + 1;
  541. lstrcpy(psz2, psz);
  542. LocalFreeMem(psz);
  543. } else
  544. goto Fail;
  545. }
  546. } else
  547. *ppszData = NULL;
  548. return;
  549. Fail:
  550. LocalFreeMem(*ppszData);
  551. LocalFreeMem(psz);
  552. LocalFreeMem(psz2);
  553. *ppszData = NULL;
  554. *pbFail = TRUE;
  555. SetLastError(STG_E_UNKNOWN);
  556. }
  557. VOID
  558. PSetupDestroyDriverInfo3(
  559. IN LPDRIVER_INFO_3 pDriverInfo3
  560. )
  561. /*++
  562. Routine Description:
  563. Frees memory allocated for a DRIVER_INFO_3 structure and all the string
  564. fields in it
  565. Arguments:
  566. pDriverInfo3 : Pointer to the DRIVER_INFO_3 structure to free memory
  567. Return Value:
  568. None
  569. --*/
  570. {
  571. LocalFreeMem(pDriverInfo3);
  572. }
  573. LPTSTR
  574. PackString(
  575. IN LPTSTR pszEnd,
  576. IN LPTSTR pszSource,
  577. IN LPTSTR *ppszTarget
  578. )
  579. /*++
  580. Routine Description:
  581. After parsing the INF the DRIVER_INFO_6 is packed in a buffer where the
  582. strings are at the end.
  583. Arguments:
  584. pszEnd : Pointer to the end of the buffer
  585. pszSource : String to copy to the end of the buffer
  586. ppszTarget : After copying the source to end of buffer this will receive
  587. addess of the packed string
  588. Return Value:
  589. New end of buffer
  590. --*/
  591. {
  592. if ( pszSource && *pszSource ) {
  593. pszEnd -= lstrlen(pszSource) + 1;
  594. lstrcpy(pszEnd, pszSource);
  595. *ppszTarget = pszEnd;
  596. }
  597. return pszEnd;
  598. }
  599. LPTSTR
  600. PackMultiSz(
  601. IN LPTSTR pszEnd,
  602. IN LPTSTR pszzSource,
  603. IN LPTSTR *ppszzTarget
  604. )
  605. /*++
  606. Routine Description:
  607. After parsing the INF the DRIVER_INFO_6 is packed in a buffer where the
  608. strings are at the end.
  609. Arguments:
  610. pszEnd : Pointer to the end of the buffer
  611. pszSource : Multi-sz field to copy to the end of the buffer
  612. ppszTarget : After copying the source to end of buffer this will receive
  613. addess of the packed multi-sz field
  614. Return Value:
  615. New end of buffer
  616. --*/
  617. {
  618. size_t dwLen = 0;
  619. LPTSTR psz1, psz2;
  620. if ( (psz1 = pszzSource) != NULL && *psz1 ) {
  621. while ( *psz1 )
  622. psz1 += lstrlen(psz1) + 1;
  623. dwLen = (size_t)(psz1 - pszzSource + 1);
  624. }
  625. if ( dwLen == 0 ) {
  626. *ppszzTarget = NULL;
  627. return pszEnd;
  628. }
  629. pszEnd -= dwLen;
  630. *ppszzTarget = pszEnd;
  631. CopyMemory((LPBYTE)pszEnd, (LPBYTE)pszzSource, dwLen * sizeof(TCHAR));
  632. return pszEnd;
  633. }
  634. VOID
  635. PackDriverInfo6(
  636. IN LPDRIVER_INFO_6 pSourceDriverInfo6,
  637. IN LPDRIVER_INFO_6 pTargetDriverInfo6,
  638. IN DWORD cbDriverInfo6
  639. )
  640. /*++
  641. Routine Description:
  642. Make a copy of a DRIVER_INFO_6 in a buffer where the strings are packed at
  643. end of the buffer.
  644. Arguments:
  645. pSourceDriverInfo6 : The DRIVER_INFO_6 to make a copy
  646. pTargetDriverInfo6 : Points to a buffer to copy the pSourceDriverInfo6
  647. cbDriverInfo3 : Size of the buffer cbDriverInfo3, which is the size
  648. needed for DRIVER_INFO_6 and the strings
  649. Return Value:
  650. None
  651. --*/
  652. {
  653. LPTSTR pszStr, pszStr2, pszMonitorDll;
  654. DWORD dwLen = 0;
  655. // Copy over he couple non-string fields
  656. pTargetDriverInfo6->cVersion = pSourceDriverInfo6->cVersion;
  657. pTargetDriverInfo6->ftDriverDate = pSourceDriverInfo6->ftDriverDate;
  658. pTargetDriverInfo6->dwlDriverVersion = pSourceDriverInfo6->dwlDriverVersion;
  659. pszStr = (LPTSTR)(((LPBYTE)pTargetDriverInfo6) + cbDriverInfo6);
  660. pszStr = PackString(pszStr,
  661. pSourceDriverInfo6->pName,
  662. &pTargetDriverInfo6->pName);
  663. pszStr = PackString(pszStr,
  664. pSourceDriverInfo6->pDriverPath,
  665. &pTargetDriverInfo6->pDriverPath);
  666. pszStr = PackString(pszStr,
  667. pSourceDriverInfo6->pDataFile,
  668. &pTargetDriverInfo6->pDataFile);
  669. pszStr = PackString(pszStr,
  670. pSourceDriverInfo6->pConfigFile,
  671. &pTargetDriverInfo6->pConfigFile);
  672. pszStr = PackString(pszStr,
  673. pSourceDriverInfo6->pHelpFile,
  674. &pTargetDriverInfo6->pHelpFile);
  675. //
  676. // Monitor dll is put right after the name
  677. // (ex. PJL Language monitor\0pjlmon.dd\0)
  678. //
  679. if ( pSourceDriverInfo6->pMonitorName ) {
  680. pszMonitorDll = pSourceDriverInfo6->pMonitorName
  681. + lstrlen(pSourceDriverInfo6->pMonitorName) + 1;
  682. pszStr = PackString(pszStr,
  683. pszMonitorDll,
  684. &pszStr2); // Don't care
  685. pszStr = PackString(pszStr,
  686. pSourceDriverInfo6->pMonitorName,
  687. &pTargetDriverInfo6->pMonitorName);
  688. }
  689. pszStr = PackString(pszStr,
  690. pSourceDriverInfo6->pDefaultDataType,
  691. &pTargetDriverInfo6->pDefaultDataType);
  692. pszStr = PackMultiSz(pszStr,
  693. pSourceDriverInfo6->pDependentFiles,
  694. &pTargetDriverInfo6->pDependentFiles);
  695. pszStr = PackMultiSz(pszStr,
  696. pSourceDriverInfo6->pszzPreviousNames,
  697. &pTargetDriverInfo6->pszzPreviousNames);
  698. pszStr = PackString(pszStr,
  699. pSourceDriverInfo6->pszMfgName,
  700. &pTargetDriverInfo6->pszMfgName);
  701. pszStr = PackString(pszStr,
  702. pSourceDriverInfo6->pszOEMUrl,
  703. &pTargetDriverInfo6->pszOEMUrl);
  704. pszStr = PackString(pszStr,
  705. pSourceDriverInfo6->pszHardwareID,
  706. &pTargetDriverInfo6->pszHardwareID);
  707. pszStr = PackString(pszStr,
  708. pSourceDriverInfo6->pszProvider,
  709. &pTargetDriverInfo6->pszProvider);
  710. if ( pTargetDriverInfo6->pszProvider )
  711. {
  712. ASSERT((LPBYTE)pTargetDriverInfo6->pszProvider
  713. >= ((LPBYTE) pTargetDriverInfo6) + sizeof(DRIVER_INFO_6));
  714. }
  715. else if ( pTargetDriverInfo6->pszHardwareID )
  716. {
  717. ASSERT((LPBYTE)pTargetDriverInfo6->pszHardwareID
  718. >= ((LPBYTE) pTargetDriverInfo6) + sizeof(DRIVER_INFO_6));
  719. }
  720. else if ( pTargetDriverInfo6->pszOEMUrl )
  721. {
  722. ASSERT((LPBYTE)pTargetDriverInfo6->pszOEMUrl
  723. >= ((LPBYTE) pTargetDriverInfo6) + sizeof(DRIVER_INFO_6));
  724. }
  725. else if ( pTargetDriverInfo6->pszMfgName )
  726. {
  727. ASSERT((LPBYTE)pTargetDriverInfo6->pszMfgName
  728. >= ((LPBYTE) pTargetDriverInfo6) + sizeof(DRIVER_INFO_6));
  729. }
  730. else if ( pTargetDriverInfo6->pszzPreviousNames )
  731. {
  732. ASSERT((LPBYTE)pTargetDriverInfo6->pszzPreviousNames
  733. >= ((LPBYTE) pTargetDriverInfo6) + sizeof(DRIVER_INFO_6));
  734. }
  735. else if ( pTargetDriverInfo6->pDependentFiles )
  736. {
  737. ASSERT((LPBYTE)pTargetDriverInfo6->pDependentFiles
  738. >= ((LPBYTE) pTargetDriverInfo6) + sizeof(DRIVER_INFO_6));
  739. }
  740. }
  741. LPDRIVER_INFO_6
  742. CloneDriverInfo6(
  743. IN LPDRIVER_INFO_6 pSourceDriverInfo6,
  744. IN DWORD cbDriverInfo6
  745. )
  746. /*++
  747. Routine Description:
  748. Allocate memory and build a DRIVER_INFO_6 from the information we got by
  749. parsing the INF
  750. Arguments:
  751. pszEnd : Pointer to the end of the buffer
  752. pszSource : String to copy to the end of the buffer
  753. ppszTarget : After copying the source to end of buffer this will receive
  754. addess of the packed string
  755. Return Value:
  756. New end of buffer
  757. --*/
  758. {
  759. LPDRIVER_INFO_6 pTargetDriverInfo6;
  760. LPTSTR pszStr, pszStr2;
  761. DWORD dwLen = 0;
  762. pTargetDriverInfo6 = (LPDRIVER_INFO_6) LocalAllocMem(cbDriverInfo6);
  763. if ( pTargetDriverInfo6 )
  764. PackDriverInfo6(pSourceDriverInfo6,
  765. pTargetDriverInfo6,
  766. cbDriverInfo6);
  767. return pTargetDriverInfo6;
  768. }
  769. VOID
  770. InfGetVendorSetup(
  771. IN OUT PPARSEINF_INFO pInfInfo,
  772. IN HINF hInf,
  773. IN LPTSTR pszDriverSection,
  774. IN LPTSTR pszDataSection,
  775. IN BOOL bDataSection,
  776. IN OUT LPBOOL pbFail
  777. )
  778. /*++
  779. Routine Description:
  780. Get the VendowSetup field, if specified, from the INF
  781. Arguments:
  782. pInfInfo : This is where the parsed info from the INF is stored
  783. hInf : INF handle
  784. pszDriverSection : Gives the driver installation section
  785. pszDataSection : Data section specified (optional) in driver install section
  786. bDataSection : Tells if a data section is specified
  787. pbFail : Set on error
  788. Return Value:
  789. New end of buffer
  790. --*/
  791. {
  792. LPTSTR p;
  793. DWORD dwSize;
  794. TCHAR szBuf[MAX_PATH];
  795. INFCONTEXT InfContext;
  796. if ( *pbFail )
  797. return;
  798. //
  799. // If VendorSetup key is not found return; the key is optional
  800. //
  801. if ( !SetupFindFirstLine(hInf, pszDriverSection,
  802. cszVendorSetup, &InfContext) &&
  803. ( !bDataSection ||
  804. !SetupFindFirstLine(hInf, pszDataSection,
  805. cszVendorSetup, &InfContext)) ) {
  806. return;
  807. }
  808. if ( SetupGetLineText(&InfContext, hInf, NULL, NULL,
  809. szBuf, SIZECHARS(szBuf), &dwSize) ) {
  810. if ( dwSize == 0 || szBuf[0] == TEXT('\0') )
  811. return;
  812. if ( !(pInfInfo->pszVendorSetup = AllocStr(szBuf)) )
  813. *pbFail = TRUE;
  814. return;
  815. }
  816. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) {
  817. *pbFail = TRUE;
  818. return;
  819. }
  820. pInfInfo->pszVendorSetup = (LPTSTR) LocalAllocMem(dwSize * sizeof(TCHAR));
  821. if ( pInfInfo->pszVendorSetup &&
  822. SetupGetLineText(&InfContext, hInf, NULL, NULL,
  823. pInfInfo->pszVendorSetup, dwSize, &dwSize) ) {
  824. return;
  825. }
  826. LocalFreeMem(pInfInfo->pszVendorSetup);
  827. pInfInfo->pszVendorSetup = NULL;
  828. *pbFail = TRUE;
  829. }
  830. VOID
  831. InfGetPreviousNames(
  832. IN HINF hInf,
  833. IN PSELECTED_DRV_INFO pDrvInfo,
  834. IN OUT LPDWORD pcchCopied,
  835. IN OUT LPBOOL pbFail
  836. )
  837. /*++
  838. Routine Description:
  839. Gets the pszzPreviousNames field for the selected driver. This field is
  840. optional, and if specified gives previous names under which the driver was
  841. known
  842. Arguments:
  843. hInf : INF handle
  844. pDrvInfo : Pointer to selected driver info
  845. pcchCopied : Number of characters copied
  846. pbFail : Set on failure
  847. Return Value:
  848. None. On failure *pbFail is set
  849. --*/
  850. {
  851. INFCONTEXT Context;
  852. if ( *pbFail )
  853. return;
  854. //
  855. // Previous names is optional; if not found we are done
  856. //
  857. if ( SetupFindFirstLine(hInf,
  858. cszPreviousNamesSection,
  859. pDrvInfo->pszModelName,
  860. &Context) ) {
  861. pDrvInfo->Flags |= SDFLAG_PREVNAME_SECTION_FOUND;
  862. InfGetMultiSz(&Context, 1, &pDrvInfo->pszzPreviousNames,
  863. pcchCopied, pbFail);
  864. } else if ( GetLastError() != ERROR_LINE_NOT_FOUND )
  865. pDrvInfo->Flags |= SDFLAG_PREVNAME_SECTION_FOUND;
  866. }
  867. VOID
  868. InfGetOEMUrl(
  869. IN HINF hInf,
  870. IN PSELECTED_DRV_INFO pDrvInfo,
  871. IN OUT LPBOOL pbFail
  872. )
  873. /*++
  874. Routine Description:
  875. Gets the OEM URL Info for the selected driver. This field is optional
  876. Arguments:
  877. hInf : INF handle
  878. pDrvInfo : Pointer to selected driver info
  879. pbFail : Set on failure
  880. Return Value:
  881. None. On failure *pbFail is set
  882. --*/
  883. {
  884. INFCONTEXT Context;
  885. DWORD dwDontCare = 0;
  886. if ( *pbFail )
  887. return;
  888. //
  889. // OEM URL is optional; if not found we are done
  890. //
  891. if ( SetupFindFirstLine(hInf,
  892. cszOEMUrlSection,
  893. pDrvInfo->pszManufacturer,
  894. &Context) ) {
  895. InfGetString(&Context, 1, &pDrvInfo->pszOEMUrl, &dwDontCare, pbFail);
  896. }
  897. }
  898. VOID
  899. AddAllIncludedInf(
  900. IN HINF hInf,
  901. IN LPTSTR pszInstallSection
  902. )
  903. {
  904. INFCONTEXT INFContext;
  905. PINFCONTEXT pINFContext = &INFContext;
  906. DWORD dwBufferNeeded;
  907. if ( SetupFindFirstLine( hInf, pszInstallSection, TEXT( "Include" ), pINFContext ) )
  908. {
  909. // Find each INF and load it & it's LAYOUT files
  910. DWORD dwINFs = SetupGetFieldCount( pINFContext );
  911. DWORD dwIndex;
  912. for ( dwIndex = 1; dwIndex <= dwINFs; dwIndex++ )
  913. {
  914. if ( SetupGetStringField( pINFContext, dwIndex, NULL, 0, &dwBufferNeeded ) )
  915. {
  916. PTSTR pszINFName = (PTSTR) LocalAllocMem( dwBufferNeeded * sizeof(TCHAR) );
  917. if ( pszINFName )
  918. {
  919. if ( SetupGetStringField( pINFContext, dwIndex, pszINFName, ( dwBufferNeeded * sizeof(TCHAR) ), &dwBufferNeeded ) )
  920. {
  921. //
  922. // Open INF file and append layout.inf specified in Version section
  923. // Layout inf is optional
  924. //
  925. SetupOpenAppendInfFile( pszINFName, hInf, NULL);
  926. SetupOpenAppendInfFile( NULL, hInf, NULL);
  927. } // Got an INF Name
  928. LocalFreeMem( pszINFName );
  929. pszINFName = NULL;
  930. } // Allocated pszINFName
  931. } // Got the Field from the INF Line
  932. } // Process all INFs in the Include Line
  933. } // Found an Include= Line
  934. }
  935. BOOL
  936. InstallAllInfSections(
  937. IN PPSETUP_LOCAL_DATA pLocalData,
  938. IN PLATFORM platform,
  939. IN LPCTSTR pszServerName,
  940. IN HSPFILEQ CopyQueue,
  941. IN LPCTSTR pszSource,
  942. IN DWORD dwInstallFlags,
  943. IN HINF hInf,
  944. IN LPCTSTR pszInstallSection
  945. )
  946. {
  947. BOOL bRet = FALSE;
  948. HINF hIncludeInf;
  949. INFCONTEXT INFContext;
  950. PINFCONTEXT pINFContext = &INFContext;
  951. INFCONTEXT NeedsContext;
  952. PINFCONTEXT pNeedsContext = &NeedsContext;
  953. DWORD dwBufferNeeded;
  954. PTSTR pszINFName = NULL;
  955. PTSTR pszSectionName = NULL;
  956. if ( CopyQueue == INVALID_HANDLE_VALUE ||
  957. !SetTargetDirectories( pLocalData,
  958. platform,
  959. pszServerName,
  960. hInf,
  961. dwInstallFlags ) ||
  962. !SetupInstallFilesFromInfSection(
  963. hInf,
  964. NULL,
  965. CopyQueue,
  966. pszInstallSection,
  967. pszSource,
  968. SP_COPY_LANGUAGEAWARE) )
  969. goto Cleanup;
  970. // To get the source directories correct, we need to load all included INFs
  971. // separately. THen use their associated layout files.
  972. if ( SetupFindFirstLine( hInf, pszInstallSection, TEXT( "Include" ), pINFContext ) )
  973. {
  974. // Find each INF and load it & it's LAYOUT files
  975. DWORD dwINFs = SetupGetFieldCount( pINFContext );
  976. DWORD dwIIndex;
  977. for ( dwIIndex = 1; dwIIndex <= dwINFs; dwIIndex++ )
  978. {
  979. if ( SetupGetStringField( pINFContext, dwIIndex, NULL, 0, &dwBufferNeeded ) )
  980. {
  981. pszINFName = (PTSTR) LocalAllocMem( dwBufferNeeded * sizeof(TCHAR) );
  982. if ( pszINFName )
  983. {
  984. if ( SetupGetStringField( pINFContext, dwIIndex, pszINFName, ( dwBufferNeeded * sizeof(TCHAR) ), &dwBufferNeeded ) )
  985. {
  986. //
  987. // Open INF file and append layout.inf specified in Version section
  988. // Layout inf is optional
  989. //
  990. // SetupOpenAppendInfFile( pszINFName, hPrinterInf, NULL);
  991. hIncludeInf = SetupOpenInfFile(pszINFName,
  992. NULL,
  993. INF_STYLE_WIN4,
  994. NULL);
  995. if ( hIncludeInf == INVALID_HANDLE_VALUE )
  996. goto Cleanup;
  997. SetupOpenAppendInfFile( NULL, hIncludeInf, NULL);
  998. // Now process all need sections for this INF
  999. // Now find the Needs Line and install all called sections
  1000. if ( SetupFindFirstLine( hInf, pszInstallSection, TEXT( "needs" ), pNeedsContext ) )
  1001. {
  1002. // Find each INF and load it & it's LAYOUT files
  1003. DWORD dwSections = SetupGetFieldCount( pNeedsContext );
  1004. DWORD dwNIndex;
  1005. for ( dwNIndex = 1; dwNIndex <= dwSections; dwNIndex++ )
  1006. {
  1007. if ( SetupGetStringField( pNeedsContext, dwNIndex, NULL, 0, &dwBufferNeeded ) )
  1008. {
  1009. pszSectionName = (PTSTR) LocalAllocMem( dwBufferNeeded * sizeof(TCHAR) );
  1010. if ( pszSectionName )
  1011. {
  1012. if ( SetupGetStringField( pNeedsContext, dwNIndex, pszSectionName, ( dwBufferNeeded * sizeof(TCHAR) ), &dwBufferNeeded ) )
  1013. {
  1014. if ( SetTargetDirectories(pLocalData,
  1015. platform,
  1016. pszServerName,
  1017. hIncludeInf,
  1018. dwInstallFlags) )
  1019. {
  1020. if ( !SetupInstallFilesFromInfSection(
  1021. hIncludeInf,
  1022. NULL,
  1023. CopyQueue,
  1024. pszSectionName,
  1025. NULL,
  1026. SP_COPY_LANGUAGEAWARE) )
  1027. goto Cleanup;
  1028. } // Able to setup Target Dirs
  1029. else
  1030. goto Cleanup;
  1031. } // Got a Section Name
  1032. LocalFreeMem( pszSectionName );
  1033. pszSectionName = NULL;
  1034. } // Allocated pszSectionName
  1035. } // Got the Field from the Section Line
  1036. } // Process all Sections in the Needs Line
  1037. } // Found a Needs= Line
  1038. // Close included INF
  1039. if ( hIncludeInf != INVALID_HANDLE_VALUE )
  1040. SetupCloseInfFile(hIncludeInf);
  1041. } // Got an INF Name
  1042. LocalFreeMem( pszINFName );
  1043. pszINFName = NULL;
  1044. } // Allocated pszINFName
  1045. } // Got the Field from the INF Line
  1046. } // Process all INFs in the Include Line
  1047. } // Found an Include= Line
  1048. bRet = TRUE;
  1049. Cleanup:
  1050. if ( pszINFName )
  1051. LocalFreeMem( pszINFName );
  1052. if ( pszSectionName )
  1053. LocalFreeMem( pszSectionName );
  1054. return bRet;
  1055. }
  1056. BOOL
  1057. ParseInf(
  1058. IN HDEVINFO hDevInfo,
  1059. IN PPSETUP_LOCAL_DATA pLocalData,
  1060. IN PLATFORM platform,
  1061. IN LPCTSTR pszServerName,
  1062. IN DWORD dwInstallFlags
  1063. )
  1064. /*++
  1065. Routine Description:
  1066. Copies driver information from an Inf file to a DriverInfo3 structure.
  1067. The following fields are filled on successful return
  1068. pName
  1069. pDriverPath
  1070. pDataFile
  1071. pConfigFile
  1072. pHelpFile
  1073. pMonitorName
  1074. pDefaultDataType
  1075. Arguments:
  1076. pLocalData :
  1077. platform : Platform for which inf should be parsed
  1078. Return Value:
  1079. TRUE -- Succesfully parsed the inf and built info for the selected driver
  1080. FALSE -- On Error
  1081. --*/
  1082. {
  1083. PPARSEINF_INFO pInfInfo = &pLocalData->InfInfo;
  1084. PDRIVER_INFO_6 pDriverInfo6 = &pLocalData->InfInfo.DriverInfo6;
  1085. LPTSTR pszDataSection, psz, pszInstallSection;
  1086. BOOL bWin95 = platform == PlatformWin95,
  1087. bFail = TRUE, bDataSection = FALSE;
  1088. INFCONTEXT Context;
  1089. DWORD cchDriverInfo6, dwNeeded, dwDontCare;
  1090. HINF hInf;
  1091. //
  1092. // Check if INF is already parsed, and if so for the right platform
  1093. //
  1094. if ( pLocalData->Flags & VALID_INF_INFO ) {
  1095. if ( platform == pInfInfo->platform )
  1096. return TRUE;
  1097. FreeStructurePointers((LPBYTE)pInfInfo, InfInfoOffsets, FALSE);
  1098. pLocalData->Flags &= ~VALID_INF_INFO;
  1099. ZeroMemory(pInfInfo, sizeof(*pInfInfo));
  1100. }
  1101. pszDataSection = NULL;
  1102. hInf = SetupOpenInfFile(pLocalData->DrvInfo.pszInfName,
  1103. NULL,
  1104. INF_STYLE_WIN4,
  1105. NULL);
  1106. if ( hInf == INVALID_HANDLE_VALUE )
  1107. goto Cleanup;
  1108. if ( bWin95 ) {
  1109. pszInstallSection = AllocStr(pLocalData->DrvInfo.pszDriverSection);
  1110. if ( !pszInstallSection )
  1111. goto Cleanup;
  1112. } else {
  1113. if ( !SetupSetPlatformPathOverride(PlatformOverride[platform].pszName) )
  1114. goto Cleanup;
  1115. if ( !SetupDiGetActualSectionToInstall(
  1116. hInf,
  1117. pLocalData->DrvInfo.pszDriverSection,
  1118. NULL,
  1119. 0,
  1120. &dwNeeded,
  1121. NULL) ||
  1122. !(pInfInfo->pszInstallSection
  1123. = (LPTSTR) LocalAllocMem(dwNeeded * sizeof(TCHAR))) ||
  1124. !SetupDiGetActualSectionToInstall(
  1125. hInf,
  1126. pLocalData->DrvInfo.pszDriverSection,
  1127. pInfInfo->pszInstallSection,
  1128. dwNeeded,
  1129. NULL,
  1130. NULL) ) {
  1131. SetupSetPlatformPathOverride(NULL);
  1132. goto Cleanup;
  1133. }
  1134. SetupSetPlatformPathOverride(NULL);
  1135. pszInstallSection = pInfInfo->pszInstallSection;
  1136. }
  1137. //
  1138. // Now load all other INFs referenced in the Install Section
  1139. //
  1140. AddAllIncludedInf( hInf, pszInstallSection );
  1141. if ( !(pDriverInfo6->pName = AllocStr(pLocalData->DrvInfo.pszModelName)) )
  1142. goto Cleanup;
  1143. bFail = FALSE;
  1144. if(bFail)
  1145. {
  1146. goto Cleanup;
  1147. }
  1148. //
  1149. // Does the driver section have a data section name specified?
  1150. //
  1151. if ( SetupFindFirstLine(hInf, pszInstallSection,
  1152. cszDataSection, &Context) ) {
  1153. InfGetString(&Context, 1, &pszDataSection, &dwDontCare, &bFail);
  1154. bDataSection = TRUE;
  1155. }
  1156. cchDriverInfo6 = lstrlen(pDriverInfo6->pName) + 1;
  1157. //
  1158. // If DataFile key is not found data file is same as driver section name
  1159. //
  1160. InfGetDriverInfoString(hInf,
  1161. pszInstallSection,
  1162. pszDataSection,
  1163. bDataSection,
  1164. cszDataFile,
  1165. &pDriverInfo6->pDataFile,
  1166. pszInstallSection,
  1167. &cchDriverInfo6,
  1168. &bFail);
  1169. //
  1170. // If DriverFile key is not found driver file is the driver section name
  1171. //
  1172. InfGetDriverInfoString(hInf,
  1173. pszInstallSection,
  1174. pszDataSection,
  1175. bDataSection,
  1176. cszDriverFile,
  1177. &pDriverInfo6->pDriverPath,
  1178. pszInstallSection,
  1179. &cchDriverInfo6,
  1180. &bFail);
  1181. //
  1182. // If ConfigFile key is not found config file is same as driver file
  1183. //
  1184. InfGetDriverInfoString(hInf,
  1185. pszInstallSection,
  1186. pszDataSection,
  1187. bDataSection,
  1188. cszConfigFile,
  1189. &pDriverInfo6->pConfigFile,
  1190. pDriverInfo6->pDriverPath,
  1191. &cchDriverInfo6,
  1192. &bFail);
  1193. //
  1194. // Help file is optional, and by default NULL
  1195. //
  1196. InfGetDriverInfoString(hInf,
  1197. pszInstallSection,
  1198. pszDataSection,
  1199. bDataSection,
  1200. cszHelpFile,
  1201. &pDriverInfo6->pHelpFile,
  1202. NULL,
  1203. &cchDriverInfo6,
  1204. &bFail);
  1205. //
  1206. // Monitor name is optional, and by default none
  1207. //
  1208. InfGet2PartString(hInf,
  1209. pszInstallSection,
  1210. pszDataSection,
  1211. bDataSection,
  1212. cszLanguageMonitor,
  1213. &pDriverInfo6->pMonitorName,
  1214. &bFail);
  1215. if ( psz = pDriverInfo6->pMonitorName ) {
  1216. psz += lstrlen(psz) + 1;
  1217. cchDriverInfo6 += lstrlen(pDriverInfo6->pMonitorName) + lstrlen(psz) + 2;
  1218. }
  1219. //
  1220. // Print processor is optional, and by default none
  1221. //
  1222. InfGet2PartString(hInf,
  1223. pszInstallSection,
  1224. pszDataSection,
  1225. bDataSection,
  1226. cszPrintProcessor,
  1227. &pLocalData->InfInfo.pszPrintProc,
  1228. &bFail);
  1229. //
  1230. // Default data type is optional, and by default none
  1231. //
  1232. InfGetDriverInfoString(hInf,
  1233. pszInstallSection,
  1234. pszDataSection,
  1235. bDataSection,
  1236. cszDefaultDataType,
  1237. &pDriverInfo6->pDefaultDataType,
  1238. NULL,
  1239. &cchDriverInfo6,
  1240. &bFail);
  1241. //
  1242. // Vendor setup is optional, and by default none
  1243. //
  1244. InfGetVendorSetup(pInfInfo,
  1245. hInf,
  1246. pszInstallSection,
  1247. pszDataSection,
  1248. bDataSection,
  1249. &bFail);
  1250. //
  1251. // Vendor installation is optional, and by default none
  1252. //
  1253. InfGetDriverInfoString(hInf,
  1254. pszInstallSection,
  1255. pszDataSection,
  1256. bDataSection,
  1257. cszVendorInstaller,
  1258. &pInfInfo->pszVendorInstaller,
  1259. NULL,
  1260. &dwDontCare,
  1261. &bFail);
  1262. bFail = bFail || !InfGetDependentFilesAndICMFiles(hDevInfo,
  1263. hInf,
  1264. bWin95,
  1265. pLocalData,
  1266. platform,
  1267. pszServerName,
  1268. dwInstallFlags,
  1269. pszInstallSection,
  1270. &cchDriverInfo6);
  1271. if ( !bWin95 ) {
  1272. InfGetPreviousNames(hInf,
  1273. &pLocalData->DrvInfo,
  1274. &cchDriverInfo6,
  1275. &bFail);
  1276. InfGetOEMUrl(hInf,
  1277. &pLocalData->DrvInfo,
  1278. &bFail);
  1279. }
  1280. Cleanup:
  1281. //
  1282. // Save the last error is we've failed. SetupCloseInfFile can change the last error and we
  1283. // don't care about it's last error in any way.
  1284. //
  1285. if( bFail ) {
  1286. dwDontCare = GetLastError();
  1287. }
  1288. LocalFreeMem(pszDataSection);
  1289. if ( hInf != INVALID_HANDLE_VALUE )
  1290. SetupCloseInfFile(hInf);
  1291. //
  1292. // On failure free all the fields filled by this routine
  1293. //
  1294. if ( bFail ) {
  1295. FreeStructurePointers((LPBYTE)pInfInfo, InfInfoOffsets, FALSE);
  1296. ZeroMemory(pInfInfo, sizeof(*pInfInfo));
  1297. SetLastError( dwDontCare );
  1298. } else {
  1299. // Point members of DriverInfo6 to strings in pDrvInfo
  1300. pInfInfo->DriverInfo6.pszzPreviousNames = pLocalData->DrvInfo.pszzPreviousNames;
  1301. pLocalData->InfInfo.DriverInfo6.pszMfgName = pLocalData->DrvInfo.pszManufacturer;
  1302. if ( pLocalData->InfInfo.DriverInfo6.pszMfgName )
  1303. cchDriverInfo6 += ( lstrlen( pLocalData->InfInfo.DriverInfo6.pszMfgName ) + 1 );
  1304. pLocalData->InfInfo.DriverInfo6.pszOEMUrl = pLocalData->DrvInfo.pszOEMUrl;
  1305. if ( pLocalData->InfInfo.DriverInfo6.pszOEMUrl )
  1306. cchDriverInfo6 += ( lstrlen( pLocalData->InfInfo.DriverInfo6.pszOEMUrl ) + 1 );
  1307. pLocalData->InfInfo.DriverInfo6.pszHardwareID = pLocalData->DrvInfo.pszHardwareID;
  1308. if ( pLocalData->InfInfo.DriverInfo6.pszHardwareID )
  1309. cchDriverInfo6 += ( lstrlen( pLocalData->InfInfo.DriverInfo6.pszHardwareID ) + 1 );
  1310. pLocalData->InfInfo.DriverInfo6.pszProvider = pLocalData->DrvInfo.pszProvider;
  1311. if ( pLocalData->InfInfo.DriverInfo6.pszProvider )
  1312. cchDriverInfo6 += ( lstrlen( pLocalData->InfInfo.DriverInfo6.pszProvider ) + 1 );
  1313. pLocalData->InfInfo.DriverInfo6.ftDriverDate = pLocalData->DrvInfo.ftDriverDate;
  1314. pLocalData->InfInfo.DriverInfo6.dwlDriverVersion = pLocalData->DrvInfo.dwlDriverVersion;
  1315. pInfInfo->cbDriverInfo6 = sizeof(DRIVER_INFO_6) +
  1316. cchDriverInfo6 * sizeof(TCHAR);
  1317. pLocalData->Flags |= VALID_INF_INFO;
  1318. pInfInfo->platform = platform;
  1319. }
  1320. return !bFail;
  1321. }
  1322. LPDRIVER_INFO_6
  1323. GetDriverInfo6(
  1324. IN PSELECTED_DRV_INFO pSelectedDrvInfo
  1325. )
  1326. /*++
  1327. Routine Description:
  1328. Gets the selected drivers information in a DRIVER_INFO_6 structure.
  1329. Arguments:
  1330. Return Value:
  1331. Pointer to the DRIVER_INFO_6 structure. Memory is allocated for it.
  1332. --*/
  1333. {
  1334. HINF hInf;
  1335. PPSETUP_LOCAL_DATA LocalData = NULL;
  1336. LPDRIVER_INFO_6 pDriverInfo6 = NULL;
  1337. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  1338. if ( !pSelectedDrvInfo ||
  1339. !pSelectedDrvInfo->pszInfName ||
  1340. !*pSelectedDrvInfo->pszInfName ||
  1341. !pSelectedDrvInfo->pszModelName ||
  1342. !*pSelectedDrvInfo->pszModelName ||
  1343. !pSelectedDrvInfo->pszDriverSection ||
  1344. !*pSelectedDrvInfo->pszDriverSection ) {
  1345. SetLastError(ERROR_INVALID_PARAMETER);
  1346. return NULL;
  1347. }
  1348. if(INVALID_HANDLE_VALUE == (hDevInfo = CreatePrinterDeviceInfoList(NULL)))
  1349. {
  1350. return NULL;
  1351. }
  1352. LocalData = PSetupDriverInfoFromName(hDevInfo, pSelectedDrvInfo->pszModelName);
  1353. if (!LocalData)
  1354. {
  1355. return NULL;
  1356. }
  1357. if ( ParseInf(hDevInfo, LocalData, MyPlatform, NULL, 0) ) {
  1358. pDriverInfo6 = CloneDriverInfo6(&(LocalData->InfInfo.DriverInfo6),
  1359. LocalData->InfInfo.cbDriverInfo6);
  1360. }
  1361. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  1362. DestroyLocalData( LocalData );
  1363. return pDriverInfo6;
  1364. }
  1365. LPDRIVER_INFO_3
  1366. PSetupGetDriverInfo3(
  1367. IN PSELECTED_DRV_INFO pSelectedDrvInfo
  1368. )
  1369. /*++
  1370. Routine Description:
  1371. Gets the selected drivers information in a DRIVER_INFO_3 structure.
  1372. This is for the test teams use
  1373. Arguments:
  1374. Return Value:
  1375. Pointer to the DRIVER_INFO_3 structure. Memory is allocated for it.
  1376. --*/
  1377. {
  1378. return (LPDRIVER_INFO_3) GetDriverInfo6(pSelectedDrvInfo);
  1379. }
  1380. LPTSTR
  1381. GetStringFromRcFile(
  1382. UINT uId
  1383. )
  1384. /*++
  1385. Routine Description:
  1386. Load a string from the .rc file and make a copy of it by doing AllocStr
  1387. Arguments:
  1388. uId : Identifier for the string to be loaded
  1389. Return Value:
  1390. String value loaded, NULL on error. Caller should free the memory
  1391. --*/
  1392. {
  1393. TCHAR buffer[MAX_SETUP_LEN];
  1394. int RetVal = 0;
  1395. RetVal = LoadString(ghInst, uId, buffer, SIZECHARS(buffer));
  1396. if ( RetVal )
  1397. {
  1398. return AllocStr(buffer);
  1399. }
  1400. else
  1401. {
  1402. return NULL;
  1403. }
  1404. }
  1405. LPTSTR
  1406. GetLongStringFromRcFile(
  1407. UINT uId
  1408. )
  1409. /*++
  1410. Routine Description:
  1411. Load a long string from the .rc file, up to MAX_SETUP_ALLOC_STRING_LEN characters
  1412. Arguments:
  1413. uId : Identifier for the string to be loaded
  1414. Return Value:
  1415. String value loaded, NULL on error. Caller should free the memory
  1416. --*/
  1417. {
  1418. LPTSTR pBuf = NULL;
  1419. int Retry = 0, RetVal;
  1420. //
  1421. // I couldn't find a way to determine the length of a string the resource file, hence
  1422. // I just try until the length returned by LoadString is smaller than the buffer I passed in
  1423. //
  1424. for (Retry = 1; Retry <= MAX_SETUP_ALLOC_STRING_LEN/MAX_SETUP_LEN; Retry++)
  1425. {
  1426. int CurrentSize = Retry * MAX_SETUP_LEN;
  1427. pBuf = LocalAllocMem(CurrentSize * sizeof(TCHAR));
  1428. if (!pBuf)
  1429. {
  1430. return NULL;
  1431. }
  1432. RetVal = LoadString(ghInst, uId, pBuf, CurrentSize);
  1433. if (RetVal == 0)
  1434. {
  1435. LocalFreeMem(pBuf);
  1436. return NULL;
  1437. }
  1438. if (RetVal < CurrentSize -1) // -1 because the LoadString ret value doesn't include the termination
  1439. {
  1440. return pBuf;
  1441. }
  1442. //
  1443. // RetVal is CurrentSize - retry
  1444. //
  1445. LocalFreeMem(pBuf);
  1446. }
  1447. return NULL;
  1448. }
  1449. BOOL
  1450. PSetupGetPathToSearch(
  1451. IN HWND hwnd,
  1452. IN LPCTSTR pszTitle,
  1453. IN LPCTSTR pszDiskName,
  1454. IN LPCTSTR pszFileName,
  1455. IN BOOL bPromptForInf,
  1456. IN OUT TCHAR szPath[MAX_PATH]
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. Get path to search for some files by prompting the user
  1461. Arguments:
  1462. hwnd : Window handle of current top-level window
  1463. pszTitle : Title for the UI
  1464. pszDiskName : Diskname ot prompt the user
  1465. pszFileName : Name of the file we are looking for (NULL ok)
  1466. pszPath : Buffer to get the path entered by the user
  1467. Return Value:
  1468. TRUE on succesfully getting a path from user
  1469. FALSE else, Do GetLastError() to get the error
  1470. --*/
  1471. {
  1472. DWORD dwReturn, dwNeeded;
  1473. dwReturn = SetupPromptForDisk(hwnd,
  1474. pszTitle,
  1475. pszDiskName,
  1476. szPath[0] ? szPath : NULL,
  1477. pszFileName,
  1478. NULL,
  1479. bPromptForInf ?
  1480. (IDF_NOSKIP | IDF_NOBEEP | IDF_NOREMOVABLEMEDIAPROMPT | IDF_USEDISKNAMEASPROMPT) :
  1481. (IDF_NOSKIP | IDF_NOBEEP),
  1482. szPath,
  1483. MAX_PATH,
  1484. &dwNeeded);
  1485. if ( dwReturn == DPROMPT_SUCCESS ) {
  1486. //
  1487. // Remove this from source list so that next time we are looking for
  1488. // native drivers we do not end up picking from wrong source
  1489. //
  1490. SetupRemoveFromSourceList(SRCLIST_SYSIFADMIN, szPath);
  1491. //
  1492. // Terminate with a \ at the end
  1493. //
  1494. dwNeeded = lstrlen(szPath);
  1495. if ( *(szPath + dwNeeded - 1) != TEXT('\\') &&
  1496. dwNeeded < MAX_PATH - 2 ) {
  1497. *(szPath + dwNeeded) = TEXT('\\');
  1498. *(szPath + dwNeeded + 1) = sZero;
  1499. }
  1500. return TRUE;
  1501. }
  1502. if ( dwReturn == DPROMPT_OUTOFMEMORY ||
  1503. dwReturn == DPROMPT_BUFFERTOOSMALL ) {
  1504. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1505. } else {
  1506. SetLastError(ERROR_CANCELLED);
  1507. }
  1508. return FALSE;
  1509. }
  1510. INT
  1511. IsDifferent(
  1512. LPTSTR p1,
  1513. LPTSTR p2,
  1514. DWORD (*pfn)(LPTSTR, LPTSTR)
  1515. )
  1516. /*++
  1517. Routine Description:
  1518. Extended version of strcmp/memcmp kind of function. Treats NULL pointer and
  1519. the pointer to NULL as a match. For other cases call function passed in.
  1520. Arguments:
  1521. p1 : First address to compare
  1522. p2 : Second address to compare
  1523. pfn : Function to call if both p1 and p2 are non-NULL
  1524. Return Value:
  1525. + means p1 > p2 (like how memcmp or strcmp defines), - means p1 < p2.
  1526. 0 if the values match
  1527. --*/
  1528. {
  1529. //
  1530. // We want to treat NULL ptr and ptr to NULL as the same thing
  1531. //
  1532. if ( p1 && !*p1 )
  1533. p1 = NULL;
  1534. if ( p2 && !*p2 )
  1535. p2 = NULL;
  1536. //
  1537. // If both are NULL then they match
  1538. //
  1539. if ( !p1 && !p2 )
  1540. return 0;
  1541. //
  1542. // Both are non NULL
  1543. //
  1544. if ( p1 && p2 )
  1545. return pfn(p1, p2);
  1546. //
  1547. // One of them is NULL
  1548. //
  1549. if ( p1 )
  1550. return 1;
  1551. else
  1552. return -1;
  1553. }
  1554. LPTSTR
  1555. FileNamePart(
  1556. IN LPCTSTR pszFullName
  1557. )
  1558. /*++
  1559. Routine Description:
  1560. Find the file name part of a fully qualified file name
  1561. Arguments:
  1562. pszFullName : Fully qualified path to the file
  1563. Return Value:
  1564. Pointer to the filename part in the fully qulaified string
  1565. --*/
  1566. {
  1567. LPTSTR pszSlash, pszTemp;
  1568. if ( !pszFullName )
  1569. return NULL;
  1570. //
  1571. // First find the : for the drive
  1572. //
  1573. if ( pszTemp = lstrchr(pszFullName, TEXT(':')) )
  1574. pszFullName = pszFullName + 1;
  1575. for ( pszTemp = (LPTSTR)pszFullName ;
  1576. pszSlash = lstrchr(pszTemp, TEXT('\\')) ;
  1577. pszTemp = pszSlash + 1 )
  1578. ;
  1579. return *pszTemp ? pszTemp : NULL;
  1580. }
  1581. BOOL
  1582. SameMultiSz(
  1583. LPTSTR ppsz1,
  1584. LPTSTR ppsz2,
  1585. BOOL bFileName
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. Checks if 2 multi-sz fields are the same. If bFileName is TRUE then
  1590. get the file name part and compare that only (i.e. dependent files)
  1591. Arguments:
  1592. ppsz1 : DependentFiles field from the INF
  1593. ppsz2 : DependentFiles field from the spooler
  1594. bFileName : If TRUE compare file names, ignoring full path
  1595. Return Value:
  1596. TRUE if the string are identical, FALSE else
  1597. 0 if the values match
  1598. --*/
  1599. {
  1600. LPTSTR p1, p2, p3;
  1601. if ( !ppsz1 && !ppsz2 )
  1602. return TRUE;
  1603. if ( !ppsz1 || !ppsz2 )
  1604. return FALSE;
  1605. //
  1606. // Check the file count is the same in the two lists
  1607. //
  1608. for ( p1 = ppsz1, p2 = ppsz2 ;
  1609. *p1 && *p2 ;
  1610. p1 += lstrlen(p1) + 1, p2 += lstrlen(p2) + 1 )
  1611. ; // Nul body
  1612. //
  1613. // If one of them is not NULL the number of strings is different
  1614. //
  1615. if ( *p1 || *p2 )
  1616. return FALSE;
  1617. //
  1618. // For each file in the first list see if it is present in the second list
  1619. //
  1620. for ( p1 = ppsz1 ; *p1 ; p1 += lstrlen(p1) + 1 ) {
  1621. for ( p2 = ppsz2 ; *p2 ; p2 += lstrlen(p2) + 1 ) {
  1622. p3 = bFileName ? FileNamePart(p2) : p2;
  1623. if ( p3 && !lstrcmpi(p1, p3) )
  1624. break;
  1625. }
  1626. //
  1627. // We did not find p1 in ppsz2
  1628. //
  1629. if ( !*p2 )
  1630. return FALSE;
  1631. }
  1632. return TRUE;
  1633. }
  1634. BOOL
  1635. IdenticalDriverInfo6(
  1636. IN LPDRIVER_INFO_6 p1,
  1637. IN LPDRIVER_INFO_6 p2
  1638. )
  1639. /*++
  1640. Routine Description:
  1641. Checks if DRIVER_INFO_6 are the same
  1642. Arguments:
  1643. p1 : DRIVER_INFO_6 from the INF
  1644. p2 : DRIVER_INFO_6 returned by the spooler
  1645. Return Value:
  1646. TRUE if the DRIVER_INFO_6s are identical, FALSE else
  1647. --*/
  1648. {
  1649. LPTSTR psz;
  1650. return (p1->dwlDriverVersion == (DWORDLONG)0 ||
  1651. p2->dwlDriverVersion == (DWORDLONG)0 ||
  1652. p1->dwlDriverVersion == p2->dwlDriverVersion) &&
  1653. !lstrcmpi(p1->pName, p2->pName) &&
  1654. (psz = FileNamePart(p2->pDriverPath)) &&
  1655. !lstrcmpi(p1->pDriverPath, psz) &&
  1656. (psz = FileNamePart(p2->pDataFile)) &&
  1657. !lstrcmpi(p1->pDataFile, psz) &&
  1658. (psz = FileNamePart(p2->pConfigFile)) &&
  1659. !lstrcmpi(p1->pConfigFile, psz) &&
  1660. !IsDifferent(p1->pHelpFile,
  1661. FileNamePart(p2->pHelpFile),
  1662. lstrcmpi) &&
  1663. !IsDifferent(p1->pMonitorName,
  1664. p2->pMonitorName,
  1665. lstrcmpi);
  1666. /*
  1667. We changed the way we find dependent files from NT4 to NT5.
  1668. So we do not want to look at them while deciding if a driver came from
  1669. an INF.
  1670. !IsDifferent(p1->pDefaultDataType,
  1671. p2->pDefaultDataType,
  1672. lstrcmpi);
  1673. SameMultiSz(p1->pDependentFiles, p2->pDependentFiles, TRUE) &&
  1674. SameMultiSz(p1->pszzPreviousNames, p2->pszzPreviousNames, FALSE);
  1675. */
  1676. }
  1677. BOOL
  1678. AllICMFilesInstalled(
  1679. IN LPCTSTR pszServerName,
  1680. IN LPTSTR pszzICMFiles
  1681. )
  1682. /*++
  1683. Routine Description:
  1684. Checks if all the icm files given are installed on the specified machine
  1685. Arguments:
  1686. pszServerName : Name of the server
  1687. pszzICMFiles : Multi-sz field giving all the ICM files
  1688. Return Value:
  1689. TRUE if all the ICM profiles are installed on the server, FALSE else
  1690. --*/
  1691. {
  1692. BOOL bRet = FALSE;
  1693. LPBYTE buf = NULL;
  1694. LPTSTR p1, p2;
  1695. DWORD dwNeeded, dwReturned;
  1696. ENUMTYPE EnumType;
  1697. if ( !pszzICMFiles || !*pszzICMFiles )
  1698. return TRUE;
  1699. //
  1700. // ICM apis are not remotablr for now
  1701. //
  1702. if ( pszServerName )
  1703. goto Cleanup;
  1704. ZeroMemory(&EnumType, sizeof(EnumType));
  1705. EnumType.dwSize = sizeof(EnumType);
  1706. EnumType.dwVersion = ENUM_TYPE_VERSION;
  1707. //
  1708. // Get all the color profiles installed on the machine
  1709. //
  1710. dwNeeded = 0;
  1711. if ( EnumColorProfiles((LPTSTR)pszServerName,
  1712. &EnumType,
  1713. NULL,
  1714. &dwNeeded,
  1715. &dwReturned) ||
  1716. GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  1717. !(buf = LocalAllocMem(dwNeeded)) ||
  1718. !EnumColorProfiles((LPTSTR)pszServerName,
  1719. &EnumType,
  1720. buf,
  1721. &dwNeeded,
  1722. &dwReturned) ) {
  1723. goto Cleanup;
  1724. }
  1725. for ( p1 = pszzICMFiles ; *p1 ; p1 += lstrlen(p1) + 1 ) {
  1726. for ( p2 = (LPTSTR)buf, dwNeeded = 0 ;
  1727. dwNeeded < dwReturned && *p2 && lstrcmpi(p1, p2) ;
  1728. ++dwNeeded, p2 += lstrlen(p2) + 1 )
  1729. ;
  1730. //
  1731. // Did we find p1 in the enumerated color profiles?
  1732. //
  1733. if ( dwNeeded == dwReturned )
  1734. goto Cleanup;
  1735. }
  1736. bRet = TRUE;
  1737. Cleanup:
  1738. LocalFreeMem(buf);
  1739. return bRet;
  1740. }
  1741. BOOL
  1742. CorrectVersionDriverFound(
  1743. IN LPDRIVER_INFO_2 pDriverInfo2,
  1744. IN DWORD dwCount,
  1745. IN LPCTSTR pszDriverName,
  1746. IN DWORD dwMajorVersion
  1747. )
  1748. /*++
  1749. Routine Description:
  1750. Check if the correct version driver we are looking for is found in the list
  1751. we got from spooler
  1752. Arguments:
  1753. pDriverInfo2 : Points to the buffer of DRIVER_INFO_2 structs
  1754. dwCount : Number of DRIVER_INFO_2 elements in the buffer
  1755. szDriverName : Driver name
  1756. dwMajorVersion : Version no
  1757. Return Value:
  1758. TRUE if driver is found in the lise, FALSE else
  1759. --*/
  1760. {
  1761. DWORD dwIndex;
  1762. for ( dwIndex = 0 ; dwIndex < dwCount ; ++dwIndex, ++pDriverInfo2 ) {
  1763. //
  1764. // Check if the driver is for the correct version
  1765. //
  1766. if ( dwMajorVersion != KERNEL_MODE_DRIVER_VERSION &&
  1767. dwMajorVersion != pDriverInfo2->cVersion )
  1768. continue;
  1769. if ( dwMajorVersion == KERNEL_MODE_DRIVER_VERSION &&
  1770. pDriverInfo2->cVersion < 2 )
  1771. continue;
  1772. if ( !lstrcmpi(pDriverInfo2->pName, pszDriverName) )
  1773. return TRUE;
  1774. }
  1775. return FALSE;
  1776. }
  1777. BOOL
  1778. PSetupIsDriverInstalled(
  1779. IN LPCTSTR pszServerName,
  1780. IN LPCTSTR pszDriverName,
  1781. IN PLATFORM platform,
  1782. IN DWORD dwMajorVersion
  1783. )
  1784. /*++
  1785. Routine Description:
  1786. Findsout if a particular version of a printer driver is already installed
  1787. in the system by querying spooler
  1788. Arguments:
  1789. pszServerName : Server name (NULL for local)
  1790. pszDriverName : Driver name
  1791. platform : platform for which we want to check the driver
  1792. dwMajorVersion : Version no
  1793. Return Value:
  1794. TRUE if driver is installed,
  1795. FALSE else (on error too)
  1796. --*/
  1797. {
  1798. BOOL bReturn = FALSE;
  1799. DWORD dwReturned, dwNeeded = 1024, dwReturned2;
  1800. LPBYTE p = NULL, p2 = NULL;
  1801. LPTSTR psz;
  1802. LPDRIVER_INFO_6 pDriverInfo6;
  1803. LPTSTR pszServerArchitecture = NULL;
  1804. if ( !(p = LocalAllocMem(dwNeeded)) )
  1805. goto Cleanup;
  1806. if ( !EnumPrinterDrivers((LPTSTR)pszServerName,
  1807. PlatformEnv[platform].pszName,
  1808. 2,
  1809. p,
  1810. dwNeeded,
  1811. &dwNeeded,
  1812. &dwReturned) ) {
  1813. LocalFreeMem(p);
  1814. p = NULL;
  1815. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  1816. !(p = LocalAllocMem(dwNeeded)) ||
  1817. !EnumPrinterDrivers((LPTSTR)pszServerName,
  1818. PlatformEnv[platform].pszName,
  1819. 2,
  1820. p,
  1821. dwNeeded,
  1822. &dwNeeded,
  1823. &dwReturned) ) {
  1824. goto Cleanup;
  1825. }
  1826. }
  1827. bReturn = CorrectVersionDriverFound((LPDRIVER_INFO_2)p,
  1828. dwReturned,
  1829. pszDriverName,
  1830. dwMajorVersion);
  1831. //
  1832. // Win95 drivers could have a different name than NT driver
  1833. //
  1834. if ( bReturn || platform != PlatformWin95 )
  1835. goto Cleanup;
  1836. dwNeeded = 1024;
  1837. if ( !(p2 = LocalAllocMem(dwNeeded)) )
  1838. goto Cleanup;
  1839. pszServerArchitecture = GetArchitectureName( (LPTSTR)pszServerName );
  1840. if (!pszServerArchitecture)
  1841. {
  1842. goto Cleanup;
  1843. }
  1844. if ( !EnumPrinterDrivers((LPTSTR)pszServerName,
  1845. pszServerArchitecture,
  1846. 6,
  1847. p2,
  1848. dwNeeded,
  1849. &dwNeeded,
  1850. &dwReturned2) ) {
  1851. LocalFreeMem(p2);
  1852. p2 = NULL;
  1853. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  1854. !(p2 = LocalAllocMem(dwNeeded)) ||
  1855. !EnumPrinterDrivers((LPTSTR)pszServerName,
  1856. pszServerArchitecture,
  1857. 6,
  1858. p2,
  1859. dwNeeded,
  1860. &dwNeeded,
  1861. &dwReturned2) )
  1862. goto Cleanup;
  1863. }
  1864. for ( dwNeeded = 0, pDriverInfo6 = (LPDRIVER_INFO_6)p2 ;
  1865. dwNeeded < dwReturned2 ;
  1866. ++pDriverInfo6, ++dwNeeded ) {
  1867. if ( pDriverInfo6->cVersion < 2 )
  1868. continue;
  1869. if ( !lstrcmpi(pDriverInfo6->pName, pszDriverName) )
  1870. break;
  1871. }
  1872. if ( dwNeeded < dwReturned2 && (psz = pDriverInfo6->pszzPreviousNames) )
  1873. while ( *psz ) {
  1874. if ( bReturn = CorrectVersionDriverFound((LPDRIVER_INFO_2)p,
  1875. dwReturned,
  1876. psz,
  1877. dwMajorVersion) )
  1878. break;
  1879. psz += lstrlen(psz) + 1;
  1880. }
  1881. Cleanup:
  1882. LocalFreeMem(p);
  1883. LocalFreeMem(p2);
  1884. LocalFreeMem( pszServerArchitecture );
  1885. return bReturn;
  1886. }
  1887. INT
  1888. PSetupIsTheDriverFoundInInfInstalled(
  1889. IN LPCTSTR pszServerName,
  1890. IN PPSETUP_LOCAL_DATA pLocalData,
  1891. IN PLATFORM platform,
  1892. IN DWORD dwMajorVersion
  1893. )
  1894. /*++
  1895. Routine Description:
  1896. Findsout if a particular version of a printer driver is already installed
  1897. in the system by querying spooler; Additionally check if the installed
  1898. driver is the same found in the INF (file name matches only)
  1899. Arguments:
  1900. pszServerName : Server name (NULL for local)
  1901. szDriverName : Driver name
  1902. platform : platform for which we want to check the driver
  1903. dwMajorVersion : Version no;
  1904. If KERNEL_MODE_DRIVER_VERSION check for a KM driver
  1905. Return Value:
  1906. DRIVER_MODEL_INSTALLED_AND_IDENTICAL :
  1907. if driver is installed and all files are identical
  1908. DRIVER_MODEL_NOT_INSTALLED :
  1909. if a driver with the given model name is not available
  1910. DRIVER_MODEL_INSTALLED_BUT_DIFFERENT :
  1911. a driver with the given model name is installed but not all files
  1912. are identical
  1913. --*/
  1914. {
  1915. INT iRet = DRIVER_MODEL_NOT_INSTALLED;
  1916. DWORD dwReturned,
  1917. dwNeeded,
  1918. dwLastError;
  1919. LPBYTE p = NULL;
  1920. LPDRIVER_INFO_6 p1DriverInfo6,
  1921. p2DriverInfo6;
  1922. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  1923. ASSERT(pLocalData && pLocalData->signature == PSETUP_SIGNATURE);
  1924. if(INVALID_HANDLE_VALUE == (hDevInfo = CreatePrinterDeviceInfoList(NULL)))
  1925. {
  1926. goto Cleanup;
  1927. }
  1928. if ( !ParseInf(hDevInfo, pLocalData, platform, pszServerName, 0) )
  1929. goto Cleanup;
  1930. p1DriverInfo6 = &pLocalData->InfInfo.DriverInfo6;
  1931. if ( EnumPrinterDrivers((LPTSTR)pszServerName,
  1932. PlatformEnv[platform].pszName,
  1933. 6,
  1934. NULL,
  1935. 0,
  1936. &dwNeeded,
  1937. &dwReturned) ) {
  1938. goto Cleanup;
  1939. }
  1940. if ( (dwLastError = GetLastError()) == ERROR_INVALID_LEVEL ) {
  1941. iRet = PSetupIsDriverInstalled(pszServerName,
  1942. p1DriverInfo6->pName,
  1943. platform,
  1944. dwMajorVersion)
  1945. ? DRIVER_MODEL_INSTALLED_BUT_DIFFERENT
  1946. : DRIVER_MODEL_NOT_INSTALLED;
  1947. goto Cleanup;
  1948. }
  1949. if ( dwLastError != ERROR_INSUFFICIENT_BUFFER ||
  1950. !(p = LocalAllocMem(dwNeeded)) ||
  1951. !EnumPrinterDrivers((LPTSTR)pszServerName,
  1952. PlatformEnv[platform].pszName,
  1953. 6,
  1954. p,
  1955. dwNeeded,
  1956. &dwNeeded,
  1957. &dwReturned) ) {
  1958. goto Cleanup;
  1959. }
  1960. for ( dwNeeded = 0, p2DriverInfo6 = (LPDRIVER_INFO_6) p ;
  1961. dwNeeded < dwReturned ;
  1962. ++dwNeeded, (LPBYTE) p2DriverInfo6 += sizeof(DRIVER_INFO_6) ) {
  1963. //
  1964. // Check if the driver is for the correct version
  1965. //
  1966. if ( dwMajorVersion != KERNEL_MODE_DRIVER_VERSION &&
  1967. dwMajorVersion != p2DriverInfo6->cVersion )
  1968. continue;
  1969. if ( dwMajorVersion == KERNEL_MODE_DRIVER_VERSION &&
  1970. p2DriverInfo6->cVersion < 2 )
  1971. continue;
  1972. if ( !lstrcmpi(p2DriverInfo6->pName, p1DriverInfo6->pName) ) {
  1973. if ( IdenticalDriverInfo6(p1DriverInfo6,
  1974. p2DriverInfo6) &&
  1975. AllICMFilesInstalled(pszServerName,
  1976. pLocalData->InfInfo.pszzICMFiles) )
  1977. iRet = DRIVER_MODEL_INSTALLED_AND_IDENTICAL;
  1978. else
  1979. iRet = DRIVER_MODEL_INSTALLED_BUT_DIFFERENT;
  1980. goto Cleanup;
  1981. }
  1982. }
  1983. Cleanup:
  1984. LocalFreeMem(p);
  1985. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  1986. return iRet;
  1987. }
  1988. PLATFORM
  1989. PSetupThisPlatform(
  1990. VOID
  1991. )
  1992. {
  1993. return MyPlatform;
  1994. }
  1995. BOOL
  1996. DeleteAllFilesInDirectory(
  1997. LPCTSTR pszDir,
  1998. BOOL bDeleteDirectory
  1999. )
  2000. /*++
  2001. Routine Description:
  2002. Delete all the files in a directory, and optionally the directory as well.
  2003. Arguments:
  2004. pszDir : Directory name to cleanup
  2005. bDeleteDirectory : If TRUE the directory gets deleted as well
  2006. Return Value:
  2007. TRUE on success, FALSE else
  2008. --*/
  2009. {
  2010. BOOL bRet = TRUE;
  2011. HANDLE hFile;
  2012. DWORD dwLen;
  2013. TCHAR *pszFile = NULL;
  2014. TCHAR *pszBuf = NULL;
  2015. INT cbLength = 0;
  2016. INT cbBufLength = 0;
  2017. INT cbInitialLength = 4 * MAX_PATH;
  2018. WIN32_FIND_DATA FindData;
  2019. if (!pszDir)
  2020. {
  2021. bRet = FALSE;
  2022. goto Cleanup;
  2023. }
  2024. cbLength = max( cbInitialLength, lstrlen( pszDir ) + lstrlen( TEXT("\\*") ) + 1);
  2025. pszFile = LocalAllocMem( cbLength * sizeof( TCHAR ));
  2026. if (!pszFile)
  2027. {
  2028. bRet = FALSE;
  2029. goto Cleanup;
  2030. }
  2031. lstrcpy(pszFile, pszDir);
  2032. dwLen = lstrlen(pszFile);
  2033. lstrcpy(pszFile + dwLen, TEXT("\\*"));
  2034. hFile = FindFirstFile(pszFile, &FindData);
  2035. if ( hFile == INVALID_HANDLE_VALUE )
  2036. {
  2037. bRet = FALSE;
  2038. goto Cleanup;
  2039. }
  2040. *(pszFile + dwLen + 1) = TEXT('\0');
  2041. pszBuf = AllocStr( pszFile );
  2042. if (!pszBuf)
  2043. {
  2044. bRet = FALSE;
  2045. goto Cleanup;
  2046. }
  2047. cbBufLength = lstrlen( pszBuf );
  2048. do {
  2049. if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  2050. continue;
  2051. cbLength = cbBufLength + lstrlen( FindData.cFileName ) + 1;
  2052. if (cbLength > cbInitialLength)
  2053. {
  2054. LocalFreeMem( pszFile );
  2055. pszFile = LocalAllocMem( cbLength * sizeof( TCHAR ));
  2056. if (!pszFile)
  2057. {
  2058. bRet = FALSE;
  2059. goto Cleanup;
  2060. }
  2061. cbInitialLength = cbLength;
  2062. }
  2063. lstrcpy(pszFile, pszBuf);
  2064. lstrcat(pszFile, FindData.cFileName );
  2065. //
  2066. // Remove the FILE_ATTRIBUTE_READONLY file attribute if it has been set
  2067. //
  2068. if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY )
  2069. {
  2070. SetFileAttributes( pszFile,
  2071. FindData.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY );
  2072. }
  2073. if ( !DeleteFile(pszFile) )
  2074. bRet = FALSE;
  2075. } while ( FindNextFile(hFile, &FindData) );
  2076. FindClose(hFile);
  2077. if ( bDeleteDirectory && !RemoveDirectory(pszDir) )
  2078. bRet = FALSE;
  2079. Cleanup:
  2080. LocalFreeMem( pszFile );
  2081. LocalFreeMem( pszBuf );
  2082. return bRet;
  2083. }
  2084. //
  2085. // enum to store the NT-CD type
  2086. //
  2087. typedef enum _eCDType {
  2088. CD_Unknown,
  2089. CD_NT4,
  2090. CD_W2K_SRV,
  2091. CD_W2K_PRO,
  2092. CD_WHISTLER_SRV,
  2093. CD_WHISTLER_WKS
  2094. } CD_TYPE;
  2095. //
  2096. // structure that stores the tag file names of the NT CDs
  2097. //
  2098. typedef struct _CD_TAGFILE_MAP_ENTRY {
  2099. CD_TYPE CdType;
  2100. LPTSTR pszTagFileName;
  2101. }CD_TAGFILE_MAP_ENTRY;
  2102. CD_TAGFILE_MAP_ENTRY TagEntries[] =
  2103. {
  2104. //
  2105. // the following entry for the Whistler CD is special in a couple of ways:
  2106. // - it uses a wildcard because the tag filename changes from Beta1 to Beta2 and again to RTM
  2107. // - it identifies the CD as W2k despite it being for Whistler. The reason is that the layout regarding
  2108. // printer drivers is identical to W2k, no need to distinguish (and duplicate entries)
  2109. //
  2110. { CD_W2K_SRV, _T("WIN51.*") },
  2111. { CD_W2K_SRV, _T("CDROM_NT.5") },
  2112. { CD_NT4, _T("CDROM_S.40") },
  2113. { CD_NT4, _T("CDROM_W.40") },
  2114. //
  2115. // no need to identify NT3.x CDs - different codepath !
  2116. //
  2117. { CD_Unknown, NULL }
  2118. };
  2119. //
  2120. // structure to store the subpaths to printer INFs on the NT CDs
  2121. //
  2122. typedef struct _CD_SUBPATHS_FOR_PLATFORMS {
  2123. CD_TYPE CdType;
  2124. PLATFORM Platform;
  2125. DWORD Version;
  2126. LPCTSTR pszSubPath;
  2127. } CD_SUBPATHS_FOR_PLATFORMS;
  2128. //
  2129. // this list is used for lookup of pathes as well - must be sorted so that paths
  2130. // that contain other paths must come before them (e.g. xxx\zzz before \zzz)
  2131. //
  2132. CD_SUBPATHS_FOR_PLATFORMS SubPathInfo[] =
  2133. {
  2134. { CD_W2K_SRV, PlatformX86, 2, _T("printers\\nt4\\i386\\") },
  2135. { CD_W2K_SRV, PlatformWin95, 0, _T("printers\\win9x\\") },
  2136. { CD_W2K_SRV, PlatformX86, 3, _T("i386\\") },
  2137. { CD_W2K_SRV, PlatformIA64, 3, _T("ia64\\") },
  2138. { CD_NT4, PlatformX86, 2, _T("i386\\") },
  2139. { CD_NT4, PlatformAlpha, 2, _T("alpha\\") },
  2140. { CD_NT4, PlatformMIPS, 2, _T("mips\\") },
  2141. { CD_NT4, PlatformPPC, 2, _T("ppc\\") },
  2142. //
  2143. // path = NULL terminates the array
  2144. //
  2145. { CD_Unknown, PlatformX86, 0 , NULL }
  2146. };
  2147. CD_TYPE
  2148. DetermineCDType(LPTSTR pszInfPath, LPTSTR pszRootPath)
  2149. /*++
  2150. Routine Description:
  2151. From a path to a printer INF, figure out what (if any) NT CD this is.
  2152. It does so by figuring out the root path if it's one of the NT CDs and
  2153. then checking the tag file that should be there.
  2154. Arguments:
  2155. pszInfPath : path to INF
  2156. pszRootPath : caller-supplied buffer (MAX_PATH long) that receives the
  2157. path to the CD "root". This is nontrivial in case the CD
  2158. is on a network share. Ends with a backslash
  2159. Return Value:
  2160. The type of CD detected, CD_Unknown if not one that we know of (i.e. an OEM CD)
  2161. --*/
  2162. {
  2163. LPTSTR pszTemp;
  2164. DWORD i;
  2165. //
  2166. // find the root path
  2167. //
  2168. DWORD_PTR MinPathLen = 0, SubPathLen, len;
  2169. _tcscpy(pszRootPath, pszInfPath);
  2170. len = _tcslen(pszRootPath);
  2171. //
  2172. // make sure it ends with a backslash
  2173. //
  2174. if (pszRootPath[len-1] != _T('\\'))
  2175. {
  2176. pszRootPath[len++] = _T('\\');
  2177. pszRootPath[len] = 0;
  2178. }
  2179. //
  2180. // Is it a UNC path ?
  2181. //
  2182. if (!_tcsncmp(pszRootPath, _T("\\\\"), 2))
  2183. {
  2184. pszTemp = _tcschr(pszRootPath + 2, _T('\\'));
  2185. if (pszTemp)
  2186. {
  2187. pszTemp = _tcschr(pszTemp+1, _T('\\'));
  2188. if (pszTemp)
  2189. {
  2190. MinPathLen = pszTemp - pszRootPath;
  2191. }
  2192. }
  2193. //
  2194. // check for illegal path, shouldn't happen
  2195. //
  2196. if ((MinPathLen == 0) || (MinPathLen > len))
  2197. {
  2198. return CD_Unknown;
  2199. }
  2200. }
  2201. else
  2202. {
  2203. MinPathLen = 2;
  2204. }
  2205. //
  2206. // now check whether the final part of the path is one that I know of
  2207. //
  2208. for (i = 0; SubPathInfo[i].pszSubPath != NULL; ++i)
  2209. {
  2210. SubPathLen = _tcslen(SubPathInfo[i].pszSubPath);
  2211. if (SubPathLen + MinPathLen <= len)
  2212. {
  2213. if (!_tcsnicmp(&(pszRootPath[len - SubPathLen]),
  2214. SubPathInfo[i].pszSubPath, SubPathLen))
  2215. {
  2216. pszRootPath[len-SubPathLen] = 0;
  2217. len = _tcslen(pszRootPath);
  2218. break;
  2219. }
  2220. }
  2221. }
  2222. //
  2223. // if it's none of the paths I know of, it can still be the root itself.
  2224. // now I know where the tag files should be if they're there
  2225. //
  2226. for (i = 0;TagEntries[i].pszTagFileName != NULL; ++i)
  2227. {
  2228. _tcscpy(&(pszRootPath[len]), TagEntries[i].pszTagFileName);
  2229. if (FileExists(pszRootPath))
  2230. {
  2231. pszRootPath[len] = 0; // cut off the tag file name
  2232. return TagEntries[i].CdType;
  2233. }
  2234. }
  2235. return CD_Unknown;
  2236. }
  2237. BOOL
  2238. CheckValidInfInPath(HWND hwnd, LPTSTR pszInfPath, DWORD dwVersion, PLATFORM Platform)
  2239. {
  2240. TCHAR szInfFiles[MAX_PATH];
  2241. WIN32_FIND_DATA FindData;
  2242. HANDLE hFind;
  2243. DWORD PathLen;
  2244. BOOL bRet = FALSE;
  2245. //
  2246. // first, find the INF in the path. There must be one else SetupPromptForPath would've complained
  2247. //
  2248. _tcscpy(szInfFiles, pszInfPath);
  2249. PathLen = _tcslen(szInfFiles);
  2250. if (szInfFiles[PathLen-1] != _T('\\'))
  2251. {
  2252. szInfFiles[PathLen++] = _T('\\');
  2253. szInfFiles[PathLen] = 0;
  2254. }
  2255. _tcscat(szInfFiles, _T("*.inf"));
  2256. hFind = FindFirstFile(szInfFiles, &FindData);
  2257. if (hFind != INVALID_HANDLE_VALUE)
  2258. {
  2259. DWORD InfStyle;
  2260. HANDLE hInfFile;
  2261. if ((dwVersion == 0) && (Platform != PlatformWin95))
  2262. {
  2263. InfStyle = INF_STYLE_OLDNT;
  2264. }
  2265. else
  2266. {
  2267. InfStyle = INF_STYLE_WIN4;
  2268. }
  2269. do
  2270. {
  2271. _tcscpy(&(szInfFiles[PathLen]), FindData.cFileName);
  2272. hInfFile = SetupOpenInfFile(szInfFiles, _T("Printer"), InfStyle, NULL);
  2273. if (hInfFile != INVALID_HANDLE_VALUE)
  2274. {
  2275. SetupCloseInfFile(hInfFile);
  2276. bRet = TRUE;
  2277. break;
  2278. }
  2279. } while ( FindNextFile(hFind, &FindData) );
  2280. FindClose(hFind);
  2281. }
  2282. if (!bRet)
  2283. {
  2284. LPTSTR pszFormat = NULL, pszPrompt = NULL, pszTitle = NULL;
  2285. pszFormat = GetStringFromRcFile(IDS_WARN_NO_ALT_PLATFORM_DRIVER);
  2286. pszTitle = GetStringFromRcFile(IDS_WARN_NO_DRIVER_FOUND);
  2287. if ( pszFormat && pszTitle)
  2288. {
  2289. pszPrompt = LocalAllocMem((lstrlen(pszFormat) + lstrlen(pszInfPath) + 2)
  2290. * sizeof(TCHAR));
  2291. if ( pszPrompt )
  2292. {
  2293. wsprintf(pszPrompt, pszFormat, pszInfPath);
  2294. MessageBox(hwnd, pszPrompt, pszTitle, MB_OK);
  2295. LocalFreeMem(pszPrompt);
  2296. }
  2297. }
  2298. LocalFreeMem(pszFormat);
  2299. LocalFreeMem(pszTitle);
  2300. }
  2301. return bRet;
  2302. }
  2303. BOOL
  2304. CheckInfPath(HWND hwnd, LPTSTR pszInfPath, DWORD dwVersion, PLATFORM platform,
  2305. LPTSTR *ppFileSrcPath)
  2306. /*++
  2307. Routine Description:
  2308. Check whether the path that a user selected as a path to install a printer
  2309. from points to one of our CDs and correct the path if necessary, i.e. if
  2310. the luser selected the \i386 subdir for an NT4 driver.
  2311. Arguments:
  2312. hwnd : windows handle of the main window
  2313. pszInfPath : path to INF
  2314. dwVersion : driver version that the new driver is installed for
  2315. platform : the platform that the new driver is installed for
  2316. ppFileSrcPath: if not NULL, receives the path to the printer files. This
  2317. is used for installation from the NT4 CD that contains a
  2318. compressed INF that I have to uncompress and install from
  2319. without copying all the files possibly referenced in it.
  2320. Needs to be freed by the caller.
  2321. Return Value:
  2322. TRUE: path contains a valid print inf
  2323. FALSE: path doesn't contain a print inf, prompt user again
  2324. --*/
  2325. {
  2326. CD_TYPE CDType;
  2327. TCHAR szRootPath[MAX_PATH];
  2328. DWORD i;
  2329. //
  2330. // determine the type of CD
  2331. //
  2332. CDType = DetermineCDType(pszInfPath, szRootPath);
  2333. if (CDType == CD_Unknown)
  2334. {
  2335. return CheckValidInfInPath(hwnd, pszInfPath, dwVersion, platform);
  2336. }
  2337. //
  2338. // NT 4 drivers are compressed -> uncompress into temp dir
  2339. //
  2340. if ((dwVersion == 2) && (CDType == CD_NT4))
  2341. {
  2342. //
  2343. // Make sure the file is actually the compressed one
  2344. //
  2345. DWORD rc, CompressedFileSize, UncompressedFileSize;
  2346. UINT CompType;
  2347. LPTSTR pszUncompFilePath = NULL, pszInfFileName = _T("ntprint.in_");
  2348. TCHAR szInf[MAX_PATH];
  2349. _tcscpy(szInf, szRootPath);
  2350. //
  2351. // append the correct subpath
  2352. //
  2353. for (i = 0; SubPathInfo[i].pszSubPath != NULL; ++i)
  2354. {
  2355. if ((SubPathInfo[i].CdType == CD_NT4) &&
  2356. (platform == SubPathInfo[i].Platform) &&
  2357. (dwVersion == SubPathInfo[i].Version))
  2358. {
  2359. _tcscat(szInf, SubPathInfo[i].pszSubPath);
  2360. break;
  2361. }
  2362. }
  2363. _tcscat(szInf, pszInfFileName);
  2364. rc = SetupGetFileCompressionInfo(szInf,
  2365. &pszUncompFilePath,
  2366. &CompressedFileSize,
  2367. &UncompressedFileSize,
  2368. &CompType);
  2369. if (rc == NO_ERROR)
  2370. {
  2371. LocalFree(pszUncompFilePath); // don't need that
  2372. if (CompType != FILE_COMPRESSION_NONE)
  2373. {
  2374. TCHAR UncompFilePath[MAX_PATH], *pTmp;
  2375. //
  2376. // decompress into temp directory
  2377. //
  2378. if (GetTempPath(MAX_PATH, UncompFilePath) &&
  2379. (_tcscat(UncompFilePath, _T("ntprint.inf")) != NULL) &&
  2380. (SetupDecompressOrCopyFile(szInf, UncompFilePath, NULL) == NO_ERROR))
  2381. {
  2382. if (ppFileSrcPath)
  2383. {
  2384. //
  2385. // delete the inf name from the path
  2386. //
  2387. pTmp = _tcsrchr(szInf, _T('\\'));
  2388. if (pTmp)
  2389. {
  2390. *(pTmp+1) = 0;
  2391. }
  2392. *ppFileSrcPath = AllocStr(szInf);
  2393. }
  2394. _tcscpy(pszInfPath, UncompFilePath);
  2395. //
  2396. // delete the inf name from the path
  2397. //
  2398. pTmp = _tcsrchr(pszInfPath, _T('\\'));
  2399. if (pTmp)
  2400. {
  2401. *(pTmp+1) = 0;
  2402. }
  2403. return TRUE;
  2404. }
  2405. }
  2406. }
  2407. }
  2408. //
  2409. // correct the path if it's the one for a different platform
  2410. //
  2411. for (i = 0; SubPathInfo[i].pszSubPath != NULL; ++i)
  2412. {
  2413. if ((CDType == SubPathInfo[i].CdType) &&
  2414. (platform == SubPathInfo[i].Platform) &&
  2415. (dwVersion == SubPathInfo[i].Version))
  2416. {
  2417. _tcscpy(pszInfPath, szRootPath);
  2418. _tcscat(pszInfPath, SubPathInfo[i].pszSubPath);
  2419. break;
  2420. }
  2421. }
  2422. return CheckValidInfInPath(hwnd, pszInfPath, dwVersion, platform);
  2423. }
  2424. HDEVINFO
  2425. GetInfAndBuildDrivers(
  2426. IN HWND hwnd,
  2427. IN DWORD dwTitleId,
  2428. IN DWORD dwDiskId,
  2429. IN TCHAR szInfPath[MAX_PATH],
  2430. IN DWORD dwInstallFlags,
  2431. IN PLATFORM platform,
  2432. IN DWORD dwVersion,
  2433. IN LPCTSTR pszDriverName, OPTIONAL
  2434. OUT PPSETUP_LOCAL_DATA *ppLocalData, OPTIONAL
  2435. OUT LPTSTR *ppFileSrcPath OPTIONAL
  2436. )
  2437. /*++
  2438. Routine Description:
  2439. Prompt for an INF and build the list of printer drivers from INFs found
  2440. in the directory. If pszDriverName is passed in then the INF should have
  2441. a model with matching name (i.e. alternate driver installation case)
  2442. Arguments:
  2443. hwnd : Parent window handle for UI
  2444. dwTitleId : Gives the identifier to be used to load the title string
  2445. from the rc file
  2446. dwDiskId : Gives the identifier to be used to load the disk identifier
  2447. from the rc file
  2448. szInfPath : Directory name where inf was found
  2449. pszDriverName : Name of the driver needed in the INF
  2450. ppLocalData : If a driver nam is given on return this will give
  2451. the local data for that
  2452. dwInstallFlags : Flags to control installation operation
  2453. Return Value:
  2454. TRUE on success, FALSE else
  2455. --*/
  2456. {
  2457. BOOL bDoRetry = TRUE;
  2458. DWORD dwLen, dwLastError;
  2459. LPTSTR pszTitle = NULL, pszDisk = NULL;
  2460. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  2461. dwLen = lstrlen(szInfPath);
  2462. szInfPath[dwLen] = TEXT('\\');
  2463. if ( dwLen + lstrlen(cszAllInfs) + 1 > MAX_PATH )
  2464. goto Cleanup;
  2465. lstrcpy(szInfPath+dwLen + 1, cszAllInfs);
  2466. Retry:
  2467. if ( bDoRetry && FileExists(szInfPath) ) {
  2468. szInfPath[dwLen] = TEXT('\0');
  2469. } else {
  2470. //
  2471. // if the file doesn't exist in the first place, prompt only once !
  2472. //
  2473. bDoRetry = FALSE;
  2474. //
  2475. // Always just prompt with the CD-ROM path
  2476. //
  2477. GetCDRomDrive(szInfPath);
  2478. if ( dwInstallFlags & DRVINST_PROMPTLESS ) {
  2479. SetLastError(ERROR_FILE_NOT_FOUND);
  2480. goto Cleanup;
  2481. }
  2482. if ( dwTitleId && !(pszTitle = GetStringFromRcFile(dwTitleId)) )
  2483. goto Cleanup;
  2484. if ( dwDiskId && !(pszDisk = GetStringFromRcFile(dwDiskId)) )
  2485. goto Cleanup;
  2486. do
  2487. {
  2488. if ( !PSetupGetPathToSearch(hwnd, pszTitle, pszDisk,
  2489. cszAllInfs, TRUE, szInfPath) )
  2490. goto Cleanup;
  2491. } while (!CheckInfPath(hwnd, szInfPath, dwVersion, platform, ppFileSrcPath));
  2492. }
  2493. hDevInfo = CreatePrinterDeviceInfoList(hwnd);
  2494. if ( hDevInfo == INVALID_HANDLE_VALUE ||
  2495. !SetDevInstallParams(hDevInfo, NULL, szInfPath) ||
  2496. !BuildClassDriverList(hDevInfo) ||
  2497. (pszDriverName &&
  2498. !(*ppLocalData = PSetupDriverInfoFromName(hDevInfo,
  2499. pszDriverName))) ) {
  2500. dwLastError = GetLastError();
  2501. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  2502. hDevInfo = INVALID_HANDLE_VALUE;
  2503. SetLastError(dwLastError);
  2504. if ( bDoRetry ) {
  2505. bDoRetry = FALSE;
  2506. goto Retry;
  2507. }
  2508. goto Cleanup;
  2509. }
  2510. Cleanup:
  2511. LocalFreeMem(pszTitle);
  2512. LocalFreeMem(pszDisk);
  2513. return hDevInfo;
  2514. }
  2515. BOOL
  2516. MyName(
  2517. IN LPCTSTR pszServerName
  2518. )
  2519. /*++
  2520. Routine Description:
  2521. Tells if the string passed in identifies the local machine. Currently
  2522. it checks for NULL and computer name only
  2523. Arguments:
  2524. pszServerName : Name of the server passed in
  2525. Return Value:
  2526. TRUE if the name is recognized as that for local machine, FALSE else
  2527. --*/
  2528. {
  2529. TCHAR szBuf[MAX_COMPUTERNAME_LENGTH+1];
  2530. DWORD dwNeeded;
  2531. if ( !pszServerName || !*pszServerName )
  2532. return TRUE;
  2533. return FALSE;
  2534. /*
  2535. dwNeeded = SIZECHARS(szBuf);
  2536. if ( *pszServerName == TEXT('\\') &&
  2537. *(pszServerName+1) == TEXT('\\') &&
  2538. GetComputerName(szBuf, &dwNeeded) &&
  2539. !lstrcmpi(pszServerName+2, szBuf) ) {
  2540. return TRUE;
  2541. }
  2542. */
  2543. }
  2544. BOOL
  2545. PSetupGetLocalDataField(
  2546. IN PPSETUP_LOCAL_DATA pLocalData,
  2547. IN PLATFORM platform,
  2548. IN OUT PDRIVER_FIELD pDrvField
  2549. )
  2550. /*++
  2551. Routine Description:
  2552. Returns a driver installation field found from inf parsing.
  2553. Printui uses this routine for all the queries.
  2554. Since INF could have different sections for different platforms
  2555. (notably for Win95 and NT but architecture specific install sections
  2556. are possible too)
  2557. Arguments:
  2558. pLocalData : Pointer to local data
  2559. platform : Which platform the field is for
  2560. pDrvField : Points to DRIVER_FIELD where field is copied to
  2561. Return Value:
  2562. TRUE on success, FALSE else
  2563. --*/
  2564. {
  2565. BOOL bRet = FALSE;
  2566. DWORD cbSize;
  2567. LPTSTR psz;
  2568. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  2569. ASSERT(pLocalData &&
  2570. pDrvField &&
  2571. pLocalData->signature == PSETUP_SIGNATURE);
  2572. if(INVALID_HANDLE_VALUE == (hDevInfo = CreatePrinterDeviceInfoList(NULL)))
  2573. {
  2574. return bRet;
  2575. }
  2576. switch ( pDrvField->Index ) {
  2577. case DRIVER_NAME:
  2578. if ( pDrvField->pszDriverName = AllocStr(pLocalData->DrvInfo.pszModelName) )
  2579. bRet = TRUE;
  2580. break;
  2581. case INF_NAME:
  2582. if ( pDrvField->pszInfName = AllocStr(pLocalData->DrvInfo.pszInfName) )
  2583. bRet = TRUE;
  2584. break;
  2585. case DRV_INFO_4:
  2586. if ( ParseInf(hDevInfo, pLocalData, platform, NULL, 0) &&
  2587. (pDrvField->pDriverInfo4
  2588. = (LPDRIVER_INFO_4) CloneDriverInfo6(&pLocalData->InfInfo.DriverInfo6,
  2589. pLocalData->InfInfo.cbDriverInfo6)) )
  2590. bRet = TRUE;
  2591. break;
  2592. case DRV_INFO_6:
  2593. if ( ParseInf(hDevInfo, pLocalData, platform, NULL, 0) &&
  2594. (pDrvField->pDriverInfo6
  2595. = CloneDriverInfo6(&pLocalData->InfInfo.DriverInfo6,
  2596. pLocalData->InfInfo.cbDriverInfo6)) )
  2597. bRet = TRUE;
  2598. break;
  2599. case PRINT_PROCESSOR_NAME:
  2600. pDrvField->pszPrintProc = NULL;
  2601. if ( ParseInf(hDevInfo, pLocalData, platform, NULL, 0) ) {
  2602. if ( !pLocalData->InfInfo.pszPrintProc ||
  2603. (pDrvField->pszPrintProc = AllocStr(pLocalData->InfInfo.pszPrintProc)) )
  2604. bRet = TRUE;
  2605. }
  2606. break;
  2607. case ICM_FILES:
  2608. pDrvField->pszzICMFiles = NULL;
  2609. if ( ParseInf(hDevInfo, pLocalData, platform, NULL ,0) ) {
  2610. for ( cbSize = 0, psz = pLocalData->InfInfo.pszzICMFiles ;
  2611. psz && *psz ;
  2612. cbSize += lstrlen(psz) + 1, psz += lstrlen(psz) + 1 )
  2613. ;
  2614. if ( cbSize == 0 ) {
  2615. bRet = TRUE;
  2616. break;
  2617. }
  2618. //
  2619. // One more char for the last \0 in the multi-sz
  2620. //
  2621. cbSize = (cbSize + 1 ) * sizeof(TCHAR);
  2622. if ( pDrvField->pszzICMFiles = LocalAllocMem(cbSize) ) {
  2623. CopyMemory((LPBYTE)pDrvField->pszzICMFiles,
  2624. (LPBYTE)pLocalData->InfInfo.pszzICMFiles,
  2625. cbSize);
  2626. bRet = TRUE;
  2627. }
  2628. }
  2629. break;
  2630. default:
  2631. SetLastError(ERROR_INVALID_PARAMETER);
  2632. bRet = FALSE;
  2633. }
  2634. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  2635. return bRet;
  2636. }
  2637. VOID
  2638. PSetupFreeDrvField(
  2639. IN PDRIVER_FIELD pDrvField
  2640. )
  2641. /*++
  2642. Routine Description:
  2643. Frees the memory allocated for a driver installation field in a previous
  2644. call
  2645. Arguments:
  2646. pDrvField : Points to DRIVER_FIELD where field is copied to
  2647. Return Value:
  2648. None
  2649. --*/
  2650. {
  2651. LocalFreeMem(pDrvField->pszPrintProc);
  2652. }
  2653. BOOL
  2654. FileExists(
  2655. IN LPCTSTR pszFileName
  2656. )
  2657. /*++
  2658. Routine Description:
  2659. Checks if the given file exists setting correct error modes not to bring
  2660. up any pop-ups.
  2661. call
  2662. Arguments:
  2663. pszFileName : File name (fully qualified)
  2664. Return Value:
  2665. TRUE if file exists, FALSE else.
  2666. --*/
  2667. {
  2668. UINT OldMode;
  2669. HANDLE hFile;
  2670. WIN32_FIND_DATA FindData;
  2671. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  2672. hFile = FindFirstFile(pszFileName, &FindData);
  2673. if ( hFile != INVALID_HANDLE_VALUE )
  2674. FindClose(hFile);
  2675. SetErrorMode(OldMode);
  2676. return hFile != INVALID_HANDLE_VALUE;
  2677. }
  2678. BOOL
  2679. IsMonitorInstalled(
  2680. IN LPTSTR pszMonitorName
  2681. )
  2682. {
  2683. LPBYTE pMonitors = NULL;
  2684. DWORD dwNeeded, dwReturned;
  2685. BOOL bMonFound = FALSE;
  2686. // First Build a list of Monitors installed on machine
  2687. //
  2688. // First query spooler for installed monitors. If we fail let's quit
  2689. //
  2690. if ( !EnumMonitors((LPTSTR) NULL, 2, NULL, 0, &dwNeeded, &dwReturned) )
  2691. {
  2692. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  2693. !(pMonitors = LocalAllocMem(dwNeeded)) ||
  2694. !EnumMonitors((LPTSTR) NULL, 2, pMonitors, dwNeeded, &dwNeeded, &dwReturned) )
  2695. {
  2696. goto Cleanup;
  2697. }
  2698. // Now see if the monitor is already installed
  2699. if ( IsMonitorFound(pMonitors, dwReturned, pszMonitorName) )
  2700. bMonFound = TRUE;
  2701. }
  2702. Cleanup:
  2703. if (pMonitors)
  2704. LocalFreeMem( pMonitors );
  2705. return bMonFound;
  2706. }
  2707. BOOL
  2708. IsLanguageMonitorInstalled(PCTSTR pszMonitorName)
  2709. /*++
  2710. Routine Description:
  2711. Checks for whether a language monitor is installed. The function above only checks for
  2712. port monitors, because EnumMonitors doesn't enumerate language monitors. Since there is
  2713. no API to do that, we sneak a peek at the registry. XP-Bug 416129.
  2714. Arguments:
  2715. pszMonitorName : Monitor name to check
  2716. Return Value:
  2717. TRUE if installed
  2718. --*/
  2719. {
  2720. PTSTR pKeyName = NULL;
  2721. BOOL IsInstalled = FALSE;
  2722. StrCatAlloc(&pKeyName, cszMonitorKey, pszMonitorName, NULL);
  2723. if (pKeyName)
  2724. {
  2725. HKEY hKey;
  2726. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pKeyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  2727. {
  2728. IsInstalled = TRUE;
  2729. RegCloseKey(hKey);
  2730. }
  2731. FreeSplMem(pKeyName);
  2732. }
  2733. return IsInstalled;
  2734. }
  2735. BOOL
  2736. CleanupUniqueScratchDirectory(
  2737. IN LPCTSTR pszServerName,
  2738. IN PLATFORM platform
  2739. )
  2740. {
  2741. BOOL bRet;
  2742. TCHAR szDir[MAX_PATH];
  2743. DWORD dwNeeded;
  2744. bRet = GetPrinterDriverDirectory((LPTSTR)pszServerName,
  2745. PlatformEnv[platform].pszName,
  2746. 1,
  2747. (LPBYTE)szDir,
  2748. sizeof(szDir),
  2749. &dwNeeded);
  2750. if (bRet)
  2751. {
  2752. bRet = AddDirectoryTag(szDir, MAX_PATH);
  2753. }
  2754. if (bRet)
  2755. {
  2756. bRet = DeleteAllFilesInDirectory(szDir, TRUE);
  2757. }
  2758. return bRet;
  2759. }
  2760. BOOL
  2761. CleanupScratchDirectory(
  2762. IN LPCTSTR pszServerName,
  2763. IN PLATFORM platform
  2764. )
  2765. {
  2766. TCHAR szDir[MAX_PATH];
  2767. DWORD dwNeeded;
  2768. return GetPrinterDriverDirectory((LPTSTR)pszServerName,
  2769. PlatformEnv[platform].pszName,
  2770. 1,
  2771. (LPBYTE)szDir,
  2772. sizeof(szDir),
  2773. &dwNeeded) &&
  2774. DeleteAllFilesInDirectory(szDir, FALSE);
  2775. }
  2776. LPTSTR
  2777. GetSystemInstallPath(
  2778. VOID
  2779. )
  2780. {
  2781. BOOL bRet = FALSE;
  2782. DWORD dwSize, dwType;
  2783. HKEY hKey;
  2784. TCHAR szSetupKey[] = TEXT( "Software\\Microsoft\\Windows\\CurrentVersion\\Setup");
  2785. TCHAR szSourceValue[] = TEXT("SourcePath");
  2786. LPTSTR pszSourcePath = NULL;
  2787. if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2788. szSetupKey,
  2789. 0,
  2790. KEY_QUERY_VALUE,
  2791. &hKey) ) {
  2792. if ( ERROR_SUCCESS == RegQueryValueEx(hKey,
  2793. szSourceValue,
  2794. NULL,
  2795. &dwType,
  2796. NULL,
  2797. &dwSize) )
  2798. {
  2799. if (pszSourcePath = (LPTSTR) LocalAllocMem(dwSize))
  2800. {
  2801. if ( ERROR_SUCCESS != RegQueryValueEx(hKey,
  2802. szSourceValue,
  2803. NULL,
  2804. &dwType,
  2805. (LPBYTE)pszSourcePath,
  2806. &dwSize) )
  2807. {
  2808. LocalFreeMem(pszSourcePath);
  2809. pszSourcePath = NULL;
  2810. }
  2811. }
  2812. }
  2813. RegCloseKey(hKey);
  2814. }
  2815. return pszSourcePath;
  2816. }
  2817. PPSETUP_LOCAL_DATA
  2818. RebuildDeviceInfo(
  2819. IN HDEVINFO hDevInfo,
  2820. IN PPSETUP_LOCAL_DATA pLocalData,
  2821. IN LPCTSTR pszSource
  2822. )
  2823. {
  2824. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  2825. SP_DRVINFO_DATA DriverInfoData, TempDriverInfoData;
  2826. PPSETUP_LOCAL_DATA pNewLocalData = NULL;
  2827. DWORD Err;
  2828. //
  2829. // Retrieve the current device install parameters, in preparation for modifying them to
  2830. // target driver search at a particular INF.
  2831. //
  2832. ZeroMemory(&DeviceInstallParams, sizeof(DeviceInstallParams));
  2833. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  2834. if(!SetupDiGetDeviceInstallParams(hDevInfo, pLocalData->DrvInfo.pDevInfoData, &DeviceInstallParams)) {
  2835. return NULL;
  2836. }
  2837. SetupDiDestroyDriverInfoList(hDevInfo,
  2838. NULL,
  2839. SPDIT_CLASSDRIVER);
  2840. // Set the path of the INF
  2841. lstrcpy( DeviceInstallParams.DriverPath, pszSource );
  2842. //
  2843. // set the flag that indicates DriverPath represents a single INF to be searched (and
  2844. // not a directory path). Then store the parameters back to the device information element.
  2845. //
  2846. // DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
  2847. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
  2848. if(!SetupDiSetDeviceInstallParams(hDevInfo, pLocalData->DrvInfo.pDevInfoData, &DeviceInstallParams))
  2849. {
  2850. Err = GetLastError();
  2851. goto clean0;
  2852. }
  2853. //
  2854. // Now build a class driver list from this INF.
  2855. //
  2856. if(!SetupDiBuildDriverInfoList(hDevInfo, pLocalData->DrvInfo.pDevInfoData, SPDIT_CLASSDRIVER))
  2857. {
  2858. Err = GetLastError();
  2859. goto clean0;
  2860. }
  2861. //
  2862. // OK, now select the driver node from that INF that was used to install this device.
  2863. // The three parameters that uniquely identify a driver node are INF Provider,
  2864. // Device Manufacturer, and Device Description. Retrieve these three pieces of information
  2865. // in preparation for selecting the proper driver node in the class list we just built.
  2866. //
  2867. ZeroMemory(&DriverInfoData, sizeof(DriverInfoData));
  2868. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  2869. DriverInfoData.DriverType = SPDIT_CLASSDRIVER;
  2870. DriverInfoData.Reserved = 0; // Search for the driver matching the specified criteria and
  2871. // select it if found.
  2872. // Fill in the Model & Mfg from original INF
  2873. lstrcpy( DriverInfoData.Description, pLocalData->DrvInfo.pszModelName );
  2874. lstrcpy( DriverInfoData.MfgName, pLocalData->DrvInfo.pszManufacturer );
  2875. // Enum One driver entry to get the INF provider
  2876. ZeroMemory(&TempDriverInfoData, sizeof(TempDriverInfoData));
  2877. TempDriverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
  2878. DriverInfoData.DriverType = SPDIT_CLASSDRIVER;
  2879. if (!SetupDiEnumDriverInfo (hDevInfo, NULL, SPDIT_CLASSDRIVER, 0, &TempDriverInfoData))
  2880. {
  2881. Err = GetLastError();
  2882. goto clean0;
  2883. }
  2884. lstrcpy( DriverInfoData.ProviderName, TempDriverInfoData.ProviderName );
  2885. if(!SetupDiSetSelectedDriver(hDevInfo, pLocalData->DrvInfo.pDevInfoData, &DriverInfoData))
  2886. {
  2887. Err = GetLastError();
  2888. goto clean0;
  2889. }
  2890. //
  2891. // At this point, we've successfully selected the currently installed driver for the specified
  2892. // device information element.
  2893. //
  2894. // Now build the new LocalData
  2895. //
  2896. pNewLocalData = BuildInternalData(hDevInfo, NULL);
  2897. if ( pNewLocalData )
  2898. {
  2899. if ( !ParseInf(hDevInfo, pNewLocalData, MyPlatform, NULL, 0) )
  2900. {
  2901. Err = GetLastError();
  2902. DestroyLocalData( pNewLocalData );
  2903. pNewLocalData = NULL;
  2904. }
  2905. else
  2906. {
  2907. SELECTED_DRV_INFO TempDrvInfo;
  2908. TempDrvInfo.pszInfName = AllocStr( pNewLocalData->DrvInfo.pszInfName );
  2909. TempDrvInfo.pszDriverSection = AllocStr( pNewLocalData->DrvInfo.pszDriverSection );
  2910. TempDrvInfo.pszModelName = AllocStr( pNewLocalData->DrvInfo.pszModelName );
  2911. TempDrvInfo.pszManufacturer = AllocStr( pNewLocalData->DrvInfo.pszManufacturer );
  2912. TempDrvInfo.pszHardwareID = AllocStr( pNewLocalData->DrvInfo.pszHardwareID );
  2913. TempDrvInfo.pszOEMUrl = AllocStr( pNewLocalData->DrvInfo.pszOEMUrl );
  2914. // Check that all strings were allocated
  2915. if ( !TempDrvInfo.pszInfName ||
  2916. !TempDrvInfo.pszDriverSection ||
  2917. !TempDrvInfo.pszModelName ||
  2918. !TempDrvInfo.pszManufacturer ||
  2919. !TempDrvInfo.pszHardwareID ||
  2920. !TempDrvInfo.pszOEMUrl )
  2921. {
  2922. // Free up all that worked
  2923. LocalFreeMem( TempDrvInfo.pszInfName );
  2924. LocalFreeMem( TempDrvInfo.pszDriverSection );
  2925. LocalFreeMem( TempDrvInfo.pszModelName );
  2926. LocalFreeMem( TempDrvInfo.pszManufacturer );
  2927. LocalFreeMem( TempDrvInfo.pszHardwareID );
  2928. LocalFreeMem( TempDrvInfo.pszOEMUrl );
  2929. }
  2930. else
  2931. {
  2932. // Free the DrvInfo pointers & refill from new local data
  2933. LocalFreeMem( pLocalData->DrvInfo.pszInfName );
  2934. LocalFreeMem( pLocalData->DrvInfo.pszDriverSection );
  2935. LocalFreeMem( pLocalData->DrvInfo.pszModelName );
  2936. LocalFreeMem( pLocalData->DrvInfo.pszManufacturer );
  2937. LocalFreeMem( pLocalData->DrvInfo.pszHardwareID );
  2938. LocalFreeMem( pLocalData->DrvInfo.pszOEMUrl );
  2939. pLocalData->DrvInfo.pszInfName = TempDrvInfo.pszInfName;
  2940. pLocalData->DrvInfo.pszDriverSection = TempDrvInfo.pszDriverSection;
  2941. pLocalData->DrvInfo.pszModelName = TempDrvInfo.pszModelName;
  2942. pLocalData->DrvInfo.pszManufacturer = TempDrvInfo.pszManufacturer;
  2943. pLocalData->DrvInfo.pszHardwareID = TempDrvInfo.pszHardwareID;
  2944. pLocalData->DrvInfo.pszOEMUrl = TempDrvInfo.pszOEMUrl;
  2945. }
  2946. Err = NO_ERROR;
  2947. }
  2948. }
  2949. else
  2950. Err = GetLastError();
  2951. clean0:
  2952. SetLastError(Err);
  2953. return pNewLocalData;
  2954. }
  2955. BOOL
  2956. SetupSkipDir(
  2957. IN PLATFORM platform,
  2958. IN LPCTSTR pszServerName
  2959. )
  2960. {
  2961. BOOL bRet = FALSE;
  2962. TCHAR szDir[MAX_PATH];
  2963. TCHAR szMSecs[10];
  2964. SYSTEMTIME SysTime;
  2965. DWORD dwNeeded = ( MAX_PATH * sizeof( TCHAR ) );
  2966. EnterCriticalSection(&SkipCritSect);
  2967. // We already have a skip dir created
  2968. if ( !gpszSkipDir )
  2969. {
  2970. // Get a location for a Temp Path
  2971. if ( !GetPrinterDriverDirectory((LPTSTR)pszServerName, PlatformEnv[platform].pszName,
  2972. 1, (LPBYTE) szDir, dwNeeded, &dwNeeded) )
  2973. goto Cleanup;
  2974. if ( dwNeeded == 0)
  2975. goto Cleanup;
  2976. // Add on the Skip Prefix
  2977. lstrcat( szDir, SKIP_DIR );
  2978. // Get System Time
  2979. GetSystemTime( &SysTime );
  2980. wsprintf( szMSecs, TEXT("%04X"), SysTime.wMilliseconds );
  2981. lstrcat( szDir, szMSecs );
  2982. gpszSkipDir = AllocStr( szDir );
  2983. if (!gpszSkipDir )
  2984. goto Cleanup;
  2985. if (!CreateDirectory( gpszSkipDir, NULL ) )
  2986. goto Cleanup;
  2987. }
  2988. bRet = TRUE;
  2989. Cleanup:
  2990. if (!bRet)
  2991. {
  2992. if (gpszSkipDir)
  2993. {
  2994. LocalFreeMem( gpszSkipDir );
  2995. gpszSkipDir = NULL;
  2996. }
  2997. }
  2998. LeaveCriticalSection(&SkipCritSect);
  2999. return bRet;
  3000. }
  3001. void
  3002. CleanupSkipDir(
  3003. VOID
  3004. )
  3005. {
  3006. // We already have a skip dir created
  3007. if ( gpszSkipDir )
  3008. {
  3009. RemoveDirectory( gpszSkipDir );
  3010. LocalFreeMem( gpszSkipDir );
  3011. }
  3012. DeleteCriticalSection(&SkipCritSect);
  3013. }
  3014. BOOL
  3015. IsLocalAdmin(BOOL *pbAdmin)
  3016. /*++
  3017. Routine Description:
  3018. This Routine determines if the user is a local admin.
  3019. Parameters:
  3020. pbAdmin - Return Value, TRUE for local admin.
  3021. Return Value:
  3022. TRUE - Function succeded (return value is valid).
  3023. --*/ {
  3024. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  3025. BOOL bRet = FALSE;
  3026. PSID pSIDAdmin = NULL;
  3027. ASSERT( pbAdmin != NULL ); // Called locally
  3028. *pbAdmin = FALSE;
  3029. if (!AllocateAndInitializeSid( &SIDAuth, 2,
  3030. SECURITY_BUILTIN_DOMAIN_RID,
  3031. DOMAIN_ALIAS_RID_ADMINS,
  3032. 0, 0, 0, 0, 0, 0,
  3033. &pSIDAdmin) )
  3034. goto Cleanup;
  3035. if (!CheckTokenMembership( NULL,
  3036. pSIDAdmin,
  3037. pbAdmin ) )
  3038. goto Cleanup;
  3039. bRet = TRUE;
  3040. Cleanup:
  3041. if (pSIDAdmin != NULL) {
  3042. FreeSid( pSIDAdmin );
  3043. }
  3044. return bRet;
  3045. }
  3046. BOOL
  3047. PruneInvalidFilesIfNotAdmin(
  3048. IN HWND hWnd,
  3049. IN OUT HSPFILEQ CopyQueue
  3050. )
  3051. /*++
  3052. Routine Description:
  3053. This routine checks whether you have administrator privileges, if you do, then
  3054. it does nothing and returns. If you do not, it scans the file queue for files
  3055. that are already present and signed and prunes them from the queue. The commit
  3056. will not allow mixing signed and unsigned files.
  3057. Note: We do this because if you are a power-user the call to MoveFileEx fails inside
  3058. SetupCommitFileQueue, this happens if the existing file cannot be overwritten. We
  3059. could improve this routine by checking if a file is actually in use before pruning
  3060. it.
  3061. Parameters:
  3062. CopyQueue - The copy queue to scan.
  3063. Return Value:
  3064. TRUE - Either you were an administrator and no action was taken, or
  3065. you were not and the FileQueue was successfully pruned.
  3066. FALSE - The operation failed.
  3067. --*/ {
  3068. BOOL bLocalAdmin;
  3069. BOOL bRet = FALSE;
  3070. DWORD dwScanQueueResult;
  3071. if (!IsLocalAdmin( &bLocalAdmin) )
  3072. goto Cleanup;
  3073. if (bLocalAdmin) {
  3074. bRet = TRUE;
  3075. goto Cleanup;
  3076. }
  3077. if (!SetupScanFileQueue( CopyQueue,
  3078. SPQ_SCAN_FILE_PRESENCE | SPQ_SCAN_PRUNE_COPY_QUEUE,
  3079. hWnd ,
  3080. NULL ,
  3081. NULL ,
  3082. &dwScanQueueResult ) )
  3083. goto Cleanup;
  3084. bRet = TRUE;
  3085. Cleanup:
  3086. return bRet;
  3087. }
  3088. BOOL
  3089. AddDriverCatalogIfNotAdmin(
  3090. IN PCWSTR pszServer,
  3091. IN HANDLE hDriverSigningInfo,
  3092. IN PCWSTR pszInfPath,
  3093. IN PCWSTR pszSrcLoc,
  3094. IN DWORD dwMediaType,
  3095. IN DWORD dwCopyStyle
  3096. )
  3097. /*++
  3098. Routine Description:
  3099. This routine calls AddDriverCatalog for non-admin, aka power user.
  3100. Parameters:
  3101. pszServer - Name of the server
  3102. hDriverSigningInfo - Handle to driver signing info
  3103. Return Value:
  3104. TRUE - Either you are an administrator and no action was taken,
  3105. or you are not and the catalog was successfully added
  3106. FALSE - The operation failed. Call GetLastError() to get
  3107. detailed error information
  3108. --*/ {
  3109. BOOL bRet = FALSE;
  3110. BOOL bLocalAdmin = TRUE;
  3111. HANDLE hPrinter = NULL;
  3112. PRINTER_DEFAULTS PrinterDefaults = {0};
  3113. DRIVER_INFCAT_INFO_1 DrvInfCatInfo1 = {0};
  3114. DRIVER_INFCAT_INFO_2 DrvInfCatInfo2 = {0};
  3115. PCWSTR pszCatPath = NULL;
  3116. if (!hDriverSigningInfo ||
  3117. !DrvSigningIsLocalAdmin(hDriverSigningInfo, &bLocalAdmin) ||
  3118. !GetCatalogFile(hDriverSigningInfo, &pszCatPath))
  3119. {
  3120. goto Cleanup;
  3121. }
  3122. //
  3123. // If there is no Cat file or we are local admin, there is nothing to do
  3124. // because for local admin, we use setup api to install the catalog file
  3125. //
  3126. if (!pszCatPath || bLocalAdmin)
  3127. {
  3128. bRet = TRUE;
  3129. goto Cleanup;
  3130. }
  3131. PrinterDefaults.DesiredAccess = SERVER_ALL_ACCESS;
  3132. if (!OpenPrinterW((PWSTR) pszServer, &hPrinter, &PrinterDefaults))
  3133. {
  3134. goto Cleanup;
  3135. }
  3136. //
  3137. // If there is a catalogfile entry in the inf file, we should call private
  3138. // spooler API AddDriverCatalog with level 2 to install the catalog which
  3139. // will install the inf and cat file by calling SetupCopyOEMInf. For inf
  3140. // files that do not have catalogfile entry we shall call AddDriverCatalog
  3141. // with level 1 which will install the catalog by using CryptoAPI
  3142. //
  3143. if (!IsCatInInf(hDriverSigningInfo))
  3144. {
  3145. DrvInfCatInfo1.pszCatPath = pszCatPath;
  3146. if (!AddDriverCatalog(hPrinter, 1, &DrvInfCatInfo1, APDC_USE_ORIGINAL_CAT_NAME))
  3147. {
  3148. goto Cleanup;
  3149. }
  3150. }
  3151. else
  3152. {
  3153. DrvInfCatInfo2.pszCatPath = pszCatPath;
  3154. DrvInfCatInfo2.pszInfPath = pszInfPath;
  3155. DrvInfCatInfo2.pszSrcLoc = pszSrcLoc;
  3156. DrvInfCatInfo2.dwMediaType = dwMediaType;
  3157. DrvInfCatInfo2.dwCopyStyle = dwCopyStyle;
  3158. if (!AddDriverCatalog(hPrinter, 2, &DrvInfCatInfo2, APDC_NONE))
  3159. {
  3160. goto Cleanup;
  3161. }
  3162. }
  3163. bRet = TRUE;
  3164. Cleanup:
  3165. if (hPrinter)
  3166. {
  3167. ClosePrinter(hPrinter);
  3168. }
  3169. return bRet;
  3170. }
  3171. /*
  3172. Function: AddDirectoryTag
  3173. pszDir - TCHAR string to add the two tags to.
  3174. dwSize - size in CHARACTERs of the allocated string buffer.
  3175. Purpose - Takes the string pszDir and tags on "\dwPIDdwTID" on the end of it.
  3176. This is used in the creation of a unique directory to copy the driver
  3177. files for a specific install to.
  3178. */
  3179. BOOL
  3180. AddDirectoryTag(
  3181. IN LPTSTR pszDir,
  3182. IN DWORD dwSize )
  3183. {
  3184. DWORD dwDirSize,
  3185. dwPID,
  3186. dwTID;
  3187. PTCHAR pEnd;
  3188. if( !pszDir || !dwSize || !(dwDirSize = lstrlen( pszDir )) )
  3189. {
  3190. SetLastError( ERROR_INVALID_PARAMETER );
  3191. return FALSE;
  3192. }
  3193. dwPID = GetCurrentProcessId();
  3194. dwTID = GetCurrentThreadId();
  3195. if( (pszDir[dwDirSize-1] != _TEXT('\\')) &&
  3196. (dwDirSize + 1 < dwSize) )
  3197. {
  3198. pszDir[dwDirSize++] = _TEXT('\\');
  3199. pszDir[dwDirSize] = 0;
  3200. }
  3201. pEnd = &pszDir[dwDirSize];
  3202. _sntprintf( pEnd,
  3203. (dwSize-dwDirSize),
  3204. _TEXT("%d%d"),
  3205. dwPID,
  3206. dwTID );
  3207. return TRUE;
  3208. }
  3209. /*
  3210. Function: AddPnpDirTag
  3211. pszDir - TCHAR string to add the tag to.
  3212. dwSize - size in CHARACTERs of the allocated string buffer.
  3213. Purpose - Takes the string pszDir and tags on the pnp-ID on to it.
  3214. This is used in the creation of a unique directory to copy the driver
  3215. files for a specific install to.
  3216. */
  3217. BOOL
  3218. AddPnpDirTag(
  3219. IN LPTSTR pszHardwareId,
  3220. IN OUT LPTSTR pszDir,
  3221. IN DWORD dwSize )
  3222. {
  3223. DWORD dwDirSize;
  3224. PTCHAR pEnd, pPnpId;
  3225. if( !pszHardwareId ||
  3226. !pszDir ||
  3227. !dwSize ||
  3228. !(dwDirSize = lstrlen( pszDir )) ||
  3229. dwSize < dwDirSize + 3 ) // need at least space for backslash, one char + 0 terminator
  3230. {
  3231. SetLastError( ERROR_INVALID_PARAMETER );
  3232. return FALSE;
  3233. }
  3234. if( (pszDir[dwDirSize-1] != _TEXT('\\')))
  3235. {
  3236. pszDir[dwDirSize++] = _TEXT('\\');
  3237. pszDir[dwDirSize] = 0;
  3238. }
  3239. pEnd = &pszDir[dwDirSize];
  3240. //
  3241. // Try to strip off the port enumerator, if applicable. The printer driver
  3242. // should be independent of it.
  3243. //
  3244. if ((pPnpId = _tcsrchr(pszHardwareId, _TEXT('\\'))) == NULL)
  3245. {
  3246. //
  3247. // it doesn't have a port enumerator, so the whole thing is the pnp ID
  3248. //
  3249. pPnpId = pszHardwareId;
  3250. }
  3251. else
  3252. {
  3253. //
  3254. // found one: advance one beyond it if it's not the last character
  3255. // to illustrate LPTENUM\abcd would become \abcd instead of abcd
  3256. //
  3257. if (*(pPnpId+1))
  3258. {
  3259. pPnpId++;
  3260. }
  3261. }
  3262. _tcsncpy(pEnd, pPnpId, dwSize - dwDirSize - 1);
  3263. //
  3264. // make sure the string is zero-terminated, so a pnp-ID that's too long doesn't result
  3265. // in a runaway string.
  3266. //
  3267. pszDir[dwSize - 1] = 0;
  3268. //
  3269. // change all suspicious characters to underscores to avoid problems with / & \ etc.
  3270. // all the distinguishing information should be in the alphanumerical characters
  3271. //
  3272. while (*pEnd)
  3273. {
  3274. if (!_istalnum(*pEnd))
  3275. {
  3276. *pEnd = _TEXT('_');
  3277. }
  3278. pEnd++;
  3279. }
  3280. return TRUE;
  3281. }
  3282. /*
  3283. Function: AddDirToDriverInfo
  3284. pszDir - Directory to append to driver info structure.
  3285. pDriverInfo6 - Pointer to the driver info structure to update.
  3286. Purpose: This function will ensure that there is no directory structure specified in the
  3287. driver info structure yet (so as not to add it multiple times).
  3288. If there isn't then it will update the driver file entries with the full path
  3289. passed in in pszDir.
  3290. */
  3291. BOOL
  3292. AddDirToDriverInfo(
  3293. IN LPTSTR pszDir,
  3294. IN LPDRIVER_INFO_6 pDriverInfo6
  3295. )
  3296. {
  3297. PTCHAR pOldString,
  3298. pCurrentString,
  3299. pNewString;
  3300. DWORD dwLength,
  3301. dwDirLength,
  3302. dwNeeded = 0;
  3303. if( !pszDir || !pDriverInfo6 )
  3304. {
  3305. SetLastError( ERROR_INVALID_PARAMETER );
  3306. return FALSE;
  3307. }
  3308. //
  3309. // If the path is zero length, nothing to do.
  3310. //
  3311. if( !(dwDirLength = lstrlen( pszDir )) )
  3312. return TRUE;
  3313. if( pDriverInfo6->pDriverPath &&
  3314. FileNamePart( pDriverInfo6->pDriverPath ) == pDriverInfo6->pDriverPath )
  3315. {
  3316. pOldString = pDriverInfo6->pDriverPath;
  3317. pDriverInfo6->pDriverPath = AllocAndCatStr2( pszDir, _TEXT("\\"), pOldString );
  3318. LocalFreeMem( pOldString );
  3319. }
  3320. if( pDriverInfo6->pDataFile &&
  3321. FileNamePart( pDriverInfo6->pDataFile ) == pDriverInfo6->pDataFile )
  3322. {
  3323. pOldString = pDriverInfo6->pDataFile;
  3324. pDriverInfo6->pDataFile = AllocAndCatStr2( pszDir, _TEXT("\\"), pOldString );
  3325. LocalFreeMem( pOldString );
  3326. }
  3327. if( pDriverInfo6->pConfigFile &&
  3328. FileNamePart( pDriverInfo6->pConfigFile ) == pDriverInfo6->pConfigFile )
  3329. {
  3330. pOldString = pDriverInfo6->pConfigFile;
  3331. pDriverInfo6->pConfigFile = AllocAndCatStr2( pszDir, _TEXT("\\"), pOldString );
  3332. LocalFreeMem( pOldString );
  3333. }
  3334. if( pDriverInfo6->pHelpFile &&
  3335. FileNamePart( pDriverInfo6->pHelpFile ) == pDriverInfo6->pHelpFile )
  3336. {
  3337. pOldString = pDriverInfo6->pHelpFile;
  3338. pDriverInfo6->pHelpFile = AllocAndCatStr2( pszDir, _TEXT("\\"), pOldString );
  3339. LocalFreeMem( pOldString );
  3340. }
  3341. if( pDriverInfo6->pDependentFiles )
  3342. {
  3343. pCurrentString = pDriverInfo6->pDependentFiles;
  3344. while( *pCurrentString )
  3345. {
  3346. dwLength = lstrlen( pCurrentString );
  3347. if( pCurrentString == FileNamePart( pCurrentString ) )
  3348. {
  3349. //
  3350. // Amount needed - the two lengths + \ + 0
  3351. //
  3352. dwNeeded += dwLength + dwDirLength + 1 + 1;
  3353. }
  3354. else
  3355. {
  3356. //
  3357. // Amount needed - the existing + 0
  3358. //
  3359. dwNeeded += dwLength + 1;
  3360. }
  3361. pCurrentString += dwLength + 1;
  3362. }
  3363. //
  3364. // Increment for the final 0
  3365. //
  3366. dwNeeded++;
  3367. if(pNewString = LocalAllocMem( dwNeeded*sizeof(TCHAR) ))
  3368. {
  3369. pCurrentString = pNewString;
  3370. pOldString = pDriverInfo6->pDependentFiles;
  3371. while( *pOldString )
  3372. {
  3373. if( pOldString == FileNamePart( pOldString ) )
  3374. {
  3375. //
  3376. // Add the directory info.
  3377. //
  3378. lstrcpy( pCurrentString, pszDir );
  3379. pCurrentString += dwDirLength;
  3380. *pCurrentString++ = _TEXT('\\');
  3381. }
  3382. //
  3383. // Add the existing file info.
  3384. //
  3385. lstrcpy( pCurrentString, pOldString );
  3386. pCurrentString += lstrlen( pOldString );
  3387. *pCurrentString++ = 0;
  3388. pOldString += lstrlen( pOldString ) + 1;
  3389. }
  3390. *pCurrentString = 0;
  3391. LocalFreeMem( pDriverInfo6->pDependentFiles );
  3392. pDriverInfo6->pDependentFiles = pNewString;
  3393. }
  3394. }
  3395. return TRUE;
  3396. }
  3397. BOOL
  3398. IsSystemUpgradeInProgress(
  3399. VOID
  3400. )
  3401. /*++
  3402. Routine Description:
  3403. Tells if we are in the middle of system setup
  3404. Arguments:
  3405. None
  3406. Return Value:
  3407. TRUE if system setup in progress, FALSE else
  3408. --*/
  3409. {
  3410. HKEY hKey = NULL;
  3411. DWORD dwValue = 0, dwSize;
  3412. if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3413. cszSystemSetupKey,
  3414. 0,
  3415. KEY_READ,
  3416. &hKey) ) {
  3417. dwSize = sizeof(dwValue);
  3418. if( ERROR_SUCCESS != RegQueryValueEx(hKey, cszSystemUpgradeValue, NULL, NULL,
  3419. (LPBYTE)&dwValue, &dwSize) ) {
  3420. dwValue = 0;
  3421. }
  3422. RegCloseKey(hKey);
  3423. }
  3424. return dwValue == 1;
  3425. }
  3426. BOOL
  3427. IsSystemSetupInProgress(
  3428. VOID
  3429. )
  3430. /*++
  3431. Routine Description:
  3432. Tells if we are in the middle of system setup (GUI mode)
  3433. Arguments:
  3434. None
  3435. Return Value:
  3436. TRUE if system setup in progress, FALSE else
  3437. --*/
  3438. {
  3439. HKEY hKey = NULL;
  3440. DWORD dwValue = 0, dwSize;
  3441. if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3442. cszSystemSetupKey,
  3443. 0,
  3444. KEY_READ,
  3445. &hKey) ) {
  3446. dwSize = sizeof(dwValue);
  3447. if( ERROR_SUCCESS != RegQueryValueEx(hKey, cszSystemSetupInProgress, NULL, NULL,
  3448. (LPBYTE)&dwValue, &dwSize) ) {
  3449. dwValue = 0;
  3450. }
  3451. RegCloseKey(hKey);
  3452. }
  3453. return dwValue == 1;
  3454. }
  3455. /*
  3456. Function: GetMyTempDir
  3457. Purpose: Creates a unique temporary directory off the TEMP directory.
  3458. This gets called by UnCompressCat to create a unique directory to store the cat
  3459. file that is to be expanded in.
  3460. Returns: NULL if failed. The full qualified path to the new directory otherwise.
  3461. Note: The returned string does contain the ending '\'.
  3462. */
  3463. LPTSTR
  3464. GetMyTempDir()
  3465. {
  3466. LPTSTR pszPath = NULL;
  3467. PTCHAR pEnd;
  3468. DWORD dwSize = 0;
  3469. DWORD dwActualSize = 0;
  3470. DWORD dwThreadID = GetCurrentThreadId();
  3471. DWORD dwProcessID = GetCurrentProcessId();
  3472. DWORD dwIDCounter = dwThreadID;
  3473. BOOL bContinue = TRUE;
  3474. dwSize = GetTempPath( 0, pszPath );
  3475. //
  3476. // dwSize + size of the two DWORDs + \ + 0
  3477. //
  3478. dwActualSize = dwSize+MAX_DWORD_LENGTH*2+2;
  3479. if( dwSize &&
  3480. NULL != (pszPath = (LPTSTR)LocalAllocMem(dwActualSize*sizeof(TCHAR))))
  3481. {
  3482. //
  3483. // If this fails, then we assume that someone is playing with the temp path at the instant that
  3484. // we are requesting it - unlikely so just fail (worst effect = probably leads to driver signing warning)
  3485. //
  3486. if( dwSize >= GetTempPath( dwSize, pszPath ))
  3487. {
  3488. dwSize = lstrlen(pszPath);
  3489. pEnd = &pszPath[lstrlen(pszPath)];
  3490. do
  3491. {
  3492. _sntprintf( pEnd, dwActualSize-dwSize, _TEXT("%d%d%s"),
  3493. dwProcessID, dwIDCounter, _TEXT("\\") );
  3494. if(CreateDirectory( pszPath, NULL ) || GetLastError() == ERROR_FILE_EXISTS)
  3495. {
  3496. //
  3497. // We've got a directory, so drop out of loop.
  3498. //
  3499. bContinue = FALSE;
  3500. }
  3501. dwIDCounter++;
  3502. //
  3503. // Will stop loop when we have an unused directory or we loop round on the dwIDCounter
  3504. //
  3505. } while (bContinue && dwIDCounter != dwThreadID);
  3506. if(bContinue)
  3507. {
  3508. LocalFreeMem( pszPath );
  3509. pszPath = NULL;
  3510. }
  3511. }
  3512. else
  3513. {
  3514. LocalFreeMem( pszPath );
  3515. pszPath = NULL;
  3516. }
  3517. }
  3518. return pszPath;
  3519. }
  3520. BOOL
  3521. GetOSVersion(
  3522. IN LPCTSTR pszServerName,
  3523. OUT POSVERSIONINFO pOSVer
  3524. )
  3525. {
  3526. BOOL bRet = FALSE;
  3527. if(pOSVer)
  3528. {
  3529. ZeroMemory(pOSVer,sizeof(OSVERSIONINFO));
  3530. pOSVer->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  3531. if(!pszServerName || !*pszServerName)
  3532. {
  3533. bRet = GetVersionEx(pOSVer);
  3534. }
  3535. else
  3536. {
  3537. HANDLE hServer = NULL;
  3538. DWORD dwNeeded = 0;
  3539. DWORD dwType = REG_BINARY;
  3540. PRINTER_DEFAULTS Defaults = { NULL, NULL, SERVER_READ };
  3541. //
  3542. // Open the server for read access.
  3543. //
  3544. if( OpenPrinter( (LPTSTR) pszServerName, &hServer, &Defaults ) )
  3545. {
  3546. //
  3547. // Get the os version from the remote spooler.
  3548. //
  3549. if( ERROR_SUCCESS == ( GetPrinterData( hServer,
  3550. SPLREG_OS_VERSION,
  3551. &dwType,
  3552. (PBYTE)pOSVer,
  3553. sizeof( OSVERSIONINFO ),
  3554. &dwNeeded ) ) )
  3555. {
  3556. bRet = TRUE;
  3557. }
  3558. else
  3559. {
  3560. //
  3561. // Assume that we're on NT4 as it doesn't support SPLREG_OS_VERSION
  3562. // at it's the only OS that doesn't that could land up in this remote code path.
  3563. //
  3564. ZeroMemory(pOSVer, sizeof(OSVERSIONINFO));
  3565. pOSVer->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  3566. pOSVer->dwMajorVersion = 4;
  3567. pOSVer->dwMinorVersion = 0;
  3568. bRet = TRUE;
  3569. }
  3570. ClosePrinter( hServer );
  3571. }
  3572. }
  3573. }
  3574. return bRet;
  3575. }
  3576. BOOL
  3577. GetOSVersionEx(
  3578. IN LPCTSTR pszServerName,
  3579. OUT POSVERSIONINFOEX pOSVerEx
  3580. )
  3581. {
  3582. BOOL bRet = FALSE;
  3583. if(pOSVerEx)
  3584. {
  3585. ZeroMemory(pOSVerEx,sizeof(OSVERSIONINFOEX));
  3586. pOSVerEx->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  3587. if(!pszServerName || !*pszServerName)
  3588. {
  3589. bRet = GetVersionEx((POSVERSIONINFO) pOSVerEx);
  3590. }
  3591. else
  3592. {
  3593. HANDLE hServer = NULL;
  3594. DWORD dwNeeded = 0;
  3595. DWORD dwType = REG_BINARY;
  3596. PRINTER_DEFAULTS Defaults = { NULL, NULL, SERVER_READ };
  3597. //
  3598. // Open the server for read access.
  3599. //
  3600. if( OpenPrinter( (LPTSTR) pszServerName, &hServer, &Defaults ) )
  3601. {
  3602. //
  3603. // Get the os version from the remote spooler.
  3604. //
  3605. if( ERROR_SUCCESS == ( GetPrinterData( hServer,
  3606. SPLREG_OS_VERSIONEX,
  3607. &dwType,
  3608. (PBYTE)pOSVerEx,
  3609. sizeof( OSVERSIONINFOEX ),
  3610. &dwNeeded ) ) )
  3611. {
  3612. bRet = TRUE;
  3613. }
  3614. else
  3615. {
  3616. //
  3617. // Assume that we're on NT4 as it doesn't support SPLREG_OS_VERSION
  3618. // at it's the only OS that doesn't that could land up in this remote code path.
  3619. //
  3620. ZeroMemory(pOSVerEx, sizeof(OSVERSIONINFOEX));
  3621. pOSVerEx->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  3622. pOSVerEx->dwMajorVersion = 4;
  3623. pOSVerEx->dwMinorVersion = 0;
  3624. bRet = TRUE;
  3625. }
  3626. ClosePrinter( hServer );
  3627. }
  3628. }
  3629. }
  3630. return bRet;
  3631. }
  3632. BOOL
  3633. GetArchitecture(
  3634. IN LPCTSTR pszServerName,
  3635. OUT LPTSTR pszArch,
  3636. IN OUT LPDWORD pcArchSize
  3637. )
  3638. /*++
  3639. Routine Description:
  3640. Obtains the local or remote server's architecture.
  3641. Arguments:
  3642. pszServerName - NULL = local machine.
  3643. pszArch - will hold the machine's architecture.
  3644. cArchSize - IN - size of pszArch in characters.
  3645. OUT - character count that was filled.
  3646. If failure is ERROR_MORE_DATA it will hold the needed character count.
  3647. Return Value:
  3648. TRUE on success.
  3649. --*/
  3650. {
  3651. BOOL bRet = FALSE;
  3652. DWORD dwByteCount = 0;
  3653. DWORD cLen = 0;
  3654. if( !pszArch )
  3655. {
  3656. SetLastError( ERROR_INVALID_PARAMETER );
  3657. }
  3658. else
  3659. {
  3660. *pszArch = 0;
  3661. if( !pszServerName || !*pszServerName )
  3662. {
  3663. cLen = _tcslen(PlatformEnv[MyPlatform].pszName);
  3664. if( cLen <= *pcArchSize )
  3665. {
  3666. _tcsncpy( pszArch, PlatformEnv[MyPlatform].pszName, *pcArchSize );
  3667. bRet = TRUE;
  3668. }
  3669. *pcArchSize = cLen;
  3670. }
  3671. else
  3672. {
  3673. HANDLE hServer = NULL;
  3674. DWORD dwNeeded = 0;
  3675. DWORD dwType = REG_SZ;
  3676. PRINTER_DEFAULTS Defaults = { NULL, NULL, SERVER_READ };
  3677. //
  3678. // Open the server for read access.
  3679. //
  3680. if( OpenPrinter( (LPTSTR) pszServerName, &hServer, &Defaults ) )
  3681. {
  3682. dwByteCount = *pcArchSize * sizeof( TCHAR );
  3683. //
  3684. // Get the os version from the remote spooler.
  3685. //
  3686. if(ERROR_SUCCESS == GetPrinterData(hServer,
  3687. SPLREG_ARCHITECTURE,
  3688. &dwType,
  3689. (PBYTE)pszArch,
  3690. dwByteCount,
  3691. &dwNeeded))
  3692. {
  3693. bRet = TRUE;
  3694. }
  3695. else
  3696. {
  3697. *pszArch = 0;
  3698. }
  3699. *pcArchSize = dwNeeded / sizeof(TCHAR);
  3700. ClosePrinter( hServer );
  3701. }
  3702. }
  3703. }
  3704. return bRet;
  3705. }
  3706. BOOL IsInWow64()
  3707. //
  3708. // find out whether we're running in WOW64
  3709. //
  3710. {
  3711. BOOL bRet = FALSE;
  3712. ULONG_PTR ul;
  3713. NTSTATUS st;
  3714. st = NtQueryInformationProcess(NtCurrentProcess(),
  3715. ProcessWow64Information,
  3716. &ul,
  3717. sizeof(ul),
  3718. NULL);
  3719. if (NT_SUCCESS(st))
  3720. {
  3721. //
  3722. // If this call succeeds, we're on Win2000 or newer machines.
  3723. //
  3724. if (0 != ul)
  3725. {
  3726. //
  3727. // 32-bit code running on Win64
  3728. //
  3729. bRet = TRUE;
  3730. }
  3731. }
  3732. return bRet;
  3733. }
  3734. BOOL
  3735. IsWhistlerOrAbove(
  3736. IN LPCTSTR pszServerName
  3737. )
  3738. /*++
  3739. Routine Description:
  3740. Determines whether the machine identified by ServerName is at least OS version 5.1
  3741. Arguments:
  3742. pszServerName - the name of the remote server. NULL means local machine.
  3743. Return Value:
  3744. TRUE if the remote server is whistler or more recent server or local
  3745. FALSE else
  3746. --*/
  3747. {
  3748. OSVERSIONINFO OsVer = {0};
  3749. BOOL bRet = FALSE;
  3750. if (!pszServerName)
  3751. {
  3752. bRet = TRUE;
  3753. }
  3754. else if (GetOSVersion(pszServerName,&OsVer))
  3755. {
  3756. if( (OsVer.dwMajorVersion > 5) ||
  3757. (OsVer.dwMajorVersion == 5 && OsVer.dwMinorVersion > 0) )
  3758. {
  3759. bRet = TRUE;
  3760. }
  3761. }
  3762. return bRet;
  3763. }
  3764. HRESULT
  3765. IsProductType(
  3766. IN BYTE ProductType,
  3767. IN BYTE Comparison
  3768. )
  3769. /*++
  3770. Routine Description:
  3771. Determines whether the version of the OS is personal, professional or server
  3772. depending on the given ProductType and Comparison
  3773. Arguments:
  3774. ProductType - VER_NT_WORKSTATION or VER_NT_SERVER
  3775. Comaprison - VER_EQUAL, VER_GREATER, VER_GREATER_EQUAL, VER_LESS, VER_LESS_EQUAL
  3776. Return Value:
  3777. S_OK if the OS version if the OS satisfies the given conditions
  3778. S_FALSE else
  3779. --*/
  3780. {
  3781. HRESULT hRetval = S_FALSE;
  3782. OSVERSIONINFOEX OsVerEx = {0};
  3783. ULONGLONG dwlConditionMask = 0;
  3784. OsVerEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  3785. OsVerEx.wProductType = ProductType;
  3786. VER_SET_CONDITION( dwlConditionMask, VER_PRODUCT_TYPE, Comparison );
  3787. if (VerifyVersionInfo(&OsVerEx, VER_PRODUCT_TYPE, dwlConditionMask))
  3788. {
  3789. hRetval = S_OK;
  3790. }
  3791. return hRetval;
  3792. }
  3793. HMODULE LoadLibraryUsingFullPath(
  3794. LPCTSTR lpFileName
  3795. )
  3796. {
  3797. TCHAR szSystemPath[MAX_PATH];
  3798. INT cLength = 0;
  3799. INT cFileNameLength = 0;
  3800. if (!lpFileName || ((cFileNameLength = lstrlen(lpFileName)) == 0))
  3801. {
  3802. return NULL;
  3803. }
  3804. if (GetSystemDirectory(szSystemPath, SIZECHARS(szSystemPath) ) == 0)
  3805. {
  3806. return NULL;
  3807. }
  3808. cLength = lstrlen(szSystemPath);
  3809. if (szSystemPath[cLength-1] != TEXT('\\'))
  3810. {
  3811. if ((cLength + 1) >= MAX_PATH)
  3812. {
  3813. return NULL;
  3814. }
  3815. szSystemPath[cLength] = TEXT('\\');
  3816. szSystemPath[cLength + 1] = TEXT('\0');
  3817. cLength++;
  3818. }
  3819. if ((cLength + cFileNameLength) >= MAX_PATH)
  3820. {
  3821. return NULL;
  3822. }
  3823. lstrcat(szSystemPath, lpFileName);
  3824. return LoadLibrary( szSystemPath );
  3825. }
  3826. BOOL
  3827. IsSpoolerRunning(
  3828. VOID
  3829. )
  3830. {
  3831. HANDLE ph;
  3832. BOOL IsRunning = FALSE;
  3833. if (OpenPrinter(NULL, &ph, NULL))
  3834. {
  3835. IsRunning = TRUE;
  3836. ClosePrinter(ph);
  3837. }
  3838. return IsRunning;
  3839. }
  3840. BOOL
  3841. CheckAndKeepPreviousNames(
  3842. IN LPCTSTR pszServer,
  3843. IN PDRIVER_INFO_6 pDriverInfo6,
  3844. IN PLATFORM platform
  3845. )
  3846. {
  3847. DWORD dwNeeded = 0;
  3848. DWORD dwReturned = 0;
  3849. DWORD dwIndex = 0;
  3850. LPDRIVER_INFO_4 pCurDriverInfo = NULL;
  3851. BOOL bRet = FALSE;
  3852. INT cPrevNamesLength = 0;
  3853. PLATFORM Platform2Enumerate = pszServer ? platform : MyPlatform;
  3854. if (pDriverInfo6 && pDriverInfo6->pName &&
  3855. (*(pDriverInfo6->pName) == TEXT('\0')) )
  3856. {
  3857. goto Cleanup;
  3858. }
  3859. if ( !EnumPrinterDrivers((LPTSTR)pszServer,
  3860. PlatformEnv[Platform2Enumerate].pszName,
  3861. 4,
  3862. (LPBYTE)pCurDriverInfo,
  3863. 0,
  3864. &dwNeeded,
  3865. &dwReturned) )
  3866. {
  3867. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  3868. !(pCurDriverInfo = LocalAllocMem(dwNeeded)) ||
  3869. !EnumPrinterDrivers((LPTSTR)pszServer,
  3870. PlatformEnv[Platform2Enumerate].pszName,
  3871. 4,
  3872. (LPBYTE)pCurDriverInfo,
  3873. dwNeeded,
  3874. &dwNeeded,
  3875. &dwReturned) ||
  3876. (dwReturned <= 0))
  3877. {
  3878. goto Cleanup;
  3879. }
  3880. }
  3881. for (dwIndex = 0; dwIndex < dwReturned; dwIndex++)
  3882. {
  3883. if ((pCurDriverInfo+dwIndex)->pName &&
  3884. (*(pCurDriverInfo+dwIndex)->pName != TEXT('\0')) &&
  3885. !lstrcmp(pDriverInfo6->pName,(pCurDriverInfo+dwIndex)->pName) )
  3886. {
  3887. if ((pCurDriverInfo+dwIndex)->pszzPreviousNames &&
  3888. (*(pCurDriverInfo+dwIndex)->pszzPreviousNames != TEXT('\0')))
  3889. {
  3890. cPrevNamesLength = lstrlen((pCurDriverInfo+dwIndex)->pszzPreviousNames);
  3891. pDriverInfo6->pszzPreviousNames = (LPTSTR)LocalAllocMem( (cPrevNamesLength + 2) * sizeof(TCHAR) );
  3892. if (pDriverInfo6->pszzPreviousNames)
  3893. {
  3894. bRet = TRUE;
  3895. CopyMemory( pDriverInfo6->pszzPreviousNames, (pCurDriverInfo+dwIndex)->pszzPreviousNames, cPrevNamesLength * sizeof(TCHAR) );
  3896. *(pDriverInfo6->pszzPreviousNames + cPrevNamesLength) = TEXT('\0');
  3897. *(pDriverInfo6->pszzPreviousNames + cPrevNamesLength + 1) = TEXT('\0');
  3898. }
  3899. else
  3900. {
  3901. bRet = FALSE;
  3902. }
  3903. goto Cleanup;
  3904. }
  3905. }
  3906. }
  3907. Cleanup:
  3908. if (pCurDriverInfo)
  3909. {
  3910. LocalFreeMem(pCurDriverInfo);
  3911. }
  3912. return bRet;
  3913. }
  3914. BOOL
  3915. IsTheSamePlatform(
  3916. IN LPCTSTR pszServer,
  3917. IN PLATFORM platform
  3918. )
  3919. {
  3920. BOOL bRet = FALSE;
  3921. DWORD dwServerArchSize = 0;
  3922. DWORD dwServerArchSizeInChars = 0;
  3923. TCHAR *pszServerArchitecture = NULL;
  3924. if (!pszServer)
  3925. {
  3926. bRet = TRUE;
  3927. goto Cleanup;
  3928. }
  3929. dwServerArchSizeInChars = lstrlen( PlatformEnv[platform].pszName ) + 1;
  3930. dwServerArchSize = dwServerArchSizeInChars * sizeof(TCHAR);
  3931. pszServerArchitecture = LocalAllocMem(dwServerArchSize);
  3932. if (!pszServerArchitecture ||
  3933. !GetArchitecture(pszServer, pszServerArchitecture, &dwServerArchSizeInChars ))
  3934. {
  3935. bRet = FALSE;
  3936. goto Cleanup;
  3937. }
  3938. bRet = !lstrcmp( pszServerArchitecture, PlatformEnv[platform].pszName );
  3939. Cleanup:
  3940. if (pszServerArchitecture)
  3941. {
  3942. LocalFreeMem( pszServerArchitecture );
  3943. }
  3944. return bRet;
  3945. }
  3946. LPTSTR
  3947. GetArchitectureName(
  3948. IN LPCTSTR pszServerName
  3949. )
  3950. {
  3951. LPTSTR pszArch = NULL;
  3952. DWORD dwArchSize = 80;
  3953. if (pszServerName && (*pszServerName == TEXT('\0')))
  3954. {
  3955. SetLastError(ERROR_INVALID_PARAMETER);
  3956. return NULL;
  3957. }
  3958. if (!pszServerName)
  3959. {
  3960. return AllocStr( PlatformEnv[MyPlatform].pszName );
  3961. }
  3962. pszArch = LocalAllocMem( dwArchSize * sizeof(TCHAR));
  3963. if (!pszArch)
  3964. {
  3965. return NULL;
  3966. }
  3967. if (!GetArchitecture( pszServerName, pszArch, &dwArchSize))
  3968. {
  3969. if (GetLastError() == ERROR_MORE_DATA)
  3970. {
  3971. LocalFreeMem( pszArch );
  3972. dwArchSize += 1;
  3973. pszArch = LocalAllocMem( dwArchSize * sizeof(TCHAR) );
  3974. if (!pszArch ||
  3975. !GetArchitecture( pszServerName, pszArch, &dwArchSize))
  3976. {
  3977. return NULL;
  3978. }
  3979. }
  3980. }
  3981. return pszArch;
  3982. }
  3983. /************************************************************************************
  3984. ** End of File (util.c)
  3985. ************************************************************************************/