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.

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