Windows NT 4.0 source code leak
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.

7677 lines
207 KiB

4 years ago
  1. /*---File: printman.c ----------------------------------------------------
  2. *
  3. * Description:
  4. * NT Print Manager main function and Window Procedures.
  5. *
  6. * This document contains confidential/proprietary information.
  7. * Copyright (c) 1990-1992 Microsoft Corporation, All Rights Reserved.
  8. *
  9. * Revision History:
  10. * [00] 21-Nov-90 stevecat created
  11. * [01] 03-Jan-91 stevecat Modified to use Windows MDI
  12. * [02] 25-Mar-91 stevecat Modified to use NT WINSPOOL APIs
  13. * [03] 13-Jan-92 stevecat New PrintMan UI
  14. *
  15. * March 1992 + andrewbe Completely updated and new function added
  16. *
  17. * ---------------------------------------------------------------------- */
  18. /* =========================================================================
  19. Header files
  20. ========================================================================= */
  21. /* Application-specific */
  22. #include "printman.h"
  23. #include <lmcons.h>
  24. #include <lmerr.h>
  25. #include <uiexport.h>
  26. #include <stdarg.h>
  27. #include <winuserp.h>
  28. #include <shellapi.h>
  29. #include <stddef.h>
  30. /* ========================================================================
  31. Definitions
  32. ======================================================================== */
  33. #define ISF_NAME 0
  34. #define ISF_STATUS 1
  35. #define ISF_WAITING 2
  36. #define SF_COUNT 3
  37. #define SW2WS( sw ) \
  38. ( sw == SW_SHOWMINIMIZED ? WS_MINIMIZE \
  39. : sw == SW_SHOWMAXIMIZED ? WS_MAXIMIZE \
  40. : 0 )
  41. #define INIVALUES 8
  42. #define RECTSIDES 4
  43. #define OPTION_NOTOOLBAR 0x00000001
  44. #define OPTION_NOSTATUSBAR 0x00000002
  45. #define OPTION_NOSAVESETTINGS 0x00000004
  46. /* Define our own IDs for menu popups, since USER doesn't:
  47. */
  48. #define POPUP_PRINTER 0
  49. #define POPUP_DOCUMENT 1
  50. #define POPUP_OPTIONS 2
  51. #define POPUP_SECURITY 3
  52. #define POPUP_WINDOW 4
  53. #define POPUP_HELP 5
  54. #define POPUP_COUNT 6
  55. #define GETMDIWIN( hwnd ) \
  56. (PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN )
  57. #define GETCONTEXT( hwnd ) \
  58. ( (PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN ) )->pContext
  59. #define GETQUEUE( hwnd ) \
  60. (PQUEUE)( (PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN ) )->pContext
  61. #define GETCOLUMN(hwnd) \
  62. ( (PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN ) )->pColumns
  63. #define STATUS_MODE_NORMAL 0
  64. #define STATUS_MODE_HELP 1
  65. #define WM_INIT_PRINTER_WINDOWS WM_USER+0xa
  66. #define WM_INIT_SERVER_WINDOWS WM_USER+0xb
  67. #define WM_REG_NOTIFY_CHANGE_KEY_VALUE WM_USER+0xc
  68. /*
  69. * Declarations for external calls
  70. * -------------------------------
  71. */
  72. /* ========================================================================
  73. Structures and Typedefs
  74. ======================================================================== */
  75. typedef struct _SAVEDWINDOWPOS
  76. {
  77. int left;
  78. int top;
  79. int width;
  80. int height;
  81. int xicon;
  82. int yicon;
  83. int sw;
  84. DWORD options;
  85. }
  86. SAVEDWINDOWPOS, *PSAVEDWINDOWPOS;
  87. typedef struct _REGISTRY_DATA
  88. {
  89. WINDOWPLACEMENT WindowPlacement;
  90. DWORD Options;
  91. INT Headers[ANYSIZE_ARRAY];
  92. }
  93. REGISTRY_DATA, *PREGISTRY_DATA;
  94. /* ==========================================================================
  95. Global Data
  96. ========================================================================== */
  97. #if DBG
  98. DWORD GLOBAL_DEBUG_FLAGS = DBG_ERROR | DBG_WARNING | DBG_BREAK_ON_ERROR;
  99. #endif
  100. TCHAR szPrintManagerClass[] = TEXT("Print Manager Frame");
  101. TCHAR szMenuClass[] = TEXT("PrintManMenu"); // This must match the name in res.rc
  102. TCHAR szChildClass[] = TEXT("Printer MDI Child");
  103. // External functions
  104. BOOL RegisterArrowClass (HANDLE hModule);
  105. // Data
  106. TCHAR szNtLanMan[] = TEXT("NTLANMAN");
  107. CHAR szI_SystemFocusDialog[] = "I_SystemFocusDialog";
  108. BOOL bToolBar;
  109. BOOL bStatusBar;
  110. BOOL bSaveSettings;
  111. //TCHAR szStatusBar[] = TEXT("StatusBar");
  112. int dyBorder; /* System Border Width/Height */
  113. int dyBorderx2; /* System Border Width/Height * 2 */
  114. //int dyStatus; /* Status Bar height */
  115. int dxStatusField;
  116. int dxStatPrtField; // Width of strStatusName text box
  117. int dxStatProgField; // Width of strStatusStatus text box
  118. int dxStatQueField; // Width of strStatusWaiting text box
  119. DWORD cx, cy; // Average char width/height - default font
  120. int dxDefaultLabel;
  121. int dyDefaultLabel;
  122. HBITMAP hbmBitmaps = NULL;
  123. HBITMAP hbmDefault = NULL;
  124. HBITMAP hbmMasks = NULL;
  125. HDC hdcMem = NULL;
  126. HDC hdcMasks = NULL;
  127. HFONT hfontHelv;
  128. HFONT hfontHelvBold;
  129. TCHAR szHelv[] = TEXT("MS Shell Dlg");
  130. TCHAR sz8[] = TEXT("8");
  131. TCHAR sz10[] = TEXT("10");
  132. TCHAR szNULL[] = TEXT("");
  133. TCHAR szTitleFormat[] = TEXT("%s - %s");
  134. TCHAR szPrintManHlp[] = TEXT("PRINTMAN.HLP");
  135. WCHAR szLPrintManHlp[] = L"PRINTMAN.HLP";
  136. DWORD SysColorHighlight;
  137. DWORD SysColorHighlightText;
  138. DWORD SysColorWindow;
  139. DWORD SysColorWindowText;
  140. DWORD SysColorBtnFace;
  141. DWORD SysColorBtnText;
  142. DWORD SysColorBtnHighlight;
  143. DWORD SysColorBtnShadow;
  144. DWORD SysColorWindowFrame;
  145. TCHAR szInternational[] = TEXT("intl");
  146. BOOL TwentyFourHourClock;
  147. // JAPAN v-hirot July.07.1993 for New Prefix
  148. // TimePrefix is for Japanese usage - krishnag
  149. BOOL TimePrefix;
  150. // CountryCode - krishnag Sept 1, 1993
  151. // We have a two code paths; one for Japan; one for the rest of the world
  152. BOOL bJapan;
  153. TCHAR szTimeSep[TIMESEP_LENGTH];
  154. TCHAR szAMPM[2][AMPM_LENGTH];
  155. BOOL TimeFormatLeadingZero;
  156. BOOL MetricMeasurement;
  157. TCHAR szDecimalPoint[2];
  158. DWORD DecimalDigits;
  159. DWORD LeadingZero;
  160. TCHAR szSizeFormat[14];
  161. UINT WM_Help = 0;
  162. UINT WM_DragList = 0;
  163. HKEY hPrinterKey; // Per User Registry Printer Key
  164. TCHAR *szRegistryPrinter=TEXT("Printers");
  165. HWND hwndStatus;
  166. DWORD WinHelpMenuID = 0; /* Global set in response to WM_MENUSELECT */
  167. /* Set this before we call AddPrinter, so that we don't need to do anything
  168. * when LocalServerThread posts us a WM_PRINTER_ADDED message:
  169. */
  170. BOOL PrinterAdded = FALSE;
  171. HANDLE hLocalServer;
  172. extern HANDLE ThreadMessageRead;
  173. extern HANDLE ThreadMessageWritten;
  174. extern MSG ThreadMessage;
  175. /* ==========================================================================
  176. Local Data
  177. ========================================================================== */
  178. TEXTMETRIC tm;
  179. COLUMN MDIPrinterDefaultColumn[MDIHEAD_JOB_COUNT];
  180. COLUMN MDIServerDefaultColumn[MDIHEAD_PRINTER_COUNT];
  181. int HeaderHeight;
  182. /* Minimum number of 'X' character widths for the columns:
  183. */
  184. INT MDIPrinterMinimumCharacterWidth[] = { 12, 20, 0, 0, 0, 0, 0 };
  185. INT MDIServerMinimumCharacterWidth[] = { 25, 0, 0, 20, 30 };
  186. HCURSOR hcursorArrow;
  187. HCURSOR hcursorReorder;
  188. HCURSOR hcursorWait;
  189. HICON hiconPrinter;
  190. HICON hiconServer;
  191. HICON hiconConnect;
  192. HICON hiconShared;
  193. //HHOOK hhookMessage;
  194. HHOOK hhookGetMsg;
  195. TCHAR szRegPrinters[] = TEXT("Printers");
  196. TCHAR szRegServers[] = TEXT("Servers");
  197. //
  198. // Lowercase, like win31.
  199. //
  200. PTCHAR szWindows = TEXT("windows");
  201. PTCHAR szDevices = TEXT("devices");
  202. PTCHAR szDevice = TEXT("device");
  203. REGISTRY_ENTRY RegistryEntries = { REG_BINARY, sizeof(REGISTRY_DATA) };
  204. WNDPROC DefListboxWndProc;
  205. /* Handles of the popup menus needed to put up help in the status bar
  206. * in response to menu selections. (Popups don't have IDs, unfortunately.)
  207. */
  208. HMENU hmenuPopups[POPUP_COUNT];
  209. DWORD pMenuHelpIDs[] =
  210. {
  211. 0, 0,
  212. IDS_HELPPRINTER, POPUP_PRINTER,
  213. IDS_HELPDOCUMENT, POPUP_DOCUMENT,
  214. IDS_HELPOPTIONS, POPUP_OPTIONS,
  215. IDS_HELPSECURITY, POPUP_SECURITY,
  216. IDS_HELPWINDOW, POPUP_WINDOW,
  217. IDS_HELPHELP, POPUP_HELP
  218. };
  219. BOOL NetworkInstalled = FALSE;
  220. /* Global hack so we can ignore registry change notification
  221. * when it was brought about by our own actions:
  222. */
  223. BOOL ExpectingNotifyChangeKeyValue = FALSE;
  224. /* ==========================================================================
  225. Local Function Declarations
  226. ========================================================================== */
  227. LONG FrameCreate(HWND hWnd, LPCREATESTRUCT pCreateStruct);
  228. VOID GetSystemColors( VOID );
  229. BOOL UserHasNetworkAccess( VOID );
  230. VOID RemoveNetworkMenuItems( HWND hwnd );
  231. BOOL NetworkIsInstalled( VOID );
  232. VOID SetStatusMode( int Mode, BOOL Update );
  233. LONG FrameThreadError(HWND hWnd, PMDIWIN_INFO pMDIWinInfo, DWORD dwError);
  234. LONG FrameInitMenu(HWND hWnd);
  235. LONG FrameMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam );
  236. LONG FramePaint(HWND hWnd);
  237. VOID FrameSize(HWND hWnd, WPARAM Type, long Dimensions);
  238. VOID FrameClose(HWND hWnd);
  239. VOID FrameHelp(HWND hwnd, UINT HelpID);
  240. VOID SaveWindowPos( HWND hwnd, DWORD Options, BOOL MDIWindow );
  241. LONG FrameCommandConnectToPrinter(HWND hWnd);
  242. //LONG FrameCommandRemoveConnection(HWND hWnd);
  243. LONG FrameCommandCreatePrinter(HWND hWnd);
  244. LONG FrameCommandProperties(HWND hWnd);
  245. LONG FrameCommandDeletePrinter(HWND hWnd);
  246. LONG FrameCommandDeletePrinterHelper(HWND hWnd, HWND hwndMDI, BOOL bConfirm);
  247. BOOL DeleteLocalPrinter(HWND hwnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm);
  248. BOOL DeleteRemotePrinter(HWND hwnd, PSERVER_CONTEXT pServerContext, BOOL bConfirm);
  249. BOOL DeleteConnection(HWND hWnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm);
  250. HWND FindPrinterWindow( LPTSTR pPrinterName );
  251. LONG FrameCommandPrinterPauseResume(HWND hWnd, BOOL bPause);
  252. //BOOL SetPrinterTitle( HWND hwnd, PTCHAR pPrinterName, DWORD Status );
  253. BOOL SetMDITitle( HWND hwnd, PMDIWIN_INFO pInfo );
  254. LONG FrameCommandPurgePrinter(HWND hWnd);
  255. LONG FrameCommandForms(HWND hWnd);
  256. LONG FrameCommandServerViewer(HWND hWnd);
  257. LONG FrameCommandChangePrinter(HWND hWnd);
  258. LONG FrameCommandRemoveDoc(HWND hWnd);
  259. LONG FrameCommandDocDetails(HWND hWnd);
  260. LONG FrameCommandDocumentPauseResume(HWND hWnd, WORD PauseResume);
  261. LONG FrameCommandRestart(HWND hWnd);
  262. LONG FrameCommandFont(HWND hWnd);
  263. LONG FrameCommandRefreshRate(HWND hWnd);
  264. LONG FrameCommandToolbar(HWND hWnd);
  265. LONG FrameCommandStatusbar(HWND hWnd);
  266. LONG FrameCommandSaveSettings(HWND hWnd);
  267. LONG FrameCommandPermissions(HWND hWnd);
  268. LONG FrameCommandAuditing(HWND hWnd);
  269. LONG FrameCommandOwner(HWND hWnd);
  270. LONG FrameCommandClose(HWND hWnd);
  271. LONG FrameCommandAbout(HWND hWnd);
  272. LONG FrameCommandReturn();
  273. VOID FrameCommandDefaultPrinter(HWND hwnd, WORD Command);
  274. VOID FrameCommandToolbarNotify( HWND hwnd, WPARAM wParam, LPARAM lParam );
  275. VOID FrameCommandTab(HWND hwnd);
  276. LONG FrameCommandDefault(HWND hWnd, WPARAM wParam, LONG lParam);
  277. VOID FrameSysColorChange( VOID );
  278. VOID FrameWinIniChange( HWND hWnd, LPTSTR pSection );
  279. VOID FramePrinterAdded( HWND hwnd, DWORD dwType );
  280. VOID FrameRegNotifyChangeKeyValue( HWND hwnd, HKEY hWindowsKey );
  281. VOID CreateMDIDefaultColumns( HWND hwnd, DWORD cColumns, DWORD idFirstColumn,
  282. PCOLUMN pColumns, PINT pDefaultWidths );
  283. PMDIWIN_INFO CreateQueueWindowInfo( PQUEUE pQueue, PINT pHeaders );
  284. DWORD CALLBACK CreateServerWindow( HWND hwnd, LPTSTR pServerName, HANDLE hServer );
  285. PMDIWIN_INFO CreateServerWindowInfo( PSERVER_CONTEXT pContext, PINT pHeaders );
  286. BOOL InitServerChildWindows( HWND hWnd );
  287. VOID FormatData( PBYTE pData, int Datatype, LPTSTR string );
  288. int GetPrinterStatusString( DWORD Status, LPTSTR string );
  289. VOID MDICreate( HWND hWnd, LONG lParam );
  290. VOID SetDefaultColumnWidths( HWND hwnd, PMDIWIN_INFO pMDIWinInfo,
  291. PINT pColumnWidths );
  292. LONG MDIPaint(HWND hwnd, WPARAM wParam, LPARAM lParam);
  293. BOOL MDIEraseBkgnd(HWND hwnd, HDC hdc);
  294. HICON MDIQueryDragIcon(HWND hwnd);
  295. LONG MDIMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam );
  296. VOID MDICommandObjListSelChange( HWND hwnd );
  297. VOID SetObjectSelection( PMDIWIN_INFO pInfo, DWORD Selection );
  298. VOID MDICommandObjListDblClk( HWND hwnd );
  299. VOID MDICommandHeaderBeginDrag( HWND hwnd, PPOINT pCursorPos );
  300. VOID MDICommandHeaderDragging( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot );
  301. VOID MDICommandHeaderEndDrag( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot );
  302. VOID InvertDragMark( HWND hwnd, PPOINT pCursorPos );
  303. VOID UpdateColumns( HWND hwnd, HD_NOTIFY * lpNot );
  304. BOOL MDIClose( HWND hwnd );
  305. VOID MDIVKeyToItemSpace( HWND hwnd );
  306. VOID MDIParentNotifyRButtonDown( HWND hwnd, DWORD CursorPos );
  307. VOID MDIVKeyToItemDefault( HWND hwnd );
  308. int MDIVKeyToItemUpDown( HWND hwnd, WORD VKey );
  309. VOID ReorderJob( HWND hwnd, PMDIWIN_INFO pInfo, DWORD Position );
  310. VOID RepaintListboxItem( HWND hwndListbox, DWORD ItemID );
  311. VOID MDISize( HWND hWnd, DWORD Coordinates );
  312. LONG MDIMDIActivate( HWND hwnd, HWND hwndDeactivate, HWND hwndActivate );
  313. VOID MDINCActivate( HWND hwnd );
  314. LONG MDIWindowPosChanged( HWND hwnd, WPARAM wParam, LPARAM lParam );
  315. VOID ClearDragPosition( PMDIWIN_INFO pInfo );
  316. VOID MDISetFocus( HWND hwnd );
  317. VOID MDIMeasureItem( HWND hwnd, LPMEASUREITEMSTRUCT pmis );
  318. VOID MDIDrawItem( HWND hwnd, LPDRAWITEMSTRUCT pdis );
  319. VOID MDITimer( HWND hWnd );
  320. VOID MDIStatusChanged( HWND hwnd );
  321. VOID MDIUpdateList( HWND hwnd );
  322. VOID MDISetParts( HWND hwnd, WPARAM wParam, LPARAM lParam );
  323. VOID MDIDestroy( HWND hwnd );
  324. LONG MDIDragList( HWND hwnd, LPDRAGLISTINFO pDragListInfo );
  325. BOOL RefreshServerContext( PVOID pContext, PDWORD pFlags );
  326. BOOL GetSavedWindowPos( LPTSTR pKey, LPTSTR WindowName, PSAVEDWINDOWPOS pswp,
  327. DWORD cHeaders, PINT pHeaders );
  328. UINT GetCurrentMenuItemID( HMENU hMenu );
  329. LONG SubclassListboxWndProc(
  330. HWND hWnd,
  331. UINT message,
  332. WPARAM wParam,
  333. LONG lParam
  334. );
  335. VOID
  336. KillMDIWinInfo(
  337. PMDIWIN_INFO pInfo);
  338. /* Copied from winfile:
  339. */
  340. INT
  341. GetHeightFromPointsString(
  342. LPTSTR szPoints)
  343. {
  344. HDC hdc;
  345. INT height;
  346. hdc = GetDC(NULL);
  347. height = MulDiv(-_tcstol(szPoints, NULL, 10), GetDeviceCaps(hdc, LOGPIXELSY), 72);
  348. ReleaseDC(NULL, hdc);
  349. return height;
  350. }
  351. /* InitializeInternationalTimeConstants
  352. *
  353. * Called to set up the following global variables:
  354. *
  355. * TwentyFourHourClock - Boolean indicating whether 12- or 24-hour clock
  356. * is currently in force.
  357. *
  358. * MetricMeasurement - Metres or feet and inches (TRUE == metric)
  359. *
  360. * szTimeSep - Separator for time string - usually ":", unless you're in
  361. * Scandinavia, Croatia or a couple of other places.
  362. *
  363. * szAMPM - Array of 2 strings - usually "AM" or "PM" for 12-hour clock.
  364. *
  365. * TimeFormatLeadingZero
  366. */
  367. VOID InitializeInternationalTimeConstants( VOID )
  368. {
  369. LCID lcid;
  370. WCHAR Buffer[128];
  371. TwentyFourHourClock = GetProfileInt (szInternational, TEXT("iTime"), 0);
  372. // JAPAN
  373. // V-Hirot July.07.1993 for New Prefix
  374. // krishnag Sept 1, 1993 CountryCode
  375. if (bJapan) {
  376. TimePrefix = GetProfileInt (szInternational, TEXT("iTimePrefix"), 0);
  377. }
  378. GetProfileString (szInternational, TEXT("sTime"), TEXT(":"), szTimeSep, TIMESEP_LENGTH);
  379. GetProfileString (szInternational, TEXT("s1159"), TEXT("AM"), szAMPM[AM], AMPM_LENGTH);
  380. GetProfileString (szInternational, TEXT("s2359"), TEXT("PM"), szAMPM[PM], AMPM_LENGTH);
  381. TimeFormatLeadingZero = (BOOL)GetProfileInt (szInternational, TEXT("iTLZero"), 1);
  382. MetricMeasurement = !((BOOL)GetProfileInt (szInternational, TEXT("iMeasure"), 0));
  383. GetProfileString (szInternational, TEXT("sDecimal"), TEXT("."), szDecimalPoint, sizeof szDecimalPoint/sizeof(TCHAR));
  384. DecimalDigits = GetProfileInt (szInternational, TEXT("iDigits"), 2);
  385. LeadingZero = GetProfileInt (szInternational, TEXT("iLzero"), 1);
  386. lcid = GetThreadLocale();
  387. ThousandSeparator = TEXT(',');
  388. if (GetLocaleInfoW (lcid, LOCALE_STHOUSAND, Buffer, sizeof Buffer /sizeof(WCHAR))) {
  389. ThousandSeparator = Buffer[0];
  390. }
  391. }
  392. HWND
  393. CreateQueueWindow(
  394. HWND hWnd,
  395. PQUEUE pQueue,
  396. DWORD Status,
  397. DWORD WindowType,
  398. DWORD Flags
  399. )
  400. {
  401. TCHAR Title[80];
  402. TCHAR StatusString[40];
  403. SAVEDWINDOWPOS swp;
  404. MDICREATESTRUCT mdicreate;
  405. INT pHeaders[MDIHEAD_JOB_COUNT];
  406. INT i;
  407. if (!pQueue)
  408. return NULL;
  409. /* Now create a window for this queue. Note that during this function
  410. * the WM_CREATE message is sent to the QueueWinProc but, the Extra
  411. * Window Word has not yet been set to hQueue value because we need
  412. * the window handle in order to set this value. In order to get
  413. * around this 'Catch-22' situation, we pass the hQueue value as the
  414. * 'lpParam' value in the MDICREATESTRUCT. Then we only have to be
  415. * a little sly when processing the WM_CREATE message to retrieve the
  416. * Queue handle. Also, we then set the Window Word value to hQueue
  417. * during WM_CREATE message processing, thereby insuring that it will
  418. * be available for all subsequent messages.
  419. */
  420. if( !GetSavedWindowPos( szRegPrinters, pQueue->pPrinterName, &swp,
  421. ( sizeof pHeaders / sizeof *pHeaders ), pHeaders ) )
  422. {
  423. /* If no window positions saved, set the column widths to default.
  424. * They will be initialised on MDI creation, since they depend
  425. * on the width of the window:
  426. */
  427. for( i = 0; i < MDIHEAD_JOB_COUNT; i++ )
  428. pHeaders[i] = CW_USEDEFAULT;
  429. }
  430. if( Flags & CREATE_PRINTER_ICONIC )
  431. swp.sw = SW_SHOWMINIMIZED;
  432. if( Status )
  433. {
  434. GetPrinterStatusString( Status, StatusString );
  435. _stprintf( Title, szTitleFormat, pQueue->pPrinterName, StatusString );
  436. }
  437. else
  438. _tcscpy( Title, pQueue->pPrinterName );
  439. if( !(pQueue->pMDIWinInfo = CreateQueueWindowInfo( pQueue, pHeaders ) ) )
  440. return NULL;
  441. pQueue->pMDIWinInfo->Status = Status;
  442. SetWindowTypeIcon(pQueue, WindowType, Flags);
  443. mdicreate.szClass = szChildClass;
  444. mdicreate.szTitle = Title;
  445. mdicreate.hOwner = hInst;
  446. mdicreate.x = swp.left;
  447. mdicreate.y = swp.top;
  448. mdicreate.cx = swp.width;
  449. mdicreate.cy = swp.height;
  450. mdicreate.style = SW2WS( swp.sw ) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  451. mdicreate.lParam = (LONG)pQueue->pMDIWinInfo;
  452. hWnd = (HWND)SendMessage(hwndClient, WM_MDICREATE, 0, (LONG)&mdicreate);
  453. return hWnd;
  454. }
  455. /*
  456. *
  457. */
  458. PMDIWIN_INFO
  459. CreateQueueWindowInfo(
  460. PQUEUE pQueue,
  461. PINT pHeaders )
  462. {
  463. PMDIWIN_INFO pInfo;
  464. PCOLUMN pColumns;
  465. int i;
  466. pInfo = (PMDIWIN_INFO)AllocSplMem( sizeof( MDIWIN_INFO ) );
  467. if( !pInfo )
  468. return NULL;
  469. pColumns = (PCOLUMN)AllocSplMem( sizeof( COLUMN ) * MDIHEAD_JOB_COUNT );
  470. if( !pColumns )
  471. {
  472. FreeSplMem( pInfo );
  473. return NULL;
  474. }
  475. for( i = 0; i < MDIHEAD_JOB_COUNT; i++ )
  476. {
  477. pColumns[i].Width = pHeaders[i];
  478. pColumns[i].Text = MDIPrinterDefaultColumn[i].Text;
  479. }
  480. /* Initialize all pColumns elements here. Rememberthat some
  481. printers can generate their own error messages which are
  482. pointed to by JOB_INFO_2's pStatus field. We have to query
  483. each time we display status info as to which field is
  484. providing the Status information */
  485. pColumns[MDIHEAD_JOB_STATUS ].Offset = offsetof( JOB_INFO_2, Status );
  486. pColumns[MDIHEAD_JOB_DOCNAME ].Offset = offsetof( JOB_INFO_2, pDocument );
  487. pColumns[MDIHEAD_JOB_OWNER ].Offset = offsetof( JOB_INFO_2, pUserName );
  488. pColumns[MDIHEAD_JOB_PRINTEDAT].Offset = offsetof( JOB_INFO_2, Submitted );
  489. pColumns[MDIHEAD_JOB_PAGES ].Offset = offsetof( JOB_INFO_2, TotalPages );
  490. pColumns[MDIHEAD_JOB_SIZE ].Offset = offsetof( JOB_INFO_2, Size );
  491. pColumns[MDIHEAD_JOB_PRIORITY ].Offset = offsetof( JOB_INFO_2, Priority );
  492. pColumns[MDIHEAD_JOB_STATUS ].Datatype = MDIDATA_JOB_STATUS;
  493. pColumns[MDIHEAD_JOB_DOCNAME ].Datatype = MDIDATA_PSZ_UNTITLED_IF_NULL;
  494. pColumns[MDIHEAD_JOB_OWNER ].Datatype = MDIDATA_PSZ;
  495. pColumns[MDIHEAD_JOB_PRINTEDAT].Datatype = MDIDATA_TIME;
  496. pColumns[MDIHEAD_JOB_PAGES ].Datatype = MDIDATA_DWORD_BLANK_IF_ZERO;
  497. pColumns[MDIHEAD_JOB_SIZE ].Datatype = MDIDATA_SIZE;
  498. pColumns[MDIHEAD_JOB_PRIORITY ].Datatype = MDIDATA_DWORD_BLANK_IF_ZERO;
  499. pInfo->WindowType = MDIWIN_PRINTER;
  500. pInfo->hwndList = NULL;
  501. pInfo->cNumLines = 0;
  502. pInfo->ppData = (PBYTE *)&pQueue->pJobs;
  503. pInfo->DataSize = sizeof( JOB_INFO_2 );
  504. pInfo->pcObjects = &pQueue->cJobs;
  505. pInfo->cColumns = MDIHEAD_JOB_COUNT;
  506. pInfo->pColumns = pColumns;
  507. pInfo->IconStatus = offsetof( JOB_INFO_2, Status );
  508. pInfo->pSelObjId = &pQueue->SelJobId;
  509. pInfo->ppSelData = (PBYTE *)&pQueue->pSelJob;
  510. pInfo->IdOffset = offsetof( JOB_INFO_2, JobId );
  511. pInfo->pFirstEnumObj = &pQueue->FirstEnumJob;
  512. pInfo->pcEnumObjs = &pQueue->cEnumJobs;
  513. pInfo->DataMutex = CreateMutex( NULL, FALSE, NULL );
  514. #ifdef SEP_WAITHANDLE
  515. pInfo->phWaitObject = &pQueue->hPrinterWait;
  516. pInfo->phMain = &pQueue->hPrinter;
  517. #else
  518. pInfo->phWaitObject = &pQueue->hPrinter;
  519. #endif
  520. pInfo->WaitFlags = PRINTER_CHANGE_PRINTER | PRINTER_CHANGE_JOB;
  521. pInfo->pfnRefresh = (REFRESHPROC)GetJobs;
  522. pInfo->pfnCheckQuit = (CHECKQUITPROC)CheckQuitQueue;
  523. pInfo->pfnInitThread = (INITTHREADPROC)InitQueueThread;
  524. // pInfo->SuspendRefresh = FALSE;
  525. pInfo->RefreshSignal = CreateEvent( NULL,
  526. EVENT_RESET_MANUAL,
  527. EVENT_INITIAL_STATE_SIGNALED,
  528. NULL );
  529. if( pInfo->RefreshSignal == NULL )
  530. DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
  531. pInfo->pContext = pQueue;
  532. return pInfo;
  533. }
  534. //
  535. // Create the server window.
  536. //
  537. // If hServer is NULL, we haven't tried the OpenPrinter yet.
  538. // If hServer is (HANDLE)-1, we tried and failed due to access denied.
  539. // else hServer is valid. InitServerWindowThread picks up these values.
  540. //
  541. DWORD CALLBACK
  542. CreateServerWindow(
  543. HWND hwnd,
  544. LPTSTR pServerName,
  545. HANDLE hServer)
  546. {
  547. PSERVER_CONTEXT pContext;
  548. LPTSTR pServerViewerTitle;
  549. TCHAR Title[MAX_PATH+20]; // Enough for server name + "Server: "
  550. SAVEDWINDOWPOS swp;
  551. MDICREATESTRUCT mdicreate;
  552. INT pHeaders[MDIHEAD_PRINTER_COUNT];
  553. INT i;
  554. pContext = AllocSplMem( sizeof( SERVER_CONTEXT ) );
  555. if (!pContext)
  556. {
  557. //
  558. // !! LATER !!
  559. // Put up an error
  560. //
  561. return NO_ERROR;
  562. }
  563. pContext->pServerName = AllocSplStr( pServerName );
  564. pContext->hServer = hServer;
  565. if( !GetSavedWindowPos( szRegServers, pServerName, &swp,
  566. ( sizeof pHeaders / sizeof *pHeaders ), pHeaders ) )
  567. {
  568. /* If no window positions saved, set the column widths to default.
  569. * They will be initialised on MDI creation, since they depend
  570. * on the width of the window:
  571. */
  572. for( i = 0; i < MDIHEAD_PRINTER_COUNT; i++ )
  573. pHeaders[i] = CW_USEDEFAULT;
  574. }
  575. pContext->pMDIWinInfo = CreateServerWindowInfo( pContext, pHeaders );
  576. pServerViewerTitle = GetString( IDS_SERVERVIEWERTITLE );
  577. _stprintf( Title, pServerViewerTitle, pServerName );
  578. FreeSplStr( pServerViewerTitle );
  579. mdicreate.szClass = szChildClass;
  580. mdicreate.szTitle = Title;
  581. mdicreate.hOwner = hInst;
  582. mdicreate.x = swp.left;
  583. mdicreate.y = swp.top;
  584. mdicreate.cx = swp.width;
  585. mdicreate.cy = swp.height;
  586. mdicreate.style = SW2WS( swp.sw ) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  587. mdicreate.lParam = (LONG)pContext->pMDIWinInfo;
  588. SendMessage(hwndClient, WM_MDICREATE, 0, (LONG)&mdicreate);
  589. return NO_ERROR;
  590. }
  591. /*
  592. *
  593. */
  594. PMDIWIN_INFO
  595. CreateServerWindowInfo(
  596. PSERVER_CONTEXT pContext,
  597. PINT pHeaders)
  598. {
  599. PMDIWIN_INFO pInfo;
  600. PCOLUMN pColumns;
  601. int i;
  602. pInfo = (PMDIWIN_INFO)AllocSplMem( sizeof( MDIWIN_INFO ) );
  603. if( !pInfo )
  604. return NULL;
  605. pColumns = (PCOLUMN)AllocSplMem( sizeof( COLUMN ) * MDIHEAD_PRINTER_COUNT );
  606. if( !pColumns )
  607. {
  608. FreeSplMem( pInfo );
  609. return NULL;
  610. }
  611. for( i = 0; i < MDIHEAD_PRINTER_COUNT; i++ )
  612. {
  613. pColumns[i].Width = pHeaders[i];
  614. pColumns[i].Text = MDIServerDefaultColumn[i].Text;
  615. }
  616. pColumns[MDIHEAD_PRINTER_PRINTER].Offset = offsetof( PRINTER_INFO_2, pPrinterName );
  617. pColumns[MDIHEAD_PRINTER_STATUS ].Offset = offsetof( PRINTER_INFO_2, Status );
  618. pColumns[MDIHEAD_PRINTER_JOBS ].Offset = offsetof( PRINTER_INFO_2, cJobs );
  619. pColumns[MDIHEAD_PRINTER_PORT ].Offset = offsetof( PRINTER_INFO_2, pPortName );
  620. pColumns[MDIHEAD_PRINTER_TYPE ].Offset = offsetof( PRINTER_INFO_2, pDriverName );
  621. pColumns[MDIHEAD_PRINTER_PRINTER].Datatype = MDIDATA_PSZ;
  622. pColumns[MDIHEAD_PRINTER_STATUS ].Datatype = MDIDATA_PRINTER_STATUS;
  623. pColumns[MDIHEAD_PRINTER_JOBS ].Datatype = MDIDATA_DWORD;
  624. pColumns[MDIHEAD_PRINTER_PORT ].Datatype = MDIDATA_PSZ;
  625. pColumns[MDIHEAD_PRINTER_TYPE ].Datatype = MDIDATA_PSZ;
  626. pInfo->WindowType = MDIWIN_SERVER;
  627. pInfo->hwndList = NULL;
  628. pInfo->cNumLines = 0;
  629. pInfo->ppData = (PBYTE *)&pContext->pPrinters;
  630. pInfo->DataSize = sizeof( PRINTER_INFO_2 );
  631. pInfo->pcObjects = &pContext->cPrinters;
  632. pInfo->cColumns = MDIHEAD_PRINTER_COUNT;
  633. pInfo->pColumns = pColumns;
  634. pInfo->IconStatus = offsetof( PRINTER_INFO_2, Status );
  635. pInfo->pSelObjId = &pContext->SelPrinterId;
  636. pInfo->ppSelData = (PBYTE *)&pContext->pSelPrinter;
  637. pInfo->IdOffset = offsetof( PRINTER_INFO_2, pPrinterName );
  638. pInfo->pFirstEnumObj = &pContext->FirstEnumPrinter;
  639. pInfo->pcEnumObjs = &pContext->cEnumPrinters;
  640. pInfo->DataMutex = CreateMutex( NULL, FALSE, NULL );
  641. #ifdef SEP_WAITHANDLE
  642. pInfo->phWaitObject = &pContext->hServerWait;
  643. pInfo->phMain = &pContext->hServer;
  644. #else
  645. pInfo->phWaitObject = &pContext->hServer;
  646. #endif
  647. pInfo->WaitFlags = PRINTER_CHANGE_PRINTER;
  648. pInfo->pfnRefresh = (REFRESHPROC)RefreshServerContext;
  649. pInfo->pfnCheckQuit = NULL;
  650. pInfo->pfnInitThread = (INITTHREADPROC)InitServerWindowThread;
  651. // pInfo->SuspendRefresh = FALSE;
  652. pInfo->RefreshSignal = CreateEvent( NULL,
  653. EVENT_RESET_MANUAL,
  654. EVENT_INITIAL_STATE_SIGNALED,
  655. NULL );
  656. pInfo->hicon = hiconServer;
  657. if( pInfo->RefreshSignal == NULL )
  658. DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
  659. pInfo->pContext = pContext;
  660. return pInfo;
  661. }
  662. /* DisplayStatusIcon
  663. *
  664. * This rather goes against the spirit of the data-driven model here,
  665. * in that we need to know about the various states that documents and printers
  666. * can be in.
  667. *
  668. * andrewbe - May 1992
  669. */
  670. BOOL DisplayStatusIcon( HDC hdc, PRECT prect, int WindowType, PBYTE pData, BOOL Highlight )
  671. {
  672. BOOL DisplayIcon = TRUE;
  673. int BitmapIndex;
  674. DWORD Status;
  675. int xBase;
  676. int yBase;
  677. int right;
  678. Status = *(DWORD *)pData;
  679. switch( WindowType )
  680. {
  681. case MDIWIN_LOCALPRINTER:
  682. case MDIWIN_NETWORKPRINTER:
  683. case MDIWIN_LOCALNETWORKPRINTER:
  684. if( ( Status & JOB_STATUS_ERROR )
  685. ||( Status & JOB_STATUS_OFFLINE )
  686. ||( Status & JOB_STATUS_PAPEROUT ) )
  687. BitmapIndex = BM_IND_DOCUMENT_ERROR;
  688. else
  689. if( Status & JOB_STATUS_PAUSED )
  690. BitmapIndex = BM_IND_DOCUMENT_PAUSED;
  691. else
  692. if( ( Status & JOB_STATUS_PRINTING )
  693. ||( Status & JOB_STATUS_SPOOLING ) )
  694. BitmapIndex = BM_IND_DOCUMENT_PRINTING;
  695. else
  696. DisplayIcon = FALSE;
  697. xBase = BM_IND_STATUS_XBASE;
  698. yBase = BM_IND_STATUS_YBASE;
  699. break;
  700. case MDIWIN_SERVER:
  701. default:
  702. if( Status & PRINTER_STATUS_ERROR )
  703. BitmapIndex = BM_IND_PRINTER_ERROR;
  704. else
  705. if( Status & PRINTER_STATUS_PAUSED )
  706. BitmapIndex = BM_IND_PRINTER_PAUSED;
  707. else
  708. BitmapIndex = BM_IND_PRINTER_READY;
  709. xBase = BM_IND_STATUS_XBASE;
  710. yBase = BM_IND_STATUS_YBASE;
  711. break;
  712. }
  713. /* Remember the old right coordinate of the drawing area:
  714. */
  715. right = prect->right;
  716. if( DisplayIcon )
  717. {
  718. BitBlt( hdc, prect->left + STATUS_BITMAP_MARGIN,
  719. prect->top,
  720. STATUS_BITMAP_WIDTH,
  721. STATUS_BITMAP_HEIGHT,
  722. hdcMem,
  723. ( xBase + ( BitmapIndex * STATUS_BITMAP_WIDTH ) ),
  724. ( yBase + ( Highlight ? STATUS_BITMAP_HEIGHT : 0 ) ),
  725. SRCCOPY );
  726. /* Draw around it so we don't get a flashing effect on the highlight line:
  727. */
  728. prect->right = ( prect->left + STATUS_BITMAP_MARGIN );
  729. DrawLine( hdc, prect, TEXT(""), Highlight );
  730. prect->left += STATUS_BITMAP_MARGIN + STATUS_BITMAP_WIDTH;
  731. prect->right = prect->left + STATUS_BITMAP_MARGIN;
  732. DrawLine( hdc, prect, TEXT(""), Highlight );
  733. prect->left += STATUS_BITMAP_MARGIN;
  734. }
  735. else
  736. {
  737. prect->right = STATUS_BITMAP_SPACE;
  738. DrawLine( hdc, prect, TEXT(""), Highlight );
  739. prect->left += STATUS_BITMAP_SPACE;
  740. }
  741. /* Restore the right coordinate (left has now been updated to the new position):
  742. */
  743. prect->right = right;
  744. return DisplayIcon;
  745. }
  746. /* FormatData
  747. *
  748. * Takes a generic data pointer, along with the datatype to be formatted,
  749. * and generates a string.
  750. *
  751. * andrewbe wrote it - April 1992
  752. */
  753. VOID FormatData( PBYTE pData, int Datatype, LPTSTR string )
  754. {
  755. TCHAR FormattedSize[MAX_PATH];
  756. LARGE_INTEGER liTemp;
  757. switch( Datatype )
  758. {
  759. case MDIDATA_DWORD:
  760. liTemp.LowPart = *(DWORD *)pData;
  761. liTemp.HighPart = 0;
  762. FormatFileSize (THOUSANDSEPSWITCH, &liTemp, 0, FormattedSize);
  763. _stprintf( string, TEXT("%s"), FormattedSize );
  764. break;
  765. case MDIDATA_DWORD_BLANK_IF_ZERO:
  766. if( *(PCHAR *)pData != 0 ) {
  767. liTemp.LowPart = *(DWORD *)pData;
  768. liTemp.HighPart = 0;
  769. FormatFileSize (THOUSANDSEPSWITCH, &liTemp, 0, FormattedSize);
  770. _stprintf( string, TEXT("%s"), FormattedSize );
  771. }
  772. else
  773. *string = NULLC;
  774. break;
  775. case MDIDATA_PSZ:
  776. if( *(PCHAR *)pData && **(PCHAR *)pData )
  777. _stprintf( string, TEXT("%s"), *(PCHAR *)pData );
  778. else
  779. *string = NULLC;
  780. break;
  781. case MDIDATA_PSZ_UNTITLED_IF_NULL:
  782. if( *(PCHAR *)pData && **(PCHAR *)pData )
  783. _stprintf( string, TEXT("%s"), *(PCHAR *)pData );
  784. else
  785. _stprintf( string, TEXT("%s"), strUntitled );
  786. break;
  787. case MDIDATA_TIME:
  788. ConvertSystemTimeToChar((SYSTEMTIME *)pData, string);
  789. break;
  790. case MDIDATA_SIZE:
  791. liTemp.LowPart = *(DWORD *)pData;
  792. liTemp.HighPart = 0;
  793. FormatFileSize (THOUSANDSEPSWITCH, &liTemp, 0, FormattedSize);
  794. _stprintf( string, szSizeFormat, FormattedSize );
  795. break;
  796. case MDIDATA_PRINTER_STATUS:
  797. GetPrinterStatusString( (DWORD)*(PDWORD *)pData, string );
  798. break;
  799. case MDIDATA_JOB_STATUS:
  800. GetJobStatusString( (DWORD)*(PDWORD *)pData, string );
  801. }
  802. }
  803. /* GetPrinterStatusString
  804. *
  805. * Loads the resource string corresponding to the supplied status code.
  806. *
  807. * andrewbe wrote it - April 1992
  808. */
  809. #define MAXLEN 40
  810. int GetPrinterStatusString( DWORD Status, LPTSTR string )
  811. {
  812. int stringID;
  813. if( Status & PRINTER_STATUS_ERROR )
  814. stringID = IDS_ERROR;
  815. else
  816. if( Status & PRINTER_STATUS_PAPER_JAM )
  817. stringID = IDS_PAPER_JAM;
  818. else
  819. if( Status & PRINTER_STATUS_PAPER_OUT )
  820. stringID = IDS_PAPEROUT;
  821. else
  822. if( Status & PRINTER_STATUS_MANUAL_FEED )
  823. stringID = IDS_MANUAL_FEED;
  824. else
  825. if( Status & PRINTER_STATUS_PAPER_PROBLEM )
  826. stringID = IDS_PAPER_PROBLEM;
  827. else
  828. if( Status & PRINTER_STATUS_OFFLINE )
  829. stringID = IDS_OFFLINE;
  830. else
  831. if( Status & PRINTER_STATUS_IO_ACTIVE )
  832. stringID = IDS_IO_ACTIVE;
  833. else
  834. if( Status & PRINTER_STATUS_BUSY )
  835. stringID = IDS_BUSY;
  836. else
  837. if( Status & PRINTER_STATUS_PRINTING )
  838. stringID = IDS_PRINTING;
  839. else
  840. if( Status & PRINTER_STATUS_OUTPUT_BIN_FULL )
  841. stringID = IDS_OUTPUT_BIN_FULL;
  842. else
  843. if( Status & PRINTER_STATUS_NOT_AVAILABLE )
  844. stringID = IDS_NOT_AVAILABLE;
  845. else
  846. if( Status & PRINTER_STATUS_WAITING )
  847. stringID = IDS_WAITING;
  848. else
  849. if( Status & PRINTER_STATUS_PROCESSING )
  850. stringID = IDS_PROCESSING;
  851. else
  852. if( Status & PRINTER_STATUS_INITIALIZING )
  853. stringID = IDS_INITIALIZING;
  854. else
  855. if( Status & PRINTER_STATUS_WARMING_UP )
  856. stringID = IDS_WARMING_UP;
  857. else
  858. if( Status & PRINTER_STATUS_TONER_LOW )
  859. stringID = IDS_TONER_LOW;
  860. else
  861. if( Status & PRINTER_STATUS_NO_TONER )
  862. stringID = IDS_NO_TONER;
  863. else
  864. if( Status & PRINTER_STATUS_PAGE_PUNT )
  865. stringID = IDS_PAGE_PUNT;
  866. else
  867. if( Status & PRINTER_STATUS_USER_INTERVENTION )
  868. stringID = IDS_USER_INTERVENTION;
  869. else
  870. if( Status & PRINTER_STATUS_OUT_OF_MEMORY )
  871. stringID = IDS_OUT_OF_MEMORY;
  872. else
  873. if( Status & PRINTER_STATUS_DOOR_OPEN )
  874. stringID = IDS_DOOR_OPEN;
  875. // else
  876. // if( Status & PRINTER_STATUS_SERVER_UNKNOWN )
  877. // stringID = IDS_SERVER_UNKNOWN;
  878. else
  879. if( Status & PRINTER_STATUS_PAUSED )
  880. stringID = IDS_PAUSED;
  881. else
  882. if( Status & PRINTER_STATUS_PENDING_DELETION )
  883. stringID = IDS_PENDING_DELETION;
  884. else
  885. if( Status & PRINTER_STATUS_ACCESS_DENIED )
  886. stringID = IDS_ACCESS_DENIED;
  887. else
  888. if( Status & PRINTER_STATUS_UNKNOWN )
  889. stringID = IDS_STATUS_UNKNOWN;
  890. else
  891. if( Status & PRINTER_STATUS_LOADING )
  892. stringID = IDS_STATUS_LOADING;
  893. //
  894. // End
  895. //
  896. else
  897. stringID = IDS_READY;
  898. return LoadString( hInst, stringID, string, MAXLEN );
  899. }
  900. /* GetJobStatusString
  901. *
  902. * Loads the resource string corresponding to the supplied status code.
  903. *
  904. * andrewbe wrote it - April 1992
  905. */
  906. int GetJobStatusString( DWORD Status, LPTSTR string )
  907. {
  908. int stringID;
  909. if( Status & JOB_STATUS_ERROR )
  910. stringID = IDS_ERROR;
  911. else
  912. if( Status & JOB_STATUS_OFFLINE )
  913. stringID = IDS_OFFLINE;
  914. else
  915. if( Status & JOB_STATUS_PAPEROUT )
  916. stringID = IDS_PAPEROUT;
  917. else
  918. if( Status & JOB_STATUS_DELETING )
  919. stringID = IDS_DELETING;
  920. else
  921. if( Status & JOB_STATUS_PAUSED )
  922. stringID = IDS_PAUSED;
  923. else
  924. if( ( Status & JOB_STATUS_SPOOLING ) && ( Status & JOB_STATUS_PRINTING ) )
  925. stringID = IDS_PRINTANDSPOOL;
  926. else
  927. if( Status & JOB_STATUS_SPOOLING )
  928. stringID = IDS_SPOOLING;
  929. else
  930. if( Status & JOB_STATUS_PRINTING )
  931. stringID = IDS_PRINTING;
  932. else
  933. if( Status & JOB_STATUS_PRINTED )
  934. stringID = IDS_PRINTED;
  935. else
  936. stringID = IDS_NOSTATUS;
  937. return LoadString( hInst, stringID, string, MAXLEN );
  938. }
  939. VOID
  940. SetWindowTypeIcon(
  941. PQUEUE pQueue,
  942. DWORD WindowType,
  943. DWORD Flags)
  944. {
  945. pQueue->pMDIWinInfo->WindowType = WindowType;
  946. switch( WindowType )
  947. {
  948. case MDIWIN_NETWORKPRINTER:
  949. case MDIWIN_LOCALNETWORKPRINTER:
  950. pQueue->pMDIWinInfo->hicon = hiconConnect;
  951. break;
  952. case MDIWIN_LOCALPRINTER:
  953. default:
  954. pQueue->pMDIWinInfo->hicon = ( ( Flags & CREATE_PRINTER_SHARED )
  955. ? hiconShared : hiconPrinter );
  956. break;
  957. }
  958. }
  959. /* --- Function: DrawLine() -------------------------------------------------
  960. *
  961. * Description:
  962. * Only draws lines visible portion of Printer and Job status lines
  963. * in window.
  964. *
  965. * ---------------------------------------------------------------------- */
  966. void
  967. DrawLine(
  968. HDC hDC,
  969. LPRECT pRect,
  970. LPTSTR pStr,
  971. BOOL bInvert
  972. )
  973. {
  974. unsigned long PrevColour, PrevTextColour;
  975. SIZE TextSize;
  976. int x, y;
  977. if (bInvert) {
  978. PrevColour = SetBkColor(hDC, SysColorHighlight );
  979. PrevTextColour = SetTextColor(hDC, SysColorHighlightText );
  980. }
  981. else
  982. {
  983. /* Hack around a USER bug that gives me the wrong colours:
  984. */
  985. SetBkColor(hDC, SysColorWindow );
  986. SetTextColor(hDC, SysColorWindowText );
  987. }
  988. GetTextExtentPoint(hDC, pStr, _tcslen(pStr), &TextSize);
  989. x = pRect->left;
  990. y = ( pRect->top + ( ( pRect->bottom - pRect->top - TextSize.cy ) / 2 ) );
  991. ExtTextOut(hDC, x, y, ETO_OPAQUE | ETO_CLIPPED, pRect, pStr, _tcslen(pStr), NULL);
  992. if (bInvert) {
  993. SetBkColor(hDC, PrevColour);
  994. SetTextColor(hDC, PrevTextColour);
  995. }
  996. }
  997. long FrameWndProc(
  998. HWND hWnd,
  999. UINT message,
  1000. WPARAM wParam,
  1001. LONG lParam
  1002. )
  1003. {
  1004. if( message == WM_Help )
  1005. {
  1006. FrameHelp(hWnd, (UINT)lParam);
  1007. return 0;
  1008. }
  1009. switch(message)
  1010. {
  1011. case WM_CREATE:
  1012. return FrameCreate(hWnd, (LPCREATESTRUCT)lParam);
  1013. case WM_DELETE_PRINTER:
  1014. return FrameCommandDeletePrinterHelper(hWnd, (HWND)lParam, FALSE);
  1015. case WM_INIT_PRINTER_WINDOWS:
  1016. InitQueueChildWindows(hWnd);
  1017. return 0;
  1018. case WM_INIT_SERVER_WINDOWS:
  1019. InitServerChildWindows(hWnd);
  1020. return 0;
  1021. case WM_INITMENU:
  1022. return FrameInitMenu(hWnd);
  1023. case WM_MENUSELECT:
  1024. return FrameMenuSelect( hWnd, wParam, lParam );
  1025. case WM_PAINT:
  1026. return FramePaint(hWnd);
  1027. case WM_SIZE:
  1028. FrameSize(hWnd, wParam, lParam);
  1029. break;
  1030. case WM_CLOSE:
  1031. FrameClose(hWnd);
  1032. return DefFrameProc(hWnd, hwndClient, message, wParam, lParam);
  1033. case WM_COMMAND:
  1034. switch(LOWORD(wParam))
  1035. {
  1036. case IDM_CONNECTTOPRINTER:
  1037. return FrameCommandConnectToPrinter(hWnd);
  1038. case IDM_INSTALLPRINTER:
  1039. return FrameCommandCreatePrinter(hWnd);
  1040. case IDM_PROPERTIES:
  1041. return FrameCommandProperties(hWnd);
  1042. case IDM_REMOVECONNECTION: /* Toolbar button only */
  1043. case IDM_DELETEPRINTER:
  1044. return FrameCommandDeletePrinter(hWnd);
  1045. case IDM_PRINTER_PAUSE:
  1046. return FrameCommandPrinterPauseResume(hWnd, TRUE);
  1047. case IDM_PRINTER_RESUME:
  1048. return FrameCommandPrinterPauseResume(hWnd, FALSE);
  1049. case IDM_PURGEPRINTER:
  1050. return FrameCommandPurgePrinter(hWnd);
  1051. case IDM_FORMS:
  1052. return FrameCommandForms(hWnd);
  1053. case IDM_SERVERVIEWER:
  1054. return FrameCommandServerViewer(hWnd);
  1055. case IDM_EXIT:
  1056. SendMessage(hWnd, WM_CLOSE, 0, 0L);
  1057. return 0;
  1058. case IDM_REMOVEDOC:
  1059. return FrameCommandRemoveDoc(hWnd);
  1060. case IDM_DOCTAILS:
  1061. return FrameCommandDocDetails(hWnd);
  1062. case IDM_DOCUMENT_PAUSE:
  1063. return FrameCommandDocumentPauseResume(hWnd, IDM_DOCUMENT_PAUSE);
  1064. case IDM_DOCUMENT_RESUME:
  1065. return FrameCommandDocumentPauseResume(hWnd, IDM_DOCUMENT_RESUME);
  1066. case IDM_RESTART:
  1067. return FrameCommandRestart(hWnd);
  1068. #ifdef LATER
  1069. case IDM_FONT:
  1070. return FrameCommandFont(hWnd);
  1071. case IDM_REFRESHRATE:
  1072. return FrameCommandRefreshRate(hWnd);
  1073. #endif
  1074. case IDM_TOOLBAR:
  1075. return FrameCommandToolbar(hWnd);
  1076. case IDM_STATUSBAR:
  1077. return FrameCommandStatusbar(hWnd);
  1078. case IDM_SAVESETTINGS:
  1079. return FrameCommandSaveSettings(hWnd);
  1080. case IDM_PERMISSIONS:
  1081. return FrameCommandPermissions(hWnd);
  1082. case IDM_AUDITING:
  1083. return FrameCommandAuditing(hWnd);
  1084. case IDM_OWNER:
  1085. return FrameCommandOwner(hWnd);
  1086. case IDM_TILEHORZ:
  1087. SendMessage(hwndClient, WM_MDITILE, MDITILE_HORIZONTAL, 0L);
  1088. return 0;
  1089. case IDM_TILEVERT:
  1090. SendMessage(hwndClient, WM_MDITILE, MDITILE_VERTICAL, 0L);
  1091. return 0;
  1092. case IDM_CASCADE:
  1093. SendMessage(hwndClient, WM_MDICASCADE, 0, 0L);
  1094. return 0;
  1095. case IDM_ARRANGE:
  1096. SendMessage(hwndClient, WM_MDIICONARRANGE, 0, 0L);
  1097. return 0;
  1098. case IDM_REFRESH:
  1099. FrameCommandRefresh(hWnd);
  1100. return 0;
  1101. case IDM_CLOSE:
  1102. return FrameCommandClose(hWnd);
  1103. case IDM_HELP_CONTENTS:
  1104. ShowHelp(hWnd, HELP_INDEX, (DWORD)TEXT(""));
  1105. break;
  1106. case IDM_HELP_SEARCH:
  1107. ShowHelp(hWnd, HELP_PARTIALKEY, (DWORD)TEXT(""));
  1108. break;
  1109. case IDM_HELP_HOWTOUSE:
  1110. ShowHelp(hWnd, HELP_HELPONHELP, (DWORD)TEXT(""));
  1111. break;
  1112. case IDM_ABOUT:
  1113. return FrameCommandAbout(hWnd);
  1114. case IDM_RETURN:
  1115. return FrameCommandReturn();
  1116. case IDTB_CB_PRINTERS:
  1117. FrameCommandDefaultPrinter(hWnd, HIWORD(wParam));
  1118. break;
  1119. case ID_TOOLBAR:
  1120. FrameCommandToolbarNotify(hWnd, wParam, lParam);
  1121. break;
  1122. case IDC_TAB:
  1123. FrameCommandTab(hWnd);
  1124. break;
  1125. default:
  1126. return FrameCommandDefault(hWnd, wParam, lParam);
  1127. }
  1128. break;
  1129. #ifdef LATER
  1130. case WM_QUERYENDSESSION:
  1131. case WM_CLOSE:
  1132. SendMessage(hWnd, WM_COMMAND, IDM_CLOSEALL, 0L);
  1133. if (NULL != GetWindow(hwndClient, GW_CHILD))
  1134. return 0;
  1135. #endif
  1136. case WM_NOTIFY:
  1137. {
  1138. LPTOOLTIPTEXT lpTT = (LPTOOLTIPTEXT) lParam;
  1139. if (lpTT->hdr.code == TTN_NEEDTEXT) {
  1140. if (!LoadString (hInst, lpTT->hdr.idFrom, lpTT->szText, 80))
  1141. lpTT->szText[0] = TEXT('\0');
  1142. }
  1143. }
  1144. break;
  1145. case WM_SYSCOLORCHANGE:
  1146. FrameSysColorChange( );
  1147. break;
  1148. case WM_WININICHANGE:
  1149. FrameWinIniChange( hWnd, (LPTSTR)lParam );
  1150. break;
  1151. case WM_DROPOBJECT:
  1152. return 0x544E5250L; // 'PRNT' tells fm to print
  1153. case WM_UPDATE_DEFAULT:
  1154. UpdateDefaultList( );
  1155. return 0;
  1156. case WM_PRINTER_ADDED:
  1157. FramePrinterAdded(hWnd, wParam);
  1158. return 0;
  1159. case WM_REG_NOTIFY_CHANGE_KEY_VALUE:
  1160. FrameRegNotifyChangeKeyValue( hWnd, (HKEY)wParam );
  1161. return 0;
  1162. case WM_THREAD_ERROR:
  1163. FrameThreadError(hWnd, (PMDIWIN_INFO)lParam, wParam);
  1164. return 0;
  1165. case WM_DESTROY :
  1166. PostQuitMessage(0);
  1167. return 0;
  1168. default:
  1169. return DefFrameProc(hWnd, hwndClient, message, wParam, lParam);
  1170. }
  1171. // Pass unprocessed msgs to DefFrameProc(not DefWindowProc)
  1172. return 0;
  1173. }
  1174. /*
  1175. * ROUTINES CALLED BY FrameWndProc:
  1176. */
  1177. /*
  1178. *
  1179. */
  1180. LONG FrameCreate(HWND hWnd, LPCREATESTRUCT pCreateStruct)
  1181. {
  1182. CLIENTCREATESTRUCT clientcreate;
  1183. HMENU hMenu;
  1184. HDC hDC;
  1185. RECT rc;
  1186. BOOL NetworkAccess;
  1187. DWORD ThreadId;
  1188. DWORD i;
  1189. SetWindowLong(hWnd, GWL_USERDATA, (LONG)pCreateStruct->lpCreateParams);
  1190. hwndFrame = hWnd;
  1191. hDC = GetDC(hWnd);
  1192. GetTextMetrics(hDC, &tm);
  1193. cy = tm.tmExternalLeading + tm.tmHeight;
  1194. cx = tm.tmAveCharWidth;
  1195. dyBorder = GetSystemMetrics(SM_CYBORDER);
  1196. dyBorderx2 = dyBorder * 2;
  1197. // dyStatus = tm.tmHeight + tm.tmExternalLeading + 7 * dyBorder;
  1198. dxStatPrtField = GetDeviceCaps(hDC, LOGPIXELSX) * 3; // 3 inches
  1199. dxStatProgField = GetDeviceCaps(hDC, LOGPIXELSX) * 3 / 2; // 1 1/2 inches
  1200. dxStatQueField = GetDeviceCaps(hDC, LOGPIXELSX) * 2; // 2 inches
  1201. ReleaseDC(hWnd, hDC);
  1202. // OpenPrinterForSpecifiedAccess( NULL, &hLocalServer,
  1203. // PRINTER_ACCESS_HIGHEST_PERMITTED,
  1204. // &LocalPermission );
  1205. GetMaximumServerAccess( NULL,
  1206. &LocalPermission,
  1207. &hLocalServer );
  1208. if( hLocalServer )
  1209. CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)LocalServerThread,
  1210. hLocalServer, 0, &ThreadId );
  1211. ThreadMessageWritten = CreateEvent( NULL,
  1212. EVENT_RESET_AUTOMATIC,
  1213. EVENT_INITIAL_STATE_NOT_SIGNALED,
  1214. NULL );
  1215. if( ThreadMessageWritten == NULL )
  1216. DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
  1217. ThreadMessageRead = CreateEvent( NULL,
  1218. EVENT_RESET_AUTOMATIC,
  1219. EVENT_INITIAL_STATE_SIGNALED,
  1220. NULL );
  1221. if( ThreadMessageRead == NULL )
  1222. DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
  1223. #if DBG
  1224. if( WaitForSingleObject( ThreadMessageRead, 0 ) != WAIT_OBJECT_0 )
  1225. DBGMSG( DBG_WARNING, ( "Event was not signaled!\n" ) );
  1226. SetEvent( ThreadMessageRead );
  1227. #endif /* DBG */
  1228. // Set initial state of some menu items
  1229. hMenu = GetMenu(hwndFrame);
  1230. if (bStatusBar)
  1231. CheckMenuItem(hMenu, IDM_STATUSBAR, MF_BYCOMMAND | MF_CHECKED);
  1232. if (bToolBar)
  1233. CheckMenuItem(hMenu, IDM_TOOLBAR, MF_BYCOMMAND | MF_CHECKED);
  1234. if (bSaveSettings)
  1235. CheckMenuItem(hMenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_CHECKED);
  1236. /* Get the handles of the popup menus:
  1237. */
  1238. for( i = 0; i < POPUP_COUNT; i++ )
  1239. pMenuHelpIDs[i*2+3] = (DWORD)GetSubMenu( hMenu, i );
  1240. // Load resource strings
  1241. LoadString(hInst, IDS_UNTITLED, strUntitled,
  1242. sizeof(strUntitled) / sizeof(*strUntitled));
  1243. LoadString(hInst, IDS_BYTES, szSizeFormat,
  1244. sizeof(szSizeFormat) / sizeof(*szSizeFormat));
  1245. // CountryCode - krishnag
  1246. if (bJapan) {
  1247. // if we're NT-J
  1248. hfontHelv = NULL;
  1249. hfontHelvBold = NULL;
  1250. } else {
  1251. // we're not NT-J
  1252. hfontHelv = CreateFont(GetHeightFromPointsString(sz8), 0, 0, 0, 400, 0, 0, 0,
  1253. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1254. DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, szHelv);
  1255. hfontHelvBold = CreateFont(GetHeightFromPointsString(sz8), 0, 0, 0, 700, 0, 0, 0,
  1256. ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1257. DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, szHelv);
  1258. }
  1259. CreateMDIDefaultColumns( hWnd, MDIHEAD_JOB_COUNT, IDS_FIRST_HEADER_PRINTER,
  1260. MDIPrinterDefaultColumn, MDIPrinterMinimumCharacterWidth );
  1261. CreateMDIDefaultColumns( hWnd, MDIHEAD_PRINTER_COUNT, IDS_FIRST_HEADER_SERVER,
  1262. MDIServerDefaultColumn, MDIServerMinimumCharacterWidth );
  1263. hcursorArrow = LoadCursor( NULL, IDC_ARROW );
  1264. hcursorWait = LoadCursor( NULL, IDC_WAIT );
  1265. hcursorReorder = LoadCursor( hInst, MAKEINTRESOURCE( IDC_REORDER ) );
  1266. InitializeInternationalTimeConstants( );
  1267. // Setup clientcreate struct for MDI windows and menu
  1268. clientcreate.hWindowMenu = GetSubMenu(GetMenu(hWnd), POPUP_WINDOW);
  1269. clientcreate.idFirstChild = IDM_FIRSTCHILD;
  1270. GetClientRect(hWnd, &rc);
  1271. NetworkAccess = UserHasNetworkAccess( );
  1272. NetworkInstalled = NetworkIsInstalled( );
  1273. if( !NetworkAccess )
  1274. RemoveNetworkMenuItems( hWnd );
  1275. // Make toolbar window
  1276. hwndToolbar = PMCreateToolbar( NetworkAccess );
  1277. if (!hwndToolbar)
  1278. return -1L;
  1279. hwndClient = CreateWindow(TEXT("MDICLIENT"), NULL,
  1280. WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL,
  1281. -dyBorder, -dyBorder + ( bToolBar ? DYTOOLBAR : 0 ),
  1282. rc.right, rc.bottom, hWnd,
  1283. (HMENU)1, hInst, (LPTSTR)&clientcreate);
  1284. hwndStatus = CreateWindow(STATUSCLASSNAME, TEXT(""),
  1285. WS_CHILD | WS_BORDER |
  1286. ( bStatusBar ? WS_VISIBLE : 0 ),
  1287. -100, -100, 10, 10, hWnd,
  1288. (HMENU) ID_STATUSBAR, hInst, NULL);
  1289. SendMessage( hwndStatus, WM_SIZE, 0, 0L );
  1290. // SetStatusMode( STATUS_MODE_NORMAL, FALSE );
  1291. if (!hwndClient)
  1292. return -1L;
  1293. DragAcceptFiles( hWnd, TRUE );
  1294. PostMessage( hWnd, WM_INIT_PRINTER_WINDOWS, 0, 0 );
  1295. if( NetworkAccess )
  1296. PostMessage( hWnd, WM_INIT_SERVER_WINDOWS, 0, 0 );
  1297. return 0;
  1298. }
  1299. VOID CreateMDIDefaultColumns( HWND hwnd, DWORD cColumns, DWORD idFirstHeader,
  1300. PCOLUMN pColumns, PINT pDefaultWidths )
  1301. {
  1302. DWORD i;
  1303. TCHAR string[40];
  1304. HDC hdc;
  1305. int dx;
  1306. SIZE TxtSize;
  1307. SIZE DefSize;
  1308. /* Test buffer to check extent of default character width of columns.
  1309. * Must contain at least as many characters as the largest value in
  1310. * Server/PrinterMinimumCharacterWidth:
  1311. */
  1312. TCHAR TestBuffer[] = TEXT("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
  1313. /* Load the heading strings:
  1314. */
  1315. for( i = 0; i < cColumns; i++ )
  1316. {
  1317. LoadString(hInst, idFirstHeader + i, string,
  1318. sizeof string / sizeof *string);
  1319. if( !( pColumns[i].Text = AllocSplStr( string ) ) )
  1320. pColumns[i].Text = szNULL;
  1321. }
  1322. // Create columnar heading text fields in window
  1323. hdc = GetDC(hwnd);
  1324. for (i = 0; i < cColumns; i++)
  1325. {
  1326. SelectObject(hdc, hfontHelv);
  1327. GetTextExtentPoint (hdc, pColumns[i].Text,
  1328. _tcslen(pColumns[i].Text),
  1329. &TxtSize);
  1330. // Allow for space on either side of char string
  1331. dx = TxtSize.cx + 4 * cx;
  1332. if( pDefaultWidths[i] )
  1333. GetTextExtentPoint (hdc, TestBuffer, pDefaultWidths[i], &DefSize);
  1334. else
  1335. DefSize.cx = 0;
  1336. dx = max( dx, DefSize.cx );
  1337. pColumns[i].Width = dx;
  1338. }
  1339. ReleaseDC(hwnd, hdc);
  1340. }
  1341. /*
  1342. *
  1343. */
  1344. VOID GetSystemColors( VOID )
  1345. {
  1346. SysColorHighlight = GetSysColor( COLOR_HIGHLIGHT );
  1347. SysColorHighlightText = GetSysColor( COLOR_HIGHLIGHTTEXT );
  1348. SysColorWindow = GetSysColor( COLOR_WINDOW );
  1349. SysColorWindowText = GetSysColor( COLOR_WINDOWTEXT );
  1350. SysColorBtnFace = GetSysColor( COLOR_BTNFACE );
  1351. SysColorBtnText = GetSysColor( COLOR_BTNTEXT );
  1352. SysColorBtnHighlight = GetSysColor( COLOR_BTNHIGHLIGHT );
  1353. SysColorBtnShadow = GetSysColor( COLOR_BTNSHADOW );
  1354. SysColorWindowFrame = GetSysColor( COLOR_WINDOWFRAME );
  1355. }
  1356. /* UserHasNetworkAccess
  1357. *
  1358. * Looks in the registry to see whether the Value under "Network" is set to 1.
  1359. *
  1360. * Three scenarios handled:
  1361. *
  1362. * 1. Key found and value == 1: Access granted
  1363. *
  1364. * 2. Key not found because it isn't there: Access granted
  1365. *
  1366. * 3. Key not found because of some other error: Access denied
  1367. *
  1368. *
  1369. * Return value:
  1370. *
  1371. * Boolean
  1372. *
  1373. */
  1374. BOOL UserHasNetworkAccess( VOID )
  1375. {
  1376. DWORD AccessFlag;
  1377. DWORD rc;
  1378. BOOL AccessGranted;
  1379. REGISTRY_ENTRY RegistryNetworkEntry = { REG_DWORD, sizeof(DWORD) };
  1380. rc = ReadRegistryData( NULL, TEXT("Network"), (LPBYTE)&AccessFlag, &RegistryNetworkEntry );
  1381. switch( rc )
  1382. {
  1383. case NO_ERROR:
  1384. AccessGranted = ( AccessFlag == 1 );
  1385. break;
  1386. case ERROR_FILE_NOT_FOUND:
  1387. AccessGranted = TRUE;
  1388. break;
  1389. default:
  1390. AccessGranted = FALSE;
  1391. }
  1392. return AccessGranted;
  1393. }
  1394. /* RemoveNetworkMenuItems
  1395. *
  1396. * Removes the following menu items in the Printer pull-down:
  1397. *
  1398. * Connect to Printer...
  1399. * Remove Printer Connection
  1400. * Server Viewer...
  1401. * (separator)
  1402. *
  1403. */
  1404. VOID RemoveNetworkMenuItems( HWND hwnd )
  1405. {
  1406. HMENU hSubMenu;
  1407. /* Get the handle of the Printer pull-down menu:
  1408. */
  1409. hSubMenu = GetSubMenu( GetMenu( hwnd ), 0 );
  1410. DeleteMenu( hSubMenu, 13, MF_BYPOSITION );
  1411. DeleteMenu( hSubMenu, IDM_SERVERVIEWER, MF_BYCOMMAND );
  1412. DeleteMenu( hSubMenu, IDM_CONNECTTOPRINTER, MF_BYCOMMAND );
  1413. // DeleteMenu( hSubMenu, IDM_REMOVECONNECTION, MF_BYCOMMAND );
  1414. }
  1415. /* NetworkIsInstalled
  1416. *
  1417. * This routine checks to see whether there is a value in the registry
  1418. * which will indicate that the network is installed.
  1419. *
  1420. * The alternative would be to call WNetOpenEnum, but this drags in
  1421. * MPR and other stuff.
  1422. */
  1423. BOOL NetworkIsInstalled( VOID )
  1424. {
  1425. DWORD Status;
  1426. HKEY hkeyNetworkProviderOrder;
  1427. DWORD Size;
  1428. BOOL rc = FALSE;
  1429. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1430. TEXT("SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order"),
  1431. 0, KEY_READ, &hkeyNetworkProviderOrder );
  1432. if( Status == NO_ERROR )
  1433. {
  1434. Status = RegQueryValueEx( hkeyNetworkProviderOrder,
  1435. TEXT("ProviderOrder"),
  1436. 0,
  1437. NULL,
  1438. NULL,
  1439. &Size );
  1440. if( Status == NO_ERROR )
  1441. rc = TRUE;
  1442. RegCloseKey( hkeyNetworkProviderOrder );
  1443. }
  1444. return rc;
  1445. }
  1446. /* SetStatusMode
  1447. *
  1448. */
  1449. VOID SetStatusMode( int Mode, BOOL Update )
  1450. {
  1451. INT RightOfPane[SF_COUNT];
  1452. RightOfPane[0] = dxStatPrtField;
  1453. RightOfPane[1] = dxStatPrtField + dxStatProgField;
  1454. RightOfPane[2] = dxStatPrtField + dxStatProgField + dxStatQueField;
  1455. switch( Mode )
  1456. {
  1457. case STATUS_MODE_NORMAL:
  1458. SendMessage( hwndStatus, SB_SIMPLE, FALSE, 0 );
  1459. SendMessage( hwndStatus, SB_SETPARTS, SF_COUNT, (LPARAM)RightOfPane );
  1460. SendMessage( hwndStatus, WM_SIZE, 0, 0L );
  1461. break;
  1462. case STATUS_MODE_HELP:
  1463. SendMessage( hwndStatus, SB_SIMPLE, TRUE, 0 );
  1464. SendMessage( hwndStatus, WM_SIZE, 0, 0L );
  1465. break;
  1466. }
  1467. if( Update )
  1468. UpdateStatus( NULL );
  1469. }
  1470. //
  1471. // Used to display any error message from worker threads.
  1472. // (This ensures even synchronization of multiple error message
  1473. // boxes and prevents the worker thread from any calling user.)
  1474. //
  1475. // We also check dwError for bit 29 (CustomerBit), which the
  1476. // Sendee can use as an extra bit of info.
  1477. //
  1478. LONG
  1479. FrameThreadError(
  1480. HWND hWnd,
  1481. PMDIWIN_INFO pMDIWinInfo,
  1482. DWORD dwError)
  1483. {
  1484. LPTSTR pErrorString;
  1485. BOOL bCustomerCode = FALSE;
  1486. if (pMDIWinInfo->Alive)
  1487. {
  1488. if (dwError & (1<<29))
  1489. {
  1490. bCustomerCode = TRUE;
  1491. //
  1492. // Now turn the bit off so we can use it normally with
  1493. // FormatMessage();
  1494. //
  1495. dwError &= ~(1<<29);
  1496. }
  1497. pErrorString = GetErrorString(dwError);
  1498. switch(pMDIWinInfo->WindowType)
  1499. {
  1500. case MDIWIN_SERVER:
  1501. //
  1502. // In InitServerWindowThread, we set bit 29 if the error
  1503. // indicates we couldn't open the server for auto refresh,
  1504. // but we could enumerate.
  1505. //
  1506. Message( hWnd,
  1507. MSG_ERROR,
  1508. IDS_PRINTMANAGER,
  1509. #if 0
  1510. //
  1511. // Turned off in threads.c, so turn off
  1512. // here.
  1513. //
  1514. bCustomerCode ?
  1515. IDS_COULDNOTOPENSERVERREFRESH :
  1516. #endif
  1517. IDS_COULDNOTGETSERVERINFO,
  1518. ((PSERVER_CONTEXT)pMDIWinInfo->pContext)->pServerName,
  1519. pErrorString );
  1520. break;
  1521. default:
  1522. Message( hWnd,
  1523. MSG_ERROR,
  1524. IDS_PRINTMANAGER,
  1525. IDS_OPEN_PRINTER_FAILED,
  1526. ((PQUEUE)pMDIWinInfo->pContext)->pPrinterName,
  1527. pErrorString );
  1528. break;
  1529. }
  1530. FreeSplStr( pErrorString );
  1531. }
  1532. return 0;
  1533. }
  1534. /*
  1535. *
  1536. */
  1537. LONG FrameInitMenu(HWND hWnd)
  1538. {
  1539. HWND hwndChild;
  1540. PMDIWIN_INFO pMDIWinInfo;
  1541. PQUEUE pQueue = NULL;
  1542. PSERVER_CONTEXT pServerContext = NULL;
  1543. UINT State;
  1544. HMENU hMenu;
  1545. PPRINTER_INFO_2 pPrinter;
  1546. BOOL PrinterExists;
  1547. BOOL PrinterPaused;
  1548. BOOL DocumentExists;
  1549. BOOL DocumentSelected;
  1550. BOOL DocumentPaused;
  1551. BOOL PrinterIsLocal; // Undefined if !PrinterExists
  1552. BOOL UserHasServerAdminAccess = FALSE;
  1553. BOOL UserHasPrinterAdminAccess = FALSE;
  1554. BOOL ShowSecurity = FALSE;
  1555. BOOL PermitAuditing = FALSE;
  1556. BOOL ForceRefresh = TRUE;
  1557. // Disable (Grey) some menu items if there are no printers
  1558. // or if there are no jobs selected (or no jobs at all) on
  1559. // the active printer
  1560. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  1561. hMenu = GetMenu(hWnd);
  1562. if( hwndChild && (pMDIWinInfo = GETMDIWIN( hwndChild )))
  1563. {
  1564. ENTER_PROTECTED_DATA( pMDIWinInfo );
  1565. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  1566. {
  1567. pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
  1568. PrinterExists = ( pServerContext->cPrinters > 0 );
  1569. if( PrinterExists )
  1570. {
  1571. PrinterIsLocal = TRUE; // because it's local to the server we're looking at
  1572. pPrinter = pServerContext->pSelPrinter;
  1573. PrinterPaused = ( pPrinter->Status & PRINTER_STATUS_PAUSED );
  1574. }
  1575. /* Can't manipulate jobs from Server windows:
  1576. */
  1577. DocumentExists = FALSE;
  1578. DocumentSelected = FALSE;
  1579. DocumentPaused = FALSE;
  1580. /* Need to check for this:
  1581. */
  1582. UserHasServerAdminAccess =
  1583. ( pServerContext->AccessGranted & SERVER_ACCESS_ADMINISTER );
  1584. /* Check whether the Printer Pause button is enabled.
  1585. * If so, the user must have Administer access on the selected printer:
  1586. */
  1587. UserHasPrinterAdminAccess = IS_BUTTON_ENABLED( IDM_PRINTER_PAUSE );
  1588. /* Don't show Security options for server windows:
  1589. */
  1590. ForceRefresh = FALSE;
  1591. }
  1592. else
  1593. {
  1594. pQueue = (PQUEUE)pMDIWinInfo->pContext;
  1595. pPrinter = pQueue->pPrinter;
  1596. PrinterExists = TRUE;
  1597. PrinterIsLocal = ( ( pMDIWinInfo->WindowType == MDIWIN_LOCALPRINTER )
  1598. ||( pMDIWinInfo->WindowType == MDIWIN_LOCALNETWORKPRINTER ) );
  1599. if( pPrinter )
  1600. PrinterPaused = ( pPrinter->Status & PRINTER_STATUS_PAUSED );
  1601. else
  1602. PrinterPaused = FALSE;
  1603. if( ( !pPrinter )
  1604. ||( pQueue->SelJobId == 0 )
  1605. ||( pPrinter->cJobs == 0 ) )
  1606. {
  1607. if( !pPrinter || ( pPrinter->cJobs == 0 ) )
  1608. DocumentExists = FALSE;
  1609. else
  1610. DocumentExists = TRUE;
  1611. DocumentSelected = FALSE;
  1612. DocumentPaused = FALSE;
  1613. }
  1614. else
  1615. {
  1616. DocumentExists = TRUE;
  1617. DocumentSelected = TRUE;
  1618. DocumentPaused = ( pQueue->pSelJob->Status
  1619. & JOB_STATUS_PAUSED );
  1620. }
  1621. /* Administer privilege on the server is needed to create a printer:
  1622. */
  1623. UserHasServerAdminAccess =
  1624. ( LocalPermission & SERVER_ACCESS_ADMINISTER );
  1625. /* Administer privilege on the printer is needed to delete a printer:
  1626. */
  1627. UserHasPrinterAdminAccess =
  1628. ( pQueue->AccessGranted & PRINTER_ACCESS_ADMINISTER );
  1629. /* Always enable the Permissions and Take Ownership options.
  1630. * The user requires READ_CONTROL to see them, which he probably
  1631. * has:
  1632. */
  1633. ShowSecurity = TRUE;
  1634. /* Auditing actually requires ACCESS_SYSTEM_SECURITY privilege.
  1635. */
  1636. PermitAuditing = TRUE;
  1637. }
  1638. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  1639. }
  1640. else
  1641. {
  1642. PrinterExists = FALSE;
  1643. PrinterPaused = FALSE;
  1644. DocumentExists = FALSE;
  1645. DocumentSelected = FALSE;
  1646. DocumentPaused = FALSE;
  1647. UserHasServerAdminAccess =
  1648. ( LocalPermission & SERVER_ACCESS_ADMINISTER );
  1649. }
  1650. State = MF_BYCOMMAND | ( PrinterExists ? MF_ENABLED : MF_GRAYED );
  1651. EnableMenuItem(hMenu, IDM_FORMS, State);
  1652. State = MF_BYCOMMAND | ( ( ( PrinterExists && PrinterIsLocal && UserHasPrinterAdminAccess
  1653. /* We need a handle to delete the printer. */
  1654. /* This may not be so if it's down: */
  1655. && ( pQueue ? (BOOL)pQueue->hPrinter : TRUE ) )
  1656. ||( PrinterExists && !PrinterIsLocal ) ) ? MF_ENABLED : MF_GRAYED );
  1657. EnableMenuItem(hMenu, IDM_DELETEPRINTER, State);
  1658. // State = MF_BYCOMMAND | ( ( PrinterExists && !PrinterIsLocal ) ? MF_ENABLED : MF_GRAYED );
  1659. // EnableMenuItem(hMenu, IDM_REMOVECONNECTION, State);
  1660. State = MF_BYCOMMAND | ( ( PrinterExists && pPrinter ) ? MF_ENABLED : MF_GRAYED );
  1661. EnableMenuItem(hMenu, IDM_PROPERTIES, State);
  1662. if( UserHasPrinterAdminAccess )
  1663. {
  1664. State = MF_BYCOMMAND | ( ( PrinterExists && !PrinterPaused ) ? MF_ENABLED : MF_GRAYED );
  1665. EnableMenuItem(hMenu, IDM_PRINTER_PAUSE, State);
  1666. State = MF_BYCOMMAND | ( ( PrinterExists && PrinterPaused ) ? MF_ENABLED : MF_GRAYED );
  1667. EnableMenuItem(hMenu, IDM_PRINTER_RESUME, State);
  1668. State = MF_BYCOMMAND | ( DocumentExists ? MF_ENABLED : MF_GRAYED );
  1669. EnableMenuItem(hMenu, IDM_PURGEPRINTER, State);
  1670. }
  1671. else
  1672. {
  1673. /* Grey out both Pause and Resume Printer menu items if no Admin priv:
  1674. */
  1675. State = MF_BYCOMMAND | MF_GRAYED;
  1676. EnableMenuItem(hMenu, IDM_PRINTER_PAUSE, State);
  1677. EnableMenuItem(hMenu, IDM_PRINTER_RESUME, State);
  1678. EnableMenuItem(hMenu, IDM_PURGEPRINTER, State);
  1679. }
  1680. State = MF_BYCOMMAND | ( DocumentSelected ? MF_ENABLED : MF_GRAYED );
  1681. EnableMenuItem(hMenu, IDM_REMOVEDOC, State);
  1682. EnableMenuItem(hMenu, IDM_DOCTAILS, State);
  1683. EnableMenuItem(hMenu, IDM_RESTART, State);
  1684. /* We can't get enough information to determine whether the user had
  1685. * Administer Document privilege, so we'll just have to enable the
  1686. * Pause or Resume Document menu item;
  1687. */
  1688. State = MF_BYCOMMAND | ( ( DocumentSelected && !DocumentPaused ) ? MF_ENABLED : MF_GRAYED );
  1689. EnableMenuItem(hMenu, IDM_DOCUMENT_PAUSE, State);
  1690. State = MF_BYCOMMAND | ( ( DocumentSelected && DocumentPaused ) ? MF_ENABLED : MF_GRAYED );
  1691. EnableMenuItem(hMenu, IDM_DOCUMENT_RESUME, State);
  1692. State = MF_BYCOMMAND | ( hwndChild ? MF_ENABLED : MF_GRAYED );
  1693. EnableMenuItem(hMenu, IDM_CASCADE, State);
  1694. EnableMenuItem(hMenu, IDM_TILEHORZ, State);
  1695. EnableMenuItem(hMenu, IDM_TILEVERT, State);
  1696. EnableMenuItem(hMenu, IDM_ARRANGE, State);
  1697. EnableMenuItem(hMenu, IDM_REFRESH, State);
  1698. State = MF_BYCOMMAND | ( UserHasServerAdminAccess ? MF_ENABLED : MF_GRAYED );
  1699. EnableMenuItem(hMenu, IDM_INSTALLPRINTER, State);
  1700. State = MF_BYCOMMAND | ( ShowSecurity ? MF_ENABLED : MF_GRAYED );
  1701. EnableMenuItem(hMenu, IDM_PERMISSIONS, State);
  1702. EnableMenuItem(hMenu, IDM_OWNER, State);
  1703. State = MF_BYCOMMAND | ( PermitAuditing ? MF_ENABLED : MF_GRAYED );
  1704. EnableMenuItem(hMenu, IDM_AUDITING, State);
  1705. State = MF_BYCOMMAND | ( ForceRefresh ? MF_ENABLED : MF_GRAYED );
  1706. EnableMenuItem(hMenu, IDM_REFRESH, State);
  1707. State = MF_BYCOMMAND | ( NetworkInstalled ? MF_ENABLED : MF_GRAYED );
  1708. EnableMenuItem(hMenu, IDM_CONNECTTOPRINTER, State);
  1709. EnableMenuItem(hMenu, IDM_SERVERVIEWER, State);
  1710. return 0;
  1711. }
  1712. /*
  1713. *
  1714. */
  1715. LONG FrameMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam )
  1716. {
  1717. UINT ItemID;
  1718. UINT Flags;
  1719. HMENU hmenu;
  1720. ItemID = (UINT)LOWORD( wParam );
  1721. Flags = (UINT)HIWORD( wParam );
  1722. hmenu = (HMENU)lParam;
  1723. /* HACK:
  1724. *
  1725. * If the item is in the "Windows" popup, but isn't between "Cascade"
  1726. * and "Refresh" it must be the name of an MDI window added by the system.
  1727. * We don't know the IDs of these added menu items - can we find out?
  1728. */
  1729. if( ( (DWORD)hmenu == pMenuHelpIDs[POPUP_WINDOW*2+3] )
  1730. &&( ( ItemID < IDM_CASCADE ) || ( ItemID > IDM_REFRESH ) ) )
  1731. {
  1732. ItemID = IDS_HELP_MDIWINDOW;
  1733. WinHelpMenuID = ID_HELP_MDIWINDOW;
  1734. }
  1735. /* Another hack:
  1736. *
  1737. * If the item selected is IDM_DELETEPRINTER and the active window
  1738. * is a network printer, change it to the now obsolete IDM_REMOVECONNECTION,
  1739. * since this has more appropriate help information:
  1740. */
  1741. if( ItemID == IDM_DELETEPRINTER )
  1742. {
  1743. HWND hwndChild;
  1744. PMDIWIN_INFO pMDIWinInfo;
  1745. if( hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L) )
  1746. {
  1747. pMDIWinInfo = GETMDIWIN( hwndChild );
  1748. if( ( pMDIWinInfo->WindowType == MDIWIN_NETWORKPRINTER )
  1749. ||( pMDIWinInfo->WindowType == MDIWIN_LOCALNETWORKPRINTER ) )
  1750. ItemID = IDM_REMOVECONNECTION;
  1751. }
  1752. }
  1753. MenuHelp( WM_MENUSELECT, MAKEWPARAM( ItemID, HIWORD( wParam ) ), lParam,
  1754. GetMenu( hwnd ), hInst, hwndStatus, pMenuHelpIDs);
  1755. if( ItemID && ( Flags & MF_SYSMENU ) )
  1756. WinHelpMenuID = ID_HELP_FRAME_SYSMENU;
  1757. else
  1758. WinHelpMenuID = ItemID;
  1759. return 0;
  1760. }
  1761. /*
  1762. *
  1763. */
  1764. LONG FramePaint(HWND hWnd)
  1765. {
  1766. PAINTSTRUCT ps;
  1767. BeginPaint(hWnd, &ps);
  1768. EndPaint(hWnd, &ps);
  1769. return 0;
  1770. }
  1771. /*
  1772. *
  1773. */
  1774. VOID FrameSize(HWND hWnd, WPARAM Type, long Dimensions)
  1775. {
  1776. RECT rc;
  1777. int dx, dy;
  1778. int yToolbar, dyTB, yClientTop;
  1779. int ToolbarHeight;
  1780. if (Type != SIZEICONIC)
  1781. {
  1782. // make things look good by putting WS_BORDER on the
  1783. // client, then adjust the thing so it gets clipped
  1784. dx = LOWORD(Dimensions) + dyBorderx2;
  1785. dy = HIWORD(Dimensions) + dyBorderx2;
  1786. if (bStatusBar)
  1787. {
  1788. GetWindowRect( hwndStatus, &rc );
  1789. dy -= ( rc.bottom - rc.top - 1);
  1790. }
  1791. GetWindowRect( hwndToolbar, &rc );
  1792. ToolbarHeight = ( rc.bottom - rc.top );
  1793. if (bToolBar)
  1794. {
  1795. dy -= ToolbarHeight + 1;
  1796. yToolbar = -dyBorder;
  1797. dyTB = ToolbarHeight + dyBorder;
  1798. yClientTop = ToolbarHeight - dyBorder;
  1799. }
  1800. else
  1801. {
  1802. dy += 1;
  1803. yToolbar = -2 * ToolbarHeight;
  1804. dyTB = ToolbarHeight;
  1805. yClientTop = -dyBorder;
  1806. }
  1807. // Size the MDI CLIENT window
  1808. MoveWindow(hwndClient, -dyBorder, yClientTop, dx, dy, TRUE);
  1809. // Size the TOOLBAR window
  1810. MoveWindow(hwndToolbar, -dyBorder, yToolbar, dx, dyTB, TRUE);
  1811. // if (bStatusBar)
  1812. // {
  1813. // GetClientRect(hwndFrame, &rc);
  1814. // rc.top = rc.bottom - dyStatus;
  1815. // InvalidateRect(hWnd, &rc, TRUE);
  1816. // }
  1817. SendMessage( hwndStatus, WM_SIZE, 0, 0L );
  1818. /* Bug #14592
  1819. * Make sure the combo-box doesn't get detached:
  1820. */
  1821. SendMessage( hwndPrinterList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0 );
  1822. }
  1823. }
  1824. /*
  1825. *
  1826. */
  1827. VOID FrameClose(HWND hwnd)
  1828. {
  1829. int i;
  1830. HWND hwndMDI;
  1831. DWORD Options;
  1832. REGISTRY_ENTRY RegistrySaveSettings = { REG_DWORD, sizeof(DWORD) };
  1833. TCHAR SaveSettings[40];
  1834. Options = 0;
  1835. if( !bToolBar )
  1836. Options |= OPTION_NOTOOLBAR;
  1837. if( !bStatusBar )
  1838. Options |= OPTION_NOSTATUSBAR;
  1839. if( !bSaveSettings )
  1840. Options |= OPTION_NOSAVESETTINGS;
  1841. if( bSaveSettings )
  1842. {
  1843. /* First delete the sections in the INI file, so we don't need to worry
  1844. * if queues have been deleted or printer names have been changed
  1845. * (since we use the printer name as the INI key name):
  1846. */
  1847. DeleteRegistryValues( szRegPrinters );
  1848. DeleteRegistryValues( szRegServers );
  1849. SaveWindowPos( hwnd, Options, FALSE );
  1850. for( hwndMDI = GetWindow( hwndClient, GW_CHILD );
  1851. hwndMDI;
  1852. hwndMDI = GetWindow( hwndMDI, GW_HWNDNEXT ) )
  1853. {
  1854. SaveWindowPos( hwndMDI, 0, TRUE );
  1855. }
  1856. }
  1857. LoadString(hInst, IDS_SAVE_SETTINGS, SaveSettings,
  1858. sizeof SaveSettings / sizeof *SaveSettings);
  1859. WriteRegistryData( NULL, SaveSettings,
  1860. (LPBYTE)&bSaveSettings,
  1861. &RegistrySaveSettings );
  1862. ClosePrinter( hLocalServer );
  1863. /* Ensure that any help instances go away.
  1864. * This does nothing if help hasn't been invoked:
  1865. */
  1866. ShowHelp(hwnd, HELP_QUIT, 0);
  1867. }
  1868. /*
  1869. *
  1870. */
  1871. VOID FrameHelp(HWND hwnd, UINT HelpID)
  1872. {
  1873. if( HelpID != 0 )
  1874. ShowHelp(hwnd, HELP_CONTEXT, HelpID);
  1875. else
  1876. ShowHelp(hwnd, HELP_INDEX, (DWORD)TEXT(""));
  1877. }
  1878. /* SaveWindowPos
  1879. *
  1880. * Saves Print Manager window positions in the registry.
  1881. * MDIWindow is FALSE for the main window.
  1882. *
  1883. */
  1884. VOID SaveWindowPos( HWND hwnd, DWORD Options, BOOL MDIWindow )
  1885. {
  1886. PMDIWIN_INFO pMDIWinInfo = NULL;
  1887. LPTSTR pWindowName;
  1888. TCHAR WindowName[40];
  1889. LPTSTR pWindowType;
  1890. DWORD cbRegistryData;
  1891. DWORD cHeaders;
  1892. PREGISTRY_DATA pRegistryData;
  1893. INT i;
  1894. /* Get the size of the fixed part of the registry data:
  1895. */
  1896. cbRegistryData = ( sizeof( REGISTRY_DATA ) - sizeof( pRegistryData->Headers ) );
  1897. /* Check there's some text.
  1898. * (We can't rely on return from GETMDIWIN, because there are some
  1899. * children of the MDI client that aren't MDI windows,
  1900. * and this causes a (non-fatal) exception because of the
  1901. * invalid index for that window.)
  1902. */
  1903. GetWindowText( hwnd, WindowName, sizeof WindowName/sizeof(TCHAR) );
  1904. if( !*WindowName )
  1905. return;
  1906. if( !MDIWindow )
  1907. {
  1908. pWindowName = GetString( IDS_PRINTMANAGER );
  1909. pWindowType = NULL;
  1910. cHeaders = 0;
  1911. }
  1912. else
  1913. {
  1914. /* Don't use the actual window text for MDI windows,
  1915. * since a paused printer has the additional string " - Paused"
  1916. * in the title.
  1917. */
  1918. pMDIWinInfo = GETMDIWIN( hwnd );
  1919. switch( pMDIWinInfo->WindowType )
  1920. {
  1921. case MDIWIN_SERVER:
  1922. default:
  1923. pWindowType = szRegServers;
  1924. pWindowName = ( (PSERVER_CONTEXT)pMDIWinInfo->pContext )->pServerName;
  1925. cHeaders = pMDIWinInfo->cColumns;
  1926. break;
  1927. case MDIWIN_LOCALPRINTER:
  1928. case MDIWIN_NETWORKPRINTER:
  1929. case MDIWIN_LOCALNETWORKPRINTER:
  1930. pWindowType = szRegPrinters;
  1931. pWindowName = ( (PQUEUE)pMDIWinInfo->pContext )->pPrinterName;
  1932. cHeaders = pMDIWinInfo->cColumns;
  1933. break;
  1934. }
  1935. }
  1936. cbRegistryData += ( cHeaders * sizeof pRegistryData->Headers );
  1937. pRegistryData = AllocSplMem( cbRegistryData );
  1938. if( !pRegistryData )
  1939. return;
  1940. /* Make sure there's a window title for the key name:
  1941. */
  1942. if( *pWindowName )
  1943. {
  1944. pRegistryData->WindowPlacement.length =
  1945. sizeof(pRegistryData->WindowPlacement);
  1946. if( GetWindowPlacement( hwnd, &pRegistryData->WindowPlacement ) )
  1947. {
  1948. pRegistryData->Options = Options;
  1949. RegistryEntries.Size = cbRegistryData;
  1950. if( MDIWindow )
  1951. {
  1952. for( i = 0; i < pMDIWinInfo->cColumns; i++ )
  1953. pRegistryData->Headers[i] = pMDIWinInfo->pColumns[i].Width;
  1954. }
  1955. WriteRegistryData( pWindowType, pWindowName,
  1956. (LPBYTE)pRegistryData,
  1957. &RegistryEntries );
  1958. }
  1959. }
  1960. FreeSplMem( pRegistryData );
  1961. if( !MDIWindow )
  1962. FreeSplStr( pWindowName );
  1963. }
  1964. /*
  1965. *
  1966. */
  1967. LONG FrameCommandConnectToPrinter(HWND hWnd)
  1968. {
  1969. HANDLE hPrinter;
  1970. LPPRINTER_INFO_2 pPrinter = NULL;
  1971. DWORD cbPrinter = 0;
  1972. PQUEUE pQueue;
  1973. HWND hwndActive;
  1974. PMDIWIN_INFO pInfo = NULL;
  1975. HWND hwndPrinter;
  1976. LPWSTR pszPrinterName;
  1977. SetCursor( hcursorWait );
  1978. hPrinter = ConnectToPrinterDlg( hWnd, 0 );
  1979. if( hPrinter )
  1980. {
  1981. if( GetGeneric( (PROC)GetPrinter, 2, (PBYTE *)&pPrinter, cbPrinter,
  1982. &cbPrinter, (PVOID)hPrinter, NULL ) )
  1983. {
  1984. //
  1985. // If it's local and not remote, yet it begins with \\,
  1986. // remove the server name since the server is the local
  1987. // machine, and the printer window won't have the server name.
  1988. //
  1989. // This handles the case when we attempt to connect to
  1990. // a local printer.
  1991. //
  1992. if ((pPrinter->Attributes & PRINTER_ATTRIBUTE_LOCAL) &&
  1993. !(pPrinter->Attributes & PRINTER_ATTRIBUTE_NETWORK) &&
  1994. pPrinter->pPrinterName[0] == BACKSLASH &&
  1995. pPrinter->pPrinterName[1] == BACKSLASH)
  1996. {
  1997. pszPrinterName = _tcsrchr(&pPrinter->pPrinterName[2], BACKSLASH);
  1998. pszPrinterName++;
  1999. }
  2000. else
  2001. {
  2002. pszPrinterName = pPrinter->pPrinterName;
  2003. }
  2004. hwndPrinter = FindPrinterWindow( pszPrinterName );
  2005. /* Don't create a new window if we already have a connexion
  2006. * to this printer:
  2007. */
  2008. if( hwndPrinter )
  2009. {
  2010. SendMessage( hwndClient, WM_MDIACTIVATE, (WPARAM)hwndPrinter, 0L );
  2011. if( IsIconic( hwndPrinter ) )
  2012. ShowWindow( hwndPrinter, SW_RESTORE );
  2013. }
  2014. else
  2015. {
  2016. pQueue = AllocQueue( pPrinter->pPrinterName );
  2017. if( pQueue )
  2018. {
  2019. pQueue->Error = OpenThreadObject(pQueue->pPrinterName,
  2020. &pQueue->hPrinter,
  2021. &pQueue->AccessGranted,
  2022. MDIWIN_NETWORKPRINTER);
  2023. if( !pQueue->Error )
  2024. {
  2025. DWORD WindowType;
  2026. DWORD Flags = 0;
  2027. pQueue->pServerName = AllocSplStr( pPrinter->pServerName );
  2028. if( ALL_FLAGS_ARE_SET( pPrinter->Attributes,
  2029. PRINTER_ATTRIBUTE_NETWORK
  2030. | PRINTER_ATTRIBUTE_LOCAL ) )
  2031. WindowType = MDIWIN_LOCALNETWORKPRINTER;
  2032. else
  2033. WindowType = MDIWIN_NETWORKPRINTER;
  2034. if( pPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED )
  2035. Flags |= CREATE_PRINTER_SHARED;
  2036. CreateQueueWindow( hwndClient, pQueue,
  2037. pPrinter->Status,
  2038. WindowType,
  2039. Flags );
  2040. }
  2041. }
  2042. }
  2043. FreeSplMem( pPrinter );
  2044. }
  2045. ClosePrinter( hPrinter );
  2046. hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2047. if( hwndActive )
  2048. pInfo = GETMDIWIN( hwndActive );
  2049. if( pInfo )
  2050. {
  2051. ENTER_PROTECTED_DATA( pInfo );
  2052. UpdateDefaultList();
  2053. UpdateStatus( (HWND)TRUE );
  2054. LEAVE_PROTECTED_DATA( pInfo );
  2055. }
  2056. if( hwndActive )
  2057. EnableCheckTBButtons(hwndActive);
  2058. }
  2059. SetCursor( hcursorArrow );
  2060. return 0;
  2061. }
  2062. /*
  2063. *
  2064. */
  2065. LONG FrameCommandCreatePrinter(HWND hWnd)
  2066. {
  2067. PQUEUE pNewQueue;
  2068. HWND hwndChild;
  2069. PMDIWIN_INFO pMDIWinInfo;
  2070. PRT_PROP_DLG_DATA PrtPropDlgData;
  2071. LPPRINTER_INFO_2 pPrinter = NULL;
  2072. DWORD cbPrinter = 0;
  2073. BOOL Error = FALSE;
  2074. BOOL Remote = FALSE;
  2075. /* Create a new window for this Print Queue and get Printer
  2076. * Properties.
  2077. */
  2078. if (!(pNewQueue = AllocQueue(TEXT(""))))
  2079. return 0;
  2080. hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2081. /* If the active window is iconic, don't worry whether it's a Server Viewer,
  2082. * we'll assume that the user wants to create the printer locally:
  2083. */
  2084. if( hwndChild && !IsIconic( hwndChild ) )
  2085. pMDIWinInfo = GETMDIWIN( hwndChild );
  2086. else
  2087. pMDIWinInfo = NULL;
  2088. ZERO_OUT( &PrtPropDlgData );
  2089. /* If this is a Server Viewer, set up the server name field.
  2090. * (Otherwise it's NULL.)
  2091. */
  2092. if( pMDIWinInfo && ( pMDIWinInfo->WindowType == MDIWIN_SERVER ) )
  2093. {
  2094. PSERVER_CONTEXT pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
  2095. Remote = TRUE;
  2096. if( pServerContext->pServerName )
  2097. PrtPropDlgData.pServerName = AllocSplStr( pServerContext->pServerName );
  2098. }
  2099. else
  2100. {
  2101. PrtPropDlgData.pServerName = NULL;
  2102. }
  2103. SetCursor( hcursorWait );
  2104. if( EnumGeneric( (PROC)EnumPrintProcessors,
  2105. 1,
  2106. (PBYTE *)&PrtPropDlgData.pPrintProcessors,
  2107. 0,
  2108. &PrtPropDlgData.cbPrintProcessors,
  2109. &PrtPropDlgData.cPrintProcessors,
  2110. PrtPropDlgData.pServerName,
  2111. NULL, /* pEnvironment */
  2112. NULL ) ) /* (ignored) */
  2113. {
  2114. if( DialogBoxParam( hInst, MAKEINTRESOURCE( DLG_PRTPROP ), hWnd,
  2115. (DLGPROC)PrtPropDlg, (DWORD)&PrtPropDlgData ) == IDOK )
  2116. {
  2117. if( !Remote )
  2118. {
  2119. DWORD Flags = 0;
  2120. SetCursor( hcursorWait );
  2121. pNewQueue->pServerName = AllocSplStr(PrtPropDlgData.pServerName);
  2122. pNewQueue->pPrinterName = PrtPropDlgData.pPrinterName;
  2123. pNewQueue->hPrinter = PrtPropDlgData.hPrinter;
  2124. /* Save ourselves the bother of opening the printer again.
  2125. * We must have Admin privilege if we just created it:
  2126. */
  2127. pNewQueue->AccessGranted |= PRINTER_ACCESS_ADMINISTER;
  2128. if( PrtPropDlgData.PrinterShared )
  2129. Flags |= CREATE_PRINTER_SHARED;
  2130. /* From here on, hwndChild is the new window:
  2131. */
  2132. if( !( hwndChild = CreateQueueWindow( hWnd, pNewQueue, 0,
  2133. MDIWIN_LOCALPRINTER,
  2134. Flags ) ) )
  2135. Error = TRUE;
  2136. else
  2137. {
  2138. PrinterAdded = TRUE;
  2139. if( GetGeneric( (PROC)GetPrinter, 2, (PBYTE *)&pPrinter, cbPrinter,
  2140. &cbPrinter, (PVOID)pNewQueue->hPrinter, NULL ) )
  2141. {
  2142. /* Change the icon for shared printers:
  2143. */
  2144. if( pPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED )
  2145. {
  2146. pMDIWinInfo = GETMDIWIN( hwndChild );
  2147. pMDIWinInfo->hicon = hiconShared;
  2148. }
  2149. FreeSplMem( pPrinter );
  2150. }
  2151. }
  2152. }
  2153. else
  2154. FreeQueue( pNewQueue );
  2155. }
  2156. else
  2157. Error = TRUE;
  2158. FreeSplMem( PrtPropDlgData.pPrintProcessors );
  2159. }
  2160. else
  2161. {
  2162. Message( hWnd, MSG_ERROR, IDS_PRINTMANAGER, IDS_NO_PRINT_PROCESSORS );
  2163. Error = TRUE;
  2164. }
  2165. if( Error )
  2166. {
  2167. FreeQueue (pNewQueue);
  2168. return 0;
  2169. }
  2170. if( PrtPropDlgData.pServerName )
  2171. FreeSplStr( PrtPropDlgData.pServerName );
  2172. if( !Remote )
  2173. {
  2174. PrinterProperties(hWnd, pNewQueue->hPrinter);
  2175. }
  2176. UpdateDefaultList();
  2177. SetCursor( hcursorArrow );
  2178. return 0;
  2179. }
  2180. /*
  2181. *
  2182. */
  2183. LONG FrameCommandProperties(HWND hWnd)
  2184. {
  2185. HWND hwndChild;
  2186. PMDIWIN_INFO pMDIWinInfo;
  2187. PRT_PROP_DLG_DATA PrtPropDlgData;
  2188. PQUEUE pQueue;
  2189. PSERVER_CONTEXT pServerContext;
  2190. BOOL OK = FALSE;
  2191. DWORD OldAttributes;
  2192. hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2193. if (!hwndChild)
  2194. return 0;
  2195. pMDIWinInfo = GETMDIWIN( hwndChild );
  2196. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2197. ZERO_OUT( &PrtPropDlgData );
  2198. SetCursor( hcursorWait );
  2199. EnumGeneric( (PROC)EnumPrintProcessors,
  2200. 1,
  2201. (PBYTE *)&PrtPropDlgData.pPrintProcessors,
  2202. 0,
  2203. &PrtPropDlgData.cbPrintProcessors,
  2204. &PrtPropDlgData.cPrintProcessors,
  2205. PrtPropDlgData.pServerName,
  2206. NULL, /* pEnvironment */
  2207. NULL ); /* (ignored) */
  2208. if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
  2209. {
  2210. pQueue = (PQUEUE)pMDIWinInfo->pContext;
  2211. /* Take a copy of the printer info, so that the dialog can scrawl
  2212. * over it without causing any problems.
  2213. * (This doesn't copy the strings and other buffers, only the pointers.)
  2214. */
  2215. if( !( PrtPropDlgData.pPrinter = AllocSplMem( sizeof( PRINTER_INFO_2 ) ) ) )
  2216. return 0;
  2217. memcpy( PrtPropDlgData.pPrinter, pQueue->pPrinter, sizeof( PRINTER_INFO_2 ) );
  2218. PrtPropDlgData.pServerName = pQueue->pServerName;
  2219. PrtPropDlgData.pMDIWinInfo = pQueue->pMDIWinInfo;
  2220. PrtPropDlgData.hPrinter = pQueue->hPrinter;
  2221. PrtPropDlgData.AccessGranted = pQueue->AccessGranted;
  2222. PrtPropDlgData.ServerAccessGranted = LocalPermission;
  2223. OldAttributes = PrtPropDlgData.pPrinter->Attributes;
  2224. OK = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_PRTPROP), hWnd,
  2225. (DLGPROC)PrtPropDlg, (DWORD)&PrtPropDlgData );
  2226. if( PrtPropDlgData.DriverChanged )
  2227. PrinterProperties(hWnd, pQueue->hPrinter);
  2228. /* If this is a local printer, and the shared attribute has changed,
  2229. * change the window's icon:
  2230. */
  2231. if( OK
  2232. &&( pMDIWinInfo->WindowType == MDIWIN_LOCALPRINTER )
  2233. &&( (BOOL)( OldAttributes & PRINTER_ATTRIBUTE_SHARED )
  2234. !=( PrtPropDlgData.PrinterShared ) ) )
  2235. {
  2236. if( PrtPropDlgData.PrinterShared )
  2237. pMDIWinInfo->hicon = hiconShared;
  2238. else
  2239. pMDIWinInfo->hicon = hiconPrinter;
  2240. /* If the printer's MDI window is in iconic state,
  2241. * ensure that it gets repainted with the new icon:
  2242. */
  2243. if( IsIconic( hwndChild ) )
  2244. InvalidateRect( hwndChild, NULL, TRUE );
  2245. }
  2246. }
  2247. else
  2248. {
  2249. pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
  2250. if( ( pServerContext->pSelPrinter )
  2251. &&( OpenPrinterForSpecifiedAccess(
  2252. pServerContext->pSelPrinter->pPrinterName,
  2253. &PrtPropDlgData.hPrinter,
  2254. PRINTER_ACCESS_HIGHEST_PERMITTED,
  2255. &PrtPropDlgData.AccessGranted ) ) )
  2256. {
  2257. PrtPropDlgData.pServerName = pServerContext->pServerName;
  2258. if( !( PrtPropDlgData.pPrinter = AllocSplMem( sizeof( PRINTER_INFO_2 ) ) ) )
  2259. return 0;
  2260. memcpy( PrtPropDlgData.pPrinter, pServerContext->pSelPrinter,
  2261. sizeof( PRINTER_INFO_2 ) );
  2262. PrtPropDlgData.pMDIWinInfo = pServerContext->pMDIWinInfo;
  2263. PrtPropDlgData.ServerAccessGranted = pServerContext->AccessGranted;
  2264. OK = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_PRTPROP), hWnd,
  2265. (DLGPROC)PrtPropDlg, (DWORD)&PrtPropDlgData );
  2266. if( OK )
  2267. {
  2268. if( PrtPropDlgData.DriverChanged )
  2269. {
  2270. PrinterProperties(hWnd, PrtPropDlgData.hPrinter);
  2271. }
  2272. }
  2273. ClosePrinter( PrtPropDlgData.hPrinter );
  2274. }
  2275. else
  2276. {
  2277. ReportFailure( hWnd, 0, IDS_COULDNOTOPENPRINTER );
  2278. }
  2279. }
  2280. if( OK )
  2281. FreeSplStr( PrtPropDlgData.pPrinterName );
  2282. FreeSplMem( PrtPropDlgData.pPrinter );
  2283. if (PrtPropDlgData.pPrintProcessors)
  2284. FreeSplMem( PrtPropDlgData.pPrintProcessors );
  2285. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  2286. return 0;
  2287. }
  2288. /*
  2289. *
  2290. */
  2291. LONG
  2292. FrameCommandDeletePrinter(
  2293. HWND hWnd)
  2294. {
  2295. HWND hwndMDIActive;
  2296. DBG_UNREFERENCED_PARAMETER(hWnd);
  2297. hwndMDIActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2298. if (!hwndMDIActive)
  2299. return 0;
  2300. return FrameCommandDeletePrinterHelper(hWnd, hwndMDIActive, TRUE);
  2301. }
  2302. LONG
  2303. FrameCommandDeletePrinterHelper(
  2304. HWND hWnd,
  2305. HWND hwndMDI,
  2306. BOOL bConfirm)
  2307. {
  2308. BOOL OK = FALSE;
  2309. PVOID pContext;
  2310. PMDIWIN_INFO pMDIWinInfo = GETMDIWIN( hwndMDI );
  2311. if (!pMDIWinInfo)
  2312. return 0;
  2313. if (pMDIWinInfo->Status & PRINTER_STATUS_LOADING) {
  2314. Message( hWnd, MSG_INFORMATION, IDS_PRINTMANAGER, IDS_PRINTER_NOT_LOADED);
  2315. return 0;
  2316. }
  2317. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2318. pContext = pMDIWinInfo->pContext;
  2319. switch( pMDIWinInfo->WindowType )
  2320. {
  2321. case MDIWIN_LOCALPRINTER:
  2322. OK = DeleteLocalPrinter(hWnd, hwndMDI, (PQUEUE)pContext, bConfirm);
  2323. break;
  2324. case MDIWIN_SERVER:
  2325. OK = DeleteRemotePrinter(hWnd, (PSERVER_CONTEXT)pContext, bConfirm);
  2326. break;
  2327. case MDIWIN_NETWORKPRINTER:
  2328. case MDIWIN_LOCALNETWORKPRINTER:
  2329. OK = DeleteConnection(hWnd, hwndMDI, (PQUEUE)pContext, bConfirm);
  2330. break;
  2331. }
  2332. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  2333. if( OK )
  2334. {
  2335. UpdateDefaultList();
  2336. /* If this was the last printer, we need to update the toolbar buttons:
  2337. */
  2338. if(!SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L))
  2339. {
  2340. EnableCheckTBButtons(NULL);
  2341. UpdateStatus(NULL);
  2342. }
  2343. else
  2344. {
  2345. hwndMDI = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2346. pMDIWinInfo = GETMDIWIN( hwndMDI );
  2347. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2348. UpdateStatus(hwndMDI);
  2349. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  2350. }
  2351. }
  2352. else
  2353. {
  2354. ReportFailure( hWnd,
  2355. IDS_INSUFFPRIV_DELETEPRINTER,
  2356. IDS_COULDNOTDELETEPRINTER );
  2357. }
  2358. return 0;
  2359. }
  2360. /*
  2361. *
  2362. */
  2363. BOOL DeleteLocalPrinter(HWND hwnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm)
  2364. {
  2365. LPTSTR pPrinterName;
  2366. HANDLE hPrinter;
  2367. BOOL OK = TRUE;
  2368. pPrinterName = pQueue->pPrinterName;
  2369. hPrinter = pQueue->hPrinter;
  2370. /* Put up fairly innocuous confirmation message:
  2371. */
  2372. if( !bConfirm || (Message( hwnd, MSG_YESNO, IDS_PRINTMANAGER, IDS_CONFIRMDELETE,
  2373. pPrinterName ) == IDYES) )
  2374. {
  2375. OK = DeletePrinter (hPrinter);
  2376. if( OK )
  2377. {
  2378. DBG_IN_PROTECTED_DATA( pQueue->pMDIWinInfo );
  2379. KillMDIWinInfo(pQueue->pMDIWinInfo);
  2380. if (SendMessage(hwndMDI, WM_QUERYENDSESSION, 0, 0L))
  2381. SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndMDI, 0L);
  2382. DBGMSG( DBG_TRACE, ( "Window destroyed\n" ) );
  2383. }
  2384. }
  2385. return OK;
  2386. }
  2387. /*
  2388. *
  2389. */
  2390. BOOL
  2391. DeleteRemotePrinter(
  2392. HWND hwnd,
  2393. PSERVER_CONTEXT pServerContext,
  2394. BOOL bConfirm)
  2395. {
  2396. LPTSTR pPrinterName;
  2397. LPTSTR pServerName;
  2398. HANDLE hPrinter;
  2399. HWND hwndPrinter = NULL;
  2400. BOOL OK = TRUE;
  2401. pServerName = pServerContext->pServerName;
  2402. pPrinterName = pServerContext->pSelPrinter->pPrinterName;
  2403. /* Get a handle to the printer:
  2404. */
  2405. if( OpenPrinterForSpecifiedAccess( pPrinterName, &hPrinter,
  2406. PRINTER_ALL_ACCESS, NULL ) )
  2407. {
  2408. /* Put up scary message up to make sure they're sure they're sure:
  2409. */
  2410. if( !bConfirm || (Message( hwnd, MSG_YESNO | MB_DEFBUTTON2, IDS_PRINTMANAGER,
  2411. IDS_CONFIRMDELETEREMOTE,
  2412. pServerName, pPrinterName ) == IDYES) )
  2413. {
  2414. /* Do it:
  2415. */
  2416. if( OK = DeletePrinter (hPrinter))
  2417. {
  2418. PMDIWIN_INFO pMDIWinInfo = GETMDIWIN( hwndPrinter );
  2419. /* Now see if we have any connections to this printer:
  2420. */
  2421. hwndPrinter = FindPrinterWindow( pPrinterName );
  2422. if( hwndPrinter )
  2423. {
  2424. if( pMDIWinInfo )
  2425. {
  2426. DBG_IN_PROTECTED_DATA( pMDIWinInfo );
  2427. KillMDIWinInfo(pMDIWinInfo);
  2428. }
  2429. else
  2430. {
  2431. DBGMSG( DBG_WARNING, ( "No MDIWinInfo in DeleteRemotePrinter\n" ) );
  2432. }
  2433. /* Blow away the MDI window:
  2434. */
  2435. if (SendMessage(hwndPrinter, WM_QUERYENDSESSION, 0, 0L))
  2436. SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndPrinter, 0L);
  2437. /* Get rid of the connection:
  2438. */
  2439. DeletePrinterConnection( pPrinterName );
  2440. }
  2441. }
  2442. }
  2443. //
  2444. // Close it!
  2445. //
  2446. ClosePrinter(hPrinter);
  2447. }
  2448. return OK;
  2449. }
  2450. /*
  2451. *
  2452. */
  2453. BOOL DeleteConnection(HWND hWnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm)
  2454. {
  2455. LPTSTR pPrinterName;
  2456. BOOL OK;
  2457. DBG_UNREFERENCED_PARAMETER(hWnd);
  2458. pPrinterName = pQueue->pPrinterName;
  2459. /* Put up fairly innocuous confirmation message:
  2460. */
  2461. if( !bConfirm || (Message( hWnd, MSG_YESNO, IDS_PRINTMANAGER, IDS_CONFIRMDELETECONNECTION,
  2462. pPrinterName ) == IDYES) )
  2463. {
  2464. /* This is a special case of a local printer masquerading
  2465. * as a network printer.
  2466. */
  2467. if( pQueue->pMDIWinInfo->WindowType == MDIWIN_LOCALNETWORKPRINTER ) {
  2468. OK = DeletePrinter( pQueue->hPrinter );
  2469. if (OK)
  2470. {
  2471. if (pQueue->pPrinter && pQueue->pPrinter->pPortName)
  2472. {
  2473. //
  2474. // ignore errors from below
  2475. //
  2476. (void)WNetCancelConnection(pQueue->pPrinter->pPortName,
  2477. TRUE) ;
  2478. (void)RemoveFromReconnectList(pQueue->pPrinter->pPortName) ;
  2479. }
  2480. }
  2481. } else
  2482. OK = DeletePrinterConnection( pPrinterName );
  2483. if( OK )
  2484. {
  2485. DBG_IN_PROTECTED_DATA( pQueue->pMDIWinInfo );
  2486. KillMDIWinInfo(pQueue->pMDIWinInfo);
  2487. if (SendMessage(hwndMDI, WM_QUERYENDSESSION, 0, 0L))
  2488. SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndMDI, 0L);
  2489. return TRUE;
  2490. }
  2491. else
  2492. return FALSE;
  2493. }
  2494. }
  2495. /* FindPrinterWindow
  2496. *
  2497. * Cycles through the MDI child windows until it finds a printer window
  2498. * whose name matches that supplied.
  2499. *
  2500. * andrewbe - April 1992
  2501. */
  2502. HWND FindPrinterWindow( LPTSTR pPrinterName )
  2503. {
  2504. HWND hwndMDI;
  2505. BOOL Found;
  2506. PMDIWIN_INFO pMDIWinInfo;
  2507. for( hwndMDI = GetWindow( hwndClient, GW_CHILD ), Found = FALSE;
  2508. hwndMDI && !Found;
  2509. hwndMDI = Found ? hwndMDI : GetWindow( hwndMDI, GW_HWNDNEXT ) )
  2510. {
  2511. pMDIWinInfo = GETMDIWIN( hwndMDI );
  2512. if( pMDIWinInfo && ( pMDIWinInfo->WindowType != MDIWIN_SERVER ) )
  2513. if( !_tcscmp( ( (PQUEUE)pMDIWinInfo->pContext )->pPrinterName, pPrinterName ) )
  2514. Found = TRUE;
  2515. }
  2516. return (Found ? hwndMDI : NULL);
  2517. }
  2518. /*
  2519. *
  2520. */
  2521. LONG
  2522. FrameCommandPrinterPauseResume(
  2523. HWND hWnd,
  2524. BOOL bPause)
  2525. {
  2526. HWND hwndChild;
  2527. PMDIWIN_INFO pMDIWinInfo;
  2528. PQUEUE pQueue;
  2529. PSERVER_CONTEXT pServerContext;
  2530. PPRINTER_INFO_2 pPrinter = NULL;
  2531. HANDLE hPrinter = NULL;
  2532. BOOL ErrorOccurred = FALSE;
  2533. DBG_UNREFERENCED_PARAMETER(hWnd);
  2534. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2535. if (!hwndChild)
  2536. return 0;
  2537. pMDIWinInfo = GETMDIWIN( hwndChild );
  2538. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2539. if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
  2540. {
  2541. pQueue = (PQUEUE)pMDIWinInfo->pContext;
  2542. hPrinter = pQueue->hPrinter;
  2543. pPrinter = pQueue->pPrinter;
  2544. }
  2545. else
  2546. {
  2547. pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
  2548. pPrinter = pServerContext->pSelPrinter;
  2549. if( pPrinter )
  2550. OpenPrinterForSpecifiedAccess( pPrinter->pPrinterName, &hPrinter,
  2551. PRINTER_ALL_ACCESS, NULL );
  2552. }
  2553. if( pPrinter && hPrinter )
  2554. {
  2555. if(!SetPrinter(hPrinter,
  2556. 0,
  2557. NULL,
  2558. bPause ?
  2559. PRINTER_CONTROL_PAUSE :
  2560. PRINTER_CONTROL_RESUME))
  2561. {
  2562. ErrorOccurred = TRUE;
  2563. CheckTBButton(bPause ?
  2564. IDM_PRINTER_RESUME :
  2565. IDM_PRINTER_PAUSE);
  2566. if( bPause )
  2567. ReportFailure( hWnd,
  2568. IDS_INSUFFPRIV_PAUSEPRINTER,
  2569. IDS_COULDNOTPAUSEPRINTER );
  2570. else
  2571. ReportFailure( hWnd,
  2572. IDS_INSUFFPRIV_RESUMEPRINTING,
  2573. IDS_COULDNOTRESUMEPRINTING );
  2574. }
  2575. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  2576. {
  2577. ClosePrinter( hPrinter );
  2578. }
  2579. // /* For Printer windows, add or remove " - Paused" from the titlebar:
  2580. // */
  2581. // else if( !ErrorOccurred )
  2582. // {
  2583. // SetPrinterTitle( hwndChild, pQueue->pPrinterName,
  2584. // ( bPause
  2585. // ? PRINTER_STATUS_PAUSED : 0 ) );
  2586. // }
  2587. // Force a refresh of the queue window until spooler sends messages
  2588. // back to PrintMan
  2589. if( !ErrorOccurred )
  2590. CheckTBButton(bPause ?
  2591. IDM_PRINTER_PAUSE :
  2592. IDM_PRINTER_RESUME);
  2593. // UpdateStatus((HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L));
  2594. }
  2595. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  2596. return 0;
  2597. }
  2598. /*
  2599. *
  2600. */
  2601. BOOL SetPrinterTitle( HWND hwnd, PTCHAR pPrinterName, DWORD Status )
  2602. {
  2603. TCHAR Title[80];
  2604. TCHAR StatusString[40];
  2605. PTCHAR pTitle;
  2606. if( Status )
  2607. {
  2608. GetPrinterStatusString( Status, StatusString );
  2609. _stprintf( Title, szTitleFormat, pPrinterName, StatusString );
  2610. pTitle = Title;
  2611. }
  2612. else
  2613. pTitle = pPrinterName;
  2614. return SetWindowText( hwnd, pTitle );
  2615. }
  2616. /* SetMDITitle
  2617. *
  2618. * Sets the title, appending status information where appropriate.
  2619. *
  2620. */
  2621. BOOL SetMDITitle( HWND hwnd, PMDIWIN_INFO pInfo )
  2622. {
  2623. TCHAR Title[80];
  2624. TCHAR StatusString[40];
  2625. if( pInfo->WindowType != MDIWIN_SERVER )
  2626. {
  2627. PQUEUE pPrinterContext = pInfo->pContext;
  2628. LPPRINTER_INFO_2 pPrinter;
  2629. if( pPrinter = pPrinterContext->pPrinter )
  2630. {
  2631. if( !pPrinter->pPrinterName )
  2632. {
  2633. /* This should not happen!!
  2634. * (It did.)
  2635. */
  2636. DBGMSG( DBG_WARNING, ( "SetMDITitle for %ws called with NULL pPrinter->pPrinterName\n",
  2637. pPrinterContext->pPrinterName ) );
  2638. return FALSE;
  2639. }
  2640. /* Check whether the printer name has changed,
  2641. * and, if so, update it:
  2642. */
  2643. if( _tcscmp( pPrinterContext->pPrinterName,
  2644. pPrinter->pPrinterName ) )
  2645. {
  2646. //
  2647. // We need to remove the old connection for remote cases
  2648. // (true connections only).
  2649. //
  2650. // It should do a rename, since at some later time we
  2651. // may want to store info like "created at 10:00."
  2652. //
  2653. //
  2654. if (pInfo->WindowType == MDIWIN_NETWORKPRINTER) {
  2655. DeletePrinterConnection(pPrinterContext->pPrinterName);
  2656. AddPrinterConnection(pPrinter->pPrinterName);
  2657. }
  2658. ReallocSplStr( &pPrinterContext->pPrinterName,
  2659. pPrinter->pPrinterName );
  2660. }
  2661. /* There is some information for this printer:
  2662. */
  2663. if( pPrinter->Status )
  2664. {
  2665. GetPrinterStatusString( pPrinter->Status, StatusString );
  2666. _stprintf( Title, szTitleFormat, pPrinterContext->pPrinterName,
  2667. StatusString );
  2668. }
  2669. else
  2670. {
  2671. _tcscpy( Title, pPrinter->pPrinterName );
  2672. }
  2673. }
  2674. else
  2675. {
  2676. if( pPrinterContext->Error == ERROR_ACCESS_DENIED )
  2677. GetPrinterStatusString( PRINTER_STATUS_ACCESS_DENIED, StatusString );
  2678. else
  2679. GetPrinterStatusString( PRINTER_STATUS_UNKNOWN, StatusString );
  2680. _stprintf( Title, szTitleFormat, pPrinterContext->pPrinterName,
  2681. StatusString );
  2682. }
  2683. }
  2684. else
  2685. {
  2686. PSERVER_CONTEXT pServerContext = pInfo->pContext;
  2687. LPTSTR pServerViewerTitle;
  2688. TCHAR TempTitle[80];
  2689. /* Get "Server: %s":
  2690. */
  2691. pServerViewerTitle = GetString( IDS_SERVERVIEWERTITLE );
  2692. if( pServerContext->Error )
  2693. {
  2694. _stprintf( TempTitle, pServerViewerTitle, pServerContext->pServerName );
  2695. GetPrinterStatusString( PRINTER_STATUS_UNKNOWN, StatusString );
  2696. _stprintf( Title, szTitleFormat, TempTitle,
  2697. StatusString );
  2698. }
  2699. else
  2700. {
  2701. _stprintf( Title, pServerViewerTitle, pServerContext->pServerName );
  2702. }
  2703. FreeSplStr( pServerViewerTitle );
  2704. }
  2705. return SetWindowText( hwnd, Title );
  2706. }
  2707. /*
  2708. *
  2709. */
  2710. LONG FrameCommandPurgePrinter(HWND hWnd)
  2711. {
  2712. HWND hwndChild;
  2713. PMDIWIN_INFO pMDIWinInfo;
  2714. PQUEUE pQueue;
  2715. // Delete all the documents in the active window
  2716. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2717. if (!hwndChild)
  2718. return 0;
  2719. pMDIWinInfo = GETMDIWIN( hwndChild );
  2720. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  2721. return 0;
  2722. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2723. pQueue = GETQUEUE( hwndChild );
  2724. if( Message( hWnd, MSG_CONFIRMATION, IDS_PRINTMANAGER,
  2725. IDS_DELETEALLPRINTJOBS_S, pQueue->pPrinterName ) == IDOK )
  2726. {
  2727. if( !SetPrinter(pQueue->hPrinter, 0, NULL, PRINTER_CONTROL_PURGE))
  2728. {
  2729. ReportFailure( hWnd,
  2730. IDS_INSUFFPRIV_PURGEPRINTER,
  2731. IDS_COULDNOTPURGEPRINTER );
  2732. }
  2733. else
  2734. {
  2735. EnableCheckTBButtons(hwndChild);
  2736. UpdateStatus(hwndChild);
  2737. }
  2738. }
  2739. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  2740. return 0;
  2741. }
  2742. /*
  2743. *
  2744. */
  2745. LONG FrameCommandForms(HWND hWnd)
  2746. {
  2747. HWND hwndChild;
  2748. PMDIWIN_INFO pMDIWinInfo;
  2749. PQUEUE pQueue;
  2750. PSERVER_CONTEXT pServerContext;
  2751. PPRINTER_INFO_2 pPrinter;
  2752. FORMS_DLG_DATA FormsDlgData;
  2753. PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL,
  2754. SERVER_ALL_ACCESS };
  2755. HANDLE hServer = NULL;
  2756. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2757. if (!hwndChild)
  2758. return 0;
  2759. pMDIWinInfo = GETMDIWIN( hwndChild );
  2760. ZERO_OUT( &FormsDlgData );
  2761. if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
  2762. {
  2763. pQueue = (PQUEUE)pMDIWinInfo->pContext;
  2764. FormsDlgData.pServerName = NULL;
  2765. FormsDlgData.hPrinter = pQueue->hPrinter;
  2766. if( pQueue->pServerName )
  2767. {
  2768. if (OpenPrinter(pQueue->pServerName,
  2769. &hServer,
  2770. &PrinterDefaults)) {
  2771. FormsDlgData.AccessGranted = SERVER_ACCESS_ADMINISTER;
  2772. } else {
  2773. FormsDlgData.AccessGranted = 0;
  2774. }
  2775. }
  2776. else
  2777. FormsDlgData.AccessGranted = LocalPermission;
  2778. }
  2779. else
  2780. {
  2781. pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
  2782. pPrinter = pServerContext->pSelPrinter;
  2783. if( pPrinter )
  2784. OpenPrinterForSpecifiedAccess( pPrinter->pPrinterName,
  2785. &FormsDlgData.hPrinter,
  2786. PRINTER_READ,
  2787. NULL );
  2788. FormsDlgData.pServerName = pServerContext->pServerName;
  2789. if( OpenPrinter( pServerContext->pServerName, &hServer,
  2790. &PrinterDefaults ) )
  2791. {
  2792. FormsDlgData.AccessGranted = SERVER_ACCESS_ADMINISTER;
  2793. }
  2794. }
  2795. if( FormsDlgData.hPrinter )
  2796. {
  2797. SetCursor( hcursorWait );
  2798. DialogBoxParam( hInst, MAKEINTRESOURCE( DLG_FORMS ), hWnd,
  2799. (DLGPROC)FormsDlg, (DWORD)&FormsDlgData );
  2800. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  2801. {
  2802. ClosePrinter( FormsDlgData.hPrinter );
  2803. }
  2804. if( hServer )
  2805. {
  2806. ClosePrinter( hServer );
  2807. }
  2808. }
  2809. return 0;
  2810. }
  2811. /* Invoke a network browse dialog to set the focus on a
  2812. * particular computer
  2813. */
  2814. LONG FrameCommandServerViewer(HWND hwnd)
  2815. {
  2816. HANDLE hLibrary;
  2817. LPFNI_SYSTEMFOCUSDIALOG lpfnI_SFD;
  2818. WCHAR ServerName[UNCLEN+1];
  2819. BOOL fOK;
  2820. DWORD Error;
  2821. HWND hwndActive;
  2822. PMDIWIN_INFO pMDIWinInfo;
  2823. SetCursor( hcursorWait );
  2824. lpfnI_SFD = (LPFNI_SYSTEMFOCUSDIALOG)LoadLibraryGetProcAddress(
  2825. hwnd, szNtLanMan, szI_SystemFocusDialog, &hLibrary);
  2826. if(lpfnI_SFD)
  2827. {
  2828. Error = (*lpfnI_SFD)(hwnd,
  2829. FOCUSDLG_SERVERS_ONLY | FOCUSDLG_BROWSE_ALL_DOMAINS,
  2830. (LPWSTR)ServerName,
  2831. sizeof(ServerName)/sizeof(WCHAR), &fOK, szLPrintManHlp,
  2832. ID_HELP_SERVERVIEWER );
  2833. SetCursor( hcursorWait );
  2834. if( Error == NO_ERROR )
  2835. {
  2836. if( fOK )
  2837. {
  2838. PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL,
  2839. SERVER_ALL_ACCESS };
  2840. HANDLE hServer = NULL;
  2841. /* Convert the string we received from NETUI to ANSI:
  2842. */
  2843. wsprintf( ServerName, TEXT("%ls"), ServerName );
  2844. //
  2845. // Attempt to open the server. Trap the ERROR_ACCESS_DENIED
  2846. // error so that we can open servers that exist but
  2847. // we don't have auto-refresh access to.
  2848. //
  2849. if( !OpenPrinter( ServerName, &hServer, &PrinterDefaults ) )
  2850. {
  2851. LPTSTR pErrorString;
  2852. DWORD dwError;
  2853. dwError = GetLastError();
  2854. //
  2855. // Special case this error code into a success
  2856. // case, with hServer == -1 to indicate a failed
  2857. // OpenPrinter.
  2858. //
  2859. if (dwError == ERROR_ACCESS_DENIED)
  2860. {
  2861. hServer = (HANDLE)-1;
  2862. goto CreateServer;
  2863. }
  2864. pErrorString = GetErrorString( GetLastError( ) );
  2865. Message( hwnd, MSG_ERROR, IDS_PRINTMANAGER,
  2866. IDS_COULDNOTGETSERVERINFO, ServerName,
  2867. pErrorString );
  2868. FreeSplStr( pErrorString );
  2869. }
  2870. else
  2871. {
  2872. CreateServer:
  2873. CreateServerWindow( hwnd, ServerName, hServer );
  2874. }
  2875. }
  2876. }
  2877. FreeLibrary(hLibrary);
  2878. }
  2879. hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2880. if( hwndActive )
  2881. {
  2882. pMDIWinInfo = GETMDIWIN( hwndActive );
  2883. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2884. UpdateStatus(hwndActive);
  2885. EnableCheckTBButtons(hwndActive);
  2886. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  2887. }
  2888. SetCursor( hcursorArrow );
  2889. return 0;
  2890. }
  2891. /*
  2892. *
  2893. */
  2894. #ifdef LATER
  2895. LONG FrameCommandChangePrinter(HWND hWnd)
  2896. {
  2897. HWND hwndChild;
  2898. PQUEUE pQueue;
  2899. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2900. if (!hwndChild)
  2901. return 0;
  2902. pQueue = GETQUEUE( hwndChild );
  2903. if (DialogBoxParam(hInst, TEXT("PRINTER"), hWnd, (DLGPROC)PrinterDlg,
  2904. (DWORD)pQueue) == IDOK)
  2905. {
  2906. if (pQueue->RedoPrinterProperties)
  2907. {
  2908. PrinterProperties(hWnd, pQueue->hPrinter);
  2909. pQueue->RedoPrinterProperties = FALSE;
  2910. }
  2911. }
  2912. return 0;
  2913. }
  2914. #endif /* LATER */
  2915. /*
  2916. *
  2917. */
  2918. LONG FrameCommandRemoveDoc(HWND hWnd)
  2919. {
  2920. HWND hwndChild;
  2921. PQUEUE pQueue;
  2922. // Delete the selected document in the active window
  2923. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2924. if (!hwndChild)
  2925. return 0;
  2926. if( ( GETMDIWIN( hwndChild ) )->WindowType == MDIWIN_SERVER )
  2927. return 0;
  2928. pQueue = GETQUEUE( hwndChild );
  2929. if( DeleteQJ(hwndChild, pQueue) != 0 )
  2930. {
  2931. ReportFailure( hWnd,
  2932. IDS_INSUFFPRIV_DELETEDOCUMENT,
  2933. IDS_COULDNOTREMOVEDOCUMENT );
  2934. }
  2935. // Force a refresh of the queue window until spooler sends messages
  2936. // back to PrintMan
  2937. EnableCheckTBButtons(hwndChild);
  2938. // UpdateStatus((HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L));
  2939. return 0;
  2940. }
  2941. /*
  2942. *
  2943. */
  2944. LONG FrameCommandDocDetails(HWND hWnd)
  2945. {
  2946. HWND hwndChild;
  2947. PMDIWIN_INFO pMDIWinInfo;
  2948. PQUEUE pQueue;
  2949. // Invoke the document details dialog for selected doc in active window
  2950. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2951. if (!hwndChild)
  2952. return 0;
  2953. pMDIWinInfo = GETMDIWIN( hwndChild );
  2954. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  2955. return 0;
  2956. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2957. pQueue = GETQUEUE( hwndChild );
  2958. if (pQueue->pSelJob == NULL){
  2959. goto Done;
  2960. }
  2961. SetCursor( hcursorWait );
  2962. DialogBoxParam (hInst, MAKEINTRESOURCE(DLG_DOCTAILS), hWnd,
  2963. (DLGPROC)DocDetailsDlg, (DWORD)pQueue);
  2964. SetCursor( hcursorArrow );
  2965. Done:
  2966. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  2967. return 0;
  2968. }
  2969. /*
  2970. *
  2971. */
  2972. LONG FrameCommandDocumentPauseResume(HWND hWnd, WORD PauseResume)
  2973. {
  2974. HWND hwndChild;
  2975. PMDIWIN_INFO pMDIWinInfo;
  2976. PQUEUE pQueue;
  2977. DBG_UNREFERENCED_PARAMETER(hWnd);
  2978. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  2979. if (!hwndChild)
  2980. return 0;
  2981. pMDIWinInfo = GETMDIWIN( hwndChild );
  2982. if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
  2983. {
  2984. ENTER_PROTECTED_DATA( pMDIWinInfo );
  2985. pQueue = (PQUEUE)pMDIWinInfo->pContext;
  2986. if( !pQueue->pSelJob )
  2987. {
  2988. /* This shouldn't happen, but did once!
  2989. */
  2990. DBGMSG( DBG_WARNING, ( "FrameCommandDocumentPauseResume called with no job selected" ) );
  2991. }
  2992. else if (!SetJob(pQueue->hPrinter,
  2993. pQueue->pSelJob->JobId,
  2994. 0, NULL,
  2995. ( ( pQueue->pSelJob->Status & JOB_STATUS_PAUSED )
  2996. ? JOB_CONTROL_RESUME
  2997. : JOB_CONTROL_PAUSE ) ) )
  2998. {
  2999. CheckTBButton( ( PauseResume == IDM_DOCUMENT_PAUSE )
  3000. ? IDM_DOCUMENT_RESUME
  3001. : IDM_DOCUMENT_PAUSE );
  3002. if( PauseResume == IDM_DOCUMENT_PAUSE )
  3003. ReportFailure( hWnd,
  3004. IDS_INSUFFPRIV_PAUSEDOCUMENT,
  3005. IDS_COULDNOTPAUSEDOCUMENT );
  3006. else
  3007. ReportFailure( hWnd,
  3008. IDS_INSUFFPRIV_RESUMEDOCUMENT,
  3009. IDS_COULDNOTRESUMEDOCUMENT );
  3010. }
  3011. else
  3012. CheckTBButton(PauseResume);
  3013. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  3014. }
  3015. return 0;
  3016. }
  3017. /*
  3018. *
  3019. */
  3020. LONG FrameCommandRestart(HWND hWnd)
  3021. {
  3022. HWND hwndChild;
  3023. PMDIWIN_INFO pMDIWinInfo;
  3024. PQUEUE pQueue;
  3025. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3026. if (!hwndChild)
  3027. return 0;
  3028. pMDIWinInfo = GETMDIWIN( hwndChild );
  3029. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  3030. return 0;
  3031. pQueue = GETQUEUE( hwndChild );
  3032. if( pQueue->SelJobId )
  3033. {
  3034. ENTER_PROTECTED_DATA( pMDIWinInfo );
  3035. // Cancel the print job
  3036. if( !SetJob( pQueue->hPrinter,
  3037. pQueue->SelJobId,
  3038. 0, NULL,
  3039. JOB_CONTROL_RESTART ) )
  3040. {
  3041. ReportFailure( hWnd,
  3042. IDS_INSUFFPRIV_RESTARTDOCUMENT,
  3043. IDS_COULDNOTRESTARTDOCUMENT );
  3044. }
  3045. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  3046. }
  3047. // Force a refresh of the queue window until spooler sends messages
  3048. // back to PrintMan
  3049. EnableCheckTBButtons(hwndChild);
  3050. return 0;
  3051. }
  3052. /*
  3053. *
  3054. */
  3055. LONG FrameCommandFont(HWND hWnd)
  3056. {
  3057. return 0;
  3058. UNREFERENCED_PARAMETER(hWnd);
  3059. }
  3060. /*
  3061. *
  3062. */
  3063. LONG FrameCommandRefreshRate(HWND hWnd)
  3064. {
  3065. return 0;
  3066. UNREFERENCED_PARAMETER(hWnd);
  3067. }
  3068. /*
  3069. *
  3070. */
  3071. LONG FrameCommandToolbar(HWND hWnd)
  3072. {
  3073. RECT rc;
  3074. bToolBar = !bToolBar;
  3075. ShowWindow( hwndToolbar, bToolBar ? SW_SHOW : SW_HIDE );
  3076. GetClientRect(hwndFrame, &rc);
  3077. SendMessage(hwndFrame, WM_SIZE, SIZENORMAL, MAKELONG(rc.right, rc.bottom));
  3078. InvalidateRect(hwndFrame, NULL, TRUE);
  3079. CheckMenuItem(GetMenu(hWnd), IDM_TOOLBAR,
  3080. MF_BYCOMMAND | (bToolBar ? MF_CHECKED : MF_UNCHECKED));
  3081. return 0;
  3082. }
  3083. /*
  3084. *
  3085. */
  3086. LONG FrameCommandStatusbar(HWND hWnd)
  3087. {
  3088. PMDIWIN_INFO pInfo;
  3089. HWND hwndChild;
  3090. RECT rc;
  3091. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3092. bStatusBar = !bStatusBar;
  3093. ShowWindow( hwndStatus, bStatusBar ? SW_SHOW : SW_HIDE );
  3094. GetClientRect(hwndFrame, &rc);
  3095. SendMessage(hwndFrame, WM_SIZE, SIZENORMAL, MAKELONG(rc.right, rc.bottom));
  3096. if( pInfo = GETMDIWIN( hwndChild ) )
  3097. {
  3098. ENTER_PROTECTED_DATA( pInfo );
  3099. UpdateStatus(hwndChild);
  3100. LEAVE_PROTECTED_DATA( pInfo );
  3101. }
  3102. InvalidateRect(hwndFrame, NULL, TRUE);
  3103. CheckMenuItem(GetMenu(hWnd), IDM_STATUSBAR,
  3104. MF_BYCOMMAND | (bStatusBar ? MF_CHECKED : MF_UNCHECKED));
  3105. return 0;
  3106. }
  3107. /*
  3108. *
  3109. */
  3110. LONG FrameCommandSaveSettings(HWND hWnd)
  3111. {
  3112. bSaveSettings = !bSaveSettings;
  3113. CheckMenuItem(GetMenu(hWnd), IDM_SAVESETTINGS,
  3114. MF_BYCOMMAND | (bSaveSettings ? MF_CHECKED : MF_UNCHECKED));
  3115. return 0;
  3116. }
  3117. /*
  3118. *
  3119. */
  3120. LONG FrameCommandPermissions(HWND hWnd)
  3121. {
  3122. HWND hwndChild;
  3123. PMDIWIN_INFO pInfo;
  3124. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3125. if( hwndChild )
  3126. {
  3127. pInfo = GETMDIWIN( hwndChild );
  3128. if( pInfo->WindowType != MDIWIN_SERVER )
  3129. {
  3130. ENTER_PROTECTED_DATA( pInfo );
  3131. ENTER_PROTECTED_HANDLE( pInfo );
  3132. ResetEvent( pInfo->RefreshSignal );
  3133. CallDiscretionaryAclEditor( hWnd, pInfo->pContext );
  3134. SetEvent( pInfo->RefreshSignal );
  3135. LEAVE_PROTECTED_HANDLE( pInfo );
  3136. LEAVE_PROTECTED_DATA( pInfo );
  3137. }
  3138. }
  3139. return 0;
  3140. }
  3141. /*
  3142. *
  3143. */
  3144. LONG FrameCommandAuditing(HWND hWnd)
  3145. {
  3146. HWND hwndChild;
  3147. PMDIWIN_INFO pInfo;
  3148. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3149. if( hwndChild )
  3150. {
  3151. pInfo = GETMDIWIN( hwndChild );
  3152. if( pInfo->WindowType != MDIWIN_SERVER )
  3153. {
  3154. ENTER_PROTECTED_DATA( pInfo );
  3155. ENTER_PROTECTED_HANDLE( pInfo );
  3156. ResetEvent( pInfo->RefreshSignal );
  3157. CallSystemAclEditor( hWnd, pInfo->pContext );
  3158. SetEvent( pInfo->RefreshSignal );
  3159. LEAVE_PROTECTED_HANDLE( pInfo );
  3160. LEAVE_PROTECTED_DATA( pInfo );
  3161. }
  3162. }
  3163. return 0;
  3164. }
  3165. /*
  3166. *
  3167. */
  3168. LONG FrameCommandOwner(HWND hWnd)
  3169. {
  3170. HWND hwndChild;
  3171. PMDIWIN_INFO pInfo;
  3172. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3173. if( hwndChild )
  3174. {
  3175. pInfo = GETMDIWIN( hwndChild );
  3176. if( pInfo->WindowType != MDIWIN_SERVER )
  3177. {
  3178. ENTER_PROTECTED_DATA( pInfo );
  3179. ENTER_PROTECTED_HANDLE( pInfo );
  3180. ResetEvent( pInfo->RefreshSignal );
  3181. CallTakeOwnershipDialog( hWnd, pInfo->pContext );
  3182. SetEvent( pInfo->RefreshSignal );
  3183. LEAVE_PROTECTED_HANDLE( pInfo );
  3184. LEAVE_PROTECTED_DATA( pInfo );
  3185. }
  3186. }
  3187. return 0;
  3188. }
  3189. /*
  3190. *
  3191. */
  3192. VOID FrameCommandRefresh(HWND hWnd)
  3193. {
  3194. HWND hwndChild;
  3195. PMDIWIN_INFO pMDIWinInfo;
  3196. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3197. if( hwndChild )
  3198. {
  3199. pMDIWinInfo = GETMDIWIN( hwndChild );
  3200. Refresh( hwndChild, pMDIWinInfo, REPAINT_FORCE );
  3201. }
  3202. UNREFERENCED_PARAMETER( hWnd );
  3203. }
  3204. /*
  3205. *
  3206. */
  3207. LONG FrameCommandClose(HWND hWnd)
  3208. {
  3209. HWND hwndChild;
  3210. DBG_UNREFERENCED_PARAMETER(hWnd);
  3211. hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3212. if (!hwndChild)
  3213. return 0;
  3214. if (SendMessage(hwndChild, WM_QUERYENDSESSION, 0, 0L))
  3215. SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM) hwndChild, 0L);
  3216. return 0;
  3217. }
  3218. LONG
  3219. FrameCommandReturn()
  3220. {
  3221. HWND hwndActive;
  3222. hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3223. if (hwndActive && IsIconic(hwndActive)) {
  3224. SendMessage(hwndActive, WM_SYSCOMMAND, SC_RESTORE, 0L);
  3225. } else {
  3226. PMDIWIN_INFO pInfo;
  3227. pInfo = GETMDIWIN(hwndActive);
  3228. if( !pInfo )
  3229. return 0;
  3230. //
  3231. // If there's nothing selected or we're in the middle
  3232. // of a drag operation, don't do anything:
  3233. //
  3234. if( ( pInfo->ObjSelected == NOSELECTION )
  3235. ||( pInfo->DragPosition != NOSELECTION ) )
  3236. {
  3237. }
  3238. else {
  3239. //
  3240. // Do the same as double-click:
  3241. //
  3242. MDICommandObjListDblClk( hwndActive );
  3243. }
  3244. }
  3245. return 0;
  3246. }
  3247. /*
  3248. *
  3249. */
  3250. LONG FrameCommandAbout(HWND hWnd)
  3251. {
  3252. TCHAR Title[RESOURCE_STRING_LENGTH];
  3253. SetCursor( hcursorWait );
  3254. LoadString( hInst, IDS_PRINTMANAGER, Title,
  3255. sizeof Title / sizeof *Title );
  3256. ShellAbout( hWnd, Title, NULL, hiconPrinter );
  3257. SetCursor( hcursorArrow );
  3258. return 0;
  3259. }
  3260. /*
  3261. *
  3262. */
  3263. VOID FrameCommandDefaultPrinter(HWND hwnd, WORD Command)
  3264. {
  3265. switch (Command)
  3266. {
  3267. case CBN_SELCHANGE:
  3268. ToolbarCommandSelChange(FALSE);
  3269. break;
  3270. /* F1 will bring up help on the Default Printer list,
  3271. * if it has the focus:
  3272. */
  3273. case CBN_SETFOCUS:
  3274. WinHelpMenuID = ID_HELP_DEFAULT_PRINTER;
  3275. break;
  3276. case CBN_KILLFOCUS:
  3277. WinHelpMenuID = 0;
  3278. break;
  3279. }
  3280. }
  3281. /* Handle notification codes from the toolbar.
  3282. * Set the status bar help in response to TBN_BEGIN/ENDDRAG.
  3283. */
  3284. VOID FrameCommandToolbarNotify( HWND hwnd, WPARAM wParam, LPARAM lParam )
  3285. {
  3286. MenuHelp( WM_COMMAND, wParam, lParam, GetMenu( hwnd ),
  3287. hInst, hwndStatus, pMenuHelpIDs );
  3288. WinHelpMenuID = (DWORD)LOWORD( wParam );
  3289. }
  3290. /* Cause tab to toggle between the default printer list and the active
  3291. * MDI window, so that the keyboard can be used to select default printer.
  3292. */
  3293. VOID FrameCommandTab(HWND hwnd)
  3294. {
  3295. HWND hwndActiveMDI;
  3296. PMDIWIN_INFO pMDIWinInfo;
  3297. HWND hwndFocus;
  3298. hwndActiveMDI = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3299. if( hwndActiveMDI )
  3300. {
  3301. pMDIWinInfo = GETMDIWIN( hwndActiveMDI );
  3302. hwndFocus = GetFocus( );
  3303. if( hwndFocus == pMDIWinInfo->hwndList )
  3304. SetFocus( hwndPrinterList );
  3305. else
  3306. SetFocus( pMDIWinInfo->hwndList );
  3307. }
  3308. }
  3309. /*
  3310. *
  3311. */
  3312. LONG FrameCommandDefault(HWND hWnd, WPARAM wParam, LONG lParam)
  3313. {
  3314. HWND hwndChild;
  3315. hwndChild =(HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  3316. if (!hwndChild)
  3317. return 0;
  3318. if (IsWindow(hwndChild))
  3319. SendMessage(hwndChild, WM_COMMAND, wParam, lParam);
  3320. // Pass unprocessed WM_COMMAND messages to DefFrameProc
  3321. return DefFrameProc(hWnd, hwndClient, WM_COMMAND, wParam, lParam);
  3322. }
  3323. /*
  3324. *
  3325. */
  3326. VOID FrameSysColorChange( )
  3327. {
  3328. DWORD OldSysColorHighlight;
  3329. DWORD OldSysColorHighlightText;
  3330. DWORD OldSysColorWindow;
  3331. DWORD OldSysColorBtnFace;
  3332. DWORD OldSysColorBtnText;
  3333. DWORD OldSysColorBtnHighlight;
  3334. DWORD OldSysColorBtnShadow;
  3335. OldSysColorHighlight = SysColorHighlight;
  3336. OldSysColorHighlightText = SysColorHighlightText;
  3337. OldSysColorWindow = SysColorWindow;
  3338. OldSysColorBtnFace = SysColorBtnFace;
  3339. OldSysColorBtnText = SysColorBtnText;
  3340. OldSysColorBtnHighlight = SysColorBtnHighlight;
  3341. OldSysColorBtnShadow = SysColorBtnShadow;
  3342. GetSystemColors( );
  3343. /* If the higlight or window colour has changed,
  3344. * we must fix up the bitmaps again.
  3345. * The easiest way to do this is by deleting the old stuff
  3346. * and reload the bitmaps from resources:
  3347. */
  3348. if( ( OldSysColorHighlight != SysColorHighlight )
  3349. ||( OldSysColorWindow != SysColorWindow ) )
  3350. {
  3351. SelectObject( hdcMem, hbmDefault );
  3352. DeleteObject( hbmBitmaps );
  3353. DeleteDC( hdcMem );
  3354. LoadBitmaps( );
  3355. }
  3356. }
  3357. /* RepaintWindow
  3358. *
  3359. * Callback function passed to EnumChildWindows by FrameWinIniChange.
  3360. * It is called on each MDI window in the event that international
  3361. * time formats might have changed.
  3362. * Enumeration continues while this function returns TRUE.
  3363. *
  3364. * Parameters:
  3365. *
  3366. * hwnd - The child window's handle
  3367. *
  3368. * lparam - Application-defined value (unused)
  3369. *
  3370. *
  3371. * Return:
  3372. *
  3373. * The return code from InvalidateRect
  3374. *
  3375. */
  3376. BOOL CALLBACK RepaintWindow( HWND hwnd, LPARAM lparam )
  3377. {
  3378. UNREFERENCED_PARAMETER( lparam );
  3379. /* Repaint only windows with ID == ID_OBJLIST,
  3380. * i.e. the document lists in printer windows
  3381. * and printer lists in server windows:
  3382. */
  3383. if( GetWindowLong( hwnd, GWL_ID ) == ID_OBJLIST )
  3384. return InvalidateRect( hwnd, NULL, TRUE );
  3385. else
  3386. return TRUE;
  3387. }
  3388. /* FrameWinIniChange
  3389. *
  3390. * Called in response to WM_WININICHANGE.
  3391. * If the section that has been changed is "intl", or if we don't know
  3392. * because NULL was passed (frowned upon but permitted),
  3393. * cause the child windows to be repainted so that any time values
  3394. * will be repainted.
  3395. * E.g., if the user has sensibly changed the time format from 12-hour
  3396. * to 24-hour, we want to repaint any times.
  3397. *
  3398. * Parameters:
  3399. *
  3400. * hwnd - The frame window handle
  3401. *
  3402. * pSection - A pointer to string specifying the section in the INI
  3403. * file that has changed. If this is NULL, play it safe,
  3404. * and assume that something might have changed.
  3405. *
  3406. */
  3407. VOID FrameWinIniChange( HWND hwnd, LPTSTR pSection )
  3408. {
  3409. TCHAR Buffer[MAX_PATH];
  3410. PTCHAR pPrinterName;
  3411. INT iNewDefaultPrinter;
  3412. if( ( pSection == NULL )
  3413. ||( _tcsicmp( pSection, szInternational ) == 0 ) )
  3414. {
  3415. InitializeInternationalTimeConstants( );
  3416. EnumChildWindows( hwnd, (WNDENUMPROC)RepaintWindow, (LPARAM)0 );
  3417. }
  3418. /* If an application has changed the windows.device section in
  3419. * WIN.INI, update the default printer:
  3420. */
  3421. if( ( pSection == NULL )
  3422. ||( _tcsicmp( pSection, TEXT("device") ) == 0 ) )
  3423. {
  3424. if( GetProfileString( szWindows, szDevice, TEXT(""), Buffer, sizeof Buffer ) )
  3425. {
  3426. pPrinterName = _tcstok( Buffer, TEXT(",") );
  3427. if( pPrinterName )
  3428. {
  3429. iNewDefaultPrinter = SendMessage( hwndPrinterList,
  3430. CB_FINDSTRINGEXACT,
  3431. (WPARAM)-1,
  3432. (LPARAM)pPrinterName );
  3433. if( iNewDefaultPrinter != CB_ERR )
  3434. {
  3435. if( SendMessage( hwndPrinterList,
  3436. CB_SETCURSEL,
  3437. (WPARAM)iNewDefaultPrinter,
  3438. 0 ) == CB_ERR )
  3439. {
  3440. DBGMSG( DBG_WARNING, ( "Failed to set new default printer\n" ) );
  3441. }
  3442. }
  3443. else
  3444. {
  3445. DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with an unknown Windows Device\n" ) );
  3446. }
  3447. }
  3448. else
  3449. {
  3450. DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with a NULL Windows Device\n" ) );
  3451. }
  3452. }
  3453. else
  3454. {
  3455. DBGMSG( DBG_WARNING, ( "GetProfileString failed: Error %d\n", GetLastError( ) ) );
  3456. }
  3457. }
  3458. }
  3459. /* We get here when the thread monitoring the local server detects that
  3460. * a printer has been added. This may be because we've just added one,
  3461. * however it might also be because someone added one remotely.
  3462. * If we added it, we should have set the global PrinterAdded = TRUE.
  3463. * Otherwise we enumerate the printers and figure out which was new,
  3464. * then create an iconised window for the new printer.
  3465. */
  3466. VOID
  3467. FramePrinterAdded(
  3468. HWND hwnd,
  3469. DWORD dwType)
  3470. {
  3471. PPRINTER_INFO_4 pPrinters = NULL;
  3472. DWORD cbPrinters = 0;
  3473. DWORD cPrinters;
  3474. LPTSTR pServerName = NULL;
  3475. LPTSTR pPrinterName = NULL;
  3476. DWORD i;
  3477. PQUEUE pQueue;
  3478. if( PrinterAdded )
  3479. {
  3480. /* We're expecting this, so forget it:
  3481. */
  3482. PrinterAdded = FALSE;
  3483. return;
  3484. }
  3485. DBGMSG( DBG_TRACE, ( "A printer was added\n" ) );
  3486. if( ENUM_PRINTERS( dwType ?
  3487. PRINTER_ENUM_LOCAL :
  3488. PRINTER_ENUM_CONNECTIONS,
  3489. pServerName,
  3490. 4,
  3491. pPrinters,
  3492. cbPrinters,
  3493. &cbPrinters,
  3494. &cPrinters ) )
  3495. {
  3496. for( i = 0; i < cPrinters; i++ )
  3497. {
  3498. if( !FindPrinterWindow( pPrinters[i].pPrinterName ) )
  3499. {
  3500. DBGMSG( DBG_TRACE, ( "Creating new printer: %s\n",
  3501. pPrinters[i].pPrinterName ) );
  3502. if( pQueue = AllocQueue( pPrinters[i].pPrinterName ) )
  3503. {
  3504. pQueue->Error = OpenThreadObject(pQueue->pPrinterName,
  3505. &pQueue->hPrinter,
  3506. &pQueue->AccessGranted,
  3507. MDIWIN_PRINTER);
  3508. if( !pQueue->Error )
  3509. {
  3510. DWORD Flags = CREATE_PRINTER_ICONIC;
  3511. HWND hwnd;
  3512. if( pPrinters[i].Attributes & PRINTER_ATTRIBUTE_SHARED )
  3513. Flags |= CREATE_PRINTER_SHARED;
  3514. hwnd = CreateQueueWindow( hwnd, pQueue,
  3515. PRINTER_STATUS_LOADING,
  3516. dwType ?
  3517. MDIWIN_LOCALPRINTER :
  3518. MDIWIN_NETWORKPRINTER,
  3519. Flags );
  3520. BringWindowToTop( hwnd );
  3521. FlashWindow( hwnd, FALSE );
  3522. }
  3523. else
  3524. {
  3525. FreeQueue( pQueue );
  3526. }
  3527. }
  3528. }
  3529. }
  3530. FreeSplMem( pPrinters );
  3531. }
  3532. else
  3533. {
  3534. DBGMSG( DBG_WARNING, ( "EnumPrinters failed: Error %d\n", GetLastError( ) ) );
  3535. }
  3536. }
  3537. /* FrameRegNotifyChangeKeyValue
  3538. *
  3539. * This routine will be called via a message posted from the main
  3540. * message dispatch loop when a change is made to the device key
  3541. * of the windows section in the registry WIN.INI mapping.
  3542. * This may be because an application has changed the default printer.
  3543. * We check whether this is the case by querying that value, parsing
  3544. * out the comma following the printer name in the entry, and ensuring
  3545. * that this is the current default printer.
  3546. * Hoping for a WM_WININICHANGE is not very reliable, since some apps
  3547. * (e.g. Lotus Improv) don't appear to broadcast it when they change
  3548. * WIN.INI.
  3549. *
  3550. * Parameters:
  3551. *
  3552. * hwnd - The frame window handle
  3553. *
  3554. * hWindowsKey - An open key to the registry WIN.INI mapping
  3555. *
  3556. *
  3557. * Note there is some redundancy here, since this will also be called
  3558. * if the user selects the default printer from Print Manager.
  3559. * This could be avoided by our setting a flag when we have caused
  3560. * the default printer to change.
  3561. *
  3562. *
  3563. * AndrewBe, 15 June 1993
  3564. *
  3565. */
  3566. VOID FrameRegNotifyChangeKeyValue( HWND hwnd, HKEY hWindowsKey )
  3567. {
  3568. DWORD Status;
  3569. TCHAR Buffer[MAX_PATH];
  3570. PTCHAR pPrinterName;
  3571. INT iNewDefaultPrinter;
  3572. DWORD BufferSize;
  3573. BufferSize = sizeof Buffer*sizeof(TCHAR);
  3574. if( ( Status = RegQueryValueEx( hWindowsKey,
  3575. szDevice,
  3576. REG_OPTION_RESERVED,
  3577. NULL,
  3578. (LPBYTE)Buffer,
  3579. &BufferSize ) ) == NO_ERROR)
  3580. {
  3581. /* Hack out the comma from the buffer,
  3582. * which strtok helpfully does for us:
  3583. */
  3584. pPrinterName = _tcstok( Buffer, TEXT(",") );
  3585. if( pPrinterName )
  3586. {
  3587. iNewDefaultPrinter = SendMessage( hwndPrinterList,
  3588. CB_FINDSTRING,
  3589. (WPARAM)-1,
  3590. (LPARAM)pPrinterName );
  3591. if( iNewDefaultPrinter != CB_ERR )
  3592. {
  3593. if( SendMessage( hwndPrinterList,
  3594. CB_SETCURSEL,
  3595. (WPARAM)iNewDefaultPrinter,
  3596. 0 ) == CB_ERR )
  3597. {
  3598. DBGMSG( DBG_WARNING, ( "Failed to set new default printer\n" ) );
  3599. }
  3600. }
  3601. else
  3602. {
  3603. DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with an unknown Windows Device\n" ) );
  3604. }
  3605. }
  3606. else
  3607. {
  3608. DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with a NULL Windows Device\n" ) );
  3609. }
  3610. }
  3611. else
  3612. {
  3613. DBGMSG( DBG_WARNING, ( "RegQueryValuEx failed: Error %d\n", Status ) );
  3614. }
  3615. }
  3616. /*
  3617. * END OF ROUTINES CALLED BY FrameWndProc
  3618. */
  3619. //////////////////////////////////////////////////////////////////////
  3620. //
  3621. // UpdateStatus
  3622. //
  3623. // Load the status buffers with the appropriate stuff and invalidates
  3624. // the status area causing it to repaint.
  3625. //
  3626. // Updates the three global status strings for the currently active
  3627. // child window.
  3628. //
  3629. // strStatusName
  3630. // strStatusStatus
  3631. // strStatusWaiting
  3632. //
  3633. //////////////////////////////////////////////////////////////////////
  3634. VOID UpdateStatus( HWND hWnd )
  3635. {
  3636. PMDIWIN_INFO pMDIWinInfo;
  3637. PVOID pContext;
  3638. LPPRINTER_INFO_2 pPrinter;
  3639. LPJOB_INFO_2 pJobSelected;
  3640. DWORD JobSelected;
  3641. TCHAR szTemp[128];
  3642. LPTSTR pServerName = NULL; /* Non-null for server windows */
  3643. DWORD Error;
  3644. if (!bStatusBar)
  3645. return;
  3646. /* If hWnd is NULL, clear the status bar,
  3647. * otherwise get the active MDI window:
  3648. */
  3649. if( !hWnd || !(hWnd = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L)))
  3650. {
  3651. *strStatusName = NULLC;
  3652. *strStatusStatus = NULLC;
  3653. *strStatusWaiting = NULLC;
  3654. }
  3655. else
  3656. {
  3657. if( !( pMDIWinInfo = GETMDIWIN( hWnd ) ) ) {
  3658. return;
  3659. }
  3660. ENTER_PROTECTED_DATA(pMDIWinInfo);
  3661. pContext = pMDIWinInfo->pContext;
  3662. if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
  3663. {
  3664. pPrinter = ( (PQUEUE)pContext )->pPrinter;
  3665. pJobSelected = ( (PQUEUE)pContext )->pSelJob;
  3666. JobSelected = pMDIWinInfo->ObjSelected;
  3667. Error = ( (PQUEUE)pContext )->Error;
  3668. }
  3669. else
  3670. {
  3671. pPrinter = ( (PSERVER_CONTEXT)pContext )->pSelPrinter;
  3672. pJobSelected = NULL;
  3673. JobSelected = NOSELECTION;
  3674. Error = ( (PSERVER_CONTEXT)pContext )->Error;
  3675. }
  3676. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  3677. {
  3678. pServerName = ( (PSERVER_CONTEXT)pContext )->pServerName;
  3679. /* No job info for Server Viewer - should we show something?
  3680. */
  3681. if( IsIconic( hWnd ) )
  3682. _tcscpy( strStatusName, pServerName );
  3683. else
  3684. {
  3685. if( pPrinter && pPrinter->pPrinterName )
  3686. _tcscpy( strStatusName, pPrinter->pPrinterName );
  3687. else
  3688. _tcscpy( strStatusName, pServerName );
  3689. }
  3690. }
  3691. else if( pPrinter )
  3692. {
  3693. if( JobSelected != NOSELECTION )
  3694. {
  3695. if( pJobSelected->pDocument && *pJobSelected->pDocument )
  3696. _tcscpy (strStatusName, pJobSelected->pDocument);
  3697. else
  3698. _tcscpy (strStatusName, strUntitled);
  3699. }
  3700. else if( ( (PQUEUE)pContext )->pPrinterName )
  3701. _tcscpy( strStatusName, ( (PQUEUE)pContext )->pPrinterName );
  3702. else
  3703. *strStatusName = NULLC;
  3704. }
  3705. else if( ( (PQUEUE)pContext )->pPrinterName )
  3706. _tcscpy( strStatusName, ( (PQUEUE)pContext )->pPrinterName );
  3707. else
  3708. *strStatusName = NULLC;
  3709. if( pServerName && IsIconic( hWnd ) )
  3710. {
  3711. *strStatusWaiting = NULLC;
  3712. *strStatusStatus = NULLC;
  3713. }
  3714. else if( pPrinter )
  3715. {
  3716. if( ( pPrinter->cJobs == 0 ) || ( JobSelected == NOSELECTION ) )
  3717. {
  3718. GetPrinterStatusString( pPrinter->Status, strStatusStatus );
  3719. LoadString (hInst, IDS_DOCUMENTSQUEUED_D, szTemp,
  3720. sizeof(szTemp) / sizeof(*szTemp));
  3721. wsprintf (strStatusWaiting, szTemp, pPrinter->cJobs);
  3722. }
  3723. else
  3724. {
  3725. if( ( pJobSelected->pStatus ) && ( *pJobSelected->pStatus ) )
  3726. _tcsncpy (strStatusStatus, pJobSelected->pStatus,
  3727. sizeof(strStatusStatus)/sizeof(TCHAR)-1);
  3728. else
  3729. GetJobStatusString( pJobSelected->Status, strStatusStatus );
  3730. LoadString (hInst, IDS_PAGESCOMPLETED_D, szTemp,
  3731. sizeof(szTemp) / sizeof(*szTemp));
  3732. wsprintf (strStatusWaiting, szTemp, pJobSelected->TotalPages );
  3733. }
  3734. }
  3735. else
  3736. {
  3737. if (Error == ERROR_ACCESS_DENIED) {
  3738. GetPrinterStatusString( PRINTER_STATUS_ACCESS_DENIED, strStatusStatus );
  3739. } else {
  3740. GetPrinterStatusString( PRINTER_STATUS_UNKNOWN, strStatusStatus );
  3741. }
  3742. *strStatusWaiting = NULLC;
  3743. }
  3744. LEAVE_PROTECTED_DATA(pMDIWinInfo);
  3745. }
  3746. // force the status area to update
  3747. SendMessage( hwndStatus, SB_SETTEXT, ISF_NAME, (LPARAM)strStatusName );
  3748. SendMessage( hwndStatus, SB_SETTEXT, ISF_STATUS, (LPARAM)strStatusStatus );
  3749. SendMessage( hwndStatus, SB_SETTEXT, ISF_WAITING, (LPARAM)strStatusWaiting );
  3750. }
  3751. BOOL
  3752. InitApplication(
  3753. HANDLE hInstance,
  3754. LPHANDLE lphAccel
  3755. )
  3756. {
  3757. WNDCLASS wc;
  3758. HCURSOR hcurArrow;
  3759. hInst = hInstance;
  3760. hcurArrow = LoadCursor(NULL, IDC_ARROW);
  3761. GetSystemColors( );
  3762. if (!LoadBitmaps())
  3763. return FALSE;
  3764. hiconPrinter = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_PRINTMAN ) );
  3765. hiconServer = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_SERVER ) );
  3766. hiconConnect = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_CONNECT ) );
  3767. hiconShared = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_SHARED ) );
  3768. // Register the main Print Manager frame window class
  3769. wc.style = CS_HREDRAW | CS_VREDRAW;
  3770. wc.lpfnWndProc = FrameWndProc;
  3771. wc.cbClsExtra = 0;
  3772. wc.cbWndExtra = 0;
  3773. wc.hInstance = hInst;
  3774. wc.hIcon = hiconPrinter;
  3775. wc.hCursor = hcurArrow;
  3776. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  3777. wc.lpszMenuName = szMenuClass;
  3778. wc.lpszClassName = szPrintManagerClass;
  3779. if (!RegisterClass(&wc))
  3780. return FALSE;
  3781. // Register the Print Queue child window class
  3782. // You can't close a window of this class
  3783. // except if the corresponding printer is deleted.
  3784. // -------------------------------------------------------------------
  3785. // There is no icon defined for this class, since we want to change it
  3786. // based on whether the printer is shared or not.
  3787. // There is a user feature (for Win31 compatibility, apparently)
  3788. // which means that we can't do this by specifying an icon here
  3789. // then responding to the WM_PAINTICON message by calling DrawIcon,
  3790. // since somewhere in the guts of user it gets a zero-sized update
  3791. // region. So instead we don't define a default class icon,
  3792. // but put an icon handle in the MDI window's instance data,
  3793. // which we then use when we get a WM_PAINT message.
  3794. wc.style = CS_HREDRAW | CS_VREDRAW;
  3795. wc.lpfnWndProc = MDIWndProc;
  3796. wc.cbClsExtra = 0;
  3797. wc.cbWndExtra = sizeof(LONG); // GWL_PMDIWIN
  3798. wc.hInstance = hInst;
  3799. wc.hIcon = NULL; // No icon -- put handle in MDIWinInfo
  3800. wc.hCursor = hcurArrow;
  3801. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  3802. wc.lpszMenuName = NULL;
  3803. wc.lpszClassName = szChildClass;
  3804. if (!RegisterClass(&wc))
  3805. return FALSE;
  3806. *lphAccel = LoadAccelerators(hInst, TEXT("PrintManAccel"));
  3807. // Register window class for custom spinner dialog box control
  3808. if (!RegisterArrowClass (hInstance))
  3809. return FALSE;
  3810. return TRUE;
  3811. }
  3812. BOOL
  3813. InitQueueChildWindows(
  3814. HWND hWnd)
  3815. {
  3816. PQUEUE pQueue;
  3817. LPPRINTER_INFO_4 pPrinters = NULL;
  3818. DWORD cbPrinters;
  3819. DWORD cReturned = 0;
  3820. DWORD i;
  3821. TCHAR GettingPrinterInfo[80];
  3822. BOOL OK;
  3823. DWORD Flags;
  3824. DWORD WindowType;
  3825. DBGMSG( DBG_TRACE, ( "InitQueueChildWindows\n" ) )
  3826. cbPrinters = 0x1000;
  3827. if( !( pPrinters = AllocSplMem( cbPrinters ) ) )
  3828. cbPrinters = 0;
  3829. LoadString( hInst, IDS_GETTING_PRINTER_INFO, GettingPrinterInfo,
  3830. sizeof GettingPrinterInfo / sizeof *GettingPrinterInfo );
  3831. SendMessage( hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)GettingPrinterInfo );
  3832. SendMessage( hwndStatus, SB_SIMPLE, 1, 0L );
  3833. UpdateWindow( hwndStatus );
  3834. OK = ENUM_PRINTERS( PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL,
  3835. NULL,
  3836. 4,
  3837. pPrinters,
  3838. cbPrinters,
  3839. &cbPrinters,
  3840. &cReturned );
  3841. DBGMSG( DBG_TRACE, ( "EnumPrinters returned %d printers\n", cReturned ) );
  3842. SetStatusMode( STATUS_MODE_NORMAL, FALSE );
  3843. if( !pPrinters && !OK )
  3844. {
  3845. Message( hWnd, MSG_ERROR, IDS_PRINTMANAGER, IDS_COULDNOTENUMERATEPRINTERS );
  3846. SendMessage( hWnd, WM_CLOSE, 0, 0 );
  3847. return FALSE;
  3848. }
  3849. // Process the list of printers returned by creating and initializing
  3850. // local data structures for these
  3851. for (i=0; i<cReturned; i++)
  3852. {
  3853. Flags = 0;
  3854. //
  3855. // We don't know if this printer is pending deletion,
  3856. // enumerate all of them.
  3857. //
  3858. DBGMSG( DBG_TRACE, ( "Initializing queue for %s\n",
  3859. pPrinters[i].pPrinterName ) );
  3860. if( pQueue = AllocQueue(pPrinters[i].pPrinterName))
  3861. {
  3862. if ( pPrinters[i].pServerName )
  3863. {
  3864. pQueue->pServerName = AllocSplStr( pPrinters[i].pServerName );
  3865. if ( !pQueue->pServerName )
  3866. {
  3867. //
  3868. // Fail... !! LATER !!
  3869. //
  3870. }
  3871. }
  3872. else
  3873. {
  3874. //
  3875. // Null implies a local printer
  3876. //
  3877. pQueue->pServerName = NULL;
  3878. }
  3879. if( ALL_FLAGS_ARE_SET( pPrinters[i].Attributes,
  3880. PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL ) )
  3881. WindowType = MDIWIN_LOCALNETWORKPRINTER;
  3882. else if( pPrinters[i].Attributes & PRINTER_ATTRIBUTE_NETWORK )
  3883. WindowType = MDIWIN_NETWORKPRINTER;
  3884. else
  3885. WindowType = MDIWIN_LOCALPRINTER;
  3886. if( pPrinters[i].Attributes & PRINTER_ATTRIBUTE_SHARED )
  3887. Flags = CREATE_PRINTER_SHARED;
  3888. CreateQueueWindow( hWnd, pQueue, PRINTER_STATUS_LOADING,
  3889. WindowType,
  3890. Flags );
  3891. }
  3892. }
  3893. if(cReturned == 0)
  3894. EnableCheckTBButtons(NULL);
  3895. else
  3896. EnableCheckTBButtons((HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L));
  3897. if( pPrinters )
  3898. FreeSplMem(pPrinters);
  3899. UpdateDefaultList();
  3900. return TRUE;
  3901. }
  3902. BOOL
  3903. InitServerChildWindows(
  3904. HWND hwnd
  3905. )
  3906. {
  3907. EnumRegistryValues( szRegServers,
  3908. (ENUMREGPROC)CreateServerWindow,
  3909. (PVOID)hwnd );
  3910. UpdateDefaultList();
  3911. return TRUE;
  3912. }
  3913. long
  3914. APIENTRY
  3915. MDIWndProc(
  3916. HWND hWnd,
  3917. UINT message,
  3918. WPARAM wParam,
  3919. LONG lParam
  3920. )
  3921. {
  3922. static POINT CursorPos;
  3923. if( message == WM_DragList )
  3924. {
  3925. return MDIDragList( hWnd, (LPDRAGLISTINFO)lParam );
  3926. }
  3927. switch (message) {
  3928. case WM_CREATE:
  3929. MDICreate( hWnd, lParam );
  3930. break;
  3931. case WM_PAINT:
  3932. return MDIPaint(hWnd, wParam, lParam);
  3933. case WM_ERASEBKGND:
  3934. if( MDIEraseBkgnd(hWnd, (HDC)wParam) )
  3935. return 1;
  3936. break;
  3937. case WM_QUERYDRAGICON:
  3938. return (long)MDIQueryDragIcon(hWnd);
  3939. case WM_MENUSELECT:
  3940. return MDIMenuSelect( hWnd, wParam, lParam );
  3941. case WM_COMMAND:
  3942. switch (WPARAM_ID(wParam))
  3943. {
  3944. case ID_OBJLIST:
  3945. switch (HIWORD(wParam))
  3946. {
  3947. case LBN_SELCHANGE:
  3948. MDICommandObjListSelChange(hWnd);
  3949. break;
  3950. case LBN_DBLCLK:
  3951. MDICommandObjListDblClk(hWnd);
  3952. break;
  3953. }
  3954. break;
  3955. }
  3956. return 0;
  3957. case WM_NOTIFY:
  3958. {
  3959. HD_NOTIFY * lpNot;
  3960. lpNot = (HD_NOTIFY *) lParam;
  3961. switch (wParam)
  3962. {
  3963. case ID_HEADER:
  3964. switch (lpNot->hdr.code)
  3965. {
  3966. case HDN_BEGINTRACK:
  3967. MDICommandHeaderBeginDrag(hWnd, &CursorPos);
  3968. break;
  3969. case HDN_TRACK:
  3970. MDICommandHeaderDragging(hWnd, &CursorPos, lpNot);
  3971. break;
  3972. case HDN_ENDTRACK:
  3973. MDICommandHeaderEndDrag(hWnd, &CursorPos, lpNot);
  3974. break;
  3975. }
  3976. break;
  3977. }
  3978. }
  3979. return 0;
  3980. case WM_SYSCOMMAND:
  3981. switch( wParam )
  3982. {
  3983. case SC_CLOSE:
  3984. if( !MDIClose(hWnd) )
  3985. {
  3986. SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, lParam);
  3987. return 0;
  3988. }
  3989. break;
  3990. }
  3991. break;
  3992. case WM_VKEYTOITEM:
  3993. switch( LOWORD( wParam ) )
  3994. {
  3995. case VK_SPACE:
  3996. MDIVKeyToItemSpace(hWnd);
  3997. return -2; // Means we handled everything
  3998. case VK_UP:
  3999. case VK_DOWN:
  4000. case VK_LEFT:
  4001. case VK_RIGHT:
  4002. if( MDIVKeyToItemUpDown(hWnd, LOWORD( wParam) ) == -2 )
  4003. return -2;
  4004. break;
  4005. default:
  4006. MDIVKeyToItemDefault(hWnd);
  4007. break;
  4008. }
  4009. break;
  4010. case WM_PARENTNOTIFY:
  4011. switch( wParam )
  4012. {
  4013. case WM_RBUTTONDOWN:
  4014. MDIParentNotifyRButtonDown( hWnd, lParam );
  4015. return 0;
  4016. }
  4017. break;
  4018. case WM_SIZE:
  4019. MDISize( hWnd, (DWORD)lParam );
  4020. break; // WM_SIZE MUST also be processed by DefMDIChildProc
  4021. case WM_MDIACTIVATE:
  4022. if (wParam)
  4023. MDIMDIActivate( hWnd, (HWND)wParam, (HWND)lParam );
  4024. break;
  4025. case WM_NCACTIVATE:
  4026. if( !wParam )
  4027. MDINCActivate( hWnd );
  4028. break;
  4029. case WM_WINDOWPOSCHANGED:
  4030. return MDIWindowPosChanged( hWnd, wParam, lParam );
  4031. case WM_SETFOCUS:
  4032. MDISetFocus( hWnd );
  4033. return 0;
  4034. case WM_MEASUREITEM:
  4035. MDIMeasureItem( hWnd, (LPMEASUREITEMSTRUCT)lParam );
  4036. return 0;
  4037. case WM_DRAWITEM:
  4038. MDIDrawItem( hWnd, (LPDRAWITEMSTRUCT)lParam );
  4039. return TRUE;
  4040. case WM_TIMER: // Update Print Jobs for this queue.
  4041. MDITimer( hWnd );
  4042. return 0;
  4043. case WM_STATUS_CHANGED:
  4044. // MDIStatusChanged( hWnd );
  4045. return 0;
  4046. case WM_UPDATE_LIST:
  4047. MDIUpdateList( hWnd );
  4048. return 0;
  4049. case SB_SETPARTS:
  4050. MDISetParts( hWnd, wParam, lParam );
  4051. return 0;
  4052. #ifdef ALLOW_DROPS_ON_ALL_PRINTERS
  4053. case WM_DROPOBJECT:
  4054. MDIDropObject( hWnd );
  4055. return 0x544E5250L; // 'PRNT' tells fm to print
  4056. #endif /* ALLOW_DROPS_ON_ALL_PRINTERS */
  4057. case WM_CLOSE:
  4058. if( !MDIClose(hWnd) )
  4059. {
  4060. SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, lParam);
  4061. return 0;
  4062. }
  4063. break;
  4064. case WM_DESTROY:
  4065. MDIDestroy( hWnd );
  4066. return 0;
  4067. }
  4068. return DefMDIChildProc(hWnd, message, wParam, lParam);
  4069. }
  4070. /*
  4071. *
  4072. */
  4073. VOID MDICreate( HWND hWnd, LONG lParam )
  4074. {
  4075. RECT rect;
  4076. DWORD xList;
  4077. DWORD yList;
  4078. DWORD cxList;
  4079. DWORD cyList;
  4080. PMDIWIN_INFO pMDIWinInfo;
  4081. RECT rectHeader;
  4082. INT i, ColumnWidths[MAX_HEADERS];
  4083. HD_ITEM hdi;
  4084. RECT rcParent;
  4085. HD_LAYOUT hdl;
  4086. WINDOWPOS wp;
  4087. DBGMSG( DBG_TRACE, ( "Enter MDICreate %08x\n", hWnd ) );
  4088. // The first time thru we have to pickup the pQueue value from
  4089. // the extra Params field of the CREATESTRUCT
  4090. pMDIWinInfo = (PMDIWIN_INFO)(((LPMDICREATESTRUCT)
  4091. (((LPCREATESTRUCT)lParam)->lpCreateParams))->lParam);
  4092. /* Store the MDIWIN_INFO struct pointer in the window struct for
  4093. * future use during other message processing by the WinProc.
  4094. */
  4095. SetWindowLong(hWnd, GWL_PMDIWIN, (unsigned)pMDIWinInfo);
  4096. pMDIWinInfo->hwnd = hWnd;
  4097. pMDIWinInfo->Alive = TRUE;
  4098. CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)RefreshThread,
  4099. pMDIWinInfo, 0, &pMDIWinInfo->ThreadId );
  4100. pMDIWinInfo->hwndHeader = CreateWindow (WC_HEADER, TEXT(""),
  4101. WS_CHILD | WS_BORDER | CCS_TOP,
  4102. 0,0,0,0, hWnd, (HMENU) ID_HEADER,
  4103. hInst, NULL);
  4104. GetClientRect(hWnd, &rcParent);
  4105. hdl.prc = &rcParent;
  4106. hdl.pwpos = &wp;
  4107. SendMessage(pMDIWinInfo->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hdl);
  4108. if (!bJapan) {
  4109. SendMessage( pMDIWinInfo->hwndHeader, WM_SETFONT, (WPARAM)hfontHelvBold, 1L );
  4110. }
  4111. for( i = 0; i < pMDIWinInfo->cColumns; i++ )
  4112. {
  4113. ColumnWidths[i] = pMDIWinInfo->pColumns[i].Width;
  4114. }
  4115. if( ColumnWidths[0] == CW_USEDEFAULT )
  4116. SetDefaultColumnWidths( hWnd, pMDIWinInfo, ColumnWidths );
  4117. hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
  4118. hdi.fmt = HDF_LEFT | HDF_STRING;
  4119. for( i = 0; i < pMDIWinInfo->cColumns; i++ ) {
  4120. hdi.pszText = pMDIWinInfo->pColumns[i].Text;
  4121. hdi.cxy = ColumnWidths[i];
  4122. hdi.cchTextMax = lstrlen(hdi.pszText);
  4123. SendMessage(pMDIWinInfo->hwndHeader, HDM_INSERTITEM,
  4124. (WPARAM) pMDIWinInfo->cColumns+ 1, (LPARAM)&hdi);
  4125. }
  4126. SetWindowPos(pMDIWinInfo->hwndHeader, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy,
  4127. wp.flags | SWP_SHOWWINDOW);
  4128. /* Calculate width and height of the list box:
  4129. */
  4130. GetWindowRect( pMDIWinInfo->hwndHeader, &rectHeader );
  4131. HeaderHeight = (rectHeader.bottom - rectHeader.top);
  4132. GetWindowRect(hWnd, &rect);
  4133. xList = 0;
  4134. yList = HeaderHeight;
  4135. cxList = rect.right;
  4136. cyList = rect.bottom - HeaderHeight;
  4137. yList = rectHeader.bottom;
  4138. cyList = rect.bottom - rectHeader.bottom;
  4139. /* Create Queue and Job Status list box control in client window
  4140. */
  4141. pMDIWinInfo->hwndList = CreateWindow( TEXT("LISTBOX"), NULL,
  4142. WS_CHILD | WS_VISIBLE | WS_VSCROLL
  4143. | WS_CLIPSIBLINGS
  4144. | LBS_NOTIFY | LBS_OWNERDRAWFIXED
  4145. | LBS_NODATA | LBS_NOINTEGRALHEIGHT
  4146. | LBS_WANTKEYBOARDINPUT,
  4147. xList, yList, cxList, cyList,
  4148. hWnd,
  4149. (HMENU)ID_OBJLIST,
  4150. hInst,
  4151. NULL);
  4152. // CountryCode - krishnag
  4153. // #ifndef JAPAN
  4154. if (!bJapan) {
  4155. SendMessage( pMDIWinInfo->hwndList, WM_SETFONT, (WPARAM)hfontHelv, 1L );
  4156. }
  4157. // #endif
  4158. // SendMessage( pMDIWinInfo->hwndList, LB_SETCOUNT, *pMDIWinInfo->pcObjects, 0L );
  4159. if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
  4160. {
  4161. MakeDragList( pMDIWinInfo->hwndList );
  4162. if( !WM_DragList )
  4163. WM_DragList = RegisterWindowMessage( DRAGLISTMSGSTRING );
  4164. DefListboxWndProc = (WNDPROC)SetWindowLong( pMDIWinInfo->hwndList,
  4165. GWL_WNDPROC,
  4166. (LONG)SubclassListboxWndProc );
  4167. pMDIWinInfo->ObjSelected = NOSELECTION;
  4168. pMDIWinInfo->DragPosition = NOSELECTION;
  4169. }
  4170. else
  4171. {
  4172. SendMessage( pMDIWinInfo->hwndList, LB_SETCURSEL, 0, 0L );
  4173. pMDIWinInfo->ObjSelected = 0;
  4174. pMDIWinInfo->DragPosition = NOSELECTION;
  4175. *pMDIWinInfo->ppSelData = *pMDIWinInfo->ppData;
  4176. }
  4177. DBGMSG( DBG_TRACE, ( "Exit MDICreate %08x\n", hWnd ) );
  4178. }
  4179. /*
  4180. *
  4181. */
  4182. VOID SetDefaultColumnWidths( HWND hwnd, PMDIWIN_INFO pMDIWinInfo,
  4183. PINT pColumnWidths )
  4184. {
  4185. RECT rect;
  4186. PCOLUMN pDefaultColumn;
  4187. INT i;
  4188. INT TotalWidth;
  4189. INT AvailableWidth;
  4190. GetWindowRect( hwnd, &rect );
  4191. AvailableWidth = ( rect.right - rect.left );
  4192. if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
  4193. pDefaultColumn = MDIServerDefaultColumn;
  4194. else
  4195. pDefaultColumn = MDIPrinterDefaultColumn;
  4196. for( i = 0, TotalWidth = 0; i < pMDIWinInfo->cColumns; i++ )
  4197. TotalWidth += pDefaultColumn[i].Width;
  4198. /* Size the headers so that they use up the space available.
  4199. */
  4200. for( i = 0; i < pMDIWinInfo->cColumns; i++ )
  4201. pColumnWidths[i] = pMDIWinInfo->pColumns[i].Width =
  4202. ( pDefaultColumn[i].Width * AvailableWidth / TotalWidth );
  4203. }
  4204. /* MDIPaint
  4205. *
  4206. * Called in response to the WM_PAINT message.
  4207. *
  4208. * If the window is iconic, and we're going to draw our own icon, do it.
  4209. *
  4210. * If it isn't iconic, draw the status bar.
  4211. */
  4212. LONG MDIPaint(HWND hwnd, WPARAM wParam, LPARAM lParam)
  4213. {
  4214. PMDIWIN_INFO pMDIWinInfo;
  4215. HDC hdc;
  4216. PAINTSTRUCT ps;
  4217. LONG rc;
  4218. pMDIWinInfo = GETMDIWIN( hwnd );
  4219. hdc = BeginPaint(hwnd, &ps);
  4220. if (IsIconic(hwnd))
  4221. {
  4222. if( pMDIWinInfo->hicon )
  4223. DrawIcon( hdc, 0, 0, pMDIWinInfo->hicon );
  4224. EndPaint(hwnd, &ps);
  4225. }
  4226. else
  4227. {
  4228. EndPaint(hwnd, &ps);
  4229. rc = DefMDIChildProc(hwnd, WM_PAINT, wParam, lParam);
  4230. /* Do the default stuff, which should cause an initial paint,
  4231. * then fake a timer message to ensure the window is up to date.
  4232. * This may result in the window being painted twice, but at least
  4233. * there won't be an obvious delay while the job info gets refreshed.
  4234. */
  4235. }
  4236. return rc;
  4237. }
  4238. /* MDIEraseBkgnd
  4239. *
  4240. * We're interested in the WM_ERASEBKGND message if we're drawing our own icon.
  4241. *
  4242. * Return:
  4243. *
  4244. * TRUE if the background was successfully painted.
  4245. * Otherwise, the message should be passed to the default procedure.
  4246. *
  4247. */
  4248. BOOL MDIEraseBkgnd(HWND hwnd, HDC hdc)
  4249. {
  4250. PMDIWIN_INFO pMDIWinInfo;
  4251. HBRUSH hbrush;
  4252. RECT rect;
  4253. BOOL Painted = FALSE;
  4254. pMDIWinInfo = GETMDIWIN( hwnd );
  4255. if( IsIconic( hwnd ) && pMDIWinInfo->hicon )
  4256. {
  4257. hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ) );
  4258. GetWindowRect( hwnd, &rect );
  4259. /* rect is in screen coordinates.
  4260. * We must convert to client coordinates:
  4261. */
  4262. ScreenToClient( hwnd, &((LPPOINT)&rect)[0] );
  4263. ScreenToClient( hwnd, &((LPPOINT)&rect)[1] );
  4264. Painted = FillRect( hdc, &rect, hbrush );
  4265. DeleteObject( hbrush );
  4266. }
  4267. return Painted;
  4268. }
  4269. /* MDIQueryDragIcon
  4270. *
  4271. * Called if the user is dragging an icon around.
  4272. * Just returns the icon handle for the window, which is non-null for
  4273. * icons that we draw ourselves.
  4274. */
  4275. HICON MDIQueryDragIcon(HWND hwnd)
  4276. {
  4277. PMDIWIN_INFO pMDIWinInfo;
  4278. pMDIWinInfo = GETMDIWIN( hwnd );
  4279. return pMDIWinInfo->hicon;
  4280. }
  4281. /* Respond to system menu selections in MDI windows.
  4282. * Update the status bar correspondingly.
  4283. */
  4284. LONG MDIMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam )
  4285. {
  4286. UINT ItemID;
  4287. UINT Flags;
  4288. ItemID = (UINT)LOWORD( wParam );
  4289. Flags = (UINT)HIWORD( wParam );
  4290. MenuHelp( WM_MENUSELECT, wParam, lParam, GetMenu( hwnd ),
  4291. hInst, hwndStatus, pMenuHelpIDs);
  4292. if( ItemID && ( Flags & MF_SYSMENU ) )
  4293. WinHelpMenuID = ID_HELP_MDI_SYSMENU;
  4294. else
  4295. WinHelpMenuID = ItemID;
  4296. return 0;
  4297. }
  4298. /* MDICommandObjListSelChange
  4299. *
  4300. * This routine will be called when a new selection is made in the list.
  4301. * It will also be called if the user just clicks on an already selected
  4302. * list item.
  4303. *
  4304. * If the user is clicking, we want to toggle selection of this item,
  4305. * otherwise reflect the change of selection in our instance data.
  4306. *
  4307. * If the user's been dragging a job in a printer window, and has now
  4308. * released the mouse back where it started, don't toggle.
  4309. *
  4310. *
  4311. */
  4312. VOID MDICommandObjListSelChange( HWND hwnd )
  4313. {
  4314. PMDIWIN_INFO pInfo;
  4315. DWORD Selection;
  4316. if( !(pInfo = GETMDIWIN(hwnd) ) )
  4317. return;
  4318. Selection = (DWORD)GETLISTSELECT( hwnd, ID_OBJLIST );
  4319. ENTER_PROTECTED_DATA( pInfo );
  4320. if( ( Selection == pInfo->ObjSelected )
  4321. &&( pInfo->WindowType != MDIWIN_SERVER )
  4322. &&( pInfo->DragPosition == NOSELECTION ) )
  4323. {
  4324. Selection = NOSELECTION;
  4325. SETLISTSELECT( hwnd, ID_OBJLIST, Selection );
  4326. }
  4327. /* Beware, jobs may have gone away since USER sent us the message;
  4328. * ensure that the data is still valid:
  4329. */
  4330. else if( !*pInfo->ppData )
  4331. {
  4332. Selection = NOSELECTION;
  4333. SETLISTSELECT( hwnd, ID_OBJLIST, Selection );
  4334. }
  4335. SetObjectSelection( pInfo, Selection );
  4336. EnableCheckTBButtons(hwnd);
  4337. UpdateStatus(hwnd);
  4338. LEAVE_PROTECTED_DATA( pInfo );
  4339. }
  4340. /* Set Print Manager's internal data structures to correspond to the selection:
  4341. *
  4342. */
  4343. VOID SetObjectSelection( PMDIWIN_INFO pInfo, DWORD Selection )
  4344. {
  4345. DBG_IN_PROTECTED_DATA( pInfo );
  4346. if( Selection == NOSELECTION )
  4347. {
  4348. *pInfo->ppSelData = NULL;
  4349. *pInfo->pSelObjId = 0;
  4350. }
  4351. else
  4352. {
  4353. *pInfo->ppSelData = (PBYTE)( *pInfo->ppData
  4354. + ( ( Selection - *pInfo->pFirstEnumObj )
  4355. * pInfo->DataSize ) );
  4356. *pInfo->pSelObjId = *(DWORD *)( *pInfo->ppSelData + pInfo->IdOffset );
  4357. }
  4358. pInfo->ObjSelected = Selection;
  4359. }
  4360. /*
  4361. *
  4362. */
  4363. VOID MDICommandObjListDblClk( HWND hwnd )
  4364. {
  4365. PMDIWIN_INFO pMDIWinInfo;
  4366. PSERVER_CONTEXT pServerContext;
  4367. PQUEUE pQueue;
  4368. PPRINTER_INFO_2 pPrinterSelected;
  4369. HWND hwndPrinter;
  4370. pMDIWinInfo = (PMDIWIN_INFO)GetWindowLong(hwnd, GWL_PMDIWIN);
  4371. if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
  4372. {
  4373. ENTER_PROTECTED_DATA( pMDIWinInfo );
  4374. pQueue = (PQUEUE)pMDIWinInfo->pContext;
  4375. if (pQueue->pSelJob)
  4376. DialogBoxParam (hInst, MAKEINTRESOURCE(DLG_DOCTAILS), hwnd,
  4377. (DLGPROC)DocDetailsDlg, (DWORD)pQueue);
  4378. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  4379. }
  4380. else
  4381. {
  4382. WCHAR szPrinterName[MAX_PATH];
  4383. DWORD dwStatus;
  4384. /* This is a Server Viewer:
  4385. */
  4386. pServerContext = pMDIWinInfo->pContext;
  4387. ENTER_PROTECTED_DATA( pMDIWinInfo );
  4388. /* See if there's already an MDI window for the printer name
  4389. * we just clicked on:
  4390. *
  4391. * !!! Actually we will probably have to combine it with the
  4392. * !!! server name.
  4393. */
  4394. pPrinterSelected = pServerContext->pSelPrinter;
  4395. if (pPrinterSelected && pPrinterSelected->pPrinterName) {
  4396. wcscpy(szPrinterName, pPrinterSelected->pPrinterName);
  4397. dwStatus = pPrinterSelected->Status;
  4398. } else {
  4399. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  4400. return;
  4401. }
  4402. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  4403. hwndPrinter = FindPrinterWindow( szPrinterName );
  4404. /* If so, just bring it into focus:
  4405. */
  4406. if( hwndPrinter )
  4407. {
  4408. SendMessage( hwndClient, WM_MDIACTIVATE, (WPARAM)hwndPrinter, 0L );
  4409. if( IsIconic( hwndPrinter ) )
  4410. ShowWindow( hwndPrinter, SW_RESTORE );
  4411. }
  4412. /* Otherwise create a new MDI window for this printer:
  4413. */
  4414. else
  4415. {
  4416. SetCursor( hcursorWait );
  4417. if( AddPrinterConnection( szPrinterName ) )
  4418. {
  4419. if( pQueue = AllocQueue( szPrinterName ) )
  4420. {
  4421. pQueue->Error = OpenThreadObject(pQueue->pPrinterName,
  4422. &pQueue->hPrinter,
  4423. &pQueue->AccessGranted,
  4424. MDIWIN_PRINTER);
  4425. if( !pQueue->Error )
  4426. {
  4427. pQueue->pServerName = AllocSplStr( pServerContext->pServerName );
  4428. CreateQueueWindow( hwnd, pQueue, dwStatus,
  4429. MDIWIN_NETWORKPRINTER, FALSE );
  4430. UpdateDefaultList();
  4431. }
  4432. else
  4433. {
  4434. FreeQueue( pQueue );
  4435. ReportFailure( hwnd, 0, IDS_COULDNOTOPENPRINTER );
  4436. }
  4437. }
  4438. }
  4439. else
  4440. {
  4441. if( GetLastError( ) == ERROR_UNKNOWN_PRINTER_DRIVER )
  4442. Message( hwnd, MSG_ERROR, IDS_PRINTMANAGER, IDS_NO_DRIVER_ON_SERVER );
  4443. else
  4444. ReportFailure( hwnd, 0, IDS_COULDNOTCONNECTTOPRINTER );
  4445. }
  4446. SetCursor( hcursorArrow );
  4447. }
  4448. }
  4449. }
  4450. /* MDICommandHeaderBeginDrag
  4451. *
  4452. * Called when the user begins to drag a movable column in an MDI list.
  4453. * Queries the current position and marks the appropriate rectangle.
  4454. *
  4455. * Parameters:
  4456. *
  4457. * hwnd - The handle of the MDI window.
  4458. *
  4459. * pCursorPos - A pointer to the coordinates of the cursor.
  4460. * Initially undefined, it will be updated with the new coordinates.
  4461. *
  4462. */
  4463. VOID MDICommandHeaderBeginDrag( HWND hwnd, PPOINT pCursorPos )
  4464. {
  4465. PMDIWIN_INFO pMDIWinInfo;
  4466. pMDIWinInfo = (PMDIWIN_INFO)GetWindowLong(hwnd, GWL_PMDIWIN);
  4467. /* Don't permit the window to be refreshed while we're dragging:
  4468. */
  4469. ENTER_PROTECTED_DATA( pMDIWinInfo );
  4470. ResetEvent( pMDIWinInfo->RefreshSignal );
  4471. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  4472. if( GetCursorPos( pCursorPos ) )
  4473. {
  4474. ScreenToClient( hwnd, pCursorPos );
  4475. InvertDragMark( hwnd, pCursorPos );
  4476. }
  4477. }
  4478. /* MDICommandHeaderDragging
  4479. *
  4480. * Called when the user is dragging a movable column in an MDI list.
  4481. * Calls InvertDragMark to clear the previous mark, then updates the current
  4482. * position and inverts the new mark area.
  4483. *
  4484. * Parameters:
  4485. *
  4486. * hwnd - The handle of the MDI window.
  4487. *
  4488. * pCursorPos - A pointer to the previous coordinates of the cursor.
  4489. * This will be updated with the new coordinates.
  4490. *
  4491. */
  4492. VOID MDICommandHeaderDragging( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot )
  4493. {
  4494. InvertDragMark( hwnd, pCursorPos );
  4495. #ifdef DRAG_AS_WE_GO
  4496. /* This doesn't look too wonderful, cos there's a lot to do to keep up:
  4497. */
  4498. UpdateColumns( hwnd, lpNot );
  4499. #endif /* DRAG_AS_WE_GO */
  4500. if( GetCursorPos( pCursorPos ) )
  4501. {
  4502. ScreenToClient( hwnd, pCursorPos );
  4503. InvertDragMark( hwnd, pCursorPos );
  4504. }
  4505. }
  4506. /* MDICommandHeaderEndDrag
  4507. *
  4508. * Called when the user releases the mouse button after dragging a movable
  4509. * column heading.
  4510. *
  4511. * Parameters:
  4512. *
  4513. * hwnd - The handle of the MDI window.
  4514. *
  4515. * pCursorPos - A pointer to the current coordinates of the cursor.
  4516. *
  4517. *
  4518. */
  4519. VOID MDICommandHeaderEndDrag( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot )
  4520. {
  4521. PMDIWIN_INFO pMDIWinInfo;
  4522. pMDIWinInfo = GETMDIWIN(hwnd);
  4523. InvertDragMark( hwnd, pCursorPos );
  4524. UpdateColumns( hwnd, lpNot );
  4525. ENTER_PROTECTED_DATA( pMDIWinInfo );
  4526. SetEvent( pMDIWinInfo->RefreshSignal );
  4527. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  4528. }
  4529. /* InvertDragMark
  4530. *
  4531. * Puts up a vertical mark to indicate where the user is dragging the movable
  4532. * headers of a list box.
  4533. * This function is called both to set and to clear the mark, since it simply
  4534. * inverts the mark rectangle.
  4535. *
  4536. * Parameters:
  4537. *
  4538. * hwnd - The handle of the MDI window.
  4539. *
  4540. * pCursorPos - A pointer to the current coordinates of the cursor.
  4541. *
  4542. */
  4543. #define MARKERWIDTH 2
  4544. VOID InvertDragMark( HWND hwnd, PPOINT pCursorPos )
  4545. {
  4546. PMDIWIN_INFO pMDIWinInfo;
  4547. HWND hwndList;
  4548. RECT rcMark;
  4549. HDC hdc;
  4550. pMDIWinInfo = GETMDIWIN( hwnd );
  4551. hwndList = pMDIWinInfo->hwndList;
  4552. if( GetClientRect( hwnd, &rcMark ) )
  4553. {
  4554. rcMark.left = pCursorPos->x;
  4555. rcMark.right = ( rcMark.left + MARKERWIDTH );
  4556. hdc = GetDC( hwndList );
  4557. InvertRect( hdc, &rcMark );
  4558. ReleaseDC( hwndList, hdc );
  4559. }
  4560. }
  4561. /* UpdateColumns
  4562. *
  4563. * Finds out the new widths of the columns by sending
  4564. * HDM_GETITEM to the movable header control. Then updates the heading
  4565. * parameters in the window's instance data, and causes the list to repaint.
  4566. *
  4567. * Parameter:
  4568. *
  4569. * hwnd - The handle of the MDI window.
  4570. *
  4571. */
  4572. VOID UpdateColumns( HWND hwnd, HD_NOTIFY * lpNot )
  4573. {
  4574. PMDIWIN_INFO pMDIWinInfo;
  4575. INT i, HeaderWidth[MAX_HEADERS];
  4576. INT cColumns;
  4577. PCOLUMN pColumn;
  4578. HD_ITEM hdi;
  4579. pMDIWinInfo = GETMDIWIN(hwnd);
  4580. cColumns = SendMessage( pMDIWinInfo->hwndHeader, HDM_GETITEMCOUNT,0,0);
  4581. pColumn = GETCOLUMN( hwnd );
  4582. hdi.mask = HDI_WIDTH;
  4583. for( i = 0; i < cColumns; i++ ) {
  4584. if (i != lpNot->iItem) {
  4585. Header_GetItem(pMDIWinInfo->hwndHeader, i, &hdi);
  4586. } else {
  4587. hdi.cxy = lpNot->pitem->cxy;
  4588. }
  4589. pColumn[i].Width = hdi.cxy;
  4590. }
  4591. InvalidateRect( pMDIWinInfo->hwndList, NULL, FALSE );
  4592. }
  4593. /* If someone's dropped a file on one of the MDI printer windows,
  4594. * we must ensure that the printer is default, since apps like File Manager
  4595. * just print to the default printer.
  4596. * Unfortunately, we can't revert to the previous default printer, because
  4597. * we won't know when the job has completed printing.
  4598. */
  4599. VOID MDIDropObject( HWND hwnd )
  4600. {
  4601. PMDIWIN_INFO pInfo;
  4602. pInfo = GETMDIWIN(hwnd);
  4603. /* This should never be false:
  4604. */
  4605. if( pInfo->WindowType != MDIWIN_SERVER )
  4606. {
  4607. /* Set the default printer and update the default combo */
  4608. }
  4609. }
  4610. /* Verify that we can close this MDI window with the system menu Close option.
  4611. * If not, an SC_MINIMIZE code should be sent to the window.
  4612. */
  4613. BOOL MDIClose( HWND hwnd )
  4614. {
  4615. PMDIWIN_INFO pInfo;
  4616. pInfo = GETMDIWIN(hwnd);
  4617. if( !pInfo )
  4618. return FALSE;
  4619. /* We can close only server windows:
  4620. */
  4621. if( pInfo->WindowType == MDIWIN_SERVER )
  4622. {
  4623. /* Just in case this is the last MDI window, clear the
  4624. * toolbar buttons and status bar:
  4625. */
  4626. EnableCheckTBButtons(NULL);
  4627. UpdateStatus(NULL);
  4628. return TRUE;
  4629. }
  4630. else
  4631. return FALSE;
  4632. }
  4633. /* MDIVKeyToItemSpace
  4634. *
  4635. * Respond to spacebar presses by toggling document selection in printer
  4636. * windows.
  4637. *
  4638. */
  4639. VOID MDIVKeyToItemSpace( HWND hwnd )
  4640. {
  4641. PMDIWIN_INFO pInfo;
  4642. DWORD Selection;
  4643. DWORD TopIndex;
  4644. RECT rcDragPosition;
  4645. pInfo = GETMDIWIN(hwnd);
  4646. if( !pInfo )
  4647. return;
  4648. if( pInfo->WindowType != MDIWIN_SERVER )
  4649. {
  4650. ENTER_PROTECTED_DATA( pInfo );
  4651. Selection = (DWORD)GETLISTSELECT( hwnd, ID_OBJLIST );
  4652. /* If there is no selection, retrieve the last selected guy,
  4653. * if it's in range:
  4654. */
  4655. if( Selection == LB_ERR )
  4656. {
  4657. TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
  4658. if( ( pInfo->PrevSelection >= TopIndex )
  4659. &&( pInfo->PrevSelection <= ( TopIndex + pInfo->cNumLines ) ) )
  4660. pInfo->ObjSelected = pInfo->PrevSelection;
  4661. else
  4662. pInfo->ObjSelected = TopIndex;
  4663. /* Let's err on the side of caution;
  4664. * ensure that the data is still valid:
  4665. */
  4666. if( !*pInfo->ppData )
  4667. {
  4668. Selection = NOSELECTION;
  4669. SETLISTSELECT( hwnd, ID_OBJLIST, Selection );
  4670. }
  4671. SetObjectSelection( pInfo, pInfo->ObjSelected );
  4672. pInfo->PrevSelection = 0;
  4673. }
  4674. else
  4675. {
  4676. pInfo->PrevSelection = Selection;
  4677. pInfo->ObjSelected = NOSELECTION;
  4678. pInfo->DragPosition = NOSELECTION;
  4679. *pInfo->pSelObjId = 0;
  4680. }
  4681. SETLISTSELECT( hwnd, ID_OBJLIST, pInfo->ObjSelected );
  4682. if( pInfo->DragPosition != NOSELECTION )
  4683. {
  4684. pInfo->DragPosition = NOSELECTION;
  4685. SendMessage( pInfo->hwndList, LB_GETITEMRECT, pInfo->DragPosition,
  4686. (LPARAM)&rcDragPosition );
  4687. InvalidateRect( pInfo->hwndList, &rcDragPosition, FALSE );
  4688. }
  4689. EnableCheckTBButtons(hwnd);
  4690. UpdateStatus(hwnd);
  4691. LEAVE_PROTECTED_DATA( pInfo );
  4692. }
  4693. }
  4694. /*
  4695. *
  4696. */
  4697. VOID MDIParentNotifyRButtonDown( HWND hwnd, DWORD CursorPos )
  4698. {
  4699. PMDIWIN_INFO pInfo;
  4700. POINT ptCursor;
  4701. INT LBItem;
  4702. pInfo = GETMDIWIN(hwnd);
  4703. if( !pInfo )
  4704. return;
  4705. if( ( pInfo->WindowType != MDIWIN_SERVER )
  4706. &&( pInfo->DragPosition == NOSELECTION ) )
  4707. {
  4708. LONG2POINT( CursorPos, ptCursor );
  4709. ClientToScreen( hwnd, &ptCursor );
  4710. LBItem = LBItemFromPt( pInfo->hwndList, ptCursor, FALSE );
  4711. if( LBItem == (INT)pInfo->ObjSelected )
  4712. {
  4713. SETLISTSELECT( hwnd, ID_OBJLIST, NOSELECTION );
  4714. SendMessage( hwnd, WM_COMMAND,
  4715. GET_WM_COMMAND_MPS( GetDlgCtrlID( pInfo->hwndList ),
  4716. pInfo->hwndList, LBN_SELCHANGE ) );
  4717. }
  4718. }
  4719. }
  4720. /*
  4721. *
  4722. */
  4723. VOID MDIVKeyToItemDefault( HWND hwnd )
  4724. {
  4725. PMDIWIN_INFO pInfo;
  4726. pInfo = GETMDIWIN(hwnd);
  4727. if( !pInfo )
  4728. return;
  4729. SendMessage( pInfo->hwndList, WM_RBUTTONDOWN, 0, 0L );
  4730. /* Clear any previous reorder mark:
  4731. */
  4732. ClearDragPosition( pInfo );
  4733. }
  4734. /* ReorderJob
  4735. *
  4736. * Sets the job position to the value in the DragPosition field of pInfo,
  4737. * then forces a refresh of the job buffer.
  4738. *
  4739. */
  4740. VOID ReorderJob( HWND hwnd, PMDIWIN_INFO pInfo, DWORD Position )
  4741. {
  4742. PQUEUE pQueue;
  4743. LPJOB_INFO_2 pJobReorder;
  4744. pQueue = (PQUEUE)pInfo->pContext;
  4745. if( !pQueue || !pQueue->pJobs )
  4746. return;
  4747. if( ( pInfo->ObjSelected == NOSELECTION ) || ( Position == NOSELECTION ) )
  4748. return;
  4749. ENTER_PROTECTED_DATA( pInfo );
  4750. pJobReorder = pQueue->pSelJob;
  4751. if( ( pJobReorder == NULL ) || ( pJobReorder == (LPJOB_INFO_2)NOSELECTION ) )
  4752. {
  4753. DBGMSG( DBG_ERROR, ( "Error: ReorderJob called with pSelJob == %d",
  4754. pJobReorder ) );
  4755. LEAVE_PROTECTED_DATA( pInfo );
  4756. return;
  4757. }
  4758. DBGMSG( DBG_INFO, ( "ReorderJob: JobId = %d; Position = %d\n",
  4759. pJobReorder->JobId, pJobReorder->Position ) );
  4760. if( pJobReorder )
  4761. {
  4762. BOOL OK;
  4763. /* Spooler order is 1-based:
  4764. */
  4765. pJobReorder->Position = ( Position + 1 );
  4766. OK = SetJob( pQueue->hPrinter,
  4767. pJobReorder->JobId,
  4768. 2, (LPBYTE)pJobReorder, 0 );
  4769. if( !OK )
  4770. ReportFailure( hwnd, 0, IDS_COULD_NOT_REORDER_JOB );
  4771. }
  4772. LEAVE_PROTECTED_DATA( pInfo );
  4773. }
  4774. /*
  4775. *
  4776. */
  4777. VOID MarkPosition( PMDIWIN_INFO pInfo, DWORD Position )
  4778. {
  4779. DWORD OldPosition;
  4780. /* N.B. Ensure pInfo->DragPosition is updated before we do any repainting,
  4781. * since MDIDrawItem depends on it:
  4782. */
  4783. if( pInfo->DragPosition != Position )
  4784. {
  4785. /* If the top index hasn't been reset, we need to force a repaint
  4786. * of the old and new reorder positions:
  4787. */
  4788. OldPosition = pInfo->DragPosition;
  4789. pInfo->DragPosition = Position;
  4790. RepaintListboxItem( pInfo->hwndList, OldPosition );
  4791. if( Position != (DWORD) NOSELECTION )
  4792. RepaintListboxItem( pInfo->hwndList, Position );
  4793. }
  4794. }
  4795. /* MDIVKeyToItemUpDown
  4796. *
  4797. * Called when the user presses an up or down cursor.
  4798. * We're interested in this only if the control key is also depressed
  4799. * at the same time, otherwise we rely on the default system response.
  4800. *
  4801. * The Ctrl-Up or Ctrl-Down combination is used
  4802. *
  4803. */
  4804. int MDIVKeyToItemUpDown( HWND hwnd, WORD VKey )
  4805. {
  4806. PMDIWIN_INFO pInfo;
  4807. DWORD Selection;
  4808. DWORD TopIndex;
  4809. DWORD DragPosition;
  4810. pInfo = GETMDIWIN(hwnd);
  4811. /* if the high-order bit of the SHORT returned from GetKeyState
  4812. * is on, the key is down:
  4813. */
  4814. if( ( pInfo->WindowType != MDIWIN_SERVER )
  4815. &&( GetKeyState( VK_CONTROL ) & 0x8000 )
  4816. &&( pInfo->pContext )
  4817. &&( ( (PQUEUE)( pInfo->pContext ) )->AccessGranted & PRINTER_ACCESS_ADMINISTER ) )
  4818. {
  4819. ENTER_PROTECTED_DATA( pInfo );
  4820. ResetEvent( pInfo->RefreshSignal );
  4821. LEAVE_PROTECTED_DATA( pInfo );
  4822. Selection = (DWORD)GETLISTSELECT( hwnd, ID_OBJLIST );
  4823. TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
  4824. DragPosition = pInfo->DragPosition;
  4825. if( DragPosition == NOSELECTION )
  4826. {
  4827. DragPosition = Selection;
  4828. pInfo->ObjSelected = Selection;
  4829. }
  4830. switch( VKey )
  4831. {
  4832. case VK_UP:
  4833. case VK_LEFT:
  4834. if( DragPosition > 0 )
  4835. DragPosition--;
  4836. break;
  4837. case VK_DOWN:
  4838. case VK_RIGHT:
  4839. if( DragPosition < ( *pInfo->pcObjects - 1 ) )
  4840. DragPosition++;
  4841. }
  4842. /* N.B. Ensure pInfo->DragPosition is updated before we do any repainting,
  4843. * since MDIDrawItem depends on it:
  4844. */
  4845. if( pInfo->DragPosition != DragPosition )
  4846. {
  4847. MarkPosition( pInfo, DragPosition );
  4848. /* Scroll up a line if we've gone off the top:
  4849. */
  4850. if( DragPosition < TopIndex )
  4851. SendMessage( pInfo->hwndList, LB_SETTOPINDEX, DragPosition, 0L );
  4852. /* Scroll down a line if we've gone off the bottom:
  4853. */
  4854. else if( DragPosition >= ( TopIndex + pInfo->cNumLines ) )
  4855. SendMessage( pInfo->hwndList, LB_SETTOPINDEX, TopIndex+1, 0L );
  4856. }
  4857. LEAVE_PROTECTED_DATA( pInfo );
  4858. return -2;
  4859. }
  4860. else
  4861. {
  4862. if( pInfo->DragPosition != NOSELECTION )
  4863. {
  4864. pInfo->DragPosition = NOSELECTION;
  4865. RepaintListboxItem( pInfo->hwndList, pInfo->DragPosition );
  4866. }
  4867. return -1;
  4868. }
  4869. }
  4870. /*
  4871. *
  4872. */
  4873. VOID RepaintListboxItem( HWND hwndListbox, DWORD ItemID )
  4874. {
  4875. RECT rcItem;
  4876. SendMessage( hwndListbox, LB_GETITEMRECT, ItemID, (LPARAM)&rcItem );
  4877. InvalidateRect( hwndListbox, &rcItem, FALSE );
  4878. }
  4879. /* Size the list in sync with the MDI window
  4880. *
  4881. */
  4882. VOID MDISize( HWND hWnd, DWORD Coordinates )
  4883. {
  4884. PMDIWIN_INFO pMDIWinInfo;
  4885. DWORD cxList, cyList;
  4886. pMDIWinInfo = GETMDIWIN(hWnd);
  4887. cxList = LOWORD(Coordinates);
  4888. cyList = HIWORD(Coordinates) - HeaderHeight;
  4889. SetWindowPos (pMDIWinInfo->hwndHeader, 0, 0, 0, cxList,
  4890. HeaderHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  4891. /* Count partial lines in the list box:
  4892. */
  4893. pMDIWinInfo->cNumLines = ( cyList / STATUS_BITMAP_HEIGHT );
  4894. // Move listbox child window also
  4895. MoveWindow(pMDIWinInfo->hwndList, 0, HeaderHeight,
  4896. cxList, cyList, TRUE);
  4897. }
  4898. /*
  4899. *
  4900. */
  4901. LONG MDIMDIActivate( HWND hwnd, HWND hwndDeactivate, HWND hwndActivate )
  4902. {
  4903. PMDIWIN_INFO pMDIWinInfo;
  4904. DWORD CurSel;
  4905. DWORD TopIndex;
  4906. if( hwnd == hwndActivate )
  4907. {
  4908. pMDIWinInfo = GETMDIWIN(hwnd);
  4909. ENTER_PROTECTED_DATA( pMDIWinInfo );
  4910. if( pMDIWinInfo )
  4911. {
  4912. CurSel = SendMessage( pMDIWinInfo->hwndList, LB_GETCURSEL, 0, 0L );
  4913. TopIndex = SendMessage( pMDIWinInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
  4914. if( ( TopIndex <= CurSel ) && ( CurSel < pMDIWinInfo->cNumLines ) )
  4915. SendMessage( pMDIWinInfo->hwndList, LB_SETCURSEL, CurSel, 0L );
  4916. }
  4917. EnableCheckTBButtons(hwnd);
  4918. UpdateStatus(hwnd);
  4919. LEAVE_PROTECTED_DATA( pMDIWinInfo );
  4920. }
  4921. else if (hwnd == hwndDeactivate){
  4922. pMDIWinInfo = GETMDIWIN(hwnd);
  4923. if (pMDIWinInfo) {
  4924. CurSel = SendMessage( pMDIWinInfo->hwndList, LB_GETCURSEL, 0, 0L);
  4925. SendMessage(pMDIWinInfo->hwndList, LB_SETCURSEL, CurSel, -1);
  4926. }
  4927. }
  4928. return 0;
  4929. }
  4930. /* MDINCActivate
  4931. *
  4932. * Forget about any drag operations that have been started
  4933. * if we're going inactive
  4934. */
  4935. VOID MDINCActivate( HWND hwnd )
  4936. {
  4937. PMDIWIN_INFO pInfo;
  4938. pInfo = GETMDIWIN(hwnd);
  4939. if( !pInfo || ( pInfo->WindowType == MDIWIN_SERVER ) )
  4940. return;
  4941. SendMessage( pInfo->hwndList, WM_RBUTTONDOWN, 0, 0L );
  4942. /* Clear any previous reorder mark:
  4943. */
  4944. ClearDragPosition( pInfo );
  4945. }
  4946. /*
  4947. *
  4948. */
  4949. LONG MDIWindowPosChanged( HWND hwnd, WPARAM wParam, LPARAM lParam )
  4950. {
  4951. HWND hwndActive;
  4952. PMDIWIN_INFO pInfo;
  4953. LONG rc;
  4954. PWINDOWPOS pWindowPos = (PWINDOWPOS)lParam;
  4955. rc = DefMDIChildProc(hwnd, WM_WINDOWPOSCHANGED, wParam, lParam);
  4956. if( !( pWindowPos->flags & SWP_HIDEWINDOW )
  4957. &&( hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L)))
  4958. {
  4959. if( pInfo = GETMDIWIN(hwndActive) )
  4960. {
  4961. ENTER_PROTECTED_DATA(pInfo);
  4962. UpdateStatus(hwndActive);
  4963. LEAVE_PROTECTED_DATA(pInfo);
  4964. }
  4965. }
  4966. return rc;
  4967. }
  4968. /*
  4969. *
  4970. */
  4971. VOID ClearDragPosition( PMDIWIN_INFO pInfo )
  4972. {
  4973. DWORD OldDragPosition;
  4974. if( ( OldDragPosition = pInfo->DragPosition ) != NOSELECTION )
  4975. {
  4976. pInfo->DragPosition = NOSELECTION;
  4977. RepaintListboxItem( pInfo->hwndList, OldDragPosition );
  4978. ENTER_PROTECTED_DATA( pInfo );
  4979. SetEvent( pInfo->RefreshSignal );
  4980. LEAVE_PROTECTED_DATA( pInfo );
  4981. }
  4982. }
  4983. /*
  4984. *
  4985. */
  4986. VOID MDISetFocus( HWND hwnd )
  4987. {
  4988. PMDIWIN_INFO pMDIWinInfo;
  4989. pMDIWinInfo = GETMDIWIN(hwnd);
  4990. /* Ensure that keyboard input will be sent to the listbox:
  4991. */
  4992. SetFocus( pMDIWinInfo->hwndList );
  4993. }
  4994. /*
  4995. *
  4996. */
  4997. VOID MDIMeasureItem( HWND hwnd, LPMEASUREITEMSTRUCT pmis )
  4998. {
  4999. /* For now just specify the bitmap size.
  5000. * This will have to change if font selection becomes a reality:
  5001. */
  5002. pmis->itemHeight = STATUS_BITMAP_HEIGHT;
  5003. }
  5004. #define LEFTMARGIN 2
  5005. #define MAXCOLUMNWIDTH 256
  5006. /*
  5007. *
  5008. */
  5009. VOID MDIDrawItem( HWND hwnd, LPDRAWITEMSTRUCT pdis )
  5010. {
  5011. PMDIWIN_INFO pInfo;
  5012. RECT WindowRect, LineRect;
  5013. PCOLUMN pColumn;
  5014. TCHAR string[MAXCOLUMNWIDTH];
  5015. int i;
  5016. int j;
  5017. PBYTE pData;
  5018. BOOL ThisWindowIsActive;
  5019. BOOL Selected;
  5020. DWORD ColumnLeft;
  5021. pInfo = GETMDIWIN(hwnd);
  5022. if( !pInfo )
  5023. return;
  5024. if( pdis->itemID == (UINT)-1 )
  5025. {
  5026. DrawFocusRect( pdis->hDC, &pdis->rcItem );
  5027. return;
  5028. }
  5029. if( pdis->itemID == 0 )
  5030. pInfo->TopIndex = SendMessage( pdis->hwndItem, LB_GETTOPINDEX, 0, 0 );
  5031. ENTER_PROTECTED_DATA( pInfo );
  5032. GetWindowRect( hwnd, &WindowRect );
  5033. pColumn = pInfo->pColumns;
  5034. i = ( (int)pdis->itemID - (int)*pInfo->pFirstEnumObj );
  5035. /* If we've strayed outside our buffer of jobs, refresh the jobs list:
  5036. */
  5037. if( ( i < 0 ) || ( (DWORD)i >= *pInfo->pcEnumObjs ) )
  5038. {
  5039. DBGMSG( DBG_TRACE, ( "MDIDrawItem calling GetJobs\n" ) );
  5040. /* This should always be true, since we're enumerating
  5041. * all the printers in a Server window:
  5042. */
  5043. if( pInfo->WindowType != MDIWIN_SERVER )
  5044. {
  5045. DWORD TopIndex;
  5046. DWORD dwChangeJob;
  5047. TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
  5048. /* Enumerate a buffer big enough to page up once ...
  5049. */
  5050. *pInfo->pFirstEnumObj = (DWORD)max( 0, (int)TopIndex - (int)pInfo->cNumLines );
  5051. SetCursor( hcursorWait );
  5052. ENTER_PROTECTED_DATA( pInfo );
  5053. dwChangeJob = PRINTER_CHANGE_JOB;
  5054. GetJobs( pInfo->pContext, &dwChangeJob );
  5055. LEAVE_PROTECTED_DATA( pInfo );
  5056. SetCursor( hcursorArrow );
  5057. }
  5058. i = ( (int)pdis->itemID - (int)*pInfo->pFirstEnumObj );
  5059. /* HARMLESS HACK:
  5060. *
  5061. * If there's a lot of scrolling going on at the moment,
  5062. * it sometimes still isn't in sync with the buffer,
  5063. * so bomb out to avoid attempting to reference a job
  5064. * we haven't got:
  5065. */
  5066. if( ( i < 0 ) || ( (DWORD)i >= *pInfo->pcEnumObjs ) )
  5067. {
  5068. LEAVE_PROTECTED_DATA( pInfo );
  5069. return;
  5070. }
  5071. }
  5072. /* Maybe there was some sort of error last time we enumerated.
  5073. * If so, ppData should be NULL. Bomb out:
  5074. */
  5075. if( !*pInfo->ppData )
  5076. {
  5077. LEAVE_PROTECTED_DATA( pInfo );
  5078. return;
  5079. }
  5080. pData = ( *pInfo->ppData + ( (DWORD)i * pInfo->DataSize ) );
  5081. /* See comment on CreateWindowInfo - we need to
  5082. determine whether printer status information is
  5083. being generated by the Status field in JOB_INFO_2
  5084. or the pStatus field in JOB_INFO_2. Also check to
  5085. see that the pInfo window type is not MDIWIN_SERVER
  5086. */
  5087. if (pInfo->WindowType != MDIWIN_SERVER) {
  5088. if (((PJOB_INFO_2)pData)->pStatus != NULL) {
  5089. pInfo->pColumns[MDIHEAD_JOB_STATUS].Offset = offsetof(JOB_INFO_2, pStatus);
  5090. pInfo->pColumns[MDIHEAD_JOB_STATUS].Datatype = MDIDATA_PSZ;
  5091. }
  5092. else {
  5093. pInfo->pColumns[MDIHEAD_JOB_STATUS].Offset = offsetof(JOB_INFO_2, Status);
  5094. pInfo->pColumns[MDIHEAD_JOB_STATUS].Datatype = MDIDATA_JOB_STATUS;
  5095. }
  5096. }
  5097. LineRect = pdis->rcItem;
  5098. ThisWindowIsActive = ( hwnd == (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L) );
  5099. Selected = ( ThisWindowIsActive && ( pdis->itemState & ODS_SELECTED ) );
  5100. /* Special case the status icon and first column:
  5101. */
  5102. DisplayStatusIcon( pdis->hDC, &LineRect, pInfo->WindowType,
  5103. ( pData + pInfo->IconStatus ), Selected );
  5104. /* Pad some blanks at the left of the field:
  5105. */
  5106. for( i = 0; i < LEFTMARGIN; i++ )
  5107. string[i] = SPACE;
  5108. ColumnLeft = 0;
  5109. for( j = 0; j < pInfo->cColumns; j++ )
  5110. {
  5111. FormatData( ( pData + pColumn[j].Offset ), pColumn[j].Datatype, &string[LEFTMARGIN-1] );
  5112. LineRect.left = ColumnLeft;
  5113. if( j == 0 )
  5114. LineRect.left += STATUS_BITMAP_SPACE;
  5115. LineRect.right = ( ColumnLeft + pColumn[j].Width );
  5116. DrawLine( pdis->hDC, &LineRect, string, Selected );
  5117. /* If this is the last column and this is a highlight line,
  5118. * continue the highlight to the right-hand side of the window:
  5119. */
  5120. if( j == ( pInfo->cColumns - 1 ) )
  5121. {
  5122. LineRect.left = LineRect.right;
  5123. LineRect.right = WindowRect.right;
  5124. DrawLine( pdis->hDC, &LineRect, TEXT(""), Selected );
  5125. }
  5126. ColumnLeft += pColumn[j].Width;
  5127. }
  5128. if( pdis->itemState & ODS_FOCUS )
  5129. DrawFocusRect( pdis->hDC, &pdis->rcItem );
  5130. if( ( pInfo->WindowType != MDIWIN_SERVER )
  5131. &&( pdis->itemID == pInfo->DragPosition ) )
  5132. {
  5133. HBRUSH hbr;
  5134. if( hbr = CreateSolidBrush( GetSysColor( COLOR_HIGHLIGHT ) ) )
  5135. {
  5136. LineRect = pdis->rcItem;
  5137. if( pInfo->DragPosition > pInfo->ObjSelected )
  5138. LineRect.top = LineRect.bottom-1;
  5139. else
  5140. LineRect.bottom = LineRect.top+1;
  5141. FrameRect( pdis->hDC, &LineRect, hbr );
  5142. DeleteObject( hbr );
  5143. }
  5144. }
  5145. LEAVE_PROTECTED_DATA( pInfo );
  5146. }
  5147. /*
  5148. *
  5149. */
  5150. VOID MDITimer( HWND hWnd )
  5151. {
  5152. PMDIWIN_INFO pInfo;
  5153. BOOL CheckStatus;
  5154. DWORD OldStatus;
  5155. DWORD NewStatus;
  5156. PQUEUE pQueue;
  5157. BOOL PrinterNameChanged = FALSE;
  5158. pInfo = GETMDIWIN( hWnd );
  5159. if( !pInfo )
  5160. return;
  5161. /* If the status of a printer has changed to/from Paused,
  5162. * we want to update the title (even if it's iconic).
  5163. * This may have happened even though the MDI window
  5164. * isn't active (e.g. through the Server Viewer).
  5165. */
  5166. CheckStatus = ( pInfo->WindowType != MDIWIN_SERVER );
  5167. ENTER_PROTECTED_DATA( pInfo );
  5168. if( CheckStatus )
  5169. {
  5170. pQueue = (PQUEUE)pInfo->pContext;
  5171. if( !pQueue )
  5172. {
  5173. LEAVE_PROTECTED_DATA( pInfo );
  5174. return;
  5175. }
  5176. if( pQueue->pPrinter )
  5177. OldStatus = pQueue->pPrinter->Status;
  5178. else
  5179. OldStatus = PRINTER_STATUS_UNKNOWN;
  5180. }
  5181. if( !IsIconic( hwndFrame )
  5182. // && !pInfo->RefreshSignal && !IsIconic( hWnd )
  5183. /* && IsWindowReallyVisible( hWnd ) */ )
  5184. /* ^^^^^^^^^^^^^^^^^^^^^ watch this space for new API from scottlu */
  5185. {
  5186. if( hWnd == (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L))
  5187. EnableCheckTBButtons(hWnd);
  5188. }
  5189. LEAVE_PROTECTED_DATA( pInfo );
  5190. if( CheckStatus )
  5191. {
  5192. if( pQueue->pPrinter )
  5193. {
  5194. ENTER_PROTECTED_DATA( pInfo );
  5195. if( _tcscmp( pQueue->pPrinterName, pQueue->pPrinter->pPrinterName ) )
  5196. {
  5197. ReallocSplStr( &pQueue->pPrinterName, pQueue->pPrinter->pPrinterName );
  5198. PrinterNameChanged = TRUE;
  5199. }
  5200. NewStatus = pQueue->pPrinter->Status;
  5201. LEAVE_PROTECTED_DATA( pInfo );
  5202. }
  5203. else
  5204. {
  5205. //
  5206. // !! BUGBUG !!
  5207. //
  5208. // This GetLastError() call looks bogus.
  5209. //
  5210. if( GetLastError() == ERROR_ACCESS_DENIED )
  5211. NewStatus = PRINTER_STATUS_ACCESS_DENIED;
  5212. else
  5213. NewStatus = PRINTER_STATUS_UNKNOWN;
  5214. }
  5215. if( ( OldStatus != NewStatus ) || PrinterNameChanged )
  5216. {
  5217. ENTER_PROTECTED_DATA( pInfo );
  5218. SetPrinterTitle( hWnd, pQueue->pPrinterName, NewStatus );
  5219. LEAVE_PROTECTED_DATA( pInfo );
  5220. /* Hack to ensure listbox is redrawn when connexion is re-established:
  5221. */
  5222. if( OldStatus == PRINTER_STATUS_UNKNOWN )
  5223. {
  5224. InvalidateRect( pQueue->pMDIWinInfo->hwndList, NULL, TRUE );
  5225. }
  5226. }
  5227. }
  5228. }
  5229. #ifdef OLDSTUFF
  5230. /*
  5231. *
  5232. */
  5233. VOID MDIStatusChanged( HWND hwnd )
  5234. {
  5235. PMDIWIN_INFO pInfo;
  5236. PQUEUE pQueue;
  5237. pInfo = GETMDIWIN( hwnd );
  5238. if( pInfo->WindowType != MDIWIN_SERVER )
  5239. {
  5240. pQueue = (PQUEUE)pInfo->pContext;
  5241. ENTER_PROTECTED_DATA( pInfo );
  5242. SetPrinterTitle( hwnd, pQueue->pPrinterName,
  5243. pQueue->pPrinter->Status );
  5244. LEAVE_PROTECTED_DATA( pInfo );
  5245. }
  5246. }
  5247. #endif /* OLDSTUFF */
  5248. /*
  5249. *
  5250. */
  5251. VOID MDIUpdateList( HWND hwnd )
  5252. {
  5253. PMDIWIN_INFO pInfo;
  5254. DWORD CurSel;
  5255. BOOL PrinterWasSet = FALSE;
  5256. RECT rcList;
  5257. DWORD TopIndex;
  5258. DWORD BottomIndex;
  5259. pInfo = GETMDIWIN( hwnd );
  5260. DBGMSG( DBG_TRACE, ( "WM_UPDATE_LIST\n" ) );
  5261. ENTER_PROTECTED_DATA( pInfo );
  5262. SendMessage( pInfo->hwndList, WM_SETREDRAW, 0, 0L );
  5263. /* Keep the listbox item count in sync with the number of objects on display:
  5264. */
  5265. if( SendMessage( pInfo->hwndList, LB_GETCOUNT, 0, 0L ) != (int)*pInfo->pcObjects )
  5266. {
  5267. /* We have to go through hoops here since the nodata listbox
  5268. * is so brain dead. When you set the count, it invalidates
  5269. * the list and sets the top index to 0...
  5270. */
  5271. CurSel = SendMessage( pInfo->hwndList, LB_GETCURSEL, 0, 0L );
  5272. SendMessage( pInfo->hwndList, LB_SETCOUNT, *pInfo->pcObjects, 0L );
  5273. SendMessage( pInfo->hwndList, LB_SETCURSEL, CurSel, 0L );
  5274. }
  5275. if( pInfo->ObjSelected == NOSELECTION )
  5276. {
  5277. SendMessage( pInfo->hwndList, LB_SETCURSEL, (WPARAM)-1, 0L );
  5278. }
  5279. /* If the selected item is currently visible, make sure it
  5280. * corresponds to the item that the system thinks is selected:
  5281. */
  5282. else if( ( pInfo->ObjSelected >= *pInfo->pFirstEnumObj )
  5283. &&( pInfo->ObjSelected < ( *pInfo->pFirstEnumObj + pInfo->cNumLines ) )
  5284. &&( SendMessage( pInfo->hwndList, LB_GETCURSEL, 0, 0L )
  5285. != (int)pInfo->ObjSelected ) )
  5286. {
  5287. SendMessage( pInfo->hwndList, LB_SETCURSEL, pInfo->ObjSelected, 0L );
  5288. }
  5289. ValidateRect( pInfo->hwndList, NULL );
  5290. SendMessage( pInfo->hwndList, WM_SETREDRAW, 1, 0L );
  5291. SetMDITitle( hwnd, pInfo );
  5292. /* Don't erase the background for the part of the listbox with items in it,
  5293. * but ensure that the rest is completely redrawn, otherwise we may leave
  5294. * things lying around:
  5295. */
  5296. GetClientRect( pInfo->hwndList, &rcList );
  5297. TopIndex = (DWORD)SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
  5298. DBGMSG( DBG_TRACE, ( "Top Index: %d\n", TopIndex ) );
  5299. if( TopIndex != (DWORD)-1 )
  5300. {
  5301. BottomIndex = ( *pInfo->pcObjects - TopIndex );
  5302. DBGMSG( DBG_TRACE, ( "Bottom Index: %d\n", BottomIndex ) );
  5303. rcList.bottom = min( rcList.bottom,
  5304. (LONG)( BottomIndex * STATUS_BITMAP_HEIGHT ) );
  5305. DBGMSG( DBG_TRACE, ( "Invalidate %d, %d, %d, %d, FALSE\n",
  5306. rcList.left, rcList.top, rcList.right, rcList.bottom ) );
  5307. InvalidateRect( pInfo->hwndList, &rcList, FALSE );
  5308. UpdateWindow( pInfo->hwndList );
  5309. GetClientRect( pInfo->hwndList, &rcList );
  5310. rcList.top = min( rcList.bottom,
  5311. (LONG)( BottomIndex * STATUS_BITMAP_HEIGHT ) );
  5312. }
  5313. DBGMSG( DBG_TRACE, ( "Invalidate %d, %d, %d, %d, TRUE\n",
  5314. rcList.left, rcList.top, rcList.right, rcList.bottom ) );
  5315. InvalidateRect( pInfo->hwndList, &rcList, TRUE );
  5316. UpdateWindow( pInfo->hwndList );
  5317. if( pInfo->hwnd == (HWND)SendMessage( hwndClient, WM_MDIGETACTIVE, 0, 0L ) )
  5318. {
  5319. UpdateStatus( pInfo->hwnd );
  5320. EnableCheckTBButtons( pInfo->hwnd );
  5321. }
  5322. if( (!( pInfo->Changes & PRINTER_CHANGE_TIMEOUT ) )
  5323. &&( pInfo->Changes & PRINTER_CHANGE_SET_PRINTER ) )
  5324. PrinterWasSet = TRUE;
  5325. if( PrinterWasSet )
  5326. UpdateDefaultList();
  5327. LEAVE_PROTECTED_DATA( pInfo );
  5328. /* Ensure that any relevant changes (e.g. port for default printer)
  5329. * get updated in WIN.INI for the benefit of Win31 apps.
  5330. * Do this by faking a change in the default printer.
  5331. * (Fixes bug #6011.)
  5332. *
  5333. * Moved from PrtPropCommandOK().
  5334. */
  5335. //
  5336. // szDefaultPrinter updated in the call to UpdateDefaultList above.
  5337. //
  5338. if( PrinterWasSet )
  5339. ToolbarCommandSelChange(TRUE);
  5340. }
  5341. /* MDISetParts
  5342. *
  5343. * Called after creation to set the column widths.
  5344. * Pass the message on to the header window.
  5345. */
  5346. VOID MDISetParts( HWND hwnd, WPARAM wParam, LPARAM lParam )
  5347. {
  5348. PMDIWIN_INFO pInfo;
  5349. if( pInfo = GETMDIWIN( hwnd ) )
  5350. {
  5351. SendMessage( pInfo->hwndHeader, SB_SETPARTS, wParam, lParam );
  5352. }
  5353. }
  5354. /*
  5355. *
  5356. */
  5357. VOID MDIDestroy( HWND hwnd )
  5358. {
  5359. PMDIWIN_INFO pInfo;
  5360. pInfo = GETMDIWIN( hwnd );
  5361. ENTER_PROTECTED_DATA( pInfo );
  5362. KillMDIWinInfo(pInfo);
  5363. switch( pInfo->WindowType )
  5364. {
  5365. case MDIWIN_LOCALPRINTER:
  5366. case MDIWIN_NETWORKPRINTER:
  5367. case MDIWIN_LOCALNETWORKPRINTER:
  5368. if( ((PQUEUE)(pInfo->pContext))->hPrinter ) {
  5369. ClosePrinter( ((PQUEUE)(pInfo->pContext))->hPrinter );
  5370. ((PQUEUE)(pInfo->pContext))->hPrinter = NULL;
  5371. }
  5372. break;
  5373. case MDIWIN_SERVER:
  5374. if( ((PSERVER_CONTEXT)(pInfo->pContext))->hServer ) {
  5375. ClosePrinter( ((PSERVER_CONTEXT)(pInfo->pContext))->hServer );
  5376. ((PSERVER_CONTEXT)(pInfo->pContext))->hServer = NULL;
  5377. }
  5378. break;
  5379. }
  5380. LEAVE_PROTECTED_DATA( pInfo );
  5381. }
  5382. /*
  5383. *
  5384. */
  5385. LONG MDIDragList( HWND hwnd, LPDRAGLISTINFO pDragInfo )
  5386. {
  5387. PMDIWIN_INFO pInfo;
  5388. PQUEUE pPrinterContext;
  5389. DWORD DragPosition;
  5390. if( !( pInfo = GETMDIWIN( hwnd ) ) )
  5391. return 0;
  5392. if( !( pPrinterContext = pInfo->pContext ) )
  5393. return 0;
  5394. /* You have to be an administrator on the printer to reorder jobs:
  5395. */
  5396. if( !( pPrinterContext->AccessGranted & PRINTER_ACCESS_ADMINISTER ) )
  5397. return 0;
  5398. if( *pInfo->pcObjects < 1 )
  5399. return 0;
  5400. DragPosition = LBItemFromPt( pDragInfo->hWnd, pDragInfo->ptCursor, TRUE );
  5401. switch( pDragInfo->uNotification )
  5402. {
  5403. case DL_BEGINDRAG:
  5404. ENTER_PROTECTED_DATA( pInfo );
  5405. ResetEvent( pInfo->RefreshSignal );
  5406. LEAVE_PROTECTED_DATA( pInfo );
  5407. return -1;
  5408. case DL_DRAGGING:
  5409. if( DragPosition < *pInfo->pcObjects )
  5410. {
  5411. MarkPosition( pInfo, DragPosition );
  5412. SetCursor( hcursorReorder );
  5413. return -1;
  5414. }
  5415. else
  5416. return DL_STOPCURSOR;
  5417. case DL_DROPPED:
  5418. if( DragPosition != pInfo->ObjSelected )
  5419. ReorderJob( hwnd, pInfo, DragPosition );
  5420. // drop through...
  5421. case DL_CANCELDRAG:
  5422. MarkPosition( pInfo, NOSELECTION );
  5423. ENTER_PROTECTED_DATA( pInfo );
  5424. SetEvent( pInfo->RefreshSignal );
  5425. LEAVE_PROTECTED_DATA( pInfo );
  5426. }
  5427. return 0;
  5428. }
  5429. VOID SubclassListboxKeyDown( HWND hwnd, INT VKey );
  5430. VOID SubclassListboxKeyUp( HWND hwnd, INT VKey );
  5431. /* Subclass window procedure for MDI printer listbox containing jobs.
  5432. * Server viewers are not subclassed.
  5433. */
  5434. long SubclassListboxWndProc(
  5435. HWND hwnd,
  5436. UINT message,
  5437. WPARAM wParam,
  5438. LONG lParam
  5439. )
  5440. {
  5441. switch( message )
  5442. {
  5443. case WM_KEYDOWN:
  5444. SubclassListboxKeyDown( hwnd, (INT)wParam );
  5445. break;
  5446. case WM_KEYUP:
  5447. SubclassListboxKeyUp( hwnd, (INT)wParam );
  5448. break;
  5449. }
  5450. return CallWindowProc( DefListboxWndProc, hwnd, message, wParam, lParam );
  5451. }
  5452. /* This catches the delete key being pressed.
  5453. * If there is a job selected, go ahead and delete it.
  5454. * We don't respond if a printer currently has the focus.
  5455. */
  5456. VOID SubclassListboxKeyDown( HWND hwnd, INT VKey )
  5457. {
  5458. PMDIWIN_INFO pInfo;
  5459. if( VKey == VK_DELETE )
  5460. {
  5461. pInfo = GETMDIWIN( GetParent( hwnd ) );
  5462. if( !pInfo )
  5463. return;
  5464. /* If there's a current selection, fake a Remove Document command:
  5465. */
  5466. if( pInfo->ObjSelected != NOSELECTION )
  5467. SendMessage( hwndFrame, WM_COMMAND,
  5468. MAKEWPARAM( IDM_REMOVEDOC, 0 ), 0 );
  5469. }
  5470. }
  5471. /* This handles the case where the user releases the control key
  5472. * whilst dragging a job using the cursor keys.
  5473. * This completes the drag operation.
  5474. */
  5475. VOID SubclassListboxKeyUp( HWND hwnd, INT VKey )
  5476. {
  5477. PMDIWIN_INFO pInfo;
  5478. DWORD NewPos;
  5479. if( VKey == VK_CONTROL )
  5480. {
  5481. pInfo = GETMDIWIN( GetParent( hwnd ) );
  5482. if( !pInfo )
  5483. return;
  5484. if( ( pInfo->DragPosition != NOSELECTION )
  5485. &&( pInfo->ObjSelected != pInfo->DragPosition ) )
  5486. {
  5487. NewPos = pInfo->DragPosition;
  5488. ReorderJob( GetParent( hwnd ), pInfo, pInfo->DragPosition );
  5489. MarkPosition( pInfo, NOSELECTION );
  5490. SETLISTSELECT( GetParent( hwnd ), ID_OBJLIST, NewPos );
  5491. SetEvent( pInfo->RefreshSignal );
  5492. LEAVE_PROTECTED_DATA( pInfo );
  5493. }
  5494. }
  5495. }
  5496. VOID
  5497. Refresh(
  5498. HWND hwnd,
  5499. PMDIWIN_INFO pInfo,
  5500. DWORD RepaintOption)
  5501. {
  5502. DWORD Changed;
  5503. DWORD TopIndex;
  5504. DWORD MutexStatus;
  5505. if( !pInfo )
  5506. return;
  5507. if (pInfo->WindowType == MDIWIN_SERVER) {
  5508. /* This can't happen, we've grayed out the menu-item for
  5509. * server mdi windows. Anyway, let's bomb out
  5510. */
  5511. return;
  5512. }
  5513. //
  5514. // If still loading, return now since the worker thread
  5515. // is initializing and will refresh when it can.
  5516. //
  5517. if (pInfo->Status & PRINTER_STATUS_LOADING)
  5518. return;
  5519. /* access protected area of pInfo with "zero"
  5520. * timeout. if we couldn't access, then quit here
  5521. * RefreshThread is in the middle of an update.
  5522. * let it take care of the refreshing.
  5523. */
  5524. MutexStatus = WaitForSingleObject(pInfo->DataMutex, 0);
  5525. if (MutexStatus == -1) {
  5526. // Couldn't acquire the mutex
  5527. return;
  5528. }
  5529. if (MutexStatus == WAIT_TIMEOUT) {
  5530. /* This means RefreshThread has ownership of the
  5531. mutex -- it will take care of updating -- return
  5532. */
  5533. return;
  5534. }
  5535. /* We own the DataMutex at this point */
  5536. TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
  5537. /* Enumerate a buffer big enough to page up once ...
  5538. */
  5539. *pInfo->pFirstEnumObj = (DWORD)max( 0, (int)TopIndex - (int)pInfo->cNumLines );
  5540. SetCursor( hcursorWait );
  5541. ENTER_PROTECTED_DATA(pInfo);
  5542. if( pInfo->pfnRefresh )
  5543. {
  5544. //
  5545. // *pInfo->phWaitObject should be NULL if the OpenPrinter
  5546. // fails... but OpenPrinter will succeed even if the
  5547. // remote printer is not available (probably for winword),
  5548. // So add unknown here also.
  5549. //
  5550. if (pInfo->Status & PRINTER_STATUS_UNKNOWN ||
  5551. !*pInfo->phWaitObject)
  5552. {
  5553. //
  5554. // We have an unknown connection; try and reopen
  5555. // when refresh, in case the admin gave us
  5556. // access recently. Or possibly the net was down...
  5557. //
  5558. if (*pInfo->phWaitObject) {
  5559. ClosePrinter(*pInfo->phWaitObject);
  5560. *pInfo->phWaitObject = NULL;
  5561. }
  5562. ReopenPrinter( pInfo->pContext, pInfo->WindowType, TRUE );
  5563. }
  5564. Changed = PRINTER_CHANGE_JOB|PRINTER_CHANGE_PRINTER;
  5565. (*pInfo->pfnRefresh)( pInfo->pContext, &Changed );
  5566. }
  5567. LEAVE_PROTECTED_DATA(pInfo);
  5568. SetCursor( hcursorArrow );
  5569. /* REPAINT_FORCE makes sense only when we definitely want the list
  5570. * to repaint even if there have been no changes to its contents.
  5571. * The only time this should happen is when the refresh is in response
  5572. * to the user's selecting the Refresh menu option:
  5573. */
  5574. if( ( Changed && ( RepaintOption == REPAINT_IF_CHANGED ) )
  5575. ||( RepaintOption == REPAINT_FORCE ) )
  5576. {
  5577. /* Keep the listbox item count in sync with the number of objects on display:
  5578. * Originally, this code was duplicating the MDIUpdateList function. So let's just
  5579. * send a WM_UPDATELIST message to the MDI window to take care of the rest.
  5580. */
  5581. PostMessage(pInfo->hwnd, WM_UPDATE_LIST, (WPARAM)pInfo, 0L);
  5582. }
  5583. ReleaseMutex(pInfo->DataMutex);
  5584. return;
  5585. }
  5586. /*
  5587. *
  5588. */
  5589. BOOL
  5590. RefreshServerContext(
  5591. PVOID pContext,
  5592. PDWORD pFlags )
  5593. {
  5594. PSERVER_CONTEXT pServerContext;
  5595. LPTSTR pCurrentSelection = NULL;
  5596. DWORD Error = NO_ERROR;
  5597. pServerContext = (PSERVER_CONTEXT)pContext;
  5598. ENTER_PROTECTED_DATA( pServerContext->pMDIWinInfo );
  5599. //
  5600. // Don't change the default printer here since the set printer
  5601. // was remote.
  5602. //
  5603. *pFlags &= ~PRINTER_CHANGE_SET_PRINTER;
  5604. /* We may end up having to reallocate the buffer, so make sure we keep track
  5605. * of the name of the currently selected printer:
  5606. */
  5607. if( pServerContext->pSelPrinter )
  5608. pCurrentSelection = AllocSplStr( pServerContext->pSelPrinter->pPrinterName );
  5609. if( ENUM_PRINTERS( PRINTER_ENUM_NAME,
  5610. pServerContext->pServerName,
  5611. 2,
  5612. pServerContext->pPrinters,
  5613. pServerContext->cbPrinters,
  5614. &pServerContext->cbPrinters,
  5615. &pServerContext->cPrinters ) )
  5616. {
  5617. DWORD i = 0;
  5618. pServerContext->cEnumPrinters = pServerContext->cPrinters;
  5619. /* Find the printer name that matches the current selection:
  5620. */
  5621. if( pCurrentSelection )
  5622. {
  5623. while( ( i < pServerContext->cPrinters )
  5624. && _tcscmp( pServerContext->pPrinters[i].pPrinterName,
  5625. pCurrentSelection ) )
  5626. i++;
  5627. }
  5628. if( i < pServerContext->cPrinters )
  5629. {
  5630. pServerContext->pSelPrinter = &pServerContext->pPrinters[i];
  5631. pServerContext->SelPrinterId = i;
  5632. pServerContext->pMDIWinInfo->ObjSelected = i;
  5633. }
  5634. else
  5635. {
  5636. pServerContext->pSelPrinter = &pServerContext->pPrinters[0];
  5637. pServerContext->SelPrinterId = 0;
  5638. }
  5639. }
  5640. else
  5641. {
  5642. pServerContext->SelPrinterId = 0;
  5643. pServerContext->pSelPrinter = NULL;
  5644. pServerContext->pMDIWinInfo->ObjSelected = NOSELECTION;
  5645. Error = GetLastError( );
  5646. }
  5647. if( pCurrentSelection )
  5648. FreeSplStr( pCurrentSelection );
  5649. pServerContext->Error = Error;
  5650. LEAVE_PROTECTED_DATA( pServerContext->pMDIWinInfo );
  5651. return ( Error == NO_ERROR );
  5652. }
  5653. /* Message
  5654. *
  5655. * Displays a message by loading the strings whose IDs are passed into
  5656. * the function, and substituting the supplied variable argument list
  5657. * using the varargs macros.
  5658. *
  5659. */
  5660. int Message(HWND hwnd, DWORD Type, int CaptionID, int TextID, ...)
  5661. {
  5662. TCHAR MsgText[MAX_PATH*2];
  5663. TCHAR MsgFormat[520];
  5664. TCHAR MsgCaption[80];
  5665. va_list vargs;
  5666. if( ( LoadString( hInst, TextID, MsgFormat,
  5667. sizeof MsgFormat / sizeof *MsgFormat ) > 0 )
  5668. && ( LoadString( hInst, CaptionID, MsgCaption,
  5669. sizeof MsgCaption / sizeof *MsgCaption ) > 0 ) )
  5670. {
  5671. va_start( vargs, TextID );
  5672. wvsprintf( MsgText, MsgFormat, vargs );
  5673. va_end( vargs );
  5674. return MessageBox(hwnd, MsgText, MsgCaption, Type);
  5675. }
  5676. else
  5677. return 0;
  5678. }
  5679. FARPROC LoadLibraryGetProcAddress(HWND hwnd, LPTSTR LibraryName, LPCSTR ProcName,
  5680. PHANDLE phLibrary)
  5681. {
  5682. HANDLE hLibrary;
  5683. FARPROC lpfn = NULL;
  5684. hLibrary = LoadLibrary(LibraryName);
  5685. if(hLibrary)
  5686. {
  5687. lpfn = GetProcAddress(hLibrary, ProcName);
  5688. if(!lpfn)
  5689. {
  5690. Message(hwnd, MSG_ERROR, IDS_PRINTMANAGER,
  5691. IDS_COULDNOTFINDPROCEDURE, ProcName, LibraryName);
  5692. FreeLibrary(hLibrary);
  5693. }
  5694. }
  5695. else
  5696. Message(hwnd, MSG_ERROR, IDS_PRINTMANAGER,
  5697. IDS_COULDNOTLOADLIBRARY, LibraryName);
  5698. *phLibrary = hLibrary;
  5699. return lpfn;
  5700. }
  5701. /* Returns the positions saved in the registry of windows and headers.
  5702. * Return code is TRUE if the information is found, FALSE otherwise.
  5703. * If there is no information found, default values are substituted
  5704. * for the window position, but no default header values are assigned.
  5705. *
  5706. */
  5707. BOOL GetSavedWindowPos( LPTSTR pKey, LPTSTR WindowName, PSAVEDWINDOWPOS pswp,
  5708. DWORD cHeaders, PINT pHeaders )
  5709. {
  5710. PREGISTRY_DATA pRegistryData;
  5711. DWORD cbRegistryData;
  5712. DWORD rc;
  5713. DWORD i;
  5714. PINT pint;
  5715. /* Get the size of the fixed part of the registry data:
  5716. */
  5717. cbRegistryData = ( sizeof( REGISTRY_DATA ) - sizeof( pRegistryData->Headers ) );
  5718. cbRegistryData += ( cHeaders * sizeof( pRegistryData->Headers ) );
  5719. pRegistryData = AllocSplMem( cbRegistryData );
  5720. RegistryEntries.Size = cbRegistryData;
  5721. rc = ReadRegistryData( pKey, WindowName, (LPBYTE)pRegistryData, &RegistryEntries );
  5722. if( rc == NO_ERROR )
  5723. {
  5724. pswp->left = pRegistryData->WindowPlacement.rcNormalPosition.left;
  5725. pswp->top = pRegistryData->WindowPlacement.rcNormalPosition.top;
  5726. pswp->width = pRegistryData->WindowPlacement.rcNormalPosition.right - pswp->left;
  5727. pswp->height = pRegistryData->WindowPlacement.rcNormalPosition.bottom - pswp->top;
  5728. pswp->xicon = pRegistryData->WindowPlacement.ptMinPosition.x;
  5729. pswp->yicon = pRegistryData->WindowPlacement.ptMinPosition.y;
  5730. pswp->sw = pRegistryData->WindowPlacement.showCmd;
  5731. pswp->options = pRegistryData->Options;
  5732. for( i = 0; i < cHeaders; i++ )
  5733. pHeaders[i] = pRegistryData->Headers[i];
  5734. }
  5735. else
  5736. {
  5737. /* No data retrieved from the registry:
  5738. * Substitute default values:
  5739. */
  5740. pint = (PINT)pswp;
  5741. for( i = 0; i < RECTSIDES; i++ )
  5742. pint[i] = CW_USEDEFAULT;
  5743. for( i = RECTSIDES; i < INIVALUES; i++ )
  5744. pint[i] = 0;
  5745. pswp->sw = SW_NORMAL;
  5746. }
  5747. FreeSplMem( pRegistryData );
  5748. return ( rc == NO_ERROR );
  5749. }
  5750. // int _CRTAPI1
  5751. HWND GetRealParent( HWND hwnd )
  5752. {
  5753. // run up the parent chain until you find a hwnd
  5754. // that doesn't have WS_CHILD set
  5755. while( GetWindowLong( hwnd, GWL_STYLE ) & WS_CHILD )
  5756. hwnd = (HWND)GetWindowLong( hwnd, GWL_HWNDPARENT );
  5757. return hwnd;
  5758. }
  5759. #ifdef OLDSTUFF
  5760. /* MessageProc
  5761. *
  5762. * This is the callback routine which hooks F1 keypresses in menus and dialog boxes.
  5763. *
  5764. * Any such message will be repackaged as a WM_Help message and sent to the frame.
  5765. *
  5766. * Two codes are handled:
  5767. *
  5768. * MSGF_MENU - In this case, the message originates in a menu item,
  5769. * and the hwnd parameter of pMsg contains the menu handle.
  5770. * We get the ID of the currently selected menu item.
  5771. *
  5772. * MSGF_DIALOGBOX - In this case, the message originates in a dialog box,
  5773. * and the hwnd parameter of pMsg contains the dialog item handle.
  5774. * We get its control ID.
  5775. *
  5776. *
  5777. * See the Win32 API programming reference for a description of how this
  5778. * routine works.
  5779. *
  5780. * Andrew Bell (andrewbe) - 2 September 1992
  5781. */
  5782. LRESULT CALLBACK MessageProc( int Code, WPARAM wParam, LPARAM lParam )
  5783. {
  5784. PMSG pMsg = (PMSG)lParam;
  5785. if( Code < 0 )
  5786. return CallNextHookEx( hhookMessage, Code, wParam, lParam );
  5787. switch( Code )
  5788. {
  5789. case MSGF_MENU:
  5790. if( ( pMsg->message == WM_KEYDOWN ) && ( pMsg->wParam == VK_F1 ) )
  5791. {
  5792. PostMessage( hwndFrame, WM_Help, (LPARAM)pMsg->hwnd,
  5793. WinHelpMenuID );
  5794. // GetCurrentMenuItemID( GetMenu( hwndFrame ) ) );
  5795. return 1;
  5796. }
  5797. break;
  5798. case MSGF_DIALOGBOX:
  5799. if( ( pMsg->message == WM_KEYDOWN ) && ( pMsg->wParam == VK_F1 ) )
  5800. {
  5801. PostMessage( GetRealParent( pMsg->hwnd ), WM_Help, (WPARAM)pMsg->hwnd, 0 );
  5802. return 1;
  5803. }
  5804. break;
  5805. }
  5806. return 0;
  5807. }
  5808. #endif /* OLDSTUFF */
  5809. /* GetMsgProc
  5810. *
  5811. * This is the callback routine which hooks F1 keypresses.
  5812. *
  5813. * Any such message will be repackaged as a WM_Help message and sent to the
  5814. * top window, which may be the frame window or a dialog box.
  5815. *
  5816. * See the Win32 API programming reference for a description of how this
  5817. * routine works.
  5818. *
  5819. * Changed from previous MessageProc so that F1 in the Default Printer combo
  5820. * will also be hooked.
  5821. *
  5822. * Andrew Bell (andrewbe) - 4 February 1993
  5823. */
  5824. LRESULT CALLBACK GetMsgProc( int Code, WPARAM wParam, LPARAM lParam )
  5825. {
  5826. PMSG pMsg = (PMSG)lParam;
  5827. if( Code < 0 )
  5828. return CallNextHookEx( hhookGetMsg, Code, wParam, lParam );
  5829. if( ( pMsg->message == WM_KEYDOWN ) && ( pMsg->wParam == VK_F1 ) )
  5830. {
  5831. PostMessage( GetRealParent( pMsg->hwnd ), WM_Help,
  5832. (LPARAM)pMsg->hwnd, WinHelpMenuID );
  5833. }
  5834. return 0;
  5835. }
  5836. /* GetCurrentMenuItemID
  5837. *
  5838. * Returns the ID of the currently selected item in a menu.
  5839. *
  5840. * There's no easy way to do this, unfortunately, so we have to enumerate
  5841. * all the menu items until we find one with the MF_HILITE flag set.
  5842. *
  5843. * The routine scans only one level of menus, so you'll have to modify
  5844. * it if you want to use it for multiple-level menus.
  5845. *
  5846. * Parameter:
  5847. *
  5848. * hMenu - The handle of the menu to be searched.
  5849. *
  5850. * Returns:
  5851. *
  5852. * The ID of the highlighted menu item,
  5853. * or 0 if no highlighted item was found or if an error occurred.
  5854. *
  5855. * Andrew Bell (andrewbe) - 2 September 1992
  5856. */
  5857. UINT GetCurrentMenuItemID( HMENU hMenu )
  5858. {
  5859. UINT MenuItemID = 0;
  5860. int MenuItemCount, iMain;
  5861. int SubMenuItemCount, iSub;
  5862. HMENU hSubMenu;
  5863. UINT MenuState;
  5864. /* Find out how many top-level pull-downs there are:
  5865. */
  5866. MenuItemCount = GetMenuItemCount( hMenu );
  5867. /* If there was an error, just set the count to zero,
  5868. * and it will fall through:
  5869. */
  5870. if( MenuItemCount == -1 )
  5871. MenuItemCount = 0;
  5872. iMain = 0;
  5873. /* Now go through each pull-down until we find a selected item:
  5874. */
  5875. while( ( MenuItemID == 0 ) && ( iMain < MenuItemCount ) )
  5876. {
  5877. hSubMenu = GetSubMenu( hMenu, iMain );
  5878. SubMenuItemCount = GetMenuItemCount( hSubMenu );
  5879. if( SubMenuItemCount == -1 )
  5880. SubMenuItemCount = 0;
  5881. iSub = 0;
  5882. while( ( MenuItemID == 0 ) && ( iSub < SubMenuItemCount ) )
  5883. {
  5884. MenuState = GetMenuState( hSubMenu, iSub, MF_BYPOSITION );
  5885. if( MenuState != (UINT)-1 )
  5886. {
  5887. if( (BYTE)MenuState & MF_HILITE )
  5888. {
  5889. MenuItemID = GetMenuItemID( hSubMenu, iSub );
  5890. /* Hack for MDI windows listed under "Window".
  5891. * Return the generic help ID:
  5892. */
  5893. if( ( iMain == POPUP_WINDOW )
  5894. &&( ( MenuItemID < IDM_CASCADE )
  5895. || ( MenuItemID > IDM_REFRESH ) ) )
  5896. MenuItemID = ID_HELP_MDIWINDOW;
  5897. }
  5898. }
  5899. iSub++;
  5900. }
  5901. iMain++;
  5902. }
  5903. return MenuItemID;
  5904. }
  5905. VOID
  5906. KillMDIWinInfo( PMDIWIN_INFO pInfo)
  5907. {
  5908. pInfo->Alive = FALSE;
  5909. }
  5910. /* Checks to see whether there is already an instance of Print Manager running.
  5911. * If so, it brings it to the foreground and returns TRUE.
  5912. *
  5913. * Body of the function borrowed from WinFile.
  5914. */
  5915. BOOL PreviousPrintManagerInstanceFound( )
  5916. {
  5917. HWND hwndPrev;
  5918. HWND hwnd;
  5919. hwndPrev = FindWindow (szPrintManagerClass, NULL);
  5920. if (hwndPrev != NULL)
  5921. {
  5922. hwnd = GetLastActivePopup(hwndPrev);
  5923. if (IsIconic(hwndPrev))
  5924. ShowWindow (hwndPrev, SW_RESTORE);
  5925. SetForegroundWindow (hwnd);
  5926. return TRUE;
  5927. }
  5928. return FALSE;
  5929. }
  5930. #define WAIT_OBJECT_MESSAGE_WRITTEN 0
  5931. #define WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE 1
  5932. #define WAIT_OBJECT_COUNT 2
  5933. int
  5934. #if !defined(_MIPS_) && !defined(_ALPHA_) && !defined(_PPC_)
  5935. _cdecl
  5936. #endif
  5937. main(
  5938. unsigned argc,
  5939. CHAR **argv
  5940. )
  5941. {
  5942. MSG msg;
  5943. HANDLE hInstance = NULL;
  5944. HANDLE hAccel;
  5945. SAVEDWINDOWPOS swp;
  5946. PRINTMAN_DATA PrintManData;
  5947. TCHAR strPrintManager[40];
  5948. DWORD EventId;
  5949. BOOL Quit = FALSE;
  5950. REGISTRY_ENTRY RegistrySaveSettings = { REG_DWORD, sizeof(DWORD) };
  5951. TCHAR SaveSettings[40];
  5952. HANDLE hWaitObjects[WAIT_OBJECT_COUNT];
  5953. HKEY hWindowsKey;
  5954. LCID lcid;
  5955. TCHAR szSystemDir[MAX_PATH];
  5956. STARTUPINFO si;
  5957. WCHAR Buffer[128];
  5958. #ifdef HEAPCHECK
  5959. HeapCheckInit();
  5960. #endif
  5961. lcid = GetThreadLocale();
  5962. bJapan = (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE);
  5963. if( PreviousPrintManagerInstanceFound( ) )
  5964. return FALSE;
  5965. ThousandSeparator = TEXT(',');
  5966. if (GetLocaleInfoW (lcid, LOCALE_STHOUSAND, Buffer, 128)) {
  5967. ThousandSeparator = Buffer[0];
  5968. }
  5969. hInstance = GetModuleHandle (NULL);
  5970. if (!InitApplication(hInstance, &hAccel))
  5971. return(FALSE);
  5972. // Might as well open the registry key now.
  5973. RegCreateKeyEx(HKEY_CURRENT_USER, szRegistryPrinter, 0, NULL, 0,
  5974. KEY_READ | KEY_WRITE, NULL, &hPrinterKey, NULL);
  5975. // Create the main Print Manager frame window
  5976. LoadString(hInstance, IDS_PRINTMANAGER, strPrintManager,
  5977. sizeof(strPrintManager) / sizeof(*strPrintManager));
  5978. GetSavedWindowPos( NULL, strPrintManager, &swp, 0, NULL );
  5979. bToolBar = !( swp.options & OPTION_NOTOOLBAR );
  5980. bStatusBar = !( swp.options & OPTION_NOSTATUSBAR );
  5981. bSaveSettings = TRUE;
  5982. LoadString(hInstance, IDS_SAVE_SETTINGS, SaveSettings,
  5983. sizeof SaveSettings / sizeof *SaveSettings);
  5984. ReadRegistryData( NULL, SaveSettings,
  5985. (LPBYTE)&bSaveSettings,
  5986. &RegistrySaveSettings );
  5987. hhookGetMsg = SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc, NULL,
  5988. GetCurrentThreadId( ) );
  5989. WM_Help = RegisterWindowMessage( TEXT("Print Manager Help Message") );
  5990. CreateWindow(szPrintManagerClass, strPrintManager,
  5991. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  5992. swp.left, swp.top, swp.width, swp.height,
  5993. NULL, NULL, hInstance, &PrintManData);
  5994. if (GetSystemDirectory(szSystemDir,
  5995. sizeof(szSystemDir)/sizeof(szSystemDir[0]))) {
  5996. SetCurrentDirectory(szSystemDir);
  5997. }
  5998. // Let the program manager over ride the saved window position
  5999. GetStartupInfo(&si);
  6000. if (si.wShowWindow == SW_MINIMIZE || si.wShowWindow == SW_SHOWMINNOACTIVE) {
  6001. ShowWindow(hwndFrame, si.wShowWindow);
  6002. } else {
  6003. ShowWindow(hwndFrame, swp.sw);
  6004. }
  6005. UpdateWindow(hwndFrame);
  6006. hWaitObjects[WAIT_OBJECT_MESSAGE_WRITTEN] = ThreadMessageWritten;
  6007. hWaitObjects[WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE] =
  6008. CreateEvent( NULL,
  6009. EVENT_RESET_AUTOMATIC,
  6010. EVENT_INITIAL_STATE_NOT_SIGNALED,
  6011. NULL );
  6012. if( RegOpenKey( HKEY_CURRENT_USER,
  6013. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"),
  6014. &hWindowsKey ) != NO_ERROR )
  6015. {
  6016. DBGMSG( DBG_WARNING, ( "RegOpenKey failed\n" ) );
  6017. }
  6018. /* Ask for notification of changes to last write time of registry key.
  6019. * Empirically found to work. I'm buggered if I know why this works,
  6020. * whereas REG_NOTIFY_CHANGE_ATTRIBUTES and REG_NOTIFY_CHANGE_NAME
  6021. * don't seem to have any effect.
  6022. */
  6023. if( RegNotifyChangeKeyValue( hWindowsKey, FALSE, REG_NOTIFY_CHANGE_LAST_SET,
  6024. hWaitObjects[WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE],
  6025. TRUE ) != NO_ERROR )
  6026. {
  6027. DBGMSG( DBG_WARNING, ( "RegNotifyChangeKeyValue failed\n" ) );
  6028. }
  6029. while( ( Quit == FALSE )
  6030. &&( ( EventId = MsgWaitForMultipleObjects( WAIT_OBJECT_COUNT,
  6031. hWaitObjects,
  6032. FALSE,
  6033. INFINITE,
  6034. QS_ALLEVENTS | QS_SENDMESSAGE
  6035. ) ) != (DWORD)-1 ) )
  6036. {
  6037. if( EventId == WAIT_OBJECT_0 + WAIT_OBJECT_MESSAGE_WRITTEN )
  6038. {
  6039. DBGMSG( DBG_TRACE, ( "Dispatching message %08x\n", ThreadMessage.message ) );
  6040. DISPATCH_THREAD_MESSAGE( &ThreadMessage );
  6041. }
  6042. else if( EventId == ( WAIT_OBJECT_0 + WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE ) )
  6043. {
  6044. if( !ExpectingNotifyChangeKeyValue )
  6045. {
  6046. DBGMSG( DBG_TRACE, ( "NotifyChangeKeyValue received\n" ) );
  6047. PostMessage( hwndFrame, WM_REG_NOTIFY_CHANGE_KEY_VALUE, (WPARAM)hWindowsKey, 0 );
  6048. }
  6049. else
  6050. {
  6051. DBGMSG( DBG_TRACE, ( "NotifyChangeKeyValue received (expected)\n" ) );
  6052. ExpectingNotifyChangeKeyValue = FALSE;
  6053. }
  6054. RegNotifyChangeKeyValue( hWindowsKey, FALSE, REG_NOTIFY_CHANGE_LAST_SET,
  6055. hWaitObjects[WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE],
  6056. TRUE );
  6057. }
  6058. else
  6059. {
  6060. while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  6061. {
  6062. //
  6063. // since we use RETURN as an accelerator we have to manually
  6064. // restore ourselves when we see VK_RETURN and we are minimized
  6065. //
  6066. if (msg.message == WM_SYSKEYDOWN &&
  6067. msg.wParam == VK_RETURN &&
  6068. IsIconic(hwndFrame))
  6069. {
  6070. ShowWindow(hwndFrame, SW_NORMAL);
  6071. }
  6072. else if( !TranslateMDISysAccel( hwndClient, &msg ) &&
  6073. !TranslateAccelerator( hwndFrame, hAccel, &msg ) )
  6074. {
  6075. TranslateMessage( &msg );
  6076. DispatchMessage( &msg );
  6077. }
  6078. if( msg.message == WM_QUIT )
  6079. {
  6080. Quit = TRUE;
  6081. break;
  6082. }
  6083. }
  6084. }
  6085. }
  6086. CloseHandle( ThreadMessageWritten );
  6087. CloseHandle( ThreadMessageRead );
  6088. RegCloseKey(hWindowsKey);
  6089. RegCloseKey(hPrinterKey);
  6090. #ifdef HEAPCHECK
  6091. HeapCheckDump(0);
  6092. HeapCheckDestroy();
  6093. #endif
  6094. return msg.wParam;
  6095. UNREFERENCED_PARAMETER(argc);
  6096. UNREFERENCED_PARAMETER(argv);
  6097. }