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.

3707 lines
118 KiB

  1. /*++
  2. Copyright (c) 1995-97 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Install.c
  6. Abstract:
  7. File queue functions
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 18-Nov-96
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include <winsprlp.h>
  14. const TCHAR szWebDirPrefix[] = TEXT("\\web\\printers\\");
  15. const TCHAR szNtPrintInf[] = TEXT("inf\\ntprint.inf");
  16. //
  17. // File queue flags, and structure
  18. //
  19. #define CALLBACK_MEDIA_CHECKED 0x01
  20. #define CALLBACK_SOURCE_SET 0x02
  21. #define CALLBACK_PATH_MODIFIED 0x04
  22. typedef struct _FILE_QUEUE_CONTEXT {
  23. HWND hwnd;
  24. PVOID QueueContext;
  25. LPCTSTR pszSource;
  26. BOOL dwCallbackFlags;
  27. DWORD dwInstallFlags;
  28. LPCTSTR pszFileSrcPath;
  29. TCHAR szInfPath[MAX_PATH];
  30. PLATFORM platform;
  31. DWORD dwVersion;
  32. } FILE_QUEUE_CONTEXT, *PFILE_QUEUE_CONTEXT;
  33. BOOL
  34. FileExistsOnMedia(
  35. PSOURCE_MEDIA pSourceMedia
  36. )
  37. {
  38. BOOL bRes = FALSE;
  39. TCHAR *pszFile = NULL;
  40. DWORD cchLength = 0;
  41. DWORD cchAdditionalSymbolsLen = 0;
  42. DWORD dwLen1 = 0;
  43. DWORD dwLen2 = 0;
  44. LPTSTR p = NULL;
  45. LPTSTR q = NULL;
  46. if ( !pSourceMedia->SourcePath || !*pSourceMedia->SourcePath ||
  47. !pSourceMedia->SourceFile || !*pSourceMedia->SourceFile )
  48. {
  49. goto Cleanup;
  50. }
  51. cchAdditionalSymbolsLen = lstrlen(TEXT("\\")) + lstrlen(TEXT("_")) + 1;
  52. cchLength = lstrlen(pSourceMedia->SourcePath) + lstrlen(pSourceMedia->SourceFile) +
  53. cchAdditionalSymbolsLen;
  54. if (cchLength == cchAdditionalSymbolsLen)
  55. {
  56. goto Cleanup;
  57. }
  58. //
  59. // First check if file is there on source path
  60. //
  61. pszFile = LocalAllocMem(cchLength * sizeof(TCHAR));
  62. if (!pszFile)
  63. {
  64. goto Cleanup;
  65. }
  66. StringCchCopy(pszFile, cchLength, pSourceMedia->SourcePath);
  67. dwLen1 = lstrlen(pszFile);
  68. if ( *(pszFile + (dwLen1-1)) != TEXT('\\') )
  69. {
  70. *(pszFile + dwLen1) = TEXT('\\');
  71. ++dwLen1;
  72. }
  73. StringCchCopy(pszFile + dwLen1, cchLength - dwLen1, pSourceMedia->SourceFile);
  74. dwLen2 = dwLen1 + lstrlen(pSourceMedia->SourceFile);
  75. bRes = FileExists(pszFile);
  76. if (bRes)
  77. {
  78. goto Cleanup;
  79. }
  80. p = lstrchr(pszFile, TEXT('.'));
  81. q = lstrchr(pszFile, TEXT('\\'));
  82. //
  83. // A dot present in filename?
  84. //
  85. if ( q < p )
  86. {
  87. //
  88. // For files with 0, 1, 2 characters after the dot append underscore.
  89. //
  90. if ( (lstrlen(p) < 4) && (dwLen2 < (cchLength-1)) )
  91. {
  92. *(pszFile + dwLen2) = TEXT('_');
  93. ++dwLen2;
  94. *(pszFile + dwLen2) = TEXT('\0');
  95. }
  96. else
  97. {
  98. //
  99. // If 3+ characters after dot then replace last character with _
  100. // to get the compressed file name
  101. //
  102. *(pszFile + (dwLen2-1)) = TEXT('_');
  103. }
  104. }
  105. else
  106. {
  107. //
  108. // If no dot then replace last character with _ for compressed name
  109. //
  110. *(pszFile + (dwLen2-1)) = TEXT('_');
  111. }
  112. //
  113. // Does the compressed file exist on source path?
  114. //
  115. bRes = FileExists(pszFile);
  116. if (bRes)
  117. {
  118. goto Cleanup;
  119. }
  120. //
  121. // Check for the file in compressed form with $ as the character
  122. //
  123. *(pszFile + (dwLen2-1)) = TEXT('$');
  124. bRes = FileExists(pszFile);
  125. if (bRes)
  126. {
  127. goto Cleanup;
  128. }
  129. if ( !pSourceMedia->Tagfile || !*pSourceMedia->Tagfile )
  130. {
  131. goto Cleanup;
  132. }
  133. //
  134. // Look for tag file
  135. //
  136. StringCchCopy(pszFile + dwLen1, cchLength - dwLen1, pSourceMedia->Tagfile);
  137. bRes = FileExists(pszFile);
  138. Cleanup:
  139. LocalFreeMem(pszFile);
  140. return bRes;
  141. }
  142. UINT
  143. MyQueueCallback(
  144. IN PVOID QueueContext,
  145. IN UINT Notification,
  146. IN UINT_PTR Param1,
  147. IN UINT_PTR Param2
  148. )
  149. {
  150. PFILE_QUEUE_CONTEXT pFileQContext=(PFILE_QUEUE_CONTEXT)QueueContext;
  151. PSOURCE_MEDIA pSourceMedia;
  152. LPTSTR pszPathOut;
  153. PFILEPATHS pFilePaths;
  154. switch (Notification) {
  155. case SPFILENOTIFY_NEEDMEDIA:
  156. pSourceMedia = (PSOURCE_MEDIA)Param1;
  157. pszPathOut = (LPTSTR)Param2;
  158. //
  159. // If pszSource is specified then we have a flat share where
  160. // all the files are available. Setup is looking for the file
  161. // in the sub-directory (ex. ..\i386) based on the layout info.
  162. // We need to tell setup to look in the root directory
  163. //
  164. if ( !(pFileQContext->dwCallbackFlags & CALLBACK_SOURCE_SET) &&
  165. pFileQContext->pszSource &&
  166. lstrcmpi(pFileQContext->pszSource,
  167. pSourceMedia->SourcePath) ) {
  168. StringCchCopy(pszPathOut, MAX_PATH, pFileQContext->pszSource);
  169. pFileQContext->dwCallbackFlags |= CALLBACK_SOURCE_SET;
  170. return FILEOP_NEWPATH;
  171. }
  172. //
  173. // If DRVINST_PROMPTLESS is set then we can't allow prompt
  174. //
  175. if ( pFileQContext->dwInstallFlags & DRVINST_PROMPTLESS ) {
  176. if ( !(pFileQContext->dwCallbackFlags & CALLBACK_MEDIA_CHECKED) ) {
  177. pFileQContext->dwCallbackFlags |= CALLBACK_MEDIA_CHECKED;
  178. if ( FileExistsOnMedia(pSourceMedia) )
  179. return FILEOP_DOIT;
  180. }
  181. return FILEOP_ABORT;
  182. }
  183. //
  184. // If we do a non-native platform install and the user points
  185. // to a server CD, the inf will specify a subdir \i386 which is
  186. // correct on an installed machine but not on a CD. Remove that dir
  187. // and try again.
  188. //
  189. if ( (pFileQContext->dwInstallFlags & DRVINST_ALT_PLATFORM_INSTALL) &&
  190. !(pFileQContext->dwCallbackFlags & CALLBACK_PATH_MODIFIED))
  191. {
  192. LPSTR pCur;
  193. size_t Pos, Len, OverrideLen;
  194. //
  195. // for NT4 installations we have possibly expanded the INF
  196. // from a server CD. Point there if that's the case
  197. //
  198. if ((pFileQContext->dwVersion == 2) &&
  199. (pFileQContext->pszFileSrcPath))
  200. {
  201. Len = _tcslen(pFileQContext->szInfPath);
  202. if (_tcsnicmp(pSourceMedia->SourcePath,
  203. pFileQContext->szInfPath, Len) == 0)
  204. {
  205. StringCchCopy(pszPathOut, MAX_PATH, pFileQContext->pszFileSrcPath);
  206. pFileQContext->dwCallbackFlags |= CALLBACK_PATH_MODIFIED;
  207. return FILEOP_NEWPATH;
  208. }
  209. }
  210. //
  211. // Find the spot where the platform ID begins
  212. //
  213. Pos = Len = _tcslen(pFileQContext->szInfPath);
  214. //
  215. // sanity check
  216. //
  217. if (_tcslen(pSourceMedia->SourcePath) <= Len)
  218. goto Default;
  219. if (pSourceMedia->SourcePath[Len] == _T('\\'))
  220. {
  221. Pos++;
  222. }
  223. OverrideLen = _tcslen(PlatformOverride[pFileQContext->platform].pszName);
  224. if (_tcsnicmp(pSourceMedia->SourcePath,
  225. pFileQContext->szInfPath, Len) == 0 &&
  226. _tcsnicmp(&(pSourceMedia->SourcePath[Pos]),
  227. PlatformOverride[pFileQContext->platform].pszName,
  228. OverrideLen) == 0)
  229. {
  230. StringCchCopy(pszPathOut, MAX_PATH, pFileQContext->szInfPath);
  231. pFileQContext->dwCallbackFlags |= CALLBACK_PATH_MODIFIED;
  232. return FILEOP_NEWPATH;
  233. }
  234. }
  235. goto Default;
  236. case SPFILENOTIFY_STARTCOPY:
  237. pFilePaths = (PFILEPATHS)Param1;
  238. if ( gpszSkipDir &&
  239. !lstrncmpi(gpszSkipDir, pFilePaths->Target, lstrlen(gpszSkipDir)) )
  240. return FILEOP_SKIP;
  241. goto Default;
  242. case SPFILENOTIFY_ENDCOPY:
  243. // Here we set the bMediaChecked flag to FALSE, this is because some OEM drivers
  244. // have more than one media, so we assume NEEDMEDIA,STARTCOPY,ENDCOPY,NEEDMEDIA
  245. // So if we reset the NEEDMEDIA flag after the ENDCOPY, we are OK
  246. //
  247. // Clear the per file flags
  248. //
  249. pFileQContext->dwCallbackFlags &= ~(CALLBACK_MEDIA_CHECKED |
  250. CALLBACK_SOURCE_SET |
  251. CALLBACK_PATH_MODIFIED);
  252. goto Default;
  253. case SPFILENOTIFY_COPYERROR:
  254. pFilePaths = (PFILEPATHS)Param1;
  255. // If there is a copy error happens in webpnp, we force it retry
  256. // the orginal flat directory
  257. if ( pFileQContext->dwInstallFlags & DRVINST_WEBPNP) {
  258. pszPathOut = (LPTSTR)Param2;
  259. // We need to make sure the path used in the copy operation is not as same as we're going
  260. // to replace, otherwise, it will go to indefinite loop.
  261. //
  262. if (lstrncmpi(pFileQContext->pszSource, pFilePaths->Source, lstrlen(pFileQContext->pszSource)) ||
  263. lstrchr (pFilePaths->Source + lstrlen(pFileQContext->pszSource) + 1, TEXT ('\\'))) {
  264. if(SUCCEEDED(StringCchCopy(pszPathOut, MAX_PATH, pFileQContext->pszSource)))
  265. {
  266. return FILEOP_NEWPATH;
  267. }
  268. }
  269. if ( pFileQContext->dwInstallFlags & DRVINST_PROMPTLESS )
  270. {
  271. return FILEOP_ABORT;
  272. }
  273. }
  274. goto Default;
  275. }
  276. Default:
  277. return SetupDefaultQueueCallback(pFileQContext->QueueContext,
  278. Notification,
  279. Param1,
  280. Param2);
  281. }
  282. VOID
  283. CheckAndEnqueueOneFile(
  284. IN LPCTSTR pszFileName,
  285. IN LPCTSTR pszzDependentFiles, OPTIONAL
  286. IN HSPFILEQ CopyQueue,
  287. IN LPCTSTR pszSourcePath,
  288. IN LPCTSTR pszTargetPath,
  289. IN LPCTSTR pszDiskName, OPTIONAL
  290. IN OUT LPBOOL lpFail
  291. )
  292. /*++
  293. Routine Description:
  294. Ensure that a file is enqueue only once for copying. To do so we check
  295. if the given file name also appears in the list of dependent files and
  296. enqueue it only if it does not.
  297. Arguments:
  298. pszFileName : File name to be checked and enqueued
  299. pszzDependentFiles : Dependent files (multi-sz) list
  300. CopyQueue : CopyQueue used to enqueue files
  301. pszSourcePath : Source directory to look for the files
  302. pszTargetPath : Target directory to copy the files to
  303. pszDiskName : Title of the disk where files are
  304. lpBool : Will be set to TRUE on error
  305. Return Value:
  306. Nothing
  307. --*/
  308. {
  309. LPCTSTR psz;
  310. if ( *lpFail )
  311. return;
  312. //
  313. // If the file also appears as a dependent file do not enqueue it
  314. //
  315. if ( pszzDependentFiles ) {
  316. for ( psz = pszzDependentFiles ; *psz ; psz += lstrlen(psz) + 1 )
  317. if ( !lstrcmpi(pszFileName, psz) )
  318. return;
  319. }
  320. *lpFail = !SetupQueueCopy(
  321. CopyQueue,
  322. pszSourcePath,
  323. NULL, // Path relative to source
  324. pszFileName,
  325. pszDiskName, // "Supplies a description of the source media to be used during disk prompts"
  326. NULL, // Source Tag file
  327. pszTargetPath,
  328. NULL, // Target file name
  329. 0); // Copy style flags
  330. }
  331. BOOL
  332. CopyPrinterDriverFiles(
  333. IN LPDRIVER_INFO_6 pDriverInfo6,
  334. IN LPCTSTR pszInfName,
  335. IN LPCTSTR pszSourcePath,
  336. IN LPCTSTR pszDiskName,
  337. IN LPCTSTR pszTargetPath,
  338. IN HWND hwnd,
  339. IN DWORD dwInstallFlags,
  340. IN BOOL bForgetSource
  341. )
  342. /*++
  343. Routine Description:
  344. Copy printer driver files to a specified directory using SetupQueue APIs
  345. Arguments:
  346. pDriverInfo6 : Points to a valid SELECTED_DRV_INFO
  347. szTargetPath : Target directory to copy to
  348. szSourcePath : Source directory to look for the files, if none is
  349. specified will use the one from prev. operation
  350. pszDiskName : Title of the disk where files are
  351. hwnd : Windows handle of current top-level window
  352. bForgetSource : TRUE if the path where driver files were copied from
  353. should not be remembered for future use
  354. Return Value:
  355. TRUE on succes
  356. FALSE else, use GetLastError() to get the error code
  357. --*/
  358. {
  359. HSPFILEQ CopyQueue;
  360. BOOL bFail = FALSE;
  361. DWORD dwOldCount, dwNewCount, dwIndex;
  362. LPTSTR psz, *List = NULL;
  363. FILE_QUEUE_CONTEXT FileQContext;
  364. //
  365. // Valid DriverInfo6
  366. //
  367. if ( !pDriverInfo6 ||
  368. !pDriverInfo6->pDriverPath ||
  369. !pDriverInfo6->pDataFile ||
  370. !pDriverInfo6->pConfigFile )
  371. return FALSE;
  372. //
  373. // If no additions should be made to the source list findout the count
  374. //
  375. if ( bForgetSource ) {
  376. dwOldCount = 0;
  377. if ( !SetupQuerySourceList(SRCLIST_USER | SRCLIST_SYSTEM,
  378. &List, &dwOldCount) ) {
  379. return FALSE;
  380. }
  381. SetupFreeSourceList(&List, dwOldCount);
  382. }
  383. //
  384. // Create a setup file copy queue and initialize setup queue callback
  385. //
  386. ZeroMemory(&FileQContext, sizeof(FileQContext));
  387. FileQContext.hwnd = hwnd;
  388. FileQContext.pszSource = NULL;
  389. FileQContext.dwInstallFlags = dwInstallFlags;
  390. if ( dwInstallFlags & DRVINST_PROGRESSLESS ) {
  391. FileQContext.QueueContext = SetupInitDefaultQueueCallbackEx(
  392. hwnd,
  393. INVALID_HANDLE_VALUE,
  394. 0,
  395. 0,
  396. NULL);
  397. } else {
  398. FileQContext.QueueContext = SetupInitDefaultQueueCallback(hwnd);
  399. }
  400. CopyQueue = SetupOpenFileQueue();
  401. if ( CopyQueue == INVALID_HANDLE_VALUE || !FileQContext.QueueContext )
  402. goto Cleanup;
  403. CheckAndEnqueueOneFile(pDriverInfo6->pDriverPath,
  404. pDriverInfo6->pDependentFiles,
  405. CopyQueue,
  406. pszSourcePath,
  407. pszTargetPath,
  408. pszDiskName,
  409. &bFail);
  410. CheckAndEnqueueOneFile(pDriverInfo6->pDataFile,
  411. pDriverInfo6->pDependentFiles,
  412. CopyQueue,
  413. pszSourcePath,
  414. pszTargetPath,
  415. pszDiskName,
  416. &bFail);
  417. CheckAndEnqueueOneFile(pDriverInfo6->pConfigFile,
  418. pDriverInfo6->pDependentFiles,
  419. CopyQueue,
  420. pszSourcePath,
  421. pszTargetPath,
  422. pszDiskName,
  423. &bFail);
  424. if ( pDriverInfo6->pHelpFile && *pDriverInfo6->pHelpFile )
  425. CheckAndEnqueueOneFile(pDriverInfo6->pHelpFile,
  426. pDriverInfo6->pDependentFiles,
  427. CopyQueue,
  428. pszSourcePath,
  429. pszTargetPath,
  430. pszDiskName,
  431. &bFail);
  432. //
  433. // Add each file in the dependent files field to the setup queue
  434. //
  435. if ( pDriverInfo6->pDependentFiles ) {
  436. for ( psz = pDriverInfo6->pDependentFiles ;
  437. *psz ;
  438. psz += lstrlen(psz) + 1 )
  439. CheckAndEnqueueOneFile(psz,
  440. NULL,
  441. CopyQueue,
  442. pszSourcePath,
  443. pszTargetPath,
  444. pszDiskName,
  445. &bFail);
  446. }
  447. if ( bFail )
  448. goto Cleanup;
  449. {
  450. // Before adding files to the File Queue set the correct Platform/Version
  451. // info for Driver Signing
  452. // Setup the structure for SETUPAPI
  453. SP_ALTPLATFORM_INFO AltPlat_Info;
  454. HINF hInf;
  455. TCHAR CatalogName[ MAX_PATH ];
  456. LPTSTR pszCatalogFile = NULL;
  457. AltPlat_Info.cbSize = sizeof(SP_ALTPLATFORM_INFO);
  458. AltPlat_Info.Platform = VER_PLATFORM_WIN32_WINDOWS;
  459. AltPlat_Info.MajorVersion = 4;
  460. AltPlat_Info.MinorVersion = 0;
  461. AltPlat_Info.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  462. AltPlat_Info.Reserved = 0;
  463. AltPlat_Info.FirstValidatedMajorVersion = AltPlat_Info.MajorVersion;
  464. AltPlat_Info.FirstValidatedMinorVersion = AltPlat_Info.MinorVersion;
  465. if ( CheckForCatalogFileInInf(pszInfName, &pszCatalogFile) && pszCatalogFile )
  466. {
  467. if ( (lstrlen(pszSourcePath)+lstrlen(pszCatalogFile)+2) < MAX_PATH )
  468. {
  469. StringCchCopy(CatalogName, COUNTOF(CatalogName), pszSourcePath);
  470. StringCchCat( CatalogName, COUNTOF(CatalogName), TEXT("\\"));
  471. StringCchCat( CatalogName, COUNTOF(CatalogName), pszCatalogFile );
  472. }
  473. else
  474. {
  475. bFail = TRUE;
  476. }
  477. LocalFreeMem( pszCatalogFile );
  478. pszCatalogFile = CatalogName;
  479. }
  480. if (bFail)
  481. goto Cleanup;
  482. // Now call the Setup API to change the parms on the FileQueue
  483. bFail = !SetupSetFileQueueAlternatePlatform( CopyQueue, &AltPlat_Info, pszCatalogFile );
  484. }
  485. if ( bFail )
  486. goto Cleanup;
  487. bFail = !SetupCommitFileQueue(hwnd,
  488. CopyQueue,
  489. MyQueueCallback,
  490. &FileQContext);
  491. //
  492. // If bForegetSource is set fix source list
  493. //
  494. if ( bForgetSource &&
  495. SetupQuerySourceList(SRCLIST_USER | SRCLIST_SYSTEM,
  496. &List, &dwNewCount) ) {
  497. dwOldCount = dwNewCount - dwOldCount;
  498. if ( dwOldCount < dwNewCount )
  499. for ( dwIndex = 0 ; dwIndex < dwOldCount ; ++dwIndex ) {
  500. SetupRemoveFromSourceList(SRCLIST_SYSIFADMIN,
  501. List[dwIndex]);
  502. }
  503. SetupFreeSourceList(&List, dwNewCount);
  504. }
  505. Cleanup:
  506. if ( CopyQueue != INVALID_HANDLE_VALUE )
  507. SetupCloseFileQueue(CopyQueue);
  508. if ( FileQContext.QueueContext )
  509. SetupTermDefaultQueueCallback(FileQContext.QueueContext);
  510. return !bFail;
  511. }
  512. BOOL
  513. AddPrinterDriverUsingCorrectLevel(
  514. IN LPCTSTR pszServerName,
  515. IN LPDRIVER_INFO_6 pDriverInfo6,
  516. IN DWORD dwAddDrvFlags
  517. )
  518. {
  519. BOOL bReturn;
  520. DWORD dwLevel;
  521. bReturn = AddPrinterDriverEx((LPTSTR)pszServerName,
  522. 6,
  523. (LPBYTE)pDriverInfo6,
  524. dwAddDrvFlags );
  525. for ( dwLevel = 4 ;
  526. !bReturn && GetLastError() == ERROR_INVALID_LEVEL && dwLevel > 1 ;
  527. --dwLevel ) {
  528. //
  529. // Since DRIVER_INFO_2, 3, 4 are subsets of DRIVER_INFO_6 and all fields
  530. // are at the beginning these calls can be made with same buffer
  531. //
  532. bReturn = AddPrinterDriverEx((LPTSTR)pszServerName,
  533. dwLevel,
  534. (LPBYTE)pDriverInfo6,
  535. dwAddDrvFlags);
  536. }
  537. return bReturn;
  538. }
  539. typedef struct _MONITOR_SCAN_INFO {
  540. LPTSTR pszMonitorDll;
  541. LPTSTR pszTargetDir;
  542. BOOL bFound;
  543. } MONITOR_SCAN_INFO, *PMONITOR_SCAN_INFO;
  544. UINT
  545. MonitorCheckCallback(
  546. IN PVOID pContext,
  547. IN UINT Notification,
  548. IN UINT_PTR Param1,
  549. IN UINT_PTR Param2
  550. )
  551. /*++
  552. Routine Description:
  553. This callback routine is to check language monitor dll is getting copied
  554. to system32 directory.
  555. Arguments:
  556. pContext : Gives the MONITOR_SCAN_INFO structure
  557. Notification : Ignored
  558. Param1 : Gives the target file name
  559. Param2 : Ignored
  560. Return Value:
  561. Win32 error code
  562. --*/
  563. {
  564. size_t dwLen;
  565. LPTSTR pszTarget = (LPTSTR)Param1, pszFileName;
  566. PMONITOR_SCAN_INFO pScanInfo = (PMONITOR_SCAN_INFO)pContext;
  567. if ( !pScanInfo->bFound ) {
  568. if ( !(pszFileName = FileNamePart(pszTarget)) )
  569. return ERROR_INVALID_PARAMETER;
  570. if ( !lstrcmpi(pScanInfo->pszMonitorDll, pszFileName) ) {
  571. //
  572. // Length excludes \ (i.e. D:\winnt\system32)
  573. //
  574. dwLen = (size_t)(pszFileName - pszTarget - 1);
  575. if ( !lstrncmpi(pScanInfo->pszTargetDir, pszTarget, dwLen) &&
  576. dwLen == (DWORD) lstrlen(pScanInfo->pszTargetDir) )
  577. pScanInfo->bFound = TRUE;
  578. }
  579. }
  580. return NO_ERROR;
  581. }
  582. BOOL
  583. CheckAndEnqueueMonitorDll(
  584. IN LPCTSTR pszMonitorDll,
  585. IN LPCTSTR pszSource,
  586. IN HSPFILEQ CopyQueue,
  587. IN HINF hInf
  588. )
  589. /*++
  590. Routine Description:
  591. This routine is to check language monitor dll is getting copied to system32
  592. directory. On NT 4.0 we did not list LM as a file to be copied. ntprint.dll
  593. automatically did it. Now we use a DRID for it. But for backward
  594. compatibility this routine is there to get NT 4.0 INFs to work.
  595. Arguments:
  596. pszMonitorDll : Monitor dll to enqueue
  597. pszSource : Source directory to look for files
  598. CopyQueue : File queue
  599. hInf : Printer driver INF file handle
  600. Return Value:
  601. TRUE on success, FALSE else
  602. --*/
  603. {
  604. BOOL bRet = FALSE;
  605. DWORD dwNeeded;
  606. LPTSTR pszPathOnSource = NULL, pszDescription = NULL,
  607. pszTagFile = NULL;
  608. TCHAR szDir[MAX_PATH];
  609. MONITOR_SCAN_INFO ScanInfo;
  610. SP_FILE_COPY_PARAMS FileCopyParams = {0};
  611. if ( !GetSystemDirectory(szDir, SIZECHARS(szDir)) )
  612. goto Cleanup;
  613. ScanInfo.pszMonitorDll = (LPTSTR)pszMonitorDll;
  614. ScanInfo.pszTargetDir = szDir;
  615. ScanInfo.bFound = FALSE;
  616. if ( !SetupScanFileQueue(CopyQueue,
  617. SPQ_SCAN_USE_CALLBACK,
  618. 0,
  619. MonitorCheckCallback,
  620. &ScanInfo,
  621. &dwNeeded) )
  622. goto Cleanup;
  623. if ( !ScanInfo.bFound ) {
  624. pszPathOnSource = (LPTSTR) LocalAllocMem(MAX_PATH * sizeof(TCHAR));
  625. if ( !pszPathOnSource )
  626. goto Cleanup;
  627. //
  628. // This gives which subdirectory to look for. By default in same dir
  629. //
  630. if ( !FindPathOnSource(pszMonitorDll, hInf,
  631. pszPathOnSource, MAX_PATH,
  632. &pszDescription, &pszTagFile) ) {
  633. LocalFreeMem(pszPathOnSource);
  634. pszPathOnSource = NULL;
  635. }
  636. FileCopyParams.cbSize = sizeof( SP_FILE_COPY_PARAMS );
  637. FileCopyParams.QueueHandle = CopyQueue;
  638. FileCopyParams.SourceRootPath = pszSource;
  639. FileCopyParams.SourcePath = pszPathOnSource;
  640. FileCopyParams.SourceFilename = pszMonitorDll;
  641. FileCopyParams.SourceDescription = pszDescription;
  642. FileCopyParams.SourceTagfile = pszTagFile;
  643. FileCopyParams.TargetDirectory = szDir;
  644. FileCopyParams.TargetFilename = NULL;
  645. FileCopyParams.CopyStyle = SP_COPY_NEWER;
  646. FileCopyParams.LayoutInf = hInf;
  647. FileCopyParams.SecurityDescriptor = NULL;
  648. if ( !SetupQueueCopyIndirect(&FileCopyParams) )
  649. {
  650. goto Cleanup;
  651. }
  652. }
  653. bRet = TRUE;
  654. Cleanup:
  655. LocalFreeMem(pszPathOnSource);
  656. LocalFreeMem(pszDescription);
  657. LocalFreeMem(pszTagFile);
  658. return bRet;
  659. }
  660. BOOL
  661. GetWebPageDir(
  662. IN PPSETUP_LOCAL_DATA pLocalData,
  663. OUT TCHAR szDir[MAX_PATH]
  664. )
  665. {
  666. BOOL bRet = FALSE;
  667. DWORD dwLen;
  668. if(!pLocalData->DrvInfo.pszManufacturer || !pLocalData->DrvInfo.pszModelName)
  669. {
  670. goto Done;
  671. }
  672. if ( !GetSystemWindowsDirectory(szDir, MAX_PATH) )
  673. goto Done;
  674. dwLen = lstrlen(szDir) + lstrlen(szWebDirPrefix)
  675. + lstrlen(pLocalData->DrvInfo.pszManufacturer)
  676. + lstrlen(pLocalData->DrvInfo.pszModelName)
  677. + 2;
  678. if ( dwLen >= MAX_PATH ) {
  679. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  680. goto Done;
  681. }
  682. StringCchCat(szDir, MAX_PATH, szWebDirPrefix);
  683. StringCchCat(szDir, MAX_PATH, pLocalData->DrvInfo.pszManufacturer);
  684. StringCchCat(szDir, MAX_PATH, TEXT("\\"));
  685. StringCchCat(szDir, MAX_PATH, pLocalData->DrvInfo.pszModelName);
  686. bRet = TRUE;
  687. Done:
  688. return bRet;
  689. }
  690. BOOL
  691. SetTargetDirectories(
  692. IN PPSETUP_LOCAL_DATA pLocalData,
  693. IN PLATFORM platform,
  694. IN LPCTSTR pszServerName,
  695. IN HINF hInf,
  696. IN DWORD dwInstallFlags
  697. )
  698. /*++
  699. Routine Description:
  700. Set all the target directories listed in the INF file for file copy
  701. operations. Also gets the source directory where we should look for
  702. driver files
  703. Arguments:
  704. hDevInfo : Handle to printer device info list
  705. pLocalData : INF parsing information
  706. platform : Gives the platform
  707. pszSource : Source directory to look for files
  708. CopyQueue : File queue
  709. hInf : Printer driver INF file handle
  710. dwInstallFlags : Driver installation flags
  711. Return Value:
  712. TRUE on success, FALSE else
  713. --*/
  714. {
  715. BOOL bRet=FALSE;
  716. DWORD dwNeeded, dwBytes, dwIndex, dwIndex2, dwCount, dwCount2;
  717. INT DRID;
  718. TCHAR szDir[MAX_PATH];
  719. INFCONTEXT InfContext;
  720. if ( (dwCount = SetupGetLineCount(hInf, TEXT("DestinationDirs"))) == -1 )
  721. goto Cleanup;
  722. // Setup the Skip Dir
  723. if ( !SetupSkipDir( platform, pszServerName ) )
  724. goto Cleanup;
  725. //
  726. // Process every line in the DestinationDirs section
  727. //
  728. for ( dwIndex = 0 ; dwIndex < dwCount ; ++dwIndex ) {
  729. if ( !SetupGetLineByIndex(hInf, TEXT("DestinationDirs"),
  730. dwIndex, &InfContext) )
  731. goto Cleanup;
  732. //
  733. // A file could be copied to multiple destination directories
  734. //
  735. if ( (dwCount2 = SetupGetFieldCount(&InfContext)) == 0 )
  736. continue;
  737. for ( dwIndex2 = 1 ; dwIndex2 <= dwCount2 ; ++dwIndex2 ) {
  738. //
  739. // Not all directories are specified with a DRID
  740. // for ex. %ProgramFiles%\%OLD_ICWDIR% could be used
  741. // If DRID is smaller than DIRID_USER setup has predefined
  742. // meaning to it
  743. //
  744. if ( !SetupGetIntField(&InfContext, dwIndex2, &DRID) ||
  745. ( DRID < DIRID_USER ) )
  746. continue;
  747. dwNeeded = SIZECHARS(szDir);
  748. dwBytes = sizeof(szDir);
  749. switch (DRID) {
  750. case PRINTER_DRIVER_DIRECTORY_ID:
  751. if ( !GetPrinterDriverDirectory(
  752. (LPTSTR)pszServerName,
  753. PlatformEnv[platform].pszName,
  754. 1,
  755. (LPBYTE)szDir,
  756. sizeof(szDir),
  757. &dwNeeded) )
  758. {
  759. goto Cleanup;
  760. }
  761. if ( dwInstallFlags & DRVINST_PRIVATE_DIRECTORY )
  762. {
  763. //
  764. // if we have a pnp-ID, and it's an installation of a native driver
  765. // and it's not an inbox driver, make the files stick around for
  766. // pnp-reinstallations, else the user gets prompted over and over again
  767. //
  768. if ((lstrlen(pLocalData->DrvInfo.pszHardwareID) != 0) &&
  769. !(dwInstallFlags & DRVINST_ALT_PLATFORM_INSTALL) &&
  770. !IsSystemNTPrintInf(pLocalData->DrvInfo.pszInfName))
  771. {
  772. //
  773. // add the pnp-ID to szDir and set flag to not clean up this directory
  774. // this is to get around users getting prompted for pnp-reinstallation
  775. //
  776. AddPnpDirTag( pLocalData->DrvInfo.pszHardwareID, szDir, sizeof(szDir)/sizeof(TCHAR));
  777. pLocalData->Flags |= LOCALDATAFLAG_PNP_DIR_INSTALL;
  778. }
  779. else
  780. {
  781. //
  782. // Add PID\TID to szDir.
  783. // If this fails, add the dir info held in szDir to the DRIVER_INFO struct
  784. // anyway as we'll attempt the install with this.
  785. //
  786. AddDirectoryTag( szDir, sizeof(szDir)/sizeof(TCHAR) );
  787. }
  788. ASSERT(pLocalData);
  789. //
  790. // Change DI6 to have the full szDir path included.
  791. // Can't do anything if this fails, so try finish install anyway.
  792. //
  793. AddDirToDriverInfo( szDir, &(pLocalData->InfInfo.DriverInfo6) );
  794. }
  795. break;
  796. case PRINT_PROC_DIRECTORY_ID:
  797. if ( dwInstallFlags & DRVINST_DRIVERFILES_ONLY ) {
  798. StringCchCopy(szDir, COUNTOF(szDir), gpszSkipDir);
  799. } else if ( !GetPrintProcessorDirectory(
  800. (LPTSTR)pszServerName,
  801. PlatformEnv[platform].pszName,
  802. 1,
  803. (LPBYTE)szDir,
  804. sizeof(szDir),
  805. &dwNeeded) )
  806. goto Cleanup;
  807. break;
  808. case SYSTEM_DIRECTORY_ID_ONLY_FOR_NATIVE_ARCHITECTURE:
  809. if ( !(dwInstallFlags & DRVINST_DRIVERFILES_ONLY) &&
  810. platform == MyPlatform &&
  811. MyName(pszServerName) ) {
  812. if ( !GetSystemDirectory(szDir, dwNeeded) )
  813. goto Cleanup;
  814. } else {
  815. StringCchCopy(szDir, COUNTOF(szDir),gpszSkipDir);
  816. }
  817. break;
  818. case ICM_PROFILE_DIRECTORY_ID:
  819. if ( !GetColorDirectory(pszServerName, szDir, &dwBytes) )
  820. goto Cleanup;
  821. break;
  822. case WEBPAGE_DIRECTORY_ID:
  823. if ( !GetWebPageDir(pLocalData, szDir) )
  824. goto Cleanup;
  825. break;
  826. default:
  827. //
  828. // This is for any new DRIDs we may add in the future
  829. //
  830. StringCchCopy(szDir, COUNTOF(szDir), gpszSkipDir);
  831. }
  832. if ( !SetupSetDirectoryId(hInf, DRID, szDir) )
  833. goto Cleanup;
  834. }
  835. }
  836. bRet = TRUE;
  837. Cleanup:
  838. return bRet;
  839. }
  840. BOOL
  841. PSetupInstallICMProfiles(
  842. IN LPCTSTR pszServerName,
  843. IN LPCTSTR pszzICMFiles
  844. )
  845. /*++
  846. Routine Description:
  847. Install ICM color profiles associated with a printer driver.
  848. Arguments:
  849. pszServerName : Server name to which we are installing
  850. pszzICMFiles : ICM profiles to install (multi-sz)
  851. Return Value:
  852. TRUE on success, FALSE else
  853. --*/
  854. {
  855. TCHAR szDir[MAX_PATH], *p;
  856. DWORD dwSize, dwNeeded;
  857. BOOL bRet = TRUE;
  858. if ( !pszzICMFiles || !*pszzICMFiles )
  859. return bRet;
  860. dwSize = SIZECHARS(szDir);
  861. dwNeeded = sizeof(szDir);
  862. if ( !GetColorDirectory(pszServerName, szDir, &dwNeeded) )
  863. return FALSE;
  864. dwNeeded /= sizeof(TCHAR);
  865. szDir[dwNeeded-1] = TEXT('\\');
  866. //
  867. // Install and assoicate each profiles from the multi-sz field
  868. //
  869. for ( p = (LPTSTR) pszzICMFiles; bRet && *p ; p += lstrlen(p) + 1 ) {
  870. if ( dwNeeded + lstrlen(p) + 1 > dwSize ) {
  871. ASSERT(dwNeeded + lstrlen(p) + 1 <= dwSize);
  872. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  873. return FALSE;
  874. }
  875. StringCchCopy(szDir + dwNeeded, dwSize - dwNeeded, p);
  876. //
  877. // This function only supports NULL as the servername
  878. //
  879. bRet = InstallColorProfile( NULL, szDir);
  880. }
  881. return bRet;
  882. }
  883. BOOL
  884. MonitorRedirectDisable(
  885. IN LPCTSTR pszMonitorDll,
  886. OUT PTCHAR *ppszDir
  887. )
  888. {
  889. BOOL bRet = FALSE;
  890. PTCHAR pszBuffer = NULL;
  891. DWORD dwDirLen = 0;
  892. if( IsInWow64() )
  893. {
  894. pszBuffer = (PTCHAR)LocalAllocMem( MAX_PATH * sizeof( TCHAR ) );
  895. if((pszBuffer != NULL) && GetSystemDirectory(pszBuffer, MAX_PATH))
  896. {
  897. dwDirLen = lstrlen(pszBuffer);
  898. //
  899. // Size of the returned string + size of file name + '\' + terminating null.
  900. //
  901. if( (dwDirLen + lstrlen(pszMonitorDll) + 2) < MAX_PATH )
  902. {
  903. if( *(pszBuffer + dwDirLen-1) != _T('\\') )
  904. {
  905. *(pszBuffer + dwDirLen++) = _T('\\');
  906. *(pszBuffer + dwDirLen) = 0;
  907. }
  908. StringCchCat(pszBuffer, MAX_PATH, pszMonitorDll);
  909. #if !_WIN64
  910. Wow64DisableFilesystemRedirector(pszBuffer);
  911. #endif
  912. bRet = TRUE;
  913. }
  914. }
  915. if (ppszDir != NULL)
  916. {
  917. *ppszDir = pszBuffer;
  918. }
  919. }
  920. return bRet;
  921. }
  922. BOOL
  923. MonitorRedirectEnable(
  924. IN OUT PTCHAR *ppszDir
  925. )
  926. {
  927. BOOL bRet = FALSE;
  928. if( IsInWow64() )
  929. {
  930. //
  931. // This MACRO works on the current thread. Only one file can be disabled for redirection at a time.
  932. //
  933. #if !_WIN64
  934. Wow64EnableFilesystemRedirector();
  935. #endif
  936. }
  937. if ((ppszDir != NULL) && (*ppszDir != NULL))
  938. {
  939. LocalFreeMem( *ppszDir );
  940. *ppszDir = NULL;
  941. bRet = TRUE;
  942. }
  943. return bRet;
  944. }
  945. BOOL
  946. UseUniqueDirectory(
  947. IN LPCTSTR pszServerName
  948. )
  949. /*++
  950. Routine Description:
  951. Determines whether the unique install directory flags should be used or not.
  952. Arguments:
  953. pszServerName - the name of the remote server. NULL means local machine.
  954. Return Value:
  955. TRUE if we are going remote to a whistler or more recent server
  956. or we are installing locally but not in setup.
  957. FALSE else
  958. --*/
  959. {
  960. BOOL bRet = FALSE;
  961. if( pszServerName && *pszServerName )
  962. {
  963. bRet = IsWhistlerOrAbove(pszServerName);
  964. }
  965. else
  966. {
  967. if( !IsSystemSetupInProgress() )
  968. {
  969. bRet = TRUE;
  970. }
  971. }
  972. return bRet;
  973. }
  974. DWORD
  975. PSetupShowBlockedDriverUI(HWND hwnd,
  976. DWORD BlockingStatus)
  977. /*++
  978. Routine Description:
  979. Throws UI to ask user what to do with a blocked/warned driver
  980. Arguments:
  981. hwnd: parent window
  982. BlockingStatus: the DWORD containing the BSP_* flags that indicate whether driver is blocked
  983. Return Value:
  984. New blocking status, the user selection is OR'd. Treats errors as if the user cancelled.
  985. --*/
  986. {
  987. DWORD NewBlockingStatus = BlockingStatus;
  988. LPTSTR pszTitle = NULL, pszPrompt = NULL;
  989. switch (BlockingStatus & BSP_BLOCKING_LEVEL_MASK)
  990. {
  991. case BSP_PRINTER_DRIVER_WARNED:
  992. if (BlockingStatus & BSP_INBOX_DRIVER_AVAILABLE)
  993. {
  994. pszTitle = GetStringFromRcFile(IDS_TITLE_BSP_WARN);
  995. pszPrompt = GetLongStringFromRcFile(IDS_BSP_WARN_WITH_INBOX);
  996. if (!pszTitle || !pszPrompt)
  997. {
  998. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  999. goto Cleanup;
  1000. }
  1001. switch (MessageBox(hwnd, pszPrompt, pszTitle, MB_YESNOCANCEL | MB_ICONWARNING))
  1002. {
  1003. case IDYES:
  1004. NewBlockingStatus |= BSP_PRINTER_DRIVER_PROCEEDED;
  1005. break;
  1006. case IDNO:
  1007. NewBlockingStatus |= BSP_PRINTER_DRIVER_REPLACED;
  1008. break;
  1009. default:
  1010. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  1011. break;
  1012. }
  1013. }
  1014. else // warned but not inbox available
  1015. {
  1016. pszTitle = GetStringFromRcFile(IDS_TITLE_BSP_WARN);
  1017. pszPrompt = GetLongStringFromRcFile(IDS_BSP_WARN_NO_INBOX);
  1018. if (!pszTitle || !pszPrompt)
  1019. {
  1020. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  1021. goto Cleanup;
  1022. }
  1023. switch (MessageBox(hwnd, pszPrompt, pszTitle, MB_OKCANCEL | MB_ICONWARNING))
  1024. {
  1025. case IDOK:
  1026. NewBlockingStatus |= BSP_PRINTER_DRIVER_PROCEEDED;
  1027. break;
  1028. default:
  1029. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  1030. break;
  1031. }
  1032. }
  1033. break;
  1034. case BSP_PRINTER_DRIVER_BLOCKED:
  1035. if (BlockingStatus & BSP_INBOX_DRIVER_AVAILABLE)
  1036. {
  1037. pszTitle = GetStringFromRcFile(IDS_TITLE_BSP_WARN);
  1038. pszPrompt = GetLongStringFromRcFile(IDS_BSP_BLOCK_WITH_INBOX);
  1039. if (!pszTitle || !pszPrompt)
  1040. {
  1041. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  1042. goto Cleanup;
  1043. }
  1044. switch (MessageBox(hwnd, pszPrompt, pszTitle, MB_OKCANCEL | MB_ICONWARNING))
  1045. {
  1046. case IDOK:
  1047. NewBlockingStatus |= BSP_PRINTER_DRIVER_REPLACED;
  1048. break;
  1049. default:
  1050. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  1051. break;
  1052. }
  1053. }
  1054. else // blocked and no inbox available - don't allow installation
  1055. {
  1056. pszTitle = GetStringFromRcFile(IDS_TITLE_BSP_ERROR);
  1057. pszPrompt = GetLongStringFromRcFile(IDS_BSP_BLOCK_NO_INBOX);
  1058. if (!pszTitle || !pszPrompt)
  1059. {
  1060. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  1061. goto Cleanup;
  1062. }
  1063. MessageBox(hwnd, pszPrompt, pszTitle, MB_OK | MB_ICONSTOP);
  1064. NewBlockingStatus |= BSP_PRINTER_DRIVER_CANCELLED;
  1065. }
  1066. break;
  1067. }
  1068. Cleanup:
  1069. if (pszTitle)
  1070. {
  1071. LocalFreeMem(pszTitle);
  1072. }
  1073. if (pszPrompt)
  1074. {
  1075. LocalFreeMem(pszPrompt);
  1076. }
  1077. return NewBlockingStatus;
  1078. }
  1079. BOOL
  1080. ValidPlatform(
  1081. IN PLATFORM platform
  1082. )
  1083. {
  1084. BOOL bRet = FALSE;
  1085. switch (platform)
  1086. {
  1087. case PlatformAlpha:
  1088. bRet = TRUE;
  1089. break;
  1090. case PlatformX86:
  1091. bRet = TRUE;
  1092. break;
  1093. case PlatformMIPS:
  1094. bRet = TRUE;
  1095. break;
  1096. case PlatformPPC:
  1097. bRet = TRUE;
  1098. break;
  1099. case PlatformWin95:
  1100. bRet = TRUE;
  1101. break;
  1102. case PlatformIA64:
  1103. bRet = TRUE;
  1104. break;
  1105. case PlatformAlpha64:
  1106. bRet = TRUE;
  1107. break;
  1108. default:
  1109. bRet = FALSE;
  1110. }
  1111. return bRet;
  1112. }
  1113. DWORD
  1114. InstallDriverFromCurrentInf(
  1115. IN HDEVINFO hDevInfo,
  1116. IN PPSETUP_LOCAL_DATA pLocalData,
  1117. IN HWND hwnd,
  1118. IN PLATFORM platform,
  1119. IN DWORD dwVersion,
  1120. IN LPCTSTR pszServerName,
  1121. IN HSPFILEQ CopyQueue,
  1122. IN PVOID QueueContext,
  1123. IN PSP_FILE_CALLBACK InstallMsgHandler,
  1124. IN DWORD Flags,
  1125. IN LPCTSTR pszSource,
  1126. IN DWORD dwInstallFlags,
  1127. IN DWORD dwAddDrvFlags,
  1128. IN LPCTSTR pszFileSrcPath,
  1129. OUT LPTSTR *ppszNewDriverName,
  1130. OUT PDWORD pBlockingStatus
  1131. )
  1132. {
  1133. HINF hPrinterInf = INVALID_HANDLE_VALUE;
  1134. BOOL bRet = FALSE;
  1135. BOOL bAddMon = FALSE;
  1136. BOOL bKeepMonName = FALSE;
  1137. BOOL bCatInInf = FALSE;
  1138. DWORD dwStatus = EXIT_FAILURE;
  1139. LPTSTR pszMonitorDll,
  1140. psz;
  1141. PSELECTED_DRV_INFO pDrvInfo;
  1142. PPARSEINF_INFO pInfInfo;
  1143. PVOID pDSInfo = NULL; // Holds pointer to the driver signing class that C can't understand.
  1144. FILE_QUEUE_CONTEXT FileQContext;
  1145. //
  1146. // The following are only used during Cleanup
  1147. //
  1148. BOOL bZeroInf = FALSE,
  1149. bCopyInf = FALSE;
  1150. DWORD dwMediaType = SPOST_NONE;
  1151. DWORD dwInstallLE = ERROR_SUCCESS; // We record the LastError in case Cleanup
  1152. // alters it
  1153. LPTSTR pszINFName = NULL; // This will record whether the inf was
  1154. // copied in
  1155. LPTSTR pszNewINFName = NULL; // Hold the name of the inf to be zeroed if necessary
  1156. TCHAR szFullINFName[ MAX_PATH ]; // The Original Inf Name
  1157. TCHAR szFullNewINFName[ MAX_PATH ]; // The fully qualified inf name as copied onto the system.
  1158. HANDLE hDriverFile = INVALID_HANDLE_VALUE;
  1159. LPTSTR pszNewDriverName = NULL;
  1160. DWORD fBlockingStatus = BSP_PRINTER_DRIVER_OK;
  1161. PTCHAR pszDirPtr = NULL;
  1162. DWORD ScanResult = 0;
  1163. //
  1164. // Those below are used to manage the situation when the driver is not signed
  1165. //
  1166. BOOL bIsPersonalOrProfessional = FALSE;
  1167. HANDLE hRestorePointHandle = NULL;
  1168. BOOL bDriverNotInstalled = TRUE;
  1169. BOOL bIsWindows64 = FALSE;
  1170. BOOL bPreviousNames = FALSE;
  1171. DWORD dwOEMInfFileAttrs = 0;
  1172. const DWORD dwGetFileAttrsError = INVALID_FILE_ATTRIBUTES;
  1173. szFullINFName[0] = TEXT('\0');
  1174. szFullNewINFName[0] = TEXT('\0');
  1175. if(!pLocalData || !ValidPlatform(platform))
  1176. {
  1177. SetLastError(ERROR_INVALID_PARAMETER);
  1178. return ERROR_INVALID_PARAMETER;
  1179. }
  1180. pDrvInfo = &pLocalData->DrvInfo;
  1181. pInfInfo = &pLocalData->InfInfo;
  1182. //
  1183. // Set the unique directory flags if we are in a situation that uses them.
  1184. //
  1185. if( UseUniqueDirectory(pszServerName) ) {
  1186. dwInstallFlags |= DRVINST_PRIVATE_DIRECTORY;
  1187. dwAddDrvFlags |= APD_COPY_FROM_DIRECTORY;
  1188. }
  1189. //
  1190. // If this is a Windows update install, we need to ensure that all
  1191. // cluster spooler resources get their drivers updated.
  1192. //
  1193. if (dwInstallFlags & DRVINST_WINDOWS_UPDATE)
  1194. {
  1195. dwAddDrvFlags |= APD_COPY_TO_ALL_SPOOLERS;
  1196. pInfInfo->DriverInfo6.cVersion = dwVersion;
  1197. }
  1198. //
  1199. // Open INF file and append layout.inf specified in Version section
  1200. // Layout inf is optional
  1201. //
  1202. hPrinterInf = SetupOpenInfFile(pDrvInfo->pszInfName,
  1203. NULL,
  1204. INF_STYLE_WIN4,
  1205. NULL);
  1206. if ( hPrinterInf == INVALID_HANDLE_VALUE )
  1207. goto Cleanup;
  1208. SetupOpenAppendInfFile(NULL, hPrinterInf, NULL);
  1209. pInfInfo->DriverInfo6.pEnvironment = PlatformEnv[platform].pszName;
  1210. //
  1211. // DI_VCP tells us not to create new file-queue and use user provided one
  1212. //
  1213. if ( !(Flags & DI_NOVCP) ) {
  1214. CopyQueue = SetupOpenFileQueue();
  1215. if ( CopyQueue == INVALID_HANDLE_VALUE )
  1216. goto Cleanup;
  1217. if ( dwInstallFlags & DRVINST_PROGRESSLESS ) {
  1218. QueueContext = SetupInitDefaultQueueCallbackEx(
  1219. hwnd,
  1220. INVALID_HANDLE_VALUE,
  1221. 0,
  1222. 0,
  1223. NULL);
  1224. } else {
  1225. QueueContext = SetupInitDefaultQueueCallback(hwnd);
  1226. }
  1227. InstallMsgHandler = MyQueueCallback;
  1228. ZeroMemory(&FileQContext, sizeof(FileQContext));
  1229. FileQContext.hwnd = hwnd;
  1230. FileQContext.QueueContext = QueueContext;
  1231. FileQContext.dwInstallFlags = dwInstallFlags;
  1232. FileQContext.pszSource = (dwInstallFlags & DRVINST_FLATSHARE)
  1233. ? pszSource : NULL;
  1234. FileQContext.platform = platform;
  1235. FileQContext.dwVersion = dwVersion;
  1236. FileQContext.pszFileSrcPath = pszFileSrcPath;
  1237. if (pDrvInfo->pszInfName)
  1238. {
  1239. StringCchCopy(FileQContext.szInfPath, COUNTOF(FileQContext.szInfPath), pDrvInfo->pszInfName);
  1240. //
  1241. // Cut off the inf file name
  1242. //
  1243. psz = _tcsrchr(FileQContext.szInfPath, _T('\\'));
  1244. if (psz)
  1245. {
  1246. *psz = 0;
  1247. }
  1248. }
  1249. }
  1250. //
  1251. // Setup the driver signing info.
  1252. //
  1253. if(NULL == (pDSInfo = SetupDriverSigning(hDevInfo, pszServerName,pDrvInfo->pszInfName,
  1254. pszSource, platform, dwVersion, CopyQueue, dwInstallFlags & DRVINST_WEBPNP)))
  1255. {
  1256. goto Cleanup;
  1257. }
  1258. //
  1259. // Find out if the cat was listed in a CatalogFile= entry.
  1260. // This is used in the cleanup.
  1261. //
  1262. bCatInInf = IsCatInInf(pDSInfo);
  1263. //
  1264. // Check if this Driver is from CDM.
  1265. // IF it is pass in the correct MediaType to Setup.
  1266. //
  1267. if ( (pLocalData->DrvInfo.Flags & SDFLAG_CDM_DRIVER) || (dwInstallFlags & DRVINST_WINDOWS_UPDATE) )
  1268. dwMediaType = SPOST_URL;
  1269. //
  1270. // For non admins, we install the catalog by calling AddDriverCatalog
  1271. //
  1272. // Do not fail the call when AddDriverCatalog fails
  1273. //
  1274. (void)AddDriverCatalogIfNotAdmin(pszServerName, pDSInfo, pDrvInfo->pszInfName, NULL, dwMediaType, 0);
  1275. //
  1276. // To support same INFs to install both NT and Win95 drivers actual
  1277. // section to install could be different than the one corresponding
  1278. // to the selected driver.
  1279. //
  1280. // SetupSetPlatformOverride tells setup which platform drivers we need
  1281. // from the media
  1282. // Also note setup does not reset PlatformPath override. So we need to
  1283. // call this always
  1284. //
  1285. if ( !ParseInf(hDevInfo, pLocalData, platform, pszServerName, dwInstallFlags, FALSE) ||
  1286. !SetupSetPlatformPathOverride(PlatformOverride[platform].pszName) ) {
  1287. goto Cleanup;
  1288. }
  1289. // Now do the actual file copies...
  1290. if ( !InstallAllInfSections( pLocalData,
  1291. platform,
  1292. pszServerName,
  1293. CopyQueue,
  1294. pszSource,
  1295. dwInstallFlags,
  1296. hPrinterInf,
  1297. pInfInfo->pszInstallSection ) )
  1298. goto Cleanup;
  1299. //
  1300. // If there is a language monitor make sure it is getting copied to
  1301. // system32. On NT 4 we used to manually queue it to system32
  1302. //
  1303. if ( pInfInfo->DriverInfo6.pMonitorName &&
  1304. platform == MyPlatform &&
  1305. !(dwInstallFlags & DRVINST_DRIVERFILES_ONLY) &&
  1306. !pszServerName)
  1307. {
  1308. //
  1309. // NOTICE-2001/06/18-rorleth -- see bug NTBUG9-416129 Installing NT4 additional driver loses LM registry information.
  1310. //
  1311. //
  1312. // If it's an alternate platform but the platform really is the same (checked above)
  1313. // it's an NT4 driver on an x86 server. In this case install the LM too if not
  1314. // already installed else point-and-print from an NT4 client that has the same driver
  1315. // installed locally will delete the LM info from the NT4 driver.
  1316. // The logic is a little twisted: install the monitor if it's not an alternate platform
  1317. // or if it is (within the limits checked above) but no monitor with this name is installed yet.
  1318. //
  1319. if (!(dwInstallFlags & DRVINST_ALT_PLATFORM_INSTALL) ||
  1320. !IsLanguageMonitorInstalled(pInfInfo->DriverInfo6.pMonitorName))
  1321. {
  1322. pszMonitorDll = pInfInfo->DriverInfo6.pMonitorName +
  1323. lstrlen(pInfInfo->DriverInfo6.pMonitorName) + 1;
  1324. //
  1325. // When we parse the INF we put the monitor dll name after \0
  1326. //
  1327. if ( !CheckAndEnqueueMonitorDll(pszMonitorDll,
  1328. pszSource,
  1329. CopyQueue,
  1330. hPrinterInf) )
  1331. goto Cleanup;
  1332. MonitorRedirectDisable( pszMonitorDll, &pszDirPtr );
  1333. bAddMon = TRUE;
  1334. }
  1335. else
  1336. {
  1337. //
  1338. // we get here if it's an alternate platform driver and the monitor is already installed
  1339. // in this case, don't clean out the monitor name from the driver info 6 below.
  1340. //
  1341. bKeepMonName = TRUE;
  1342. }
  1343. }
  1344. //
  1345. // DI_NOVCP is used for pre-install when the class installer is just
  1346. // supposed to queue the files and return. Printing needs special
  1347. // handling since APIs need to be called. But we will obey the flags
  1348. // as much as possible for those who use it
  1349. //
  1350. if ( Flags & DI_NOVCP ) {
  1351. bRet = TRUE;
  1352. goto Cleanup;
  1353. }
  1354. // We need a Queue Context to actually install files
  1355. if ( !QueueContext )
  1356. goto Cleanup;
  1357. // Check if this is a WebPnP install
  1358. if ( dwInstallFlags & DRVINST_WEBPNP || !(bAddMon || bKeepMonName) )
  1359. {
  1360. //
  1361. // Check to see if there is a Monitor. If so clear out.
  1362. // There is no need to call IsLanguageMonitorInstalled here, since if we
  1363. // get to this point in the code either it is a Web-PnP installation
  1364. // in which case the language monitor is useless, or the printer driver
  1365. // (and language monitor) is for a different platform or we are installing
  1366. // on a server different than our local machine, in which case we cannot
  1367. // enumerate the language monitors. Note EnumMonitors does NOT enumerate
  1368. // language monitors.
  1369. //
  1370. if ( pInfInfo->DriverInfo6.pMonitorName )
  1371. {
  1372. LocalFreeMem( pInfInfo->DriverInfo6.pMonitorName );
  1373. pInfInfo->DriverInfo6.pMonitorName = NULL;
  1374. }
  1375. }
  1376. if (!PruneInvalidFilesIfNotAdmin( hwnd,
  1377. CopyQueue ))
  1378. goto Cleanup;
  1379. //
  1380. // prune files that are already present (correct version etc. checked by signature), ignore return value
  1381. //
  1382. SetupScanFileQueue( CopyQueue,
  1383. (SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE),
  1384. hwnd,
  1385. NULL,
  1386. NULL,
  1387. &ScanResult);
  1388. if (!pszServerName || !lstrlen(pszServerName))
  1389. {
  1390. bIsPersonalOrProfessional = IsProductType( VER_NT_WORKSTATION, VER_EQUAL) == S_OK;
  1391. }
  1392. else
  1393. {
  1394. bIsPersonalOrProfessional = FALSE;
  1395. }
  1396. if (bIsPersonalOrProfessional)
  1397. {
  1398. SetupSetFileQueueFlags( CopyQueue,
  1399. SPQ_FLAG_ABORT_IF_UNSIGNED,
  1400. SPQ_FLAG_ABORT_IF_UNSIGNED );
  1401. }
  1402. if ( !SetupCommitFileQueue(hwnd,
  1403. CopyQueue,
  1404. (PSP_FILE_CALLBACK)InstallMsgHandler,
  1405. (PVOID)&FileQContext) )
  1406. {
  1407. bIsWindows64 = IsInWow64();
  1408. if ((bIsWindows64 == FALSE) && bIsPersonalOrProfessional &&
  1409. (GetLastError() == ERROR_SET_SYSTEM_RESTORE_POINT))
  1410. {
  1411. //
  1412. // Here we have to start a Restore Point because there is
  1413. // something unsigned and this is either a personal or
  1414. // professional.
  1415. //
  1416. hRestorePointHandle = StartSystemRestorePoint( NULL,
  1417. (PCWSTR)(pLocalData->DrvInfo.pszModelName),
  1418. ghInst,
  1419. IDS_BSP_WARN_UNSIGNED_DRIVER );
  1420. //
  1421. // Terminate the default setupapi callback
  1422. //
  1423. SetupTermDefaultQueueCallback( QueueContext );
  1424. QueueContext = NULL;
  1425. //
  1426. // Initialize the QueueContext structure
  1427. //
  1428. if ( dwInstallFlags & DRVINST_PROGRESSLESS )
  1429. {
  1430. QueueContext = SetupInitDefaultQueueCallbackEx(hwnd,
  1431. INVALID_HANDLE_VALUE,
  1432. 0,
  1433. 0,
  1434. NULL);
  1435. }
  1436. else
  1437. {
  1438. QueueContext = SetupInitDefaultQueueCallback(hwnd);
  1439. }
  1440. if (!QueueContext)
  1441. {
  1442. goto Cleanup;
  1443. }
  1444. else
  1445. {
  1446. FileQContext.QueueContext = QueueContext;
  1447. }
  1448. //
  1449. // Reset the flag and call the function again
  1450. //
  1451. SetupSetFileQueueFlags( CopyQueue,
  1452. SPQ_FLAG_ABORT_IF_UNSIGNED,
  1453. 0 );
  1454. if ( !SetupCommitFileQueue(hwnd,
  1455. CopyQueue,
  1456. (PSP_FILE_CALLBACK)InstallMsgHandler,
  1457. (PVOID)&FileQContext) )
  1458. {
  1459. goto Cleanup;
  1460. }
  1461. }
  1462. else
  1463. {
  1464. goto Cleanup;
  1465. }
  1466. }
  1467. //
  1468. // Now that we did the file copy part of install we will do anything
  1469. // else specified in the INF
  1470. //
  1471. if ( !pszServerName && platform == MyPlatform )
  1472. {
  1473. SetupInstallFromInfSection(hwnd,
  1474. hPrinterInf,
  1475. pInfInfo->pszInstallSection,
  1476. SPINST_ALL & (~SPINST_FILES),
  1477. NULL,
  1478. pszSource,
  1479. 0,
  1480. NULL,
  1481. QueueContext,
  1482. hDevInfo,
  1483. pDrvInfo->pDevInfoData);
  1484. }
  1485. if ( bAddMon )
  1486. {
  1487. if( !AddPrintMonitor(pInfInfo->DriverInfo6.pMonitorName, pszMonitorDll) )
  1488. {
  1489. DWORD dwSavedLastError = EXIT_FAILURE;
  1490. //
  1491. // If we can not add monitor, check whether this
  1492. // driver is in printupg. If it is, consider it blocked then and
  1493. // popups a UI asking whether to install the replacement driver.
  1494. //
  1495. // After this point bRet is allways false, we only try to change
  1496. // the error code in last error.
  1497. //
  1498. //
  1499. // Save the last error first
  1500. //
  1501. dwSavedLastError = GetLastError();
  1502. if (BlockedDriverPrintUpgUI(pszServerName,
  1503. &pInfInfo->DriverInfo6,
  1504. dwInstallFlags & DRVINST_PRIVATE_DIRECTORY, // whether use full path
  1505. !(dwInstallFlags & DRVINST_DONT_OFFER_REPLACEMENT), // whether to offer replacement
  1506. !(dwInstallFlags & (DRVINST_NO_WARNING_PROMPT | DRVINST_PROMPTLESS)), // whether to popup UI
  1507. &pszNewDriverName,
  1508. &fBlockingStatus) &&
  1509. (fBlockingStatus & BSP_PRINTER_DRIVER_REPLACED))
  1510. {
  1511. SetLastError(ERROR_PRINTER_DRIVER_BLOCKED);
  1512. }
  1513. else
  1514. {
  1515. SetLastError(dwSavedLastError); // restore the error code
  1516. }
  1517. goto Cleanup;
  1518. }
  1519. MonitorRedirectEnable( &pszDirPtr );
  1520. }
  1521. //
  1522. // If a print processor is specified in the INF need to install it.
  1523. // For non-native architectur spooler fails this call (for remote case)
  1524. // We have to install a Print Processor only in the case of a local installation AND
  1525. // same platform.
  1526. //
  1527. if ( !(dwInstallFlags & DRVINST_ALT_PLATFORM_INSTALL) &&
  1528. !pszServerName &&
  1529. pInfInfo->pszPrintProc &&
  1530. !AddPrintProcessor((LPTSTR)pszServerName,
  1531. PlatformEnv[platform].pszName,
  1532. pInfInfo->pszPrintProc
  1533. + lstrlen(pInfInfo->pszPrintProc) + 1,
  1534. pInfInfo->pszPrintProc) &&
  1535. GetLastError() != ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED &&
  1536. GetLastError() != ERROR_INVALID_ENVIRONMENT )
  1537. {
  1538. goto Cleanup;
  1539. }
  1540. if (IsTheSamePlatform(pszServerName, platform) && IsWhistlerOrAbove(pszServerName))
  1541. {
  1542. bPreviousNames = CheckAndKeepPreviousNames( pszServerName, &pInfInfo->DriverInfo6, platform );
  1543. }
  1544. bRet = AddPrinterDriverUsingCorrectLevelWithPrintUpgRetry(pszServerName,
  1545. &pInfInfo->DriverInfo6,
  1546. dwAddDrvFlags | APD_DONT_SET_CHECKPOINT,
  1547. dwInstallFlags & DRVINST_PRIVATE_DIRECTORY, // whether use full path
  1548. !(dwInstallFlags & DRVINST_DONT_OFFER_REPLACEMENT), // whether to offer replacement
  1549. !(dwInstallFlags & (DRVINST_NO_WARNING_PROMPT | DRVINST_PROMPTLESS)), // whether to popup UI
  1550. &pszNewDriverName,
  1551. &fBlockingStatus) &&
  1552. PSetupInstallICMProfiles(pszServerName, pInfInfo->pszzICMFiles);
  1553. if (bPreviousNames)
  1554. {
  1555. LocalFreeMem( pInfInfo->DriverInfo6.pszzPreviousNames );
  1556. pInfInfo->DriverInfo6.pszzPreviousNames = NULL;
  1557. }
  1558. bDriverNotInstalled = FALSE;
  1559. Cleanup:
  1560. dwInstallLE = GetLastError(); // Get the real error message
  1561. if (bAddMon && pszDirPtr)
  1562. {
  1563. MonitorRedirectEnable( &pszDirPtr );
  1564. }
  1565. if ((bIsWindows64 == FALSE) && hRestorePointHandle)
  1566. {
  1567. //
  1568. // Here we have to end the Restore Point because one was
  1569. // started
  1570. //
  1571. EndSystemRestorePoint(hRestorePointHandle, bDriverNotInstalled);
  1572. }
  1573. if (hDriverFile != INVALID_HANDLE_VALUE)
  1574. {
  1575. CloseHandle(hDriverFile);
  1576. }
  1577. //
  1578. // Zero the inf if DI_NOVCP and - either we've fail, it is a Web PNP
  1579. // install. or - this is installing from a non-system ntprint.inf AND
  1580. // there is a cat to be protected. - not yet!!
  1581. //
  1582. bZeroInf = (!bRet || ( dwInstallFlags & DRVINST_WEBPNP )
  1583. || (IsNTPrintInf( pDrvInfo->pszInfName ) && bCatInInf)) &&
  1584. !(Flags & DI_NOVCP);
  1585. //
  1586. // We have to copy the INF if the following conditions are satisfied
  1587. //
  1588. bCopyInf = // bRet is TRUE (the call to AddPrinterDriverUsingCorrectLevelWithPrintUpgRetry succeeded)
  1589. bRet &&
  1590. // and the Installation flags say the INF to be copied
  1591. !(dwInstallFlags & DRVINST_DONOTCOPY_INF) &&
  1592. // and the platform is the same as ours
  1593. platform == MyPlatform &&
  1594. // and the INF it's not the system ntprint.inf (obviously) or
  1595. // it's from WU
  1596. (!IsSystemNTPrintInf(pDrvInfo->pszInfName) || (pLocalData->DrvInfo.Flags & SDFLAG_CDM_DRIVER)) &&
  1597. // and DI_NOVCP flag is not set
  1598. !(Flags & DI_NOVCP) &&
  1599. // and this is not Web PnP or there is a cat to protect
  1600. !((dwInstallFlags & DRVINST_WEBPNP) && !bCatInInf) &&
  1601. // and this is not ntprint.inf or there is a cat to protect
  1602. !(IsNTPrintInf( pDrvInfo->pszInfName ) && !bCatInInf);
  1603. //
  1604. // How we have to call SetupCopyOEMInf to take the name of the INF which
  1605. // has been copied on our system when we called SetupCommitFileQueue
  1606. //
  1607. if (!SetupCopyOEMInf(pDrvInfo->pszInfName,
  1608. NULL,
  1609. dwMediaType,
  1610. SP_COPY_REPLACEONLY,
  1611. szFullINFName,
  1612. MAX_PATH,
  1613. NULL,
  1614. &pszINFName) )
  1615. {
  1616. // If we can't find the original name might as well not copy or
  1617. // zero
  1618. if (bZeroInf && !bCopyInf)
  1619. {
  1620. bZeroInf = FALSE;
  1621. }
  1622. }
  1623. else
  1624. {
  1625. if (bZeroInf)
  1626. {
  1627. bCopyInf = FALSE;
  1628. }
  1629. }
  1630. //
  1631. // If we succesfully installed a native architecture driver
  1632. // then is when we copy the OEM INF file and give it a unique name
  1633. //
  1634. if ( bCopyInf )
  1635. {
  1636. //
  1637. // Earlier we used to call CopyOEMInfFileAndGiveUniqueName here
  1638. // Now that Setup API has this and we are going to support CDM
  1639. // we call this setup API
  1640. //
  1641. (VOID)SetupCopyOEMInf(pDrvInfo->pszInfName,
  1642. NULL,
  1643. dwMediaType,
  1644. SP_COPY_NOOVERWRITE,
  1645. szFullNewINFName,
  1646. MAX_PATH,
  1647. NULL,
  1648. &pszNewINFName);
  1649. //
  1650. // If this fails we don't give the proverbial, since the file won't
  1651. // be there
  1652. //
  1653. }
  1654. else
  1655. {
  1656. if (!bZeroInf && !(Flags & DI_NOVCP))
  1657. {
  1658. //
  1659. // We have to remove the INF in the case of unsuccessful installation and ONLY if the DI_NOVCP
  1660. // flag is not set. If the flag is set then we don't have to change the state because the file
  1661. // queue hasn't been commited and the INF just has been already there before the call to our
  1662. // function.
  1663. //
  1664. //
  1665. // Remove the READONLY file attribute if set
  1666. //
  1667. dwOEMInfFileAttrs = GetFileAttributes( szFullINFName );
  1668. if ((dwOEMInfFileAttrs != dwGetFileAttrsError) &&
  1669. (dwOEMInfFileAttrs & FILE_ATTRIBUTE_READONLY))
  1670. {
  1671. dwOEMInfFileAttrs &= ~FILE_ATTRIBUTE_READONLY;
  1672. SetFileAttributes( szFullINFName, dwOEMInfFileAttrs);
  1673. }
  1674. DeleteFile( szFullINFName );
  1675. }
  1676. }
  1677. // Ignore the error message from SetupCopyOEMInf and DeleteFile
  1678. dwStatus = bRet ? ERROR_SUCCESS : dwInstallLE;
  1679. // If the install failed or this was Web Point&Print
  1680. // we may need to get rid of the INF
  1681. if ( bZeroInf )
  1682. {
  1683. // If INFName is different then possibly set to 0 length
  1684. // Or this is ntprint.inf being renamed to OEMx.inf - we want it zeroed.
  1685. if (( pszINFName &&
  1686. (psz=FileNamePart( pDrvInfo->pszInfName )) &&
  1687. lstrcmp( psz, pszINFName ) ) ||
  1688. ( IsNTPrintInf( pDrvInfo->pszInfName ) &&
  1689. bCatInInf &&
  1690. pszNewINFName &&
  1691. (psz=FileNamePart( pDrvInfo->pszInfName )) &&
  1692. lstrcmp( psz, pszINFName ) ) )
  1693. {
  1694. HANDLE hFile;
  1695. //
  1696. // Remove the READONLY file attribute if set
  1697. //
  1698. dwOEMInfFileAttrs = GetFileAttributes(szFullINFName ? szFullINFName : szFullNewINFName);
  1699. if ((dwOEMInfFileAttrs != dwGetFileAttrsError) &&
  1700. (dwOEMInfFileAttrs & FILE_ATTRIBUTE_READONLY))
  1701. {
  1702. dwOEMInfFileAttrs &= ~FILE_ATTRIBUTE_READONLY;
  1703. SetFileAttributes(szFullINFName ? szFullINFName : szFullNewINFName, dwOEMInfFileAttrs);
  1704. }
  1705. // Open the File
  1706. hFile = CreateFile( szFullINFName ? szFullINFName : szFullNewINFName,
  1707. (GENERIC_READ | GENERIC_WRITE),
  1708. ( FILE_SHARE_READ | FILE_SHARE_WRITE ),
  1709. NULL,
  1710. OPEN_EXISTING,
  1711. FILE_ATTRIBUTE_NORMAL,
  1712. NULL );
  1713. // If we opened a file
  1714. if ( hFile != INVALID_HANDLE_VALUE )
  1715. {
  1716. SetFilePointer( hFile, 0, 0, FILE_BEGIN );
  1717. SetEndOfFile( hFile );
  1718. CloseHandle( hFile );
  1719. }
  1720. }
  1721. }
  1722. if ( hPrinterInf != INVALID_HANDLE_VALUE )
  1723. SetupCloseInfFile(hPrinterInf);
  1724. //
  1725. // Free the Driver Signing class.
  1726. //
  1727. if(pDSInfo)
  1728. {
  1729. CleanupDriverSigning(pDSInfo);
  1730. }
  1731. if ( !(Flags & DI_NOVCP) ) {
  1732. //
  1733. // The driver signing code may have associated the queue to the SP_DEVINSTALL_PARAMS.
  1734. // We've finished with this and need to remove the queue from the SP_DEVINSTALL_PARAMS before we delete it.
  1735. //
  1736. SP_DEVINSTALL_PARAMS DevInstallParams = {0};
  1737. DevInstallParams.cbSize = sizeof(DevInstallParams);
  1738. if(SetupDiGetDeviceInstallParams(hDevInfo,
  1739. NULL,
  1740. &DevInstallParams))
  1741. {
  1742. if(DevInstallParams.FileQueue == CopyQueue)
  1743. {
  1744. DevInstallParams.FlagsEx &= ~DI_FLAGSEX_ALTPLATFORM_DRVSEARCH;
  1745. DevInstallParams.Flags &= ~DI_NOVCP;
  1746. DevInstallParams.FileQueue = INVALID_HANDLE_VALUE;
  1747. SetupDiSetDeviceInstallParams(hDevInfo,
  1748. NULL,
  1749. &DevInstallParams);
  1750. }
  1751. }
  1752. //
  1753. // Now free up the queue.
  1754. //
  1755. if ( CopyQueue != INVALID_HANDLE_VALUE )
  1756. {
  1757. SetupCloseFileQueue(CopyQueue);
  1758. }
  1759. if ( QueueContext )
  1760. {
  1761. SetupTermDefaultQueueCallback(QueueContext);
  1762. }
  1763. if( dwAddDrvFlags & APD_COPY_FROM_DIRECTORY )
  1764. {
  1765. //
  1766. // if this was an installation with a path derived from the Pnp-ID,
  1767. // do not cleanup, else users will get prompted for media when they re-pnp the driver
  1768. //
  1769. if ( ! (pLocalData->Flags & LOCALDATAFLAG_PNP_DIR_INSTALL) )
  1770. {
  1771. CleanupUniqueScratchDirectory( pszServerName, platform );
  1772. }
  1773. }
  1774. else
  1775. {
  1776. CleanupScratchDirectory( pszServerName, platform );
  1777. }
  1778. }
  1779. //
  1780. // Return the new driver name and the blocking flags if they were asked for.
  1781. //
  1782. if (ppszNewDriverName)
  1783. {
  1784. *ppszNewDriverName = pszNewDriverName;
  1785. }
  1786. else if (pszNewDriverName)
  1787. {
  1788. LocalFreeMem(pszNewDriverName);
  1789. }
  1790. if (pBlockingStatus)
  1791. {
  1792. *pBlockingStatus = fBlockingStatus;
  1793. }
  1794. return dwStatus;
  1795. }
  1796. DWORD
  1797. InstallDriverAfterPromptingForInf(
  1798. IN PLATFORM platform,
  1799. IN LPCTSTR pszServerName,
  1800. IN HWND hwnd,
  1801. IN LPCTSTR pszModelName,
  1802. IN DWORD dwVersion,
  1803. IN OUT TCHAR szInfPath[MAX_PATH],
  1804. IN DWORD dwInstallFlags,
  1805. IN DWORD dwAddDrvFlags,
  1806. OUT LPTSTR *ppszNewDriverName
  1807. )
  1808. {
  1809. DWORD dwRet, dwTitleId, dwMediaId;
  1810. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  1811. PPSETUP_LOCAL_DATA pLocalData = NULL;
  1812. LPTSTR pszFileSrcPath = NULL;
  1813. DWORD dwBlockingStatus = BSP_PRINTER_DRIVER_OK;
  1814. switch (platform) {
  1815. case PlatformAlpha:
  1816. dwTitleId = IDS_DRIVERS_FOR_NT4_ALPHA;
  1817. break;
  1818. case PlatformX86:
  1819. if( dwVersion == 2 )
  1820. {
  1821. dwTitleId = IDS_DRIVERS_FOR_NT4_X86;
  1822. }
  1823. else
  1824. {
  1825. dwTitleId = IDS_DRIVERS_FOR_X86;
  1826. }
  1827. break;
  1828. case PlatformMIPS:
  1829. dwTitleId = IDS_DRIVERS_FOR_NT4_MIPS;
  1830. break;
  1831. case PlatformPPC:
  1832. dwTitleId = IDS_DRIVERS_FOR_NT4_PPC;
  1833. break;
  1834. case PlatformIA64:
  1835. dwTitleId = IDS_DRIVERS_FOR_IA64;
  1836. break;
  1837. default:
  1838. ASSERT(0);
  1839. return ERROR_INVALID_PARAMETER;
  1840. }
  1841. dwMediaId = IDS_PROMPT_ALT_PLATFORM_DRIVER;
  1842. dwInstallFlags |= DRVINST_ALT_PLATFORM_INSTALL | DRVINST_NO_WARNING_PROMPT;
  1843. hDevInfo = GetInfAndBuildDrivers(hwnd,
  1844. dwTitleId,
  1845. dwMediaId,
  1846. szInfPath,
  1847. dwInstallFlags,
  1848. platform, dwVersion,
  1849. pszModelName,
  1850. &pLocalData,
  1851. &pszFileSrcPath);
  1852. if ( hDevInfo == INVALID_HANDLE_VALUE ) {
  1853. dwRet = GetLastError();
  1854. goto Cleanup;
  1855. }
  1856. //
  1857. // we want the printupg prompt
  1858. //
  1859. dwInstallFlags &= ~DRVINST_NO_WARNING_PROMPT;
  1860. dwRet = InstallDriverFromCurrentInf(hDevInfo,
  1861. pLocalData,
  1862. hwnd,
  1863. platform,
  1864. dwVersion,
  1865. pszServerName,
  1866. INVALID_HANDLE_VALUE,
  1867. NULL,
  1868. NULL,
  1869. 0,
  1870. szInfPath,
  1871. dwInstallFlags,
  1872. dwAddDrvFlags,
  1873. pszFileSrcPath,
  1874. ppszNewDriverName,
  1875. &dwBlockingStatus);
  1876. if (((ERROR_PRINTER_DRIVER_BLOCKED == dwRet) || (ERROR_PRINTER_DRIVER_WARNED == dwRet)) &&
  1877. (ppszNewDriverName && *ppszNewDriverName) &&
  1878. (dwBlockingStatus & BSP_PRINTER_DRIVER_REPLACED))
  1879. {
  1880. //
  1881. // We pass NULL instead of pLocalData here since InstallDriverAfterPromptingForInf
  1882. // is not called when we want to setup a printer queue, but when the platform
  1883. // and/or version of the driver matches that of our local platform or version
  1884. // does not match our dwMajorVersion (note when installing a printer queue
  1885. // through the APW that uses an NT4 driver dwVersion will be set to 3 so
  1886. // InstallDriverFromCurrentInf will be called instead!). Thus we do not
  1887. // need to pass back e.g. print processor, color profiles and vendor setup dlls.
  1888. //
  1889. dwRet = InstallReplacementDriver(hwnd,
  1890. pszServerName,
  1891. *ppszNewDriverName,
  1892. platform,
  1893. dwVersion,
  1894. dwInstallFlags,
  1895. dwAddDrvFlags,
  1896. NULL);
  1897. }
  1898. else if (ppszNewDriverName && *ppszNewDriverName)
  1899. {
  1900. LocalFreeMem(*ppszNewDriverName);
  1901. *ppszNewDriverName = NULL;
  1902. }
  1903. Cleanup:
  1904. if (pszFileSrcPath)
  1905. {
  1906. //
  1907. // we did the NT4 copy/expand thing -> delete the expanded inf!
  1908. //
  1909. if(SUCCEEDED(StringCchCat(szInfPath, MAX_PATH, _T("ntprint.inf"))))
  1910. {
  1911. DeleteFile(szInfPath);
  1912. }
  1913. LocalFreeMem(pszFileSrcPath);
  1914. }
  1915. if ( hDevInfo != INVALID_HANDLE_VALUE )
  1916. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  1917. DestroyLocalData(pLocalData);
  1918. return dwRet;
  1919. }
  1920. const TCHAR gcszNTPrint[] = _TEXT("inf\\ntprint.inf");
  1921. DWORD GetNtprintDotInfPath(LPTSTR pszNTPrintInf, DWORD len)
  1922. {
  1923. DWORD dwLastError = ERROR_INVALID_DATA, dwSize, dwRemainingSize;
  1924. LPTSTR pData;
  1925. //
  1926. // Get %windir%
  1927. // If the return is 0 - the call failed.
  1928. // If the return is greater than MAX_PATH we want to fail as something has managed to change
  1929. // the system dir to longer than MAX_PATH which is invalid.
  1930. //
  1931. dwSize = GetSystemWindowsDirectory( pszNTPrintInf, len );
  1932. if( !dwSize || dwSize > len )
  1933. goto Cleanup;
  1934. //
  1935. // If we don't end in a \ then add one.
  1936. //
  1937. dwSize = _tcslen(pszNTPrintInf);
  1938. pData = &(pszNTPrintInf[ dwSize-1 ]);
  1939. if (*pData++ != _TEXT('\\') )
  1940. {
  1941. if (dwSize + 1 < len)
  1942. {
  1943. *(pData++) = _TEXT('\\');
  1944. dwSize++;
  1945. }
  1946. else
  1947. {
  1948. goto Cleanup;
  1949. }
  1950. }
  1951. dwRemainingSize = len - dwSize;
  1952. *(pData) = 0;
  1953. dwSize += _tcslen( gcszNTPrint ) + 1;
  1954. //
  1955. // If what we've got sums up to a longer string than the allowable length MAX_PATH - fail
  1956. //
  1957. if ( dwSize > len )
  1958. goto Cleanup;
  1959. //
  1960. // Copy the inf\ntprint.inf string onto the end of the %windir%\ string.
  1961. //
  1962. StringCchCopy( pData, dwRemainingSize, gcszNTPrint);
  1963. dwLastError = ERROR_SUCCESS;
  1964. Cleanup:
  1965. if (dwLastError != ERROR_SUCCESS)
  1966. {
  1967. //
  1968. // Got here due to some error. Get what the called function set the last error to.
  1969. // If the function set a success, set some error code.
  1970. //
  1971. if ( (dwLastError = GetLastError()) == ERROR_SUCCESS)
  1972. {
  1973. dwLastError = ERROR_INVALID_DATA;
  1974. }
  1975. if (len)
  1976. {
  1977. pszNTPrintInf[0] = 0;
  1978. }
  1979. }
  1980. return dwLastError;
  1981. }
  1982. DWORD
  1983. InstallReplacementDriver(HWND hwnd,
  1984. LPCTSTR pszServerName,
  1985. LPCTSTR pszModelName,
  1986. PLATFORM platform,
  1987. DWORD version,
  1988. DWORD dwInstallFlags,
  1989. DWORD dwAddDrvFlags,
  1990. PPSETUP_LOCAL_DATA pOldLocalData)
  1991. /*++
  1992. Routine Description:
  1993. Install an inbox replacement driver for blocked/warned drivers.
  1994. Arguments:
  1995. hwnd : parent windows handle.
  1996. pszServerName : Server name to which we are installing
  1997. pszModelName : driver model name to install
  1998. Return Value:
  1999. ERROR_SUCCESS on success, error code otherwise
  2000. --*/
  2001. {
  2002. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  2003. PPSETUP_LOCAL_DATA pLocalData = NULL;
  2004. TCHAR szNtprintDotInf[MAX_PATH];
  2005. DWORD dwLastError;
  2006. if ((dwLastError = GetNtprintDotInfPath(szNtprintDotInf, COUNTOF(szNtprintDotInf))) != ERROR_SUCCESS)
  2007. {
  2008. goto Cleanup;
  2009. }
  2010. if ((hDevInfo = PSetupCreatePrinterDeviceInfoList(NULL)) != INVALID_HANDLE_VALUE &&
  2011. PSetupBuildDriversFromPath(hDevInfo, szNtprintDotInf, TRUE) &&
  2012. PSetupPreSelectDriver(hDevInfo, NULL, pszModelName) &&
  2013. (pLocalData = BuildInternalData(hDevInfo, NULL)) != NULL &&
  2014. ParseInf(hDevInfo, pLocalData, platform, NULL, dwInstallFlags, FALSE))
  2015. {
  2016. //
  2017. // Don't prompt for blocked or warned drivers.
  2018. //
  2019. dwInstallFlags |= DRVINST_NO_WARNING_PROMPT;
  2020. dwLastError = InstallDriverFromCurrentInf( hDevInfo,
  2021. pLocalData,
  2022. hwnd,
  2023. platform,
  2024. version,
  2025. pszServerName,
  2026. INVALID_HANDLE_VALUE,
  2027. NULL,
  2028. NULL,
  2029. 0,
  2030. szNtprintDotInf,
  2031. dwInstallFlags,
  2032. dwAddDrvFlags,
  2033. NULL,
  2034. NULL,
  2035. NULL);
  2036. }
  2037. else
  2038. {
  2039. dwLastError = GetLastError();
  2040. }
  2041. Cleanup:
  2042. if(pOldLocalData && pLocalData)
  2043. {
  2044. //
  2045. // The following code is almost identical to PSetupDestroySelectedDriverInfo,
  2046. // only that we do not free the memory allocated for the pOldLocalData structure.
  2047. //
  2048. if ( pLocalData->Flags & VALID_INF_INFO )
  2049. FreeStructurePointers((LPBYTE)&pOldLocalData->InfInfo,
  2050. InfInfoOffsets,
  2051. FALSE);
  2052. if ( pLocalData->Flags & VALID_PNP_INFO )
  2053. FreeStructurePointers((LPBYTE)&pOldLocalData->PnPInfo,
  2054. PnPInfoOffsets,
  2055. FALSE);
  2056. FreeStructurePointers((LPBYTE)pOldLocalData, LocalDataOffsets, FALSE);
  2057. //
  2058. // Now copy the new data into the old pLocalData structure
  2059. //
  2060. *pOldLocalData = *pLocalData;
  2061. }
  2062. else if(pLocalData)
  2063. {
  2064. PSetupDestroySelectedDriverInfo(pLocalData);
  2065. }
  2066. //
  2067. // Release the driver setup parameter handle.
  2068. //
  2069. if(hDevInfo != INVALID_HANDLE_VALUE)
  2070. {
  2071. PSetupDestroyPrinterDeviceInfoList( hDevInfo );
  2072. }
  2073. return dwLastError;
  2074. }
  2075. //
  2076. // Paths where we search for the driver files
  2077. //
  2078. SPLPLATFORMINFO szPlatformExtn[] = {
  2079. { TEXT("\\alpha") },
  2080. { TEXT("\\i386") },
  2081. { TEXT("\\mips") },
  2082. { TEXT("\\ppc") },
  2083. { TEXT("") },
  2084. { TEXT("\\ia64") }
  2085. };
  2086. VOID
  2087. GetCDRomDrive(
  2088. TCHAR szDrive[5]
  2089. )
  2090. {
  2091. DWORD dwDrives;
  2092. INT iIndex;
  2093. szDrive[1] = TEXT(':');
  2094. szDrive[2] = TEXT('\\');
  2095. szDrive[3] = TEXT('\0');
  2096. dwDrives = GetLogicalDrives();
  2097. for ( iIndex = 0 ; iIndex < 26 ; ++iIndex )
  2098. if ( dwDrives & (1 << iIndex) ) {
  2099. szDrive[0] = TEXT('A') + iIndex;
  2100. if ( GetDriveType(szDrive) == DRIVE_CDROM )
  2101. goto Done;
  2102. }
  2103. szDrive[0] = TEXT('A');
  2104. Done:
  2105. return;
  2106. }
  2107. BOOL
  2108. BuildPathToPrompt(
  2109. IN HDEVINFO hDevInfo,
  2110. IN PPSETUP_LOCAL_DATA pLocalData,
  2111. IN PLATFORM platform,
  2112. IN DWORD dwVersion,
  2113. IN TCHAR szPathOut[MAX_PATH]
  2114. )
  2115. /*++
  2116. --*/
  2117. {
  2118. LPTSTR pszExtn = TEXT("");
  2119. DWORD dwLen;
  2120. //
  2121. // NTRAID#NTBUG9-527971-2002/03/06-mikaelho
  2122. // The function BuildPathToPromp in ntprint.dll does not take into account that x86 NT4 drivers
  2123. // are delivered with the OS (on IA64 server installations) and will always prompt you for driver,
  2124. // even if the OS was installed from a network share and we know where to retrieve the driver.
  2125. //
  2126. //
  2127. // The CD we installed from OS can have only the following drivers:
  2128. // -- NT5 same platform drivers
  2129. // -- NT4 same platform drivers (only on server CD)
  2130. // -- Win9x drivers (only on server CD)
  2131. //
  2132. if ( (platform == MyPlatform && dwVersion >= 2) ||
  2133. platform == PlatformWin95 ) {
  2134. GetDriverPath(hDevInfo, pLocalData, szPathOut);
  2135. } else {
  2136. GetCDRomDrive(szPathOut);
  2137. }
  2138. if ( dwVersion >= dwThisMajorVersion && platform == MyPlatform )
  2139. return TRUE;
  2140. //
  2141. // append a backslash if needed
  2142. //
  2143. dwLen = lstrlen(szPathOut);
  2144. if (dwLen && (dwLen + 1 < MAX_PATH) && (szPathOut[dwLen-1] != TEXT('\\')))
  2145. {
  2146. szPathOut[dwLen] = TEXT('\\');
  2147. szPathOut[++dwLen] = 0;
  2148. }
  2149. switch (dwVersion) {
  2150. case 0:
  2151. if ( platform == PlatformWin95 )
  2152. pszExtn = TEXT("printers\\Win9X\\");
  2153. //
  2154. // For NT 3.51 and 3.1 we do not include drivers on CD, so
  2155. // nothing to add to the base path
  2156. //
  2157. case 1:
  2158. break;
  2159. case 2:
  2160. if ( platform == PlatformX86 ) // Alpha is now on the NT4.0 CD
  2161. pszExtn = TEXT("printers\\NT4\\");
  2162. break;
  2163. case 3:
  2164. break;
  2165. default:
  2166. ASSERT(dwVersion <= 3);
  2167. SetLastError(ERROR_INVALID_PARAMETER);
  2168. return FALSE;
  2169. }
  2170. if ( dwLen + lstrlen(pszExtn) + lstrlen(szPlatformExtn[platform].pszName) + 1
  2171. > MAX_PATH ) {
  2172. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2173. return FALSE;
  2174. }
  2175. StringCchCat(szPathOut, MAX_PATH, pszExtn);
  2176. //
  2177. // Skip the leading \ of the platform extension as we have one already.
  2178. //
  2179. StringCchCat(szPathOut, MAX_PATH, &(szPlatformExtn[platform].pszName[1]));
  2180. return TRUE;
  2181. }
  2182. DWORD
  2183. PSetupInstallPrinterDriver(
  2184. IN HDEVINFO hDevInfo,
  2185. IN PPSETUP_LOCAL_DATA pLocalData,
  2186. IN LPCTSTR pszDriverName,
  2187. IN PLATFORM platform,
  2188. IN DWORD dwVersion,
  2189. IN LPCTSTR pszServerName,
  2190. IN HWND hwnd,
  2191. IN LPCTSTR pszDiskName,
  2192. IN LPCTSTR pszSource OPTIONAL,
  2193. IN DWORD dwInstallFlags,
  2194. IN DWORD dwAddDrvFlags,
  2195. OUT LPTSTR *ppszNewDriverName
  2196. )
  2197. /*++
  2198. Routine Description:
  2199. Copies all the necessary driver files to the printer driver directory so
  2200. that an AddPrinterDriver call could be made. . This function also prompt
  2201. user for disk if necessary, prompt in case of unsigned driver or if the
  2202. printer driver is warned or block. In addition to printer drivers it also
  2203. installs language monitors, Color Profiles and Print Processors.
  2204. Arguments:
  2205. hDevInfo : Handle to the printer class device information list
  2206. pLocalData : Gives information got by parsing the inf
  2207. pszDriverName : Printer driver name, used only if pLocalData is NULL
  2208. platform : Platform for which drivers need to be installed
  2209. dwVersion : Version of the driver to install
  2210. pszServerName : Server on which driver should be installed
  2211. hwnd : Parent windows handle for UI
  2212. pszDiskName : Disk name for prompting
  2213. pszSource : If provided this is a flat directory having all the files
  2214. dwAddDrvFlags : Flags for AddPrinterDriverEx
  2215. Return Value:
  2216. On succesfully copying files ERROR_SUCCESS, else the error code
  2217. --*/
  2218. {
  2219. BOOL bDeleteLocalData = pLocalData == NULL;
  2220. DWORD dwRet;
  2221. TCHAR szPath[MAX_PATH];
  2222. szPath[0] = 0;
  2223. if( !( (dwVersion == 0) || (dwVersion == 2) || (dwVersion == 3) ) )
  2224. {
  2225. SetLastError(dwRet = ERROR_INVALID_PARAMETER);
  2226. return dwRet;
  2227. }
  2228. if ( pszSource && !*pszSource )
  2229. pszSource = NULL;
  2230. if ( pLocalData )
  2231. {
  2232. ASSERT(pLocalData->signature == PSETUP_SIGNATURE && !pszDriverName);
  2233. }
  2234. else
  2235. {
  2236. ASSERT(pszDriverName && *pszDriverName);
  2237. }
  2238. //
  2239. // If FLATSHARE bit is set then a path should be given
  2240. //
  2241. ASSERT( (dwInstallFlags & DRVINST_FLATSHARE) == 0 || pszSource != NULL );
  2242. Retry:
  2243. //
  2244. // If a path is given use it. Otherwise if this is a driver for different
  2245. // version or platform then we determine the path, otherwise let SetupAPI determine the
  2246. // path.
  2247. //
  2248. if ( dwVersion != dwThisMajorVersion || platform != MyPlatform ) {
  2249. // If this is not an NT5 driver and we are asked to get it
  2250. // from the web, then just return.....
  2251. if ( pLocalData &&
  2252. ( pLocalData->DrvInfo.Flags & SDFLAG_CDM_DRIVER ) )
  2253. return ERROR_SUCCESS;
  2254. if ( pszSource )
  2255. StringCchCopy(szPath, COUNTOF(szPath), pszSource);
  2256. else if ( !BuildPathToPrompt(hDevInfo,
  2257. pLocalData,
  2258. platform,
  2259. dwVersion,
  2260. szPath) ) {
  2261. if ( (dwRet = GetLastError()) == ERROR_SUCCESS )
  2262. dwRet = STG_E_UNKNOWN;
  2263. return dwRet;
  2264. }
  2265. }
  2266. //
  2267. // For Win95 drivers we need to parse their INFs,
  2268. // For non native environemnt dirvers ask user for path
  2269. //
  2270. if ( platform == PlatformWin95 ) {
  2271. if ( pLocalData ) {
  2272. //
  2273. // Parse the inf so that we can pick up any
  2274. // previous names entries and use them.
  2275. //
  2276. if ( !ParseInf(hDevInfo, pLocalData, MyPlatform,
  2277. pszServerName, dwInstallFlags, FALSE) )
  2278. return GetLastError();
  2279. dwRet = InstallWin95Driver(hwnd,
  2280. pLocalData->DrvInfo.pszModelName,
  2281. pLocalData->DrvInfo.pszzPreviousNames,
  2282. (pLocalData->DrvInfo.Flags &
  2283. SDFLAG_PREVNAME_SECTION_FOUND),
  2284. pszServerName,
  2285. szPath,
  2286. pszDiskName,
  2287. dwInstallFlags,
  2288. dwAddDrvFlags);
  2289. } else {
  2290. dwRet = InstallWin95Driver(hwnd,
  2291. pszDriverName,
  2292. NULL,
  2293. TRUE, // Exact model name match only
  2294. pszServerName,
  2295. szPath,
  2296. pszDiskName,
  2297. dwInstallFlags,
  2298. dwAddDrvFlags);
  2299. }
  2300. } else if ( dwVersion != dwThisMajorVersion || platform != MyPlatform ) {
  2301. dwRet = InstallDriverAfterPromptingForInf(
  2302. platform,
  2303. pszServerName,
  2304. hwnd,
  2305. pLocalData ?
  2306. pLocalData->DrvInfo.pszModelName :
  2307. pszDriverName,
  2308. dwVersion,
  2309. szPath,
  2310. dwInstallFlags,
  2311. dwAddDrvFlags,
  2312. ppszNewDriverName);
  2313. } else if ( pLocalData &&
  2314. (pLocalData->DrvInfo.Flags & SDFLAG_CDM_DRIVER) ) {
  2315. dwRet = PSetupInstallPrinterDriverFromTheWeb(hDevInfo,
  2316. pLocalData,
  2317. platform,
  2318. pszServerName,
  2319. &OsVersionInfo,
  2320. hwnd,
  2321. pszSource);
  2322. } else {
  2323. if ( !pLocalData )
  2324. {
  2325. pLocalData = PSetupDriverInfoFromName(hDevInfo, pszDriverName);
  2326. }
  2327. if ( pLocalData )
  2328. {
  2329. DWORD dwBlockingStatus = BSP_PRINTER_DRIVER_OK;
  2330. dwRet = InstallDriverFromCurrentInf(hDevInfo,
  2331. pLocalData,
  2332. hwnd,
  2333. platform,
  2334. dwVersion,
  2335. pszServerName,
  2336. INVALID_HANDLE_VALUE,
  2337. NULL,
  2338. NULL,
  2339. 0,
  2340. pszSource,
  2341. dwInstallFlags,
  2342. dwAddDrvFlags,
  2343. NULL,
  2344. ppszNewDriverName,
  2345. &dwBlockingStatus);
  2346. if ((ppszNewDriverName && *ppszNewDriverName) &&
  2347. (dwBlockingStatus & BSP_PRINTER_DRIVER_REPLACED))
  2348. {
  2349. dwRet = InstallReplacementDriver(hwnd,
  2350. pszServerName,
  2351. *ppszNewDriverName,
  2352. platform,
  2353. dwVersion,
  2354. dwInstallFlags,
  2355. dwAddDrvFlags,
  2356. pLocalData);
  2357. }
  2358. else if (ppszNewDriverName && *ppszNewDriverName)
  2359. {
  2360. LocalFreeMem(*ppszNewDriverName);
  2361. *ppszNewDriverName = NULL;
  2362. }
  2363. }
  2364. else
  2365. {
  2366. dwRet = GetLastError();
  2367. }
  2368. }
  2369. if (
  2370. (dwRet == ERROR_EXE_MACHINE_TYPE_MISMATCH) &&
  2371. !(dwInstallFlags & DRVINST_PROMPTLESS)
  2372. )
  2373. {
  2374. int i;
  2375. TCHAR szTitle[256], szMsg[256];
  2376. LoadString(ghInst,
  2377. IDS_INVALID_DRIVER,
  2378. szTitle,
  2379. SIZECHARS(szTitle));
  2380. LoadString(ghInst,
  2381. IDS_WRONG_ARCHITECTURE,
  2382. szMsg,
  2383. SIZECHARS(szMsg));
  2384. i = MessageBox(hwnd,
  2385. szMsg,
  2386. szTitle,
  2387. MB_RETRYCANCEL | MB_ICONSTOP | MB_DEFBUTTON1 | MB_APPLMODAL);
  2388. if ( i == IDRETRY )
  2389. {
  2390. if ( bDeleteLocalData )
  2391. {
  2392. DestroyLocalData(pLocalData);
  2393. pLocalData = NULL;
  2394. }
  2395. goto Retry;
  2396. }
  2397. else
  2398. {
  2399. SetLastError(dwRet =ERROR_CANCELLED);
  2400. }
  2401. }
  2402. if ( bDeleteLocalData )
  2403. DestroyLocalData(pLocalData);
  2404. return dwRet;
  2405. }
  2406. //
  2407. // SCAN_INFO structure is used with SetupScanFileQueue to find dependent files
  2408. // and ICM files
  2409. //
  2410. typedef struct _SCAN_INFO {
  2411. BOOL bWin95;
  2412. PPSETUP_LOCAL_DATA pLocalData;
  2413. DWORD cchDependentFiles, cchICMFiles;
  2414. DWORD cchDriverDir, cchColorDir;
  2415. LPTSTR p1, p2;
  2416. TCHAR szDriverDir[MAX_PATH], szColorDir[MAX_PATH];
  2417. } SCAN_INFO, *PSCAN_INFO;
  2418. UINT
  2419. DriverInfoCallback(
  2420. IN PVOID pContext,
  2421. IN UINT Notification,
  2422. IN UINT_PTR Param1,
  2423. IN UINT_PTR Param2
  2424. )
  2425. /*++
  2426. Routine Description:
  2427. This callback routine is used with SetupScanFileQueue to findout the
  2428. dependent files and ICM files associated in an INF. All files going to the
  2429. printer driver directory are dependent files in DRIVER_INFO_6, and all
  2430. files goint to the Color directory are ICM files.
  2431. We use SetupScanFileQueue twice. We find the size of the buffers required
  2432. for the multi-sz fields in the first pass. After allocating buffers of size
  2433. found in first pass second pass is used to copy the strings and build the
  2434. multi-sz fields.
  2435. Arguments:
  2436. pContext : Gives the SCAN_INFO structure
  2437. Notification : Ignored
  2438. Param1 : Gives the target file name
  2439. Param2 : Ignored
  2440. Return Value:
  2441. Win32 error code
  2442. --*/
  2443. {
  2444. DWORD dwLen;
  2445. LPTSTR pszTarget = (LPTSTR)Param1, pszFileName;
  2446. PSCAN_INFO pScanInfo = (PSCAN_INFO)pContext;
  2447. LPDRIVER_INFO_6 pDriverInfo6;
  2448. pszFileName = FileNamePart(pszTarget);
  2449. if ( pszFileName )
  2450. {
  2451. dwLen = lstrlen(pszFileName) + 1;
  2452. if ( !lstrncmpi(pszTarget,
  2453. gpszSkipDir,
  2454. lstrlen( gpszSkipDir ) ) )
  2455. goto Done;
  2456. if ( !lstrncmpi(pszTarget,
  2457. pScanInfo->szDriverDir,
  2458. pScanInfo->cchDriverDir) ) {
  2459. pDriverInfo6 = &pScanInfo->pLocalData->InfInfo.DriverInfo6;
  2460. //
  2461. // On NT dependent file list will not include files appearing as
  2462. // other DRIVER_INFO_6 fields
  2463. //
  2464. if ( !pScanInfo->bWin95 &&
  2465. ( !lstrcmpi(pszFileName, pDriverInfo6->pDriverPath) ||
  2466. !lstrcmpi(pszFileName, pDriverInfo6->pConfigFile) ||
  2467. !lstrcmpi(pszFileName, pDriverInfo6->pDataFile) ||
  2468. ( pDriverInfo6->pHelpFile &&
  2469. !lstrcmpi(pszFileName, pDriverInfo6->pHelpFile))) )
  2470. goto Done;
  2471. //
  2472. // If pointer is not NULL this is pass 2
  2473. //
  2474. if ( pScanInfo->p1 ) {
  2475. StringCchCopy(pScanInfo->p1, dwLen, pszFileName);
  2476. pScanInfo->p1 += dwLen;
  2477. } else {
  2478. pScanInfo->cchDependentFiles += dwLen;
  2479. }
  2480. } else if ( !lstrncmpi(pszTarget,
  2481. pScanInfo->szColorDir,
  2482. pScanInfo->cchColorDir) ) {
  2483. //
  2484. // If pointer is not NULL this is pass 2
  2485. //
  2486. if ( pScanInfo->p2 ) {
  2487. StringCchCopy(pScanInfo->p2, dwLen, pszFileName);
  2488. pScanInfo->p2 += dwLen;
  2489. } else {
  2490. pScanInfo->cchICMFiles += dwLen;
  2491. }
  2492. }
  2493. }
  2494. else
  2495. {
  2496. return ERROR_INVALID_PARAMETER;
  2497. }
  2498. Done:
  2499. return NO_ERROR;
  2500. }
  2501. BOOL
  2502. InfGetDependentFilesAndICMFiles(
  2503. IN HDEVINFO hDevInfo,
  2504. IN HINF hInf,
  2505. IN BOOL bWin95,
  2506. IN OUT PPSETUP_LOCAL_DATA pLocalData,
  2507. IN PLATFORM platform,
  2508. IN LPCTSTR pszServerName,
  2509. IN DWORD dwInstallFlags,
  2510. IN LPCTSTR pszSectionNameWithExt,
  2511. IN OUT LPDWORD pcchSize
  2512. )
  2513. /*++
  2514. Routine Description:
  2515. Findout the dependent files for the DRIVER_INFO_6 and the ICM files
  2516. for the selected driver
  2517. This is done by simulating the install operation by create a setup
  2518. queue to do the install operations and scanning the queue to find out
  2519. where files are getting copied to
  2520. Dependent files are those getting copied to driver scratch directory
  2521. without including other DRIVER_INFO_6 fields like pDriverPath. For Win95
  2522. case all files getting copied to the driver directory are dependent files.
  2523. ICM files are those getting copied to the color directory
  2524. Arguments:
  2525. hInf : INF handle
  2526. bWin95 : TRUE if it is a Win95 INF
  2527. pLocalData : INF parsing information
  2528. pszSectionNameWithExt : Section name with extension for install
  2529. pcchSize : Size needed for DRIVER_INFO_6 and strings in it
  2530. Return Value:
  2531. TRUE on success, FALSE on error
  2532. --*/
  2533. {
  2534. BOOL bRet = FALSE;
  2535. DWORD dwResult;
  2536. PSCAN_INFO pScanInfo = NULL;
  2537. HSPFILEQ ScanQueue = INVALID_HANDLE_VALUE;
  2538. LPTSTR ppszDepFiles = NULL,
  2539. pszzICMFiles = NULL;
  2540. PSP_DEVINSTALL_PARAMS pStoreDevInstallParams = NULL;
  2541. PSP_DEVINSTALL_PARAMS pDevInstallParams = NULL;
  2542. SP_ALTPLATFORM_INFO AltPlat_Info = {0};
  2543. POSVERSIONINFO pOSVer = NULL;
  2544. pStoreDevInstallParams = LocalAllocMem(sizeof(SP_DEVINSTALL_PARAMS));
  2545. if(!pStoreDevInstallParams)
  2546. {
  2547. goto Cleanup;
  2548. }
  2549. pDevInstallParams = LocalAllocMem(sizeof(SP_DEVINSTALL_PARAMS));
  2550. if(!pDevInstallParams)
  2551. {
  2552. goto Cleanup;
  2553. }
  2554. pOSVer = LocalAllocMem(sizeof(OSVERSIONINFO));
  2555. if(!pOSVer)
  2556. {
  2557. goto Cleanup;
  2558. }
  2559. pScanInfo = LocalAllocMem(sizeof(SCAN_INFO));
  2560. if(!pScanInfo)
  2561. {
  2562. goto Cleanup;
  2563. }
  2564. pScanInfo->p1 = pScanInfo->p2 = NULL;
  2565. pScanInfo->cchDependentFiles = pScanInfo->cchICMFiles = 0;
  2566. pScanInfo->cchColorDir = sizeof(pScanInfo->szColorDir);
  2567. pScanInfo->cchDriverDir = sizeof(pScanInfo->szDriverDir);
  2568. if ( !GetColorDirectory( pszServerName, pScanInfo->szColorDir, &pScanInfo->cchColorDir) ||
  2569. !GetSystemDirectory(pScanInfo->szDriverDir, (pScanInfo->cchDriverDir / sizeof(TCHAR)) ) ) {
  2570. goto Cleanup;
  2571. }
  2572. //
  2573. // Set pScanInfo->cchColorDir to char count of pScanInfo->szColorDir without \0
  2574. //
  2575. pScanInfo->cchColorDir /= sizeof(TCHAR);
  2576. --pScanInfo->cchColorDir;
  2577. //
  2578. // Win95 INFs tell setup to copy the driver files to system32 directory
  2579. // NT INFs expect install programs to set the target using
  2580. // SetupSetDirectoryId
  2581. //
  2582. if ( bWin95 ) {
  2583. pScanInfo->cchDriverDir = lstrlen(pScanInfo->szDriverDir);
  2584. } else {
  2585. if ( !GetPrinterDriverDirectory((LPTSTR)pszServerName,
  2586. PlatformEnv[platform].pszName,
  2587. 1,
  2588. (LPBYTE)pScanInfo->szDriverDir,
  2589. pScanInfo->cchDriverDir,
  2590. &pScanInfo->cchDriverDir) )
  2591. goto Cleanup;
  2592. //
  2593. // Set pScanInfo->cchDriverDir to char count of pScanInfo->szDriverDir
  2594. // without \0
  2595. //
  2596. pScanInfo->cchDriverDir /= sizeof(TCHAR);
  2597. --pScanInfo->cchDriverDir;
  2598. }
  2599. //
  2600. // Inf MAY refer to another one (like layout.inf)
  2601. //
  2602. SetupOpenAppendInfFile(NULL, hInf, NULL);
  2603. pScanInfo->bWin95 = bWin95;
  2604. pScanInfo->pLocalData = pLocalData;
  2605. ScanQueue = SetupOpenFileQueue();
  2606. if (ScanQueue == INVALID_HANDLE_VALUE)
  2607. {
  2608. goto Cleanup;
  2609. }
  2610. pDevInstallParams->cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  2611. if(!SetupDiGetDeviceInstallParams(hDevInfo,
  2612. NULL,
  2613. pDevInstallParams))
  2614. {
  2615. goto Cleanup;
  2616. }
  2617. if(!GetOSVersion(pszServerName, pOSVer))
  2618. {
  2619. goto Cleanup;
  2620. }
  2621. //
  2622. // Save the current config...
  2623. //
  2624. memcpy(pStoreDevInstallParams, pDevInstallParams, sizeof(SP_DEVINSTALL_PARAMS));
  2625. pDevInstallParams->FlagsEx |= DI_FLAGSEX_ALTPLATFORM_DRVSEARCH;
  2626. pDevInstallParams->Flags |= DI_NOVCP;
  2627. pDevInstallParams->FileQueue = ScanQueue;
  2628. AltPlat_Info.cbSize = sizeof(SP_ALTPLATFORM_INFO);
  2629. AltPlat_Info.MajorVersion = pOSVer->dwMajorVersion;
  2630. AltPlat_Info.MinorVersion = pOSVer->dwMinorVersion;
  2631. AltPlat_Info.Platform = PlatformArch[ platform ][OS_PLATFORM];
  2632. AltPlat_Info.ProcessorArchitecture = (WORD) PlatformArch[ platform ][PROCESSOR_ARCH];
  2633. AltPlat_Info.Reserved = 0;
  2634. AltPlat_Info.FirstValidatedMajorVersion = AltPlat_Info.MajorVersion;
  2635. AltPlat_Info.FirstValidatedMinorVersion = AltPlat_Info.MinorVersion;
  2636. if(!SetupDiSetDeviceInstallParams(hDevInfo,
  2637. NULL,
  2638. pDevInstallParams) ||
  2639. !SetupSetFileQueueAlternatePlatform(ScanQueue,
  2640. &AltPlat_Info,
  2641. NULL))
  2642. {
  2643. goto Cleanup;
  2644. }
  2645. //
  2646. // First pass using SetupScanFileQueue will find the sizes required
  2647. //
  2648. if ( !InstallAllInfSections( pLocalData,
  2649. platform,
  2650. pszServerName,
  2651. ScanQueue,
  2652. NULL,
  2653. dwInstallFlags,
  2654. hInf,
  2655. pszSectionNameWithExt ) ||
  2656. !SetupScanFileQueue(ScanQueue,
  2657. SPQ_SCAN_USE_CALLBACK,
  2658. 0,
  2659. DriverInfoCallback,
  2660. pScanInfo,
  2661. &dwResult) ) {
  2662. goto Cleanup;
  2663. }
  2664. if ( pScanInfo->cchDependentFiles ) {
  2665. ++pScanInfo->cchDependentFiles;
  2666. ppszDepFiles = (LPTSTR) LocalAllocMem(pScanInfo->cchDependentFiles * sizeof(TCHAR));
  2667. if ( !ppszDepFiles )
  2668. goto Cleanup;
  2669. pScanInfo->p1 = ppszDepFiles;
  2670. }
  2671. if ( pScanInfo->cchICMFiles ) {
  2672. ++pScanInfo->cchICMFiles;
  2673. pszzICMFiles = (LPTSTR) LocalAllocMem(pScanInfo->cchICMFiles * sizeof(TCHAR));
  2674. if ( !pszzICMFiles )
  2675. goto Cleanup;
  2676. pScanInfo->p2 = pszzICMFiles;
  2677. }
  2678. //
  2679. // Second call to SetupScanFileQueue build the actual multi-sz fields
  2680. //
  2681. bRet = SetupScanFileQueue(ScanQueue,
  2682. SPQ_SCAN_USE_CALLBACK,
  2683. 0,
  2684. DriverInfoCallback,
  2685. pScanInfo,
  2686. &dwResult);
  2687. Cleanup:
  2688. //
  2689. // Save the last error as it may get toasted by the following calls.
  2690. //
  2691. dwResult = GetLastError();
  2692. if ( ScanQueue != INVALID_HANDLE_VALUE )
  2693. {
  2694. if (pDevInstallParams)
  2695. {
  2696. pDevInstallParams->FlagsEx &= ~DI_FLAGSEX_ALTPLATFORM_DRVSEARCH;
  2697. pDevInstallParams->Flags &= ~DI_NOVCP;
  2698. pDevInstallParams->FileQueue = INVALID_HANDLE_VALUE;
  2699. if (!SetupDiSetDeviceInstallParams(hDevInfo, NULL, pDevInstallParams))
  2700. {
  2701. dwResult = (ERROR_SUCCESS == dwResult) ? GetLastError() : dwResult;
  2702. }
  2703. }
  2704. SetupCloseFileQueue(ScanQueue);
  2705. }
  2706. if (pStoreDevInstallParams)
  2707. {
  2708. if (pStoreDevInstallParams->cbSize == sizeof(SP_DEVINSTALL_PARAMS))
  2709. {
  2710. //
  2711. // Reset the HDEVINFO params.
  2712. //
  2713. SetupDiSetDeviceInstallParams(hDevInfo,
  2714. NULL,
  2715. pStoreDevInstallParams);
  2716. }
  2717. LocalFreeMem(pStoreDevInstallParams);
  2718. }
  2719. if ( bRet ) {
  2720. *pcchSize += pScanInfo->cchDependentFiles;
  2721. pLocalData->InfInfo.DriverInfo6.pDependentFiles = ppszDepFiles;
  2722. pLocalData->InfInfo.pszzICMFiles = pszzICMFiles;
  2723. } else {
  2724. LocalFreeMem(ppszDepFiles);
  2725. LocalFreeMem(pszzICMFiles);
  2726. }
  2727. if (pDevInstallParams)
  2728. {
  2729. LocalFreeMem(pDevInstallParams);
  2730. }
  2731. if (pOSVer)
  2732. {
  2733. LocalFreeMem(pOSVer);
  2734. }
  2735. if (pScanInfo)
  2736. {
  2737. LocalFreeMem(pScanInfo);
  2738. }
  2739. SetLastError(dwResult);
  2740. return bRet;
  2741. }
  2742. VOID
  2743. DestroyCodedownload(
  2744. PCODEDOWNLOADINFO pCodeDownLoadInfo
  2745. )
  2746. {
  2747. if ( pCodeDownLoadInfo ) {
  2748. pCodeDownLoadInfo->pfnClose(pCodeDownLoadInfo->hConnection);
  2749. if ( pCodeDownLoadInfo->hModule )
  2750. FreeLibrary(pCodeDownLoadInfo->hModule);
  2751. LocalFreeMem(pCodeDownLoadInfo);
  2752. }
  2753. }
  2754. BOOL
  2755. InitCodedownload(
  2756. HWND hwnd
  2757. )
  2758. {
  2759. BOOL bRet = FALSE;
  2760. PCODEDOWNLOADINFO pCDMInfo = NULL;
  2761. EnterCriticalSection(&CDMCritSect);
  2762. // We already have a context & function pointers
  2763. // So reuse them...
  2764. if (gpCodeDownLoadInfo)
  2765. {
  2766. LeaveCriticalSection(&CDMCritSect);
  2767. return TRUE;
  2768. }
  2769. pCDMInfo = (PCODEDOWNLOADINFO) LocalAllocMem(sizeof(CODEDOWNLOADINFO));
  2770. if ( !pCDMInfo )
  2771. goto Cleanup;
  2772. pCDMInfo->hModule = LoadLibraryUsingFullPath(TEXT("cdm.dll"));
  2773. if ( !pCDMInfo->hModule )
  2774. goto Cleanup;
  2775. (FARPROC)pCDMInfo->pfnOpen = GetProcAddress(pCDMInfo->hModule,
  2776. "OpenCDMContext");
  2777. (FARPROC)pCDMInfo->pfnDownload = GetProcAddress(pCDMInfo->hModule,
  2778. "DownloadUpdatedFiles");
  2779. (FARPROC)pCDMInfo->pfnClose = GetProcAddress(pCDMInfo->hModule,
  2780. "CloseCDMContext");
  2781. bRet = pCDMInfo->pfnOpen &&
  2782. pCDMInfo->pfnDownload &&
  2783. pCDMInfo->pfnClose;
  2784. if ( bRet )
  2785. pCDMInfo->hConnection = pCDMInfo->pfnOpen(hwnd);
  2786. Cleanup:
  2787. if ( !bRet ||
  2788. ( pCDMInfo && !pCDMInfo->hConnection ) ) {
  2789. DestroyCodedownload(pCDMInfo);
  2790. pCDMInfo = NULL;
  2791. bRet = FALSE;
  2792. }
  2793. if (bRet)
  2794. gpCodeDownLoadInfo = pCDMInfo;
  2795. LeaveCriticalSection(&CDMCritSect);
  2796. return bRet;
  2797. }
  2798. DWORD
  2799. PSetupInstallPrinterDriverFromTheWeb(
  2800. IN HDEVINFO hDevInfo,
  2801. IN PPSETUP_LOCAL_DATA pLocalData,
  2802. IN PLATFORM platform,
  2803. IN LPCTSTR pszServerName,
  2804. IN LPOSVERSIONINFO pOsVersionInfo,
  2805. IN HWND hwnd,
  2806. IN LPCTSTR pszSource
  2807. )
  2808. /*++
  2809. Routine Description:
  2810. Downloads driver files from server and installs it by calling
  2811. InstallDriverFromCurrentInf.
  2812. Arguments:
  2813. Return Value:
  2814. ERROR_SUCCESS is successful.
  2815. --*/
  2816. {
  2817. BOOL bRet = FALSE;
  2818. DWORD dwLen, dwReturn = ERROR_SUCCESS;
  2819. UINT uNeeded;
  2820. TCHAR szSourceDir[MAX_PATH];
  2821. DOWNLOADINFO DownLoadInfo;
  2822. PPSETUP_LOCAL_DATA pNewLocalData = NULL;
  2823. INT clpFileBufferLength = 0;
  2824. INT cProviderNameLength = 0;
  2825. INT cManufacturerNameLength = 0;
  2826. INT cDriverNameLength = 0;
  2827. ZeroMemory(&DownLoadInfo, sizeof(DownLoadInfo));
  2828. if (!pLocalData || !pOsVersionInfo)
  2829. {
  2830. SetLastError(dwReturn = ERROR_INVALID_PARAMETER);
  2831. goto Cleanup;
  2832. }
  2833. if ( !gpCodeDownLoadInfo )
  2834. goto Cleanup;
  2835. DownLoadInfo.dwDownloadInfoSize = sizeof(DownLoadInfo);
  2836. DownLoadInfo.localid = lcid;
  2837. // dwLen = lstrlen( cszWebNTPrintPkg );
  2838. dwLen = lstrlen(pLocalData->DrvInfo.pszHardwareID);
  2839. //
  2840. // lpHardwareIDs is multi-sz
  2841. //
  2842. if ( !(DownLoadInfo.lpHardwareIDs = LocalAllocMem((dwLen + 2 ) * sizeof(TCHAR))) )
  2843. goto Cleanup;
  2844. // lstrcpy(DownLoadInfo.lpHardwareIDs, cszWebNTPrintPkg );
  2845. StringCchCopy( (LPTSTR) DownLoadInfo.lpHardwareIDs, dwLen + 2, pLocalData->DrvInfo.pszHardwareID);
  2846. CopyMemory(&DownLoadInfo.OSVersionInfo,
  2847. pOsVersionInfo,
  2848. sizeof(OSVERSIONINFO));
  2849. // Assign the correct Processor Architecture to the download
  2850. DownLoadInfo.dwArchitecture = (WORD) PlatformArch[ platform ][PROCESSOR_ARCH];
  2851. DownLoadInfo.lpFile = NULL;
  2852. //
  2853. // Below we have to check if we have valid Provider, Manufacturer, and
  2854. // driver names and if this is the case then we have to prepare a
  2855. // MULTISZ including Provider, Manufacturer, and Driver Names,
  2856. // and to set a pointer to that MULTISZ into DownLoadInfo.lpFile
  2857. //
  2858. if (pLocalData->DrvInfo.pszProvider &&
  2859. pLocalData->DrvInfo.pszManufacturer &&
  2860. pLocalData->DrvInfo.pszModelName)
  2861. {
  2862. cProviderNameLength = lstrlen(pLocalData->DrvInfo.pszProvider);
  2863. if (cProviderNameLength)
  2864. {
  2865. cManufacturerNameLength = lstrlen(pLocalData->DrvInfo.pszManufacturer);
  2866. if (cManufacturerNameLength)
  2867. {
  2868. cDriverNameLength = lstrlen(pLocalData->DrvInfo.pszModelName);
  2869. if (cDriverNameLength)
  2870. {
  2871. clpFileBufferLength = cProviderNameLength + 1 +
  2872. cManufacturerNameLength + 1 +
  2873. cDriverNameLength + 1 +
  2874. 1;
  2875. DownLoadInfo.lpFile = (LPTSTR)LocalAllocMem(clpFileBufferLength * sizeof(TCHAR));
  2876. if (DownLoadInfo.lpFile)
  2877. {
  2878. StringCchCopy( (LPTSTR)(DownLoadInfo.lpFile), cProviderNameLength + 1, (LPTSTR)(pLocalData->DrvInfo.pszProvider));
  2879. StringCchCopy( (LPTSTR)(DownLoadInfo.lpFile + cProviderNameLength + 1), cManufacturerNameLength + 1, (LPTSTR)(pLocalData->DrvInfo.pszManufacturer));
  2880. StringCchCopy( (LPTSTR)(DownLoadInfo.lpFile + cProviderNameLength + 1 + cManufacturerNameLength + 1), cDriverNameLength + 1, (LPTSTR)(pLocalData->DrvInfo.pszModelName));
  2881. }
  2882. }
  2883. }
  2884. }
  2885. }
  2886. if ( !gpCodeDownLoadInfo->pfnDownload(gpCodeDownLoadInfo->hConnection,
  2887. hwnd,
  2888. &DownLoadInfo,
  2889. szSourceDir,
  2890. SIZECHARS(szSourceDir),
  2891. &uNeeded) )
  2892. goto Cleanup;
  2893. // Now rework install data based on the actual INF
  2894. pNewLocalData = RebuildDeviceInfo( hDevInfo, pLocalData, szSourceDir );
  2895. if ( pNewLocalData == NULL )
  2896. goto Cleanup;
  2897. pNewLocalData->DrvInfo.Flags |= SDFLAG_CDM_DRIVER;
  2898. dwReturn = InstallDriverFromCurrentInf(hDevInfo,
  2899. pNewLocalData,
  2900. hwnd,
  2901. platform,
  2902. dwThisMajorVersion,
  2903. pszServerName,
  2904. INVALID_HANDLE_VALUE,
  2905. NULL,
  2906. NULL,
  2907. 0,
  2908. szSourceDir,
  2909. DRVINST_FLATSHARE | DRVINST_NO_WARNING_PROMPT,
  2910. APD_COPY_NEW_FILES,
  2911. NULL,
  2912. NULL,
  2913. NULL);
  2914. (VOID) DeleteAllFilesInDirectory(szSourceDir, TRUE);
  2915. if ( dwReturn == ERROR_SUCCESS )
  2916. bRet = TRUE;
  2917. Cleanup:
  2918. if ( pNewLocalData )
  2919. DestroyLocalData( pNewLocalData );
  2920. LocalFreeMem((PVOID)DownLoadInfo.lpHardwareIDs);
  2921. LocalFreeMem((PVOID)DownLoadInfo.lpFile);
  2922. CleanupScratchDirectory(pszServerName, platform);
  2923. if ( !bRet && ( dwReturn == ERROR_SUCCESS ) )
  2924. dwReturn = STG_E_UNKNOWN;
  2925. return dwReturn;
  2926. }
  2927. /*++
  2928. Routine Name:
  2929. PSetupInstallInboxDriverSilently
  2930. Routine Description:
  2931. This is used to install inbox drivers silently. The driver must exist in
  2932. ntprint.inf. The inf isn't passed in to make the only code that needs to know
  2933. about ntprint.inf reside in setup. No UIs are popped up and the function
  2934. will fail if UI would be required.
  2935. Arguments:
  2936. pszDriverName - The driver name that we want to install.
  2937. Return Value:
  2938. BOOL, Last error
  2939. --*/
  2940. DWORD
  2941. PSetupInstallInboxDriverSilently(
  2942. IN LPCTSTR pszDriverName
  2943. )
  2944. {
  2945. DWORD Status = ERROR_SUCCESS;
  2946. TCHAR szInfFile[MAX_PATH];
  2947. Status = pszDriverName ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
  2948. //
  2949. // Get the system directory.
  2950. //
  2951. if (Status == ERROR_SUCCESS)
  2952. {
  2953. Status = GetSystemWindowsDirectory(szInfFile, COUNTOF(szInfFile)) ? ERROR_SUCCESS : GetLastError();
  2954. }
  2955. if (Status == ERROR_SUCCESS)
  2956. {
  2957. Status = StrNCatBuff(szInfFile, COUNTOF(szInfFile), szInfFile, TEXT("\\"), szNtPrintInf, NULL);
  2958. }
  2959. if (Status == ERROR_SUCCESS)
  2960. {
  2961. Status = InstallDriverSilently(szInfFile, pszDriverName, NULL);
  2962. }
  2963. return Status;
  2964. }
  2965. /*++
  2966. Routine Name:
  2967. InstallDriverSilently
  2968. Routine Description:
  2969. Install the given printer driver from the given inf from the optional
  2970. source directory, do not pop up UI and fail if UI would be required.
  2971. Arguments:
  2972. pszInfFile - The inf file to install the driver from.
  2973. pszDriverName - The driver name.
  2974. pszSource - The source installation location.
  2975. Return Value:
  2976. BOOL, Last error
  2977. --*/
  2978. DWORD
  2979. InstallDriverSilently(
  2980. IN LPCTSTR pszInfFile,
  2981. IN LPCTSTR pszDriverName,
  2982. IN LPCTSTR pszSource
  2983. )
  2984. {
  2985. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  2986. DWORD dwInstallFlags = DRVINST_PROGRESSLESS | DRVINST_PROMPTLESS;
  2987. PPSETUP_LOCAL_DATA pData = NULL;
  2988. DWORD Status = ERROR_SUCCESS;
  2989. Status = pszInfFile && pszDriverName ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
  2990. //
  2991. // Ensure that setupapi does not throw any UI
  2992. //
  2993. SetupSetNonInteractiveMode(TRUE);
  2994. if (Status == ERROR_SUCCESS)
  2995. {
  2996. if ((hDevInfo = PSetupCreatePrinterDeviceInfoList(NULL)) != INVALID_HANDLE_VALUE &&
  2997. PSetupBuildDriversFromPath(hDevInfo, pszInfFile, TRUE) &&
  2998. PSetupPreSelectDriver(hDevInfo, NULL, pszDriverName) &&
  2999. (pData = BuildInternalData(hDevInfo, NULL)) != NULL &&
  3000. ParseInf(hDevInfo, pData, MyPlatform, NULL, dwInstallFlags, FALSE))
  3001. {
  3002. Status = ERROR_SUCCESS;
  3003. }
  3004. else
  3005. {
  3006. //
  3007. // Ensure that if we have a failure the return is shown as such.
  3008. //
  3009. Status = GetLastError();
  3010. Status = Status == ERROR_SUCCESS ? ERROR_INVALID_DATA : Status;
  3011. }
  3012. }
  3013. if (Status == ERROR_SUCCESS)
  3014. {
  3015. //
  3016. // We don't want to launch a vendor setup entry, but vendor setup
  3017. // only gets launch after an AddPrinter call, which we're not doing - just adding drivers here.
  3018. // NOTE: For future if this included Queue creation we WILL have to handle this.
  3019. //
  3020. Status = PSetupInstallPrinterDriver(hDevInfo,
  3021. pData,
  3022. NULL,
  3023. MyPlatform,
  3024. dwThisMajorVersion,
  3025. NULL,
  3026. NULL,
  3027. NULL,
  3028. pszSource,
  3029. dwInstallFlags,
  3030. APD_COPY_NEW_FILES,
  3031. NULL);
  3032. }
  3033. //
  3034. // Switch on setupapi UI again
  3035. //
  3036. SetupSetNonInteractiveMode(FALSE);
  3037. if(pData != NULL)
  3038. {
  3039. PSetupDestroySelectedDriverInfo(pData);
  3040. }
  3041. //
  3042. // Release the driver setup parameter handle.
  3043. //
  3044. if(hDevInfo != INVALID_HANDLE_VALUE)
  3045. {
  3046. PSetupDestroyPrinterDeviceInfoList( hDevInfo );
  3047. }
  3048. return Status;
  3049. }