Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9887 lines
276 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. All rights reserved.
  4. Module Name:
  5. setup.cxx
  6. Abstract:
  7. Holds Install wizard.
  8. Author:
  9. Albert Ting (AlbertT) 16-Sept-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "time.hxx"
  15. #include "psetup.hxx"
  16. #include "drvsetup.hxx"
  17. #include "instarch.hxx"
  18. #include "portslv.hxx"
  19. #include "dsinterf.hxx"
  20. #include "prtprop.hxx"
  21. #include "prtshare.hxx"
  22. #include "dsinterf.hxx"
  23. #include "drvsetup.hxx"
  24. #include "driverif.hxx"
  25. #include "driverlv.hxx"
  26. #include "archlv.hxx"
  27. #include "detect.hxx"
  28. #include "setup.hxx"
  29. #include "portdlg.hxx"
  30. #include "tstpage.hxx"
  31. #include "drvver.hxx"
  32. #include "printui.h"
  33. #include "query.hxx"
  34. #include "asyncdlg.hxx"
  35. #include "addprn.hxx"
  36. #include "persist.hxx"
  37. #include "compinfo.hxx"
  38. #include "physloc.hxx"
  39. #include "findloc.hxx"
  40. /********************************************************************
  41. Publicly exported functions.
  42. ********************************************************************/
  43. BOOL
  44. bPrinterSetupWOW64(
  45. IN HWND hwnd,
  46. IN UINT uAction,
  47. IN UINT cchPrinterName,
  48. IN OUT LPTSTR pszPrinterName,
  49. OUT UINT *pcchPrinterName,
  50. IN LPCTSTR pszServerName
  51. )
  52. /*++
  53. Routine Description:
  54. WOW64 version.
  55. see bPrinterSetup below.
  56. Arguments:
  57. see bPrinterSetup below.
  58. Return Value:
  59. --*/
  60. {
  61. BOOL bRet = FALSE;
  62. //
  63. // This function potentially may load the driver UI so we call a private API
  64. // exported by winspool.drv, which will RPC the call to a special 64 bit surrogate
  65. // process where the 64 bit driver can be loaded.
  66. //
  67. CDllLoader dll(TEXT("winspool.drv"));
  68. if (dll)
  69. {
  70. ptr_PrintUIPrinterSetup pfn =
  71. (ptr_PrintUIPrinterSetup )dll.GetProcAddress(ord_PrintUIPrinterSetup);
  72. if (pfn)
  73. {
  74. // call into winspool.drv
  75. bRet = pfn(hwnd, uAction, cchPrinterName, pszPrinterName, pcchPrinterName, pszServerName);
  76. }
  77. }
  78. return bRet;
  79. }
  80. BOOL
  81. bPrinterSetupNative(
  82. IN HWND hwnd,
  83. IN UINT uAction,
  84. IN UINT cchPrinterName,
  85. IN OUT LPTSTR pszPrinterName,
  86. OUT UINT *pcchPrinterName,
  87. IN LPCTSTR pszServerName
  88. )
  89. /*++
  90. Routine Description:
  91. Native version.
  92. see bPrinterSetup below.
  93. Arguments:
  94. see bPrinterSetup below.
  95. Return Value:
  96. --*/
  97. {
  98. //
  99. // szNull server is the local server.
  100. //
  101. if( pszServerName && !pszServerName[0] ){
  102. pszServerName = NULL;
  103. }
  104. switch( uAction ){
  105. case MSP_NEWPRINTER:
  106. return bPrinterSetupNew( hwnd, TWizard::kPrinterInstall, cchPrinterName, pszPrinterName, pcchPrinterName, pszServerName, NULL, FALSE );
  107. case MSP_NEWPRINTER_MODELESS:
  108. return bPrinterSetupNew( hwnd, TWizard::kPrinterInstallModeless, cchPrinterName, pszPrinterName, pcchPrinterName, pszServerName, NULL, FALSE );
  109. case MSP_NETPRINTER:
  110. return bPrinterNetInstall( hwnd, pszPrinterName );
  111. case MSP_REMOVENETPRINTER:
  112. return bPrinterNetRemove( hwnd, pszPrinterName, 0 );
  113. case MSP_REMOVEPRINTER:
  114. return bRemovePrinter( hwnd, pszPrinterName, pszServerName, 0 );
  115. case MSP_NEWDRIVER:
  116. return bDriverSetupNew( hwnd, TWizard::kDriverInstall, cchPrinterName, pszPrinterName, pcchPrinterName, pszServerName, kSkipArchSelection, FALSE );
  117. case MSP_FINDPRINTER:
  118. return bFindPrinter( hwnd, pszPrinterName, pcchPrinterName );
  119. default:
  120. DBGMSG( DBG_WARN, ( "bPrinterSetup: unknown command %d\n", uAction ));
  121. }
  122. return FALSE;
  123. }
  124. BOOL
  125. bPrinterSetup(
  126. IN HWND hwnd,
  127. IN UINT uAction,
  128. IN UINT cchPrinterName,
  129. IN OUT LPTSTR pszPrinterName,
  130. OUT UINT *pcchPrinterName,
  131. IN LPCTSTR pszServerName
  132. )
  133. /*++
  134. Routine Description:
  135. Brings up the install printer wizard.
  136. Arguments:
  137. hwnd - Parent window.
  138. uAction - Action requested (defined in windows\inc16\msprintx.h)
  139. cchPrinterName - Length of pszPrinterName buffer.
  140. pszPrinterName - Input setup printer name, Output pointer to new printer name
  141. pcchPrinterName - New length of pszPrinterName on return.
  142. pszServerName - Name of server that printer is on.
  143. Return Value:
  144. TRUE - Success, FALSE = FAILURE.
  145. Notes:
  146. --*/
  147. {
  148. BOOL bRet = FALSE;
  149. if (IsRunningWOW64())
  150. {
  151. bRet = bPrinterSetupWOW64(hwnd, uAction, cchPrinterName, pszPrinterName, pcchPrinterName, pszServerName);
  152. }
  153. else
  154. {
  155. bRet = bPrinterSetupNative(hwnd, uAction, cchPrinterName, pszPrinterName, pcchPrinterName, pszServerName);
  156. }
  157. return bRet;
  158. }
  159. DWORD
  160. PnPInterface(
  161. IN EPnPFunctionCode Function,
  162. IN TParameterBlock *pParameterBlock
  163. )
  164. /*++
  165. Routine Description:
  166. PnP interface which ntprint uses to install printers.
  167. Arguments:
  168. EPnPFunctionCode - Function code.
  169. TParameterBlock - Union of structures see printui.h
  170. Return Value:
  171. TRUE - Success, FALSE = FAILURE.
  172. Notes:
  173. --*/
  174. {
  175. SPLASSERT( pParameterBlock );
  176. BOOL bStatus = FALSE;
  177. DWORD dwLastError = ERROR_SUCCESS;
  178. switch( Function )
  179. {
  180. //
  181. // Do quiet install of printer a printer.
  182. //
  183. case kPrinterInstall:
  184. {
  185. TPrinterInstall *pPI = pParameterBlock->pPrinterInstall;
  186. SPLASSERT( sizeof( TPrinterInstall ) == pPI->cbSize );
  187. if( pPI->cchPrinterName && pPI->pszPrinterNameBuffer ) *(pPI->pszPrinterNameBuffer) = 0;
  188. bStatus = bPrinterInstall( pPI->pszServerName,
  189. pPI->pszDriverName,
  190. pPI->pszPortName,
  191. pPI->pszPrinterNameBuffer,
  192. pPI->cchPrinterName,
  193. 0,
  194. 0,
  195. NULL,
  196. &dwLastError );
  197. break;
  198. }
  199. //
  200. // Invoke integrated installation wizard.
  201. //
  202. case kInstallWizard:
  203. {
  204. TInstallWizard *pPIW = pParameterBlock->pInstallWizard;
  205. SPLASSERT( sizeof( TInstallWizard ) == pPIW->cbSize );
  206. bStatus = bInstallWizard( pPIW->pszServerName,
  207. pPIW->pData,
  208. &pPIW->pReferenceData,
  209. &dwLastError );
  210. break;
  211. }
  212. //
  213. // Destroy integrated installation wizard.
  214. //
  215. case kDestroyWizardData:
  216. {
  217. TDestroyWizard *pPDW = pParameterBlock->pDestroyWizard;
  218. SPLASSERT( sizeof( TDestroyWizard ) == pPDW->cbSize );
  219. bStatus = bDestroyWizard( pPDW->pszServerName,
  220. pPDW->pData,
  221. pPDW->pReferenceData,
  222. &dwLastError );
  223. break;
  224. }
  225. //
  226. // Invoke the Inf printer installation.
  227. //
  228. case kInfInstall:
  229. {
  230. TInfInstall *pII = pParameterBlock->pInfInstall;
  231. SPLASSERT( sizeof( TInfInstall ) == pII->cbSize );
  232. bStatus = bInfInstall( pII->pszServerName,
  233. pII->pszInfName,
  234. pII->pszModelName,
  235. pII->pszPortName,
  236. pII->pszPrinterNameBuffer,
  237. pII->cchPrinterName,
  238. pII->pszSourcePath,
  239. pII->dwFlags,
  240. 0,
  241. NULL,
  242. NULL,
  243. &dwLastError );
  244. break;
  245. }
  246. //
  247. // Invoke the Advanced Inf printer installation.
  248. //
  249. case kAdvInfInstall:
  250. {
  251. TAdvInfInstall *pAII = pParameterBlock->pAdvInfInstall;
  252. SPLASSERT( sizeof( TAdvInfInstall ) == pAII->cbSize );
  253. bStatus = bInfInstall( pAII->pszServerName,
  254. pAII->pszInfName,
  255. pAII->pszModelName,
  256. pAII->pszPortName,
  257. pAII->pszPrinterNameBuffer,
  258. pAII->cchPrinterName,
  259. pAII->pszSourcePath,
  260. pAII->dwFlags,
  261. pAII->dwAttributes,
  262. pAII->pSecurityDescriptor,
  263. &pAII->dwOutFlags,
  264. &dwLastError );
  265. break;
  266. }
  267. //
  268. // Invoke the Inf driver installation.
  269. //
  270. case kInfDriverInstall:
  271. {
  272. TInfDriverInstall *pII = pParameterBlock->pInfDriverInstall;
  273. SPLASSERT( sizeof( TInfDriverInstall ) == pII->cbSize );
  274. bStatus = bInstallPrinterDriver( pII->pszServerName,
  275. pII->pszModelName,
  276. pII->pszArchitecture,
  277. pII->pszVersion,
  278. pII->pszInfName,
  279. pII->pszSourcePath,
  280. pII->dwFlags,
  281. NULL,
  282. &dwLastError );
  283. break;
  284. }
  285. //
  286. // Invoke the driver removal
  287. //
  288. case kDriverRemoval:
  289. {
  290. TDriverRemoval *pII = pParameterBlock->pDriverRemoval;
  291. SPLASSERT( sizeof( TDriverRemoval ) == pII->cbSize );
  292. bStatus = bRemovePrinterDriver( pII->pszServerName,
  293. pII->pszModelName,
  294. pII->pszArchitecture,
  295. pII->pszVersion,
  296. pII->dwFlags,
  297. &dwLastError );
  298. break;
  299. }
  300. default:
  301. DBGMSG( DBG_WARN, ( "PnPInterface: unknown function %d\n", Function ) );
  302. break;
  303. }
  304. //
  305. // If something failed and the last error is not set then set the
  306. // last error to a general failure.
  307. //
  308. if( !bStatus )
  309. {
  310. if( dwLastError == ERROR_SUCCESS )
  311. {
  312. dwLastError = ERROR_INVALID_PARAMETER;
  313. }
  314. }
  315. DBGMSG( DBG_WARN, ( "PnPInterface: return value %d\n", dwLastError ) );
  316. //
  317. // The caller expects the last error to be valid after this call.
  318. //
  319. return dwLastError;
  320. }
  321. BOOL
  322. bPrinterInstall(
  323. IN LPCTSTR pszServerName,
  324. IN LPCTSTR pszDriverName,
  325. IN LPCTSTR pszPortName,
  326. IN OUT LPTSTR pszPrinterNameBuffer,
  327. IN UINT cchPrinterName,
  328. IN DWORD dwFlags,
  329. IN DWORD dwAttributes,
  330. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  331. OUT PDWORD pdwError
  332. )
  333. /*++
  334. Routine Description:
  335. Called by plug and play manager to install a printer.
  336. The driver is assumed to already be installed for this printer.
  337. Arguments:
  338. pszServerName - Server where to install printer,
  339. - Currently NULL == local machine is supported.
  340. pszDriverName - Pointer to printer driver name.
  341. pszPortName - Name of port to install.
  342. pszPrinterNameBuffer - Buffer where to return fully installed printer name.
  343. cchPrinterName - Size of printer name buffer
  344. Return Value:
  345. TRUE - Success, FALSE = Failure.
  346. Notes:
  347. --*/
  348. {
  349. DBGMSG( DBG_TRACE, ( "ServerName " TSTR "\n", DBGSTR( pszServerName ) ) );
  350. DBGMSG( DBG_TRACE, ( "DriverName " TSTR "\n", DBGSTR( pszDriverName ) ) );
  351. DBGMSG( DBG_TRACE, ( "PortName " TSTR "\n", DBGSTR( pszPortName ) ) );
  352. DBGMSG( DBG_TRACE, ( "pszPrinterNameBuffer " TSTR "\n", DBGSTR( pszPrinterNameBuffer ) ) );
  353. DBGMSG( DBG_TRACE, ( "cchPrinterName %d\n", cchPrinterName ) );
  354. SPLASSERT( pszDriverName );
  355. SPLASSERT( pszPortName );
  356. SPLASSERT( pdwError );
  357. TStatusB bStatus;
  358. TCHAR szPrinterBase[kPrinterBufMax];
  359. TCHAR szPrinterName[kPrinterBufMax];
  360. WORD wInstance = 0;
  361. UINT uRetryCount = 0;
  362. //
  363. // If the provided printer buffer name contains a name then use
  364. // it as the base printer name, otherwise use the driver name.
  365. //
  366. szPrinterBase[0] = 0;
  367. szPrinterName[0] = 0;
  368. if( pszPrinterNameBuffer && *pszPrinterNameBuffer )
  369. {
  370. lstrcpyn(szPrinterBase, pszPrinterNameBuffer, ARRAYSIZE(szPrinterBase));
  371. lstrcpyn(szPrinterName, pszPrinterNameBuffer, ARRAYSIZE(szPrinterName));
  372. }
  373. else
  374. {
  375. if( pszDriverName && *pszDriverName )
  376. {
  377. lstrcpyn(szPrinterBase, pszDriverName, ARRAYSIZE(szPrinterBase));
  378. lstrcpyn(szPrinterName, pszDriverName, ARRAYSIZE(szPrinterName));
  379. }
  380. }
  381. //
  382. // Check how to handle the case when the printer
  383. // already exists on the system
  384. //
  385. if( !(dwFlags & kPnPInterface_DontAutoGenerateName) )
  386. {
  387. //
  388. // Generate a friendly unique printer name.
  389. //
  390. bStatus DBGNOCHK = NewFriendlyName( const_cast<LPTSTR>( pszServerName ),
  391. const_cast<LPTSTR>( szPrinterBase ),
  392. szPrinterName, &wInstance );
  393. }
  394. //
  395. // szNull server is the local server.
  396. //
  397. if( pszServerName && !pszServerName[0] )
  398. {
  399. pszServerName = NULL;
  400. }
  401. //
  402. // If a printer name buffer was not provided then force the buffer
  403. // size to a valid value.
  404. //
  405. if( !pszPrinterNameBuffer )
  406. {
  407. cchPrinterName = kPrinterBufMax;
  408. }
  409. //
  410. // Ensure the provided buffer can hold the entire generated printer name.
  411. //
  412. if( cchPrinterName > _tcslen( szPrinterName ) )
  413. {
  414. BOOL bSetDefault = FALSE;
  415. //
  416. // If a server name was specified, do not try and
  417. // set the default printer. The Default printer is a
  418. // per user setting which can only be applied to the local machine.
  419. // Check if there is a default printer.
  420. //
  421. if( !pszServerName && ( CheckDefaultPrinter( NULL ) == kNoDefault ) )
  422. {
  423. DBGMSG( DBG_TRACE, ( "Default Printer does not exist.\n" ) );
  424. bSetDefault = TRUE;
  425. }
  426. //
  427. // Check if this machine is NTW or NTS.
  428. //
  429. CComputerInfo CompInfo( pszServerName );
  430. BOOL bIsNTServer = CompInfo.GetProductInfo() ? CompInfo.IsRunningNtServer() : FALSE;
  431. //
  432. // Set the default sharing and publishing state.
  433. //
  434. BOOL bShared = bIsNTServer ? TRUE : kDefaultShareState;
  435. BOOL bPublish = kDefaultPublishState;
  436. //
  437. // Read the bits from the policy location.
  438. //
  439. TPersist PersistPolicy( gszAddPrinterWizardPolicy, TPersist::kOpen|TPersist::kRead );
  440. if( VALID_OBJ( PersistPolicy ) )
  441. {
  442. bStatus DBGNOCHK = PersistPolicy.bRead( gszAPWSharing, bShared );
  443. }
  444. //
  445. // Read the bits from the policy location from hkey local machine.
  446. //
  447. TPersist PersistPolicy2( gszAddPrinterWizardPolicy, TPersist::kOpen|TPersist::kRead, HKEY_LOCAL_MACHINE );
  448. if( VALID_OBJ( PersistPolicy2 ) )
  449. {
  450. bStatus DBGNOCHK = PersistPolicy2.bRead( gszAPWPublish, bPublish );
  451. }
  452. //
  453. // If we are specificlay told not to share this device. This
  454. // was requested by the fax installation code, because the workstation
  455. // service may not have been stated yet. Also it has been mentioned
  456. // that in the next release of the fax code they may prevent all
  457. // fax sharing.
  458. //
  459. if( dwFlags & kPnPInterface_NoShare )
  460. {
  461. bShared = FALSE;
  462. }
  463. //
  464. // If the caller is forcing sharing.
  465. //
  466. if( dwFlags & kPnPInterface_Share )
  467. {
  468. bShared = TRUE;
  469. }
  470. //
  471. // Read the per machine policy bit that the spooler uses for
  472. // printer publishing. The per user policy and the per machine policy
  473. // must agree inorder for the wizard to publish the printer.
  474. //
  475. TPersist SpoolerPolicy( gszSpoolerPolicy, TPersist::kOpen|TPersist::kRead, HKEY_LOCAL_MACHINE );
  476. if( VALID_OBJ( SpoolerPolicy ) )
  477. {
  478. BOOL bCanPublish = kDefaultPublishState;
  479. bStatus DBGNOCHK = SpoolerPolicy.bRead( gszSpoolerPublish, bCanPublish );
  480. if( bStatus )
  481. {
  482. bPublish = bPublish && bCanPublish;
  483. }
  484. }
  485. //
  486. // Check if the Direcotory Services is available.
  487. //
  488. TDirectoryService Ds;
  489. TWizard::EDsStatus eIsDsAvailable;
  490. eIsDsAvailable = Ds.bIsDsAvailable( pszServerName ) ? TWizard::kDsStatusAvailable : TWizard::kDsStatusUnavailable;
  491. //
  492. // Set the printer install flags, using the passed in command line flags.
  493. //
  494. TWizard::EAddPrinterAttributes eAddAttributes = ( dwFlags & kPnPInterface_WebPointAndPrint ) ?
  495. TWizard::kAttributesMasq : TWizard::kAttributesNone;
  496. for( ;; )
  497. {
  498. //
  499. // Install the printer with defaults.
  500. //
  501. bStatus DBGCHK = TWizard::bInstallPrinter( pszServerName,
  502. szPrinterName,
  503. gszNULL,
  504. pszPortName,
  505. pszDriverName,
  506. NULL,
  507. NULL,
  508. NULL,
  509. bShared,
  510. bPublish,
  511. eAddAttributes,
  512. eIsDsAvailable,
  513. dwAttributes,
  514. pSecurityDescriptor );
  515. if( !bStatus && ERROR_PRINTER_ALREADY_EXISTS == GetLastError() &&
  516. uRetryCount < TWizard::kAddPrinterMaxRetry &&
  517. !(dwFlags & kPnPInterface_DontAutoGenerateName))
  518. {
  519. wInstance++;
  520. uRetryCount++;
  521. //
  522. // Generate a friendly unique printer name.
  523. //
  524. bStatus DBGNOCHK = NewFriendlyName( const_cast<LPTSTR>( pszServerName ),
  525. const_cast<LPTSTR>( szPrinterBase ),
  526. szPrinterName, &wInstance );
  527. continue;
  528. }
  529. if( bStatus )
  530. {
  531. //
  532. // Copy back the printer name if a buffer was provided
  533. //
  534. if( pszPrinterNameBuffer )
  535. {
  536. _tcscpy( pszPrinterNameBuffer, szPrinterName );
  537. }
  538. //
  539. // If there are no default printers, make this the default.
  540. //
  541. if( bSetDefault )
  542. {
  543. SetDefaultPrinter( szPrinterName );
  544. }
  545. }
  546. //
  547. // exit the for( ;; ) loop
  548. //
  549. break;
  550. }
  551. }
  552. else
  553. {
  554. //
  555. // The buffer was too small to hold the resultant printer name.
  556. //
  557. bStatus DBGNOCHK = FALSE;
  558. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  559. }
  560. //
  561. // If an error occurred then preserve the last error.
  562. // Note: The calling of destructors will modify the last error.
  563. //
  564. if( !bStatus )
  565. {
  566. *pdwError = GetLastError();
  567. }
  568. return bStatus;
  569. }
  570. /********************************************************************
  571. Private functions.
  572. ********************************************************************/
  573. BOOL
  574. bRemovePrinter(
  575. IN HWND hwnd,
  576. IN LPCTSTR pszPrinterName,
  577. IN LPCTSTR pszServerName,
  578. IN BOOL bQuiet
  579. )
  580. /*++
  581. Routine Description:
  582. Remove the specified printer on the specified server.
  583. Arguments:
  584. hwnd - Parent window.
  585. pszPrinterName - Name of printer to remove.
  586. Return Value:
  587. TRUE - Success, FALSE = FAILURE.
  588. Notes:
  589. --*/
  590. {
  591. TString strFullPrinterName;
  592. TStatusB bStatus;
  593. bStatus DBGCHK = bBuildFullPrinterName( pszServerName, pszPrinterName, strFullPrinterName );
  594. DWORD dwLastError = ERROR_SUCCESS;
  595. HANDLE hPrinter = NULL;
  596. PRINTER_DEFAULTS pd;
  597. pd.pDatatype = NULL;
  598. pd.pDevMode = NULL;
  599. pd.DesiredAccess = PRINTER_ALL_ACCESS;
  600. bStatus DBGCHK = OpenPrinter( (LPTSTR)(LPCTSTR)strFullPrinterName, &hPrinter, &pd );
  601. if( bStatus ){
  602. //
  603. // Delete the printer.
  604. //
  605. bStatus DBGCHK = DeletePrinter( hPrinter );
  606. //
  607. // Preserve the last error because close printer is
  608. // setting the last error to ERROR_SUCCESS
  609. //
  610. if( !bStatus )
  611. {
  612. dwLastError = GetLastError();
  613. }
  614. else
  615. {
  616. //
  617. // Printer removed, clean up any queue view informaiton.
  618. //
  619. TQueue::vRemove( pszPrinterName );
  620. }
  621. //
  622. // Close the open printer handle.
  623. //
  624. if( hPrinter ){
  625. TStatusB bStatusClosePrinter;
  626. bStatusClosePrinter DBGCHK = ClosePrinter( hPrinter );
  627. }
  628. }
  629. //
  630. // If we cannot open or delete the printer inform the user.
  631. //
  632. if( !bStatus ){
  633. //
  634. // Set the last error if it is not error success.
  635. //
  636. if( dwLastError != ERROR_SUCCESS )
  637. {
  638. SetLastError( dwLastError );
  639. }
  640. DBGMSG( DBG_WARN, ( "bPrinterSetup: Unable to delete printer "TSTR": %d\n", DBGSTR( pszPrinterName ), GetLastError( )));
  641. if( !bQuiet )
  642. {
  643. iMessage( hwnd,
  644. IDS_ERR_REMOVE_PRINTER_TITLE,
  645. IDS_ERR_REMOVE_PRINTER,
  646. MB_OK|MB_ICONHAND,
  647. kMsgGetLastError,
  648. NULL );
  649. }
  650. }
  651. return bStatus;
  652. }
  653. BOOL
  654. bPrinterNetInstall(
  655. IN HWND hwnd,
  656. IN LPCTSTR pszPrinterName
  657. )
  658. /*++
  659. Routine Description:
  660. Installs a printer connection on this machine to the
  661. the specified printer.
  662. Arguments:
  663. hwnd - Parent window.
  664. pszPrinterName - Name of printer to install a connection to.
  665. Return Value:
  666. TRUE - Success, FALSE = FAILURE.
  667. Notes:
  668. --*/
  669. {
  670. TStatusB bStatus;
  671. //
  672. // Validate the printer name as possible
  673. //
  674. bStatus DBGNOCHK =
  675. ( NULL != pszPrinterName &&
  676. lstrlen( pszPrinterName ) > 2 &&
  677. pszPrinterName[0] == TEXT( '\\' ) &&
  678. pszPrinterName[1] == TEXT( '\\' )
  679. );
  680. if( bStatus ){
  681. //
  682. // Async version of add printer connection.
  683. //
  684. bStatus DBGNOCHK = PrintUIAddPrinterConnectionUI( hwnd, pszPrinterName );
  685. }
  686. if( bStatus ){
  687. //
  688. // HACK: The SUR spooler does not handle the default
  689. // printer, so we are forced to do it here.
  690. //
  691. // If there are no default printers, make this the default.
  692. //
  693. if( CheckDefaultPrinter( NULL ) == kNoDefault ){
  694. bStatus DBGCHK = SetDefaultPrinter( NULL );
  695. }
  696. bStatus DBGNOCHK = TRUE;
  697. }
  698. return bStatus;
  699. }
  700. BOOL
  701. bPrinterNetRemove(
  702. IN HWND hwnd,
  703. IN LPCTSTR pszPrinterName,
  704. IN BOOL bQuiet
  705. )
  706. /*++
  707. Routine Description:
  708. Removes a printer connection from this machine.
  709. Arguments:
  710. hwnd - Parent window.
  711. pszPrinterName - Name of printer to remove connection from.
  712. Return Value:
  713. TRUE - Success, FALSE = FAILURE.
  714. Notes:
  715. --*/
  716. {
  717. TStatusB bStatus;
  718. bStatus DBGCHK = DeletePrinterConnection( const_cast<LPTSTR>( pszPrinterName ) );
  719. if( !bStatus )
  720. {
  721. DBGMSG( DBG_WARN, ( "bPrinterSetup: Unable to Delete Connection "TSTR" %d\n", DBGSTR( pszPrinterName ), GetLastError( )));
  722. if( !bQuiet )
  723. {
  724. iMessage( hwnd,
  725. IDS_ERR_REMOVE_PRINTER_TITLE,
  726. IDS_ERR_REMOVE_PRINTER_CONNECTION,
  727. MB_OK|MB_ICONHAND,
  728. kMsgGetLastError,
  729. NULL );
  730. }
  731. }
  732. else
  733. {
  734. //
  735. // Printer connection removed, clean up any queue view informaiton.
  736. //
  737. TQueue::vRemove( pszPrinterName );
  738. }
  739. return bStatus;
  740. }
  741. BOOL
  742. bPrinterSetupNew(
  743. IN HWND hwnd,
  744. IN UINT uAction,
  745. IN UINT cchPrinterName,
  746. IN OUT LPTSTR pszPrinterName,
  747. OUT UINT* pcchPrinterName,
  748. IN LPCTSTR pszServerName,
  749. IN LPCTSTR pszInfFileName,
  750. IN BOOL bRestartableFromLastPage
  751. )
  752. /*++
  753. Routine Description:
  754. Brings up the install printer wizard.
  755. Arguments:
  756. hwnd - Parent window.
  757. uAction - Action requested (defined in windows\inc16\msprintx.h)
  758. cchPrinterName - Length of pszPrinterName buffer.
  759. pszPrinterName - Input setup printer name, Output pointer to new printer name
  760. pcchPrinterName - New length of pszPrinterName on return.
  761. pszServerName - Name of server that printer is on.
  762. Return Value:
  763. TRUE - Success, FALSE = FAILURE.
  764. Notes:
  765. --*/
  766. {
  767. DBGMSG( DBG_TRACE, ( "bPrinterSetupNew\n" ) );
  768. TStatusB bStatus;
  769. //
  770. // Get the current machine name.
  771. //
  772. TString strMachineName;
  773. bStatus DBGCHK = bGetMachineName( strMachineName );
  774. //
  775. // If the machine name matches the specified server name
  776. // adjust the server name pointer to null, which indicates
  777. // the local machine.
  778. //
  779. if( pszServerName &&
  780. !_tcsicmp( pszServerName, strMachineName ) ){
  781. pszServerName = NULL;
  782. }
  783. //
  784. // Build a unique name for the singleton window.
  785. //
  786. TString strWindowName;
  787. bStatus DBGCHK = strWindowName.bUpdate( pszServerName );
  788. //
  789. // If string is not empty add slash separator.
  790. //
  791. if( !strWindowName.bEmpty( ) ){
  792. bStatus DBGCHK = strWindowName.bCat( gszWack );
  793. }
  794. //
  795. // Concatinate the printer name string.
  796. //
  797. bStatus DBGCHK = strWindowName.bCat( pszPrinterName );
  798. //
  799. // Check if we are invoked modely.
  800. //
  801. BOOL bModal = uAction == TWizard::kPrinterInstall;
  802. //
  803. // Create the printer setup data class.
  804. //
  805. TPrinterSetupData *pSetupData;
  806. pSetupData = new TPrinterSetupData( hwnd,
  807. uAction,
  808. cchPrinterName,
  809. pszPrinterName,
  810. pcchPrinterName,
  811. pszServerName,
  812. strWindowName,
  813. pszInfFileName,
  814. bModal,
  815. bRestartableFromLastPage );
  816. //
  817. // Check for valid setup data pointer, and valid construction.
  818. //
  819. if( VALID_PTR( pSetupData ) ){
  820. switch ( uAction ){
  821. case TWizard::kPrinterInstallModeless: {
  822. //
  823. // Create the thread which handles a modeless call of the
  824. // add printer wizard ui.
  825. //
  826. DWORD dwIgnore;
  827. HANDLE hThread;
  828. hThread = TSafeThread::Create( NULL,
  829. 0,
  830. (LPTHREAD_START_ROUTINE)TPrinterSetupData::iPrinterSetupProc,
  831. pSetupData,
  832. 0,
  833. &dwIgnore );
  834. //
  835. // If the thread could not be created.
  836. //
  837. if( !hThread ){
  838. DBGMSG( DBG_WARN, ( "bPrinterSetupNew thead creation failed.\n" ) );
  839. delete pSetupData;
  840. bStatus DBGNOCHK = FALSE;
  841. //
  842. // A thread was created then release the thread handle
  843. // and set the return value.
  844. //
  845. } else {
  846. CloseHandle( hThread );
  847. bStatus DBGNOCHK = TRUE;
  848. }
  849. }
  850. break;
  851. case TWizard::kPrinterInstall:
  852. //
  853. // Do a modal call of the add printer wizard ui.
  854. //
  855. bStatus DBGNOCHK = (BOOL)TPrinterSetupData::iPrinterSetupProc( pSetupData );
  856. break;
  857. default:
  858. DBGMSG( DBG_WARN, ("Invalid add printer option.\n" ) );
  859. delete pSetupData;
  860. break;
  861. }
  862. //
  863. // If the pSetupData was allocated but the object faild during construction
  864. // as indicated by a call to bValid(), we must free the memory. This code path
  865. // will be take very often because the constructor of pSetupData checks if
  866. // another instance of the AddPrinter wizard is currently executing.
  867. //
  868. } else {
  869. DBGMSG( DBG_WARN, ("Add printer is currently running.\n" ) );
  870. delete pSetupData;
  871. }
  872. DBGMSG( DBG_TRACE, ( "bPrinterSetupNew - Returned %d\n", bStatus ) );
  873. return bStatus;
  874. }
  875. BOOL
  876. bDriverSetupNew(
  877. IN HWND hwnd,
  878. IN UINT uAction,
  879. IN UINT cchDriverName,
  880. IN OUT LPTSTR pszDriverName,
  881. OUT UINT* pcchDriverName,
  882. IN LPCTSTR pszServerName,
  883. IN INT Flags,
  884. IN BOOL bRestartableFromLastPage
  885. )
  886. /*++
  887. Routine Description:
  888. Brings up the install driver wizard.
  889. Arguments:
  890. hwnd - Parent window.
  891. uAction - Action requested (defined in windows\inc16\msprintx.h)
  892. cchDriverName - Length of pszDriverName buffer.
  893. pszDriverName - Input setup driver name, Output new driver name
  894. pcchDriverName - New length of pszDriverName on return.
  895. pszServerName - Name of server that printer is on.
  896. Return Value:
  897. TRUE - Success, FALSE = FAILURE.
  898. Notes:
  899. --*/
  900. {
  901. DBGMSG( DBG_TRACE, ( "bDriverSetupNew\n" ) );
  902. TStatusB bStatus;
  903. TString strDriverName;
  904. BOOL bCanceled = FALSE;
  905. //
  906. // Copy the passed in printer driver name.
  907. //
  908. bStatus DBGCHK = strDriverName.bUpdate( pszDriverName );
  909. //
  910. // Install the new printer driver.
  911. //
  912. bStatus DBGCHK = bInstallNewPrinterDriver( hwnd,
  913. uAction,
  914. pszServerName,
  915. strDriverName,
  916. NULL,
  917. Flags,
  918. &bCanceled,
  919. bRestartableFromLastPage
  920. );
  921. if( bStatus )
  922. {
  923. //
  924. // Copy back the installed printer driver name,
  925. // if a buffer was provided.
  926. //
  927. if( pszDriverName &&
  928. pcchDriverName &&
  929. cchDriverName > strDriverName.uLen() )
  930. {
  931. _tcscpy( pszDriverName, strDriverName );
  932. *pcchDriverName = strDriverName.uLen();
  933. }
  934. }
  935. //
  936. // If the wizard was canceled, set the last error.
  937. //
  938. if( bCanceled )
  939. {
  940. SetLastError( ERROR_CANCELLED );
  941. }
  942. return bStatus;
  943. }
  944. BOOL
  945. bInstallNewPrinterDriver(
  946. IN HWND hwnd,
  947. IN UINT uAction,
  948. IN LPCTSTR pszServerName,
  949. IN OUT TString &strDriverName,
  950. OUT TDriverTransfer *pDriverTransfer,
  951. IN INT Flags,
  952. OUT PBOOL pbCanceled,
  953. IN BOOL bRestartableFromLastPage,
  954. IN PUINT pnDriverInstallCount
  955. )
  956. /*++
  957. Routine Description:
  958. Addes our wizard pages to the set of passed in pages. The pages
  959. are only appended to the passed in pages.
  960. Arguments:
  961. pszServerName - Name of server that printer is on.
  962. pWizardData - Pointer to wizard data structure see setupapi.h
  963. Return Value:
  964. TRUE = Success, FALSE = FAILURE.
  965. Notes:
  966. The wizard object is orphaned to the caller if successfull. It's the
  967. callers responsibility to clean up if ProperySheets() is not called.
  968. In the case caller does call PropertySheets() the wizard object will
  969. be release at or near WM_DESTROY time.
  970. --*/
  971. {
  972. TStatusB bStatus;
  973. bStatus DBGNOCHK = TRUE;
  974. BOOL bSkipIntroPageDueToRestart = FALSE;
  975. BOOL bWizardDone = FALSE;
  976. INT iPosX = -1;
  977. INT iPosY = -1;
  978. for( ; bStatus && !bWizardDone; )
  979. {
  980. //
  981. // Create the wizard object.
  982. //
  983. TWizard Wizard( hwnd, uAction, strDriverName, pszServerName );
  984. //
  985. // Validate the wizard object.
  986. //
  987. bStatus DBGCHK = VALID_OBJ( Wizard );
  988. if( bStatus )
  989. {
  990. //
  991. // Set the pointer to the driver transfer data. This pointer will be use
  992. // to pass back multiple selected drivers to the caller.
  993. //
  994. // Note: The ? : test with TRUE FALSE assignments is necessary, because the
  995. // we test the bXXX flags for equality with TRUE and FALSE in the page
  996. // table finite state machine.
  997. //
  998. Wizard.pDriverTransfer() = pDriverTransfer;
  999. Wizard.bSkipArchSelection() = Flags & kSkipArchSelection ? TRUE : FALSE;
  1000. Wizard.bRestartableFromLastPage() = bRestartableFromLastPage;
  1001. Wizard.bRestartAgain() = bSkipIntroPageDueToRestart;
  1002. Wizard.iPosX() = iPosX;
  1003. Wizard.iPosY() = iPosY;
  1004. //
  1005. // Display the wizard to the user.
  1006. //
  1007. if( bStatus )
  1008. {
  1009. bStatus DBGCHK = Wizard.bPropPages();
  1010. }
  1011. if( bStatus && Wizard.bShouldRestart() )
  1012. {
  1013. //
  1014. // Second time through the wizard we skip the intro page.
  1015. //
  1016. bSkipIntroPageDueToRestart = TRUE;
  1017. iPosX = Wizard.iPosX();
  1018. iPosY = Wizard.iPosY();
  1019. //
  1020. // Restart the wizard to add another printer driver.
  1021. //
  1022. continue;
  1023. }
  1024. else
  1025. {
  1026. bWizardDone = TRUE;
  1027. if( bStatus )
  1028. {
  1029. (VOID)strDriverName.bUpdate( Wizard.strDriverName() );
  1030. }
  1031. //
  1032. // Check if the dialog was canceled.
  1033. //
  1034. if( pbCanceled )
  1035. {
  1036. *pbCanceled = Wizard.bWizardCanceled();
  1037. }
  1038. if( pnDriverInstallCount )
  1039. {
  1040. *pnDriverInstallCount = Wizard.nDriverInstallCount();
  1041. }
  1042. }
  1043. }
  1044. }
  1045. return bStatus;
  1046. }
  1047. BOOL
  1048. GetOrUseInfName(
  1049. IN OUT TString &strInfName
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. Given a file name and if the name is not empty it will expand
  1054. it to a full file path. If the name is an empty string, this
  1055. function will return the default system printer inf file name.
  1056. Arguments:
  1057. strInfName - reference to inf file name. On input
  1058. Return Value:
  1059. TRUE success, FALSE an error occurred.
  1060. --*/
  1061. {
  1062. TStatusB bStatus;
  1063. bStatus DBGNOCHK = strInfName.bEmpty();
  1064. //
  1065. // If the inf name was not specified then use the system inf, "ntprint.inf"
  1066. //
  1067. if( bStatus )
  1068. {
  1069. TCHAR szBuff[MAX_PATH];
  1070. bStatus DBGCHK = GetSystemWindowsDirectory( szBuff, COUNTOF( szBuff ) );
  1071. if( bStatus )
  1072. {
  1073. bStatus DBGCHK = strInfName.bUpdate( szBuff );
  1074. if( bStatus )
  1075. {
  1076. bStatus DBGCHK = strInfName.bCat( gszWack ) &&
  1077. strInfName.bCat( gszInf ) &&
  1078. strInfName.bCat( gszWack ) &&
  1079. strInfName.bCat( gszNtPrintInf );
  1080. }
  1081. }
  1082. }
  1083. else
  1084. {
  1085. //
  1086. // The inf name must be fully qualified.
  1087. //
  1088. TCHAR szFullInfName[MAX_PATH];
  1089. LPTSTR pszDummy;
  1090. DWORD dwLength = GetFullPathName( strInfName, COUNTOF( szFullInfName ), szFullInfName, &pszDummy );
  1091. if( dwLength )
  1092. {
  1093. bStatus DBGCHK = strInfName.bUpdate( szFullInfName );
  1094. }
  1095. else
  1096. {
  1097. bStatus DBGCHK = FALSE;
  1098. }
  1099. }
  1100. return bStatus;
  1101. }
  1102. BOOL
  1103. bInstallPrinterDriver(
  1104. IN LPCTSTR pszServerName,
  1105. IN LPCTSTR pszDriverName,
  1106. IN LPCTSTR pszArchitecture,
  1107. IN LPCTSTR pszVersion,
  1108. IN LPCTSTR pszInfName,
  1109. IN LPCTSTR pszSourcePath,
  1110. IN DWORD dwFlags,
  1111. IN HWND hwnd,
  1112. IN DWORD *pdwError
  1113. )
  1114. /*++
  1115. Routine Description:
  1116. Installs the specified printer driver
  1117. Arguments:
  1118. pszServerName - Name of server that printer is on.
  1119. pWizardData - Pointer to wizard data structure see setupapi.h
  1120. Return Value:
  1121. TRUE = Success, FALSE = FAILURE.
  1122. --*/
  1123. {
  1124. DBGMSG( DBG_TRACE, ( "bInstallPrinterDriver\n" ) );
  1125. DBGMSG( DBG_TRACE, ( "ServerName "TSTR"\n", DBGSTR( pszServerName ) ) );
  1126. DBGMSG( DBG_TRACE, ( "DriverName "TSTR"\n", DBGSTR( pszDriverName ) ) );
  1127. DBGMSG( DBG_TRACE, ( "Architecture "TSTR"\n", DBGSTR( pszArchitecture ) ) );
  1128. DBGMSG( DBG_TRACE, ( "Version "TSTR"\n", DBGSTR( pszVersion ) ) );
  1129. DBGMSG( DBG_TRACE, ( "InfName "TSTR"\n", DBGSTR( pszInfName ) ) );
  1130. DBGMSG( DBG_TRACE, ( "SourcePath "TSTR"\n", DBGSTR( pszSourcePath ) ) );
  1131. SPLASSERT( pszDriverName );
  1132. SPLASSERT( pdwError );
  1133. // check if we are supposed to suppress the setup warnings UI
  1134. // -- i.e. in super quiet mode.
  1135. if( dwFlags & kPnPInterface_SupressSetupUI )
  1136. {
  1137. SetupSetNonInteractiveMode(TRUE);
  1138. }
  1139. TStatusB bStatus;
  1140. DWORD dwEncode = 0;
  1141. TString strInfName( pszInfName );
  1142. bStatus DBGNOCHK = TRUE;
  1143. DWORD dwLastError = ERROR_SUCCESS;
  1144. //
  1145. // Set the last error to a known state.
  1146. //
  1147. SetLastError( ERROR_SUCCESS );
  1148. bStatus DBGCHK = GetOrUseInfName(strInfName);
  1149. if( bStatus )
  1150. {
  1151. TPrinterDriverInstallation Di( pszServerName );
  1152. bStatus DBGCHK = VALID_OBJ( Di );
  1153. if( bStatus )
  1154. {
  1155. if( pszArchitecture && pszVersion )
  1156. {
  1157. bStatus DBGCHK = TArchLV::bArchAndVersionToEncode(&dwEncode,
  1158. pszArchitecture,
  1159. pszVersion,
  1160. dwFlags & kPnPInterface_UseNonLocalizedStrings);
  1161. }
  1162. else
  1163. {
  1164. //
  1165. // Get this machines current encoding.
  1166. //
  1167. bStatus DBGCHK = Di.bGetCurrentDriverEncode(&dwEncode);
  1168. }
  1169. }
  1170. if( bStatus )
  1171. {
  1172. bStatus DBGCHK = Di.bSetDriverName( pszDriverName ) &&
  1173. Di.bSetSourcePath( pszSourcePath ) &&
  1174. Di.bSelectDriverFromInf( strInfName );
  1175. if( bStatus )
  1176. {
  1177. DWORD dwInstallFlags = 0;
  1178. //
  1179. // If the we are in quiet mode.
  1180. //
  1181. if( dwFlags & kPnPInterface_Quiet )
  1182. {
  1183. dwInstallFlags |= (DRVINST_PROGRESSLESS | DRVINST_PROMPTLESS);
  1184. }
  1185. if( dwFlags & kPnPInterface_WindowsUpdate )
  1186. {
  1187. dwInstallFlags |= DRVINST_WINDOWS_UPDATE;
  1188. }
  1189. //
  1190. // If the source path was specified then use a flat share.
  1191. //
  1192. if( pszSourcePath )
  1193. {
  1194. dwInstallFlags |= DRVINST_FLATSHARE;
  1195. }
  1196. //
  1197. // Set the install flags.
  1198. //
  1199. Di.SetInstallFlags( dwInstallFlags );
  1200. //
  1201. // Install the driver.
  1202. //
  1203. bStatus DBGCHK = Di.bInstallDriver(NULL, FALSE, FALSE, NULL, dwEncode );
  1204. //
  1205. // Save the last error here, because the destructor
  1206. // of the TPrinterDriverInstallation will stomp it.
  1207. //
  1208. dwLastError = GetLastError();
  1209. }
  1210. }
  1211. }
  1212. if( !bStatus )
  1213. {
  1214. if( dwLastError == ERROR_SUCCESS )
  1215. dwLastError = ERROR_INVALID_PARAMETER;
  1216. }
  1217. else
  1218. {
  1219. dwLastError = ERROR_SUCCESS;
  1220. }
  1221. // turn back on the setup warnings UI if necessary
  1222. if( dwFlags & kPnPInterface_SupressSetupUI )
  1223. {
  1224. SetupSetNonInteractiveMode(FALSE);
  1225. }
  1226. SetLastError( dwLastError );
  1227. *pdwError = dwLastError;
  1228. return bStatus;
  1229. }
  1230. BOOL
  1231. bRemovePrinterDriver(
  1232. IN LPCTSTR pszServerName,
  1233. IN LPCTSTR pszDriverName,
  1234. IN LPCTSTR pszArchitecture,
  1235. IN LPCTSTR pszVersion,
  1236. IN DWORD dwFlags,
  1237. IN DWORD *pdwError
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. Remove the specified printer driver.
  1242. Arguments:
  1243. pszServerName - Name of server that printer is on.
  1244. Return Value:
  1245. TRUE = Success, FALSE = FAILURE.
  1246. --*/
  1247. {
  1248. DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bRemove\n" ) );
  1249. TString strEnv;
  1250. TStatusB bStatus;
  1251. DWORD dwEncode;
  1252. bStatus DBGNOCHK = TRUE;
  1253. if( pszArchitecture && pszVersion )
  1254. {
  1255. //
  1256. // Convert the architecture and version string to a driver encoding.
  1257. //
  1258. bStatus DBGCHK = TArchLV::bArchAndVersionToEncode(&dwEncode,
  1259. pszArchitecture,
  1260. pszVersion,
  1261. dwFlags & kPnPInterface_UseNonLocalizedStrings);
  1262. }
  1263. else
  1264. {
  1265. //
  1266. // get default environment and version
  1267. //
  1268. bStatus DBGCHK = bGetCurrentDriver( pszServerName, &dwEncode );
  1269. }
  1270. if( bStatus )
  1271. {
  1272. bStatus DBGCHK = bGetDriverEnv( dwEncode, strEnv );
  1273. if( bStatus )
  1274. {
  1275. //
  1276. // Delete the specfied printer driver.
  1277. //
  1278. bStatus DBGCHK = DeletePrinterDriverEx( const_cast<LPTSTR>( pszServerName ),
  1279. const_cast<LPTSTR>( static_cast<LPCTSTR>( strEnv ) ),
  1280. const_cast<LPTSTR>( pszDriverName ),
  1281. DPD_DELETE_UNUSED_FILES|DPD_DELETE_SPECIFIC_VERSION,
  1282. GetDriverVersion( dwEncode ) );
  1283. //
  1284. // If we are trying this action on a down level spooler.
  1285. //
  1286. if( !bStatus && GetLastError() == RPC_S_PROCNUM_OUT_OF_RANGE )
  1287. {
  1288. bStatus DBGCHK = DeletePrinterDriver( const_cast<LPTSTR>( pszServerName ),
  1289. const_cast<LPTSTR>( static_cast<LPCTSTR>( strEnv ) ),
  1290. const_cast<LPTSTR>( pszDriverName ) );
  1291. }
  1292. }
  1293. else
  1294. {
  1295. SetLastError( ERROR_BAD_ENVIRONMENT );
  1296. }
  1297. }
  1298. else
  1299. {
  1300. SetLastError( ERROR_BAD_ENVIRONMENT );
  1301. }
  1302. //
  1303. // If an error occurred then preserve the last error.
  1304. // Note: The calling of destructors will modify the last error.
  1305. //
  1306. if( !bStatus )
  1307. {
  1308. *pdwError = GetLastError();
  1309. }
  1310. return bStatus;
  1311. }
  1312. BOOL
  1313. bInstallWizard(
  1314. IN LPCTSTR pszServerName,
  1315. IN OUT PSP_INSTALLWIZARD_DATA pWizardData,
  1316. IN OUT PVOID *pReferenceData,
  1317. OUT PDWORD pdwError
  1318. )
  1319. /*++
  1320. Routine Description:
  1321. Addes our wizard pages to the set of passed in pages. The pages
  1322. are only appended to the passed in pages.
  1323. Arguments:
  1324. pszServerName - Name of server that printer is on.
  1325. pWizardData - Pointer to wizard data structure see setupapi.h
  1326. Return Value:
  1327. TRUE = Success, FALSE = FAILURE.
  1328. Notes:
  1329. The wizard object is orphaned to the caller if successfull. It's the
  1330. callers responsibility to clean up if ProperySheets() is not called.
  1331. In the case caller does call PropertySheets() the wizard object will
  1332. be release at or near WM_DESTROY time.
  1333. --*/
  1334. {
  1335. DBGMSG( DBG_TRACE, ( "bInstallWizard\n" ) );
  1336. SPLASSERT( pWizardData );
  1337. DBGMSG( DBG_TRACE, ( "ServerName "TSTR"\n", DBGSTR( pszServerName ) ) );
  1338. DBGMSG( DBG_TRACE, ( "WizardData %08x\n", pWizardData ) );
  1339. DBGMSG( DBG_TRACE, ( "RefrenceData %08x\n", *pReferenceData ) );
  1340. DBGMSG( DBG_TRACE, ( "InstallWizardData:\n" ) );
  1341. DBGMSG( DBG_TRACE, ( "ClassInstallHeader %08x\n", &pWizardData->ClassInstallHeader ) );
  1342. DBGMSG( DBG_TRACE, ( "Flags %x\n", pWizardData->Flags ) );
  1343. DBGMSG( DBG_TRACE, ( "DynamicPages %08x\n", pWizardData->DynamicPages ) );
  1344. DBGMSG( DBG_TRACE, ( "NumDynamicPages %d\n", pWizardData->NumDynamicPages ) );
  1345. DBGMSG( DBG_TRACE, ( "DynamicPageFlags %x\n", pWizardData->DynamicPageFlags ) );
  1346. DBGMSG( DBG_TRACE, ( "PrivateFlags %x\n", pWizardData->PrivateFlags ) );
  1347. DBGMSG( DBG_TRACE, ( "PrivateData %08x\n", pWizardData->PrivateData ) );
  1348. DBGMSG( DBG_TRACE, ( "hwndWizardDlg %x\n", pWizardData->hwndWizardDlg ) );
  1349. TStatusB bReturn;
  1350. //
  1351. // Create the wizard object.
  1352. //
  1353. TWizard *pWizard = new TWizard( pWizardData->hwndWizardDlg, TWizard::kPnPInstall, gszNULL, pszServerName );
  1354. //
  1355. // Check if the wizard was constructed ok.
  1356. //
  1357. if( VALID_PTR( pWizard ))
  1358. {
  1359. //
  1360. // Add our wizard pages to the array of pages.
  1361. //
  1362. bReturn DBGCHK = pWizard->bAddPages( pWizardData );
  1363. }
  1364. else
  1365. {
  1366. bReturn DBGNOCHK = FALSE;
  1367. }
  1368. //
  1369. // If we failed then clean up the wizard object.
  1370. //
  1371. if( !bReturn )
  1372. {
  1373. *pdwError = GetLastError();
  1374. delete pWizard;
  1375. pWizard = NULL;
  1376. }
  1377. //
  1378. // Copy back the reference data.
  1379. //
  1380. *pReferenceData = pWizard;
  1381. DBGMSG( DBG_TRACE, ( "RefrenceData %08x\n", *pReferenceData ) );
  1382. return bReturn;
  1383. }
  1384. BOOL
  1385. bDestroyWizard(
  1386. IN LPCTSTR pszServerName,
  1387. IN OUT PSP_INSTALLWIZARD_DATA pWizardData,
  1388. IN PVOID pReferenceData,
  1389. OUT PDWORD pdwError
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. Destroys our wizard pages and any associated data that
  1394. was created during a bInstallWizard call.
  1395. Arguments:
  1396. pszServerName - Name of server that printer is on.
  1397. pWizardData - Pointer to wizard data structure see setupapi.h
  1398. Return Value:
  1399. TRUE = Success, FALSE = FAILURE.
  1400. Notes:
  1401. --*/
  1402. {
  1403. DBGMSG( DBG_TRACE, ( "bDestroyWizard\n" ) );
  1404. SPLASSERT( pWizardData );
  1405. DBGMSG( DBG_TRACE, ( "ServerName "TSTR"\n", DBGSTR( pszServerName ) ) );
  1406. DBGMSG( DBG_TRACE, ( "WizardData %08x\n", pWizardData ) );
  1407. DBGMSG( DBG_TRACE, ( "RefrenceData %08x\n", pReferenceData ) );
  1408. TWizard *pWizard = (TWizard *)pReferenceData;
  1409. SPLASSERT( pWizard );
  1410. delete pWizard;
  1411. return TRUE;
  1412. }
  1413. BOOL
  1414. bInfInstall(
  1415. IN LPCTSTR pszServerName,
  1416. IN LPCTSTR pszInfName,
  1417. IN LPCTSTR pszModelName,
  1418. IN LPCTSTR pszPortName,
  1419. IN OUT LPTSTR pszPrinterNameBuffer,
  1420. IN UINT cchPrinterName,
  1421. IN LPCTSTR pszSourcePath,
  1422. IN DWORD dwFlags,
  1423. IN DWORD dwAttributes,
  1424. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1425. IN OUT PDWORD pdwOutFlags,
  1426. OUT PDWORD pdwError
  1427. )
  1428. /*++
  1429. Routine Description:
  1430. Inf install of a printer.
  1431. Arguments:
  1432. pszServerName; // Machine name NULL equals local machine
  1433. pszInfName; // Name of INF file including full path
  1434. pszModelName; // Model name of printer in inf to install
  1435. pszPortName; // Port name where to install printer
  1436. pszPrinterNameBuffer; // Base printer name, Note if a printer exists
  1437. // with this name a unique name will be
  1438. // generated ie. "printer (Copy 1)". This parameter
  1439. // may contain the null string in which case the printer
  1440. // name will be auto generated using the model name
  1441. // as the base name. This parameter can be null,
  1442. // and the new name will not be copied back
  1443. cchPrinterName; // Size of printer name buffer in characters
  1444. pdwOutFlags // Flags returned to the caller.
  1445. Return Value:
  1446. TRUE = Success, FALSE = FAILURE.
  1447. Notes:
  1448. --*/
  1449. {
  1450. SPLASSERT( pszModelName );
  1451. SPLASSERT( pszPortName );
  1452. SPLASSERT( pszPrinterNameBuffer );
  1453. SPLASSERT( cchPrinterName );
  1454. SPLASSERT( pdwError );
  1455. DBGMSG( DBG_TRACE, ( "pszServerName " TSTR "\n", DBGSTR( pszServerName ) ) );
  1456. DBGMSG( DBG_TRACE, ( "pszSourcePath " TSTR "\n", DBGSTR( pszSourcePath ) ) );
  1457. DBGMSG( DBG_TRACE, ( "pszInfName " TSTR "\n", pszInfName ) );
  1458. DBGMSG( DBG_TRACE, ( "pszModelName " TSTR "\n", pszModelName ) );
  1459. DBGMSG( DBG_TRACE, ( "pszPortName " TSTR "\n", pszPortName ) );
  1460. DBGMSG( DBG_TRACE, ( "pszPrinterNameBuffer " TSTR "\n", DBGSTR( pszPrinterNameBuffer ) ) );
  1461. DBGMSG( DBG_TRACE, ( "cchPrinterName %d\n", cchPrinterName ) );
  1462. DBGMSG( DBG_TRACE, ( "dwFlags %x\n", dwFlags ) );
  1463. // check if we are supposed to suppress the setup warnings UI
  1464. // -- i.e. in super quiet mode.
  1465. if( dwFlags & kPnPInterface_SupressSetupUI )
  1466. {
  1467. SetupSetNonInteractiveMode(TRUE);
  1468. }
  1469. if (pdwOutFlags)
  1470. {
  1471. *pdwOutFlags = 0;
  1472. }
  1473. TStatusB bStatus;
  1474. TString strDriverName( pszModelName );
  1475. TPrinterDriverInstallation Di( pszServerName, GetDesktopWindow() );
  1476. TCHAR szSourcePath[MAX_PATH];
  1477. DWORD dwDefaultInstallFlags = 0;
  1478. TString strInfName(pszInfName);
  1479. BOOL bOfferReplacementDriver = FALSE;
  1480. //
  1481. // Get a valid inf file name.
  1482. //
  1483. bStatus DBGCHK = GetOrUseInfName(strInfName);
  1484. //
  1485. // If we are doing an install as a result of web point and print
  1486. // we don't want to copy the inf or install driver files.
  1487. //
  1488. if( dwFlags & kPnPInterface_WebPointAndPrint )
  1489. {
  1490. dwDefaultInstallFlags |= (DRVINST_DONOTCOPY_INF | DRVINST_DRIVERFILES_ONLY | DRVINST_WEBPNP);
  1491. //
  1492. // If the source path has not been set then use the current working directory,
  1493. // this is necessary for web point and print because they do not pass use a path,
  1494. // because the uncompression code just runs in the current directory.
  1495. //
  1496. if( !pszSourcePath || !*pszSourcePath)
  1497. {
  1498. if( GetCurrentDirectory( COUNTOF( szSourcePath ), szSourcePath ) )
  1499. {
  1500. pszSourcePath = szSourcePath;
  1501. }
  1502. }
  1503. DBGMSG( DBG_TRACE, ( "Source Path " TSTR "\n", DBGSTR( pszSourcePath ) ) );
  1504. }
  1505. //
  1506. // If we are given a source path we will do a flat share install.
  1507. //
  1508. if( pszSourcePath && *pszSourcePath )
  1509. {
  1510. dwDefaultInstallFlags |= DRVINST_FLATSHARE;
  1511. }
  1512. //
  1513. // If we are supposed to prompt for the CD.
  1514. //
  1515. if( dwFlags & kPnPInterface_PromptForCD )
  1516. {
  1517. dwDefaultInstallFlags &= ~DRVINST_FLATSHARE;
  1518. pszSourcePath = NULL;
  1519. }
  1520. //
  1521. // If we are supposed to suppress the copying progress UI.
  1522. //
  1523. if( dwFlags & kPnPInterface_Quiet )
  1524. {
  1525. dwDefaultInstallFlags |= (DRVINST_PROGRESSLESS | DRVINST_PROMPTLESS);
  1526. }
  1527. //
  1528. // Prompt if files are needed.
  1529. //
  1530. if( dwFlags & kPnPInterface_PromptIfFileNeeded )
  1531. {
  1532. dwDefaultInstallFlags &= ~DRVINST_PROMPTLESS;
  1533. }
  1534. //
  1535. // Set the install flags.
  1536. //
  1537. Di.SetInstallFlags( dwDefaultInstallFlags );
  1538. //
  1539. // Check if the driver installation class is valid,
  1540. // We were able to set the driver name,
  1541. //
  1542. bStatus DBGCHK = bStatus &&
  1543. VALID_OBJ( strInfName ) &&
  1544. VALID_OBJ( Di ) &&
  1545. VALID_OBJ( strDriverName ) &&
  1546. Di.bSetDriverName( strDriverName ) &&
  1547. Di.bSetSourcePath( pszSourcePath );
  1548. //
  1549. // If the driver name is an empty string, we treat this as
  1550. // an unknown printer driver.
  1551. //
  1552. if( bStatus )
  1553. {
  1554. bStatus DBGCHK = !strDriverName.bEmpty();
  1555. if( !bStatus )
  1556. {
  1557. SetLastError( ERROR_UNKNOWN_PRINTER_DRIVER );
  1558. }
  1559. }
  1560. //
  1561. // Assume we should install the driver.
  1562. //
  1563. BOOL bInstallDriver = TRUE;
  1564. if( bStatus )
  1565. {
  1566. //
  1567. // If were asked to use the existing driver if it is installed.
  1568. //
  1569. if( dwFlags & kPnpInterface_UseExisting )
  1570. {
  1571. //
  1572. // Check if a compatible printer driver is installed.
  1573. //
  1574. bInstallDriver = !Di.bIsDriverInstalled( TPrinterDriverInstallation::kDefault, TRUE );
  1575. }
  1576. //
  1577. // Driver is not installed or we were asked not to use the existing driver.
  1578. //
  1579. if( bInstallDriver )
  1580. {
  1581. bStatus DBGCHK = Di.bSelectDriverFromInf( strInfName ) &&
  1582. Di.bInstallDriver(NULL, bOfferReplacementDriver);
  1583. }
  1584. }
  1585. //
  1586. // Prompt the user if the driver is not known, then add the driver failed installation.
  1587. //
  1588. if( !bStatus && GetLastError() == ERROR_UNKNOWN_PRINTER_DRIVER && ( dwFlags & kPnpInterface_PromptIfUnknownDriver ) )
  1589. {
  1590. bStatus DBGCHK = bPromptForUnknownDriver( Di, strDriverName, dwFlags );
  1591. }
  1592. if( bStatus )
  1593. {
  1594. //
  1595. // Install the printer using specified printer driver.
  1596. //
  1597. bStatus DBGCHK = bPrinterInstall( pszServerName,
  1598. strDriverName,
  1599. pszPortName,
  1600. pszPrinterNameBuffer,
  1601. cchPrinterName,
  1602. dwFlags,
  1603. dwAttributes,
  1604. pSecurityDescriptor,
  1605. pdwError );
  1606. }
  1607. //
  1608. // Preserve the last error.
  1609. //
  1610. *pdwError = bStatus ? ERROR_SUCCESS : GetLastError();
  1611. //
  1612. // Success
  1613. //
  1614. if( bStatus )
  1615. {
  1616. TString strFullPrinterName;
  1617. BOOL bColor = FALSE;
  1618. //
  1619. // Get the full printer name and check if the printer supports color
  1620. //
  1621. bStatus DBGCHK = bBuildFullPrinterName(pszServerName, pszPrinterNameBuffer, strFullPrinterName) &&
  1622. SUCCEEDED(IsColorPrinter(strFullPrinterName, &bColor));
  1623. if (bStatus && pdwOutFlags && bColor)
  1624. {
  1625. //
  1626. // Update the flags returned to the caller. TS is interested if the printer installed
  1627. // supports color or not. TS will save ICM color profiles for color printers.
  1628. //
  1629. *pdwOutFlags |= kAdvInf_ColorPrinter;
  1630. }
  1631. //
  1632. // At this point bInstallDriver has the following meaning: TRUE means that the driver
  1633. // was installed in this function before the printer was added. FALSE means that the
  1634. // driver was already present on the machine.
  1635. //
  1636. // If the driver was already installed on the machine and our caller wants us to take
  1637. // care of color profiles, then we check if the printer suports color and we reinstall
  1638. // the driver. By doing so, Di is populated with all the extra information needed by
  1639. // vPrinterAdded(). That function performs things like installing ICM color profiles
  1640. //
  1641. if (bStatus &&
  1642. !bInstallDriver &&
  1643. dwFlags & kPnPInterface_InstallColorProfiles &&
  1644. bColor)
  1645. {
  1646. //
  1647. // By reinstalling the driver we get the extra infromation about the
  1648. // ICM color profiles
  1649. //
  1650. bStatus DBGCHK = Di.bSelectDriverFromInf(strInfName) &&
  1651. Di.bInstallDriver(NULL, bOfferReplacementDriver);
  1652. //
  1653. // We successfully installed the driver. We need to update the bInstallDriver
  1654. // variable so that vPrinterAdded will be called below.
  1655. //
  1656. if (bStatus)
  1657. {
  1658. bInstallDriver = TRUE;
  1659. }
  1660. }
  1661. //
  1662. // Inform the printer class installer that a printer was added.
  1663. // This is need to for vendor installition options that
  1664. // may have been specified in the inf.
  1665. //
  1666. if (bStatus && bInstallDriver)
  1667. {
  1668. Di.vPrinterAdded( strFullPrinterName );
  1669. }
  1670. //
  1671. // Our basic operation of adding the printer succeeded. We will not fail
  1672. // the bInfInstall function call or return an error if the code that does
  1673. // the ICM association and updates other settings happens to fail.
  1674. //
  1675. bStatus DBGNOCHK = TRUE;
  1676. }
  1677. // turn back on the setup warnings UI if necessary
  1678. if( dwFlags & kPnPInterface_SupressSetupUI )
  1679. {
  1680. SetupSetNonInteractiveMode(FALSE);
  1681. }
  1682. return bStatus;
  1683. }
  1684. BOOL
  1685. bPromptForUnknownDriver(
  1686. IN TPrinterDriverInstallation &Di,
  1687. IN TString &strDriverName,
  1688. IN DWORD dwFlags
  1689. )
  1690. /*++
  1691. Routine Description:
  1692. Prompts the user for a printer driver.
  1693. Arguments:
  1694. Return Value:
  1695. TRUE = Success, FALSE = FAILURE.
  1696. Notes:
  1697. --*/
  1698. {
  1699. TStatusB bStatus;
  1700. //
  1701. // Put up a message telling the user they must select the driver.
  1702. //
  1703. if( iMessage( Di.hGetHwnd(),
  1704. IDS_ERR_ADD_PRINTER_TITLE,
  1705. 0 == strDriverName.uLen() ? IDS_CONFIRMUNKNOWNDRIVER : IDS_CONFIRMKNOWNDRIVER,
  1706. MB_OKCANCEL | MB_ICONEXCLAMATION,
  1707. kMsgNone,
  1708. NULL,
  1709. (LPCTSTR)strDriverName ) == IDOK )
  1710. {
  1711. bStatus DBGNOCHK = TRUE;
  1712. }
  1713. else
  1714. {
  1715. bStatus DBGNOCHK = FALSE;
  1716. SetLastError(ERROR_CANCELLED);
  1717. }
  1718. if( bStatus )
  1719. {
  1720. if( dwFlags & kPnpInterface_HydraSpecific )
  1721. {
  1722. //
  1723. // Remove the have disk button.
  1724. //
  1725. Di.bShowOem( FALSE );
  1726. TString strSetupPageTitle, strSetupPageSubTitle, strSetupPageInstructions;
  1727. //
  1728. // Update the title, subtite & description of the setup page
  1729. //
  1730. bStatus DBGCHK = strSetupPageTitle.bLoadString( ghInst, IDS_APW_SETUP_PAGE_TITLE) &&
  1731. strSetupPageSubTitle.bLoadString( ghInst, IDS_APW_SETUP_PAGE_SUBTITLE) &&
  1732. strSetupPageInstructions.bLoadString( ghInst, IDS_APW_SETUP_PAGE_INSTRUCT_HYDRA) &&
  1733. Di.bSetDriverSetupPageTitle( strSetupPageTitle, strSetupPageSubTitle, strSetupPageInstructions );
  1734. }
  1735. if( bStatus )
  1736. {
  1737. //
  1738. // Prompt the user for a driver, since the one we were given was not found.
  1739. //
  1740. bStatus DBGNOCHK = (TPrinterDriverInstallation::EStatusCode::kSuccess == Di.ePromptForDriverSelection());
  1741. if( bStatus )
  1742. {
  1743. //
  1744. // Get the selected driver.
  1745. //
  1746. bStatus DBGCHK = Di.bGetSelectedDriver();
  1747. if( bStatus )
  1748. {
  1749. //
  1750. // Get the selected driver name.
  1751. //
  1752. bStatus DBGCHK = Di.bGetDriverName( strDriverName );
  1753. if( bStatus )
  1754. {
  1755. //
  1756. // If the driver the user selected is already installed then do not re-install it.
  1757. //
  1758. if( !Di.bIsDriverInstalled() )
  1759. {
  1760. //
  1761. // The driver was not installed then install it now.
  1762. //
  1763. BOOL bOfferReplacementDriver = TRUE;
  1764. bStatus DBGCHK = Di.bInstallDriver(&strDriverName, bOfferReplacementDriver);
  1765. }
  1766. }
  1767. }
  1768. }
  1769. }
  1770. }
  1771. return bStatus;
  1772. }
  1773. /********************************************************************
  1774. TPrinterSetupData class.
  1775. ********************************************************************/
  1776. TPrinterSetupData::
  1777. TPrinterSetupData(
  1778. IN HWND hwnd,
  1779. IN UINT uAction,
  1780. IN UINT cchPrinterName,
  1781. IN OUT LPTSTR pszPrinterName,
  1782. OUT UINT* pcchPrinterName,
  1783. IN LPCTSTR pszServerName,
  1784. IN LPCTSTR pszWindowName,
  1785. IN LPCTSTR pszInfFileName,
  1786. IN BOOL bModal,
  1787. IN BOOL bRestartableFromLastPage
  1788. ) : MSingletonWin( pszWindowName, hwnd, bModal ),
  1789. _uAction( uAction ),
  1790. _cchPrinterName( cchPrinterName ),
  1791. _pcchPrinterName( pcchPrinterName ),
  1792. _pszPrinterName( pszPrinterName ),
  1793. _pszServerName( NULL ),
  1794. _strPrinterName( pszPrinterName ),
  1795. _strServerName( pszServerName ),
  1796. _strInfFileName( pszInfFileName ),
  1797. _bValid( FALSE ),
  1798. _bRestartableFromLastPage( bRestartableFromLastPage )
  1799. /*++
  1800. Routine Description:
  1801. Create the small setup data class for running the add printer
  1802. wizard in a separate thread.
  1803. Arguments:
  1804. hwnd - Parent window.
  1805. uAction - Action requested (defined in windows\inc16\msprintx.h)
  1806. cchPrinterName - Length of pszPrinterName buffer.
  1807. pszPrinterName - Input setup printer name, Output pointer to new printer name
  1808. pcchPrinterName - New length of pszPrinterName on return.
  1809. pszServerName - Name of server that printer is on.
  1810. pszWindowName - Name of the sub window for creating the singleton.
  1811. Return Value:
  1812. TRUE - Success, FALSE = FAILURE.
  1813. Notes:
  1814. --*/
  1815. {
  1816. DBGMSG( DBG_TRACE, ( "TPinterSetupData::ctor\n" ) );
  1817. DBGMSG( DBG_TRACE, ( "TPinterSetupData::ServerName " TSTR "\n", (LPCTSTR)_strServerName ) );
  1818. DBGMSG( DBG_TRACE, ( "TPinterSetupData::PrinterName " TSTR "\n", (LPCTSTR)_strPrinterName ) );
  1819. DBGMSG( DBG_TRACE, ( "TPinterSetupData::WindowName " TSTR "\n", (LPCTSTR)pszWindowName ) );
  1820. //
  1821. // Check for valid singleton window.
  1822. //
  1823. if( MSingletonWin::bValid( ) &&
  1824. _strServerName.bValid( ) &&
  1825. _strPrinterName.bValid( ) &&
  1826. _strInfFileName.bValid( ) ){
  1827. //
  1828. // Since we are starting a separate thread the server name
  1829. // pointer must point to valid storage when the thread is
  1830. // executing.
  1831. //
  1832. if( !_strServerName.bEmpty() ){
  1833. _pszServerName = (LPCTSTR)_strServerName;
  1834. }
  1835. _bValid = TRUE;
  1836. }
  1837. }
  1838. TPrinterSetupData::
  1839. ~TPrinterSetupData(
  1840. VOID
  1841. )
  1842. /*++
  1843. Routine Description:
  1844. Destructor
  1845. Arguments:
  1846. None
  1847. Return Value:
  1848. Nothing.
  1849. Notes:
  1850. --*/
  1851. {
  1852. DBGMSG( DBG_TRACE, ( "TPinterSetupData::dtor\n" ) );
  1853. }
  1854. BOOL
  1855. TPrinterSetupData::
  1856. bValid(
  1857. VOID
  1858. )
  1859. /*++
  1860. Routine Description:
  1861. Indicates if the class is valid.
  1862. Arguments:
  1863. None
  1864. Return Value:
  1865. Nothing.
  1866. Notes:
  1867. --*/
  1868. {
  1869. return _bValid;
  1870. }
  1871. INT
  1872. TPrinterSetupData::
  1873. iPrinterSetupProc(
  1874. IN TPrinterSetupData *pSetupData ADOPT
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. Brings up the install printer wizard.
  1879. Arguments:
  1880. pSetupData - pointer to setup data clsss which we adopt.
  1881. Return Value:
  1882. TRUE - Success, FALSE = FAILURE.
  1883. --*/
  1884. {
  1885. DBGMSG( DBG_TRACE, ( "TPrinterSetup::iPrinterSetupProc\n" ) );
  1886. TStatusB bStatus;
  1887. bStatus DBGNOCHK = FALSE;
  1888. BOOL bCancelled = FALSE;
  1889. BOOL bSkipIntroPageDueToRestart = FALSE;
  1890. BOOL bWizardDone = FALSE;
  1891. INT iPosX = -1;
  1892. INT iPosY = -1;
  1893. //
  1894. // Register the singleton window.
  1895. //
  1896. bStatus DBGCHK = pSetupData->MSingletonWin::bRegisterWindow( PRINTER_PIDL_TYPE_PROPERTIES );
  1897. if( bStatus ){
  1898. //
  1899. // Check if the window is already present.
  1900. //
  1901. if( pSetupData->bIsWindowPresent() ){
  1902. DBGMSG( DBG_TRACE, ( "bPrinterSetup: currently running.\n" ) );
  1903. bStatus DBGNOCHK = FALSE;
  1904. }
  1905. //
  1906. // If registering the singlton window failed.
  1907. //
  1908. } else {
  1909. iMessage( NULL,
  1910. IDS_ERR_ADD_PRINTER_TITLE,
  1911. IDS_ERR_ADD_PRINTER_WINDOW,
  1912. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  1913. kMsgGetLastError,
  1914. NULL );
  1915. }
  1916. if( bStatus ){
  1917. //
  1918. // Set the correct icon in the alt-tab menu. This is shared icon,
  1919. // (obtained through LoadIcon()), so it doesn't need to be destroyed.
  1920. //
  1921. HICON hIcon = LoadIcon( ghInst, MAKEINTRESOURCE( IDI_PRINTER ) );
  1922. if( hIcon ) {
  1923. SendMessage( pSetupData->hwnd(), WM_SETICON, ICON_BIG, (LPARAM )hIcon );
  1924. }
  1925. }
  1926. for( ; bStatus && !bWizardDone; ) {
  1927. //
  1928. // Create the wizard object.
  1929. //
  1930. TWizard Wizard( pSetupData->_hwnd,
  1931. pSetupData->_uAction,
  1932. pSetupData->_strPrinterName,
  1933. pSetupData->_pszServerName );
  1934. if( !VALID_OBJ( Wizard )){
  1935. vShowResourceError( pSetupData->_hwnd );
  1936. bStatus DBGNOCHK = FALSE;
  1937. } else {
  1938. //
  1939. // Set the inf file name if one was provided.
  1940. //
  1941. Wizard.strInfFileName().bUpdate( pSetupData->_strInfFileName );
  1942. Wizard.bRestartableFromLastPage() = pSetupData->_bRestartableFromLastPage;
  1943. Wizard.bRestartAgain() = bSkipIntroPageDueToRestart;
  1944. Wizard.iPosX() = iPosX;
  1945. Wizard.iPosY() = iPosY;
  1946. //
  1947. // Display the wizard pages.
  1948. //
  1949. bStatus DBGCHK = Wizard.bPropPages();
  1950. if( bStatus && Wizard.bShouldRestart() ) {
  1951. //
  1952. // Second time through the wizard we skip the into page.
  1953. //
  1954. bSkipIntroPageDueToRestart = TRUE;
  1955. iPosX = Wizard.iPosX();
  1956. iPosY = Wizard.iPosY();
  1957. continue;
  1958. } else {
  1959. bCancelled = Wizard.bWizardCanceled();
  1960. bWizardDone = TRUE;
  1961. }
  1962. if( bStatus ) {
  1963. //
  1964. // If modal copy back the printer name to the provided buffer.
  1965. //
  1966. if( pSetupData->_uAction == TWizard::kPrinterInstall ){
  1967. UINT uPrinterNameLength = Wizard.strPrinterName().uLen();
  1968. //
  1969. // Check if the provided return buffer is big enough.
  1970. //
  1971. if( pSetupData->_cchPrinterName > uPrinterNameLength ){
  1972. //
  1973. // Copy the name of the new printer into pszPrintername.
  1974. //
  1975. _tcscpy( pSetupData->_pszPrinterName, Wizard.strPrinterName( ));
  1976. *pSetupData->_pcchPrinterName = uPrinterNameLength;
  1977. } else {
  1978. DBGMSG( DBG_WARN, ( "bPrinterSetup: printer "TSTR" too long.\n", (LPCTSTR)Wizard.strPrinterName( )));
  1979. //
  1980. // We don't fail the call if the provided buffer is too small since the
  1981. // printer was created, instead we will clear the printer name length,
  1982. // maybe this will mean something to the caller.
  1983. //
  1984. *pSetupData->_pcchPrinterName = 0;
  1985. }
  1986. }
  1987. }
  1988. }
  1989. }
  1990. DBGMSG( DBG_TRACE, ( "bPrinterSetup: returned %d.\n", bStatus ) );
  1991. //
  1992. // Release the adopted se-tup data.
  1993. //
  1994. delete pSetupData;
  1995. if( bCancelled )
  1996. {
  1997. SetLastError( ERROR_CANCELLED );
  1998. }
  1999. return bStatus;
  2000. }
  2001. /********************************************************************
  2002. Page switch controller class (implements IPageSwitch)
  2003. ********************************************************************/
  2004. TPageSwitch::
  2005. TPageSwitch(
  2006. TWizard *pWizard
  2007. ): _pWizard( pWizard )
  2008. {
  2009. }
  2010. TPageSwitch::
  2011. ~TPageSwitch(
  2012. VOID
  2013. )
  2014. {
  2015. // do nothing
  2016. }
  2017. STDMETHODIMP
  2018. TPageSwitch::
  2019. GetPrevPageID( THIS_ UINT *puPageID )
  2020. {
  2021. //
  2022. // Just pop the page ID from the stack
  2023. //
  2024. _pWizard->Stack().bPop( puPageID );
  2025. // OK - allow switching to the prev page
  2026. return S_OK;
  2027. }
  2028. STDMETHODIMP
  2029. TPageSwitch::
  2030. GetNextPageID( THIS_ UINT *puPageID )
  2031. {
  2032. //
  2033. // Assume don't advance to the next page
  2034. //
  2035. HRESULT hResult = S_FALSE;
  2036. //
  2037. // Check if the connection has been made sucessfully?
  2038. //
  2039. if( _pWizard->bConnected() )
  2040. {
  2041. //
  2042. // Check for any default printer.
  2043. //
  2044. if( !_pWizard->bIsPrinterFolderEmpty() )
  2045. {
  2046. //
  2047. // Always set it as the default.
  2048. //
  2049. _pWizard->bSetDefault() = TRUE;
  2050. //
  2051. // Don't show the set as default UI.
  2052. //
  2053. _pWizard->bShowSetDefault() = FALSE;
  2054. }
  2055. //
  2056. // Save the current page ID
  2057. //
  2058. TStatusB bStatus;
  2059. bStatus DBGCHK = _pWizard->Stack().bPush( _pWizard->nBrowsePageID( ) );
  2060. //
  2061. // Here must determine the next page ID
  2062. //
  2063. if( _pWizard->bShowSetDefault() )
  2064. {
  2065. //
  2066. // Ask the user if he want to change the default
  2067. // printer
  2068. //
  2069. *puPageID = DLG_WIZ_NET;
  2070. }
  2071. else
  2072. {
  2073. //
  2074. // Set the printer as default and go directly to
  2075. // the finish page
  2076. //
  2077. *puPageID = DLG_WIZ_FINISH;
  2078. }
  2079. //
  2080. // OK - allow to advance to the next page
  2081. //
  2082. hResult = S_OK;
  2083. }
  2084. return hResult;
  2085. }
  2086. STDMETHODIMP
  2087. TPageSwitch::
  2088. SetPrinterInfo( THIS_ LPCTSTR pszPrinterName, LPCTSTR pszComment, LPCTSTR pszLocation, LPCTSTR pszShareName )
  2089. {
  2090. //
  2091. // Indicate a printer connection has been made.
  2092. //
  2093. _pWizard->bConnected() = TRUE;
  2094. //
  2095. // Here must save the printer information for the
  2096. // next page (the info page)
  2097. //
  2098. TStatusB bStatus;
  2099. bStatus DBGCHK = _pWizard->strPrinterName().bUpdate( pszPrinterName );
  2100. bStatus DBGCHK = _pWizard->strComment().bUpdate( pszComment );
  2101. bStatus DBGCHK = _pWizard->strLocation().bUpdate( pszLocation );
  2102. bStatus DBGCHK = _pWizard->strShareName().bUpdate( pszShareName );
  2103. return S_OK;
  2104. }
  2105. STDMETHODIMP
  2106. TPageSwitch::
  2107. QueryCancel( THIS_ )
  2108. {
  2109. //
  2110. // Allow the cancel operation and
  2111. // close the wizard
  2112. //
  2113. _pWizard->_bWizardCanceled = TRUE;
  2114. return S_FALSE;
  2115. }
  2116. /********************************************************************
  2117. TWizard.
  2118. ********************************************************************/
  2119. TWizard::
  2120. TWizard(
  2121. IN HWND hwnd,
  2122. IN UINT uAction,
  2123. IN LPCTSTR pszPrinterName,
  2124. IN LPCTSTR pszServerName
  2125. ) : _hwnd( hwnd ),
  2126. _uAction( uAction ),
  2127. _strPrinterName( pszPrinterName ),
  2128. _strServerName( pszServerName ),
  2129. _pszServerName( pszServerName ),
  2130. _bPrinterCreated( FALSE ),
  2131. _bErrorSaving( FALSE ),
  2132. _bValid( FALSE ),
  2133. _bSetDefault( TRUE ),
  2134. _bShowSetDefault( TRUE ),
  2135. _bConnected( FALSE ),
  2136. _uDriverExists( kUninitialized ),
  2137. _bDriverChanged( FALSE ),
  2138. _bTestPage( TRUE ),
  2139. _bRefreshPrinterName( FALSE ),
  2140. _bShared( kDefaultShareState ),
  2141. _eIsDsAvailablePerMachine( kDsStatusUnknown ),
  2142. _eIsDsAvailablePerUser( kDsStatusUnknown ),
  2143. _bNetworkInstalled( FALSE ),
  2144. _Di( pszServerName, hwnd ),
  2145. _bUseNewDriver( FALSE ),
  2146. _bUseNewDriverSticky( FALSE ),
  2147. _bNet( FALSE ),
  2148. _bDefaultPrinter( FALSE ),
  2149. _bIsCodeDownLoadAvailable( FALSE ),
  2150. _bUseWeb( FALSE ),
  2151. _Stack( kInitialStackSize ),
  2152. _bNoPageChange( FALSE ),
  2153. _bPreDir( FALSE ),
  2154. _bPostDir( FALSE ),
  2155. _pDriverTransfer( NULL ),
  2156. _bSkipArchSelection( FALSE ),
  2157. _bPersistSettings( TRUE ),
  2158. _LocateType( kSearch ),
  2159. _bPublish( kDefaultPublishState ),
  2160. _dwAdditionalDrivers( 0 ),
  2161. _bAdditionalDrivers( TRUE ),
  2162. _bDownlevelBrowse( TRUE ),
  2163. _bIsNTServer( FALSE ),
  2164. _hBigBoldFont( NULL ),
  2165. _bWizardCanceled( FALSE ),
  2166. _bIsPrinterFolderEmpty( FALSE ),
  2167. _nDriverInstallCount( 0 ),
  2168. _bAdminPrivilege( FALSE ),
  2169. _nBrowsePageID( 0 ),
  2170. _pPageSwitchController( NULL ),
  2171. _bStylePatched( FALSE ),
  2172. _bPrinterAutoDetected( FALSE ),
  2173. _bPnPAutodetect( TRUE ),
  2174. _bRunDetection( FALSE ),
  2175. _COM(FALSE),
  2176. _bRestartableFromLastPage( FALSE ),
  2177. _bRestartAgain( FALSE ),
  2178. _bIsSharingEnabled( FALSE ),
  2179. _iPosX(-1),
  2180. _iPosY(-1)
  2181. /*++
  2182. Routine Description:
  2183. Create all state information for the printer wizard.
  2184. Arguments:
  2185. hwnd - Parent hwnd.
  2186. pszServerName - Server to install printer on; NULL = local.
  2187. pszPrinterName - Return buffer for newly created printer.
  2188. uAction - Action, MSP_NEWPRINTER and MSP_NEWPRINTER_MODELESS.
  2189. Return Value:
  2190. --*/
  2191. {
  2192. DBGMSG( DBG_TRACE, ( "TWizard::ctor\n" ) );
  2193. //
  2194. // Initialize the page array.
  2195. //
  2196. ZeroMemory( _aPages, sizeof( _aPages ) );
  2197. //
  2198. // Get the select device title.
  2199. //
  2200. _strTitle.bLoadString( ghInst, _uAction == kDriverInstall ? IDS_DRIVER_WIZ_TITLE : IDS_ADD_PRINTER_TITLE );
  2201. _strSetupPageTitle.bLoadString( ghInst, _uAction == kDriverInstall ? IDS_APDW_SETUP_PAGE_TITLE : IDS_APW_SETUP_PAGE_TITLE );
  2202. _strSetupPageSubTitle.bLoadString( ghInst, _uAction == kDriverInstall ? IDS_APDW_SETUP_PAGE_SUBTITLE : IDS_APW_SETUP_PAGE_SUBTITLE );
  2203. _strSetupPageDescription.bLoadString( ghInst, _uAction == kDriverInstall ? IDS_APDW_SETUP_PAGE_INSTRUCT : IDS_APW_SETUP_PAGE_INSTRUCT );
  2204. // _strSetupPageDescription.bLoadString( ghInst, _uAction == kDriverInstall ? IDS_APDW_SETUP_PAGE_INSTRUCT : IDS_APW_SETUP_PAGE_INSTRUCT_HYDRA );
  2205. //
  2206. // setup APIs do not validate the input buffers correctly and just fail if
  2207. // the length is less than MAX_XXX_LEN-1 - this is incorrect. we workaround
  2208. // this bug by bounding the length to MAX_XXX_LEN-1 before calling them.
  2209. // i hope this will get fixed and then i'll fix the code and remove this comment.
  2210. //
  2211. //
  2212. // those limits are defined in setupapi.h and we need to enforse this
  2213. // lengths before calling the setup APIs - otherwise they fail.
  2214. //
  2215. ASSERT(_strSetupPageTitle.uLen() < (MAX_TITLE_LEN-1));
  2216. ASSERT(_strSetupPageSubTitle.uLen() < (MAX_SUBTITLE_LEN-1));
  2217. ASSERT(_strSetupPageDescription.uLen() < (MAX_INSTRUCTION_LEN-1));
  2218. //
  2219. // Since we don't want setup APIs to fail in this case we
  2220. // bound the strings to the requred buffer length.
  2221. //
  2222. _strSetupPageTitle.bLimitBuffer(MAX_TITLE_LEN-1);
  2223. _strSetupPageSubTitle.bLimitBuffer(MAX_SUBTITLE_LEN-1);
  2224. _strSetupPageDescription.bLimitBuffer(MAX_INSTRUCTION_LEN-1);
  2225. //
  2226. // Check if all the aggregate objects are valid.
  2227. //
  2228. if( !VALID_OBJ( _strPrinterName) ||
  2229. !VALID_OBJ( _strServerName ) ||
  2230. !VALID_OBJ( _strTitle ) ||
  2231. !VALID_OBJ( _strSetupPageTitle ) ||
  2232. !VALID_OBJ( _strSetupPageSubTitle ) ||
  2233. !VALID_OBJ( _strSetupPageDescription )||
  2234. !VALID_OBJ( _Ds ) ||
  2235. !VALID_OBJ( _Di ) )
  2236. {
  2237. return;
  2238. }
  2239. // check to see if we have access to the server
  2240. HRESULT hr = ServerAccessCheck(pszServerName, &_bAdminPrivilege);
  2241. if( FAILED(hr) )
  2242. {
  2243. // failed to open the print server - setup the last error.
  2244. SetLastError(SCODE_CODE(GetScode(hr)));
  2245. return;
  2246. }
  2247. else
  2248. {
  2249. if (pszServerName && (FALSE == _bAdminPrivilege))
  2250. {
  2251. // this is not a local server and you don't have full access
  2252. // then the wizard should fail with access denied.
  2253. SetLastError(ERROR_ACCESS_DENIED);
  2254. return;
  2255. }
  2256. }
  2257. //
  2258. // Create the wizard pages.
  2259. //
  2260. if( !bCreatePages() )
  2261. {
  2262. return;
  2263. }
  2264. //
  2265. // Check if the network is installed.
  2266. //
  2267. _bNetworkInstalled = TPrtShare::bNetworkInstalled();
  2268. //
  2269. // Check if this machine is NTW or NTS.
  2270. //
  2271. CComputerInfo CompInfo( _strServerName );
  2272. _bIsNTServer = CompInfo.GetProductInfo() ? CompInfo.IsRunningNtServer() : FALSE;
  2273. //
  2274. // On NT server we want to share printers by default.
  2275. //
  2276. _bShared = _bIsNTServer ? TRUE : kDefaultShareState;
  2277. //
  2278. // On NT server install additional drivers.
  2279. // 0 install the additonal drivers on this machine.
  2280. // 1 do not install additional drivers on this machine.
  2281. //
  2282. // _dwAdditionalDrivers = _bIsNTServer ? 0 : -1;
  2283. //
  2284. // After the drivers went to a CAB file and we removed
  2285. // the cross-platform drivers from the media we will never
  2286. // give the user oportunity to install additional drivers
  2287. // in the APW
  2288. //
  2289. _dwAdditionalDrivers = -1;
  2290. //
  2291. // Check if code download is available, as long as this is a
  2292. // local install. We do not support code download remotely.
  2293. //
  2294. if( !bIsRemote( _strServerName ) )
  2295. {
  2296. _bIsCodeDownLoadAvailable = _Di.bIsCodeDownLoadAvailable();
  2297. }
  2298. //
  2299. // If we are launched as the add printer driver wizard then
  2300. // do not persist any settings and do not set as default
  2301. // and do not print a test page.
  2302. //
  2303. if( _uAction == kDriverInstall )
  2304. {
  2305. _bPersistSettings = FALSE;
  2306. _bTestPage = FALSE;
  2307. _bSetDefault = FALSE;
  2308. _strDriverName.bUpdate( _strPrinterName );
  2309. }
  2310. //
  2311. // Read the default setting state from the registry.
  2312. //
  2313. vReadRegistrySettingDefaults();
  2314. //
  2315. // If the network is not installed then disable sharing.
  2316. //
  2317. _bShared = _bNetworkInstalled ? _bShared : FALSE;
  2318. //
  2319. // Check if current printer folder is empty. This flag is needed to
  2320. // skip the default printer ui page in the network case.
  2321. //
  2322. _bIsPrinterFolderEmpty = CheckDefaultPrinter( NULL ) != kNoDefault;
  2323. //
  2324. // Setup the big bold fonts for the WIZARD97 style.
  2325. //
  2326. SetupFonts( ghInst, _hwnd, &_hBigBoldFont );
  2327. //
  2328. // Initialize the page switch controller class
  2329. //
  2330. _pPageSwitchController = new TPageSwitch( this );
  2331. if( !_pPageSwitchController )
  2332. {
  2333. return;
  2334. }
  2335. hr = IsSharingEnabled(&_bIsSharingEnabled);
  2336. if( FAILED(hr) )
  2337. {
  2338. // we don't want to fail the wizard rather than simply not allow
  2339. // sharing (since we don't know if it is enabled).
  2340. _bIsSharingEnabled = FALSE;
  2341. }
  2342. _bValid = TRUE;
  2343. }
  2344. TWizard::
  2345. ~TWizard(
  2346. VOID
  2347. )
  2348. /*++
  2349. Routine Description:
  2350. Destruct and cleanup the printer wizard state data.
  2351. Note: the global static is not deleted; we keep it in memory
  2352. so it will not have to be reparsed.
  2353. Arguments:
  2354. Return Value:
  2355. --*/
  2356. {
  2357. DBGMSG( DBG_TRACE, ( "TWizard::dtor\n" ) );
  2358. //
  2359. // Save the default settings in the registry.
  2360. //
  2361. vWriteRegistrySettingDefaults();
  2362. //
  2363. // Release all our created wizard pages.
  2364. //
  2365. UINT uSize = COUNTOF( _aPages );
  2366. while( uSize-- )
  2367. {
  2368. if( _aPages[uSize].pPage )
  2369. {
  2370. DBGMSG( DBG_TRACE, ( "TWizard::dtor deleting page\n" ) );
  2371. delete _aPages[uSize].pPage;
  2372. }
  2373. }
  2374. //
  2375. // Release the bold font handles.
  2376. //
  2377. if( _hBigBoldFont )
  2378. {
  2379. TStatusB bStatus;
  2380. bStatus DBGCHK = DeleteObject( _hBigBoldFont );
  2381. }
  2382. //
  2383. // Destroy the page controller class
  2384. //
  2385. delete _pPageSwitchController;
  2386. }
  2387. BOOL
  2388. TWizard::
  2389. bCreatePages(
  2390. VOID
  2391. )
  2392. /*++
  2393. Routine Description:
  2394. Creates the wizard pages. Note the order is significant.
  2395. Arguments:
  2396. None
  2397. Return Value:
  2398. TRUE - success, FALSE - error.
  2399. --*/
  2400. {
  2401. UINT iIndex = 0;
  2402. if( _uAction == kDriverInstall )
  2403. {
  2404. if( !bInsertPage( iIndex, new TWizDriverIntro( this ), DLG_WIZ_DRIVER_INTRO ) ||
  2405. !bInsertPage( iIndex, new TWizDriverEnd( this ), DLG_WIZ_DRIVER_END ) ||
  2406. !bInsertPage( iIndex, new TWizPreSelectDriver( this ), DLG_WIZ_PRE_SELECT_DEVICE ) ||
  2407. !bInsertPage( iIndex, NULL, static_cast<UINT>( kSelectDriverPage ) ) ||
  2408. !bInsertPage( iIndex, new TWizPostSelectDriver( this ), DLG_WIZ_POST_SELECT_DEVICE ) ||
  2409. !bInsertPage( iIndex, new TWizArchitecture( this ), DLG_WIZ_DRIVER_ARCHITECTURE, IDS_WIZ_ARCH_TITLE, IDS_WIZ_ARCH_SUBTITLE ) )
  2410. {
  2411. return FALSE;
  2412. }
  2413. }
  2414. else
  2415. {
  2416. if( !bInsertPage( iIndex, new TWizPreIntro( this ), DLG_WIZ_PRE_INTRO ) ||
  2417. !bInsertPage( iIndex, new TWizIntro( this ), DLG_WIZ_INTRO ) ||
  2418. !bInsertPage( iIndex, new TWizFinish( this ), DLG_WIZ_FINISH ) ||
  2419. !bInsertPage( iIndex, new TWizPreSelectDriver( this ), DLG_WIZ_PRE_SELECT_DEVICE ) ||
  2420. !bInsertPage( iIndex, NULL, static_cast<UINT>( kSelectDriverPage ) ) ||
  2421. !bInsertPage( iIndex, new TWizPostSelectDriver( this ), DLG_WIZ_POST_SELECT_DEVICE ) ||
  2422. !bInsertPage( iIndex, new TWizPortNew( this ), DLG_WIZ_PORT_NEW, IDS_WIZ_PORT_TITLE, IDS_WIZ_PORT_SUBTITLE ) ||
  2423. !bInsertPage( iIndex, new TWizDriverExists( this ), DLG_WIZ_DRIVEREXISTS, IDS_WIZ_DRIVEREXISTS_TITLE, IDS_WIZ_DRIVEREXISTS_SUBTITLE ) ||
  2424. !bInsertPage( iIndex, new TWizName( this ), DLG_WIZ_NAME, IDS_WIZ_NAME_TITLE, IDS_WIZ_NAME_SUBTITLE ) ||
  2425. !bInsertPage( iIndex, new TWizShare( this ), DLG_WIZ_SHARE, IDS_WIZ_SHARE_TITLE, IDS_WIZ_SHARE_SUBTITLE ) ||
  2426. !bInsertPage( iIndex, new TWizComment( this ), DLG_WIZ_COMMENT, IDS_WIZ_COMMENT_TITLE, IDS_WIZ_COMMENT_SUBTITLE ) ||
  2427. !bInsertPage( iIndex, new TWizLocate( this ), DLG_WIZ_LOCATE, IDS_WIZ_LOCATE_TITLE, IDS_WIZ_LOCATE_SUBTITLE ) ||
  2428. !bInsertPage( iIndex, new TWizType( this ), DLG_WIZ_TYPE, IDS_WIZ_TYPE_TITLE, IDS_WIZ_TYPE_SUBTITLE ) ||
  2429. !bInsertPage( iIndex, new TWizDetect( this ), DLG_WIZ_DETECT, IDS_WIZ_DETECT_TITLE, IDS_WIZ_DETECT_SUBTITLE ) ||
  2430. !bInsertPage( iIndex, new TWizNet( this ), DLG_WIZ_NET, IDS_WIZ_NET_TITLE, IDS_WIZ_NET_SUBTITLE ) ||
  2431. !bInsertPage( iIndex, new TWizTestPage( this ), DLG_WIZ_TEST_PAGE, IDS_WIZ_TEST_PAGE_TITLE, IDS_WIZ_TEST_PAGE_SUBTITLE ) ||
  2432. !bInsertPage( iIndex, NULL, static_cast<UINT>( kSelectPrinterPage ) ) )
  2433. {
  2434. return FALSE;
  2435. }
  2436. }
  2437. return TRUE;
  2438. }
  2439. BOOL
  2440. TWizard::
  2441. bInsertPage(
  2442. IN OUT UINT &Index,
  2443. IN MGenericProp *pWizPage,
  2444. IN UINT uDlgId,
  2445. IN UINT uTitleId,
  2446. IN UINT uSubTitleId
  2447. )
  2448. {
  2449. DBGMSG( DBG_TRACE, ( "TWizard::bInsertPage\n" ) );
  2450. BOOL bReturn = TRUE;
  2451. if( Index < kPropMax )
  2452. {
  2453. _aPages[Index].pPage = pWizPage;
  2454. _aPages[Index].iDialog = uDlgId;
  2455. _aPages[Index].iTitle = uTitleId;
  2456. _aPages[Index].iSubTitle = uSubTitleId;
  2457. Index++;
  2458. if( !pWizPage && !( uDlgId == kSelectDriverPage || uDlgId == kSelectPrinterPage ) )
  2459. {
  2460. bReturn = FALSE;
  2461. }
  2462. }
  2463. else
  2464. {
  2465. //
  2466. // This is code error. It shouldn't happen
  2467. //
  2468. SPLASSERT( Index < kPropMax );
  2469. DBGMSG( DBG_TRACE, ( "TWizard::bInsertPage - Trying to insert more prop pages than kPropMax\n" ) );
  2470. bReturn = FALSE;
  2471. }
  2472. return bReturn;
  2473. }
  2474. HRESULT
  2475. TWizard::
  2476. ServerAccessCheck(
  2477. LPCTSTR pszServer,
  2478. BOOL *pbFullAccess
  2479. )
  2480. {
  2481. HRESULT hr = E_FAIL;
  2482. if (pbFullAccess)
  2483. {
  2484. CAutoHandlePrinter shServer;
  2485. DWORD dwAccess = SERVER_ALL_ACCESS;
  2486. // Attempt to open the server with Admin access
  2487. TStatus Status;
  2488. Status DBGCHK = TPrinter::sOpenPrinter(pszServer, &dwAccess, &shServer);
  2489. if (Status == ERROR_SUCCESS)
  2490. {
  2491. // We have an admin access
  2492. hr = S_OK;
  2493. *pbFullAccess = TRUE;
  2494. }
  2495. else
  2496. {
  2497. if (Status == ERROR_ACCESS_DENIED)
  2498. {
  2499. // We don't have an admin access.
  2500. hr = S_OK;
  2501. *pbFullAccess = FALSE;
  2502. }
  2503. else
  2504. {
  2505. // Failed to open the server.
  2506. hr = HRESULT_FROM_WIN32(Status);
  2507. }
  2508. }
  2509. }
  2510. else
  2511. {
  2512. // invalid argument
  2513. hr = E_INVALIDARG;
  2514. }
  2515. return hr;
  2516. }
  2517. BOOL
  2518. TWizard::
  2519. bAddPages(
  2520. IN OUT PSP_INSTALLWIZARD_DATA pWizardData
  2521. )
  2522. {
  2523. DBGMSG( DBG_TRACE, ( "TWizard::bAddPages\n" ) );
  2524. BOOL bReturn = FALSE;
  2525. UINT nExistingPages = pWizardData->NumDynamicPages;
  2526. UINT nSlots = COUNTOF( pWizardData->DynamicPages );
  2527. UINT nPagesAdded = 0;
  2528. UINT nOurPages = COUNTOF( _aPages );
  2529. //
  2530. // If the number of existing pages plus our pages is
  2531. // greater than number available slots, exit with an error.
  2532. //
  2533. if( nExistingPages + nOurPages > nSlots )
  2534. {
  2535. DBGMSG( DBG_TRACE, ( "Too many dynamic pags %d\n", pWizardData->NumDynamicPages + COUNTOF( _aPages ) ) );
  2536. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  2537. }
  2538. else
  2539. {
  2540. //
  2541. // Calculate the address of the first available slot.
  2542. //
  2543. HPROPSHEETPAGE *pPages = &pWizardData->DynamicPages[nExistingPages];
  2544. //
  2545. // Create the property page pages.
  2546. //
  2547. if( bCreatePropPages( &nPagesAdded, nSlots - nExistingPages, pPages, nOurPages, _aPages ) )
  2548. {
  2549. //
  2550. // Indicate pages were added.
  2551. //
  2552. pWizardData->DynamicPageFlags = pWizardData->DynamicPageFlags | DYNAWIZ_FLAG_PAGESADDED;
  2553. //
  2554. // Adjust the total page count.
  2555. //
  2556. pWizardData->NumDynamicPages = nExistingPages + nPagesAdded;
  2557. //
  2558. // Indicate success.
  2559. //
  2560. bReturn = TRUE;
  2561. }
  2562. }
  2563. return bReturn;
  2564. }
  2565. BOOL
  2566. TWizard::
  2567. bPropPages(
  2568. VOID
  2569. )
  2570. /*++
  2571. Routine Description:
  2572. Thread proc to create the printer wizard.
  2573. Arguments:
  2574. Return Value:
  2575. TRUE = success, FALSE = fail.
  2576. History:
  2577. Lazar Ivanov (LazarI) - Nov-30-2000, redesign.
  2578. --*/
  2579. {
  2580. HPROPSHEETPAGE ahpsp[TWizard::kPropMax];
  2581. PROPSHEETHEADER psh = {0};
  2582. BOOL bLinkWindowRegistered = FALSE;
  2583. TStatusB bReturn;
  2584. // initialize the return value.
  2585. bReturn DBGNOCHK = FALSE;
  2586. // register the link window class
  2587. bLinkWindowRegistered = LinkWindow_RegisterClass();
  2588. if( !bLinkWindowRegistered )
  2589. {
  2590. // unable to register the link window class - this is fatal, so exit
  2591. DBGMSG( DBG_WARN, ( "LinkWindow_RegisterClass() failed - unable to register link window class\n" ) );
  2592. vShowResourceError(_hwnd);
  2593. goto Done;
  2594. }
  2595. // initialize the property sheet header.
  2596. ZeroMemory(ahpsp, sizeof(ahpsp));
  2597. psh.dwSize = sizeof(psh);
  2598. psh.hwndParent = _hwnd;
  2599. psh.hInstance = ghInst;
  2600. psh.dwFlags = PSH_WIZARD | PSH_USECALLBACK | PSH_WIZARD97 | PSH_STRETCHWATERMARK | PSH_WATERMARK | PSH_HEADER;
  2601. psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
  2602. psh.pszbmHeader = MAKEINTRESOURCE(IDB_BANNER);
  2603. psh.phpage = ahpsp;
  2604. psh.pfnCallback = TWizard::iSetupDlgCallback;
  2605. psh.nStartPage = 0;
  2606. psh.nPages = 0;
  2607. // if this is a specific inf install then build the driver list using the specified inf file.
  2608. if( !_strInfFileName.bEmpty() )
  2609. {
  2610. if( !_Di.bSelectDriverFromInf(_strInfFileName, TRUE) )
  2611. {
  2612. // this is fatal
  2613. DBGMSG( DBG_WARN, ( "TWizard::vWizardPropPage: Unable to use specified inf " TSTR "\n", (LPCTSTR)_strInfFileName ));
  2614. vShowResourceError( _hwnd );
  2615. goto Done;
  2616. }
  2617. }
  2618. // create the property page pages and bring up the wizard.
  2619. if( !bCreatePropPages(&psh.nPages, ARRAYSIZE(ahpsp), ahpsp, ARRAYSIZE(_aPages), _aPages) )
  2620. {
  2621. DBGMSG( DBG_WARN, ( "TWizard::bCreatePropPages failed\n" ) );
  2622. vShowResourceError( _hwnd );
  2623. goto Done;
  2624. }
  2625. if( -1 == PropertySheet(&psh) )
  2626. {
  2627. DBGMSG( DBG_WARN, ( "TWizard::vWizardPropPages: PropertySheet failed %d\n", GetLastError( )));
  2628. vShowResourceError( _hwnd );
  2629. goto Done;
  2630. }
  2631. // if a printer was created or connectd to then indicate success.
  2632. bReturn DBGNOCHK = _bPrinterCreated || _bConnected;
  2633. Done:
  2634. // set browse page ID to invalid
  2635. _nBrowsePageID = 0;
  2636. if( bLinkWindowRegistered )
  2637. {
  2638. // unregister the link window class
  2639. LinkWindow_UnregisterClass(ghInst);
  2640. }
  2641. return bReturn;
  2642. }
  2643. VOID
  2644. TWizard::
  2645. SetupFonts(
  2646. IN HINSTANCE hInstance,
  2647. IN HWND hwnd,
  2648. IN HFONT *hBigBoldFont
  2649. )
  2650. /*++
  2651. Routine Description:
  2652. Sets up the large fonts for the WORD 97 wizard style.
  2653. Arguments:
  2654. hInstance - Instance handle.
  2655. hwnd - Current window handle.
  2656. hBigBoldFont - Pointer where to return big bold font handle.
  2657. Return Value:
  2658. Nothing. Returned font handles indicate success or failure.
  2659. --*/
  2660. {
  2661. DBGMSG( DBG_TRACE, ( "TWizard::SetupFonts\n" ) );
  2662. //
  2663. // Create the fonts we need based on the dialog font
  2664. //
  2665. NONCLIENTMETRICS ncm = {0};
  2666. ncm.cbSize = sizeof(ncm);
  2667. SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
  2668. LOGFONT BigBoldLogFont = ncm.lfMessageFont;
  2669. //
  2670. // Create the Big Bold Font
  2671. //
  2672. BigBoldLogFont.lfWeight = FW_BOLD;
  2673. INT FontSize;
  2674. TString strLargeFontName;
  2675. TString strLargeFontSize;
  2676. TStatusB bStatus;
  2677. //
  2678. // Load size and name from resources, since these may change
  2679. // from locale to locale based on the size of the system font, etc.
  2680. //
  2681. bStatus DBGCHK = strLargeFontName.bLoadString( hInstance, IDS_LARGEFONTNAME ) &&
  2682. strLargeFontSize.bLoadString( hInstance, IDS_LARGEFONTSIZE );
  2683. if( bStatus )
  2684. {
  2685. _tcsncpy( BigBoldLogFont.lfFaceName, strLargeFontName, COUNTOF( BigBoldLogFont.lfFaceName ) );
  2686. FontSize = _tcstoul( strLargeFontSize, NULL, 10 );
  2687. }
  2688. else
  2689. {
  2690. _tcscpy( BigBoldLogFont.lfFaceName, TEXT("MS Shell Dlg") );
  2691. FontSize = 18;
  2692. }
  2693. HDC hdc = GetDC( hwnd );
  2694. if( hdc )
  2695. {
  2696. BigBoldLogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72);
  2697. *hBigBoldFont = CreateFontIndirect( &BigBoldLogFont );
  2698. ReleaseDC( hwnd, hdc);
  2699. }
  2700. }
  2701. BOOL
  2702. TWizard::
  2703. bPrintTestPage(
  2704. VOID
  2705. )
  2706. /*++
  2707. Routine Description:
  2708. Prints the test page for the newly created printer.
  2709. Arguments:
  2710. None.
  2711. Return Value:
  2712. TRUE success, FALSE error.
  2713. --*/
  2714. {
  2715. TString strFullPrinterName;
  2716. TStatusB bStatus;
  2717. //
  2718. // The test page requires a fully qualified printer name.
  2719. //
  2720. bStatus DBGCHK = bBuildFullPrinterName( _pszServerName, _strPrinterName, strFullPrinterName );
  2721. if( bStatus )
  2722. {
  2723. //
  2724. // Print the test page.
  2725. //
  2726. bStatus DBGCHK = ::bPrintTestPage( _hwnd, strFullPrinterName, NULL );
  2727. }
  2728. return bStatus;
  2729. }
  2730. UINT
  2731. TWizard::
  2732. MapPageID(
  2733. UINT uPageID
  2734. ) const
  2735. /*++
  2736. Routine Description:
  2737. Maps the page ID to the real one. This function
  2738. allows mapping of imaginary page IDs as the
  2739. kSelectPrinterPage to the real ones
  2740. Arguments:
  2741. uPageID - The page ID to be mapped
  2742. Return Value:
  2743. The real page ID
  2744. --*/
  2745. {
  2746. //
  2747. // Just map the kSelectPrinterPage to the
  2748. // appropriate ID
  2749. //
  2750. if( kSelectPrinterPage == uPageID )
  2751. {
  2752. SPLASSERT( 0 != nBrowsePageID() );
  2753. uPageID = nBrowsePageID();
  2754. }
  2755. return uPageID;
  2756. }
  2757. VOID
  2758. TWizard::
  2759. OnWizardInitro(
  2760. HWND hDlgIntroPage
  2761. )
  2762. {
  2763. HWND hWndThis = GetParent( hDlgIntroPage );
  2764. //
  2765. // Subclass the wizard here.
  2766. //
  2767. Attach( hWndThis );
  2768. if( bRestartAgain() )
  2769. {
  2770. if( -1 != iPosX() && -1 != iPosY() )
  2771. {
  2772. //
  2773. // We are in the case where the wizard gets restarted, so we
  2774. // want to restore its position at the same place it has been
  2775. // when the user has clicked "Finish" last time.
  2776. //
  2777. SetWindowPos( hWndThis, NULL, iPosX(), iPosY(), 0, 0, SWP_NOZORDER|SWP_NOSIZE );
  2778. }
  2779. //
  2780. // We are restarting the wizard, so skip the into page.
  2781. //
  2782. PropSheet_PressButton( hWndThis, PSBTN_NEXT );
  2783. }
  2784. }
  2785. VOID
  2786. TWizard::
  2787. OnWizardFinish(
  2788. HWND hDlgFinishPage
  2789. )
  2790. {
  2791. if( bRestartAgain() && FALSE == bNoPageChange() )
  2792. {
  2793. //
  2794. // We are going to restart the wizard - should blow off
  2795. // the DFA stack here....
  2796. //
  2797. UINT uPage;
  2798. while( Stack().bPop(&uPage) );
  2799. //
  2800. // ...then reset some internal vars, so the wizard doesn't
  2801. // get messed up next time.
  2802. //
  2803. bPreDir() = FALSE;
  2804. bPostDir() = FALSE;
  2805. uDriverExists() = TWizard::kUninitialized;
  2806. //
  2807. // save the window position, so it can be restored later when
  2808. // the wizard gets restarted.
  2809. //
  2810. RECT rcClient;
  2811. HWND hwndThis = GetParent( hDlgFinishPage );
  2812. GetWindowRect( hwndThis, &rcClient );
  2813. MapWindowPoints( HWND_DESKTOP, GetParent( hwndThis ), (LPPOINT)&rcClient, 2 );
  2814. iPosX() = rcClient.left;
  2815. iPosY() = rcClient.top;
  2816. }
  2817. }
  2818. BOOL
  2819. TWizard::
  2820. bShouldRestart(
  2821. VOID
  2822. )
  2823. /*++
  2824. Routine Description:
  2825. Decide whether the wizard should be restarted.
  2826. Arguments:
  2827. None.
  2828. Return Value:
  2829. TRUE for restart, FALSE for not restart.
  2830. --*/
  2831. {
  2832. //
  2833. // We check the !(_bPreDir ^ _bPostDir) because we don't have control on the driver setup page.
  2834. // If the user cancel the wizard the driver setup page, the _bPreDir will be TRUE and _bPostDir
  2835. // will be FALSE.
  2836. //
  2837. TStatusB bStatus;
  2838. bStatus DBGNOCHK = _bRestartAgain && !(_bWizardCanceled) && !(_bPreDir ^ _bPostDir);
  2839. return bStatus;
  2840. }
  2841. LRESULT
  2842. TWizard::
  2843. WindowProc(
  2844. IN HWND hwnd,
  2845. IN UINT uMsg,
  2846. IN WPARAM wParam,
  2847. IN LPARAM lParam
  2848. )
  2849. {
  2850. //
  2851. // This code is taken from MSDN:
  2852. // http://msdn.microsoft.com/library/psdk/shellcc/shell/Shell_basics/Autoplay_reg.htm#suppressing
  2853. // and the purpose is to suppress autoplay when the add printer wizard is up and running
  2854. //
  2855. static UINT uQueryCancelAutoPlay = 0;
  2856. if( 0 == uQueryCancelAutoPlay )
  2857. {
  2858. uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  2859. }
  2860. if( uMsg == uQueryCancelAutoPlay )
  2861. {
  2862. SetWindowLong(hwnd, DWLP_MSGRESULT, TRUE);
  2863. return 1;
  2864. }
  2865. // allways call the default processing
  2866. return DefDlgProc(hwnd, uMsg, wParam, lParam);
  2867. }
  2868. BOOL
  2869. TWizard::
  2870. bCreatePropPages(
  2871. IN UINT *pnPageHandles,
  2872. IN UINT nPageHandles,
  2873. IN HPROPSHEETPAGE *pPageHandles,
  2874. IN UINT nPages,
  2875. IN Page *pPages
  2876. )
  2877. /*++
  2878. Routine Description:
  2879. Create prop page internal function.
  2880. Arguments:
  2881. Return Value:
  2882. TRUE success, FALSE error.
  2883. --*/
  2884. {
  2885. DBGMSG( DBG_TRACE, ( "TWizard.bCreatePropPages\n" ) );
  2886. SPLASSERT( pnPageHandles || pPageHandles || pPages );
  2887. TStatusB bReturn;
  2888. bReturn DBGNOCHK = FALSE;
  2889. //
  2890. // If there is room to store all the page handles.
  2891. //
  2892. if( nPages <= nPageHandles )
  2893. {
  2894. HPROPSHEETPAGE *pHandles = pPageHandles;
  2895. PROPSHEETPAGE psp = {0};
  2896. // assume success
  2897. bReturn DBGNOCHK = TRUE;
  2898. //
  2899. // Initialize the property sheet page structure.
  2900. //
  2901. psp.dwSize = sizeof( psp );
  2902. psp.hInstance = ghInst;
  2903. psp.pfnDlgProc = MGenericProp::SetupDlgProc;
  2904. //
  2905. // Initialze the page handle count.
  2906. //
  2907. *pnPageHandles = 0;
  2908. //
  2909. // Create all the page and fill in the page handle array.
  2910. //
  2911. for( UINT i = 0; i < nPageHandles && i < nPages && bReturn; i++ )
  2912. {
  2913. if( pPages[i].iDialog == kSelectDriverPage )
  2914. {
  2915. bReturn DBGCHK = _Di.bGetDriverSetupPage( &pHandles[i], _strSetupPageTitle, _strSetupPageSubTitle, _strSetupPageDescription );
  2916. }
  2917. else if( pPages[i].iDialog == kSelectPrinterPage )
  2918. {
  2919. //
  2920. // Special creation for the browse for printer page
  2921. //
  2922. HRESULT hr = ConnectToPrinterPropertyPage( &pHandles[i], &_nBrowsePageID, pPageSwitchController() );
  2923. bReturn DBGCHK = ( S_OK == hr ) && ( NULL != pHandles[i] );
  2924. }
  2925. else if( NULL != pPages[i].pPage )
  2926. {
  2927. psp.dwFlags = PSP_DEFAULT;
  2928. psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  2929. if( _uAction == kDriverInstall )
  2930. {
  2931. if( pPages[i].iDialog == DLG_WIZ_DRIVER_INTRO || pPages[i].iDialog == DLG_WIZ_DRIVER_END )
  2932. {
  2933. psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
  2934. }
  2935. }
  2936. else
  2937. {
  2938. if( pPages[i].iDialog == DLG_WIZ_INTRO || pPages[i].iDialog == DLG_WIZ_FINISH )
  2939. {
  2940. psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
  2941. }
  2942. }
  2943. //
  2944. // Set the title and subtitle.
  2945. //
  2946. TString strTitle;
  2947. TString strSubTitle;
  2948. strTitle.bLoadString( ghInst, pPages[i].iTitle );
  2949. strSubTitle.bLoadString( ghInst, pPages[i].iSubTitle );
  2950. psp.pszHeaderTitle = strTitle;
  2951. psp.pszHeaderSubTitle = strSubTitle;
  2952. psp.pszTemplate = MAKEINTRESOURCE( pPages[i].iDialog );
  2953. psp.lParam = reinterpret_cast<LPARAM>( pPages[i].pPage );
  2954. pHandles[i] = CreatePropertySheetPage( &psp );
  2955. bReturn DBGCHK = pHandles[i] ? TRUE : FALSE;
  2956. }
  2957. else
  2958. {
  2959. pHandles[i] = NULL;
  2960. }
  2961. if( bReturn && pHandles[i] )
  2962. {
  2963. //
  2964. // Update the handle count for valid page handles.
  2965. //
  2966. (*pnPageHandles)++;
  2967. DBGMSG( DBG_TRACE, ( "TWizard::bCreatePropPages Page created %d\n", *pnPageHandles ) );
  2968. }
  2969. else
  2970. {
  2971. //
  2972. // Page creation failed. Fail gracefully.
  2973. //
  2974. DBGMSG( DBG_TRACE, ( "TWizard::bCreatePropPages CreatePropertySheetPage failed %d\n", GetLastError() ) );
  2975. break;
  2976. }
  2977. }
  2978. if( bReturn )
  2979. {
  2980. //
  2981. // The pages were created, and we are not remote and
  2982. // not in the add printer driver wizard, then enable
  2983. // the web button.
  2984. //
  2985. if( _uAction != kDriverInstall && !bIsRemote( _strServerName ) )
  2986. {
  2987. (VOID)_Di.bSetWebMode( TRUE );
  2988. }
  2989. }
  2990. else
  2991. {
  2992. //
  2993. // If something failed then relase any created pages.
  2994. //
  2995. pHandles = pPageHandles;
  2996. for( UINT i = 0; i < nPageHandles; i++ )
  2997. {
  2998. if( pHandles[i] )
  2999. {
  3000. DestroyPropertySheetPage( pHandles[i] );
  3001. }
  3002. }
  3003. }
  3004. }
  3005. return bReturn;
  3006. }
  3007. INT CALLBACK
  3008. TWizard::
  3009. iSetupDlgCallback(
  3010. IN HWND hwndDlg,
  3011. IN UINT uMsg,
  3012. IN LPARAM lParam
  3013. )
  3014. /*++
  3015. Routine Description:
  3016. Call back used to remove the "?" from the wizard page.
  3017. Arguments:
  3018. hwndDlg - Handle to the property sheet dialog box.
  3019. uMsg - Identifies the message being received. This parameter
  3020. is one of the following values:
  3021. PSCB_INITIALIZED - Indicates that the property sheet is
  3022. being initialized. The lParam value is zero for this message.
  3023. PSCB_PRECREATE Indicates that the property sheet is about
  3024. to be created. The hwndDlg parameter is NULL and the lParam
  3025. parameter is a pointer to a dialog template in memory. This
  3026. template is in the form of a DLGTEMPLATE structure followed
  3027. by one or more DLGITEMTEMPLATE structures.
  3028. lParam - Specifies additional information about the message. The
  3029. meaning of this value depends on the uMsg parameter.
  3030. Return Value:
  3031. The function returns zero.
  3032. --*/
  3033. {
  3034. DBGMSG( DBG_TRACE, ( "TWizard::uSetupDlgCallback\n" ) );
  3035. switch( uMsg )
  3036. {
  3037. case PSCB_INITIALIZED:
  3038. break;
  3039. case PSCB_PRECREATE:
  3040. break;
  3041. }
  3042. return FALSE;
  3043. }
  3044. BOOL
  3045. TWizard::
  3046. bParseDriver(
  3047. IN HWND hDlg
  3048. )
  3049. /*++
  3050. Routine Description:
  3051. Parse the driver data. This ensures that selected
  3052. the driver information is initialized correctly.
  3053. Arguments:
  3054. HWND hDlg - Handle to parent dialog.
  3055. Return Value:
  3056. TRUE = success,
  3057. FALSE = fail, GLE.
  3058. --*/
  3059. {
  3060. DBGMSG( DBG_TRACE, ( "TWizard::bParseDriver\n" ) );
  3061. TStatusB bStatus;
  3062. TString strDriverName;
  3063. //
  3064. // Refresh the selected driver.
  3065. //
  3066. bStatus DBGCHK = _Di.bGetSelectedDriver();
  3067. if( bStatus )
  3068. {
  3069. //
  3070. // Get the selected driver name.
  3071. //
  3072. bStatus DBGCHK = _Di.bGetDriverName( strDriverName );
  3073. if( bStatus )
  3074. {
  3075. DBGMSG( DBG_TRACE, ( "Selected Driver name " TSTR "\n", (LPCTSTR)strDriverName ) );
  3076. //
  3077. // Check if the driver name has changed.
  3078. //
  3079. if( _tcsicmp( _strDriverName, strDriverName ) )
  3080. {
  3081. //
  3082. // Force _uDriverExists to recheck if the driver is installed
  3083. // on the server. Turn everything off.
  3084. //
  3085. _uDriverExists = kUninitialized;
  3086. _bDriverChanged = TRUE;
  3087. _bRefreshPrinterName = TRUE;
  3088. //
  3089. // Update the new driver name.
  3090. //
  3091. bStatus DBGCHK = _strDriverName.bUpdate( strDriverName );
  3092. }
  3093. }
  3094. }
  3095. //
  3096. // Check if an error occurred.
  3097. //
  3098. if( !bStatus ){
  3099. _bErrorSaving = TRUE;
  3100. //
  3101. // Driver data failed to be parsed.
  3102. //
  3103. iMessage( hDlg,
  3104. IDS_ERR_ADD_PRINTER_TITLE,
  3105. IDS_ERR_DRIVER_SELECTION,
  3106. MB_OK|MB_ICONHAND,
  3107. kMsgNone,
  3108. NULL );
  3109. //
  3110. // Terminate the wizard.
  3111. //
  3112. vTerminate( hDlg );
  3113. }
  3114. return bStatus;
  3115. }
  3116. BOOL
  3117. TWizard::
  3118. bDriverExists(
  3119. VOID
  3120. )
  3121. /*++
  3122. Routine Description:
  3123. Returns whether the selected driver already exists on the server.
  3124. Assumes bParseDriver called successfully.
  3125. Arguments:
  3126. Return Value:
  3127. TRUE = driver exists, FALSE = does not exist on the server.
  3128. --*/
  3129. {
  3130. DBGMSG( DBG_TRACE, ( "TWizard::bDriverExists\n" ) );
  3131. if( _uDriverExists == kUninitialized ){
  3132. //
  3133. // Check if a compatible driver is installed.
  3134. //
  3135. INT Status;
  3136. Status = _Di.IsDriverInstalledForInf( TPrinterDriverInstallation::kDefault, TRUE );
  3137. if( Status == DRIVER_MODEL_NOT_INSTALLED )
  3138. {
  3139. _uDriverExists = kDoesNotExist;
  3140. }
  3141. else
  3142. {
  3143. _uDriverExists = kExists;
  3144. }
  3145. }
  3146. return ( _uDriverExists & kExists ) ? TRUE : FALSE;
  3147. }
  3148. BOOL
  3149. TWizard::
  3150. bCreatePrinter(
  3151. IN HWND hwnd
  3152. )
  3153. /*++
  3154. Routine Description:
  3155. Creates the printer. Puts up UI on failure.
  3156. Arguments:
  3157. Return Value:
  3158. TRUE = success, FALSE = fail.
  3159. --*/
  3160. {
  3161. TStatusB bReturn;
  3162. //
  3163. // Install the current architecture/version if requested.
  3164. //
  3165. if( _bUseNewDriver ){
  3166. //
  3167. // Attempt to install the specified driver.
  3168. //
  3169. BOOL bOfferReplacementDriver = TRUE;
  3170. bReturn DBGCHK = _Di.bInstallDriver(
  3171. &_strDriverName, bOfferReplacementDriver, _bUseWeb, hwnd);
  3172. //
  3173. // If and error occurred installing the printer driver. Display an
  3174. // error message to the user and do not exit the wizard.
  3175. //
  3176. if( !bReturn ){
  3177. switch( GetLastError() )
  3178. {
  3179. case ERROR_CANCELLED:
  3180. break;
  3181. case ERROR_UNKNOWN_PRINTER_DRIVER:
  3182. iMessage( hwnd,
  3183. IDS_ERR_ADD_PRINTER_TITLE,
  3184. IDS_ERROR_UNKNOWN_DRIVER,
  3185. MB_OK | MB_ICONSTOP,
  3186. kMsgNone,
  3187. NULL );
  3188. break;
  3189. default:
  3190. iMessage( hwnd,
  3191. IDS_ERR_ADD_PRINTER_TITLE,
  3192. IDS_ERR_INSTALL_DRIVER,
  3193. MB_OK|MB_ICONHAND,
  3194. kMsgGetLastError,
  3195. NULL );
  3196. break;
  3197. }
  3198. return bReturn;
  3199. } else {
  3200. //
  3201. // Add any additional printer drivers. Note policy bits define which
  3202. // drivers are the additional drivers. The wizard will not fail if any
  3203. // additional drivers are not copied down or installation fails
  3204. //
  3205. if( !bAddAdditionalDrivers( hwnd ) )
  3206. {
  3207. iMessage( hwnd,
  3208. IDS_ERR_ADD_PRINTER_TITLE,
  3209. IDS_ERR_ADDITIONAL_DRIVERS,
  3210. MB_OK|MB_ICONWARNING,
  3211. kMsgNone,
  3212. NULL );
  3213. }
  3214. //
  3215. // Prevent the driver from being installed again if the printer
  3216. // fails to be added to either the spooler or the DS
  3217. //
  3218. _bUseNewDriver = FALSE;
  3219. }
  3220. }
  3221. //
  3222. // Get the selected print processor.
  3223. //
  3224. TString strPrintProcessor;
  3225. bReturn DBGCHK = _Di.bGetPrintProcessor( strPrintProcessor );
  3226. //
  3227. // Check if the Directory Service is installed and available.
  3228. //
  3229. if( ( _eIsDsAvailablePerMachine == TWizard::kDsStatusUnknown ) && _bPublish )
  3230. {
  3231. TWaitCursor Cur;
  3232. _eIsDsAvailablePerMachine = _Ds.bIsDsAvailable( _strServerName ) ? TWizard::kDsStatusAvailable : TWizard::kDsStatusUnavailable;
  3233. }
  3234. //
  3235. // The driver has been installed, now add the printer to the
  3236. // spooler and the DS.
  3237. //
  3238. bReturn DBGCHK = bInstallPrinter(_pszServerName,
  3239. _strPrinterName,
  3240. _strShareName,
  3241. _strPortName,
  3242. _strDriverName,
  3243. strPrintProcessor,
  3244. _strLocation,
  3245. _strComment,
  3246. _bShared,
  3247. _bPublish,
  3248. kAttributesNone,
  3249. _eIsDsAvailablePerMachine,
  3250. 0,
  3251. NULL );
  3252. //
  3253. // If an error occurred adding the printer.
  3254. //
  3255. if( !bReturn ){
  3256. DBGMSG( DBG_WARN, ( "Wizard.bCreatePrinter: could not create "TSTR" %d\n" , DBGSTR( (LPCTSTR)_strPrinterName ), GetLastError()));
  3257. iMessage( _hwnd,
  3258. IDS_ERR_ADD_PRINTER_TITLE,
  3259. IDS_ERR_INSTALLPRINTER,
  3260. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  3261. kMsgGetLastError,
  3262. NULL );
  3263. } else {
  3264. TString strFullPrinterName;
  3265. TStatusB bStatus;
  3266. //
  3267. // Build full printer name.
  3268. //
  3269. bStatus DBGCHK = bBuildFullPrinterName( _pszServerName, _strPrinterName, strFullPrinterName );
  3270. //
  3271. // Inform the driver installation that a printer has been added.
  3272. //
  3273. _Di.vPrinterAdded( strFullPrinterName );
  3274. }
  3275. return bReturn;
  3276. }
  3277. BOOL
  3278. TWizard::
  3279. bAddAdditionalDrivers(
  3280. IN HWND hwnd
  3281. )
  3282. /*++
  3283. Routine Description:
  3284. Adds any additonal printer drivers.
  3285. Arguments:
  3286. Pointer to add info structure.
  3287. Return Value:
  3288. TRUE post printer install was successful, otherwize FALSE.
  3289. --*/
  3290. {
  3291. //
  3292. // Assume success.
  3293. //
  3294. BOOL bStatus = TRUE;
  3295. //
  3296. // If the user did not check the 'Do not install additional drivers' and
  3297. // the policy bits indicate we should add the addtional drivers and the
  3298. // the user is not using a existing driver and the user has not
  3299. // used the 'HaveDisk'.
  3300. //
  3301. if( !_bUseWeb && _bAdditionalDrivers && _dwAdditionalDrivers != -1 && _bUseNewDriver && !_Di.bIsOemDriver() )
  3302. {
  3303. //
  3304. // If we should install the default additional drivers.
  3305. //
  3306. if( _dwAdditionalDrivers == 0 )
  3307. {
  3308. _dwAdditionalDrivers = kDefaultAdditionalDrivers;
  3309. }
  3310. DBGMSG( DBG_TRACE, ( "Wizard.bAddAdditonalDrivers additional drivers %x\n", _dwAdditionalDrivers ));
  3311. //
  3312. // Install the additional drivers.
  3313. //
  3314. for( UINT i = 0, uBit = 1; uBit; uBit <<= 1, i++ )
  3315. {
  3316. //
  3317. // Did we find a match.
  3318. //
  3319. if( uBit & _dwAdditionalDrivers )
  3320. {
  3321. DWORD dwEncode;
  3322. //
  3323. // Convert this bit to a driver encode.
  3324. //
  3325. if( TArchLV::bGetEncodeFromIndex( i, &dwEncode ) )
  3326. {
  3327. //
  3328. // Do not re-install installed drivers.
  3329. //
  3330. if( !_Di.bIsDriverInstalled( dwEncode ) )
  3331. {
  3332. //
  3333. // Install the printer driver.
  3334. //
  3335. if( !TWizDriverEnd::bInstallDriver( hwnd, dwEncode, _Di, FALSE, DRVINST_PROMPTLESS, &_strDriverName ) )
  3336. {
  3337. bStatus = FALSE;
  3338. }
  3339. }
  3340. }
  3341. }
  3342. }
  3343. }
  3344. //
  3345. // We indicate failure if any additional driver fails
  3346. // to install successfully.
  3347. //
  3348. return bStatus;
  3349. }
  3350. BOOL
  3351. TWizard::
  3352. bInstallPrinter(
  3353. IN LPCTSTR pszServerName,
  3354. IN LPCTSTR pszPrinterName,
  3355. IN LPCTSTR pszShareName,
  3356. IN LPCTSTR pszPortName,
  3357. IN LPCTSTR pszDriverName,
  3358. IN LPCTSTR pszPrintProcessor,
  3359. IN LPCTSTR pszLocation,
  3360. IN LPCTSTR pszComment,
  3361. IN BOOL bShared,
  3362. IN BOOL bPublish,
  3363. IN EAddPrinterAttributes eAttributeFlags,
  3364. IN EDsStatus eIsDsAvailable,
  3365. IN DWORD dwAttributes,
  3366. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  3367. )
  3368. /*++
  3369. Routine Description:
  3370. Installs a printer by calling add printer.
  3371. Arguments:
  3372. Parameters needed for filling in a printer info 2
  3373. structure and a printer info 7 structure.
  3374. Return Value:
  3375. TRUE = success, FALSE = fail.
  3376. --*/
  3377. {
  3378. TStatusB bStatus;
  3379. HANDLE hPrinter;
  3380. AddInfo Info;
  3381. TWaitCursor Cur;
  3382. //
  3383. // Fill in the Info structure.
  3384. //
  3385. Info.pszServerName = pszServerName;
  3386. Info.pszPrinterName = pszPrinterName;
  3387. Info.pszShareName = pszShareName;
  3388. Info.pszPrintProcessor = pszPrintProcessor;
  3389. Info.bShared = bShared;
  3390. Info.bPublish = bPublish;
  3391. Info.eFlags = eAttributeFlags;
  3392. Info.eIsDsAvailable = eIsDsAvailable;
  3393. Info.dwAttributes = dwAttributes;
  3394. //
  3395. // Do any pre add printer actions.
  3396. //
  3397. bStatus DBGCHK = bPreAddPrinter( Info );
  3398. if( bStatus )
  3399. {
  3400. //
  3401. // Ask the spooler to add this printer.
  3402. //
  3403. PRINTER_INFO_2 PrinterInfo2;
  3404. ZeroMemory( &PrinterInfo2, sizeof( PrinterInfo2 ));
  3405. PrinterInfo2.pPrinterName = (LPTSTR)pszPrinterName;
  3406. PrinterInfo2.pShareName = (LPTSTR)Info.pszShareName;
  3407. PrinterInfo2.pPortName = (LPTSTR)pszPortName;
  3408. PrinterInfo2.pDriverName = (LPTSTR)pszDriverName;
  3409. PrinterInfo2.pLocation = (LPTSTR)pszLocation;
  3410. PrinterInfo2.pComment = (LPTSTR)pszComment;
  3411. PrinterInfo2.pPrintProcessor = (LPTSTR)Info.pszPrintProcessor;
  3412. PrinterInfo2.pDatatype = (LPTSTR)gszDefaultDataType;
  3413. PrinterInfo2.Attributes = Info.dwAttributes;
  3414. PrinterInfo2.pSecurityDescriptor= pSecurityDescriptor;
  3415. hPrinter = AddPrinter( (LPTSTR)pszServerName, 2, (PBYTE)&PrinterInfo2 );
  3416. //
  3417. // Do any post add printer processing.
  3418. //
  3419. bStatus DBGCHK = bPostAddPrinter( Info, hPrinter );
  3420. if( hPrinter ){
  3421. bStatus DBGCHK = ClosePrinter( hPrinter );
  3422. bStatus DBGNOCHK = TRUE;
  3423. } else {
  3424. bStatus DBGNOCHK = FALSE;
  3425. }
  3426. }
  3427. return bStatus;
  3428. }
  3429. BOOL
  3430. TWizard::
  3431. bPreAddPrinter(
  3432. IN AddInfo &Info
  3433. )
  3434. /*++
  3435. Routine Description:
  3436. Handles any pre printer install processing. Note this routine is very
  3437. tighly coupled to the bInstallPrinter routine.
  3438. Arguments:
  3439. Pointer to add info structure.
  3440. Return Value:
  3441. TRUE pre printer install was successful, otherwize FALSE.
  3442. --*/
  3443. {
  3444. TStatusB bStatus;
  3445. bStatus DBGNOCHK = TRUE;
  3446. //
  3447. // If a valid print processor string was given
  3448. // use it, otherwize use the default print
  3449. // processor.
  3450. //
  3451. if( !Info.pszPrintProcessor || !*Info.pszPrintProcessor )
  3452. {
  3453. Info.pszPrintProcessor = gszDefaultPrintProcessor;
  3454. }
  3455. //
  3456. // The default attribute is to print spooled jobs first.
  3457. //
  3458. DWORD dwDefaultAttributes = PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST;
  3459. //
  3460. // Get the default attributes from the registry if the value is not there
  3461. // then set the default attribute value.
  3462. //
  3463. TPersist Persist( gszAddPrinterWizard, TPersist::kCreate|TPersist::kRead|TPersist::kWrite );
  3464. if( VALID_OBJ( Persist ) )
  3465. {
  3466. bStatus DBGCHK = Persist.bRead( gszAPWAttributes, dwDefaultAttributes );
  3467. if( !bStatus )
  3468. {
  3469. //
  3470. // Set the default attribute in the registry.
  3471. //
  3472. bStatus DBGCHK = Persist.bWrite( gszAPWAttributes, dwDefaultAttributes );
  3473. }
  3474. }
  3475. //
  3476. // Set the returned default attributes, not we are clearing the sharing
  3477. // bit to ensure we do not try and share the printer during the add
  3478. // printer call. If the print is to be shared then we will share it
  3479. // during the post add printer call.
  3480. //
  3481. Info.dwAttributes |= (dwDefaultAttributes & ~PRINTER_ATTRIBUTE_SHARED);
  3482. //
  3483. // If we are to create a masq printer, set the attribute bits that indicate
  3484. // it is a masq printer. A masq printer is a printer which has both the
  3485. // local and network attribute bits set.
  3486. //
  3487. if( Info.eFlags == kAttributesMasq )
  3488. {
  3489. Info.dwAttributes |= PRINTER_ATTRIBUTE_LOCAL | PRINTER_ATTRIBUTE_NETWORK;
  3490. }
  3491. //
  3492. // There is a race conditions when attempting to use a port that was dynamicaly
  3493. // added ports. We make a EnumPorts call to kick off discovery of this new
  3494. // port before the AddPrinter call is done.
  3495. //
  3496. // This is really should be done in spooler.
  3497. //
  3498. if( !Info.pszServerName || !*Info.pszServerName )
  3499. {
  3500. DWORD dwLevel = 2;
  3501. PPORT_INFO_2 pPorts = NULL;
  3502. DWORD cbPorts = 0;
  3503. DWORD cPorts = 0;
  3504. //
  3505. // Enumerate the port starting at level 2.
  3506. //
  3507. bStatus DBGCHK = VDataRefresh::bEnumPortsMaxLevel( Info.pszServerName,
  3508. &dwLevel,
  3509. (PVOID *)&pPorts,
  3510. &cbPorts,
  3511. &cPorts );
  3512. if( bStatus )
  3513. {
  3514. FreeMem( pPorts );
  3515. }
  3516. }
  3517. //
  3518. // If we are adding the masq printer do not validate the printer name.
  3519. //
  3520. if( Info.eFlags == kAttributesMasq )
  3521. {
  3522. bStatus DBGNOCHK = TRUE;
  3523. }
  3524. else
  3525. {
  3526. //
  3527. // Check the printe name for illegal characters.
  3528. //
  3529. bStatus DBGCHK = bIsLocalPrinterNameValid( Info.pszPrinterName );
  3530. if( !bStatus )
  3531. {
  3532. SetLastError( ERROR_INVALID_PRINTER_NAME );
  3533. }
  3534. }
  3535. return bStatus;
  3536. }
  3537. BOOL
  3538. TWizard::
  3539. bPostAddPrinter(
  3540. IN AddInfo &Info,
  3541. IN HANDLE hPrinter
  3542. )
  3543. /*++
  3544. Routine Description:
  3545. Handles any post printer install processing. Note this routine is very
  3546. tighly coupled to the bInstallPrinter routine.
  3547. Arguments:
  3548. Pointer to add info structure.
  3549. Return Value:
  3550. TRUE post printer install was successful, otherwize FALSE.
  3551. --*/
  3552. {
  3553. TStatusB bStatus;
  3554. bStatus DBGNOCHK = FALSE;
  3555. if( !hPrinter )
  3556. {
  3557. DBGMSG( DBG_TRACE, ( "bPostAddPrinter called with invalid printer handle.\n" ) );
  3558. return FALSE;
  3559. }
  3560. //
  3561. // We don't share or publish the masq printers.
  3562. //
  3563. if( Info.eFlags == kAttributesMasq )
  3564. {
  3565. DBGMSG( DBG_TRACE, ( "bPostAddPrinter called with masq printer.\n" ) );
  3566. return FALSE;
  3567. }
  3568. //
  3569. // If the network is available and we are to share the printer.
  3570. //
  3571. if( TPrtShare::bNetworkInstalled() && Info.bShared )
  3572. {
  3573. TString strShareName;
  3574. TString strPrinterName;
  3575. TPrtShare PrtShare( Info.pszServerName );
  3576. if( !Info.pszShareName || !*Info.pszShareName )
  3577. {
  3578. //
  3579. // Copy the printer name to a temporary string class because the
  3580. // TPrtShare object only accepts the printer name as a string refrence.
  3581. //
  3582. bStatus DBGCHK = strPrinterName.bUpdate( Info.pszPrinterName );
  3583. //
  3584. // Validate the prt share object and the printer name.
  3585. //
  3586. bStatus DBGNOCHK = VALID_OBJ( PrtShare ) && VALID_OBJ( strPrinterName );
  3587. if( bStatus )
  3588. {
  3589. //
  3590. // Generate a unique share name.
  3591. //
  3592. bStatus DBGCHK = PrtShare.bNewShareName( strShareName, strPrinterName );
  3593. }
  3594. }
  3595. else
  3596. {
  3597. bStatus DBGCHK = strShareName.bUpdate( Info.pszShareName );
  3598. }
  3599. //
  3600. // If the share name was either given or generated then
  3601. // attempt to share the printer.
  3602. //
  3603. if( bStatus )
  3604. {
  3605. PPRINTER_INFO_2 pInfo2 = NULL;
  3606. DWORD cbInfo2 = 0;
  3607. //
  3608. // Get the current printer info 2.
  3609. //
  3610. bStatus DBGCHK = VDataRefresh::bGetPrinter( hPrinter, 2, (PVOID*)&pInfo2, &cbInfo2 );
  3611. if( bStatus )
  3612. {
  3613. pInfo2->Attributes |= PRINTER_ATTRIBUTE_SHARED;
  3614. pInfo2->pShareName = (LPTSTR)(LPCTSTR)strShareName;
  3615. bStatus DBGCHK = SetPrinter( hPrinter, 2, (PBYTE)pInfo2, 0 );
  3616. }
  3617. //
  3618. // Release the printer info 2 structure.
  3619. //
  3620. FreeMem( pInfo2 );
  3621. }
  3622. //
  3623. // Attempt to publish the printer if the DS is available.
  3624. // Note this is only a suggestion, if the publish fails
  3625. // do not inform the user just complete the add printer.
  3626. //
  3627. if( bStatus && Info.bPublish && ( Info.eIsDsAvailable == kDsStatusAvailable ) )
  3628. {
  3629. DBGMSG( DBG_TRACE, ( "bPostAddPrinter attempting to publish printer.\n" ) );
  3630. PRINTER_INFO_7 Info7 = { 0 };
  3631. Info7.dwAction = DSPRINT_PUBLISH;
  3632. bStatus DBGCHK = SetPrinter( hPrinter, 7, (PBYTE)&Info7, 0 );
  3633. }
  3634. }
  3635. return bStatus;
  3636. }
  3637. VOID
  3638. TWizard::
  3639. vTerminate(
  3640. IN HWND hDlg
  3641. )
  3642. /*++
  3643. Routine Description:
  3644. Terminates the wizard.
  3645. Arguments:
  3646. Window handle of current page.
  3647. Return Value:
  3648. Nothing.
  3649. --*/
  3650. {
  3651. PostMessage( GetParent( hDlg ), PSM_PRESSBUTTON, PSBTN_CANCEL, 0 );
  3652. }
  3653. VOID
  3654. TWizard::
  3655. vReadRegistrySettingDefaults(
  3656. VOID
  3657. )
  3658. /*++
  3659. Routine Description:
  3660. Reads any default settings from the registry.
  3661. Arguments:
  3662. None.
  3663. Return Value:
  3664. Nothing.
  3665. --*/
  3666. {
  3667. TStatusB bStatus;
  3668. TPersist Persist( gszAddPrinterWizard, TPersist::kCreate|TPersist::kRead );
  3669. if( VALID_OBJ( Persist ) && _bPersistSettings )
  3670. {
  3671. bStatus DBGNOCHK = Persist.bRead( gszAPWTestPage, _bTestPage );
  3672. bStatus DBGNOCHK = Persist.bRead( gszAPWUseWeb, _bUseWeb );
  3673. bStatus DBGNOCHK = Persist.bRead( gszAPWUseExisting, _bUseNewDriverSticky );
  3674. bStatus DBGNOCHK = Persist.bRead( gszAPWSetAsDefault, _bSetDefault );
  3675. bStatus DBGNOCHK = Persist.bRead( gszAPWDriverName, _strDriverName );
  3676. bStatus DBGNOCHK = Persist.bRead( gszAPWLocalPrinter, _bNet );
  3677. bStatus DBGNOCHK = Persist.bRead( gszAPWShared, _bShared );
  3678. bStatus DBGNOCHK = Persist.bRead( gszAPWAdditionalDrv, _bAdditionalDrivers );
  3679. bStatus DBGNOCHK = Persist.bRead( gszAPWPnPAutodetect, _bPnPAutodetect );
  3680. }
  3681. //
  3682. // Read the bits from the policy location.
  3683. //
  3684. TPersist PersistPolicy( gszAddPrinterWizardPolicy, TPersist::kOpen|TPersist::kRead );
  3685. if( VALID_OBJ( PersistPolicy ) )
  3686. {
  3687. bStatus DBGNOCHK = PersistPolicy.bRead( gszAPWSharing, _bShared );
  3688. bStatus DBGNOCHK = PersistPolicy.bRead( gszAPWDownLevelBrowse, _bDownlevelBrowse );
  3689. //
  3690. // After the drivers went to a CAB file and we removed
  3691. // the cross-platform drivers from the media we will never
  3692. // give the user oportunity to install additional drivers
  3693. // in the APW
  3694. //
  3695. // bStatus DBGNOCHK = PersistPolicy.bRead( gszAPWDrivers, _dwAdditionalDrivers );
  3696. bStatus DBGNOCHK = PersistPolicy.bRead( gszAPWPrintersPageURL, _strPrintersPageURL );
  3697. }
  3698. //
  3699. // Read the bits from the policy location from hkey local machine.
  3700. //
  3701. TPersist PersistPolicy2( gszAddPrinterWizardPolicy, TPersist::kOpen|TPersist::kRead, HKEY_LOCAL_MACHINE );
  3702. if( VALID_OBJ( PersistPolicy2 ) )
  3703. {
  3704. bStatus DBGNOCHK = PersistPolicy2.bRead( gszAPWPublish, _bPublish );
  3705. }
  3706. //
  3707. // Read the per machine policy bit that the spooler uses for
  3708. // printer publishing. The per user policy and the per machine policy
  3709. // must agree inorder for the wizard to publish the printer.
  3710. //
  3711. TPersist SpoolerPolicy( gszSpoolerPolicy, TPersist::kOpen|TPersist::kRead, HKEY_LOCAL_MACHINE );
  3712. if( VALID_OBJ( SpoolerPolicy ) )
  3713. {
  3714. BOOL bCanPublish = kDefaultPublishState;
  3715. bStatus DBGNOCHK = SpoolerPolicy.bRead( gszSpoolerPublish, bCanPublish );
  3716. if( bStatus )
  3717. {
  3718. _bPublish = _bPublish && bCanPublish;
  3719. }
  3720. }
  3721. }
  3722. VOID
  3723. TWizard::
  3724. vWriteRegistrySettingDefaults(
  3725. VOID
  3726. )
  3727. /*++
  3728. Routine Description:
  3729. Writes any default settings to the registry.
  3730. Arguments:
  3731. None.
  3732. Return Value:
  3733. Nothing.
  3734. --*/
  3735. {
  3736. TPersist Persist( gszAddPrinterWizard, TPersist::kOpen|TPersist::kWrite );
  3737. if( VALID_OBJ( Persist ) && _bPersistSettings )
  3738. {
  3739. TStatusB bStatus;
  3740. bStatus DBGCHK = Persist.bWrite( gszAPWTestPage, _bTestPage );
  3741. bStatus DBGCHK = Persist.bWrite( gszAPWUseWeb, _bUseWeb );
  3742. bStatus DBGCHK = Persist.bWrite( gszAPWUseExisting, _bUseNewDriverSticky );
  3743. bStatus DBGCHK = Persist.bWrite( gszAPWSetAsDefault, _bSetDefault );
  3744. bStatus DBGCHK = Persist.bWrite( gszAPWDriverName, _strDriverName );
  3745. bStatus DBGCHK = Persist.bWrite( gszAPWLocalPrinter, _bNet );
  3746. bStatus DBGCHK = Persist.bWrite( gszAPWShared, _bShared );
  3747. bStatus DBGCHK = Persist.bWrite( gszAPWAdditionalDrv, _bAdditionalDrivers );
  3748. bStatus DBGCHK = Persist.bWrite( gszAPWPnPAutodetect, _bPnPAutodetect );
  3749. }
  3750. }
  3751. /********************************************************************
  3752. Generic wizard base class.
  3753. ********************************************************************/
  3754. MWizardProp::
  3755. MWizardProp(
  3756. TWizard* pWizard
  3757. ) : _pWizard( pWizard )
  3758. {
  3759. }
  3760. MWizardProp::
  3761. ~MWizardProp(
  3762. VOID
  3763. )
  3764. {
  3765. }
  3766. BOOL
  3767. MWizardProp::
  3768. bHandleMessage(
  3769. UINT uMsg,
  3770. WPARAM wParam,
  3771. LPARAM lParam
  3772. )
  3773. {
  3774. BOOL bReturn = FALSE;
  3775. switch( uMsg )
  3776. {
  3777. case WM_INITDIALOG:
  3778. {
  3779. //
  3780. // Patch some styles of the property sheet window once
  3781. //
  3782. vCheckToPatchStyles( );
  3783. //
  3784. // Handle the WM_INITDIALOG message
  3785. //
  3786. bReturn = bHandle_InitDialog();
  3787. }
  3788. break;
  3789. case WM_COMMAND:
  3790. bReturn = bHandle_Command( GET_WM_COMMAND_ID( wParam, lParam ),
  3791. GET_WM_COMMAND_CMD(wParam, lParam ),
  3792. (HWND)lParam );
  3793. break;
  3794. case WM_TIMER:
  3795. bReturn = bHandle_Timer( wParam, (TIMERPROC *)lParam );
  3796. break;
  3797. case WM_NOTIFY:
  3798. {
  3799. LPNMHDR pnmh = (LPNMHDR)lParam;
  3800. switch( pnmh->code )
  3801. {
  3802. case PSN_SETACTIVE:
  3803. bReturn = bHandle_SetActive();
  3804. break;
  3805. case PSN_KILLACTIVE:
  3806. bReturn = bHandle_KillActive();
  3807. break;
  3808. case PSN_WIZBACK:
  3809. bReturn = bHandle_WizBack();
  3810. break;
  3811. case PSN_WIZNEXT:
  3812. bReturn = bHandle_WizNext();
  3813. break;
  3814. case PSN_WIZFINISH:
  3815. bReturn = bHandle_WizFinish();
  3816. break;
  3817. case PSN_QUERYCANCEL:
  3818. bReturn = bHandle_Cancel();
  3819. break;
  3820. //
  3821. // Message not handled.
  3822. //
  3823. default:
  3824. bReturn = bHandle_Notify( wParam, pnmh );
  3825. break;
  3826. }
  3827. //
  3828. // Handle any page changes.
  3829. //
  3830. bReturn = bHandle_PageChange( bReturn, pnmh->code, wParam, lParam );
  3831. }
  3832. break;
  3833. //
  3834. // Message not handled.
  3835. //
  3836. default:
  3837. bReturn = FALSE;
  3838. break;
  3839. }
  3840. return bReturn;
  3841. }
  3842. VOID
  3843. MWizardProp::
  3844. vCheckToPatchStyles(
  3845. VOID
  3846. )
  3847. {
  3848. SPLASSERT( _pWizard );
  3849. SPLASSERT( _hDlg );
  3850. if( !_pWizard->bStylePatched() )
  3851. {
  3852. HWND hPropSheet = GetParent( _hDlg );
  3853. SPLASSERT( hPropSheet );
  3854. LONG lStyle = GetWindowLong( hPropSheet, GWL_STYLE );
  3855. lStyle &= ~( WS_SYSMENU | DS_CONTEXTHELP );
  3856. SetWindowLong( hPropSheet, GWL_STYLE, lStyle );
  3857. _pWizard->bStylePatched() = TRUE;
  3858. }
  3859. }
  3860. BOOL
  3861. MWizardProp::
  3862. bHandle_InitDialog(
  3863. VOID
  3864. )
  3865. {
  3866. return FALSE;
  3867. }
  3868. BOOL
  3869. MWizardProp::
  3870. bHandle_Command(
  3871. IN WORD wId,
  3872. IN WORD wNotifyId,
  3873. IN HWND hwnd
  3874. )
  3875. {
  3876. return FALSE;
  3877. }
  3878. BOOL
  3879. MWizardProp::
  3880. bHandle_Notify(
  3881. IN WPARAM wParam,
  3882. IN LPNMHDR pnmh
  3883. )
  3884. {
  3885. return FALSE;
  3886. }
  3887. BOOL
  3888. MWizardProp::
  3889. bHandle_SetActive(
  3890. VOID
  3891. )
  3892. {
  3893. return FALSE;
  3894. }
  3895. BOOL
  3896. MWizardProp::
  3897. bHandle_KillActive(
  3898. VOID
  3899. )
  3900. {
  3901. return FALSE;
  3902. }
  3903. BOOL
  3904. MWizardProp::
  3905. bHandle_WizBack(
  3906. VOID
  3907. )
  3908. {
  3909. return FALSE;
  3910. }
  3911. BOOL
  3912. MWizardProp::
  3913. bHandle_WizNext(
  3914. VOID
  3915. )
  3916. {
  3917. return FALSE;
  3918. }
  3919. BOOL
  3920. MWizardProp::
  3921. bHandle_WizFinish(
  3922. VOID
  3923. )
  3924. {
  3925. return FALSE;
  3926. }
  3927. BOOL
  3928. MWizardProp::
  3929. bHandle_Cancel(
  3930. VOID
  3931. )
  3932. {
  3933. _pWizard->_bWizardCanceled = TRUE;
  3934. return FALSE;
  3935. }
  3936. BOOL
  3937. MWizardProp::
  3938. bHandle_Timer(
  3939. IN WPARAM wIdTimer,
  3940. IN TIMERPROC *tmProc
  3941. )
  3942. {
  3943. return FALSE;
  3944. }
  3945. VOID
  3946. MWizardProp::
  3947. SetControlFont(
  3948. IN HFONT hFont,
  3949. IN HWND hwnd,
  3950. IN INT nId
  3951. )
  3952. {
  3953. if( hFont )
  3954. {
  3955. HWND hwndControl = GetDlgItem(hwnd, nId);
  3956. if( hwndControl )
  3957. {
  3958. SetWindowFont(hwndControl, hFont, TRUE);
  3959. }
  3960. }
  3961. }
  3962. BOOL
  3963. MWizardProp::
  3964. bHandle_PageChange(
  3965. IN BOOL bReturn,
  3966. IN UINT uMsg,
  3967. IN WPARAM wParam,
  3968. IN LPARAM lParam
  3969. )
  3970. {
  3971. //
  3972. // If no page change request was made then
  3973. // do not switch the page and return.
  3974. //
  3975. if( _pWizard->bNoPageChange() )
  3976. {
  3977. _pWizard->bNoPageChange() = FALSE;
  3978. // XP bug #22031: if uMsg == PSN_WIZFINISH then in case we want to prevent the wizard
  3979. // from finishing we should return the handle of a window to receive the focus (this is
  3980. // valid for comctl32 ver 5.80 or higer - for more information, see SDK).
  3981. vSetDlgMsgResult( uMsg == PSN_WIZFINISH ? reinterpret_cast<LONG_PTR>(_hDlg) : (LPARAM)-1 );
  3982. return TRUE;
  3983. }
  3984. if( uMsg == PSN_WIZNEXT ||
  3985. uMsg == PSN_WIZBACK ||
  3986. uMsg == PSN_SETACTIVE ||
  3987. uMsg == PSN_KILLACTIVE )
  3988. {
  3989. //
  3990. // The Twizard object controls both the add printer and add driver wizard.
  3991. // Since these two wizard do not share the page switching code we must
  3992. // detect which mode the wizard is in.
  3993. //
  3994. if( _pWizard->uAction() == TWizard::kPnPInstall ||
  3995. _pWizard->uAction() == TWizard::kPrinterInstall ||
  3996. _pWizard->uAction() == TWizard::kPrinterInstallModeless )
  3997. {
  3998. //
  3999. // Handle the add printer wizard page change.
  4000. //
  4001. if( bAddPrinterWizardPageChange( uMsg ) )
  4002. {
  4003. bReturn = TRUE;
  4004. }
  4005. }
  4006. if( _pWizard->uAction() == TWizard::kDriverInstall )
  4007. {
  4008. //
  4009. // Handle the add driver wizard page change.
  4010. //
  4011. if( bDriverWizardPageChange( uMsg ) )
  4012. {
  4013. bReturn = TRUE;
  4014. }
  4015. }
  4016. }
  4017. return bReturn;
  4018. }
  4019. BOOL
  4020. MWizardProp::
  4021. bAddPrinterWizardPageChange(
  4022. IN UINT uMsg
  4023. )
  4024. {
  4025. BOOL bReturn = FALSE;
  4026. static PrinterWizPageEntry Table [] = {
  4027. // Message Current Page SharingEnabled, Autodetect, PrnDetected, PnpInstall, Keep Existing, Driver Exists, Net Avail, Network, Is Remote DS, Dir Pre, Dir Post Default Shared, Admin LocateType bDownlevelBrowse bConnected Result Extra
  4028. { PSN_SETACTIVE, DLG_WIZ_PRE_INTRO, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_INTRO, kPush },
  4029. { PSN_SETACTIVE, DLG_WIZ_PRE_INTRO, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_PORT_NEW, kPush },
  4030. { PSN_WIZNEXT, DLG_WIZ_INTRO, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_TYPE, kPush },
  4031. { PSN_WIZNEXT, DLG_WIZ_INTRO, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_PORT_NEW, kPush },
  4032. // DLG_WIZ_TYPE rules
  4033. { PSN_WIZNEXT, DLG_WIZ_TYPE, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, DLG_WIZ_DETECT, kPush },
  4034. { PSN_WIZNEXT, DLG_WIZ_TYPE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kTrue, kTrue, TWizard::kSelectPrinterPage, kPush },
  4035. { PSN_WIZNEXT, DLG_WIZ_TYPE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_LOCATE, kPush },
  4036. { PSN_WIZNEXT, DLG_WIZ_TYPE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_PORT_NEW, kPush },
  4037. // DLG_WIZ_DETECT rules
  4038. { PSN_WIZNEXT, DLG_WIZ_DETECT, kDontCare, kTrue, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, DLG_WIZ_FINISH, kPush },
  4039. { PSN_WIZNEXT, DLG_WIZ_DETECT, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, DLG_WIZ_PORT_NEW, kPush },
  4040. // DLG_WIZ_LOCATE rules
  4041. { PSN_WIZNEXT, DLG_WIZ_LOCATE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, TWizard::kSearch, kTrue, kFalse, TWizard::kSelectPrinterPage, kPush },
  4042. { PSN_WIZNEXT, DLG_WIZ_LOCATE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, TWizard::kBrowseNET, kTrue, kFalse, TWizard::kSelectPrinterPage, kPush },
  4043. { PSN_WIZNEXT, DLG_WIZ_LOCATE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, TWizard::kSearch, kDontCare, kTrue, DLG_WIZ_NET, kPush },
  4044. { PSN_WIZNEXT, DLG_WIZ_LOCATE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, TWizard::kSearch, kDontCare, kTrue, DLG_WIZ_FINISH, kPush },
  4045. { PSN_WIZNEXT, DLG_WIZ_LOCATE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, DLG_WIZ_NET, kPush },
  4046. { PSN_WIZNEXT, DLG_WIZ_LOCATE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, DLG_WIZ_FINISH, kPush },
  4047. { PSN_WIZNEXT, DLG_WIZ_DRIVEREXISTS, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_NAME, kPush },
  4048. { PSN_WIZNEXT, DLG_WIZ_NAME, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_TEST_PAGE, kPush },
  4049. { PSN_WIZNEXT, DLG_WIZ_TEST_PAGE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_FINISH, kPush },
  4050. { PSN_WIZNEXT, DLG_WIZ_NET, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_FINISH, kPush },
  4051. { PSN_WIZNEXT, DLG_WIZ_NAME, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_SHARE, kPush },
  4052. { PSN_WIZNEXT, DLG_WIZ_NAME, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_TEST_PAGE, kPush },
  4053. { PSN_WIZNEXT, DLG_WIZ_SHARE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_COMMENT, kPush },
  4054. { PSN_WIZNEXT, DLG_WIZ_SHARE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_TEST_PAGE, kPush },
  4055. { PSN_WIZNEXT, DLG_WIZ_COMMENT, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_TEST_PAGE, kPush },
  4056. { PSN_WIZNEXT, DLG_WIZ_PORT_NEW, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_PRE_SELECT_DEVICE, kPush },
  4057. { PSN_SETACTIVE, DLG_WIZ_PRE_SELECT_DEVICE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kSkipPage },
  4058. { PSN_SETACTIVE, DLG_WIZ_POST_SELECT_DEVICE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_NAME, kPush },
  4059. { PSN_SETACTIVE, DLG_WIZ_POST_SELECT_DEVICE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, DLG_WIZ_DRIVEREXISTS, kPush },
  4060. { PSN_WIZBACK, DLG_WIZ_DRIVEREXISTS, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kPop },
  4061. { PSN_WIZBACK, DLG_WIZ_NAME, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kPop },
  4062. { PSN_SETACTIVE, DLG_WIZ_POST_SELECT_DEVICE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kSkipPage },
  4063. { PSN_SETACTIVE, DLG_WIZ_PRE_SELECT_DEVICE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kPop },
  4064. { PSN_WIZBACK, DLG_WIZ_PORT_NEW, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, IDD_DYNAWIZ_SELECTCLASS_PAGE, kPop },
  4065. { PSN_WIZBACK, DLG_WIZ_TYPE, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kPop },
  4066. { PSN_WIZBACK, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kPop },
  4067. { PSN_SETACTIVE, DLG_WIZ_INTRO, kDontCare, kDontCare, kDontCare, kTrue, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_NEXT | PSWIZB_BACK, kSetButtonState },
  4068. { PSN_SETACTIVE, DLG_WIZ_INTRO, kDontCare, kDontCare, kDontCare, kFalse, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_NEXT, kSetButtonState },
  4069. { PSN_SETACTIVE, DLG_WIZ_PORT_NEW, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4070. { PSN_SETACTIVE, DLG_WIZ_NAME, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4071. { PSN_SETACTIVE, DLG_WIZ_SHARE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4072. { PSN_SETACTIVE, DLG_WIZ_COMMENT, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4073. { PSN_SETACTIVE, DLG_WIZ_DRIVEREXISTS, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4074. { PSN_SETACTIVE, DLG_WIZ_LOCATE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4075. { PSN_SETACTIVE, DLG_WIZ_TEST_PAGE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4076. { PSN_SETACTIVE, DLG_WIZ_TYPE, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4077. { PSN_SETACTIVE, DLG_WIZ_NET, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, kDontCare, PSWIZB_NEXT, kSetButtonState },
  4078. { kEnd }};
  4079. //
  4080. // Scan for a message match, disregarding don't care fields.
  4081. //
  4082. for( PrinterWizPageEntry *pTable = Table; pTable->uMessage != kEnd; pTable++ )
  4083. {
  4084. PrinterWizPageEntry Entry;
  4085. Entry.uMessage = pTable->uMessage == kDontCare ? kDontCare : uMsg;
  4086. Entry.uCurrentPage = pTable->uCurrentPage == kDontCare ? kDontCare : uGetPageId();
  4087. Entry.uSharingEnabled = pTable->uSharingEnabled == kDontCare ? kDontCare : _pWizard->bIsSharingEnabled() ? kTrue : kFalse;
  4088. Entry.uAutodetect = pTable->uAutodetect == kDontCare ? kDontCare : _pWizard->pszServerName() ? 0 : _pWizard->_bPnPAutodetect;
  4089. Entry.uPrinterDetected = pTable->uPrinterDetected == kDontCare ? kDontCare : _pWizard->bPrinterAutoDetected();
  4090. Entry.uPnPInstall = pTable->uPnPInstall == kDontCare ? kDontCare : _pWizard->uAction() == TWizard::kPnPInstall ? kTrue : kFalse;
  4091. Entry.uDriverExists = pTable->uDriverExists == kDontCare ? kDontCare : _pWizard->uDriverExists() == TWizard::kExists ? kTrue : kFalse;
  4092. Entry.uSharing = pTable->uSharing == kDontCare ? kDontCare : _pWizard->bNetworkInstalled() ? kTrue : kFalse;
  4093. Entry.uNetwork = pTable->uNetwork == kDontCare ? kDontCare : _pWizard->bNet() ? kTrue : kFalse;
  4094. Entry.bIsRemoteServer = pTable->bIsRemoteServer == kDontCare ? kDontCare : bIsRemote( _pWizard->pszServerName() ) ? kTrue : kFalse;
  4095. Entry.uDirectoryService = pTable->uDirectoryService == kDontCare ? kDontCare : _pWizard->eIsDsAvailablePerUser() == TWizard::kDsStatusAvailable ? kTrue : kFalse;
  4096. Entry.uKeepExisting = pTable->uKeepExisting == kDontCare ? kDontCare : !_pWizard->bUseNewDriver() ? kTrue : kFalse;
  4097. Entry.uSetDefault = pTable->uSetDefault == kDontCare ? kDontCare : _pWizard->bIsPrinterFolderEmpty() ? kTrue : kFalse;
  4098. Entry.uShared = pTable->uShared == kDontCare ? kDontCare : _pWizard->bShared() ? kTrue : kFalse;
  4099. Entry.uPreDir = pTable->uPreDir == kDontCare ? kDontCare : _pWizard->bPreDir();
  4100. Entry.uPostDir = pTable->uPostDir == kDontCare ? kDontCare : _pWizard->bPostDir();
  4101. Entry.bAdminPrivilege = pTable->bAdminPrivilege == kDontCare ? kDontCare : _pWizard->bAdminPrivilege();
  4102. Entry.nLocateType = pTable->nLocateType == kDontCare ? kDontCare : _pWizard->LocateType();
  4103. Entry.nDownlevelBrowse = pTable->nDownlevelBrowse == kDontCare ? kDontCare : _pWizard->bDownlevelBrowse() ? kTrue : kFalse;
  4104. Entry.uConnected = pTable->uConnected == kDontCare ? kDontCare : _pWizard->bConnected() ? kTrue : kFalse;
  4105. if( pTable->uMessage == Entry.uMessage &&
  4106. pTable->uCurrentPage == Entry.uCurrentPage &&
  4107. pTable->uSharingEnabled == Entry.uSharingEnabled &&
  4108. pTable->uAutodetect == Entry.uAutodetect &&
  4109. pTable->uPrinterDetected == Entry.uPrinterDetected &&
  4110. pTable->uPnPInstall == Entry.uPnPInstall &&
  4111. pTable->uDriverExists == Entry.uDriverExists &&
  4112. pTable->uSharing == Entry.uSharing &&
  4113. pTable->uNetwork == Entry.uNetwork &&
  4114. pTable->bIsRemoteServer == Entry.bIsRemoteServer &&
  4115. pTable->uDirectoryService == Entry.uDirectoryService &&
  4116. pTable->uKeepExisting == Entry.uKeepExisting &&
  4117. pTable->uSetDefault == Entry.uSetDefault &&
  4118. pTable->uShared == Entry.uShared &&
  4119. pTable->uPreDir == Entry.uPreDir &&
  4120. pTable->uPostDir == Entry.uPostDir &&
  4121. pTable->bAdminPrivilege == Entry.bAdminPrivilege &&
  4122. pTable->nDownlevelBrowse == Entry.nDownlevelBrowse &&
  4123. pTable->nLocateType == Entry.nLocateType &&
  4124. pTable->uConnected == Entry.uConnected )
  4125. {
  4126. break;
  4127. }
  4128. }
  4129. //
  4130. // If a table match was found handle the page switch.
  4131. //
  4132. if( pTable->uMessage != kEnd )
  4133. {
  4134. DBGMSG( DBG_NONE, ( "Match found Entry index %d\n" , pTable - Table ) );
  4135. TStatusB bStatus;
  4136. UINT uNextPage = 0;
  4137. switch( pTable->Action )
  4138. {
  4139. case kPush:
  4140. bStatus DBGCHK = _pWizard->Stack().bPush( uGetPageId() );
  4141. uNextPage = _pWizard->MapPageID(pTable->Result);
  4142. vSetDlgMsgResult( reinterpret_cast<LONG_PTR>(MAKEINTRESOURCE(uNextPage)) );
  4143. break;
  4144. case kPop:
  4145. bStatus DBGCHK = _pWizard->Stack().bPop( &uNextPage );
  4146. if( _pWizard->MapPageID(pTable->Result) != kNoPage )
  4147. {
  4148. uNextPage = _pWizard->MapPageID(pTable->Result);
  4149. }
  4150. vSetDlgMsgResult( reinterpret_cast<LONG_PTR>(MAKEINTRESOURCE(uNextPage)) );
  4151. break;
  4152. case kSkipPage:
  4153. vSetDlgMsgResult( -1 );
  4154. break;
  4155. case kSetButtonState:
  4156. PropSheet_SetWizButtons( GetParent( _hDlg ), pTable->Result );
  4157. break;
  4158. default:
  4159. break;
  4160. }
  4161. bReturn = TRUE;
  4162. }
  4163. return bReturn;
  4164. }
  4165. BOOL
  4166. MWizardProp::
  4167. bDriverWizardPageChange(
  4168. IN UINT uMsg
  4169. )
  4170. {
  4171. BOOL bReturn = FALSE;
  4172. static DriverWizPageEntry Table [] = {
  4173. // Message Current Page Skip Arch, Dir Pre, Dir Post Result Action
  4174. { PSN_WIZNEXT, DLG_WIZ_DRIVER_INTRO, kDontCare, kDontCare, kDontCare, DLG_WIZ_PRE_SELECT_DEVICE, kPush },
  4175. { PSN_WIZNEXT, DLG_WIZ_DRIVER_ARCHITECTURE, kDontCare, kDontCare, kDontCare, DLG_WIZ_DRIVER_END, kPush },
  4176. { PSN_SETACTIVE, DLG_WIZ_PRE_SELECT_DEVICE, kDontCare, kTrue, kDontCare, kNoPage, kSkipPage },
  4177. { PSN_SETACTIVE, DLG_WIZ_PRE_SELECT_DEVICE, kDontCare, kFalse, kDontCare, kNoPage, kPop },
  4178. { PSN_SETACTIVE, DLG_WIZ_POST_SELECT_DEVICE, kDontCare, kDontCare, kFalse, kNoPage, kSkipPage },
  4179. { PSN_SETACTIVE, DLG_WIZ_POST_SELECT_DEVICE, kFalse, kDontCare, kTrue, DLG_WIZ_DRIVER_ARCHITECTURE,kPush },
  4180. { PSN_SETACTIVE, DLG_WIZ_POST_SELECT_DEVICE, kTrue, kDontCare, kTrue, DLG_WIZ_DRIVER_END, kPush },
  4181. { PSN_SETACTIVE, DLG_WIZ_DRIVER_INTRO, kDontCare, kDontCare, kDontCare, PSWIZB_NEXT, kSetButtonState },
  4182. { PSN_SETACTIVE, DLG_WIZ_DRIVER_ARCHITECTURE, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_NEXT, kSetButtonState },
  4183. { PSN_SETACTIVE, DLG_WIZ_DRIVER_END, kDontCare, kDontCare, kDontCare, PSWIZB_BACK | PSWIZB_FINISH,kSetButtonState },
  4184. { PSN_WIZBACK, kDontCare, kDontCare, kDontCare, kDontCare, kNoPage, kPop },
  4185. { kEnd }};
  4186. //
  4187. // Scan for a message match, disregarding don't care fields.
  4188. //
  4189. for( DriverWizPageEntry *pTable = Table; pTable->uMessage != kEnd; pTable++ )
  4190. {
  4191. DriverWizPageEntry Entry;
  4192. Entry.uMessage = uMsg;
  4193. Entry.uSkipArchPage = pTable->uSkipArchPage == kDontCare ? kDontCare : _pWizard->bSkipArchSelection();
  4194. Entry.uCurrentPage = pTable->uCurrentPage == kDontCare ? kDontCare : uGetPageId();
  4195. Entry.uPreDir = pTable->uPreDir == kDontCare ? kDontCare : _pWizard->bPreDir() ? kTrue : kFalse;
  4196. Entry.uPostDir = pTable->uPostDir == kDontCare ? kDontCare : _pWizard->bPostDir() ? kTrue : kFalse;
  4197. if( pTable->uMessage == Entry.uMessage &&
  4198. pTable->uCurrentPage == Entry.uCurrentPage &&
  4199. pTable->uSkipArchPage == Entry.uSkipArchPage &&
  4200. pTable->uPreDir == Entry.uPreDir &&
  4201. pTable->uPostDir == Entry.uPostDir )
  4202. {
  4203. break;
  4204. }
  4205. }
  4206. //
  4207. // If a table match was found handle the page switch.
  4208. //
  4209. if( pTable->uMessage != kEnd )
  4210. {
  4211. DBGMSG( DBG_NONE, ( "Match found Entry index %d\n" , pTable - Table ) );
  4212. TStatusB bStatus;
  4213. UINT uNextPage = 0;
  4214. switch( pTable->Action )
  4215. {
  4216. case kPush:
  4217. bStatus DBGCHK = _pWizard->Stack().bPush( uGetPageId() );
  4218. uNextPage = pTable->Result;
  4219. vSetDlgMsgResult( reinterpret_cast<LONG_PTR>(MAKEINTRESOURCE(uNextPage)) );
  4220. break;
  4221. case kPop:
  4222. bStatus DBGCHK = _pWizard->Stack().bPop( &uNextPage );
  4223. if( pTable->Result != kNoPage )
  4224. {
  4225. uNextPage = pTable->Result;
  4226. }
  4227. vSetDlgMsgResult( reinterpret_cast<LONG_PTR>(MAKEINTRESOURCE(uNextPage)) );
  4228. break;
  4229. case kSkipPage:
  4230. vSetDlgMsgResult( -1 );
  4231. break;
  4232. case kSetButtonState:
  4233. PropSheet_SetWizButtons( GetParent( _hDlg ), pTable->Result );
  4234. break;
  4235. default:
  4236. break;
  4237. }
  4238. bReturn = TRUE;
  4239. }
  4240. return bReturn;
  4241. }
  4242. /********************************************************************
  4243. Pre-Introduction
  4244. ********************************************************************/
  4245. TWizPreIntro::
  4246. TWizPreIntro(
  4247. TWizard *pWizard
  4248. ) : MWizardProp( pWizard )
  4249. {
  4250. }
  4251. BOOL
  4252. TWizPreIntro::
  4253. bHandle_SetActive(
  4254. VOID
  4255. )
  4256. {
  4257. if( _pWizard->uAction() != TWizard::kPnPInstall )
  4258. {
  4259. PropSheet_SetTitle( GetParent( _hDlg ), PSH_DEFAULT, _pWizard->_strTitle );
  4260. }
  4261. else
  4262. {
  4263. //
  4264. // Set the select device page title to the wizard title.
  4265. //
  4266. _pWizard->_Di.bSetDriverSetupPageTitle( _pWizard->_strSetupPageTitle, _pWizard->_strSetupPageSubTitle, _pWizard->_strSetupPageDescription );
  4267. }
  4268. return TRUE;
  4269. }
  4270. /********************************************************************
  4271. Introduction
  4272. ********************************************************************/
  4273. TWizIntro::
  4274. TWizIntro(
  4275. TWizard *pWizard
  4276. ) : MWizardProp( pWizard )
  4277. {
  4278. }
  4279. BOOL
  4280. TWizIntro::
  4281. bHandle_InitDialog(
  4282. VOID
  4283. )
  4284. {
  4285. TString strTemp;
  4286. TCHAR szServerName[kDNSMax + 1];
  4287. //
  4288. // The fonts for the Word 97 wizard style.
  4289. //
  4290. SetControlFont( _pWizard->_hBigBoldFont, _hDlg, IDC_MAIN_TITLE );
  4291. HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_INFORMATION));
  4292. if (hIcon)
  4293. {
  4294. HWND hwndIcon = GetDlgItem(_hDlg, IDC_ICON_INFO);
  4295. if (hwndIcon)
  4296. {
  4297. SendMessage(hwndIcon, STM_SETICON, (WPARAM )hIcon, 0L);
  4298. ShowWindow(hwndIcon, SW_SHOW);
  4299. }
  4300. }
  4301. TString strUSBInfo;
  4302. TStatusB bStatus;
  4303. bStatus DBGCHK = strUSBInfo.bLoadString(ghInst, IDS_TEXT_USB);
  4304. if (bStatus)
  4305. {
  4306. HWND hwndText = GetDlgItem(_hDlg, IDC_TEXT_USB);
  4307. if (hwndText)
  4308. {
  4309. SetWindowText(hwndText, strUSBInfo);
  4310. ShowWindow(hwndText, SW_SHOW);
  4311. }
  4312. }
  4313. //
  4314. // If we are admining a remote server, we'll change the title and text.
  4315. // And we need to check the priviledge to add printer on remote server.
  4316. //
  4317. if( bIsRemote( _pWizard->pszServerName() ) )
  4318. {
  4319. //
  4320. // Remove "\\" from the server name, and change the server name
  4321. // to lower case
  4322. //
  4323. lstrcpy( szServerName, (LPTSTR)_pWizard->pszServerName() + 2 );
  4324. CharLower( szServerName );
  4325. //
  4326. // Change "Add Printer Wizard" to "Add Printer Wizard on '%s.'"
  4327. //
  4328. strTemp.bLoadString( ghInst, IDS_ADD_PRINTER_TITLE_REMOTE );
  4329. _pWizard->_strTitle.bFormat( strTemp, szServerName );
  4330. PropSheet_SetTitle( GetParent( _hDlg ), 0, _pWizard->_strTitle );
  4331. //
  4332. // change the text for intro and desc to fit remote APW
  4333. //
  4334. strTemp.bLoadString( ghInst, IDS_ADD_PRINTER_INTRO_REMOTE );
  4335. strTemp.bFormat( strTemp, szServerName );
  4336. bSetEditText( _hDlg, IDC_MAIN_TITLE, strTemp );
  4337. strTemp.bLoadString( ghInst, IDS_ADD_PRINTER_DESC_REMOTE );
  4338. bSetEditText( _hDlg, IDC_ADD_PRINTER_DESC, strTemp );
  4339. //
  4340. // we don't want the user to add network connections, since that's per-user.
  4341. // then we go directly to the port page
  4342. //
  4343. _pWizard->_bNet = FALSE;
  4344. _pWizard->_bPnPAutodetect = FALSE;
  4345. _pWizard->_bRunDetection = _pWizard->_bPnPAutodetect;
  4346. }
  4347. //
  4348. // Let the wizard to initialize itself.
  4349. //
  4350. _pWizard->OnWizardInitro( hDlg() );
  4351. return TRUE;
  4352. }
  4353. /********************************************************************
  4354. Finish
  4355. ********************************************************************/
  4356. TWizFinish::
  4357. TWizFinish(
  4358. TWizard *pWizard
  4359. ) : MWizardProp( pWizard )
  4360. {
  4361. }
  4362. BOOL
  4363. TWizFinish::
  4364. bHandle_InitDialog(
  4365. VOID
  4366. )
  4367. {
  4368. BOOL bReturn = TRUE;
  4369. //
  4370. // check to see if the wizard is restartable and if so
  4371. // show the appropriate checkbox
  4372. //
  4373. if( _pWizard->bRestartableFromLastPage() )
  4374. {
  4375. _pWizard->bRestartAgain() = TRUE; // assume "On" by default
  4376. ShowWindow( GetDlgItem( _hDlg, IDC_RESTART_WIZARD ), SW_SHOW );
  4377. }
  4378. vSetCheck( _hDlg, IDC_RESTART_WIZARD, _pWizard->bRestartAgain() );
  4379. //
  4380. // Set the commpletion text to what the title is in the pnp install case.
  4381. //
  4382. if( _pWizard->uAction() == TWizard::kPnPInstall )
  4383. {
  4384. TCHAR szBuffer [MAX_PATH] = {0};
  4385. GetWindowText( GetParent( _hDlg ), szBuffer, COUNTOF( szBuffer ) );
  4386. if( *szBuffer )
  4387. {
  4388. TStatusB bStatus;
  4389. TString strCompletionText;
  4390. bStatus DBGCHK = strCompletionText.bLoadString( ghInst, IDS_COMPLETING_TEXT );
  4391. bStatus DBGCHK = strCompletionText.bFormat( strCompletionText, szBuffer );
  4392. bStatus DBGCHK = bSetEditText( _hDlg, IDC_MAIN_TITLE, strCompletionText );
  4393. }
  4394. }
  4395. //
  4396. // The fonts for the Word 97 wizard style.
  4397. //
  4398. SetControlFont( _pWizard->_hBigBoldFont, _hDlg, IDC_MAIN_TITLE );
  4399. if( _pWizard->_bConnected || _pWizard->_bPrinterAutoDetected )
  4400. {
  4401. //
  4402. // Set cancel to close, since the printer connection can't
  4403. // be undone at this point. (We could try just deleting the
  4404. // connection, but this doesn't undo the driver downloads, etc.
  4405. //
  4406. PropSheet_CancelToClose( GetParent( _hDlg ) );
  4407. }
  4408. if( _pWizard->_bPrinterAutoDetected )
  4409. {
  4410. //
  4411. // If the printer has been autodetected at this point we don't
  4412. // know anything but the printer name. Get all the rest of the
  4413. // information for the finish page here.
  4414. //
  4415. DWORD dwAccess = PRINTER_READ;
  4416. TStatus Status;
  4417. HANDLE hPrinter;
  4418. //
  4419. // Open the printer
  4420. //
  4421. Status DBGCHK = TPrinter::sOpenPrinter( _pWizard->strPrinterName(), &dwAccess, &hPrinter );
  4422. if( Status == ERROR_SUCCESS )
  4423. {
  4424. TStatusB bStatus;
  4425. //
  4426. // Get PRINTER_INFO_2 for the autodetected printer. This call
  4427. // should be rather quick as hPrinter is a local printer.
  4428. //
  4429. PPRINTER_INFO_2 pInfo2 = NULL;
  4430. DWORD cbInfo2 = 0;
  4431. bStatus DBGCHK = VDataRefresh::bGetPrinter( hPrinter,
  4432. 2,
  4433. (PVOID*)&pInfo2,
  4434. &cbInfo2 );
  4435. if( bStatus )
  4436. {
  4437. _pWizard->_strPortName.bUpdate( pInfo2->pPortName );
  4438. _pWizard->_strDriverName.bUpdate( pInfo2->pDriverName );
  4439. _pWizard->_strShareName.bUpdate( pInfo2->pShareName );
  4440. _pWizard->_strLocation.bUpdate( pInfo2->pLocation );
  4441. _pWizard->_strComment.bUpdate( pInfo2->pComment );
  4442. //
  4443. // Check default printer
  4444. //
  4445. _pWizard->_bSetDefault = (kDefault == CheckDefaultPrinter(_pWizard->strPrinterName()));
  4446. }
  4447. //
  4448. // Release the printer info 2 structure and close
  4449. // the printer handle.
  4450. //
  4451. FreeMem( pInfo2 );
  4452. ClosePrinter( hPrinter );
  4453. bReturn = bStatus;
  4454. }
  4455. else
  4456. {
  4457. bReturn = FALSE;
  4458. }
  4459. }
  4460. return TRUE;
  4461. }
  4462. BOOL
  4463. TWizFinish::
  4464. bHandle_SetActive(
  4465. VOID
  4466. )
  4467. {
  4468. if( _pWizard->_bConnected && !_pWizard->_bIsPrinterFolderEmpty )
  4469. {
  4470. PropSheet_SetWizButtons( GetParent( _hDlg ), PSWIZB_FINISH );
  4471. }
  4472. else
  4473. {
  4474. PropSheet_SetWizButtons( GetParent( _hDlg ), PSWIZB_BACK | PSWIZB_FINISH );
  4475. }
  4476. TStatusB bStatus;
  4477. TString strShareName;
  4478. TString strConShareName;
  4479. TString strAsDefault;
  4480. TString strPrintTestPage;
  4481. bStatus DBGCHK = _pWizard->_bShared ? strShareName.bUpdate( _pWizard->_strShareName ) : strShareName.bLoadString( ghInst, IDS_NOT_SHARED );
  4482. bStatus DBGCHK = _pWizard->_bSetDefault ? strAsDefault.bLoadString( ghInst, IDS_YES ) : strAsDefault.bLoadString( ghInst, IDS_NO );
  4483. bStatus DBGCHK = _pWizard->_bTestPage ? strPrintTestPage.bLoadString( ghInst, IDS_YES ) : strPrintTestPage.bLoadString( ghInst, IDS_NO );
  4484. BOOL bShared = _pWizard->_bConnected ? FALSE : !_pWizard->_bShared;
  4485. LPCTSTR pszServer;
  4486. LPCTSTR pszPrinter;
  4487. TCHAR szScratch[kStrMax+kPrinterBufMax];
  4488. TString strPrinterFriendlyName;
  4489. UINT nSize = COUNTOF( szScratch );
  4490. //
  4491. // Split the printer name into its components.
  4492. //
  4493. vPrinterSplitFullName( szScratch, _pWizard->_strPrinterName, &pszServer, &pszPrinter );
  4494. //
  4495. // If share name is empty then indicate the printer is not shared.
  4496. //
  4497. if( _pWizard->_strShareName.bEmpty() )
  4498. {
  4499. strConShareName.bLoadString( ghInst, IDS_NOT_SHARED );
  4500. }
  4501. else
  4502. {
  4503. bBuildFullPrinterName( pszServer, _pWizard->_strShareName, strConShareName );
  4504. }
  4505. if( _pWizard->_bConnected )
  4506. {
  4507. //
  4508. // Create the formatted printer friendly name, when adding connections
  4509. // or the masq printer.
  4510. //
  4511. ConstructPrinterFriendlyName( (LPCTSTR)_pWizard->_strPrinterName, szScratch, &nSize );
  4512. strPrinterFriendlyName.bUpdate( szScratch );
  4513. }
  4514. struct TextInfo
  4515. {
  4516. BOOL bType;
  4517. UINT Id;
  4518. LPCTSTR pszText;
  4519. };
  4520. TextInfo aText [] = {
  4521. { FALSE, IDC_PORT_NAME_TEXT, NULL },
  4522. { FALSE, IDC_PORT_NAME_SUMMARY, _pWizard->_strPortName },
  4523. { FALSE, IDC_SET_AS_DEFAULT_TEXT, NULL },
  4524. { FALSE, IDC_SET_AS_DEFAULT_SUMMARY, strAsDefault },
  4525. { FALSE, IDC_PRINTER_NAME_TEXT, NULL },
  4526. { FALSE, IDC_PRINTER_NAME_SUMMARY, _pWizard->_strPrinterName },
  4527. { FALSE, IDC_MODEL_NAME_TEXT, NULL },
  4528. { FALSE, IDC_MODEL_NAME_SUMMARY, _pWizard->_strDriverName },
  4529. { FALSE, IDC_SHARE_NAME_TEXT, NULL },
  4530. { FALSE, IDC_SHARE_NAME_SUMMARY, strShareName },
  4531. { FALSE, IDC_PRINT_TEST_PAGE_TEXT, NULL },
  4532. { FALSE, IDC_PRINT_TEST_PAGE_SUMMARY, strPrintTestPage },
  4533. { bShared, IDC_LOCATION_TEXT, NULL },
  4534. { bShared, IDC_LOCATION_SUMMARY, _pWizard->_strLocation },
  4535. { bShared, IDC_COMMENT_TEXT, NULL },
  4536. { bShared, IDC_COMMENT_SUMMARY, _pWizard->_strComment },
  4537. { FALSE, IDC_COMPLETION_TEXT, NULL },
  4538. { FALSE, IDC_CLICK_TO_ADD_TEXT, NULL },
  4539. { TRUE, IDC_CONNECTION_TEXT, NULL },
  4540. { TRUE, IDC_CONNECTION_SUMMARY, strPrinterFriendlyName },
  4541. { TRUE, IDC_CON_COMMENT_TEXT, NULL },
  4542. { TRUE, IDC_CON_COMMENT_SUMMARY, _pWizard->_strComment },
  4543. { TRUE, IDC_CON_LOCATION_TEXT, NULL },
  4544. { TRUE, IDC_CON_LOCATION_SUMMARY, _pWizard->_strLocation },
  4545. { TRUE, IDC_CON_SET_DEFAULT_TEXT, NULL },
  4546. { TRUE, IDC_CON_SET_DEFAULT_SUMMARY, strAsDefault },
  4547. { TRUE, IDC_CON_COMPLETION_TEXT, NULL },
  4548. { TRUE, IDC_CON_CLICK_TO_ADD_TEXT, NULL }};
  4549. //
  4550. // Hide or show the controls, whether we have connection or local printer install.
  4551. //
  4552. for( UINT i = 0; i < COUNTOF( aText ); i++ )
  4553. {
  4554. if( _pWizard->_bConnected )
  4555. {
  4556. ShowWindow( GetDlgItem( _hDlg, aText[i].Id ), aText[i].bType ? SW_NORMAL : SW_HIDE );
  4557. }
  4558. else
  4559. {
  4560. ShowWindow( GetDlgItem( _hDlg, aText[i].Id ), aText[i].bType ? SW_HIDE : SW_NORMAL );
  4561. }
  4562. if( aText[i].pszText )
  4563. {
  4564. bStatus DBGCHK = bSetEditText( _hDlg, aText[i].Id, aText[i].pszText );
  4565. }
  4566. }
  4567. return TRUE;
  4568. }
  4569. BOOL
  4570. TWizFinish::
  4571. bHandle_WizFinish(
  4572. VOID
  4573. )
  4574. {
  4575. BOOL bCloseOnError =(_pWizard->_bConnected || _pWizard->_bPrinterAutoDetected);
  4576. _pWizard->bRestartAgain() = bGetCheck( _hDlg, IDC_RESTART_WIZARD );
  4577. if( !_pWizard->_bPrinterAutoDetected )
  4578. {
  4579. //
  4580. // If an error occurred saving a setting
  4581. //
  4582. if( _pWizard->bErrorSaving() )
  4583. {
  4584. iMessage( _hDlg,
  4585. IDS_ERR_ADD_PRINTER_TITLE,
  4586. IDS_ERR_ERROR_SAVING,
  4587. MB_OK|MB_ICONSTOP,
  4588. kMsgNone,
  4589. NULL );
  4590. //
  4591. // Policy question, is it correct to prevent switching
  4592. // or closing the wizard if an error occurred saving.
  4593. //
  4594. _pWizard->bNoPageChange() = !bCloseOnError;
  4595. }
  4596. else
  4597. {
  4598. //
  4599. // If we are not doing a network install, install the printer
  4600. // and print a test page.
  4601. //
  4602. if( !_pWizard->bNet( ) )
  4603. {
  4604. //
  4605. // Create the printer.
  4606. //
  4607. _pWizard->bPrinterCreated() = _pWizard->bCreatePrinter( _hDlg );
  4608. //
  4609. // If the printer failed creation, keep the wizard up and
  4610. // stay on this page.
  4611. //
  4612. if( !_pWizard->bPrinterCreated() )
  4613. {
  4614. //
  4615. // Something failed stay on this page.
  4616. //
  4617. _pWizard->bNoPageChange() = !bCloseOnError;
  4618. }
  4619. else
  4620. {
  4621. if( _pWizard->_bTestPage )
  4622. {
  4623. //
  4624. // Print this printers test page.
  4625. //
  4626. _pWizard->bPrintTestPage();
  4627. }
  4628. }
  4629. }
  4630. }
  4631. //
  4632. // If a printer was created or connected to
  4633. // and the set as default was requested and
  4634. // we are not adding a printer remotely
  4635. //
  4636. if( ( _pWizard->bPrinterCreated() || _pWizard->bConnected() ) &&
  4637. _pWizard->bSetDefault() && !_pWizard->pszServerName() )
  4638. {
  4639. //
  4640. // Set the default printer.
  4641. //
  4642. if( !SetDefaultPrinter( _pWizard->strPrinterName() )){
  4643. iMessage( _hDlg,
  4644. IDS_ERR_ADD_PRINTER_TITLE,
  4645. IDS_ERR_SET_DEFAULT_PRINTER,
  4646. MB_OK|MB_ICONHAND,
  4647. kMsgNone,
  4648. NULL );
  4649. _pWizard->bNoPageChange() = !bCloseOnError;
  4650. }
  4651. }
  4652. }
  4653. else
  4654. {
  4655. //
  4656. // Only print the test page if necessary
  4657. //
  4658. if( _pWizard->_bTestPage )
  4659. {
  4660. //
  4661. // Print this printers test page.
  4662. //
  4663. _pWizard->bPrintTestPage();
  4664. }
  4665. }
  4666. //
  4667. // Let the wizard cleanup here.
  4668. //
  4669. _pWizard->OnWizardFinish( _hDlg );
  4670. return TRUE;
  4671. }
  4672. /********************************************************************
  4673. Type of printer: local or network.
  4674. ********************************************************************/
  4675. TWizType::
  4676. TWizType(
  4677. TWizard* pWizard
  4678. ) : MWizardProp( pWizard )
  4679. {
  4680. }
  4681. BOOL
  4682. TWizType::
  4683. bHandle_InitDialog(
  4684. VOID
  4685. )
  4686. {
  4687. TStatusB bStatus;
  4688. //
  4689. // Set the default control id.
  4690. //
  4691. INT idcDefault = _pWizard->_bNet ? IDC_NET : IDC_LOCAL;
  4692. if (FALSE == _pWizard->_bAdminPrivilege)
  4693. {
  4694. idcDefault = IDC_NET;
  4695. vEnableCtl(_hDlg, IDC_LOCAL, FALSE);
  4696. vEnableCtl(_hDlg, IDC_KICKOFF_PNP_REFRESH, FALSE);
  4697. }
  4698. //
  4699. // Initialize the default value from the sticky settings
  4700. //
  4701. vSetCheck( _hDlg, IDC_KICKOFF_PNP_REFRESH, _pWizard->_bPnPAutodetect );
  4702. //
  4703. // If the network is not loaded then do not show the net selection.
  4704. //
  4705. if( !_pWizard->bNetworkInstalled() )
  4706. {
  4707. idcDefault = IDC_LOCAL;
  4708. ShowWindow( GetDlgItem( _hDlg, IDC_NET ), SW_HIDE );
  4709. }
  4710. HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_INFORMATION));
  4711. if (hIcon)
  4712. {
  4713. HWND hwndIcon = GetDlgItem(_hDlg, IDC_ICON_INFO);
  4714. if (hwndIcon)
  4715. {
  4716. SendMessage(hwndIcon, STM_SETICON, (WPARAM )hIcon, 0L);
  4717. ShowWindow(hwndIcon, SW_SHOW);
  4718. }
  4719. }
  4720. //
  4721. // Set the default button.
  4722. //
  4723. bStatus DBGCHK = CheckRadioButton( _hDlg, IDC_LOCAL, IDC_NET, idcDefault );
  4724. //
  4725. // Initially enable/disable the PnP refresh checkbox
  4726. // regardless of the fact if it is visible or not
  4727. //
  4728. vEnableCtl( _hDlg, IDC_KICKOFF_PNP_REFRESH,
  4729. NULL == _pWizard->pszServerName( ) && // Not in the remote case
  4730. _pWizard->_bAdminPrivilege && // Have admin privileges
  4731. IDC_LOCAL == idcDefault ); // We are in the local case
  4732. return bStatus;
  4733. }
  4734. BOOL
  4735. TWizType::
  4736. bHandle_SetActive(
  4737. VOID
  4738. )
  4739. {
  4740. vSetCheck( _hDlg, IDC_KICKOFF_PNP_REFRESH, _pWizard->_bPnPAutodetect );
  4741. return TRUE;
  4742. }
  4743. VOID
  4744. TWizType::
  4745. vReadUI(
  4746. VOID
  4747. )
  4748. /*++
  4749. Routine Description:
  4750. Save the state the user has set in the UI elements into _pWizard.
  4751. Arguments:
  4752. Return Value:
  4753. --*/
  4754. {
  4755. _pWizard->_bNet = ( IsDlgButtonChecked( _hDlg, IDC_NET ) == BST_CHECKED );
  4756. _pWizard->_bPnPAutodetect = bGetCheck( _hDlg, IDC_KICKOFF_PNP_REFRESH );
  4757. _pWizard->_bRunDetection = _pWizard->_bPnPAutodetect;
  4758. }
  4759. BOOL
  4760. TWizType::
  4761. bConnectToPrinter(
  4762. IN HWND hDlg,
  4763. IN TString &strPrinterName,
  4764. IN TString *pstrComment,
  4765. IN TString *pstrLocation,
  4766. IN TString *pstrShareName
  4767. )
  4768. /*++
  4769. Routine Description:
  4770. Browse and connect to a printer.
  4771. Arguments:
  4772. Return Value:
  4773. Notes:
  4774. This is a static function, other wizard pages
  4775. use this funtion to invoke the printer browser.
  4776. --*/
  4777. {
  4778. TStatusB bStatus;
  4779. bStatus DBGNOCHK = FALSE;
  4780. //
  4781. // Call the ConnectToPrinterDlg to browse for a printer.
  4782. //
  4783. HANDLE hPrinter = ConnectToPrinterDlg( hDlg, 0 );
  4784. if( hPrinter )
  4785. {
  4786. //
  4787. // Get the printer name from the handle so we can
  4788. // pass it back to the user.
  4789. //
  4790. PPRINTER_INFO_2 pInfo2 = NULL;
  4791. DWORD cbInfo2 = 0;
  4792. bStatus DBGCHK = VDataRefresh::bGetPrinter( hPrinter,
  4793. 2,
  4794. (PVOID*)&pInfo2,
  4795. &cbInfo2 );
  4796. //
  4797. // Printer connection made copy back the new printer name.
  4798. //
  4799. if( bStatus )
  4800. {
  4801. bStatus DBGCHK = strPrinterName.bUpdate( pInfo2->pPrinterName );
  4802. if( pstrLocation )
  4803. pstrLocation->bUpdate( pInfo2->pLocation );
  4804. if( pstrComment )
  4805. pstrComment->bUpdate( pInfo2->pComment );
  4806. if( pstrShareName )
  4807. pstrShareName->bUpdate( pInfo2->pShareName );
  4808. }
  4809. //
  4810. // If the printer name could not be found don't indicate
  4811. // a failure and fail to switch pages.
  4812. //
  4813. bStatus DBGNOCHK = TRUE;
  4814. FreeMem( pInfo2 );
  4815. ClosePrinter( hPrinter );
  4816. }
  4817. return bStatus;
  4818. }
  4819. BOOL
  4820. TWizType::
  4821. bHandle_WizNext(
  4822. VOID
  4823. )
  4824. {
  4825. TStatusB bStatus;
  4826. //
  4827. // Read the information from the UI controls.
  4828. //
  4829. vReadUI();
  4830. //
  4831. // If we are not in the remote case and the user is
  4832. // attempting to install printer locally and the PnP
  4833. // is selcted then kick off the PnP enumeration event
  4834. //
  4835. if( !_pWizard->_bNet &&
  4836. bGetCheck( _hDlg, IDC_KICKOFF_PNP_REFRESH ) )
  4837. {
  4838. //
  4839. // Autodetection has been slected. Kick off the
  4840. // PnP enumeration here before going to the next page
  4841. //
  4842. }
  4843. //
  4844. // We are advancing to the next page. For network installs,
  4845. // and the DS is installed then jump to the locate / browse page.
  4846. //
  4847. if( _pWizard->bNet( ) )
  4848. {
  4849. //
  4850. // Check if the Directory Service is installed and available.
  4851. //
  4852. if( _pWizard->_eIsDsAvailablePerUser == TWizard::kDsStatusUnknown )
  4853. {
  4854. TWaitCursor Cur;
  4855. _pWizard->_eIsDsAvailablePerUser = _pWizard->_Ds.bIsDsAvailable() ? TWizard::kDsStatusAvailable : TWizard::kDsStatusUnavailable;
  4856. }
  4857. }
  4858. return TRUE;
  4859. }
  4860. BOOL
  4861. TWizType::
  4862. bHandle_Command(
  4863. IN WORD wId,
  4864. IN WORD wNotifyId,
  4865. IN HWND hwnd
  4866. )
  4867. {
  4868. BOOL bStatus = (NULL == _pWizard->pszServerName( ));
  4869. if( bStatus )
  4870. {
  4871. switch( wId )
  4872. {
  4873. case IDC_LOCAL:
  4874. case IDC_NET:
  4875. {
  4876. //
  4877. // Check to enable/disable PnP refresh if "Network"
  4878. // printer is selected
  4879. //
  4880. EnableWindow( GetDlgItem( _hDlg, IDC_KICKOFF_PNP_REFRESH ), wId == IDC_LOCAL );
  4881. }
  4882. break;
  4883. default:
  4884. bStatus = FALSE;
  4885. break;
  4886. }
  4887. }
  4888. return bStatus;
  4889. }
  4890. /********************************************************************
  4891. Auto detect: show the autodetection progress
  4892. ********************************************************************/
  4893. TWizDetect::
  4894. TWizDetect(
  4895. TWizard* pWizard
  4896. ): MWizardProp( pWizard )
  4897. {
  4898. }
  4899. VOID
  4900. TWizDetect::
  4901. vReadUI(
  4902. VOID
  4903. )
  4904. {
  4905. if( _pWizard->_bPrinterAutoDetected )
  4906. {
  4907. //
  4908. // Read the test page setting from the ui.
  4909. //
  4910. if( IsDlgButtonChecked( _hDlg, IDC_RADIO_YES ) == BST_CHECKED )
  4911. {
  4912. _pWizard->_bTestPage = TRUE;
  4913. }
  4914. else
  4915. {
  4916. _pWizard->_bTestPage = FALSE;
  4917. }
  4918. }
  4919. }
  4920. BOOL
  4921. TWizDetect::
  4922. bHandle_InitDialog(
  4923. VOID
  4924. )
  4925. {
  4926. TStatusB bStatus;
  4927. //
  4928. // Set the test page setting and hide the controls.
  4929. //
  4930. INT iValueId = _pWizard->bTestPage() ? IDC_RADIO_YES : IDC_RADIO_NO;
  4931. bStatus DBGCHK = CheckRadioButton( _hDlg, IDC_RADIO_YES, IDC_RADIO_NO, iValueId );
  4932. vToggleTestPageControls( SW_HIDE );
  4933. //
  4934. // Load the animation
  4935. //
  4936. HWND hwndAnimation = GetDlgItem( _hDlg, IDC_DETECT_ANIMATE );
  4937. Animate_Open( hwndAnimation, MAKEINTRESOURCE( IDA_INSPECT ) );
  4938. return TRUE;
  4939. }
  4940. BOOL
  4941. TWizDetect::
  4942. bHandle_SetActive(
  4943. VOID
  4944. )
  4945. {
  4946. if( _pWizard->_bPrinterAutoDetected )
  4947. {
  4948. //
  4949. // The printer has been autodetected and installed already.
  4950. // Enable only Next button
  4951. //
  4952. PropSheet_SetWizButtons( GetParent( _hDlg ), PSWIZB_NEXT );
  4953. }
  4954. else
  4955. {
  4956. if( _pWizard->_bRunDetection && !pnpPrinterDetector().bDetectionInProgress( ) )
  4957. {
  4958. TStatusB bStatus;
  4959. //
  4960. // Show the wait cursor
  4961. //
  4962. TWaitCursor wait;
  4963. //
  4964. // Show/Hide some controls appropriately
  4965. //
  4966. ShowWindow( GetDlgItem( _hDlg, IDC_ICON_DETECT_PRINTER ), SW_HIDE );
  4967. ShowWindow( GetDlgItem( _hDlg, IDC_DETECT_STATUS ), SW_HIDE );
  4968. ShowWindow( GetDlgItem( _hDlg, IDC_TEXT_DETECT_INFO ), SW_SHOW );
  4969. //
  4970. // Disable Back & Next wizard buttons
  4971. //
  4972. PropSheet_SetWizButtons( GetParent( _hDlg ), 0 );
  4973. //
  4974. // Kick off the PnP enumeration event
  4975. //
  4976. bStatus DBGCHK = pnpPrinterDetector().bKickOffPnPEnumeration();
  4977. if( bStatus )
  4978. {
  4979. //
  4980. // Stop the animation
  4981. //
  4982. vStartAnimation( );
  4983. //
  4984. // Setup the polling timer to hit on each POLLING_TIMER_INTERVAL
  4985. //
  4986. SetTimer( _hDlg, POLLING_TIMER_ID, POLLING_TIMER_INTERVAL, NULL );
  4987. }
  4988. else
  4989. {
  4990. //
  4991. // PnP enumeration failed. We need to handle this case properly.
  4992. // This actually shouldn't never happen, but if it happens somehow
  4993. // we don't want to mess up the UI.
  4994. //
  4995. LPCTSTR pszIconName = NULL;
  4996. TString strStatus;
  4997. //
  4998. // Revert the buttons in case of failure
  4999. //
  5000. PropSheet_SetWizButtons( GetParent( _hDlg ), PSWIZB_BACK | PSWIZB_NEXT );
  5001. bStatus DBGCHK = strStatus.bLoadString( ghInst, IDS_TEXT_DETECT_FAILURE );
  5002. pszIconName = MAKEINTRESOURCE( IDI_WARNING );
  5003. //
  5004. // Don't run the detection process any more until
  5005. // the user goes to the prev page (TWizType).
  5006. //
  5007. _pWizard->_bRunDetection = FALSE;
  5008. //
  5009. // Show/Hide some controls appropriately
  5010. //
  5011. ShowWindow( GetDlgItem( _hDlg, IDC_TEXT_DETECT_INFO ), SW_HIDE );
  5012. ShowWindow( GetDlgItem( _hDlg, IDC_DETECT_STATUS ), SW_SHOW );
  5013. //
  5014. // Check to load and show the approprate icon.
  5015. //
  5016. if( pszIconName )
  5017. {
  5018. HICON hIcon = LoadIcon( NULL, pszIconName );
  5019. if( hIcon )
  5020. {
  5021. HWND hwndIcon = GetDlgItem( _hDlg, IDC_ICON_DETECT_PRINTER );
  5022. SendMessage( hwndIcon, STM_SETICON, (WPARAM )hIcon, 0L );
  5023. ShowWindow( hwndIcon, SW_SHOW );
  5024. }
  5025. }
  5026. //
  5027. // Show the failed status text.
  5028. //
  5029. bStatus DBGCHK = SetWindowText( GetDlgItem( _hDlg, IDC_DETECT_STATUS ), strStatus );
  5030. }
  5031. }
  5032. }
  5033. return TRUE;
  5034. }
  5035. BOOL
  5036. TWizDetect::
  5037. bHandle_WizNext(
  5038. VOID
  5039. )
  5040. {
  5041. vReadUI();
  5042. return TRUE;
  5043. }
  5044. BOOL
  5045. TWizDetect::
  5046. bHandle_Cancel(
  5047. VOID
  5048. )
  5049. {
  5050. TStatusB bStatus;
  5051. //
  5052. // Stop the animation & kill the polling timer.
  5053. //
  5054. vStartAnimation( FALSE );
  5055. bStatus DBGCHK = KillTimer( _hDlg, POLLING_TIMER_ID );
  5056. return TRUE;
  5057. }
  5058. BOOL
  5059. TWizDetect::
  5060. bHandle_Timer(
  5061. IN WPARAM wIdTimer,
  5062. IN TIMERPROC *tmProc
  5063. )
  5064. {
  5065. TStatusB bStatus;
  5066. TString strStatus, strPrinterName;
  5067. bStatus DBGNOCHK = FALSE;
  5068. BOOL bResult = FALSE;
  5069. if( POLLING_TIMER_ID == wIdTimer )
  5070. {
  5071. //
  5072. // If PnP printer detection process is in progress ...
  5073. //
  5074. if( pnpPrinterDetector().bDetectionInProgress( ) )
  5075. {
  5076. //
  5077. // Ping the PnP detection/installation process to see whether
  5078. // it has finished?
  5079. //
  5080. if( pnpPrinterDetector().bFinished( ) )
  5081. {
  5082. LPCTSTR pszIconName = NULL;
  5083. //
  5084. // Show wait cursor because the following operation below might
  5085. // take some time.
  5086. //
  5087. TWaitCursor wait;
  5088. //
  5089. // Check whether the detection/installation is successful or not.
  5090. //
  5091. if( pnpPrinterDetector().bGetDetectedPrinterName( &strPrinterName ) )
  5092. {
  5093. //
  5094. // The detect/install process was successful.
  5095. //
  5096. _pWizard->_bPrinterAutoDetected = TRUE;
  5097. bStatus DBGCHK = strStatus.bLoadString( ghInst, IDS_TEXT_DETECT_SUCCESS );
  5098. pszIconName = MAKEINTRESOURCE( IDI_INFORMATION );
  5099. //
  5100. // The printer is installed here, so there is no point Back and
  5101. // Cancel buttons.
  5102. //
  5103. PropSheet_SetWizButtons( GetParent( _hDlg ), PSWIZB_NEXT );
  5104. PropSheet_CancelToClose( GetParent( _hDlg ) );
  5105. //
  5106. // Show the test page controls
  5107. //
  5108. vToggleTestPageControls( SW_SHOW );
  5109. //
  5110. // Select the first control with WS_TABSTOP style
  5111. SendMessage( _hDlg, WM_NEXTDLGCTL, 0, (LPARAM )FALSE );
  5112. //
  5113. // Here must setup all the parameters configured from PnP
  5114. // before jump to the finish page. Done forget to disable
  5115. // Back and Cancel buttons.
  5116. //
  5117. bStatus DBGCHK = _pWizard->_strPrinterName.bUpdate( strPrinterName );
  5118. }
  5119. else
  5120. {
  5121. //
  5122. // The detect/install process *was not* successful.
  5123. //
  5124. bStatus DBGCHK = strStatus.bLoadString( ghInst, IDS_TEXT_DETECT_FAILURE );
  5125. pszIconName = MAKEINTRESOURCE( IDI_WARNING );
  5126. PropSheet_SetWizButtons( GetParent( _hDlg ), PSWIZB_BACK | PSWIZB_NEXT );
  5127. }
  5128. //
  5129. // Don't run the detection process any more until
  5130. // the user goes to the prev (type) page.
  5131. //
  5132. _pWizard->_bRunDetection = FALSE;
  5133. //
  5134. // Show/Hide some controls appropriately
  5135. //
  5136. ShowWindow( GetDlgItem( _hDlg, IDC_TEXT_DETECT_INFO ), SW_HIDE );
  5137. ShowWindow( GetDlgItem( _hDlg, IDC_DETECT_STATUS ), SW_SHOW );
  5138. //
  5139. // Check to load and show the approprate icon.
  5140. //
  5141. if( pszIconName )
  5142. {
  5143. HICON hIcon = LoadIcon( NULL, pszIconName );
  5144. if( hIcon )
  5145. {
  5146. HWND hwndIcon = GetDlgItem( _hDlg, IDC_ICON_DETECT_PRINTER );
  5147. SendMessage( hwndIcon, STM_SETICON, (WPARAM )hIcon, 0L );
  5148. ShowWindow( hwndIcon, SW_SHOW );
  5149. }
  5150. }
  5151. //
  5152. // Kill the timer and show the status text.
  5153. //
  5154. bStatus DBGCHK = KillTimer( _hDlg, POLLING_TIMER_ID );
  5155. bStatus DBGCHK = SetWindowText( GetDlgItem( _hDlg, IDC_DETECT_STATUS ), strStatus );
  5156. //
  5157. // Stop the animation
  5158. //
  5159. vStartAnimation( FALSE );
  5160. }
  5161. }
  5162. // Message is processed
  5163. bResult = TRUE;
  5164. }
  5165. return bResult;
  5166. }
  5167. VOID
  5168. TWizDetect::
  5169. vToggleTestPageControls(
  5170. int nCmdShow
  5171. )
  5172. /*++
  5173. Routine Description:
  5174. Toggles the visibility state of the test
  5175. page controls.
  5176. Arguments:
  5177. nCmdShow - Whether to show or hide the controls.
  5178. Return Value:
  5179. None.
  5180. --*/
  5181. {
  5182. static DWORD arrTestPageControls[] =
  5183. {
  5184. IDC_TEST_PAGE_QUESTION,
  5185. IDC_RADIO_YES,
  5186. IDC_RADIO_NO
  5187. };
  5188. for( UINT i = 0; i < COUNTOF( arrTestPageControls ); ++i )
  5189. {
  5190. ShowWindow( GetDlgItem( _hDlg, arrTestPageControls[i] ), nCmdShow );
  5191. }
  5192. }
  5193. VOID
  5194. TWizDetect::
  5195. vStartAnimation(
  5196. BOOL bStart
  5197. )
  5198. /*++
  5199. Routine Description:
  5200. Toggles the animation control between
  5201. show and play/hide and stop play mode
  5202. Arguments:
  5203. bStart - Start or stop the animation.
  5204. Return Value:
  5205. None.
  5206. --*/
  5207. {
  5208. HWND hwndAnimation = GetDlgItem( _hDlg, IDC_DETECT_ANIMATE );
  5209. ShowWindow( hwndAnimation, bStart ? SW_SHOW : SW_HIDE );
  5210. if( bStart )
  5211. {
  5212. //
  5213. // Request to start the animation
  5214. //
  5215. Animate_Play( hwndAnimation, 0, -1, -1 );
  5216. }
  5217. else
  5218. {
  5219. //
  5220. // Request to stop the animation
  5221. //
  5222. Animate_Stop( hwndAnimation );
  5223. }
  5224. }
  5225. /********************************************************************
  5226. Driver Exists dialog.
  5227. ********************************************************************/
  5228. TWizDriverExists::
  5229. TWizDriverExists(
  5230. TWizard* pWizard
  5231. ) : MWizardProp( pWizard )
  5232. {
  5233. }
  5234. BOOL
  5235. TWizDriverExists::
  5236. bHandle_InitDialog(
  5237. VOID
  5238. )
  5239. {
  5240. TStatusB bStatus;
  5241. //
  5242. // Determine what the default setting to use.
  5243. //
  5244. INT iValueId = _pWizard->bUseNewDriverSticky() ? IDC_DRIVEREXISTS_USE_NEW : IDC_DRIVEREXISTS_KEEP_OLD;
  5245. //
  5246. // By default, use existing driver.
  5247. //
  5248. bStatus DBGCHK = CheckRadioButton( _hDlg,
  5249. IDC_DRIVEREXISTS_KEEP_OLD,
  5250. IDC_DRIVEREXISTS_USE_NEW,
  5251. iValueId );
  5252. //
  5253. // Set the page title.
  5254. //
  5255. if( _pWizard->uAction() == TWizard::kDriverInstall )
  5256. {
  5257. PropSheet_SetTitle( GetParent( _hDlg ), 0, IDS_DRIVER_WIZ_TITLE );
  5258. PropSheet_SetTitle( _hDlg, 0, IDS_DRIVER_WIZ_TITLE );
  5259. }
  5260. return bStatus;
  5261. }
  5262. VOID
  5263. TWizDriverExists::
  5264. vReadUI(
  5265. VOID
  5266. )
  5267. /*++
  5268. Routine Description:
  5269. Save the state the user has set in the UI elements into _pWizard.
  5270. Arguments:
  5271. Return Value:
  5272. --*/
  5273. {
  5274. _pWizard->bUseNewDriverSticky() = IsDlgButtonChecked( _hDlg, IDC_DRIVEREXISTS_USE_NEW ) == BST_CHECKED;
  5275. _pWizard->bUseNewDriver() = _pWizard->bUseNewDriverSticky();
  5276. }
  5277. BOOL
  5278. TWizDriverExists::
  5279. bHandle_SetActive(
  5280. VOID
  5281. )
  5282. {
  5283. //
  5284. // Set the driver name in the page.
  5285. //
  5286. bSetEditText( _hDlg, IDC_DRIVEREXISTS_TEXT, _pWizard->strDriverName() );
  5287. return TRUE;
  5288. }
  5289. BOOL
  5290. TWizDriverExists::
  5291. bHandle_WizNext(
  5292. VOID
  5293. )
  5294. {
  5295. vReadUI();
  5296. return TRUE;
  5297. }
  5298. /********************************************************************
  5299. Port selection.
  5300. ********************************************************************/
  5301. TWizPort::
  5302. TWizPort(
  5303. TWizard* pWizard
  5304. ) : MWizardProp( pWizard ),
  5305. _hMonitorList( NULL )
  5306. {
  5307. }
  5308. BOOL
  5309. TWizPort::
  5310. bValid(
  5311. VOID
  5312. )
  5313. {
  5314. return MGenericProp::bValid() && _PortsLV.bValid();
  5315. }
  5316. BOOL
  5317. TWizPort::
  5318. bHandle_InitDialog(
  5319. VOID
  5320. )
  5321. {
  5322. TStatusB bStatus;
  5323. //
  5324. // Initialize the monitor list.
  5325. //
  5326. if( !bInitializeMonitorList() )
  5327. {
  5328. DBGMSG( DBG_WARN, ( "bInitializeMonitorList failed %d\n", GetLastError( )));
  5329. vShowUnexpectedError( _pWizard->hwnd(), IDS_ERR_ADD_PRINTER_TITLE );
  5330. return FALSE;
  5331. }
  5332. //
  5333. // Initialize the ports list view. No user selcection and two column mode.
  5334. //
  5335. if( !_PortsLV.bSetUI( GetDlgItem( _hDlg, IDC_PORTS ), FALSE, FALSE, TRUE, _hDlg, IDC_PORT_DOUBLE_CLICKED ) )
  5336. {
  5337. DBGMSG( DBG_WARN, ( "PortsLV.bSetUI failed %d\n", GetLastError( )));
  5338. vShowUnexpectedError( _pWizard->hwnd(), IDS_ERR_ADD_PRINTER_TITLE );
  5339. return FALSE;
  5340. }
  5341. //
  5342. // Load ports into the view.
  5343. //
  5344. if( !_PortsLV.bReloadPorts( _pWizard->pszServerName( ) ))
  5345. {
  5346. DBGMSG( DBG_WARN, ( "PortsLV.bReloadPorts failed %d\n", GetLastError( )));
  5347. vShowUnexpectedError( _pWizard->hwnd(), IDS_ERR_ADD_PRINTER_TITLE );
  5348. return FALSE;
  5349. }
  5350. //
  5351. // Select the default port. Note the default port does not exist
  5352. // as a valid port then no port will be selected as the default.
  5353. //
  5354. bStatus DBGCHK = _pWizard->_strPortName.bLoadString( ghInst, IDS_DEFAULT_PORT );
  5355. //
  5356. // Check the existing port by default.
  5357. //
  5358. CheckRadioButton( _hDlg, IDC_PORT_OTHER, IDC_PORT_EXISTING, IDC_PORT_EXISTING );
  5359. //
  5360. // Do any of the port selection action.
  5361. //
  5362. PostMessage( _hDlg, WM_COMMAND, MAKELPARAM( IDC_PORT_EXISTING, 0 ), (LPARAM)GetDlgItem( _hDlg, IDC_PORT_EXISTING ) );
  5363. return TRUE;
  5364. }
  5365. BOOL
  5366. TWizPort::
  5367. bHandle_Notify(
  5368. IN WPARAM wParam,
  5369. IN LPNMHDR pnmh
  5370. )
  5371. {
  5372. return _PortsLV.bHandleNotifyMessage( (LPARAM)pnmh );
  5373. }
  5374. BOOL
  5375. TWizPort::
  5376. bHandle_WizNext(
  5377. VOID
  5378. )
  5379. {
  5380. if( IsDlgButtonChecked( _hDlg, IDC_PORT_EXISTING ) == BST_CHECKED )
  5381. {
  5382. vSelectionPort();
  5383. }
  5384. else
  5385. {
  5386. vSelectionMonitor();
  5387. }
  5388. return TRUE;
  5389. }
  5390. BOOL
  5391. TWizPort::
  5392. bHandle_SetActive(
  5393. VOID
  5394. )
  5395. {
  5396. //
  5397. // Select the default port.
  5398. //
  5399. _PortsLV.vSelectPort( _pWizard->_strPortName );
  5400. //
  5401. // If the port monitor is the select radio button,
  5402. // then ensure the list view is disable, problem
  5403. // is vSelectPort sets the selection state.
  5404. //
  5405. if( IsDlgButtonChecked( _hDlg, IDC_PORT_OTHER ) == BST_CHECKED )
  5406. {
  5407. _PortsLV.vDisable( TRUE );
  5408. }
  5409. return TRUE;
  5410. }
  5411. BOOL
  5412. TWizPort::
  5413. bHandle_Command(
  5414. IN WORD wId,
  5415. IN WORD wNotifyId,
  5416. IN HWND hwnd
  5417. )
  5418. {
  5419. BOOL bStatus = TRUE;
  5420. switch( wId )
  5421. {
  5422. case IDC_PORT_EXISTING:
  5423. _PortsLV.vEnable( TRUE );
  5424. _PortsLV.vSetFocus();
  5425. vDisableMonitorList();
  5426. break;
  5427. case IDC_PORT_OTHER:
  5428. _PortsLV.vDisable( TRUE );
  5429. vEnableMonitorList();
  5430. vSetFocusMonitorList();
  5431. break;
  5432. case IDC_PORT_DOUBLE_CLICKED:
  5433. PropSheet_PressButton( GetParent( _hDlg ), PSBTN_NEXT );
  5434. break;
  5435. default:
  5436. bStatus = FALSE;
  5437. break;
  5438. }
  5439. return bStatus;
  5440. }
  5441. VOID
  5442. TWizPort::
  5443. vSelectionPort(
  5444. VOID
  5445. )
  5446. {
  5447. if( !_PortsLV.bReadUI( _pWizard->_strPortName, TRUE ) )
  5448. {
  5449. //
  5450. // Put up error explaining that at least one
  5451. // port must be selected.
  5452. //
  5453. iMessage( _hDlg,
  5454. IDS_ERR_ADD_PRINTER_TITLE,
  5455. IDS_ERR_NO_PORTS,
  5456. MB_OK|MB_ICONSTOP,
  5457. kMsgNone,
  5458. NULL );
  5459. //
  5460. // Set focus to ports LV.
  5461. //
  5462. _PortsLV.vSetFocus();
  5463. //
  5464. // Remain on this page, do not switch.
  5465. //
  5466. _pWizard->bNoPageChange() = TRUE;
  5467. }
  5468. }
  5469. /********************************************************************
  5470. Monitor related members.
  5471. ********************************************************************/
  5472. BOOL
  5473. TWizPort::
  5474. bInitializeMonitorList(
  5475. VOID
  5476. )
  5477. {
  5478. //
  5479. // Get and save the monitor list handle.
  5480. //
  5481. _hMonitorList = GetDlgItem( _hDlg, IDC_MONITOR_LIST );
  5482. SPLASSERT( _hMonitorList );
  5483. //
  5484. // Clear the monitor list.
  5485. //
  5486. ComboBox_ResetContent( _hMonitorList );
  5487. //
  5488. // Enumerate the monitors.
  5489. //
  5490. TStatusB bStatus;
  5491. DWORD cbMonitors = 0;
  5492. PMONITOR_INFO_1 pMonitors = NULL;
  5493. DWORD cMonitors = 0;
  5494. bStatus DBGCHK = VDataRefresh::bEnumMonitors( _pWizard->_strServerName,
  5495. 1,
  5496. (PVOID *)&pMonitors,
  5497. &cbMonitors,
  5498. &cMonitors );
  5499. if( bStatus )
  5500. {
  5501. for( UINT i = 0; i < cMonitors; i++ )
  5502. {
  5503. BOOL bAddMonitor = TRUE;
  5504. //
  5505. // If we are on a remote machine check if the monitor
  5506. // supports remoteable calls. Only remoteable monitors
  5507. // should show up in the combobox.
  5508. //
  5509. if( bIsRemote( _pWizard->_strServerName ) )
  5510. {
  5511. bAddMonitor = bIsRemoteableMonitor( pMonitors[i].pName );
  5512. }
  5513. //
  5514. // Hide the fax monitor, users are not allowed to
  5515. // create fax printer from the add printer wizard.
  5516. //
  5517. bAddMonitor = _tcsicmp( pMonitors[i].pName, FAX_MONITOR_NAME );
  5518. if( bAddMonitor )
  5519. {
  5520. ComboBox_AddString( _hMonitorList, pMonitors[i].pName );
  5521. }
  5522. }
  5523. ComboBox_SetCurSel( _hMonitorList, 0 );
  5524. }
  5525. FreeMem( pMonitors );
  5526. //
  5527. // If there are no monitors in the list, hide the UI.
  5528. // This is possible if all the monitors are not remoteable
  5529. //
  5530. BOOL bDisableMonitorUI = !ComboBox_GetCount( _hMonitorList );
  5531. //
  5532. // Adding ports remotely is not supported on downlevel machines.
  5533. //
  5534. if( bIsRemote( _pWizard->_strServerName ) )
  5535. {
  5536. if( _pWizard->_Di.dwGetCurrentDriverVersion( ) <= 2 )
  5537. {
  5538. bDisableMonitorUI = TRUE;
  5539. }
  5540. }
  5541. //
  5542. // Hide the monitor UI.
  5543. //
  5544. if( bDisableMonitorUI )
  5545. {
  5546. EnableWindow( _hMonitorList, FALSE);
  5547. EnableWindow( GetDlgItem( _hDlg, IDC_MONITOR_TEXT ), FALSE );
  5548. EnableWindow( GetDlgItem( _hDlg, IDC_PORT_OTHER ), FALSE );
  5549. }
  5550. return bStatus;
  5551. }
  5552. BOOL
  5553. TWizPort::
  5554. bGetSelectedMonitor(
  5555. IN TString &strMonitor
  5556. )
  5557. {
  5558. return bGetEditText( _hDlg, IDC_MONITOR_LIST, strMonitor );
  5559. }
  5560. VOID
  5561. TWizPort::
  5562. vEnableMonitorList(
  5563. VOID
  5564. )
  5565. {
  5566. EnableWindow( _hMonitorList, TRUE );
  5567. EnableWindow( GetDlgItem( _hDlg, IDC_MONITOR_TEXT ), TRUE );
  5568. }
  5569. VOID
  5570. TWizPort::
  5571. vDisableMonitorList(
  5572. VOID
  5573. )
  5574. {
  5575. EnableWindow( _hMonitorList, FALSE );
  5576. EnableWindow( GetDlgItem( _hDlg, IDC_MONITOR_TEXT ), FALSE );
  5577. }
  5578. VOID
  5579. TWizPort::
  5580. vSetFocusMonitorList(
  5581. VOID
  5582. )
  5583. {
  5584. SetFocus( _hMonitorList );
  5585. }
  5586. BOOL
  5587. TWizPort::
  5588. bIsRemoteableMonitor(
  5589. IN LPCTSTR pszMonitorName
  5590. )
  5591. {
  5592. //
  5593. // !!LATER!!
  5594. // Add private winspool.drv interface to check if a
  5595. // port monitor is remoteable.
  5596. //
  5597. return TRUE;
  5598. }
  5599. VOID
  5600. TWizPort::
  5601. vSelectionMonitor(
  5602. VOID
  5603. )
  5604. {
  5605. TString strMonitor;
  5606. if( bGetSelectedMonitor( strMonitor ) )
  5607. {
  5608. TStatusB bStatus;
  5609. //
  5610. // Add the port using the selected montior.
  5611. //
  5612. bStatus DBGCHK = AddPort( (LPTSTR)(LPCTSTR)_pWizard->_pszServerName,
  5613. _hDlg,
  5614. (LPTSTR)(LPCTSTR)strMonitor );
  5615. DBGMSG( DBG_TRACE, ( "AddPort returned %d GLE %d\n", bStatus, GetLastError( )));
  5616. if( !bStatus )
  5617. {
  5618. //
  5619. // If not a cancel request then display error message.
  5620. //
  5621. if( GetLastError() != ERROR_CANCELLED )
  5622. {
  5623. extern MSG_ERRMAP gaMsgErrMapPorts[];
  5624. iMessage( _hDlg,
  5625. IDS_ERR_ADD_PRINTER_TITLE,
  5626. IDS_ERR_ADD_PORT,
  5627. MB_OK|MB_ICONSTOP,
  5628. kMsgGetLastError,
  5629. gaMsgErrMapPorts );
  5630. }
  5631. _pWizard->bNoPageChange() = TRUE;
  5632. }
  5633. else
  5634. {
  5635. //
  5636. // Locate the added port
  5637. //
  5638. bStatus DBGCHK = _PortsLV.bLocateAddedPort( _pWizard->pszServerName(),
  5639. _pWizard->_strPortName );
  5640. //
  5641. // We are here because: The monitor returned success but
  5642. // did not add a new port. The whole monitor error reporting path
  5643. // is totaly busted. Monitors are returning success even if they don't
  5644. // add a port. They are also displaying error UI and then returning
  5645. // a success. It is impossible to know what they did and how to react.
  5646. // Therefore I am going to just silently fail, hopeing the monitor
  5647. // writers display a reasonable error message if something went wrong.
  5648. //
  5649. if( !bStatus )
  5650. {
  5651. //
  5652. // Remain on this page, do not switch.
  5653. //
  5654. _pWizard->bNoPageChange() = TRUE;
  5655. //
  5656. // Restore the focus to the monitor list
  5657. //
  5658. SetFocus( GetDlgItem( _hDlg, IDC_MONITOR_LIST ));
  5659. }
  5660. else
  5661. {
  5662. //
  5663. // Reload the ports list view.
  5664. //
  5665. bStatus DBGCHK = _PortsLV.bReloadPorts( _pWizard->pszServerName() );
  5666. //
  5667. // Check the existing port since a new port was added.
  5668. //
  5669. CheckRadioButton( _hDlg, IDC_PORT_OTHER, IDC_PORT_EXISTING, IDC_PORT_EXISTING );
  5670. PostMessage( _hDlg, WM_COMMAND, MAKELPARAM( IDC_PORT_EXISTING, 0 ), (LPARAM)GetDlgItem( _hDlg, IDC_PORT_EXISTING ) );
  5671. }
  5672. }
  5673. }
  5674. else
  5675. {
  5676. _pWizard->bNoPageChange() = TRUE;
  5677. }
  5678. }
  5679. /********************************************************************
  5680. Port selection - new version.
  5681. ********************************************************************/
  5682. static UINT g_arrPorts[] = {IDC_PORTS, IDC_PORTS_INFO_TEXT};
  5683. static UINT g_arrMonitors[] = {IDC_MONITOR_TEXT, IDC_MONITOR_LIST};
  5684. static UINT g_arrMonitorsUI[] = {IDC_MONITOR_TEXT, IDC_MONITOR_LIST, IDC_PORT_OTHER};
  5685. static UINT g_arrPortDesc[TWizPortNew::PORT_TYPE_OTHER] =
  5686. {
  5687. IDS_TEXT_RECOMMENDED,
  5688. IDS_TEXT_PRINTERPORT,
  5689. IDS_TEXT_SERIALPORT,
  5690. IDS_TEXT_PRINTTOFILE
  5691. };
  5692. TWizPortNew::
  5693. TWizPortNew(
  5694. TWizard* pWizard
  5695. ) : MWizardProp(pWizard),
  5696. m_hBmp(NULL),
  5697. m_hwndCB_Ports(NULL),
  5698. m_hwndCB_Monitors(NULL)
  5699. {
  5700. // nothing
  5701. }
  5702. BOOL
  5703. TWizPortNew::
  5704. bHandle_InitDialog(
  5705. VOID
  5706. )
  5707. {
  5708. TStatusB bStatus;
  5709. bStatus DBGNOCHK = FALSE;
  5710. m_hwndCB_Ports = GetDlgItem(hDlg(), IDC_PORTS);
  5711. m_hwndCB_Monitors = GetDlgItem(hDlg(), IDC_MONITOR_LIST);
  5712. // something is wrong with the .rc template if those are not here...
  5713. ASSERT(m_hwndCB_Ports);
  5714. ASSERT(m_hwndCB_Monitors);
  5715. if( m_hwndCB_Ports && m_hwndCB_Monitors )
  5716. {
  5717. HWND hwndImagePlug = GetDlgItem(hDlg(), IDC_IMAGE_PRNPLUG);
  5718. if( hwndImagePlug )
  5719. {
  5720. m_hBmp = (HBITMAP)LoadImage(
  5721. ghInst, MAKEINTRESOURCE(IDB_PRNPLUG), IMAGE_BITMAP, 0, 0,
  5722. LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS);
  5723. if( m_hBmp )
  5724. {
  5725. HANDLE hOldBmp = (HANDLE)SendMessage(hwndImagePlug, STM_SETIMAGE, IMAGE_BITMAP,
  5726. reinterpret_cast<LPARAM>((HBITMAP)m_hBmp));
  5727. if( hOldBmp )
  5728. {
  5729. DeleteObject( hOldBmp );
  5730. }
  5731. }
  5732. }
  5733. // initialize the port's list combobox
  5734. int iPosNew = -1;
  5735. bStatus DBGCHK = bInitializePortsList(&iPosNew);
  5736. if( bStatus && m_spPorts->Count() )
  5737. {
  5738. // select the default port here
  5739. bStatus DBGCHK = pWizard()->strPortName().bUpdate((*m_spPorts)[0].pszName);
  5740. ComboBox_SetCurSel(m_hwndCB_Ports, 0);
  5741. }
  5742. // initialize the monitor's list combobox
  5743. bStatus DBGCHK = bInitializeMonitorsList();
  5744. if( bStatus && ComboBox_GetCount(m_hwndCB_Monitors) )
  5745. {
  5746. // select the default monitor
  5747. ComboBox_SetCurSel(m_hwndCB_Monitors, 0);
  5748. }
  5749. // select ports radio button
  5750. vSelectPortsRadio();
  5751. }
  5752. return bStatus;
  5753. }
  5754. BOOL
  5755. TWizPortNew::
  5756. bHandle_SetActive(
  5757. VOID
  5758. )
  5759. {
  5760. BOOL bPorts = (BST_CHECKED == IsDlgButtonChecked(hDlg(), IDC_PORT_EXISTING));
  5761. PostMessage(hDlg(), WM_NEXTDLGCTL,
  5762. reinterpret_cast<WPARAM>(bPorts ? m_hwndCB_Ports : m_hwndCB_Monitors), (LPARAM)TRUE);
  5763. return TRUE;
  5764. }
  5765. BOOL
  5766. TWizPortNew::
  5767. bHandle_WizNext(
  5768. VOID
  5769. )
  5770. {
  5771. if( BST_CHECKED == IsDlgButtonChecked(hDlg(), IDC_PORT_EXISTING) )
  5772. {
  5773. vSelectionPort();
  5774. }
  5775. else
  5776. {
  5777. vSelectionMonitor();
  5778. }
  5779. return TRUE;
  5780. }
  5781. BOOL
  5782. TWizPortNew::
  5783. bHandle_Command(
  5784. IN WORD wId,
  5785. IN WORD wNotifyId,
  5786. IN HWND hwnd
  5787. )
  5788. {
  5789. BOOL bRet = TRUE;
  5790. switch( wId )
  5791. {
  5792. case IDC_PORT_OTHER:
  5793. case IDC_PORT_EXISTING:
  5794. {
  5795. // enable/disable controls appropriately
  5796. BOOL bPorts = IDC_PORT_EXISTING == wId ? TRUE : FALSE;
  5797. vEnableControls(hDlg(), bPorts, g_arrPorts, ARRAYSIZE(g_arrPorts));
  5798. vEnableControls(hDlg(), !bPorts, g_arrMonitors, ARRAYSIZE(g_arrMonitors));
  5799. PostMessage(hDlg(), WM_NEXTDLGCTL,
  5800. reinterpret_cast<WPARAM>(bPorts ? m_hwndCB_Ports : m_hwndCB_Monitors), (LPARAM)TRUE);
  5801. }
  5802. break;
  5803. default:
  5804. // message not processed
  5805. bRet = FALSE;
  5806. break;
  5807. }
  5808. return bRet;
  5809. }
  5810. VOID
  5811. TWizPortNew::
  5812. vSelectionPort(
  5813. VOID
  5814. )
  5815. {
  5816. int iPos = ComboBox_GetCurSel(m_hwndCB_Ports);
  5817. if( CB_ERR == iPos )
  5818. {
  5819. // that would be pretty weird, but may happen
  5820. vShowUnexpectedError(hDlg(), IDS_ERR_ADD_PRINTER_TITLE);
  5821. pWizard()->bNoPageChange() = TRUE;
  5822. PostMessage(hDlg(), WM_NEXTDLGCTL, reinterpret_cast<WPARAM>(m_hwndCB_Ports), (LPARAM)TRUE);
  5823. }
  5824. else
  5825. {
  5826. // update pWizard()->strPortName & continue
  5827. TStatusB bStatus;
  5828. bStatus DBGCHK = pWizard()->strPortName().bUpdate(
  5829. (*m_spPorts)[iPos].pszName);
  5830. }
  5831. }
  5832. VOID
  5833. TWizPortNew::
  5834. vSelectionMonitor(
  5835. VOID
  5836. )
  5837. {
  5838. TStatusB bStatus;
  5839. TString strMonitor;
  5840. if( !bGetEditText(hDlg(), IDC_MONITOR_LIST, strMonitor) )
  5841. {
  5842. // that would pretty weird, but may happen
  5843. vShowUnexpectedError(hDlg(), IDS_ERR_ADD_PRINTER_TITLE);
  5844. pWizard()->bNoPageChange() = TRUE;
  5845. PostMessage(hDlg(), WM_NEXTDLGCTL, reinterpret_cast<WPARAM>(m_hwndCB_Ports), (LPARAM)TRUE);
  5846. }
  5847. else
  5848. {
  5849. // add the port using the selected montior.
  5850. bStatus DBGCHK = AddPort(
  5851. const_cast<LPTSTR>(static_cast<LPCTSTR>(pWizard()->pszServerName())), hDlg(),
  5852. const_cast<LPTSTR>(static_cast<LPCTSTR>(strMonitor)));
  5853. if( bStatus )
  5854. {
  5855. // remember the last selected string
  5856. TCHAR szLastSel[MAX_PATH];
  5857. ComboBox_GetText( m_hwndCB_Ports, szLastSel, ARRAYSIZE(szLastSel) );
  5858. // reinitiaize the ports list and select the newly added port, if any
  5859. int iPosNew;
  5860. bStatus DBGCHK = bInitializePortsList(&iPosNew);
  5861. if( -1 == iPosNew )
  5862. {
  5863. // We are here because: The monitor returned success but
  5864. // did not add a new port. The whole monitor error reporting path
  5865. // is totaly busted. Monitors are returning success even if they don't
  5866. // add a port. They are also displaying error UI and then returning
  5867. // a success. It is impossible to know what they did and how to react.
  5868. // Therefore I am going to just silently fail, hopeing the monitor
  5869. // writers display a reasonable error message if something went wrong.
  5870. // Reselect the last selected item
  5871. int iLastSel = ComboBox_FindStringExact( m_hwndCB_Ports, -1, szLastSel );
  5872. ComboBox_SetCurSel( m_hwndCB_Ports, ((iLastSel == CB_ERR) ? 0 : iLastSel) );
  5873. pWizard()->bNoPageChange() = TRUE;
  5874. PostMessage(hDlg(), WM_NEXTDLGCTL, reinterpret_cast<WPARAM>(m_hwndCB_Monitors), (LPARAM)TRUE);
  5875. }
  5876. else
  5877. {
  5878. // select the newly added port and continue
  5879. ComboBox_SetCurSel(m_hwndCB_Ports, iPosNew);
  5880. // select ports radio button
  5881. vSelectPortsRadio();
  5882. // proceed with the port selection
  5883. vSelectionPort();
  5884. }
  5885. }
  5886. else
  5887. {
  5888. // if not ERROR_CANCELLED then display error message.
  5889. if( GetLastError() != ERROR_CANCELLED )
  5890. {
  5891. extern MSG_ERRMAP gaMsgErrMapPorts[];
  5892. iMessage(hDlg(), IDS_ERR_ADD_PRINTER_TITLE, IDS_ERR_ADD_PORT, MB_OK|MB_ICONSTOP, kMsgGetLastError, gaMsgErrMapPorts);
  5893. }
  5894. pWizard()->bNoPageChange() = TRUE;
  5895. PostMessage(hDlg(), WM_NEXTDLGCTL, reinterpret_cast<WPARAM>(m_hwndCB_Monitors), (LPARAM)TRUE);
  5896. }
  5897. }
  5898. }
  5899. BOOL
  5900. TWizPortNew::
  5901. bInitializePortsList(
  5902. OUT int *piNewlyAdded
  5903. )
  5904. {
  5905. // enumerate the ports starting at level 2 downward.
  5906. TStatusB bStatus;
  5907. bStatus DBGCHK = SUCCEEDED(hGetPorts(piNewlyAdded));
  5908. if( bStatus )
  5909. {
  5910. ASSERT(m_hwndCB_Ports);
  5911. ComboBox_ResetContent(m_hwndCB_Ports);
  5912. int i, iCount = m_spPorts->Count();
  5913. if( iCount )
  5914. {
  5915. // go ahead and insert the ports...
  5916. TString strFriendly;
  5917. for( i = 0; i < iCount; i++ )
  5918. {
  5919. bStatus DBGCHK = bFormatPortName((*m_spPorts)[i], &strFriendly);
  5920. if( bStatus )
  5921. {
  5922. bStatus DBGCHK = (CB_ERR != ComboBox_AddString(m_hwndCB_Ports,
  5923. static_cast<LPCTSTR>(strFriendly)));
  5924. if( !bStatus )
  5925. {
  5926. // something has failed - cleanup
  5927. ComboBox_ResetContent(m_hwndCB_Ports);
  5928. m_spPorts->DeleteAll();
  5929. m_spBuffer = NULL;
  5930. break;
  5931. }
  5932. }
  5933. }
  5934. }
  5935. }
  5936. return bStatus;
  5937. }
  5938. BOOL
  5939. TWizPortNew::
  5940. bInitializeMonitorsList(
  5941. VOID
  5942. )
  5943. {
  5944. DWORD cbMonitors = 0;
  5945. DWORD cMonitors = 0;
  5946. CAutoPtrSpl<MONITOR_INFO_2> spMonitors;
  5947. TStatusB bStatus;
  5948. bStatus DBGCHK = VDataRefresh::bEnumMonitors(_pWizard->_strServerName, 2, spMonitors.GetPPV(), &cbMonitors, &cMonitors);
  5949. if( bStatus )
  5950. {
  5951. // port monitors enumerated successfully here, we are about to fill up the combo
  5952. ComboBox_ResetContent(m_hwndCB_Monitors);
  5953. for( DWORD i = 0; i < cMonitors; i++ )
  5954. {
  5955. BOOL bAddMonitor = TRUE;
  5956. // If we are on a remote machine check if the monitor
  5957. // supports remoteable calls. Only remoteable monitors
  5958. // should show up in the combobox.
  5959. if( bIsRemote(_pWizard->_strServerName) )
  5960. {
  5961. bAddMonitor = bIsRemoteableMonitor(spMonitors[i].pName);
  5962. }
  5963. // Hide the fax monitor, users are not allowed to
  5964. // create fax printer from the add printer wizard.
  5965. bAddMonitor = _tcsicmp(spMonitors[i].pName, FAX_MONITOR_NAME);
  5966. if( bAddMonitor )
  5967. {
  5968. // this monitor is OK to add...
  5969. ComboBox_AddString(m_hwndCB_Monitors, spMonitors[i].pName);
  5970. }
  5971. }
  5972. ComboBox_SetCurSel(m_hwndCB_Monitors, 0);
  5973. }
  5974. if( !ComboBox_GetCount(m_hwndCB_Monitors) ||
  5975. (bIsRemote(_pWizard->_strServerName) && _pWizard->_Di.dwGetCurrentDriverVersion() <= 2) )
  5976. {
  5977. // If there are no monitors in the list, hide the UI.
  5978. // This is possible if all the monitors are not remoteable
  5979. // Also adding ports remotely is not supported on downlevel
  5980. // machines.
  5981. vEnableControls(_hDlg, FALSE, g_arrMonitorsUI, ARRAYSIZE(g_arrMonitorsUI));
  5982. }
  5983. return bStatus;
  5984. }
  5985. BOOL
  5986. TWizPortNew::
  5987. bIsRemoteableMonitor(
  5988. IN LPCTSTR pszMonitorName
  5989. )
  5990. {
  5991. //
  5992. // !!LATER!!
  5993. // Add private winspool.drv interface to check if a
  5994. // port monitor is remoteable.
  5995. //
  5996. return TRUE;
  5997. }
  5998. VOID
  5999. TWizPortNew::
  6000. vSelectPortsRadio(
  6001. VOID
  6002. )
  6003. {
  6004. // so any of the port selection action.
  6005. CheckRadioButton(hDlg(), IDC_PORT_OTHER, IDC_PORT_EXISTING, IDC_PORT_EXISTING);
  6006. // enable/diable the controls appropriately
  6007. vEnableControls(hDlg(), TRUE, g_arrPorts, ARRAYSIZE(g_arrPorts));
  6008. vEnableControls(hDlg(), FALSE, g_arrMonitors, ARRAYSIZE(g_arrMonitors));
  6009. PostMessage(hDlg(), WM_NEXTDLGCTL, reinterpret_cast<WPARAM>(m_hwndCB_Ports), (LPARAM)TRUE);
  6010. }
  6011. HRESULT
  6012. TWizPortNew::
  6013. hGetPorts(
  6014. OUT int *piNewlyAdded
  6015. )
  6016. {
  6017. HRESULT hr = E_INVALIDARG;
  6018. // validate arguments...
  6019. if( piNewlyAdded )
  6020. {
  6021. hr = S_OK;
  6022. // enumerate the ports starting at level 2 downward.
  6023. CAutoPtrSpl<BYTE> spBuffer;
  6024. CAutoPtr<CPortsArray> spPorts = new CPortsArray;
  6025. DWORD dwLevel = 2, cbPorts = 0, cPorts = 0;
  6026. if( spPorts && VDataRefresh::bEnumPortsMaxLevel(
  6027. pWizard()->pszServerName(), &dwLevel,
  6028. spBuffer.GetPPV(), &cbPorts, &cPorts) )
  6029. {
  6030. // insert ports in the priority array
  6031. int iPos;
  6032. BOOL bNewFound = FALSE;
  6033. PortInfo piNew, pi = {0, NULL, NULL};
  6034. for( DWORD dw = 0; dw < cPorts; dw++ )
  6035. {
  6036. pi.pszName = (2 == dwLevel ? spBuffer.GetPtrAs<PORT_INFO_2*>()[dw].pPortName :
  6037. spBuffer.GetPtrAs<PORT_INFO_1*>()[dw].pName);
  6038. if( 2 == dwLevel && bIsFaxPort(pi.pszName,
  6039. spBuffer.GetPtrAs<PORT_INFO_2*>()[dw].pMonitorName) )
  6040. {
  6041. // skip the fax ports
  6042. continue;
  6043. }
  6044. pi.pszDesc = (2 == dwLevel ? spBuffer.GetPtrAs<PORT_INFO_2*>()[dw].pDescription : NULL);
  6045. pi.iType = iGetPortType(pi.pszName);
  6046. if( m_spPorts && FALSE == bNewFound && FALSE == m_spPorts->FindItem(pi, &iPos) )
  6047. {
  6048. // this is a newly added port, remember it
  6049. bNewFound = TRUE;
  6050. piNew = pi;
  6051. }
  6052. // insert...
  6053. if( -1 == spPorts->SortedInsert(pi) )
  6054. {
  6055. hr = E_OUTOFMEMORY;
  6056. break;
  6057. }
  6058. }
  6059. if( SUCCEEDED(hr) )
  6060. {
  6061. m_spBuffer = spBuffer.Detach();
  6062. m_spPorts = spPorts.Detach();
  6063. *piNewlyAdded = (bNewFound && m_spPorts->FindItem(piNew, &iPos)) ? iPos : -1;
  6064. }
  6065. }
  6066. else
  6067. {
  6068. // spPorts is NULL or VDataRefresh::bEnumPortsMaxLevel failed
  6069. DWORD dwErr = GetLastError();
  6070. hr = (!spPorts ? E_OUTOFMEMORY : (ERROR_SUCCESS == dwErr ?
  6071. E_FAIL : HRESULT_FROM_WIN32(dwErr)));
  6072. }
  6073. }
  6074. return hr;
  6075. }
  6076. int
  6077. TWizPortNew::
  6078. iGetPortType(
  6079. IN LPCTSTR pszPortName
  6080. )
  6081. {
  6082. ASSERT(pszPortName);
  6083. if( bMatchTemplate(TEXT("LPT1:"), pszPortName) )
  6084. {
  6085. // "LPT1:" has the ultimate highest priority - pri 0
  6086. return PORT_TYPE_LPT1;
  6087. }
  6088. else if( bMatchTemplate(TEXT("LPT?:"), pszPortName) )
  6089. {
  6090. // followed by the rest of the LPT ports as pri 1
  6091. return PORT_TYPE_LPTX;
  6092. }
  6093. else if( bMatchTemplate(TEXT("COM?:"), pszPortName) )
  6094. {
  6095. // followed by the COM ports as pri 2
  6096. return PORT_TYPE_COMX;
  6097. }
  6098. else if( bMatchTemplate(TEXT("FILE:"), pszPortName) )
  6099. {
  6100. // followed by the FILE ports as pri 3
  6101. return PORT_TYPE_FILE;
  6102. }
  6103. else
  6104. {
  6105. // followed by the other ports as pri 4
  6106. return PORT_TYPE_OTHER;
  6107. }
  6108. }
  6109. BOOL
  6110. TWizPortNew::
  6111. bFormatPortName(
  6112. IN const PortInfo &pi,
  6113. OUT TString *pstrFriendlyName
  6114. )
  6115. {
  6116. ASSERT(pstrFriendlyName);
  6117. TStatusB bStatus;
  6118. if( pi.iType < PORT_TYPE_OTHER )
  6119. {
  6120. // this is a common port type - load frendly decr...
  6121. TString strDesc;
  6122. bStatus DBGCHK = strDesc.bLoadString(ghInst, g_arrPortDesc[pi.iType]);
  6123. if( bStatus )
  6124. {
  6125. bStatus DBGCHK = pstrFriendlyName->bFormat(TEXT("%s (%s)"),
  6126. pi.pszName, static_cast<LPCTSTR>(strDesc));
  6127. }
  6128. }
  6129. else
  6130. {
  6131. // pi.pszName can be NULL, but that's OK
  6132. bStatus DBGCHK = ((pi.pszDesc && pi.pszDesc[0]) ?
  6133. pstrFriendlyName->bFormat(TEXT("%s (%s)"), pi.pszName, pi.pszDesc) :
  6134. pstrFriendlyName->bUpdate(pi.pszName));
  6135. }
  6136. return bStatus;
  6137. }
  6138. /********************************************************************
  6139. Printer name.
  6140. ********************************************************************/
  6141. TWizName::
  6142. TWizName(
  6143. TWizard* pWizard
  6144. ) : MWizardProp( pWizard )
  6145. {
  6146. }
  6147. BOOL
  6148. TWizName::
  6149. bHandle_InitDialog(
  6150. VOID
  6151. )
  6152. {
  6153. TStatusB bStatus;
  6154. //
  6155. // If we are adding a printer on a remote machine, don't bother
  6156. // showing the default settings, since the user doen't have a
  6157. // connection.
  6158. //
  6159. // Check if there is a default printer. If there isn't one,
  6160. // we'll always make it the default, so we want to hide
  6161. // the controls.
  6162. //
  6163. if( _pWizard->pszServerName() || CheckDefaultPrinter( NULL ) == kNoDefault ){
  6164. static DWORD adwDefault[] = {
  6165. IDC_SET_DEFAULT,
  6166. IDC_RADIO_YES,
  6167. IDC_RADIO_NO
  6168. };
  6169. for( UINT i = 0; i < COUNTOF( adwDefault ); ++i )
  6170. {
  6171. ShowWindow( GetDlgItem( _hDlg, adwDefault[i] ), SW_HIDE );
  6172. }
  6173. //
  6174. // If we're here not because we're adding a printer on a remote
  6175. // machine, then always make it the default.
  6176. //
  6177. if( !_pWizard->pszServerName( )){
  6178. //
  6179. // Always set it as the default.
  6180. //
  6181. _pWizard->bSetDefault() = TRUE;
  6182. //
  6183. // Don't show the set as default UI.
  6184. //
  6185. _pWizard->bShowSetDefault() = FALSE;
  6186. }
  6187. } else {
  6188. //
  6189. // Get the default button state.
  6190. //
  6191. INT iValueId = _pWizard->bSetDefault() ? IDC_RADIO_YES : IDC_RADIO_NO;
  6192. //
  6193. // By default, don't make it the default printer.
  6194. //
  6195. bStatus DBGCHK = CheckRadioButton( _hDlg,
  6196. IDC_RADIO_YES,
  6197. IDC_RADIO_NO,
  6198. iValueId );
  6199. }
  6200. //
  6201. // Set the printer name limit. The limit in win9x is 32 chars
  6202. // (including NULL terminator). There isn't a properly defined
  6203. // WinNT spooler limit, but it crashes around MAX_PATH (260 including
  6204. // NULL). Note that win32spl.dll prepends \\server\ when connection
  6205. // remotely, so our effective limit, including NULL is
  6206. // MAX_PATH - (kServerLenMax = MAX_COMPUTERNAME_LEN - 3).
  6207. //
  6208. SendDlgItemMessage( _hDlg,
  6209. IDC_PRINTER_NAME,
  6210. EM_SETLIMITTEXT,
  6211. kPrinterLocalNameMax,
  6212. 0 );
  6213. //
  6214. // Generate a new printer name that is unique.
  6215. //
  6216. vUpdateName();
  6217. return TRUE;
  6218. }
  6219. VOID
  6220. TWizName::
  6221. vUpdateName(
  6222. VOID
  6223. )
  6224. {
  6225. TStatusB bStatus;
  6226. TCHAR szDefault[kPrinterBufMax];
  6227. LPCTSTR pszPrinterName;
  6228. TString strPrinterName;
  6229. //
  6230. // Read the current contents of the edit control.
  6231. //
  6232. bStatus DBGCHK = bGetEditText( _hDlg,
  6233. IDC_PRINTER_NAME,
  6234. strPrinterName );
  6235. // If the name is empty then generate a unique name.
  6236. // If the current printer name is equal to the generated name
  6237. // then we assume the user has not provided their own printer name
  6238. // and thus we will generated a printer name.
  6239. //
  6240. if( strPrinterName.bEmpty() ||
  6241. (strPrinterName == _strGeneratedPrinterName &&
  6242. _pWizard->_bRefreshPrinterName ) ){
  6243. //
  6244. // Clear the refresh printer name flag.
  6245. //
  6246. _pWizard->_bRefreshPrinterName = FALSE;
  6247. //
  6248. // Create a new friendly printer name.
  6249. //
  6250. bStatus DBGNOCHK = NewFriendlyName( _pWizard->_pszServerName,
  6251. (LPTSTR)(LPCTSTR)_pWizard->strDriverName(),
  6252. szDefault );
  6253. //
  6254. // If a new Friendly name was created.
  6255. //
  6256. if( bStatus ){
  6257. pszPrinterName = szDefault;
  6258. } else {
  6259. pszPrinterName = _pWizard->strDriverName();
  6260. }
  6261. //
  6262. // Save the generated printer name.
  6263. //
  6264. bStatus DBGCHK = _strGeneratedPrinterName.bUpdate( pszPrinterName );
  6265. //
  6266. // Update the edit control with new printer name.
  6267. //
  6268. bStatus DBGCHK = bSetEditText( _hDlg, IDC_PRINTER_NAME, pszPrinterName );
  6269. }
  6270. }
  6271. VOID
  6272. TWizName::
  6273. vReadUI(
  6274. VOID
  6275. )
  6276. {
  6277. //
  6278. // Save state.
  6279. //
  6280. if( !bGetEditText( _hDlg, IDC_PRINTER_NAME, _pWizard->_strPrinterName )){
  6281. _pWizard->_bErrorSaving = TRUE;
  6282. vShowUnexpectedError( _hDlg, IDS_ERR_ADD_PRINTER_TITLE );
  6283. _pWizard->bNoPageChange() = TRUE;
  6284. return;
  6285. }
  6286. //
  6287. // Printer names cannot have trailing white spaces.
  6288. //
  6289. vStripTrailWhiteSpace( (LPTSTR)(LPCTSTR)_pWizard->_strPrinterName );
  6290. //
  6291. // Check if the name has any illegal characters.
  6292. //
  6293. if( !bIsLocalPrinterNameValid( _pWizard->_strPrinterName ) )
  6294. {
  6295. iMessage( _hDlg,
  6296. IDS_ERR_ADD_PRINTER_TITLE,
  6297. IDS_ERR_BAD_PRINTER_NAME,
  6298. MB_OK|MB_ICONSTOP,
  6299. kMsgNone,
  6300. NULL );
  6301. goto BadName;
  6302. }
  6303. //
  6304. // Check if the name is null.
  6305. //
  6306. if( _pWizard->_strPrinterName.bEmpty( ) ){
  6307. iMessage( _hDlg,
  6308. IDS_ERR_ADD_PRINTER_TITLE,
  6309. IDS_ERR_NO_PRINTER_NAME,
  6310. MB_OK|MB_ICONSTOP,
  6311. kMsgNone,
  6312. NULL );
  6313. goto BadName;
  6314. }
  6315. //
  6316. // Check if the name is longer than kPrinterLocalNameMax characters.
  6317. //
  6318. if( lstrlen(_pWizard->_strPrinterName) > kPrinterLocalNameMax ){
  6319. iMessage( _hDlg,
  6320. IDS_ERR_ADD_PRINTER_TITLE,
  6321. IDS_ERR_LONG_PRINTER_NAME,
  6322. MB_OK|MB_ICONSTOP,
  6323. kMsgNone,
  6324. NULL );
  6325. goto BadName;
  6326. }
  6327. //
  6328. // Check if the name conflicts with an existing printer name.
  6329. //
  6330. TCHAR szDefault[kPrinterBufMax];
  6331. if( NewFriendlyName( _pWizard->_pszServerName,
  6332. (LPTSTR)(LPCTSTR)_pWizard->_strPrinterName,
  6333. szDefault ) ){
  6334. iMessage( _hDlg,
  6335. IDS_ERR_ADD_PRINTER_TITLE,
  6336. IDS_ERR_PRINTER_NAME_CONFLICT,
  6337. MB_OK|MB_ICONSTOP,
  6338. ERROR_PRINTER_ALREADY_EXISTS,
  6339. NULL );
  6340. goto BadName;
  6341. }
  6342. //
  6343. // If the default UI is displayed then read the UI setting.
  6344. //
  6345. if( _pWizard->bShowSetDefault() )
  6346. {
  6347. //
  6348. // Get default printer selection.
  6349. //
  6350. _pWizard->bSetDefault() = IsDlgButtonChecked( _hDlg, IDC_RADIO_YES ) == BST_CHECKED;
  6351. }
  6352. return;
  6353. BadName:
  6354. //
  6355. // Set focus to name edit control.
  6356. //
  6357. SetFocus( GetDlgItem( _hDlg, IDC_PRINTER_NAME ));
  6358. _pWizard->bNoPageChange() = TRUE;
  6359. }
  6360. BOOL
  6361. TWizName::
  6362. bHandle_SetActive(
  6363. VOID
  6364. )
  6365. {
  6366. //
  6367. // Since the driver name may have changed we may
  6368. // have to generate a new unique printer name.
  6369. //
  6370. vUpdateName();
  6371. return TRUE;
  6372. }
  6373. BOOL
  6374. TWizName::
  6375. bHandle_WizNext(
  6376. VOID
  6377. )
  6378. {
  6379. vReadUI();
  6380. return TRUE;
  6381. }
  6382. /********************************************************************
  6383. Sharing and architecture.
  6384. ********************************************************************/
  6385. TWizShare::
  6386. TWizShare(
  6387. TWizard* pWizard
  6388. ) : MWizardProp( pWizard ),
  6389. _pPrtShare( NULL )
  6390. {
  6391. }
  6392. TWizShare::
  6393. ~TWizShare(
  6394. VOID
  6395. )
  6396. {
  6397. delete _pPrtShare;
  6398. }
  6399. BOOL
  6400. TWizShare::
  6401. bHandle_InitDialog(
  6402. VOID
  6403. )
  6404. {
  6405. //
  6406. // By default, don't share the printer.
  6407. //
  6408. if( _pWizard->bShared() )
  6409. {
  6410. vSharePrinter();
  6411. }
  6412. else
  6413. {
  6414. vUnsharePrinter();
  6415. }
  6416. //
  6417. // Set the printer share name limit. The limit in win9x is
  6418. // 8.3 == 12+1 chars (including NULL terminator). The Winnt limit
  6419. // is defined as NNLEN;
  6420. //
  6421. SendDlgItemMessage( _hDlg, IDC_SHARED_NAME, EM_SETLIMITTEXT, kPrinterShareNameMax, 0 );
  6422. return TRUE;
  6423. }
  6424. VOID
  6425. TWizShare::
  6426. vReadUI(
  6427. VOID
  6428. )
  6429. {
  6430. PDWORD pdwSelected = NULL;
  6431. _pWizard->_bShared = ( IsDlgButtonChecked( _hDlg, IDC_SHARED ) == BST_CHECKED );
  6432. if( !bGetEditText( _hDlg, IDC_SHARED_NAME, _pWizard->_strShareName )){
  6433. _pWizard->_bErrorSaving = TRUE;
  6434. vShowUnexpectedError( _hDlg, IDS_ERR_ADD_PRINTER_TITLE );
  6435. goto Fail;
  6436. }
  6437. //
  6438. // Has the user choosen to share this printer.
  6439. //
  6440. if( _pWizard->bShared( ) ){
  6441. //
  6442. // If the share name is NULL, put up an error.
  6443. //
  6444. if( _pWizard->_strShareName.bEmpty( ) ){
  6445. iMessage( _hDlg,
  6446. IDS_ERR_ADD_PRINTER_TITLE,
  6447. IDS_ERR_NO_SHARE_NAME,
  6448. MB_OK|MB_ICONSTOP,
  6449. kMsgNone,
  6450. NULL );
  6451. //
  6452. // Set the focus to the shared as text.
  6453. //
  6454. SetFocus( GetDlgItem( _hDlg, IDC_SHARED_NAME ));
  6455. goto Fail;
  6456. }
  6457. //
  6458. // Ensure the Printer share object is valid.
  6459. //
  6460. if( VALID_PTR( _pPrtShare ) ){
  6461. //
  6462. // Check the share name if its valid.
  6463. //
  6464. INT iStatus;
  6465. iStatus = _pPrtShare->iIsValidNtShare( _pWizard->_strShareName );
  6466. //
  6467. // If share name is not a valid NT share name, put error message.
  6468. //
  6469. if( iStatus != TPrtShare::kSuccess ){
  6470. iMessage( _hDlg,
  6471. IDS_ERR_ADD_PRINTER_TITLE,
  6472. IDS_ERR_INVALID_CHAR_SHARENAME,
  6473. MB_OK|MB_ICONSTOP,
  6474. kMsgNone,
  6475. NULL );
  6476. SetFocus( GetDlgItem( _hDlg, IDC_SHARED_NAME ));
  6477. goto Fail;
  6478. }
  6479. //
  6480. // Check if the share name is a valid DOS share.
  6481. //
  6482. iStatus = _pPrtShare->iIsValidDosShare( _pWizard->_strShareName );
  6483. //
  6484. // If share name is not a valid DOS share name, warn the user.
  6485. //
  6486. if( iStatus != TPrtShare::kSuccess ){
  6487. if( IDYES != iMessage( _hDlg,
  6488. IDS_ERR_ADD_PRINTER_TITLE,
  6489. IDS_ERR_SHARE_NAME_NOT_DOS,
  6490. MB_YESNO|MB_ICONEXCLAMATION,
  6491. kMsgNone,
  6492. NULL ) ){
  6493. SetFocus( GetDlgItem( _hDlg, IDC_SHARED_NAME ) );
  6494. goto Fail;
  6495. }
  6496. }
  6497. //
  6498. // Check if the share name is unique.
  6499. //
  6500. if( !_pPrtShare->bIsValidShareNameForThisPrinter( _pWizard->_strShareName,
  6501. _pWizard->_strPrinterName ) ){
  6502. iMessage( _hDlg,
  6503. IDS_ERR_ADD_PRINTER_TITLE,
  6504. IDS_ERR_DUPLICATE_SHARE,
  6505. MB_OK|MB_ICONSTOP,
  6506. kMsgNone,
  6507. NULL );
  6508. //
  6509. // Set the focus to the shared as text.
  6510. //
  6511. SetFocus( GetDlgItem( _hDlg, IDC_SHARED_NAME ));
  6512. goto Fail;
  6513. }
  6514. }
  6515. }
  6516. if (FALSE == _pWizard->_bShared)
  6517. {
  6518. // if the printer is not shared we should clear the comment and
  6519. // location since they may have been set already in the case
  6520. // where the wizard has been restarted from the last page.
  6521. _pWizard->_strLocation.bUpdate(NULL);
  6522. _pWizard->_strComment.bUpdate(NULL);
  6523. }
  6524. return;
  6525. Fail:
  6526. _pWizard->bNoPageChange() = TRUE;
  6527. return;
  6528. }
  6529. VOID
  6530. TWizShare::
  6531. vSharePrinter(
  6532. VOID
  6533. )
  6534. /*++
  6535. Routine Description:
  6536. User clicked share radio button. Change the UI appropriately.
  6537. Arguments:
  6538. Return Value:
  6539. --*/
  6540. {
  6541. //
  6542. // Set radio button and possibly enable window.
  6543. //
  6544. CheckRadioButton( _hDlg, IDC_SHARED_OFF, IDC_SHARED, IDC_SHARED );
  6545. vEnableCtl( _hDlg, IDC_SHARED_NAME, TRUE );
  6546. //
  6547. // Set the default share name.
  6548. //
  6549. vSetDefaultShareName();
  6550. //
  6551. // Set the focus to the shared as text.
  6552. //
  6553. SetFocus( GetDlgItem( _hDlg, IDC_SHARED_NAME ));
  6554. Edit_SetSel( GetDlgItem( _hDlg, IDC_SHARED_NAME ), 0, -1 );
  6555. }
  6556. VOID
  6557. TWizShare::
  6558. vUnsharePrinter(
  6559. VOID
  6560. )
  6561. /*++
  6562. Routine Description:
  6563. User clicked don't share radio button. Change the UI appropriately.
  6564. Arguments:
  6565. Return Value:
  6566. --*/
  6567. {
  6568. //
  6569. // Set radio button and disable window.
  6570. //
  6571. CheckRadioButton( _hDlg, IDC_SHARED_OFF, IDC_SHARED, IDC_SHARED_OFF );
  6572. vEnableCtl( _hDlg, IDC_SHARED_NAME, FALSE );
  6573. }
  6574. VOID
  6575. TWizShare::
  6576. vSetDefaultShareName(
  6577. VOID
  6578. )
  6579. /*++
  6580. Routine Description:
  6581. Sets the default share name if use has choosen to share
  6582. this printer. We will update the share name if
  6583. this is the first time setting the share name.
  6584. Arguments:
  6585. BOOL Indicating if the printer name has changed. TRUE
  6586. if the printe name has changed and FALSE if printer name
  6587. has not change.
  6588. Return Value:
  6589. Nothing.
  6590. --*/
  6591. {
  6592. TStatusB bStatus;
  6593. TString strShareName;
  6594. //
  6595. // Ignore share name generation if the printer has
  6596. // not been shared.
  6597. //
  6598. if( IsDlgButtonChecked( _hDlg, IDC_SHARED ) != BST_CHECKED ){
  6599. return;
  6600. }
  6601. //
  6602. // Read the current contents of the edit control.
  6603. //
  6604. bStatus DBGCHK = bGetEditText( _hDlg, IDC_SHARED_NAME, strShareName );
  6605. DBGMSG( DBG_TRACE, ( "strShareName " TSTR "\n", (LPCTSTR)strShareName ) );
  6606. DBGMSG( DBG_TRACE, ( "_strGeneratedShareName " TSTR "\n", (LPCTSTR)_strGeneratedShareName ) );
  6607. //
  6608. // Create a share name if the current edit field is empty.
  6609. // or if the current share name is the same as the previously
  6610. // generated share name.
  6611. //
  6612. if( strShareName.bEmpty() || (_strGeneratedShareName == strShareName) ){
  6613. //
  6614. // If the share object has not be constructed, then
  6615. // construct it.
  6616. //
  6617. if( !_pPrtShare ){
  6618. _pPrtShare = new TPrtShare( _pWizard->_pszServerName );
  6619. }
  6620. //
  6621. // Ensure the share object is still valid.
  6622. //
  6623. if( VALID_PTR( _pPrtShare ) ){
  6624. //
  6625. // Create valid unique share name.
  6626. //
  6627. bStatus DBGNOCHK = _pPrtShare->bNewShareName( strShareName, _pWizard->_strPrinterName );
  6628. //
  6629. // Set the generated share name.
  6630. //
  6631. bStatus DBGCHK = bSetEditText( _hDlg, IDC_SHARED_NAME, strShareName );
  6632. //
  6633. // Save the generated share name.
  6634. //
  6635. bStatus DBGCHK = _strGeneratedShareName.bUpdate( strShareName );
  6636. }
  6637. }
  6638. }
  6639. BOOL
  6640. TWizShare::
  6641. bHandle_SetActive(
  6642. VOID
  6643. )
  6644. {
  6645. //
  6646. // Clear the driver changed status.
  6647. //
  6648. _pWizard->bDriverChanged() = FALSE;
  6649. //
  6650. // Refresh the share name, the printer name may have changed.
  6651. //
  6652. vSetDefaultShareName();
  6653. return TRUE;
  6654. }
  6655. BOOL
  6656. TWizShare::
  6657. bHandle_WizNext(
  6658. VOID
  6659. )
  6660. {
  6661. vReadUI();
  6662. return TRUE;
  6663. }
  6664. BOOL
  6665. TWizShare::
  6666. bHandle_Command(
  6667. IN WORD wId,
  6668. IN WORD wNotifyId,
  6669. IN HWND hwnd
  6670. )
  6671. {
  6672. BOOL bStatus = TRUE;
  6673. switch( wId )
  6674. {
  6675. case IDC_SHARED_OFF:
  6676. vUnsharePrinter();
  6677. break;
  6678. case IDC_SHARED:
  6679. vSharePrinter();
  6680. break;
  6681. default:
  6682. bStatus = FALSE;
  6683. break;
  6684. }
  6685. return bStatus;
  6686. }
  6687. /********************************************************************
  6688. Comment
  6689. ********************************************************************/
  6690. TWizComment::
  6691. TWizComment(
  6692. TWizard* pWizard
  6693. ) : MWizardProp( pWizard ),
  6694. _pLocDlg(NULL)
  6695. {
  6696. }
  6697. TWizComment::
  6698. ~TWizComment(
  6699. VOID
  6700. )
  6701. {
  6702. delete _pLocDlg;
  6703. }
  6704. BOOL
  6705. TWizComment::
  6706. bHandle_InitDialog(
  6707. VOID
  6708. )
  6709. {
  6710. // subclass the edit control to workaround a bug
  6711. if( !m_wndComment.IsAttached() )
  6712. {
  6713. VERIFY(m_wndComment.Attach(GetDlgItem(hDlg(), IDC_WIZ_COMMENT)));
  6714. }
  6715. TDirectoryService ds;
  6716. TStatusB bStatus;
  6717. //
  6718. // Set resonable limits on the comment and location edit controls.
  6719. //
  6720. SendDlgItemMessage( _hDlg, IDC_WIZ_LOCATION, EM_SETLIMITTEXT, kPrinterLocationBufMax, 0 );
  6721. SendDlgItemMessage( _hDlg, IDC_WIZ_COMMENT, EM_SETLIMITTEXT, kPrinterCommentBufMax, 0 );
  6722. _pLocDlg = new TFindLocDlg;
  6723. bStatus DBGCHK = VALID_PTR(_pLocDlg);
  6724. if (bStatus)
  6725. {
  6726. bStatus DBGCHK = ds.bValid();
  6727. if (bStatus)
  6728. {
  6729. bStatus DBGCHK = ds.bIsDsAvailable();
  6730. //
  6731. // If the DS is not available or the location policy is disabled then
  6732. // remove the location UI.
  6733. //
  6734. if (!bStatus || !TPhysicalLocation::bLocationEnabled())
  6735. {
  6736. //
  6737. // If no DS is available, hide the Browse button and extend the location
  6738. // edit control appropriately
  6739. //
  6740. RECT rcComment;
  6741. RECT rcLocation;
  6742. HWND hLoc;
  6743. hLoc = GetDlgItem (_hDlg, IDC_WIZ_LOCATION);
  6744. GetWindowRect (GetDlgItem (_hDlg, IDC_WIZ_COMMENT), &rcComment);
  6745. GetWindowRect (hLoc, &rcLocation);
  6746. SetWindowPos (hLoc,
  6747. NULL,
  6748. 0,0,
  6749. rcComment.right-rcComment.left,
  6750. rcLocation.bottom-rcLocation.top,
  6751. SWP_NOMOVE|SWP_NOZORDER);
  6752. //
  6753. // Remove the location button.
  6754. //
  6755. ShowWindow (GetDlgItem (_hDlg, IDC_WIZ_BROWSE_LOCATION), SW_HIDE);
  6756. }
  6757. }
  6758. }
  6759. return TRUE;
  6760. }
  6761. BOOL
  6762. TWizComment::
  6763. bHandle_WizNext(
  6764. VOID
  6765. )
  6766. {
  6767. TStatusB bStatus;
  6768. UINT uLen;
  6769. bStatus DBGCHK = bGetEditText( _hDlg, IDC_WIZ_LOCATION, _pWizard->_strLocation );
  6770. TPhysicalLocation::vTrimSlash (_pWizard->_strLocation);
  6771. bStatus DBGCHK = bGetEditText( _hDlg, IDC_WIZ_COMMENT, _pWizard->_strComment );
  6772. return TRUE;
  6773. }
  6774. BOOL
  6775. TWizComment::
  6776. bHandle_Command(
  6777. IN WORD wId,
  6778. IN WORD wNotifyId,
  6779. IN HWND hwnd
  6780. )
  6781. {
  6782. TString strLocation;
  6783. TStatusB bStatus;
  6784. bStatus DBGNOCHK = TRUE;
  6785. switch (wId)
  6786. {
  6787. case IDC_WIZ_BROWSE_LOCATION:
  6788. {
  6789. //
  6790. // Get the current edit control contents.
  6791. //
  6792. bStatus DBGCHK = bGetEditText (_hDlg, IDC_WIZ_LOCATION, strLocation);
  6793. //
  6794. // Display the location tree to the user.
  6795. //
  6796. bStatus DBGCHK = _pLocDlg->bDoModal(_hDlg, &strLocation);
  6797. //
  6798. // If the user click ok, then populate location edit control with
  6799. // the users selection, along with a trailing slash.
  6800. //
  6801. if (bStatus)
  6802. {
  6803. bStatus DBGCHK = _pLocDlg->bGetLocation (strLocation);
  6804. if (bStatus && !strLocation.bEmpty())
  6805. {
  6806. //
  6807. // Check to append a trailing slash
  6808. //
  6809. UINT uLen = strLocation.uLen();
  6810. if( uLen && gchSeparator != static_cast<LPCTSTR>(strLocation)[uLen-1] )
  6811. {
  6812. static const TCHAR szSepStr[] = { gchSeparator };
  6813. bStatus DBGCHK = strLocation.bCat( szSepStr );
  6814. }
  6815. bStatus DBGCHK = _pWizard->_strLocation.bUpdate( strLocation );
  6816. bStatus DBGCHK = bSetEditText ( _hDlg, IDC_WIZ_LOCATION, _pWizard->_strLocation );
  6817. }
  6818. //
  6819. // Set focus to the edit control for location
  6820. //
  6821. SetFocus (GetDlgItem (_hDlg, IDC_WIZ_LOCATION));
  6822. //
  6823. // Place the caret at the end of the text, for appending
  6824. //
  6825. SendDlgItemMessage (_hDlg, IDC_WIZ_LOCATION, EM_SETSEL, _pWizard->_strLocation.uLen(), (LPARAM)-1);
  6826. }
  6827. break;
  6828. }
  6829. default:
  6830. {
  6831. bStatus DBGNOCHK = FALSE;
  6832. break;
  6833. }
  6834. }
  6835. return bStatus;
  6836. }
  6837. /********************************************************************
  6838. Network install dialog.
  6839. ********************************************************************/
  6840. TWizNet::
  6841. TWizNet(
  6842. TWizard* pWizard
  6843. ) : MWizardProp( pWizard )
  6844. {
  6845. }
  6846. BOOL
  6847. TWizNet::
  6848. bHandle_InitDialog(
  6849. VOID
  6850. )
  6851. {
  6852. TStatusB bStatus;
  6853. //
  6854. // Get the default control state.
  6855. //
  6856. INT iValueId = _pWizard->bSetDefault() ? IDC_RADIO_YES : IDC_RADIO_NO;
  6857. //
  6858. // By default, don't make it the default printer.
  6859. //
  6860. bStatus DBGCHK = CheckRadioButton( _hDlg, IDC_RADIO_YES, IDC_RADIO_NO, iValueId );
  6861. //
  6862. // Set cancel to close, since the printer connection can't
  6863. // be undone at this point. (We could try just deleting the
  6864. // connection, but this doesn't undo the driver downloads, etc.
  6865. //
  6866. PropSheet_CancelToClose( GetParent( _hDlg ) );
  6867. return TRUE;
  6868. }
  6869. BOOL
  6870. TWizNet::
  6871. bHandle_WizNext(
  6872. VOID
  6873. )
  6874. {
  6875. //
  6876. // Get default printer selection.
  6877. //
  6878. _pWizard->_bSetDefault = ( IsDlgButtonChecked( _hDlg, IDC_RADIO_YES ) == BST_CHECKED );
  6879. return TRUE;
  6880. }
  6881. /********************************************************************
  6882. Locate printer wizard page.
  6883. ********************************************************************/
  6884. TWizLocate::
  6885. TWizLocate(
  6886. TWizard* pWizard
  6887. ) : MWizardProp( pWizard )
  6888. {
  6889. }
  6890. BOOL
  6891. TWizLocate::
  6892. bHandle_InitDialog(
  6893. VOID
  6894. )
  6895. {
  6896. TStatusB bStatus;
  6897. bStatus DBGCHK = TRUE;
  6898. if( _pWizard->bAdminPrivilege() && _pWizard->strPrintersPageURL().uLen() )
  6899. {
  6900. //
  6901. // Show browse for printer URL button,
  6902. // note this depends on a policy settings.
  6903. //
  6904. ShowWindow( GetDlgItem( _hDlg, IDC_BROWSELINK_BTN ), SW_SHOW );
  6905. }
  6906. //
  6907. // Enable URL browse if the current user has an administrative
  6908. // priviledge only
  6909. //
  6910. EnableWindow( GetDlgItem( _hDlg, IDC_URL_BROWSE ), _pWizard->bAdminPrivilege() );
  6911. EnableWindow( GetDlgItem( _hDlg, IDC_BROWSELINK_BTN ), _pWizard->bAdminPrivilege() );
  6912. if( TWizard::kDsStatusAvailable == _pWizard->eIsDsAvailablePerUser() )
  6913. {
  6914. //
  6915. // DS available case - change the browse text appropriately
  6916. //
  6917. TString strText;
  6918. bStatus DBGCHK = strText.bLoadString( ghInst, IDS_DS_SEARCH_DIR_NAME );
  6919. SetWindowText(GetDlgItem( _hDlg, IDC_DS_SEARCH ), strText );
  6920. }
  6921. else
  6922. {
  6923. //
  6924. // NON-DS case - check to see is downlevel browsing is enabled at all
  6925. //
  6926. if( !_pWizard->bDownlevelBrowse() )
  6927. {
  6928. //
  6929. // There is no Directory Service installed and downlevel
  6930. // browse is not enabled....
  6931. //
  6932. // make the "connect to..." the default option
  6933. _pWizard->_LocateType = TWizard::kBrowseNET;
  6934. // hide & disable the search DS/browse radio button
  6935. ShowWindow( GetDlgItem( _hDlg, IDC_DS_SEARCH ), SW_HIDE );
  6936. EnableWindow( GetDlgItem( _hDlg, IDC_DS_SEARCH ), FALSE );
  6937. }
  6938. }
  6939. if( !_pWizard->bDownlevelBrowse() )
  6940. {
  6941. TString strText;
  6942. // if downlevel browse policy is not enabled then
  6943. // change the text of the "connect to..." not to imply browsing
  6944. bStatus DBGCHK = strText.bLoadString( ghInst, IDS_APW_TEXT_CONNECT_TO_THIS_PRINTER );
  6945. SetWindowText(GetDlgItem( _hDlg, IDC_NET_BROWSE ), strText );
  6946. }
  6947. if( _pWizard->COM() )
  6948. {
  6949. //
  6950. // Enable autocomplete for the printer share/name
  6951. //
  6952. ShellServices::InitPrintersAutoComplete(GetDlgItem(_hDlg, IDC_CONNECT_TO_NET));
  6953. }
  6954. return bStatus;
  6955. }
  6956. BOOL
  6957. TWizLocate::
  6958. bHandle_SetActive(
  6959. VOID
  6960. )
  6961. {
  6962. //
  6963. // Setup a radio table for fast lookup
  6964. //
  6965. static INT radioTable[] =
  6966. { IDC_DS_SEARCH, IDC_NET_BROWSE, IDC_URL_BROWSE };
  6967. //
  6968. // Set the default setting.
  6969. //
  6970. TStatusB bStatus;
  6971. bStatus DBGCHK = CheckRadioButton( _hDlg,
  6972. radioTable[0], radioTable[COUNTOF(radioTable)-1],
  6973. radioTable[ _pWizard->_LocateType ] );
  6974. //
  6975. // Set the initial control enable state.
  6976. //
  6977. PostMessage( _hDlg, WM_COMMAND,
  6978. radioTable[ _pWizard->_LocateType ], 0 );
  6979. return TRUE;
  6980. }
  6981. BOOL
  6982. TWizLocate::
  6983. Handle_ConnectToPrinterName(
  6984. VOID
  6985. )
  6986. {
  6987. LPCTSTR lpszNameOrURL = _strConnectToNET;
  6988. if( TWizard::kBrowseURL == _pWizard->_LocateType )
  6989. lpszNameOrURL = _strConnectToURL;
  6990. //
  6991. // Eat the white spaces, in front of the string
  6992. //
  6993. while( lpszNameOrURL && lpszNameOrURL[0] && TEXT(' ') == lpszNameOrURL[0] )
  6994. {
  6995. lpszNameOrURL++;
  6996. }
  6997. //
  6998. // If the edit contol blank warn the user and do not switch the page.
  6999. //
  7000. if( 0 == lstrlen(lpszNameOrURL) )
  7001. {
  7002. UINT uErrID = IDS_ERR_MISSING_PRINTER_NAME;
  7003. if( TWizard::kBrowseURL == _pWizard->_LocateType )
  7004. uErrID = IDS_ERR_MISSING_PRINTER_URL;
  7005. iMessage( _hDlg,
  7006. IDS_ERR_ADD_PRINTER_TITLE,
  7007. uErrID,
  7008. MB_OK|MB_ICONHAND,
  7009. kMsgNone,
  7010. NULL );
  7011. //
  7012. // Printer name was not entered. Do not switch pages.
  7013. //
  7014. _pWizard->bNoPageChange() = TRUE;
  7015. }
  7016. else
  7017. {
  7018. TWaitCursor Cur;
  7019. TStatusB bStatus;
  7020. //
  7021. // Add the printer connection.
  7022. //
  7023. bStatus DBGCHK = PrintUIAddPrinterConnectionUIEx( _hDlg,
  7024. lpszNameOrURL,
  7025. &_pWizard->_strPrinterName,
  7026. &_pWizard->_strComment,
  7027. &_pWizard->_strLocation,
  7028. &_pWizard->_strShareName );
  7029. if( bStatus )
  7030. {
  7031. //
  7032. // Indicate a printer connection has been made.
  7033. //
  7034. _pWizard->bConnected() = TRUE;
  7035. //
  7036. // Check for any default printer.
  7037. //
  7038. if( !_pWizard->bIsPrinterFolderEmpty() )
  7039. {
  7040. //
  7041. // Always set it as the default.
  7042. //
  7043. _pWizard->bSetDefault() = TRUE;
  7044. //
  7045. // Don't show the set as default UI.
  7046. //
  7047. _pWizard->bShowSetDefault() = FALSE;
  7048. }
  7049. }
  7050. else
  7051. {
  7052. //
  7053. // An error occurred adding the printer connection do not
  7054. // switch the page on error. Note we do not display an error
  7055. // message if something failed add printer connection will display
  7056. // an error if one does happens.
  7057. //
  7058. _pWizard->bNoPageChange() = TRUE;
  7059. }
  7060. }
  7061. return TRUE;
  7062. }
  7063. BOOL
  7064. TWizLocate::
  7065. Handle_URLBrowseClick(
  7066. VOID
  7067. )
  7068. {
  7069. ShellExecute( NULL, _T("open"), _pWizard->strPrintersPageURL(), NULL, NULL, SW_SHOWDEFAULT );
  7070. PropSheet_PressButton( GetParent( _hDlg ), PSBTN_CANCEL );
  7071. return TRUE;
  7072. }
  7073. VOID
  7074. TWizLocate::
  7075. vReadUI(
  7076. VOID
  7077. )
  7078. {
  7079. TStatusB bStatus;
  7080. //
  7081. // Read the LocateType first
  7082. //
  7083. _pWizard->_LocateType = TWizard::kSearch;
  7084. if( IsDlgButtonChecked( _hDlg, IDC_NET_BROWSE ) )
  7085. _pWizard->_LocateType = TWizard::kBrowseNET;
  7086. if( IsDlgButtonChecked( _hDlg, IDC_URL_BROWSE ) )
  7087. _pWizard->_LocateType = TWizard::kBrowseURL;
  7088. //
  7089. // get the URL of the printer
  7090. //
  7091. bStatus DBGCHK = bGetEditText( _hDlg, IDC_CONNECT_TO_URL, _strConnectToURL );
  7092. //
  7093. // get the network name of the printer
  7094. //
  7095. bStatus DBGCHK = bGetEditText( _hDlg, IDC_CONNECT_TO_NET, _strConnectToNET );
  7096. //
  7097. // Stip trailing white spaces from the names.
  7098. //
  7099. vStripTrailWhiteSpace( const_cast<LPTSTR>( static_cast<LPCTSTR>( _strConnectToURL ) ) );
  7100. vStripTrailWhiteSpace( const_cast<LPTSTR>( static_cast<LPCTSTR>( _strConnectToNET ) ) );
  7101. }
  7102. VOID
  7103. TWizLocate::
  7104. vSearch(
  7105. VOID
  7106. )
  7107. {
  7108. TStatusB bStatus;
  7109. TQuery Query( _hDlg );
  7110. TString strPrinterName;
  7111. INT iMessageId = IDS_ERR_ADD_PRINTER_CONNECTION;
  7112. BOOL bErrorMessageAlreadyDisplayed = FALSE;
  7113. //
  7114. // Validate the query class.
  7115. //
  7116. bStatus DBGCHK = VALID_OBJ( Query );
  7117. if( bStatus )
  7118. {
  7119. //
  7120. // Show waiting cursor when building printer connections.
  7121. //
  7122. TWaitCursor Cur;
  7123. //
  7124. // Display the query dialog.
  7125. //
  7126. (VOID)Query.bDoQuery();
  7127. //
  7128. // For all printers selected in the results pane install the
  7129. // selected printer.
  7130. //
  7131. for( UINT i = 0; i < Query.cItems(); i++ )
  7132. {
  7133. DBGMSG( DBG_TRACE, ( "cItems %d\n", Query.cItems() ) );
  7134. DBGMSG( DBG_TRACE, ( "Name " TSTR "\n", (LPCTSTR)(Query._pItems[i]._strName) ) );
  7135. DBGMSG( DBG_TRACE, ( "Class " TSTR "\n", (LPCTSTR)(Query._pItems[i]._strClass) ) );
  7136. //
  7137. // We want to only install printer selected devices.
  7138. //
  7139. if( Query.pItems()[i].strClass() == gszDsPrinterClassName )
  7140. {
  7141. //
  7142. // Get the printer name from the DS name.
  7143. //
  7144. bStatus DBGCHK = Query.bPrinterName( strPrinterName, Query.pItems()[i].strName() );
  7145. if( bStatus )
  7146. {
  7147. TString strRealPrinterName;
  7148. //
  7149. // Install network printer connection.
  7150. //
  7151. bStatus DBGCHK = PrintUIAddPrinterConnectionUIEx( _hDlg,
  7152. strPrinterName,
  7153. &strRealPrinterName,
  7154. &_pWizard->_strComment,
  7155. &_pWizard->_strLocation,
  7156. &_pWizard->_strShareName );
  7157. if( bStatus )
  7158. {
  7159. //
  7160. // If only one item was selected then we will set the
  7161. // default printer so get the real printer name because
  7162. // the user may have connected using the printer share name.
  7163. //
  7164. if( Query.cItems() == 1 && bStatus )
  7165. {
  7166. bStatus DBGCHK = strPrinterName.bUpdate( strRealPrinterName );
  7167. }
  7168. }
  7169. else
  7170. {
  7171. bErrorMessageAlreadyDisplayed = TRUE;
  7172. _pWizard->bNoPageChange() = TRUE;
  7173. break;
  7174. }
  7175. }
  7176. }
  7177. else
  7178. {
  7179. iMessageId = IDS_ERR_ADD_ONLY_PRINTERS;
  7180. bStatus DBGCHK = FALSE;
  7181. break;
  7182. }
  7183. }
  7184. }
  7185. //
  7186. // If a printer was installed successfully
  7187. //
  7188. if( bStatus )
  7189. {
  7190. //
  7191. // If no items were selected stay on this page, if the user
  7192. // want to exit they will have to hit the cancel button.
  7193. //
  7194. if( Query.cItems() == 0 )
  7195. {
  7196. //
  7197. // Do not switch away from this page.
  7198. //
  7199. _pWizard->bNoPageChange() = TRUE;
  7200. }
  7201. else
  7202. {
  7203. //
  7204. // Check for a default printer.
  7205. //
  7206. if( !_pWizard->bIsPrinterFolderEmpty() )
  7207. {
  7208. //
  7209. // Always set it as the default, skip the set as default page.
  7210. //
  7211. _pWizard->bSetDefault() = TRUE;
  7212. //
  7213. // Don't show the set as default UI.
  7214. //
  7215. _pWizard->bShowSetDefault() = FALSE;
  7216. }
  7217. //
  7218. // If more then one item was selected and the default printer
  7219. // has already been set, don't prompt for setting the default
  7220. // printer.
  7221. //
  7222. if( Query.cItems() > 1 && _pWizard->bSetDefault() == FALSE )
  7223. {
  7224. //
  7225. // Don't show the set as default UI.
  7226. //
  7227. _pWizard->bShowSetDefault() = FALSE;
  7228. //
  7229. // Indicate no printer connection was made to prevent setting
  7230. // the default printer, at wizard termination.
  7231. //
  7232. _pWizard->bConnected() = FALSE;
  7233. }
  7234. else
  7235. {
  7236. //
  7237. // Indicate a printer connection has been made.
  7238. //
  7239. _pWizard->bConnected() = TRUE;
  7240. //
  7241. // Set the printer name. This is need to set the default
  7242. // printer when the wizard terminates.
  7243. //
  7244. bStatus DBGCHK = _pWizard->strPrinterName().bUpdate( strPrinterName );
  7245. }
  7246. }
  7247. }
  7248. if( !bStatus )
  7249. {
  7250. if( !bErrorMessageAlreadyDisplayed )
  7251. {
  7252. //
  7253. // Something failed display an error message.
  7254. //
  7255. iMessage( _hDlg,
  7256. IDS_ERR_ADD_PRINTER_TITLE,
  7257. iMessageId,
  7258. MB_OK|MB_ICONHAND,
  7259. iMessageId == IDS_ERR_ADD_PRINTER_CONNECTION ? kMsgGetLastError : kMsgNone,
  7260. NULL );
  7261. }
  7262. //
  7263. // Do not switch away from this page.
  7264. //
  7265. _pWizard->bNoPageChange() = TRUE;
  7266. }
  7267. }
  7268. BOOL
  7269. TWizLocate::
  7270. bHandle_WizNext(
  7271. VOID
  7272. )
  7273. {
  7274. //
  7275. // Assume success
  7276. //
  7277. BOOL bResult = TRUE;
  7278. //
  7279. // Read the edit control.
  7280. //
  7281. vReadUI();
  7282. switch( _pWizard->_LocateType )
  7283. {
  7284. case TWizard::kSearch:
  7285. {
  7286. if( TWizard::kDsStatusAvailable == _pWizard->eIsDsAvailablePerUser() )
  7287. {
  7288. //
  7289. // If DS is avilable then let the user to search for a printer.
  7290. // otherwise just skip to the next page.
  7291. //
  7292. vSearch();
  7293. }
  7294. }
  7295. break;
  7296. case TWizard::kBrowseNET:
  7297. if( !_pWizard->bDownlevelBrowse() || strConnectToNET().uLen() )
  7298. {
  7299. //
  7300. // If downlevel browsing is not enabled then we enforce
  7301. // connection here. otherwise just skip to the browse page.
  7302. //
  7303. bResult = Handle_ConnectToPrinterName();
  7304. }
  7305. break;
  7306. case TWizard::kBrowseURL:
  7307. {
  7308. //
  7309. // Try to connect to the specified network name
  7310. //
  7311. bResult = Handle_ConnectToPrinterName();
  7312. }
  7313. break;
  7314. }
  7315. return bResult;
  7316. }
  7317. BOOL
  7318. TWizLocate::
  7319. bHandle_WizBack(
  7320. VOID
  7321. )
  7322. {
  7323. //
  7324. // Read the edit controls.
  7325. //
  7326. vReadUI();
  7327. return TRUE;
  7328. }
  7329. BOOL
  7330. TWizLocate::
  7331. bHandle_Command(
  7332. IN WORD wId,
  7333. IN WORD wNotifyId,
  7334. IN HWND hwnd
  7335. )
  7336. {
  7337. BOOL bStatus = TRUE;
  7338. switch( wId )
  7339. {
  7340. case IDC_DS_SEARCH:
  7341. case IDC_NET_BROWSE:
  7342. case IDC_URL_BROWSE:
  7343. {
  7344. //
  7345. // Check to enable/disable controls depending
  7346. // on connect type selection
  7347. //
  7348. EnableWindow( GetDlgItem( _hDlg, IDC_CONNECT_TO_URL ), wId == IDC_URL_BROWSE );
  7349. EnableWindow( GetDlgItem( _hDlg, IDC_CONNECT_TO_NET ), wId == IDC_NET_BROWSE );
  7350. //
  7351. // Setup the focus to the apropriate edit control
  7352. //
  7353. if( wId == IDC_URL_BROWSE )
  7354. {
  7355. SetFocus( GetDlgItem( _hDlg, IDC_CONNECT_TO_URL ) );
  7356. }
  7357. if( wId == IDC_NET_BROWSE )
  7358. {
  7359. SetFocus( GetDlgItem( _hDlg, IDC_CONNECT_TO_NET ) );
  7360. }
  7361. }
  7362. break;
  7363. default:
  7364. bStatus = FALSE;
  7365. break;
  7366. }
  7367. return bStatus;
  7368. }
  7369. BOOL
  7370. TWizLocate::
  7371. bHandle_Notify(
  7372. IN WPARAM wIdCtrl,
  7373. IN LPNMHDR pnmh
  7374. )
  7375. {
  7376. BOOL bStatus = FALSE;
  7377. switch( pnmh->code )
  7378. {
  7379. case NM_RETURN:
  7380. case NM_CLICK:
  7381. if( IDC_BROWSELINK_BTN == wIdCtrl )
  7382. {
  7383. bStatus = Handle_URLBrowseClick( );
  7384. }
  7385. break;
  7386. }
  7387. return bStatus;
  7388. }
  7389. /********************************************************************
  7390. Test page.
  7391. ********************************************************************/
  7392. TWizTestPage::
  7393. TWizTestPage(
  7394. TWizard* pWizard
  7395. ) : MWizardProp( pWizard )
  7396. {
  7397. }
  7398. BOOL
  7399. TWizTestPage::
  7400. bHandle_InitDialog(
  7401. VOID
  7402. )
  7403. {
  7404. TStatusB bStatus;
  7405. //
  7406. // Set the test page setting.
  7407. //
  7408. INT iValueId = _pWizard->bTestPage() ? IDC_RADIO_YES : IDC_RADIO_NO;
  7409. //
  7410. // By default, don't make it the default printer.
  7411. //
  7412. bStatus DBGCHK = CheckRadioButton( _hDlg,
  7413. IDC_RADIO_YES,
  7414. IDC_RADIO_NO,
  7415. iValueId );
  7416. //
  7417. // Set the additional driver check state.
  7418. //
  7419. vSetCheck( _hDlg, IDC_ADDITIONAL_DRIVERS, _pWizard->_bAdditionalDrivers );
  7420. return TRUE;
  7421. }
  7422. BOOL
  7423. TWizTestPage::
  7424. bHandle_SetActive(
  7425. VOID
  7426. )
  7427. {
  7428. UINT uFlags = SW_HIDE;
  7429. //
  7430. // If we are to add additional drivers and not the existing driver and not using 'HaveDisk'.
  7431. //
  7432. if( _pWizard->_dwAdditionalDrivers != -1 && _pWizard->_bUseNewDriver && !_pWizard->_Di.bIsOemDriver() )
  7433. {
  7434. uFlags = SW_NORMAL;
  7435. }
  7436. //
  7437. // Set the control states.
  7438. //
  7439. ShowWindow( GetDlgItem( _hDlg, IDC_ADDITIONAL_DRIVERS_TEXT ), uFlags );
  7440. ShowWindow( GetDlgItem( _hDlg, IDC_ADDITIONAL_DRIVERS ), uFlags );
  7441. return TRUE;
  7442. }
  7443. VOID
  7444. TWizTestPage::
  7445. vReadUI(
  7446. VOID
  7447. )
  7448. {
  7449. //
  7450. // Read the test page setting from the ui.
  7451. //
  7452. if( IsDlgButtonChecked( _hDlg, IDC_RADIO_YES ) == BST_CHECKED )
  7453. {
  7454. _pWizard->_bTestPage = TRUE;
  7455. }
  7456. else
  7457. {
  7458. _pWizard->_bTestPage = FALSE;
  7459. }
  7460. //
  7461. // Read the additional drivers from the check box control.
  7462. //
  7463. if( _pWizard->_dwAdditionalDrivers != -1 && _pWizard->_bUseNewDriver )
  7464. {
  7465. _pWizard->_bAdditionalDrivers = bGetCheck( _hDlg, IDC_ADDITIONAL_DRIVERS );
  7466. }
  7467. }
  7468. BOOL
  7469. TWizTestPage::
  7470. bHandle_WizNext(
  7471. VOID
  7472. )
  7473. {
  7474. vReadUI();
  7475. return TRUE;
  7476. }
  7477. /********************************************************************
  7478. Driver introduction page.
  7479. ********************************************************************/
  7480. TWizDriverIntro::
  7481. TWizDriverIntro(
  7482. TWizard* pWizard
  7483. ) : MWizardProp( pWizard )
  7484. {
  7485. }
  7486. BOOL
  7487. TWizDriverIntro::
  7488. bHandle_InitDialog(
  7489. VOID
  7490. )
  7491. {
  7492. TString strTemp;
  7493. TCHAR szServerName[kDNSMax + 1];
  7494. //
  7495. // The fonts for the Word 97 wizard style.
  7496. //
  7497. SetControlFont( _pWizard->_hBigBoldFont, _hDlg, IDC_MAIN_TITLE );
  7498. //
  7499. // If we are admining a remote server, we'll change the title and text.
  7500. // And we need to check the priviledge to add printer on remote server.
  7501. //
  7502. if( bIsRemote( _pWizard->pszServerName() ) )
  7503. {
  7504. //
  7505. // Remove "\\" from the server name, and change the server name
  7506. // to lower case
  7507. //
  7508. lstrcpy( szServerName, (LPTSTR)_pWizard->pszServerName() + 2 );
  7509. CharLower( szServerName );
  7510. //
  7511. // Change "Add Printer Driver Wizard" to "Add Printer Driver Wizard on '%s.'"
  7512. //
  7513. strTemp.bLoadString( ghInst, IDS_ADD_DRIVER_TITLE_REMOTE );
  7514. _pWizard->_strTitle.bFormat( strTemp, szServerName );
  7515. PropSheet_SetTitle( GetParent( _hDlg ), 0, _pWizard->_strTitle );
  7516. //
  7517. // change the test for intro to fit remote APDW
  7518. //
  7519. strTemp.bLoadString( ghInst, IDS_ADD_DRIVER_INTRO_REMOTE );
  7520. strTemp.bFormat( strTemp, szServerName );
  7521. bSetEditText( _hDlg, IDC_MAIN_TITLE, strTemp );
  7522. }
  7523. if( _pWizard->_bSkipArchSelection )
  7524. {
  7525. TString strTitle;
  7526. if( strTitle.bLoadString( ghInst, IDS_DRIVER_INTRO_TEXT ) )
  7527. {
  7528. SetWindowText( GetDlgItem( _hDlg, IDC_DRIVER_INTRO_TEXT1 ), (LPCTSTR)strTitle );
  7529. }
  7530. ShowWindow( GetDlgItem( _hDlg, IDC_DRIVER_INTRO_TEXT2 ), SW_HIDE );
  7531. }
  7532. //
  7533. // Let the wizard to initialize itself.
  7534. //
  7535. _pWizard->OnWizardInitro( hDlg() );
  7536. return TRUE;
  7537. }
  7538. BOOL
  7539. TWizDriverIntro::
  7540. bHandle_SetActive(
  7541. VOID
  7542. )
  7543. {
  7544. PropSheet_SetTitle( GetParent( _hDlg ), PSH_DEFAULT, _pWizard->_strTitle );
  7545. return TRUE;
  7546. }
  7547. /********************************************************************
  7548. Architecture page.
  7549. ********************************************************************/
  7550. TWizArchitecture::
  7551. TWizArchitecture(
  7552. TWizard* pWizard
  7553. ) : MWizardProp( pWizard )
  7554. {
  7555. }
  7556. BOOL
  7557. TWizArchitecture::
  7558. bHandle_InitDialog(
  7559. VOID
  7560. )
  7561. {
  7562. TStatusB bStatus;
  7563. //
  7564. // Set the architecture list view UI.
  7565. //
  7566. bStatus DBGCHK = _pWizard->ArchLV().bSetUI( _hDlg );
  7567. return TRUE;
  7568. }
  7569. BOOL
  7570. TWizArchitecture::
  7571. bHandle_WizNext(
  7572. VOID
  7573. )
  7574. {
  7575. TStatusB bStatus;
  7576. BOOL bInstalled = FALSE;
  7577. DWORD dwEncode = 0;
  7578. UINT uNotInstalledItemCount = 0;
  7579. //
  7580. // Get the selected item count.
  7581. //
  7582. UINT cSelectedCount = _pWizard->ArchLV().uGetCheckedItemCount();
  7583. //
  7584. // Fill the driver list view with the selected architectures from
  7585. // the architecture list view.
  7586. //
  7587. for( UINT i = 0; i < cSelectedCount; i++ )
  7588. {
  7589. bStatus DBGCHK = _pWizard->ArchLV().bGetCheckedItems( i, &bInstalled, &dwEncode );
  7590. if( bStatus )
  7591. {
  7592. if( !bInstalled )
  7593. {
  7594. uNotInstalledItemCount++;
  7595. }
  7596. }
  7597. }
  7598. //
  7599. // If a non installed item was not checked then warn the user.
  7600. //
  7601. if( !uNotInstalledItemCount )
  7602. {
  7603. //
  7604. // At least one version must be choosen to switch pages.
  7605. //
  7606. iMessage( _hDlg,
  7607. IDS_DRIVER_WIZ_TITLE,
  7608. IDS_ERR_ATLEAST_ONE_VERSION,
  7609. MB_OK|MB_ICONHAND,
  7610. kMsgNone,
  7611. NULL );
  7612. //
  7613. // Don't switch to the next page.
  7614. //
  7615. _pWizard->bNoPageChange() = TRUE;
  7616. }
  7617. return TRUE;
  7618. }
  7619. BOOL
  7620. TWizArchitecture::
  7621. bHandle_SetActive(
  7622. VOID
  7623. )
  7624. {
  7625. //
  7626. // Show the hour glass this can take a while
  7627. // when talking to a remote machine.
  7628. //
  7629. TWaitCursor Cursor;
  7630. //
  7631. // Parse the driver data.
  7632. //
  7633. if( _pWizard->bParseDriver( _hDlg ) )
  7634. {
  7635. //
  7636. // If the driver changed or a driver was installed
  7637. // then refresh the architecture list. Since the driver
  7638. // install count is always incrementing once a driver
  7639. // was installed we will always fresh the the architecture
  7640. // list. I supect this will happen seldom, but it could
  7641. // lead to slow page changes in the remote case. Since
  7642. // we hit the net to determine if the printer driver
  7643. // is installed.
  7644. //
  7645. if( _pWizard->bDriverChanged() == TRUE || _pWizard->_nDriverInstallCount )
  7646. {
  7647. _pWizard->bDriverChanged() = FALSE;
  7648. //
  7649. // Refresh the architecture list.
  7650. //
  7651. TStatusB bStatus;
  7652. bStatus DBGCHK = _pWizard->ArchLV().bRefreshListView( _pWizard->pszServerName(),
  7653. _pWizard->strDriverName() );
  7654. //
  7655. // Check the default architecture.
  7656. //
  7657. bStatus DBGCHK = _pWizard->ArchLV().bSetCheckDefaultArch( _pWizard->pszServerName() );
  7658. //
  7659. // Select the first item in the list view.
  7660. //
  7661. _pWizard->ArchLV().vSelectItem( 0 );
  7662. }
  7663. }
  7664. return TRUE;
  7665. }
  7666. BOOL
  7667. TWizArchitecture::
  7668. bHandle_Notify(
  7669. IN WPARAM wParam,
  7670. IN LPNMHDR pnmh
  7671. )
  7672. {
  7673. //
  7674. // Forward notify messages to the architecture list view.
  7675. //
  7676. return _pWizard->ArchLV().bHandleNotifyMessage( WM_NOTIFY, wParam, (LPARAM)pnmh );
  7677. }
  7678. /********************************************************************
  7679. Install driver end page.
  7680. ********************************************************************/
  7681. TWizDriverEnd::
  7682. TWizDriverEnd(
  7683. TWizard* pWizard
  7684. ) : MWizardProp( pWizard )
  7685. {
  7686. }
  7687. BOOL
  7688. TWizDriverEnd::
  7689. bHandle_InitDialog(
  7690. VOID
  7691. )
  7692. {
  7693. //
  7694. // The fonts for the Word 97 wizard style.
  7695. //
  7696. SetControlFont( _pWizard->_hBigBoldFont, _hDlg, IDC_MAIN_TITLE );
  7697. //
  7698. // check to see if the wizard is restartable and if so
  7699. // show the appropriate checkbox
  7700. //
  7701. if( _pWizard->bRestartableFromLastPage() )
  7702. {
  7703. _pWizard->bRestartAgain() = TRUE; // assume "On" by default
  7704. ShowWindow( GetDlgItem( _hDlg, IDC_RESTART_WIZARD ), SW_SHOW );
  7705. }
  7706. vSetCheck( _hDlg, IDC_RESTART_WIZARD, _pWizard->bRestartAgain() );
  7707. return TRUE;
  7708. }
  7709. BOOL
  7710. TWizDriverEnd::
  7711. bHandle_SetActive(
  7712. VOID
  7713. )
  7714. {
  7715. TStatusB bStatus;
  7716. //
  7717. // If the architecture page was skipped.
  7718. // We will add this platforms driver.
  7719. //
  7720. if( _pWizard->bSkipArchSelection() )
  7721. {
  7722. //
  7723. // Parse the selected inf file.
  7724. //
  7725. bStatus DBGCHK = _pWizard->bParseDriver( _hDlg );
  7726. }
  7727. else
  7728. {
  7729. bStatus DBGNOCHK = FALSE;
  7730. }
  7731. vDisplaySelectedDrivers();
  7732. return bStatus;
  7733. }
  7734. VOID
  7735. TWizDriverEnd::
  7736. vDisplaySelectedDrivers(
  7737. VOID
  7738. )
  7739. {
  7740. TStatusB bStatus;
  7741. TDriverInfo DriverInfo;
  7742. TString strResults;
  7743. BOOL bInstalled;
  7744. DWORD dwEncode;
  7745. TCHAR const cszFormat[] = TEXT("%s, %s, %s\r\n");
  7746. //
  7747. // If the architecture page was skipped.
  7748. // We will add this platforms driver.
  7749. //
  7750. if( _pWizard->bSkipArchSelection() )
  7751. {
  7752. //
  7753. // Get the current driver encode, this is then native driver.
  7754. //
  7755. bStatus DBGCHK = _pWizard->_Di.bGetCurrentDriverEncode( &dwEncode );
  7756. if( bStatus )
  7757. {
  7758. TString strEnvironment;
  7759. TString strVersion;
  7760. (VOID)TArchLV::bEncodeToArchAndVersion( dwEncode, strEnvironment, strVersion );
  7761. bStatus DBGCHK = strResults.bFormat( cszFormat,
  7762. static_cast<LPCTSTR>( _pWizard->strDriverName() ),
  7763. static_cast<LPCTSTR>( strEnvironment ),
  7764. static_cast<LPCTSTR>( strVersion ) );
  7765. }
  7766. }
  7767. else
  7768. {
  7769. //
  7770. // Get the selected item count.
  7771. //
  7772. UINT cSelectedCount = _pWizard->ArchLV().uGetCheckedItemCount();
  7773. //
  7774. // Display the results of the users selection.
  7775. //
  7776. for( UINT i = 0; i < cSelectedCount; i++ )
  7777. {
  7778. bStatus DBGCHK = _pWizard->ArchLV().bGetCheckedItems( i, &bInstalled, &dwEncode );
  7779. if( bStatus && !bInstalled )
  7780. {
  7781. TString strEnvironment;
  7782. TString strVersion;
  7783. (VOID)TArchLV::bEncodeToArchAndVersion( dwEncode, strEnvironment, strVersion );
  7784. TString strFmt;
  7785. bStatus DBGCHK = strFmt.bFormat( cszFormat,
  7786. static_cast<LPCTSTR>( _pWizard->strDriverName() ),
  7787. static_cast<LPCTSTR>( strEnvironment ),
  7788. static_cast<LPCTSTR>( strVersion ) );
  7789. if( bStatus )
  7790. {
  7791. bStatus DBGCHK = strResults.bCat( strFmt );
  7792. }
  7793. }
  7794. }
  7795. }
  7796. if( !strResults.bEmpty() )
  7797. {
  7798. bStatus DBGCHK = bSetEditText( _hDlg, IDC_DRIVER_SELECTION_SUMMARY, strResults );
  7799. }
  7800. }
  7801. BOOL
  7802. TWizDriverEnd::
  7803. bHandle_WizFinish(
  7804. VOID
  7805. )
  7806. {
  7807. DWORD dwEncode = static_cast<DWORD>(-1);
  7808. TStatusB bStatus;
  7809. _pWizard->bRestartAgain() = bGetCheck( _hDlg, IDC_RESTART_WIZARD );
  7810. //
  7811. // If the architecture page was skipped.
  7812. // We will add the native driver.
  7813. //
  7814. if( _pWizard->bSkipArchSelection() )
  7815. {
  7816. bStatus DBGCHK = bInstallNativeDriver( &dwEncode );
  7817. }
  7818. else
  7819. {
  7820. bStatus DBGCHK = bInstallSelectedDrivers( &dwEncode );
  7821. }
  7822. if( !bStatus )
  7823. {
  7824. switch( GetLastError() )
  7825. {
  7826. case ERROR_CANCELLED:
  7827. break;
  7828. case ERROR_UNKNOWN_PRINTER_DRIVER:
  7829. {
  7830. iMessage( _hDlg,
  7831. IDS_DRIVER_WIZ_TITLE,
  7832. IDS_ERROR_UNKNOWN_DRIVER,
  7833. MB_OK | MB_ICONSTOP,
  7834. kMsgNone,
  7835. NULL );
  7836. }
  7837. break;
  7838. default:
  7839. //
  7840. // in the case where bInstallSelectedDrivers fails there is no way to tell why it
  7841. // has failed and there is no guarantee that dwEncode will be set correctly to a valid
  7842. // arch/ver encoding. to avoid showing incorrect error messages and/or plain crashes we
  7843. // need to assign an invalid value and then check to see if it has been set correctly.
  7844. //
  7845. {
  7846. if( static_cast<DWORD>(-1) != dwEncode )
  7847. {
  7848. TString strEnvironment;
  7849. TString strVersion;
  7850. (VOID)TArchLV::bEncodeToArchAndVersion( dwEncode, strEnvironment, strVersion );
  7851. //
  7852. // An error occurred installing a printer driver.
  7853. //
  7854. iMessage( _hDlg,
  7855. IDS_DRIVER_WIZ_TITLE,
  7856. IDS_ERR_ALL_DRIVER_NOT_INSTALLED,
  7857. MB_OK|MB_ICONHAND,
  7858. kMsgGetLastError,
  7859. NULL,
  7860. static_cast<LPCTSTR>( _pWizard->strDriverName() ),
  7861. static_cast<LPCTSTR>( strVersion ),
  7862. static_cast<LPCTSTR>( strEnvironment ) );
  7863. }
  7864. else
  7865. {
  7866. //
  7867. // in this case we don't really know what happened, so just show a generic error message
  7868. //
  7869. iMessage( _hDlg,
  7870. IDS_DRIVER_WIZ_TITLE,
  7871. IDS_ERR_GENERIC,
  7872. MB_OK|MB_ICONHAND,
  7873. kMsgGetLastError,
  7874. NULL );
  7875. }
  7876. }
  7877. break;
  7878. }
  7879. //
  7880. // Don't switch to the next page.
  7881. //
  7882. _pWizard->bNoPageChange() = TRUE;
  7883. }
  7884. else
  7885. {
  7886. //
  7887. // bPrinterCreated flag is overloaded in the add printer driver
  7888. // wizard, it indicates that the driver was added successfully.
  7889. //
  7890. _pWizard->bPrinterCreated() = TRUE;
  7891. }
  7892. //
  7893. // Let the wizard cleanup here.
  7894. //
  7895. _pWizard->OnWizardFinish( _hDlg );
  7896. return bStatus;
  7897. }
  7898. BOOL
  7899. TWizDriverEnd::
  7900. bInstallNativeDriver(
  7901. OUT DWORD *pdwEncode
  7902. )
  7903. {
  7904. TStatusB bStatus;
  7905. //
  7906. // Get the current driver encode, this is then native driver.
  7907. //
  7908. bStatus DBGCHK = _pWizard->_Di.bGetCurrentDriverEncode( pdwEncode );
  7909. if( bStatus )
  7910. {
  7911. //
  7912. // Install the driver.
  7913. //
  7914. bStatus DBGCHK = bInstallDriver( _hDlg, *pdwEncode, _pWizard->_Di, FALSE, 0, &(_pWizard->strDriverName()) );
  7915. }
  7916. return bStatus;
  7917. }
  7918. BOOL
  7919. TWizDriverEnd::
  7920. bInstallSelectedDrivers(
  7921. OUT DWORD *pdwEncode
  7922. )
  7923. {
  7924. BOOL bInstalled;
  7925. TStatusB bStatus;
  7926. //
  7927. // Initialize the status return value.
  7928. //
  7929. bStatus DBGNOCHK = TRUE;
  7930. //
  7931. // Get the selected item count.
  7932. //
  7933. UINT cSelectedCount = _pWizard->ArchLV().uGetCheckedItemCount();
  7934. //
  7935. // Fill the driver list view with the selected architectures from
  7936. // the architecture list view.
  7937. //
  7938. for( UINT i = 0; i < cSelectedCount; i++ )
  7939. {
  7940. bStatus DBGCHK = _pWizard->ArchLV().bGetCheckedItems( i, &bInstalled, pdwEncode );
  7941. if( bStatus && !bInstalled )
  7942. {
  7943. bStatus DBGCHK = bInstallDriver( _hDlg, *pdwEncode, _pWizard->_Di, _pWizard->bUseWeb(), 0, &(_pWizard->strDriverName()) );
  7944. //
  7945. // If the installation was successful keep track of the number of
  7946. // drivers that were actually installed. This information is necceasary
  7947. // for determining if the drivers list view needs to be refreshed.
  7948. //
  7949. if( bStatus )
  7950. {
  7951. _pWizard->_nDriverInstallCount++;
  7952. }
  7953. //
  7954. // Exit the loop if any of the drivers fail to install.
  7955. //
  7956. if( !bStatus )
  7957. {
  7958. break;
  7959. }
  7960. }
  7961. }
  7962. return bStatus;
  7963. }
  7964. BOOL
  7965. TWizDriverEnd::
  7966. bInstallDriver(
  7967. IN HWND hwnd,
  7968. IN DWORD dwEncode,
  7969. IN TPrinterDriverInstallation &Di,
  7970. IN BOOL bFromWeb,
  7971. IN DWORD dwDriverFlags,
  7972. OUT TString *pstrDriverName
  7973. )
  7974. {
  7975. TStatusB bStatus;
  7976. //
  7977. // Get the current install flags.
  7978. //
  7979. DWORD dwPrevInstallFlags = Di.GetInstallFlags();
  7980. //
  7981. // We do not copy the inf for version 2 drivers.
  7982. //
  7983. if( GetDriverVersion( dwEncode ) == 2 )
  7984. {
  7985. //
  7986. // We don't copy the inf for version 2 drivers.
  7987. //
  7988. dwDriverFlags |= DRVINST_DONOTCOPY_INF;
  7989. }
  7990. //
  7991. // Set the install flags.
  7992. //
  7993. Di.SetInstallFlags( dwDriverFlags );
  7994. //
  7995. // Install the driver.
  7996. //
  7997. BOOL bOfferReplacementDriver = TRUE;
  7998. bStatus DBGCHK = Di.bInstallDriver(
  7999. pstrDriverName, bOfferReplacementDriver, bFromWeb, hwnd, dwEncode);
  8000. //
  8001. // Restore the previous install flags.
  8002. //
  8003. Di.SetInstallFlags( dwPrevInstallFlags );
  8004. return bStatus;
  8005. }
  8006. /********************************************************************
  8007. Pre select driver wizard page
  8008. ********************************************************************/
  8009. TWizPreSelectDriver::
  8010. TWizPreSelectDriver(
  8011. TWizard* pWizard
  8012. ) : MWizardProp( pWizard )
  8013. {
  8014. }
  8015. BOOL
  8016. TWizPreSelectDriver::
  8017. bHandle_SetActive(
  8018. VOID
  8019. )
  8020. {
  8021. //
  8022. // Toggle the direction flag.
  8023. //
  8024. _pWizard->bPreDir() = _pWizard->bPreDir() == FALSE ? TRUE : FALSE;
  8025. //
  8026. // Preselect the driver using the previous driver
  8027. // the user selected.
  8028. //
  8029. if( !_pWizard->strDriverName().bEmpty() )
  8030. {
  8031. TWaitCursor Cursor;
  8032. TStatusB bStatus;
  8033. bStatus DBGCHK = _pWizard->_Di.bSetDriverName( _pWizard->strDriverName() );
  8034. bStatus DBGCHK = _pWizard->_Di.bGetSelectedDriver( TRUE );
  8035. }
  8036. return TRUE;
  8037. }
  8038. /********************************************************************
  8039. Post select driver wizard page
  8040. ********************************************************************/
  8041. TWizPostSelectDriver::
  8042. TWizPostSelectDriver(
  8043. TWizard* pWizard
  8044. ) : MWizardProp( pWizard )
  8045. {
  8046. }
  8047. BOOL
  8048. TWizPostSelectDriver::
  8049. bHandle_SetActive(
  8050. VOID
  8051. )
  8052. {
  8053. if( _pWizard->uAction() == TWizard::kPnPInstall ||
  8054. _pWizard->uAction() == TWizard::kPrinterInstall ||
  8055. _pWizard->uAction() == TWizard::kPrinterInstallModeless )
  8056. {
  8057. //
  8058. // Parse the driver data.
  8059. //
  8060. if( _pWizard->bParseDriver( _hDlg ) )
  8061. {
  8062. //
  8063. // Check if the diriver exists.
  8064. //
  8065. _pWizard->bUseNewDriver() = _pWizard->bDriverExists() ? FALSE : TRUE;
  8066. }
  8067. }
  8068. //
  8069. // Toggle the direction flag.
  8070. //
  8071. _pWizard->bPostDir() = _pWizard->bPostDir() == FALSE ? TRUE : FALSE;
  8072. return TRUE;
  8073. }
  8074. BOOL
  8075. bFindPrinter(
  8076. IN HWND hwnd,
  8077. IN LPTSTR pszBuffer,
  8078. IN UINT *puSize
  8079. )
  8080. {
  8081. DBGMSG( DBG_TRACE, ( "bFindPrinter\n" ) );
  8082. SPLASSERT( pszBuffer );
  8083. SPLASSERT( puSize );
  8084. TStatusB bStatus;
  8085. TString strPrinterName;
  8086. TString strRealPrinterName;
  8087. TDirectoryService Ds;
  8088. if( Ds.bIsDsAvailable() )
  8089. {
  8090. //
  8091. // Create the query object.
  8092. //
  8093. TQuery Query( hwnd );
  8094. //
  8095. // Ensue the query object is valid.
  8096. //
  8097. bStatus DBGCHK = VALID_OBJ( Query );
  8098. if( bStatus )
  8099. {
  8100. //
  8101. // Display the ds printer query dialog.
  8102. //
  8103. bStatus DBGCHK = Query.bDoQuery();
  8104. //
  8105. // Show waiting cursor when building printer connections.
  8106. //
  8107. TWaitCursor Cur;
  8108. //
  8109. // For all printers selected in the results pane install the
  8110. // selected printer.
  8111. //
  8112. for( UINT i = 0; i < Query.cItems(); i++ )
  8113. {
  8114. DBGMSG( DBG_TRACE, ( "cItems %d\n", Query.cItems() ) );
  8115. DBGMSG( DBG_TRACE, ( "Name " TSTR "\n", (LPCTSTR)(Query._pItems[i]._strName) ) );
  8116. DBGMSG( DBG_TRACE, ( "Class " TSTR "\n", (LPCTSTR)(Query._pItems[i]._strClass) ) );
  8117. //
  8118. // We want to only install printer selected devices.
  8119. //
  8120. if( Query.pItems()[i].strClass() == gszDsPrinterClassName )
  8121. {
  8122. //
  8123. // Get the printer name from the DS name.
  8124. //
  8125. bStatus DBGCHK = Query.bPrinterName( strPrinterName, Query.pItems()[i].strName() );
  8126. if( bStatus )
  8127. {
  8128. //
  8129. // Install network printer connection.
  8130. //
  8131. bStatus DBGCHK = PrintUIAddPrinterConnectionUIEx( hwnd, strPrinterName, &strRealPrinterName );
  8132. if( bStatus && i == 1 )
  8133. {
  8134. bStatus DBGCHK = strPrinterName.bUpdate( strRealPrinterName );
  8135. }
  8136. }
  8137. }
  8138. }
  8139. }
  8140. }
  8141. else
  8142. {
  8143. //
  8144. // Allow a user to browse for a printer conneciton.
  8145. //
  8146. bStatus DBGCHK = TWizType::bConnectToPrinter( hwnd, strPrinterName );
  8147. }
  8148. //
  8149. // If everything succeeded and a printer was returned
  8150. // check if there is a default printer and if not set then
  8151. // set this printer as the default.
  8152. //
  8153. if( bStatus && !strPrinterName.bEmpty() )
  8154. {
  8155. if( pszBuffer )
  8156. {
  8157. if( *puSize > strPrinterName.uLen() )
  8158. {
  8159. //
  8160. // Copy the printer name to the supplied buffer if it fits.
  8161. //
  8162. _tcsncpy( pszBuffer, strPrinterName, *puSize );
  8163. }
  8164. else
  8165. {
  8166. *puSize = strPrinterName.uLen()+1;
  8167. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  8168. bStatus DBGNOCHK = FALSE;
  8169. }
  8170. }
  8171. if( bStatus )
  8172. {
  8173. //
  8174. // Set the default printer if there is no default printer.
  8175. //
  8176. TCHAR szPrinter[kPrinterBufMax] = {0};
  8177. DWORD dwSize = COUNTOF( szPrinter );
  8178. //
  8179. // Get the default printer.
  8180. //
  8181. bStatus DBGNOCHK = GetDefaultPrinter( szPrinter, &dwSize );
  8182. if( !bStatus )
  8183. {
  8184. bStatus DBGCHK = SetDefaultPrinter( strPrinterName );
  8185. }
  8186. }
  8187. }
  8188. return bStatus;
  8189. }