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

2454 lines
66 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. All rights reserved.
  4. Module Name:
  5. rundll.cxx
  6. Abstract:
  7. Run dll entry interface for lauching printer related
  8. UI from shell extenstion and other shell related components.
  9. Author:
  10. Steve Kiraly (SteveKi) 29-Sept-1996
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "rundll.hxx"
  16. #include "getopt.hxx"
  17. #include "parser.hxx"
  18. #include "permc.hxx"
  19. #include "asyncdlg.hxx"
  20. #include "tstpage.hxx"
  21. #include "time.hxx"
  22. #include "psetup.hxx"
  23. #include "drvsetup.hxx"
  24. #include "instarch.hxx"
  25. #include "portslv.hxx"
  26. #include "dsinterf.hxx"
  27. #include "prtprop.hxx"
  28. #include "prtshare.hxx"
  29. #include "dsinterf.hxx"
  30. #include "drvsetup.hxx"
  31. #include "driverif.hxx"
  32. #include "driverlv.hxx"
  33. #include "archlv.hxx"
  34. #include "detect.hxx"
  35. #include "setup.hxx"
  36. #include "spllibex.hxx"
  37. #include "spinterf.hxx"
  38. /*++
  39. Routine Name:
  40. PrintUIEntryW
  41. Routine Description:
  42. Interface for the Rundll32 process.
  43. Arguments:
  44. hwnd - Window handle of stub window.
  45. hInstance, - Rundll instance handle.
  46. pszCmdLine - Pointer to UNICOE command line.
  47. nCmdShow - Show command value always TRUE.
  48. Return Value:
  49. Nothing.
  50. --*/
  51. DWORD
  52. PrintUIEntryW(
  53. IN HWND hwnd,
  54. IN HINSTANCE hInstance,
  55. IN LPCTSTR pszCmdLine,
  56. IN UINT nCmdShow
  57. )
  58. {
  59. DBGMSG( DBG_TRACE, ( "PrintUIEntryW interface\n" ) );
  60. DBGMSG( DBG_TRACE, ( "hwnd %x\n", hwnd ) );
  61. DBGMSG( DBG_TRACE, ( "hInstance %x\n", hInstance ) );
  62. DBGMSG( DBG_TRACE, ( "pszCmdLine %ws\n", pszCmdLine ) );
  63. DBGMSG( DBG_TRACE, ( "nCmdShow %d\n", nCmdShow ) );
  64. DBGMSG( DBG_TRACE, ( "CommandLine %ws\n", GetCommandLine() ) );
  65. //
  66. // we need to count the error messages to see if necessary to
  67. // show up UI in case of an error or if somebody has been done
  68. // this already
  69. //
  70. CMsgBoxCounter msgCounter(MB_ICONSTOP|MB_ICONINFORMATION);
  71. UINT ac = 0;
  72. TCHAR **av = NULL;
  73. BOOL bRetval = FALSE;
  74. AParams Params = {0};
  75. //
  76. // Strip any trailing white space.
  77. //
  78. vStripTrailWhiteSpace( (LPTSTR)pszCmdLine );
  79. //
  80. // Convert the command line to an argv,
  81. //
  82. bRetval = StringToArgv( pszCmdLine, // Command line arguments
  83. &ac, // Place to return arg count
  84. &av, // Place to return argv
  85. FALSE ); // There is no file name on the command line
  86. if( bRetval )
  87. {
  88. //
  89. // Store pointer to command line.
  90. //
  91. Params.pszCmdLine = pszCmdLine;
  92. //
  93. // Parse the command line argumens and execute the command.
  94. //
  95. bRetval = bDoCommand( hwnd, ac, av, &Params );
  96. }
  97. if( !bRetval )
  98. {
  99. //
  100. // If we are not in quiet mode display error messsage.
  101. //
  102. if( !Params.Flags.IsQuiet && 0 == msgCounter.GetCount() )
  103. {
  104. switch( Params.dwLastError )
  105. {
  106. case ERROR_SUCCESS:
  107. case ERROR_CANCELLED:
  108. break;
  109. case ERROR_ACCESS_DENIED:
  110. {
  111. // show up a friendly message that conform the shell32.dll
  112. // message in this case. this is because this will be invoked
  113. // primarily from shell32.dll from the runas commands
  114. iMessage(NULL, IDS_PRINTERS_TITLE, IDS_FRIENDLY_ACCESSDENIED,
  115. MB_OK|MB_ICONINFORMATION, kMsgNone, NULL);
  116. }
  117. break;
  118. case ERROR_INVALID_PARAMETER:
  119. {
  120. // show up a friendly message to say that the arguments are invalid
  121. iMessage(NULL, IDS_PRINTERS_TITLE, IDS_ERROR_INVALID_ARG,
  122. MB_OK|MB_ICONSTOP, kMsgNone, NULL);
  123. }
  124. break;
  125. default:
  126. {
  127. // we are going to show a generic error message here
  128. iMessage(NULL, IDS_PRINTERS_TITLE, IDS_ERR_GENERIC,
  129. MB_OK|MB_ICONSTOP, Params.dwLastError, NULL);
  130. }
  131. break;
  132. }
  133. //
  134. // If the last error code was not set then set it to a generic
  135. // error value. We just chose one, ERROR_INVALID_FUNCTION
  136. //
  137. if( Params.dwLastError == ERROR_SUCCESS )
  138. {
  139. Params.dwLastError = GetLastError();
  140. if( Params.dwLastError == ERROR_SUCCESS )
  141. {
  142. Params.dwLastError = ERROR_INVALID_FUNCTION;
  143. }
  144. }
  145. }
  146. }
  147. //
  148. // Ensure we release the command line argv.
  149. //
  150. ReleaseArgv( av );
  151. //
  152. // If something failed and the error code was not set then set
  153. // the error to an unspecified error value.
  154. //
  155. if( !bRetval )
  156. {
  157. //
  158. // Set the last error incase the caller ignores the return value.
  159. //
  160. SetLastError( Params.dwLastError );
  161. }
  162. return Params.dwLastError;
  163. }
  164. /*++
  165. Routine Name:
  166. bDoCommand
  167. Routine Description:
  168. Parses the commmand line passed by rundll32.
  169. Arguments:
  170. hwnd - Parent window handle.
  171. ac - Number of strings.
  172. av - Pointer to an array of pointer to strings.
  173. Return Value:
  174. TRUE function complete ok. FALSE error occurred.
  175. --*/
  176. BOOL
  177. bDoCommand(
  178. IN HWND hwnd,
  179. IN INT ac,
  180. IN LPTSTR *av,
  181. IN AParams *pParams
  182. )
  183. {
  184. INT retval;
  185. LPTSTR options = TEXT("?KYUPHwuzZkyxqeospS:X:t:d:i:n:r:m:c:l:a:f:b:g:h:v:j:M:W:G:"); // Supported options
  186. INT iFunction = kUnknown;
  187. BOOL bStatus = FALSE;
  188. //
  189. // Set to known state
  190. //
  191. SetLastError( ERROR_SUCCESS );
  192. //
  193. // Indicate there is not a file name as the first argument.
  194. //
  195. TGetOptContext context;
  196. context.optind = 0;
  197. //
  198. // Process any command line arguments switches.
  199. //
  200. for (context.opterr = 0, retval = 0; retval != EOF; )
  201. {
  202. retval = getopt (ac, av, options, context);
  203. switch (retval)
  204. {
  205. case 't':
  206. pParams->dwSheet = _ttoi( context.optarg );
  207. break;
  208. case 'n':
  209. pParams->pPrinterName = context.optarg;
  210. break;
  211. case 'r':
  212. pParams->pPortName = context.optarg;
  213. break;
  214. case 'm':
  215. pParams->pModelName = context.optarg;
  216. break;
  217. case 'M':
  218. // get the message type first
  219. pParams->uMsgType = *context.optarg == TEXT('q') ? kMsgConfirmation :
  220. *context.optarg == TEXT('w') ? kMsgWarning : kMsgUnknownType;
  221. // get the real message text here
  222. context.optarg++;
  223. if( kMsgUnknownType != pParams->uMsgType && context.optarg && *context.optarg )
  224. {
  225. pParams->pMsgConfirm = context.optarg;
  226. }
  227. break;
  228. case 'b':
  229. pParams->pBasePrinterName = context.optarg;
  230. break;
  231. case 'f':
  232. pParams->pInfFileName = context.optarg;
  233. break;
  234. case 'a':
  235. pParams->pBinFileName = context.optarg;
  236. break;
  237. case 'G':
  238. {
  239. // global flags
  240. if( *context.optarg == TEXT('w') )
  241. {
  242. // we should suppress the setup driver warnings UI
  243. // -- i.e. we're in super quiet mode
  244. pParams->Flags.IsSupressSetupUI = TRUE;
  245. }
  246. }
  247. break;
  248. case 'g':
  249. iFunction = *context.optarg == TEXT('a') ? kAddPerMachineConnection :
  250. *context.optarg == TEXT('d') ? kDeletePerMachineConnection :
  251. *context.optarg == TEXT('e') ? kEnumPerMachineConnections : kUnknown;
  252. break;
  253. case 'j':
  254. pParams->pProvider = context.optarg;
  255. break;
  256. case 'i':
  257. iFunction = *context.optarg == TEXT('n') ? kInstallNetPrinter :
  258. *context.optarg == TEXT('l') ? kInstallLocalPrinter :
  259. *context.optarg == TEXT('d') ? kInstallPrinterDriver :
  260. *context.optarg == TEXT('a') ? kInstallDriverWithInf :
  261. *context.optarg == TEXT('f') ? kInstallPrinterWithInf :
  262. *context.optarg == TEXT('i') ? kInstallLocalPrinterWithInf : kUnknown;
  263. break;
  264. case 'd':
  265. iFunction = *context.optarg == TEXT('n') ? kDeleteNetPrinter :
  266. *context.optarg == TEXT('l') ? kDeleteLocalPrinter :
  267. *context.optarg == TEXT('d') ? kDeletePrinterDriver : kUnknown;
  268. break;
  269. case 'o':
  270. iFunction = kWin32QueueView;
  271. break;
  272. case 's':
  273. iFunction = kServerProperties;
  274. break;
  275. case 'p':
  276. iFunction = kProperties;
  277. break;
  278. case 'X':
  279. iFunction = *context.optarg == TEXT('g') ? kPrinterGetSettings :
  280. *context.optarg == TEXT('s') ? kPrinterSetSettings : kUnknown;
  281. break;
  282. case 'e':
  283. iFunction = kDocumentDefaults;
  284. break;
  285. case 'c':
  286. pParams->pMachineName = context.optarg;
  287. break;
  288. case 'l':
  289. pParams->pSourcePath = context.optarg;
  290. break;
  291. case 'h':
  292. pParams->pArchitecture = context.optarg;
  293. break;
  294. case 'v':
  295. pParams->pVersion = context.optarg;
  296. break;
  297. case 'q':
  298. pParams->Flags.IsQuiet = TRUE;
  299. break;
  300. case 'k':
  301. iFunction = kPrintTestPage;
  302. break;
  303. case 'y':
  304. iFunction = kSetAsDefault;
  305. break;
  306. case 'x':
  307. pParams->Flags.IsWebPointAndPrint = TRUE;
  308. break;
  309. case 'z':
  310. pParams->Flags.IsNoSharing = TRUE;
  311. break;
  312. case 'Z':
  313. pParams->Flags.IsShared = TRUE;
  314. break;
  315. case 'u':
  316. pParams->Flags.IsUseExistingDriver = TRUE;
  317. break;
  318. case 'w':
  319. pParams->Flags.IsUnknownDriverPrompt = TRUE;
  320. break;
  321. case 'W':
  322. // wizards flags
  323. pParams->Flags.IsWizardRestartable = *context.optarg == TEXT('r') ? TRUE : FALSE;
  324. break;
  325. case 'H':
  326. pParams->Flags.IsHydraSpecific = TRUE;
  327. break;
  328. case 'P':
  329. pParams->Flags.IsPromptForNeededFiles = TRUE;
  330. break;
  331. case 'Y':
  332. pParams->Flags.IsDontAutoGenerateName = TRUE;
  333. break;
  334. case 'K':
  335. pParams->Flags.IsUseNonLocalizedStrings = TRUE;
  336. break;
  337. case 'S':
  338. iFunction = *context.optarg == TEXT('s') ? kPrinterPersist :
  339. *context.optarg == TEXT('r') ? kPrinterRestore : kUnknown;
  340. break;
  341. case 'U':
  342. pParams->Flags.IsWindowsUpdate = TRUE;
  343. break;
  344. case EOF:
  345. bStatus = TRUE;
  346. break;
  347. case '?':
  348. iFunction = kCommandHelp;
  349. bStatus = TRUE;
  350. retval = EOF;
  351. break;
  352. case INVALID_COMAND:
  353. bStatus = FALSE;
  354. retval = EOF;
  355. break;
  356. default:
  357. retval = EOF;
  358. break;
  359. }
  360. }
  361. //
  362. // If success validate the command line arguments.
  363. //
  364. if( bStatus )
  365. {
  366. //
  367. // Do simple validation on the command line arguments.
  368. //
  369. bStatus = bValidateCommand( iFunction, pParams );
  370. if( bStatus )
  371. {
  372. //
  373. // If there are any remaining arguments then get
  374. // the argument count and pointer to it.
  375. //
  376. if( context.optind < ac )
  377. {
  378. pParams->av = &av[context.optind];
  379. pParams->ac = ac - context.optind;
  380. }
  381. //
  382. // Check to see if we need to ask the user to confirm the operation if
  383. // not in quiet mode.
  384. //
  385. BOOL bContinueExecution = TRUE;
  386. if( !pParams->Flags.IsQuiet && kMsgUnknownType != pParams->uMsgType && pParams->pMsgConfirm )
  387. {
  388. //
  389. // there is a confirmation/warning message specified and we are going to
  390. // give opportunity to the user to cancel the whole command here
  391. //
  392. UINT uFlags = kMsgConfirmation == pParams->uMsgType ? MB_ICONQUESTION :
  393. kMsgConfirmation == pParams->uMsgType ? MB_ICONEXCLAMATION : 0;
  394. ASSERT(uFlags); // shouldn't be zero
  395. uFlags |= MB_YESNO; // we are asking YES/NO question
  396. bContinueExecution = (IDYES == iMessage2(NULL, MAKEINTRESOURCE(IDS_PRINTERS_TITLE),
  397. pParams->pMsgConfirm, uFlags, kMsgNone, NULL));
  398. }
  399. if( bContinueExecution )
  400. {
  401. //
  402. // Execute the command.
  403. //
  404. bStatus = bExecuteCommand( hwnd, iFunction, pParams );
  405. }
  406. }
  407. }
  408. return bStatus;
  409. }
  410. /*++
  411. Routine Name:
  412. bValidateCommand
  413. Routine Description:
  414. Validates the command line arguments
  415. Arguments:
  416. iFunction - Function code.
  417. pParams - pointer to paramter structure.
  418. Return Value:
  419. TRUE arguments are valid. FALSE invalid argument found.
  420. --*/
  421. BOOL
  422. bValidateCommand(
  423. IN INT iFunction,
  424. IN AParams *pParams
  425. )
  426. {
  427. DBGMSG( DBG_TRACE, ("iFunction %d\n", iFunction ) );
  428. DBGMSG( DBG_TRACE, ("Params\n" ) );
  429. DBGMSG( DBG_TRACE, ("Flags %x\n", pParams->Flags ) );
  430. DBGMSG( DBG_TRACE, ("dwSheet %d\n", pParams->dwSheet ) );
  431. DBGMSG( DBG_TRACE, ("dwLastError %d\n", pParams->dwLastError ) );
  432. DBGMSG( DBG_TRACE, ("pPrinterName "TSTR"\n", DBGSTR( pParams->pPrinterName ) ) );
  433. DBGMSG( DBG_TRACE, ("pPortName "TSTR"\n", DBGSTR( pParams->pPortName ) ) );
  434. DBGMSG( DBG_TRACE, ("pModelName "TSTR"\n", DBGSTR( pParams->pModelName ) ) );
  435. DBGMSG( DBG_TRACE, ("pInfFileName "TSTR"\n", DBGSTR( pParams->pInfFileName ) ) );
  436. DBGMSG( DBG_TRACE, ("pBasePrinterName "TSTR"\n", DBGSTR( pParams->pBasePrinterName) ) );
  437. DBGMSG( DBG_TRACE, ("pMachineName "TSTR"\n", DBGSTR( pParams->pMachineName ) ) );
  438. DBGMSG( DBG_TRACE, ("pSourcePath "TSTR"\n", DBGSTR( pParams->pSourcePath ) ) );
  439. DBGMSG( DBG_TRACE, ("pszCmdLine "TSTR"\n", DBGSTR( pParams->pszCmdLine ) ) );
  440. DBGMSG( DBG_TRACE, ("pBinFileName "TSTR"\n", DBGSTR( pParams->pBinFileName ) ) );
  441. BOOL bRetval = FALSE;
  442. switch( iFunction )
  443. {
  444. case kInstallLocalPrinter:
  445. case kDeleteLocalPrinter:
  446. case kInstallPrinterDriver:
  447. case kEnumPerMachineConnections:
  448. case kServerProperties:
  449. case kCommandHelp:
  450. bRetval = TRUE;
  451. break;
  452. case kInstallLocalPrinterWithInf:
  453. if( pParams->pInfFileName )
  454. {
  455. bRetval = TRUE;
  456. }
  457. break;
  458. case kSetAsDefault:
  459. case kAddPerMachineConnection:
  460. case kDeletePerMachineConnection:
  461. case kInstallNetPrinter:
  462. case kDeleteNetPrinter:
  463. case kWin32QueueView:
  464. case kProperties:
  465. case kDocumentDefaults:
  466. case kPrintTestPage:
  467. case kPrinterGetSettings:
  468. case kPrinterSetSettings:
  469. if( pParams->pPrinterName )
  470. {
  471. bRetval = TRUE;
  472. }
  473. else
  474. {
  475. pParams->dwLastError = ERROR_INVALID_PRINTER_NAME;
  476. }
  477. break;
  478. case kInstallPrinterWithInf:
  479. if( pParams->pModelName && pParams->pInfFileName && pParams->pPortName )
  480. {
  481. bRetval = TRUE;
  482. if( pParams->Flags.IsWebPointAndPrint )
  483. {
  484. //
  485. // Commenting out pBinFileName - for local cab install for wp&p the bin file
  486. // won't exist. This may be fixed if syncing to the server is added and
  487. // this could be put back then. - pvine
  488. //
  489. bRetval = pParams->pPrinterName /*&& pParams->pBinFileName */? TRUE : FALSE;
  490. }
  491. else if( pParams->Flags.IsDontAutoGenerateName )
  492. {
  493. bRetval = pParams->pBasePrinterName != NULL;
  494. }
  495. }
  496. break;
  497. case kPrinterPersist:
  498. case kPrinterRestore:
  499. bRetval = pParams->pPrinterName && pParams->pBinFileName ? TRUE : FALSE;
  500. break;
  501. case kDeletePrinterDriver:
  502. case kInstallDriverWithInf:
  503. if( pParams->pModelName )
  504. {
  505. bRetval = TRUE;
  506. }
  507. break;
  508. case kUnknown:
  509. pParams->dwLastError = ERROR_INVALID_FUNCTION;
  510. bRetval = FALSE;
  511. break;
  512. }
  513. if( !bRetval && ERROR_SUCCESS == pParams->dwLastError )
  514. {
  515. //
  516. // An invalid parameter has been passed.
  517. //
  518. pParams->dwLastError = ERROR_INVALID_PARAMETER;
  519. }
  520. return bRetval;
  521. }
  522. /*++
  523. Routine Name:
  524. bExecuteCommand
  525. Routine Description:
  526. Executes the command from the rundll32 command line
  527. after it has parsed.
  528. Arguments:
  529. hwnd - parent window handle.
  530. iFunction - Function code.
  531. pParams - pointer to paramter structure.
  532. Return Value:
  533. TRUE function complete ok. FALSE error occurred.
  534. --*/
  535. BOOL
  536. bExecuteCommand(
  537. IN HWND hwnd,
  538. IN INT iFunction,
  539. IN AParams *pParams
  540. )
  541. {
  542. BOOL bRetval = TRUE;
  543. TCHAR szBuffer[kPrinterBufMax];
  544. UINT uSize = COUNTOF( szBuffer );
  545. DBGMSG( DBG_TRACE, ("Function %d\n", iFunction ) );
  546. szBuffer[0] = TEXT('\0');
  547. if( pParams->pPrinterName )
  548. {
  549. _tcsncpy( szBuffer, pParams->pPrinterName, COUNTOF( szBuffer ) );
  550. }
  551. //
  552. // Dispatch the specified function.
  553. //
  554. // !!Policy!! if a command is executed then it is responsible
  555. // for displaying any error UI i.e message boxes.
  556. //
  557. switch( iFunction )
  558. {
  559. case kInstallNetPrinter:
  560. (VOID)bPrinterSetup( NULL, MSP_NETPRINTER, MAX_PATH, szBuffer, &uSize, pParams->pMachineName );
  561. break;
  562. case kDeleteNetPrinter:
  563. bRetval = bPrinterNetRemove( NULL, szBuffer, pParams->Flags.IsQuiet );
  564. break;
  565. case kDeleteLocalPrinter:
  566. bRetval = bRemovePrinter( NULL, szBuffer, pParams->pMachineName, pParams->Flags.IsQuiet );
  567. break;
  568. case kInstallPrinterDriver:
  569. bRetval = bDriverSetupNew( NULL, TWizard::kDriverInstall, MAX_PATH, szBuffer, &uSize,
  570. pParams->pMachineName, 0, pParams->Flags.IsWizardRestartable );
  571. break;
  572. case kInstallLocalPrinter:
  573. bRetval = bPrinterSetupNew( NULL, TWizard::kPrinterInstall, MAX_PATH, szBuffer, &uSize,
  574. pParams->pMachineName, NULL, pParams->Flags.IsWizardRestartable );
  575. break;
  576. case kInstallLocalPrinterWithInf:
  577. bRetval = bPrinterSetupNew( NULL, TWizard::kPrinterInstall, MAX_PATH, szBuffer, &uSize, pParams->pMachineName, pParams->pInfFileName, FALSE );
  578. break;
  579. case kInstallDriverWithInf:
  580. bRetval = bDoInfDriverInstall( pParams );
  581. break;
  582. case kInstallPrinterWithInf:
  583. bRetval = bDoInfPrinterInstall( pParams );
  584. break;
  585. case kAddPerMachineConnection:
  586. vAddPerMachineConnection(pParams->pMachineName,pParams->pPrinterName,pParams->pProvider,pParams->Flags.IsQuiet);
  587. break;
  588. case kDeletePerMachineConnection:
  589. vDeletePerMachineConnection(pParams->pMachineName,pParams->pPrinterName,pParams->Flags.IsQuiet);
  590. break;
  591. case kEnumPerMachineConnections:
  592. vEnumPerMachineConnections(pParams->pMachineName,pParams->pInfFileName,pParams->Flags.IsQuiet);
  593. break;
  594. case kWin32QueueView:
  595. vQueueCreate( NULL, pParams->pPrinterName, SW_SHOW, TRUE );
  596. break;
  597. case kProperties:
  598. vPrinterPropPages( NULL, pParams->pPrinterName, SW_SHOW, MAKELPARAM( pParams->dwSheet+256, 0 ));
  599. break;
  600. case kDocumentDefaults:
  601. vDocumentDefaults( NULL, pParams->pPrinterName, SW_SHOW, MAKELPARAM( pParams->dwSheet, 1 ));
  602. break;
  603. case kServerProperties:
  604. vServerPropPages( NULL, pParams->pPrinterName, SW_SHOW, MAKELPARAM( pParams->dwSheet, 1 ));
  605. break;
  606. case kDeletePrinterDriver:
  607. bRetval = bDoDriverRemoval( pParams );
  608. break;
  609. case kSetAsDefault:
  610. bRetval = SetDefaultPrinter( pParams->pPrinterName );
  611. break;
  612. case kPrintTestPage:
  613. bRetval = bDoPrintTestPage( hwnd, pParams->pPrinterName );
  614. break;
  615. case kPrinterGetSettings:
  616. bRetval = bDoGetPrintSettings( pParams );
  617. break;
  618. case kPrinterSetSettings:
  619. bRetval = bDoSetPrintSettings( pParams );
  620. break;
  621. case kPrinterPersist:
  622. bRetval = bDoPersistPrinterSettings( kPrinterPersist , pParams );
  623. break;
  624. case kPrinterRestore:
  625. bRetval = bDoPersistPrinterSettings( kPrinterRestore , pParams );
  626. break;
  627. case kCommandHelp:
  628. vUsage( pParams );
  629. break;
  630. case kUnknown:
  631. default:
  632. bRetval = TRUE;
  633. break;
  634. }
  635. //
  636. // Some of the functions do not setup pParams->dwLastError,
  637. // so we must rely on the GetLastError() in this case.
  638. //
  639. if( !bRetval && ERROR_SUCCESS == pParams->dwLastError )
  640. {
  641. pParams->dwLastError = GetLastError();
  642. }
  643. return bRetval;
  644. }
  645. /*++
  646. Routine Name:
  647. vUsage
  648. Routine Description:
  649. Display a usage message for the rundll switches.
  650. Arguments:
  651. Nothing.
  652. Return Value:
  653. None.
  654. --*/
  655. VOID
  656. vUsage(
  657. IN AParams *pParams
  658. )
  659. {
  660. TStatusB bStatus;
  661. TString strTemp;
  662. if (!pParams->Flags.IsQuiet)
  663. {
  664. TRunDllDisplay Usage( NULL );
  665. if (VALID_OBJ( Usage ))
  666. {
  667. #ifdef COMMAND_SPECIFIC_HELP
  668. if( pParams->ac )
  669. {
  670. for( UINT i = 0; i < pParams->ac; i++ )
  671. {
  672. bStatus DBGCHK = Usage.WriteOut( pParams->av[i] );
  673. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") );
  674. }
  675. }
  676. else
  677. #endif
  678. {
  679. //
  680. // Note we do not check the return values of the string operations
  681. // because bombing out is just as bad as printing an empty string. The
  682. // string class will prevent us from ever crashing.
  683. //
  684. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_TITLE );
  685. bStatus DBGCHK = Usage.SetTitle( strTemp );
  686. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_USAGE );
  687. bStatus DBGCHK = Usage.WriteOut( strTemp );
  688. for( UINT i = IDS_RUNDLL_OPTION0; i <= IDS_RUNDLL_OPTION_END; i++ )
  689. {
  690. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n ") );
  691. bStatus DBGCHK = strTemp.bLoadString( ghInst, i );
  692. bStatus DBGCHK = Usage.WriteOut( strTemp );
  693. }
  694. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n\r\n") );
  695. bStatus DBGCHK = strTemp.bLoadString( ghInst,IDS_RUNDLL_EXAMPLE0 );
  696. bStatus DBGCHK = Usage.WriteOut( strTemp );
  697. for( i = IDS_RUNDLL_EXAMPLE1; i <= IDS_RUNDLL_EXAMPLE_END; i++ )
  698. {
  699. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n ") );
  700. bStatus DBGCHK = strTemp.bLoadString( ghInst, i );
  701. bStatus DBGCHK = Usage.WriteOut( strTemp );
  702. }
  703. }
  704. Usage.bDoModal();
  705. }
  706. }
  707. }
  708. /*++
  709. Routine Name:
  710. bDoPersistPrinterSettings
  711. Routine Description:
  712. Store printer settings into file
  713. Calls Re/StorePrinterSettings with args :
  714. pParams->pPrinterName, pParams->pBinFileName and flags builded upon pParams->av
  715. if pParams->ac == 0 , all setttings will be stored/restored
  716. For restoring settings PRINTER_ALL_ACCESS required for specified printer
  717. Arguments:
  718. iFunction specify what function should be called ( Store/RestorePrinterSettings )
  719. AParams* ptr to AParam structure
  720. Return Value:
  721. TRUE if Re/StorePrinterSettings SUCCEEDED.
  722. FALSE otherwise
  723. --*/
  724. BOOL
  725. bDoPersistPrinterSettings(
  726. IN INT iFunction,
  727. IN AParams *pParams
  728. )
  729. {
  730. DWORD dwFlags = 0;
  731. UINT idx;
  732. UINT ParamIdx;
  733. UINT OptionIdx;
  734. HRESULT hr;
  735. struct ParamEntry
  736. {
  737. TCHAR Option;
  738. DWORD Flag;
  739. };
  740. static ParamEntry PrintSettings_ParamTable [] = {
  741. {TEXT('2'), PRST_PRINTER_INFO_2},
  742. {TEXT('7'), PRST_PRINTER_INFO_7},
  743. {TEXT('c'), PRST_COLOR_PROF},
  744. {TEXT('d'), PRST_PRINTER_DATA},
  745. {TEXT('s'), PRST_PRINTER_SEC},
  746. {TEXT('g'), PRST_PRINTER_DEVMODE},
  747. {TEXT('u'), PRST_USER_DEVMODE},
  748. {TEXT('r'), PRST_RESOLVE_NAME},
  749. {TEXT('f'), PRST_FORCE_NAME},
  750. {TEXT('p'), PRST_RESOLVE_PORT},
  751. {TEXT('h'), PRST_RESOLVE_SHARE},
  752. {TEXT('H'), PRST_DONT_GENERATE_SHARE},
  753. {TEXT('m'), PRST_MINIMUM_SETTINGS},
  754. {0, 0},
  755. };
  756. // for every entry in table
  757. for (ParamIdx = 0 ; ParamIdx < pParams->ac; ParamIdx++ )
  758. {
  759. //for every option argv
  760. for (idx = 0; PrintSettings_ParamTable[idx].Option; idx++)
  761. {
  762. OptionIdx = 0;
  763. //for every char in option argv
  764. while(pParams->av[ParamIdx][OptionIdx])
  765. {
  766. if(OptionIdx > 0)
  767. {
  768. hr = E_FAIL;
  769. goto End;
  770. }
  771. if(PrintSettings_ParamTable[idx].Option == pParams->av[ParamIdx][OptionIdx])
  772. {
  773. // apply flags if in table
  774. dwFlags |= PrintSettings_ParamTable[idx].Flag;
  775. DBGMSG(DBG_TRACE , ("Char %c\n" , pParams->av[ParamIdx][OptionIdx]));
  776. }
  777. OptionIdx++;
  778. }
  779. }
  780. }
  781. if((dwFlags & PRST_FORCE_NAME) && (dwFlags & PRST_RESOLVE_NAME))
  782. {
  783. hr = E_FAIL;
  784. goto End;
  785. }
  786. //
  787. // if no "printer" flags specified , set flags to PRST_ALL_SETTINGS
  788. //
  789. if(!(dwFlags & PRST_ALL_SETTINGS))
  790. {
  791. dwFlags |= PRST_ALL_SETTINGS;
  792. }
  793. hr = (iFunction == kPrinterRestore) ?
  794. RestorePrinterSettings( pParams->pPrinterName, pParams->pBinFileName, dwFlags)
  795. :
  796. StorePrinterSettings( pParams->pPrinterName, pParams->pBinFileName, dwFlags) ;
  797. End:
  798. return SUCCEEDED(hr);
  799. }
  800. /*++
  801. Routine Name:
  802. bDoWebPnpPreInstall
  803. Routine Description:
  804. Do Web Point and Print Pre installation tasks.
  805. Arguments:
  806. pParams - pointer to paramter structure.
  807. pfConnection - pointer where to return connection status
  808. Return Value:
  809. TRUE Web Point and Print code was successfull, FALSE error occurred.
  810. --*/
  811. BOOL
  812. bDoWebPnpPreInstall(
  813. IN AParams *pParams
  814. )
  815. {
  816. TStatusB bStatus;
  817. //
  818. // Inform the point and print code pre entry.
  819. //
  820. bStatus DBGCHK = SUCCEEDED(Winspool_WebPnpEntry( pParams->pszCmdLine ));
  821. //
  822. // If something failed return the last error.
  823. //
  824. if( !bStatus )
  825. {
  826. pParams->dwLastError = GetLastError();
  827. }
  828. return bStatus;
  829. }
  830. /*++
  831. Routine Name:
  832. bDoInfPrinterInstall
  833. Routine Description:
  834. Do inf based printer installation.
  835. Arguments:
  836. pParams - pointer to paramter structure.
  837. Return Value:
  838. None.
  839. --*/
  840. BOOL
  841. bDoInfPrinterInstall(
  842. IN AParams *pParams
  843. )
  844. {
  845. TStatusB bStatus;
  846. TCHAR szBuffer[kPrinterBufMax];
  847. //
  848. // Assume success.
  849. //
  850. bStatus DBGNOCHK = TRUE;
  851. //
  852. // If we are invoked for a Web Point and Pint install.
  853. //
  854. if( bStatus && pParams->Flags.IsWebPointAndPrint )
  855. {
  856. //
  857. // Inform the point and print code pre entry.
  858. //
  859. bStatus DBGCHK = bDoWebPnpPreInstall( pParams );
  860. }
  861. //
  862. // If web pnp pre installed succeeded.
  863. //
  864. if( bStatus )
  865. {
  866. TInfInstall II;
  867. TParameterBlock PB;
  868. ZeroMemory( &II, sizeof( II ) );
  869. ZeroMemory( &PB, sizeof( PB ) );
  870. ZeroMemory( szBuffer, sizeof( szBuffer ) );
  871. if( pParams->pBasePrinterName )
  872. {
  873. _tcsncpy( szBuffer, pParams->pBasePrinterName, COUNTOF( szBuffer ) );
  874. }
  875. II.cbSize = sizeof( II );
  876. II.pszServerName = pParams->pMachineName;
  877. II.pszInfName = pParams->pInfFileName;
  878. II.pszModelName = pParams->pModelName;
  879. II.pszPortName = pParams->pPortName;
  880. II.pszSourcePath = pParams->pSourcePath;
  881. II.pszPrinterNameBuffer = szBuffer;
  882. II.cchPrinterName = COUNTOF( szBuffer );
  883. //
  884. // If this is a web point and print install then set the flags
  885. // to indicate that we want to create the masq printer.
  886. //
  887. II.dwFlags = 0;
  888. II.dwFlags |= pParams->Flags.IsWebPointAndPrint ? kPnPInterface_WebPointAndPrint : 0;
  889. II.dwFlags |= pParams->Flags.IsQuiet ? kPnPInterface_Quiet : 0;
  890. II.dwFlags |= pParams->Flags.IsNoSharing ? kPnPInterface_NoShare : 0;
  891. II.dwFlags |= pParams->Flags.IsUseExistingDriver ? kPnpInterface_UseExisting : 0;
  892. II.dwFlags |= pParams->Flags.IsUnknownDriverPrompt ? kPnpInterface_PromptIfUnknownDriver : 0;
  893. II.dwFlags |= pParams->Flags.IsHydraSpecific ? kPnpInterface_HydraSpecific : 0;
  894. II.dwFlags |= pParams->Flags.IsPromptForNeededFiles ? kPnPInterface_PromptIfFileNeeded : 0;
  895. II.dwFlags |= pParams->Flags.IsShared ? kPnPInterface_Share : 0;
  896. II.dwFlags |= pParams->Flags.IsDontAutoGenerateName ? kPnPInterface_DontAutoGenerateName : 0;
  897. II.dwFlags |= pParams->Flags.IsSupressSetupUI ? kPnPInterface_SupressSetupUI : 0;
  898. PB.pInfInstall = &II;
  899. pParams->dwLastError = PnPInterface( kInfInstall, &PB );
  900. bStatus DBGNOCHK = (pParams->dwLastError == ERROR_SUCCESS);
  901. }
  902. //
  903. // If we succeeded and this is a web point and print event.
  904. //
  905. if( bStatus && pParams->Flags.IsWebPointAndPrint )
  906. {
  907. //
  908. // Inform the web point and print code that the printer was
  909. // installed, they can do ay post processing here.
  910. //
  911. bStatus DBGCHK = SUCCEEDED(Winspool_WebPnpPostEntry( FALSE, pParams->pBinFileName, pParams->pPortName, szBuffer ));
  912. }
  913. return pParams->dwLastError == ERROR_SUCCESS ? TRUE : FALSE;
  914. }
  915. /*++
  916. Routine Name:
  917. bDoInfDriverInstall
  918. Routine Description:
  919. Do inf based printer driver installation.
  920. Arguments:
  921. pParams - pointer to paramter structure.
  922. Return Value:
  923. None.
  924. --*/
  925. BOOL
  926. bDoInfDriverInstall(
  927. IN AParams *pParams
  928. )
  929. {
  930. TInfDriverInstall II = {0};
  931. TParameterBlock PB = {0};
  932. II.cbSize = sizeof( II );
  933. II.pszServerName = pParams->pMachineName;
  934. II.pszInfName = pParams->pInfFileName;
  935. II.pszModelName = pParams->pModelName;
  936. II.pszSourcePath = pParams->pSourcePath;
  937. II.pszVersion = pParams->pVersion;
  938. II.pszArchitecture = pParams->pArchitecture;
  939. II.dwFlags = 0;
  940. II.dwFlags |= pParams->Flags.IsQuiet ? kPnPInterface_Quiet : 0;
  941. II.dwFlags |= pParams->Flags.IsWindowsUpdate ? kPnPInterface_WindowsUpdate : 0;
  942. II.dwFlags |= pParams->Flags.IsUseNonLocalizedStrings ? kPnPInterface_UseNonLocalizedStrings : 0;
  943. II.dwFlags |= pParams->Flags.IsSupressSetupUI ? kPnPInterface_SupressSetupUI : 0;
  944. PB.pInfDriverInstall = &II;
  945. pParams->dwLastError = PnPInterface( kInfDriverInstall, &PB );
  946. return pParams->dwLastError == ERROR_SUCCESS;
  947. }
  948. /*++
  949. Routine Name:
  950. bDoDriverRemoval
  951. Routine Description:
  952. Do driver delete
  953. Arguments:
  954. pParams - pointer to paramter structure.
  955. Return Value:
  956. None.
  957. --*/
  958. BOOL
  959. bDoDriverRemoval(
  960. IN AParams *pParams
  961. )
  962. {
  963. TDriverRemoval II = {0};
  964. TParameterBlock PB = {0};
  965. II.cbSize = sizeof( II );
  966. II.pszServerName = pParams->pMachineName;
  967. II.pszModelName = pParams->pModelName;
  968. II.pszVersion = pParams->pVersion;
  969. II.pszArchitecture = pParams->pArchitecture;
  970. II.dwFlags = 0;
  971. II.dwFlags |= pParams->Flags.IsUseNonLocalizedStrings ? kPnPInterface_UseNonLocalizedStrings : 0;
  972. II.dwFlags |= pParams->Flags.IsQuiet ? kPnPInterface_Quiet : 0;
  973. II.dwFlags |= pParams->Flags.IsSupressSetupUI ? kPnPInterface_SupressSetupUI : 0;
  974. PB.pDriverRemoval = &II;
  975. pParams->dwLastError = PnPInterface( kDriverRemoval, &PB );
  976. if( ERROR_UNKNOWN_PRINTER_DRIVER == pParams->dwLastError )
  977. {
  978. // this error code is used primarily for blocking bad
  979. // oem drivers so the default message used is pretty
  980. // incorrect. remap the message to better one based on
  981. // the context
  982. CMsgBoxCounter::SetMsg(IDS_ERROR_DRIVER_DOESNT_EXISTS);
  983. }
  984. return pParams->dwLastError == ERROR_SUCCESS;
  985. }
  986. /********************************************************************
  987. Setting and Getting printer information methods.
  988. ********************************************************************/
  989. static TSelect::SelectionVal PrintSettings_ValueTable [] = {
  990. {IDS_RUNDLL_SET_PAUSE, PRINTER_CONTROL_PAUSE, OFFSETOF( PRINTER_INFO_2, Status )},
  991. {IDS_RUNDLL_SET_RESUME, PRINTER_CONTROL_RESUME, OFFSETOF( PRINTER_INFO_2, Status )},
  992. {IDS_RUNDLL_SET_PURGE, PRINTER_CONTROL_PURGE, OFFSETOF( PRINTER_INFO_2, Status )},
  993. {NULL, 0, NULL}};
  994. static TSelect::SelectionBit PrintSettings_BitTable [] = {
  995. {IDS_RUNDLL_SET_QUEUED, PRINTER_ATTRIBUTE_QUEUED, TSelect::kNop},
  996. {IDS_RUNDLL_SET_DIRECT, PRINTER_ATTRIBUTE_DIRECT, TSelect::kNop},
  997. {IDS_RUNDLL_SET_DEFAULT, PRINTER_ATTRIBUTE_DEFAULT, TSelect::kNop},
  998. {IDS_RUNDLL_SET_SHARED, PRINTER_ATTRIBUTE_SHARED, TSelect::kNop},
  999. {IDS_RUNDLL_SET_HIDDEN, PRINTER_ATTRIBUTE_HIDDEN, TSelect::kNop},
  1000. {IDS_RUNDLL_SET_NETWORK, PRINTER_ATTRIBUTE_NETWORK, TSelect::kNop},
  1001. {IDS_RUNDLL_SET_LOCAL, PRINTER_ATTRIBUTE_LOCAL, TSelect::kNop},
  1002. {IDS_RUNDLL_SET_ENABLEDEVQ, PRINTER_ATTRIBUTE_ENABLE_DEVQ, TSelect::kNop},
  1003. {IDS_RUNDLL_SET_KEEPPRINTEDJOBS,PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS, TSelect::kNop},
  1004. {IDS_RUNDLL_SET_DOCOMPLETEFIRST,PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,TSelect::kNop},
  1005. {IDS_RUNDLL_SET_WORKOFFLINE, PRINTER_ATTRIBUTE_WORK_OFFLINE, TSelect::kNop},
  1006. {IDS_RUNDLL_SET_ENABLEBIDI, PRINTER_ATTRIBUTE_ENABLE_BIDI, TSelect::kNop},
  1007. {IDS_RUNDLL_SET_RAWONLY, PRINTER_ATTRIBUTE_RAW_ONLY, TSelect::kNop},
  1008. {IDS_RUNDLL_SET_PUBLISHED, PRINTER_ATTRIBUTE_PUBLISHED, TSelect::kNop},
  1009. {0, 0, TSelect::kNop}};
  1010. static TSelect::Selection PrintSettings_Table [] = {
  1011. {IDS_RUNDLL_SET_PRINTERNAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pPrinterName ) },
  1012. {IDS_RUNDLL_SET_SHARENAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pShareName ) },
  1013. {IDS_RUNDLL_SET_PORTNAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pPortName ) },
  1014. {IDS_RUNDLL_SET_DRIVERNAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pDriverName ) },
  1015. {IDS_RUNDLL_SET_COMMENT, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pComment ) },
  1016. {IDS_RUNDLL_SET_LOCATION, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pLocation ) },
  1017. {IDS_RUNDLL_SET_SEPFILE, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pSepFile ) },
  1018. {IDS_RUNDLL_SET_PRINTPROCESSOR, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pPrintProcessor )},
  1019. {IDS_RUNDLL_SET_DATATYPE, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pDatatype ) },
  1020. {IDS_RUNDLL_SET_PARAMETERS, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pParameters ) },
  1021. {IDS_RUNDLL_SET_ATTRIBUTES, TSelect::kBitTable, PrintSettings_BitTable, OFFSETOF( PRINTER_INFO_2, Attributes ) },
  1022. {IDS_RUNDLL_SET_PRIORITY, TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, Priority ) },
  1023. {IDS_RUNDLL_SET_DEFAULTPRIORITY,TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, DefaultPriority ) },
  1024. {IDS_RUNDLL_SET_STARTTIME, TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, StartTime ) },
  1025. {IDS_RUNDLL_SET_UNTILTIME, TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, UntilTime ) },
  1026. {IDS_RUNDLL_SET_STATUS, TSelect::kValTable, PrintSettings_ValueTable,OFFSETOF( PRINTER_INFO_2, Status ) },
  1027. {NULL, TSelect::kNone, NULL, NULL }};
  1028. /*++
  1029. Routine Name:
  1030. bDoGetPrintSettings
  1031. Routine Description:
  1032. Get the specified printer settings.
  1033. Arguments:
  1034. pParams - pointer to paramter structure.
  1035. Return Value:
  1036. TRUE success, FALSE error.
  1037. --*/
  1038. BOOL
  1039. bDoGetPrintSettings(
  1040. IN AParams *pParams
  1041. )
  1042. {
  1043. DBGMSG( DBG_TRACE, ( "bDoGetPrintSettings\n" ) );
  1044. return PrintSettings_DisplayInformation( pParams, PrintSettings_Table );
  1045. }
  1046. /*++
  1047. Routine Name:
  1048. bDoSetPrintSettings
  1049. Routine Description:
  1050. Set the specified printer settings.
  1051. Arguments:
  1052. pParams - pointer to paramter structure.
  1053. Return Value:
  1054. TRUE success, FALSE error.
  1055. --*/
  1056. BOOL
  1057. bDoSetPrintSettings(
  1058. IN AParams *pParams
  1059. )
  1060. {
  1061. DBGMSG( DBG_TRACE, ( "bDoSetPrintSettings\n" ) );
  1062. DBGMSG( DBG_TRACE, ( "Argument count %d.\n", pParams->ac ) );
  1063. TStatusB bStatus;
  1064. bStatus DBGNOCHK = FALSE;
  1065. TSelect Select;
  1066. PRINTER_INFO_2 Info = {0};
  1067. Info.Attributes = (DWORD)-1;
  1068. Info.Priority = (DWORD)-1;
  1069. Info.DefaultPriority = (DWORD)-1;
  1070. Info.StartTime = (DWORD)-1;
  1071. Info.UntilTime = (DWORD)-1;
  1072. Info.Status = (DWORD)-1;
  1073. //
  1074. // Validate command arguments
  1075. //
  1076. if( !PrintSettings_ValidateArguments( pParams ) )
  1077. {
  1078. DBGMSG( DBG_WARN, ( "Argument validation failed.\n" ) );
  1079. return pParams->dwLastError == ERROR_SUCCESS;
  1080. }
  1081. //
  1082. // Lookup the printer setting command.
  1083. //
  1084. for( UINT i = 0; i < pParams->ac; i += 2 )
  1085. {
  1086. if( (i+0 < pParams->ac) && (i+1 < pParams->ac) )
  1087. {
  1088. bStatus DBGCHK = Select.bLookup( PrintSettings_Table, &Info, pParams->av[i], pParams->av[i+1] );
  1089. if( !bStatus )
  1090. {
  1091. DBGMSG( DBG_WARN, ( "Invalid key name found.\n" ) );
  1092. pParams->dwLastError = ERROR_INVALID_PARAMETER;
  1093. break;
  1094. }
  1095. }
  1096. else
  1097. {
  1098. DBGMSG( DBG_WARN, ( "Unmatched key / value pair arguments\n" ) );
  1099. pParams->dwLastError = ERROR_INVALID_PARAMETER;
  1100. bStatus DBGNOCHK = FALSE;
  1101. break;
  1102. }
  1103. }
  1104. //
  1105. // Set the printer data.
  1106. //
  1107. if( bStatus )
  1108. {
  1109. //
  1110. // Set the printer information.
  1111. //
  1112. bStatus DBGCHK = PrintSettings_SetInfo( pParams, Info );
  1113. if( !bStatus )
  1114. {
  1115. DBGMSG( DBG_TRACE, ( "PrintSettings_SetInfo failed with %d\n", pParams->dwLastError ) );
  1116. }
  1117. }
  1118. return bStatus;
  1119. }
  1120. /*++
  1121. Routine Name:
  1122. PrintSettings_ValidateArguments
  1123. Routine Description:
  1124. Validate the command line arguments
  1125. Arguments:
  1126. pParams - pointer to paramter structure.
  1127. Return Value:
  1128. TRUE success, FALSE error.
  1129. --*/
  1130. BOOL
  1131. PrintSettings_ValidateArguments(
  1132. IN AParams *pParams
  1133. )
  1134. {
  1135. TStatusB bStatus;
  1136. bStatus DBGNOCHK = FALSE;
  1137. TString strHelp1;
  1138. TString strHelp2;
  1139. //
  1140. // There must be at least one additional argumet.
  1141. //
  1142. if( !(pParams->ac >= 1) )
  1143. {
  1144. DBGMSG( DBG_WARN, ( "Insufficent number of additional arguments.\n" ) );
  1145. pParams->dwLastError = ERROR_INVALID_PARAMETER;
  1146. return bStatus;
  1147. }
  1148. //
  1149. // If a help command was specified.
  1150. //
  1151. bStatus DBGCHK = strHelp1.bLoadString( ghInst, IDS_RUNDLL_HELP1 );
  1152. bStatus DBGCHK = strHelp2.bLoadString( ghInst, IDS_RUNDLL_HELP2 );
  1153. if( !_tcsicmp( pParams->av[0], strHelp1 ) || !_tcsicmp( pParams->av[0], strHelp2 ) )
  1154. {
  1155. pParams->dwLastError = ERROR_SUCCESS;
  1156. PrintSettings_DisplayHelp( pParams, PrintSettings_Table );
  1157. return FALSE;
  1158. }
  1159. //
  1160. // Success we have validated the arguments.
  1161. //
  1162. bStatus DBGNOCHK = TRUE;
  1163. return bStatus;
  1164. }
  1165. /*++
  1166. Routine Name:
  1167. PrintSettings_SetInfo
  1168. Routine Description:
  1169. Set the printer info data.
  1170. Arguments:
  1171. Info - Reference to printer info data.
  1172. pParams - pointer to paramter structure.
  1173. Return Value:
  1174. TRUE success, FALSE error.
  1175. --*/
  1176. BOOL
  1177. PrintSettings_SetInfo(
  1178. IN AParams *pParams,
  1179. IN PRINTER_INFO_2 &Info
  1180. )
  1181. {
  1182. DBGMSG( DBG_TRACE, ( "PrintSettings_SetInfo\n" ) );
  1183. TStatus Status;
  1184. TStatusB bStatus;
  1185. bStatus DBGNOCHK = FALSE;
  1186. HANDLE hPrinter = NULL;
  1187. PPRINTER_INFO_2 pInfo = NULL;
  1188. DWORD cbInfo = 0;
  1189. DWORD dwAccess = 0;
  1190. DWORD dwOldAttributes = 0;
  1191. DWORD dwNewAttributes = 0;
  1192. //
  1193. // Open the printer.
  1194. //
  1195. Status DBGCHK = TPrinter::sOpenPrinter( pParams->pPrinterName, &dwAccess, &hPrinter );
  1196. if( Status == ERROR_SUCCESS )
  1197. {
  1198. //
  1199. // Get the printer data.
  1200. //
  1201. bStatus DBGNOCHK = VDataRefresh::bGetPrinter( hPrinter, 2, (PVOID *)&pInfo, (PDWORD)&cbInfo );
  1202. //
  1203. // Merge in any changed fields.
  1204. //
  1205. if( bStatus )
  1206. {
  1207. TSelect Select;
  1208. //
  1209. // Convert the bit table to a value.
  1210. //
  1211. Select.bApplyBitTableToValue( PrintSettings_BitTable, pInfo->Attributes, &Info.Attributes );
  1212. //
  1213. // Publishing and UnPublishing needs to be special cased, since this setting is
  1214. // not done in the printer info 2 structure. The published bit is a read only
  1215. // attribute in the printer info 2, the publish state is changed using set printer
  1216. // info 7.
  1217. //
  1218. dwOldAttributes = pInfo->Attributes;
  1219. dwNewAttributes = Info.Attributes != -1 ? Info.Attributes : pInfo->Attributes;
  1220. //
  1221. // Copy the changed date into the info sturcture.
  1222. //
  1223. pInfo->pPrinterName = Info.pPrinterName ? Info.pPrinterName : pInfo->pPrinterName;
  1224. pInfo->pShareName = Info.pShareName ? Info.pShareName : pInfo->pShareName;
  1225. pInfo->pPortName = Info.pPortName ? Info.pPortName : pInfo->pPortName;
  1226. pInfo->pDriverName = Info.pDriverName ? Info.pDriverName : pInfo->pDriverName;
  1227. pInfo->pComment = Info.pComment ? Info.pComment : pInfo->pComment;
  1228. pInfo->pLocation = Info.pLocation ? Info.pLocation : pInfo->pLocation;
  1229. pInfo->pSepFile = Info.pSepFile ? Info.pSepFile : pInfo->pSepFile;
  1230. pInfo->pDatatype = Info.pDatatype ? Info.pDatatype : pInfo->pDatatype;
  1231. pInfo->pParameters = Info.pParameters ? Info.pParameters : pInfo->pParameters;
  1232. pInfo->Attributes = Info.Attributes != -1 ? Info.Attributes : pInfo->Attributes;
  1233. pInfo->Priority = Info.Priority != -1 ? Info.Priority : pInfo->Priority;
  1234. pInfo->DefaultPriority = Info.DefaultPriority != -1 ? Info.DefaultPriority : pInfo->DefaultPriority;
  1235. pInfo->StartTime = Info.StartTime != -1 ? Info.StartTime : pInfo->StartTime;
  1236. pInfo->UntilTime = Info.UntilTime != -1 ? Info.UntilTime : pInfo->UntilTime;
  1237. }
  1238. //
  1239. // Set the changed printer data.
  1240. //
  1241. if( bStatus )
  1242. {
  1243. bStatus DBGCHK = SetPrinter( hPrinter, 2, (PBYTE)pInfo, 0 );
  1244. if( bStatus )
  1245. {
  1246. if( Info.Status != -1 )
  1247. {
  1248. bStatus DBGCHK = SetPrinter( hPrinter, 0, NULL, Info.Status );
  1249. }
  1250. }
  1251. }
  1252. //
  1253. // Handle the printer publishing case.
  1254. //
  1255. if( bStatus )
  1256. {
  1257. //
  1258. // Only do something if the attributes are different.
  1259. //
  1260. if( dwOldAttributes != dwNewAttributes )
  1261. {
  1262. //
  1263. // If the current printer state is not shared and it
  1264. // was previously published then unpublish it now.
  1265. //
  1266. if(!(pInfo->Attributes & PRINTER_ATTRIBUTE_SHARED) &&
  1267. dwOldAttributes & PRINTER_ATTRIBUTE_PUBLISHED)
  1268. {
  1269. dwNewAttributes &= ~PRINTER_ATTRIBUTE_PUBLISHED;
  1270. }
  1271. //
  1272. // Only unpublish requests or shared printer publish requests.
  1273. //
  1274. bStatus DBGCHK = !(dwNewAttributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
  1275. (dwNewAttributes & PRINTER_ATTRIBUTE_PUBLISHED &&
  1276. pInfo->Attributes & PRINTER_ATTRIBUTE_SHARED);
  1277. if(bStatus)
  1278. {
  1279. PRINTER_INFO_7 Info7 = {0};
  1280. Info7.dwAction = (dwNewAttributes & PRINTER_ATTRIBUTE_PUBLISHED)
  1281. ? DSPRINT_PUBLISH : DSPRINT_UNPUBLISH;
  1282. bStatus DBGCHK = SetPrinter( hPrinter, 7, (PBYTE)&Info7, 0 );
  1283. //
  1284. // Printer info 7 fails with ERROR_IO_PENDING when the publishing is occurring
  1285. // in the background. For the rundll32 interface just return success.
  1286. //
  1287. if(!bStatus && (GetLastError() == ERROR_IO_PENDING))
  1288. {
  1289. SetLastError(ERROR_SUCCESS);
  1290. bStatus DBGNOCHK = TRUE;
  1291. }
  1292. }
  1293. else
  1294. {
  1295. SetLastError(ERROR_INVALID_PARAMETER);
  1296. }
  1297. }
  1298. }
  1299. //
  1300. // Release the printer info data.
  1301. //
  1302. FreeMem( pInfo );
  1303. //
  1304. // Close the printer handle if one was opened.
  1305. //
  1306. if( hPrinter )
  1307. {
  1308. ClosePrinter( hPrinter );
  1309. }
  1310. }
  1311. //
  1312. // If something failed preserve the last error.
  1313. //
  1314. if( !bStatus )
  1315. {
  1316. pParams->dwLastError = GetLastError();
  1317. }
  1318. return bStatus;
  1319. }
  1320. /*++
  1321. Routine Name:
  1322. PrintSettings_DisplayHelp
  1323. Routine Description:
  1324. Displays the printer settings command arguments.
  1325. Arguments:
  1326. pParams - pointer to paramter structure.
  1327. pSelection - pointer argument selection table.
  1328. Return Value:
  1329. TRUE success, FALSE error.
  1330. --*/
  1331. BOOL
  1332. PrintSettings_DisplayHelp(
  1333. IN AParams *pParams,
  1334. IN TSelect::Selection *pSelection
  1335. )
  1336. {
  1337. DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayHelp\n" ) );
  1338. TStatusB bStatus;
  1339. TRunDllDisplay Usage( NULL, pParams->pInfFileName, (pParams->pInfFileName && *pParams->pInfFileName) ?
  1340. TRunDllDisplay::kFile : TRunDllDisplay::kEditBox );
  1341. bStatus DBGNOCHK = VALID_OBJ( Usage );
  1342. if( bStatus )
  1343. {
  1344. TString strTemp;
  1345. TString strString;
  1346. TString strInt;
  1347. TString strStart;
  1348. TString strEnd;
  1349. TString strSep;
  1350. TString strFormat;
  1351. TString strBit;
  1352. LPCTSTR pszType;
  1353. //
  1354. // Set the title.
  1355. //
  1356. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_SET_ATTRIBUTE_TITLE );
  1357. bStatus DBGCHK = Usage.SetTitle( strTemp );
  1358. //
  1359. // Set the usage example.
  1360. //
  1361. bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_SET_ATTRIBUTE_USAGE );
  1362. bStatus DBGCHK = Usage.WriteOut( strTemp );
  1363. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") );
  1364. //
  1365. // Load some constant strings.
  1366. //
  1367. bStatus DBGCHK = strString.bLoadString( ghInst, IDS_RUNDLL_STRING );
  1368. bStatus DBGCHK = strInt.bLoadString( ghInst, IDS_RUNDLL_INTEGER );
  1369. bStatus DBGCHK = strStart.bLoadString( ghInst, IDS_RUNDLL_START );
  1370. bStatus DBGCHK = strEnd.bLoadString( ghInst, IDS_RUNDLL_END );
  1371. bStatus DBGCHK = strSep.bLoadString( ghInst, IDS_RUNDLL_SEP );
  1372. bStatus DBGCHK = strFormat.bLoadString( ghInst, IDS_RUNDLL_FORMAT );
  1373. for( ; pSelection->iKeyWord; pSelection++ )
  1374. {
  1375. switch( pSelection->eDataType )
  1376. {
  1377. case TSelect::kInt:
  1378. pszType = strInt;
  1379. break;
  1380. case TSelect::kString:
  1381. pszType = strString;
  1382. break;
  1383. case TSelect::kValTable:
  1384. case TSelect::kBitTable:
  1385. {
  1386. bStatus DBGCHK = strBit.bUpdate( strStart );
  1387. TSelect::SelectionBit *pSel = (TSelect::SelectionBit *)pSelection->pTable;
  1388. for( ; pSel->iKeyWord; pSel++ )
  1389. {
  1390. bStatus DBGCHK = strTemp.bLoadString( ghInst, pSel->iKeyWord );
  1391. bStatus DBGCHK = strBit.bCat( strTemp );
  1392. if( (pSel+1)->iKeyWord )
  1393. {
  1394. bStatus DBGCHK = strBit.bCat( strSep );
  1395. }
  1396. }
  1397. bStatus DBGCHK = strBit.bCat( strEnd );
  1398. pszType = strBit;
  1399. }
  1400. break;
  1401. default:
  1402. pszType = gszNULL;
  1403. break;
  1404. }
  1405. bStatus DBGCHK = strTemp.bLoadString( ghInst, pSelection->iKeyWord );
  1406. bStatus DBGCHK = strTemp.bFormat( strFormat, (LPCTSTR)strTemp, pszType );
  1407. bStatus DBGCHK = Usage.WriteOut( strTemp );
  1408. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") );
  1409. }
  1410. bStatus DBGCHK = strTemp.bLoadString( ghInst,IDS_RUNDLL_EXAMPLE0 );
  1411. bStatus DBGCHK = Usage.WriteOut( strTemp );
  1412. for( UINT i = IDS_RUNDLL_SET_EXAMPLE1; i <= IDS_RUNDLL_SET_EXAMPLE_END; i++ )
  1413. {
  1414. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n ") );
  1415. bStatus DBGCHK = strTemp.bLoadString( ghInst, i );
  1416. bStatus DBGCHK = Usage.WriteOut( strTemp );
  1417. }
  1418. bStatus DBGCHK = Usage.bDoModal();
  1419. }
  1420. return bStatus;
  1421. }
  1422. /*++
  1423. Routine Name:
  1424. PrintSettings_DisplayInformation
  1425. Routine Description:
  1426. Displays the printer settings
  1427. Arguments:
  1428. pParams - pointer to paramter structure.
  1429. pSelection - pointer argument selection table.
  1430. Return Value:
  1431. TRUE success, FALSE error.
  1432. --*/
  1433. BOOL
  1434. PrintSettings_DisplayInformation(
  1435. IN AParams *pParams,
  1436. IN TSelect::Selection *pSelection
  1437. )
  1438. {
  1439. DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayInformation\n" ) );
  1440. TStatus Status( DBG_WARN );
  1441. TString strTemp;
  1442. TString strKeyword;
  1443. TString strFormat1;
  1444. TString strFormat2;
  1445. TString strTitle;
  1446. TStatusB bStatus;
  1447. bStatus DBGNOCHK = FALSE;
  1448. DWORD dwAccess = 0;
  1449. HANDLE hPrinter = NULL;
  1450. PPRINTER_INFO_2 pInfo = NULL;
  1451. DWORD cbInfo = 0;
  1452. //
  1453. // Open the printer.
  1454. //
  1455. Status DBGCHK = TPrinter::sOpenPrinter( pParams->pPrinterName, &dwAccess, &hPrinter );
  1456. if( Status == ERROR_SUCCESS )
  1457. {
  1458. //
  1459. // Get the printer data.
  1460. //
  1461. bStatus DBGNOCHK = VDataRefresh::bGetPrinter( hPrinter, 2, (PVOID *)&pInfo, (PDWORD)&cbInfo );
  1462. if( bStatus )
  1463. {
  1464. //
  1465. // Display the printer data.
  1466. //
  1467. TRunDllDisplay Usage( NULL, pParams->pInfFileName, (pParams->pInfFileName && *pParams->pInfFileName) ?
  1468. TRunDllDisplay::kFile : TRunDllDisplay::kEditBox );
  1469. bStatus DBGNOCHK = VALID_OBJ( Usage );
  1470. if( bStatus )
  1471. {
  1472. Usage.vSetTabStops(64);
  1473. bStatus DBGCHK = strTitle.bLoadString( ghInst, IDS_RUNDLL_DISPLAY_TITLE );
  1474. bStatus DBGCHK = strTitle.bCat( pParams->pPrinterName );
  1475. Usage.SetTitle( strTitle );
  1476. bStatus DBGCHK = strFormat1.bLoadString( ghInst, IDS_RUNDLL_DISPLAY_FORMAT1 );
  1477. bStatus DBGCHK = strFormat2.bLoadString( ghInst, IDS_RUNDLL_DISPLAY_FORMAT2 );
  1478. for( ; pSelection->iKeyWord; pSelection++ )
  1479. {
  1480. bStatus DBGCHK = strKeyword.bLoadString( ghInst, pSelection->iKeyWord );
  1481. switch( pSelection->eDataType )
  1482. {
  1483. case TSelect::kString:
  1484. bStatus DBGCHK = strTemp.bFormat( strFormat1, (LPCTSTR)strKeyword, *(LPCTSTR *)((PBYTE)pInfo+pSelection->iOffset) );
  1485. break;
  1486. case TSelect::kInt:
  1487. bStatus DBGCHK = strTemp.bFormat( strFormat2, (LPCTSTR)strKeyword, *(UINT *)((PBYTE)pInfo+pSelection->iOffset) );
  1488. break;
  1489. case TSelect::kBitTable:
  1490. bStatus DBGCHK = PrintSettings_DisplayAttributes( strTemp, pSelection, *(UINT *)((PBYTE)pInfo+pSelection->iOffset) );
  1491. bStatus DBGCHK = strTemp.bFormat( strFormat1, (LPCTSTR)strKeyword, (LPCTSTR)strTemp );
  1492. break;
  1493. case TSelect::kValTable:
  1494. bStatus DBGCHK = PrintSettings_DisplayStatus( strTemp, pSelection, *(UINT *)((PBYTE)pInfo+pSelection->iOffset) );
  1495. bStatus DBGCHK = strTemp.bFormat( strFormat1, (LPCTSTR)strKeyword, (LPCTSTR)strTemp );
  1496. break;
  1497. default:
  1498. bStatus DBGCHK = strTemp.bUpdate( NULL );
  1499. break;
  1500. }
  1501. bStatus DBGCHK = Usage.WriteOut( strTemp );
  1502. bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") );
  1503. }
  1504. bStatus DBGCHK = Usage.bDoModal();
  1505. }
  1506. }
  1507. //
  1508. // Release the printer info data.
  1509. //
  1510. FreeMem( pInfo );
  1511. //
  1512. // Close the printer handle if one was opened.
  1513. //
  1514. if( hPrinter )
  1515. {
  1516. ClosePrinter( hPrinter );
  1517. }
  1518. }
  1519. return bStatus;
  1520. }
  1521. /*++
  1522. Routine Name:
  1523. PrintSettings_DisplayAttributes
  1524. Routine Description:
  1525. Get the current printer attributes in a displayable form.
  1526. Arguments:
  1527. Return Value:
  1528. TRUE success, FALSE error.
  1529. --*/
  1530. BOOL
  1531. PrintSettings_DisplayAttributes(
  1532. IN TString &strBit,
  1533. IN TSelect::Selection *pSelection,
  1534. IN UINT uAttributes
  1535. )
  1536. {
  1537. DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayAttributes\n" ) );
  1538. TStatusB bStatus;
  1539. TString strStart;
  1540. TString strEnd;
  1541. TString strSep;
  1542. TString strTemp;
  1543. bStatus DBGCHK = strStart.bLoadString( ghInst, IDS_RUNDLL_START );
  1544. bStatus DBGCHK = strEnd.bLoadString( ghInst, IDS_RUNDLL_END );
  1545. bStatus DBGCHK = strSep.bLoadString( ghInst, IDS_RUNDLL_SEP );
  1546. TSelect::SelectionBit *pSel = (TSelect::SelectionBit *)pSelection->pTable;
  1547. bStatus DBGCHK = strBit.bUpdate( strStart );
  1548. for( ; pSel->iKeyWord; pSel++ )
  1549. {
  1550. if( uAttributes & pSel->uBit )
  1551. {
  1552. bStatus DBGCHK = strTemp.bLoadString( ghInst, pSel->iKeyWord );
  1553. bStatus DBGCHK = strBit.bCat( strTemp );
  1554. bStatus DBGCHK = strBit.bCat( strSep );
  1555. }
  1556. }
  1557. bStatus DBGCHK = strBit.bCat( strEnd );
  1558. return TRUE;
  1559. }
  1560. /*++
  1561. Routine Name:
  1562. PrintSettings_DisplayStatus
  1563. Routine Description:
  1564. Get the status in a displayable form.
  1565. Arguments:
  1566. Return Value:
  1567. TRUE success, FALSE error.
  1568. --*/
  1569. BOOL
  1570. PrintSettings_DisplayStatus(
  1571. IN TString &strVal,
  1572. IN TSelect::Selection *pSelection,
  1573. IN UINT uStatus
  1574. )
  1575. {
  1576. DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayStatus\n" ) );
  1577. TStatusB bStatus;
  1578. TString strStart;
  1579. TString strEnd;
  1580. TString strTemp;
  1581. bStatus DBGCHK = strStart.bLoadString( ghInst, IDS_RUNDLL_START );
  1582. bStatus DBGCHK = strEnd.bLoadString( ghInst, IDS_RUNDLL_END );
  1583. TSelect::SelectionVal *pSel = (TSelect::SelectionVal *)pSelection->pTable;
  1584. bStatus DBGCHK = strVal.bUpdate( strStart );
  1585. for( ; pSel->iKeyWord; pSel++ )
  1586. {
  1587. if( uStatus == pSel->uValue )
  1588. {
  1589. bStatus DBGCHK = strTemp.bLoadString( ghInst, pSel->iKeyWord );
  1590. bStatus DBGCHK = strVal.bCat( strTemp );
  1591. break;
  1592. }
  1593. }
  1594. bStatus DBGCHK = strVal.bCat( strEnd );
  1595. return TRUE;
  1596. }
  1597. /********************************************************************
  1598. RunDll Usage
  1599. ********************************************************************/
  1600. TRunDllDisplay::
  1601. TRunDllDisplay(
  1602. IN HWND hWnd,
  1603. IN LPCTSTR pszFileName,
  1604. IN DisplayType Display
  1605. ) : _hWnd( hWnd ),
  1606. _bValid( FALSE ),
  1607. _Display( Display ),
  1608. _pFile( NULL ),
  1609. _cxGrip( 0 ),
  1610. _cyGrip( 0 ),
  1611. _hwndGrip( NULL ),
  1612. _cTabStop( 0 ),
  1613. _dwTabStop( 0 )
  1614. {
  1615. memset( &_ptLastSize, 0, sizeof(_ptLastSize) );
  1616. memset( &_ptMinTrack, 0, sizeof(_ptMinTrack) );
  1617. switch( _Display )
  1618. {
  1619. case kFile:
  1620. _pFile = new TFile( pszFileName );
  1621. _bValid = VALID_PTR( _pFile );
  1622. break;
  1623. case kEditBox:
  1624. _bValid = TRUE;
  1625. break;
  1626. default:
  1627. SPLASSERT( FALSE );
  1628. _bValid = FALSE;
  1629. break;
  1630. }
  1631. }
  1632. TRunDllDisplay::
  1633. ~TRunDllDisplay(
  1634. VOID
  1635. )
  1636. {
  1637. if( _hwndGrip )
  1638. {
  1639. DestroyWindow( _hwndGrip );
  1640. }
  1641. delete _pFile;
  1642. }
  1643. BOOL
  1644. TRunDllDisplay::
  1645. WriteOut(
  1646. LPCTSTR pszData
  1647. )
  1648. {
  1649. SPLASSERT( pszData );
  1650. return _StringOutput.bCat(pszData);
  1651. }
  1652. BOOL
  1653. TRunDllDisplay::
  1654. bValid(
  1655. VOID
  1656. )
  1657. {
  1658. return _bValid;
  1659. }
  1660. VOID
  1661. TRunDllDisplay::
  1662. vSetTabStops(
  1663. IN UINT uTabStop
  1664. )
  1665. {
  1666. _cTabStop = 1;
  1667. _dwTabStop = uTabStop;
  1668. }
  1669. BOOL
  1670. TRunDllDisplay::
  1671. bDoModal(
  1672. VOID
  1673. )
  1674. {
  1675. TStatusB bStatus;
  1676. switch( _Display )
  1677. {
  1678. case kEditBox:
  1679. bStatus DBGCHK = (BOOL)DialogBoxParam( ghInst,
  1680. MAKEINTRESOURCE( DLG_RUNDLL ),
  1681. _hWnd,
  1682. MGenericDialog::SetupDlgProc,
  1683. (LPARAM)this );
  1684. break;
  1685. case kFile:
  1686. bStatus DBGCHK = _pFile->bWrite( _StringOutput );
  1687. break;
  1688. default:
  1689. bStatus DBGNOCHK = FALSE;
  1690. break;
  1691. }
  1692. return bStatus;
  1693. }
  1694. BOOL
  1695. TRunDllDisplay::
  1696. SetTitle(
  1697. IN LPCTSTR pszData
  1698. )
  1699. {
  1700. TStatusB bStatus;
  1701. bStatus DBGCHK = _StringTitle.bUpdate(pszData);
  1702. return bStatus;
  1703. }
  1704. BOOL
  1705. TRunDllDisplay::
  1706. bSetUI(
  1707. VOID
  1708. )
  1709. {
  1710. TStatusB bStatus;
  1711. bStatus DBGCHK = bSetEditText( _hDlg, IDC_RUNDLL_TITLE, _StringTitle );
  1712. bStatus DBGCHK = bSetEditText( _hDlg, IDC_RUNDLL_TEXT, _StringOutput );
  1713. SendDlgItemMessage( _hDlg, IDC_RUNDLL_TEXT, EM_SETMODIFY, TRUE, 0 );
  1714. //
  1715. // Set any applicable tab stops.
  1716. //
  1717. SendDlgItemMessage( _hDlg, IDC_RUNDLL_TEXT, EM_SETTABSTOPS, _cTabStop, (LPARAM)&_dwTabStop );
  1718. //
  1719. // Set the initial size.
  1720. //
  1721. RECT rect;
  1722. GetWindowRect(_hDlg, &rect);
  1723. _ptLastSize.x = rect.right - rect.left;
  1724. _ptLastSize.y = rect.bottom - rect.top;
  1725. //
  1726. // Save the minimum track information.
  1727. //
  1728. _ptMinTrack.x = rect.right - rect.left;
  1729. _ptMinTrack.y = rect.bottom - rect.top;
  1730. //
  1731. // Create the sizing grip.
  1732. //
  1733. RECT rc;
  1734. GetClientRect(_hDlg, &rc);
  1735. _cxGrip = GetSystemMetrics(SM_CXVSCROLL);
  1736. _cyGrip = GetSystemMetrics(SM_CYHSCROLL);
  1737. _hwndGrip = CreateWindow( TEXT("Scrollbar"),
  1738. NULL,
  1739. WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS |
  1740. WS_CLIPCHILDREN | SBS_BOTTOMALIGN | SBS_SIZEGRIP |
  1741. SBS_SIZEBOXBOTTOMRIGHTALIGN,
  1742. rc.right - _cxGrip,
  1743. rc.bottom - _cyGrip,
  1744. _cxGrip,
  1745. _cyGrip,
  1746. _hDlg,
  1747. (HMENU)-1,
  1748. ghInst,
  1749. NULL );
  1750. if( !_hwndGrip )
  1751. {
  1752. bStatus DBGCHK = FALSE;
  1753. }
  1754. //
  1755. // Set the dialog icon.
  1756. //
  1757. INT cxIcon = GetSystemMetrics(SM_CXICON);
  1758. INT cyIcon = GetSystemMetrics(SM_CYICON);
  1759. HANDLE hIcon;
  1760. if( hIcon = LoadImage( ghInst, MAKEINTRESOURCE(IDI_PRINTER), IMAGE_ICON, cxIcon, cyIcon, 0 ) )
  1761. {
  1762. SendMessage( _hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon );
  1763. }
  1764. //
  1765. // The small icon size is already cached for the queue view.
  1766. //
  1767. if( hIcon = LoadImage( ghInst, MAKEINTRESOURCE(IDI_PRINTER), IMAGE_ICON, gcxSmIcon, gcySmIcon, 0 ) )
  1768. {
  1769. SendMessage( _hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon );
  1770. }
  1771. return bStatus;
  1772. }
  1773. BOOL
  1774. TRunDllDisplay::
  1775. bHandle_WM_SIZE(
  1776. IN WPARAM wParam,
  1777. IN LPARAM lParam
  1778. )
  1779. {
  1780. INT width = LOWORD( lParam );
  1781. INT height = HIWORD( lParam );
  1782. //
  1783. // Get the current window size.
  1784. //
  1785. RECT rect;
  1786. GetWindowRect(_hDlg, &rect);
  1787. //
  1788. // Calculate the deltas in the x and y positions that we need to move
  1789. // each of the child controls.
  1790. //
  1791. INT dx = (rect.right - rect.left) - _ptLastSize.x;
  1792. INT dy = (rect.bottom - rect.top) - _ptLastSize.y;
  1793. //
  1794. // Update the new size.
  1795. //
  1796. _ptLastSize.x = rect.right - rect.left;
  1797. _ptLastSize.y = rect.bottom - rect.top;
  1798. //
  1799. // Set the sizing grip to the correct location.
  1800. //
  1801. if( _hwndGrip )
  1802. {
  1803. SetWindowPos( _hwndGrip,
  1804. NULL,
  1805. width - _cxGrip,
  1806. height - _cyGrip,
  1807. _cxGrip,
  1808. _cyGrip,
  1809. SWP_NOZORDER | SWP_NOACTIVATE );
  1810. }
  1811. //
  1812. // Move the ok button.
  1813. //
  1814. GetWindowRect(GetDlgItem(_hDlg, IDOK), &rect);
  1815. MapWindowPoints(NULL, _hDlg, (LPPOINT)&rect, 2);
  1816. SetWindowPos(GetDlgItem(_hDlg, IDOK),
  1817. NULL,
  1818. rect.left+dx,
  1819. rect.top+dy,
  1820. 0,
  1821. 0,
  1822. SWP_NOZORDER|SWP_NOSIZE);
  1823. //
  1824. // Resize the edit control
  1825. //
  1826. GetWindowRect(GetDlgItem(_hDlg, IDC_RUNDLL_TEXT), &rect);
  1827. MapWindowPoints(NULL, _hDlg, (LPPOINT)&rect, 2);
  1828. SetWindowPos(GetDlgItem(_hDlg, IDC_RUNDLL_TEXT),
  1829. NULL,
  1830. 0,
  1831. 0,
  1832. (rect.right-rect.left)+dx,
  1833. (rect.bottom-rect.top)+dy,
  1834. SWP_NOZORDER|SWP_NOMOVE);
  1835. return FALSE;
  1836. }
  1837. BOOL
  1838. TRunDllDisplay::
  1839. bHandle_WM_GETMINMAXINFO(
  1840. IN WPARAM wParam,
  1841. IN LPARAM lParam
  1842. )
  1843. {
  1844. BOOL bRetval = TRUE;
  1845. LPMINMAXINFO pmmi = (LPMINMAXINFO)lParam;
  1846. if( ( _ptMinTrack.x != 0 ) || ( _ptMinTrack.y != 0 ) )
  1847. {
  1848. pmmi->ptMinTrackSize = _ptMinTrack;
  1849. bRetval = FALSE;
  1850. }
  1851. return bRetval;
  1852. }
  1853. BOOL
  1854. TRunDllDisplay::
  1855. bHandleMessage(
  1856. IN UINT uMsg,
  1857. IN WPARAM wParam,
  1858. IN LPARAM lParam
  1859. )
  1860. {
  1861. BOOL bStatus = TRUE;
  1862. switch (uMsg)
  1863. {
  1864. case WM_INITDIALOG:
  1865. bSetUI();
  1866. break;
  1867. case WM_SIZE:
  1868. bStatus = bHandle_WM_SIZE( wParam, lParam );
  1869. break;
  1870. case WM_GETMINMAXINFO:
  1871. bStatus = bHandle_WM_GETMINMAXINFO( wParam, lParam );
  1872. break;
  1873. case WM_COMMAND:
  1874. switch ( LOWORD( wParam ) )
  1875. {
  1876. case IDOK:
  1877. case IDCANCEL:
  1878. EndDialog( _hDlg, LOWORD( wParam ) );
  1879. break;
  1880. default:
  1881. bStatus = FALSE;
  1882. break;
  1883. }
  1884. default:
  1885. bStatus = FALSE;
  1886. break;
  1887. }
  1888. return bStatus;
  1889. }
  1890. /********************************************************************
  1891. Very simple file output class
  1892. ********************************************************************/
  1893. TFile::
  1894. TFile(
  1895. IN LPCTSTR pszFileName,
  1896. IN BOOL bNoUnicodeByteMark
  1897. ) : _strFileName( pszFileName ),
  1898. _hFile( INVALID_HANDLE_VALUE ),
  1899. _bValid( FALSE )
  1900. {
  1901. if( !_strFileName.bEmpty() )
  1902. {
  1903. _hFile = CreateFile( _strFileName,
  1904. GENERIC_READ | GENERIC_WRITE,
  1905. 0,
  1906. NULL,
  1907. CREATE_ALWAYS,
  1908. FILE_ATTRIBUTE_NORMAL,
  1909. NULL );
  1910. if( _hFile != INVALID_HANDLE_VALUE )
  1911. {
  1912. _bValid = TRUE;
  1913. }
  1914. //
  1915. // If we are built for unicode then write the unicode byte mark.
  1916. //
  1917. #ifdef UNICODE
  1918. if( _bValid && !bNoUnicodeByteMark )
  1919. {
  1920. WORD wUnicodeByteMark = kUnicodePrefix;
  1921. _bValid = bWrite( sizeof( wUnicodeByteMark ), reinterpret_cast<LPBYTE>( &wUnicodeByteMark ) );
  1922. }
  1923. #endif
  1924. }
  1925. }
  1926. TFile::
  1927. ~TFile(
  1928. VOID
  1929. )
  1930. {
  1931. if( _hFile != INVALID_HANDLE_VALUE )
  1932. {
  1933. CloseHandle( _hFile );
  1934. }
  1935. }
  1936. BOOL
  1937. TFile::
  1938. bValid(
  1939. VOID
  1940. )
  1941. {
  1942. return _bValid;
  1943. }
  1944. BOOL
  1945. TFile::
  1946. bWrite(
  1947. IN TString &strString,
  1948. OUT UINT *pBytesWritten OPTIONAL
  1949. )
  1950. {
  1951. return bWrite( strString.uLen() * sizeof( TCHAR ),
  1952. reinterpret_cast<LPBYTE>( const_cast<LPTSTR>( static_cast<LPCTSTR>( strString ) ) ),
  1953. pBytesWritten );
  1954. }
  1955. BOOL
  1956. TFile::
  1957. bWrite(
  1958. IN UINT uSize,
  1959. IN LPBYTE pData,
  1960. OUT UINT *pBytesWritten OPTIONAL
  1961. )
  1962. {
  1963. DWORD dwWritten;
  1964. TStatusB bStatus;
  1965. bStatus DBGCHK = WriteFile(_hFile,
  1966. pData,
  1967. uSize,
  1968. &dwWritten,
  1969. NULL );
  1970. if( bStatus )
  1971. {
  1972. if( pBytesWritten )
  1973. {
  1974. *pBytesWritten = dwWritten;
  1975. }
  1976. bStatus DBGCHK = dwWritten == uSize ? TRUE : FALSE;
  1977. }
  1978. return bStatus;
  1979. }