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

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