Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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