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

/*---File: printman.c ----------------------------------------------------
*
* Description:
* NT Print Manager main function and Window Procedures.
*
* This document contains confidential/proprietary information.
* Copyright (c) 1990-1992 Microsoft Corporation, All Rights Reserved.
*
* Revision History:
* [00] 21-Nov-90 stevecat created
* [01] 03-Jan-91 stevecat Modified to use Windows MDI
* [02] 25-Mar-91 stevecat Modified to use NT WINSPOOL APIs
* [03] 13-Jan-92 stevecat New PrintMan UI
*
* March 1992 + andrewbe Completely updated and new function added
*
* ---------------------------------------------------------------------- */
/* =========================================================================
Header files
========================================================================= */
/* Application-specific */
#include "printman.h"
#include <lmcons.h>
#include <lmerr.h>
#include <uiexport.h>
#include <stdarg.h>
#include <winuserp.h>
#include <shellapi.h>
#include <stddef.h>
/* ========================================================================
Definitions
======================================================================== */
#define ISF_NAME 0
#define ISF_STATUS 1
#define ISF_WAITING 2
#define SF_COUNT 3
#define SW2WS( sw ) \
( sw == SW_SHOWMINIMIZED ? WS_MINIMIZE \
: sw == SW_SHOWMAXIMIZED ? WS_MAXIMIZE \
: 0 )
#define INIVALUES 8
#define RECTSIDES 4
#define OPTION_NOTOOLBAR 0x00000001
#define OPTION_NOSTATUSBAR 0x00000002
#define OPTION_NOSAVESETTINGS 0x00000004
/* Define our own IDs for menu popups, since USER doesn't:
*/
#define POPUP_PRINTER 0
#define POPUP_DOCUMENT 1
#define POPUP_OPTIONS 2
#define POPUP_SECURITY 3
#define POPUP_WINDOW 4
#define POPUP_HELP 5
#define POPUP_COUNT 6
#define GETMDIWIN( hwnd ) \
(PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN )
#define GETCONTEXT( hwnd ) \
( (PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN ) )->pContext
#define GETQUEUE( hwnd ) \
(PQUEUE)( (PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN ) )->pContext
#define GETCOLUMN(hwnd) \
( (PMDIWIN_INFO)GetWindowLong( hwnd, GWL_PMDIWIN ) )->pColumns
#define STATUS_MODE_NORMAL 0
#define STATUS_MODE_HELP 1
#define WM_INIT_PRINTER_WINDOWS WM_USER+0xa
#define WM_INIT_SERVER_WINDOWS WM_USER+0xb
#define WM_REG_NOTIFY_CHANGE_KEY_VALUE WM_USER+0xc
/*
* Declarations for external calls
* -------------------------------
*/
/* ========================================================================
Structures and Typedefs
======================================================================== */
typedef struct _SAVEDWINDOWPOS
{
int left;
int top;
int width;
int height;
int xicon;
int yicon;
int sw;
DWORD options;
}
SAVEDWINDOWPOS, *PSAVEDWINDOWPOS;
typedef struct _REGISTRY_DATA
{
WINDOWPLACEMENT WindowPlacement;
DWORD Options;
INT Headers[ANYSIZE_ARRAY];
}
REGISTRY_DATA, *PREGISTRY_DATA;
/* ==========================================================================
Global Data
========================================================================== */
#if DBG
DWORD GLOBAL_DEBUG_FLAGS = DBG_ERROR | DBG_WARNING | DBG_BREAK_ON_ERROR;
#endif
TCHAR szPrintManagerClass[] = TEXT("Print Manager Frame");
TCHAR szMenuClass[] = TEXT("PrintManMenu"); // This must match the name in res.rc
TCHAR szChildClass[] = TEXT("Printer MDI Child");
// External functions
BOOL RegisterArrowClass (HANDLE hModule);
// Data
TCHAR szNtLanMan[] = TEXT("NTLANMAN");
CHAR szI_SystemFocusDialog[] = "I_SystemFocusDialog";
BOOL bToolBar;
BOOL bStatusBar;
BOOL bSaveSettings;
//TCHAR szStatusBar[] = TEXT("StatusBar");
int dyBorder; /* System Border Width/Height */
int dyBorderx2; /* System Border Width/Height * 2 */
//int dyStatus; /* Status Bar height */
int dxStatusField;
int dxStatPrtField; // Width of strStatusName text box
int dxStatProgField; // Width of strStatusStatus text box
int dxStatQueField; // Width of strStatusWaiting text box
DWORD cx, cy; // Average char width/height - default font
int dxDefaultLabel;
int dyDefaultLabel;
HBITMAP hbmBitmaps = NULL;
HBITMAP hbmDefault = NULL;
HBITMAP hbmMasks = NULL;
HDC hdcMem = NULL;
HDC hdcMasks = NULL;
HFONT hfontHelv;
HFONT hfontHelvBold;
TCHAR szHelv[] = TEXT("MS Shell Dlg");
TCHAR sz8[] = TEXT("8");
TCHAR sz10[] = TEXT("10");
TCHAR szNULL[] = TEXT("");
TCHAR szTitleFormat[] = TEXT("%s - %s");
TCHAR szPrintManHlp[] = TEXT("PRINTMAN.HLP");
WCHAR szLPrintManHlp[] = L"PRINTMAN.HLP";
DWORD SysColorHighlight;
DWORD SysColorHighlightText;
DWORD SysColorWindow;
DWORD SysColorWindowText;
DWORD SysColorBtnFace;
DWORD SysColorBtnText;
DWORD SysColorBtnHighlight;
DWORD SysColorBtnShadow;
DWORD SysColorWindowFrame;
TCHAR szInternational[] = TEXT("intl");
BOOL TwentyFourHourClock;
// JAPAN v-hirot July.07.1993 for New Prefix
// TimePrefix is for Japanese usage - krishnag
BOOL TimePrefix;
// CountryCode - krishnag Sept 1, 1993
// We have a two code paths; one for Japan; one for the rest of the world
BOOL bJapan;
TCHAR szTimeSep[TIMESEP_LENGTH];
TCHAR szAMPM[2][AMPM_LENGTH];
BOOL TimeFormatLeadingZero;
BOOL MetricMeasurement;
TCHAR szDecimalPoint[2];
DWORD DecimalDigits;
DWORD LeadingZero;
TCHAR szSizeFormat[14];
UINT WM_Help = 0;
UINT WM_DragList = 0;
HKEY hPrinterKey; // Per User Registry Printer Key
TCHAR *szRegistryPrinter=TEXT("Printers");
HWND hwndStatus;
DWORD WinHelpMenuID = 0; /* Global set in response to WM_MENUSELECT */
/* Set this before we call AddPrinter, so that we don't need to do anything
* when LocalServerThread posts us a WM_PRINTER_ADDED message:
*/
BOOL PrinterAdded = FALSE;
HANDLE hLocalServer;
extern HANDLE ThreadMessageRead;
extern HANDLE ThreadMessageWritten;
extern MSG ThreadMessage;
/* ==========================================================================
Local Data
========================================================================== */
TEXTMETRIC tm;
COLUMN MDIPrinterDefaultColumn[MDIHEAD_JOB_COUNT];
COLUMN MDIServerDefaultColumn[MDIHEAD_PRINTER_COUNT];
int HeaderHeight;
/* Minimum number of 'X' character widths for the columns:
*/
INT MDIPrinterMinimumCharacterWidth[] = { 12, 20, 0, 0, 0, 0, 0 };
INT MDIServerMinimumCharacterWidth[] = { 25, 0, 0, 20, 30 };
HCURSOR hcursorArrow;
HCURSOR hcursorReorder;
HCURSOR hcursorWait;
HICON hiconPrinter;
HICON hiconServer;
HICON hiconConnect;
HICON hiconShared;
//HHOOK hhookMessage;
HHOOK hhookGetMsg;
TCHAR szRegPrinters[] = TEXT("Printers");
TCHAR szRegServers[] = TEXT("Servers");
//
// Lowercase, like win31.
//
PTCHAR szWindows = TEXT("windows");
PTCHAR szDevices = TEXT("devices");
PTCHAR szDevice = TEXT("device");
REGISTRY_ENTRY RegistryEntries = { REG_BINARY, sizeof(REGISTRY_DATA) };
WNDPROC DefListboxWndProc;
/* Handles of the popup menus needed to put up help in the status bar
* in response to menu selections. (Popups don't have IDs, unfortunately.)
*/
HMENU hmenuPopups[POPUP_COUNT];
DWORD pMenuHelpIDs[] =
{
0, 0,
IDS_HELPPRINTER, POPUP_PRINTER,
IDS_HELPDOCUMENT, POPUP_DOCUMENT,
IDS_HELPOPTIONS, POPUP_OPTIONS,
IDS_HELPSECURITY, POPUP_SECURITY,
IDS_HELPWINDOW, POPUP_WINDOW,
IDS_HELPHELP, POPUP_HELP
};
BOOL NetworkInstalled = FALSE;
/* Global hack so we can ignore registry change notification
* when it was brought about by our own actions:
*/
BOOL ExpectingNotifyChangeKeyValue = FALSE;
/* ==========================================================================
Local Function Declarations
========================================================================== */
LONG FrameCreate(HWND hWnd, LPCREATESTRUCT pCreateStruct);
VOID GetSystemColors( VOID );
BOOL UserHasNetworkAccess( VOID );
VOID RemoveNetworkMenuItems( HWND hwnd );
BOOL NetworkIsInstalled( VOID );
VOID SetStatusMode( int Mode, BOOL Update );
LONG FrameThreadError(HWND hWnd, PMDIWIN_INFO pMDIWinInfo, DWORD dwError);
LONG FrameInitMenu(HWND hWnd);
LONG FrameMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam );
LONG FramePaint(HWND hWnd);
VOID FrameSize(HWND hWnd, WPARAM Type, long Dimensions);
VOID FrameClose(HWND hWnd);
VOID FrameHelp(HWND hwnd, UINT HelpID);
VOID SaveWindowPos( HWND hwnd, DWORD Options, BOOL MDIWindow );
LONG FrameCommandConnectToPrinter(HWND hWnd);
//LONG FrameCommandRemoveConnection(HWND hWnd);
LONG FrameCommandCreatePrinter(HWND hWnd);
LONG FrameCommandProperties(HWND hWnd);
LONG FrameCommandDeletePrinter(HWND hWnd);
LONG FrameCommandDeletePrinterHelper(HWND hWnd, HWND hwndMDI, BOOL bConfirm);
BOOL DeleteLocalPrinter(HWND hwnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm);
BOOL DeleteRemotePrinter(HWND hwnd, PSERVER_CONTEXT pServerContext, BOOL bConfirm);
BOOL DeleteConnection(HWND hWnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm);
HWND FindPrinterWindow( LPTSTR pPrinterName );
LONG FrameCommandPrinterPauseResume(HWND hWnd, BOOL bPause);
//BOOL SetPrinterTitle( HWND hwnd, PTCHAR pPrinterName, DWORD Status );
BOOL SetMDITitle( HWND hwnd, PMDIWIN_INFO pInfo );
LONG FrameCommandPurgePrinter(HWND hWnd);
LONG FrameCommandForms(HWND hWnd);
LONG FrameCommandServerViewer(HWND hWnd);
LONG FrameCommandChangePrinter(HWND hWnd);
LONG FrameCommandRemoveDoc(HWND hWnd);
LONG FrameCommandDocDetails(HWND hWnd);
LONG FrameCommandDocumentPauseResume(HWND hWnd, WORD PauseResume);
LONG FrameCommandRestart(HWND hWnd);
LONG FrameCommandFont(HWND hWnd);
LONG FrameCommandRefreshRate(HWND hWnd);
LONG FrameCommandToolbar(HWND hWnd);
LONG FrameCommandStatusbar(HWND hWnd);
LONG FrameCommandSaveSettings(HWND hWnd);
LONG FrameCommandPermissions(HWND hWnd);
LONG FrameCommandAuditing(HWND hWnd);
LONG FrameCommandOwner(HWND hWnd);
LONG FrameCommandClose(HWND hWnd);
LONG FrameCommandAbout(HWND hWnd);
LONG FrameCommandReturn();
VOID FrameCommandDefaultPrinter(HWND hwnd, WORD Command);
VOID FrameCommandToolbarNotify( HWND hwnd, WPARAM wParam, LPARAM lParam );
VOID FrameCommandTab(HWND hwnd);
LONG FrameCommandDefault(HWND hWnd, WPARAM wParam, LONG lParam);
VOID FrameSysColorChange( VOID );
VOID FrameWinIniChange( HWND hWnd, LPTSTR pSection );
VOID FramePrinterAdded( HWND hwnd, DWORD dwType );
VOID FrameRegNotifyChangeKeyValue( HWND hwnd, HKEY hWindowsKey );
VOID CreateMDIDefaultColumns( HWND hwnd, DWORD cColumns, DWORD idFirstColumn,
PCOLUMN pColumns, PINT pDefaultWidths );
PMDIWIN_INFO CreateQueueWindowInfo( PQUEUE pQueue, PINT pHeaders );
DWORD CALLBACK CreateServerWindow( HWND hwnd, LPTSTR pServerName, HANDLE hServer );
PMDIWIN_INFO CreateServerWindowInfo( PSERVER_CONTEXT pContext, PINT pHeaders );
BOOL InitServerChildWindows( HWND hWnd );
VOID FormatData( PBYTE pData, int Datatype, LPTSTR string );
int GetPrinterStatusString( DWORD Status, LPTSTR string );
VOID MDICreate( HWND hWnd, LONG lParam );
VOID SetDefaultColumnWidths( HWND hwnd, PMDIWIN_INFO pMDIWinInfo,
PINT pColumnWidths );
LONG MDIPaint(HWND hwnd, WPARAM wParam, LPARAM lParam);
BOOL MDIEraseBkgnd(HWND hwnd, HDC hdc);
HICON MDIQueryDragIcon(HWND hwnd);
LONG MDIMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam );
VOID MDICommandObjListSelChange( HWND hwnd );
VOID SetObjectSelection( PMDIWIN_INFO pInfo, DWORD Selection );
VOID MDICommandObjListDblClk( HWND hwnd );
VOID MDICommandHeaderBeginDrag( HWND hwnd, PPOINT pCursorPos );
VOID MDICommandHeaderDragging( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot );
VOID MDICommandHeaderEndDrag( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot );
VOID InvertDragMark( HWND hwnd, PPOINT pCursorPos );
VOID UpdateColumns( HWND hwnd, HD_NOTIFY * lpNot );
BOOL MDIClose( HWND hwnd );
VOID MDIVKeyToItemSpace( HWND hwnd );
VOID MDIParentNotifyRButtonDown( HWND hwnd, DWORD CursorPos );
VOID MDIVKeyToItemDefault( HWND hwnd );
int MDIVKeyToItemUpDown( HWND hwnd, WORD VKey );
VOID ReorderJob( HWND hwnd, PMDIWIN_INFO pInfo, DWORD Position );
VOID RepaintListboxItem( HWND hwndListbox, DWORD ItemID );
VOID MDISize( HWND hWnd, DWORD Coordinates );
LONG MDIMDIActivate( HWND hwnd, HWND hwndDeactivate, HWND hwndActivate );
VOID MDINCActivate( HWND hwnd );
LONG MDIWindowPosChanged( HWND hwnd, WPARAM wParam, LPARAM lParam );
VOID ClearDragPosition( PMDIWIN_INFO pInfo );
VOID MDISetFocus( HWND hwnd );
VOID MDIMeasureItem( HWND hwnd, LPMEASUREITEMSTRUCT pmis );
VOID MDIDrawItem( HWND hwnd, LPDRAWITEMSTRUCT pdis );
VOID MDITimer( HWND hWnd );
VOID MDIStatusChanged( HWND hwnd );
VOID MDIUpdateList( HWND hwnd );
VOID MDISetParts( HWND hwnd, WPARAM wParam, LPARAM lParam );
VOID MDIDestroy( HWND hwnd );
LONG MDIDragList( HWND hwnd, LPDRAGLISTINFO pDragListInfo );
BOOL RefreshServerContext( PVOID pContext, PDWORD pFlags );
BOOL GetSavedWindowPos( LPTSTR pKey, LPTSTR WindowName, PSAVEDWINDOWPOS pswp,
DWORD cHeaders, PINT pHeaders );
UINT GetCurrentMenuItemID( HMENU hMenu );
LONG SubclassListboxWndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LONG lParam
);
VOID
KillMDIWinInfo(
PMDIWIN_INFO pInfo);
/* Copied from winfile:
*/
INT
GetHeightFromPointsString(
LPTSTR szPoints)
{
HDC hdc;
INT height;
hdc = GetDC(NULL);
height = MulDiv(-_tcstol(szPoints, NULL, 10), GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(NULL, hdc);
return height;
}
/* InitializeInternationalTimeConstants
*
* Called to set up the following global variables:
*
* TwentyFourHourClock - Boolean indicating whether 12- or 24-hour clock
* is currently in force.
*
* MetricMeasurement - Metres or feet and inches (TRUE == metric)
*
* szTimeSep - Separator for time string - usually ":", unless you're in
* Scandinavia, Croatia or a couple of other places.
*
* szAMPM - Array of 2 strings - usually "AM" or "PM" for 12-hour clock.
*
* TimeFormatLeadingZero
*/
VOID InitializeInternationalTimeConstants( VOID )
{
LCID lcid;
WCHAR Buffer[128];
TwentyFourHourClock = GetProfileInt (szInternational, TEXT("iTime"), 0);
// JAPAN
// V-Hirot July.07.1993 for New Prefix
// krishnag Sept 1, 1993 CountryCode
if (bJapan) {
TimePrefix = GetProfileInt (szInternational, TEXT("iTimePrefix"), 0);
}
GetProfileString (szInternational, TEXT("sTime"), TEXT(":"), szTimeSep, TIMESEP_LENGTH);
GetProfileString (szInternational, TEXT("s1159"), TEXT("AM"), szAMPM[AM], AMPM_LENGTH);
GetProfileString (szInternational, TEXT("s2359"), TEXT("PM"), szAMPM[PM], AMPM_LENGTH);
TimeFormatLeadingZero = (BOOL)GetProfileInt (szInternational, TEXT("iTLZero"), 1);
MetricMeasurement = !((BOOL)GetProfileInt (szInternational, TEXT("iMeasure"), 0));
GetProfileString (szInternational, TEXT("sDecimal"), TEXT("."), szDecimalPoint, sizeof szDecimalPoint/sizeof(TCHAR));
DecimalDigits = GetProfileInt (szInternational, TEXT("iDigits"), 2);
LeadingZero = GetProfileInt (szInternational, TEXT("iLzero"), 1);
lcid = GetThreadLocale();
ThousandSeparator = TEXT(',');
if (GetLocaleInfoW (lcid, LOCALE_STHOUSAND, Buffer, sizeof Buffer /sizeof(WCHAR))) {
ThousandSeparator = Buffer[0];
}
}
HWND
CreateQueueWindow(
HWND hWnd,
PQUEUE pQueue,
DWORD Status,
DWORD WindowType,
DWORD Flags
)
{
TCHAR Title[80];
TCHAR StatusString[40];
SAVEDWINDOWPOS swp;
MDICREATESTRUCT mdicreate;
INT pHeaders[MDIHEAD_JOB_COUNT];
INT i;
if (!pQueue)
return NULL;
/* Now create a window for this queue. Note that during this function
* the WM_CREATE message is sent to the QueueWinProc but, the Extra
* Window Word has not yet been set to hQueue value because we need
* the window handle in order to set this value. In order to get
* around this 'Catch-22' situation, we pass the hQueue value as the
* 'lpParam' value in the MDICREATESTRUCT. Then we only have to be
* a little sly when processing the WM_CREATE message to retrieve the
* Queue handle. Also, we then set the Window Word value to hQueue
* during WM_CREATE message processing, thereby insuring that it will
* be available for all subsequent messages.
*/
if( !GetSavedWindowPos( szRegPrinters, pQueue->pPrinterName, &swp,
( sizeof pHeaders / sizeof *pHeaders ), pHeaders ) )
{
/* If no window positions saved, set the column widths to default.
* They will be initialised on MDI creation, since they depend
* on the width of the window:
*/
for( i = 0; i < MDIHEAD_JOB_COUNT; i++ )
pHeaders[i] = CW_USEDEFAULT;
}
if( Flags & CREATE_PRINTER_ICONIC )
swp.sw = SW_SHOWMINIMIZED;
if( Status )
{
GetPrinterStatusString( Status, StatusString );
_stprintf( Title, szTitleFormat, pQueue->pPrinterName, StatusString );
}
else
_tcscpy( Title, pQueue->pPrinterName );
if( !(pQueue->pMDIWinInfo = CreateQueueWindowInfo( pQueue, pHeaders ) ) )
return NULL;
pQueue->pMDIWinInfo->Status = Status;
SetWindowTypeIcon(pQueue, WindowType, Flags);
mdicreate.szClass = szChildClass;
mdicreate.szTitle = Title;
mdicreate.hOwner = hInst;
mdicreate.x = swp.left;
mdicreate.y = swp.top;
mdicreate.cx = swp.width;
mdicreate.cy = swp.height;
mdicreate.style = SW2WS( swp.sw ) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
mdicreate.lParam = (LONG)pQueue->pMDIWinInfo;
hWnd = (HWND)SendMessage(hwndClient, WM_MDICREATE, 0, (LONG)&mdicreate);
return hWnd;
}
/*
*
*/
PMDIWIN_INFO
CreateQueueWindowInfo(
PQUEUE pQueue,
PINT pHeaders )
{
PMDIWIN_INFO pInfo;
PCOLUMN pColumns;
int i;
pInfo = (PMDIWIN_INFO)AllocSplMem( sizeof( MDIWIN_INFO ) );
if( !pInfo )
return NULL;
pColumns = (PCOLUMN)AllocSplMem( sizeof( COLUMN ) * MDIHEAD_JOB_COUNT );
if( !pColumns )
{
FreeSplMem( pInfo );
return NULL;
}
for( i = 0; i < MDIHEAD_JOB_COUNT; i++ )
{
pColumns[i].Width = pHeaders[i];
pColumns[i].Text = MDIPrinterDefaultColumn[i].Text;
}
/* Initialize all pColumns elements here. Rememberthat some
printers can generate their own error messages which are
pointed to by JOB_INFO_2's pStatus field. We have to query
each time we display status info as to which field is
providing the Status information */
pColumns[MDIHEAD_JOB_STATUS ].Offset = offsetof( JOB_INFO_2, Status );
pColumns[MDIHEAD_JOB_DOCNAME ].Offset = offsetof( JOB_INFO_2, pDocument );
pColumns[MDIHEAD_JOB_OWNER ].Offset = offsetof( JOB_INFO_2, pUserName );
pColumns[MDIHEAD_JOB_PRINTEDAT].Offset = offsetof( JOB_INFO_2, Submitted );
pColumns[MDIHEAD_JOB_PAGES ].Offset = offsetof( JOB_INFO_2, TotalPages );
pColumns[MDIHEAD_JOB_SIZE ].Offset = offsetof( JOB_INFO_2, Size );
pColumns[MDIHEAD_JOB_PRIORITY ].Offset = offsetof( JOB_INFO_2, Priority );
pColumns[MDIHEAD_JOB_STATUS ].Datatype = MDIDATA_JOB_STATUS;
pColumns[MDIHEAD_JOB_DOCNAME ].Datatype = MDIDATA_PSZ_UNTITLED_IF_NULL;
pColumns[MDIHEAD_JOB_OWNER ].Datatype = MDIDATA_PSZ;
pColumns[MDIHEAD_JOB_PRINTEDAT].Datatype = MDIDATA_TIME;
pColumns[MDIHEAD_JOB_PAGES ].Datatype = MDIDATA_DWORD_BLANK_IF_ZERO;
pColumns[MDIHEAD_JOB_SIZE ].Datatype = MDIDATA_SIZE;
pColumns[MDIHEAD_JOB_PRIORITY ].Datatype = MDIDATA_DWORD_BLANK_IF_ZERO;
pInfo->WindowType = MDIWIN_PRINTER;
pInfo->hwndList = NULL;
pInfo->cNumLines = 0;
pInfo->ppData = (PBYTE *)&pQueue->pJobs;
pInfo->DataSize = sizeof( JOB_INFO_2 );
pInfo->pcObjects = &pQueue->cJobs;
pInfo->cColumns = MDIHEAD_JOB_COUNT;
pInfo->pColumns = pColumns;
pInfo->IconStatus = offsetof( JOB_INFO_2, Status );
pInfo->pSelObjId = &pQueue->SelJobId;
pInfo->ppSelData = (PBYTE *)&pQueue->pSelJob;
pInfo->IdOffset = offsetof( JOB_INFO_2, JobId );
pInfo->pFirstEnumObj = &pQueue->FirstEnumJob;
pInfo->pcEnumObjs = &pQueue->cEnumJobs;
pInfo->DataMutex = CreateMutex( NULL, FALSE, NULL );
#ifdef SEP_WAITHANDLE
pInfo->phWaitObject = &pQueue->hPrinterWait;
pInfo->phMain = &pQueue->hPrinter;
#else
pInfo->phWaitObject = &pQueue->hPrinter;
#endif
pInfo->WaitFlags = PRINTER_CHANGE_PRINTER | PRINTER_CHANGE_JOB;
pInfo->pfnRefresh = (REFRESHPROC)GetJobs;
pInfo->pfnCheckQuit = (CHECKQUITPROC)CheckQuitQueue;
pInfo->pfnInitThread = (INITTHREADPROC)InitQueueThread;
// pInfo->SuspendRefresh = FALSE;
pInfo->RefreshSignal = CreateEvent( NULL,
EVENT_RESET_MANUAL,
EVENT_INITIAL_STATE_SIGNALED,
NULL );
if( pInfo->RefreshSignal == NULL )
DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
pInfo->pContext = pQueue;
return pInfo;
}
//
// Create the server window.
//
// If hServer is NULL, we haven't tried the OpenPrinter yet.
// If hServer is (HANDLE)-1, we tried and failed due to access denied.
// else hServer is valid. InitServerWindowThread picks up these values.
//
DWORD CALLBACK
CreateServerWindow(
HWND hwnd,
LPTSTR pServerName,
HANDLE hServer)
{
PSERVER_CONTEXT pContext;
LPTSTR pServerViewerTitle;
TCHAR Title[MAX_PATH+20]; // Enough for server name + "Server: "
SAVEDWINDOWPOS swp;
MDICREATESTRUCT mdicreate;
INT pHeaders[MDIHEAD_PRINTER_COUNT];
INT i;
pContext = AllocSplMem( sizeof( SERVER_CONTEXT ) );
if (!pContext)
{
//
// !! LATER !!
// Put up an error
//
return NO_ERROR;
}
pContext->pServerName = AllocSplStr( pServerName );
pContext->hServer = hServer;
if( !GetSavedWindowPos( szRegServers, pServerName, &swp,
( sizeof pHeaders / sizeof *pHeaders ), pHeaders ) )
{
/* If no window positions saved, set the column widths to default.
* They will be initialised on MDI creation, since they depend
* on the width of the window:
*/
for( i = 0; i < MDIHEAD_PRINTER_COUNT; i++ )
pHeaders[i] = CW_USEDEFAULT;
}
pContext->pMDIWinInfo = CreateServerWindowInfo( pContext, pHeaders );
pServerViewerTitle = GetString( IDS_SERVERVIEWERTITLE );
_stprintf( Title, pServerViewerTitle, pServerName );
FreeSplStr( pServerViewerTitle );
mdicreate.szClass = szChildClass;
mdicreate.szTitle = Title;
mdicreate.hOwner = hInst;
mdicreate.x = swp.left;
mdicreate.y = swp.top;
mdicreate.cx = swp.width;
mdicreate.cy = swp.height;
mdicreate.style = SW2WS( swp.sw ) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
mdicreate.lParam = (LONG)pContext->pMDIWinInfo;
SendMessage(hwndClient, WM_MDICREATE, 0, (LONG)&mdicreate);
return NO_ERROR;
}
/*
*
*/
PMDIWIN_INFO
CreateServerWindowInfo(
PSERVER_CONTEXT pContext,
PINT pHeaders)
{
PMDIWIN_INFO pInfo;
PCOLUMN pColumns;
int i;
pInfo = (PMDIWIN_INFO)AllocSplMem( sizeof( MDIWIN_INFO ) );
if( !pInfo )
return NULL;
pColumns = (PCOLUMN)AllocSplMem( sizeof( COLUMN ) * MDIHEAD_PRINTER_COUNT );
if( !pColumns )
{
FreeSplMem( pInfo );
return NULL;
}
for( i = 0; i < MDIHEAD_PRINTER_COUNT; i++ )
{
pColumns[i].Width = pHeaders[i];
pColumns[i].Text = MDIServerDefaultColumn[i].Text;
}
pColumns[MDIHEAD_PRINTER_PRINTER].Offset = offsetof( PRINTER_INFO_2, pPrinterName );
pColumns[MDIHEAD_PRINTER_STATUS ].Offset = offsetof( PRINTER_INFO_2, Status );
pColumns[MDIHEAD_PRINTER_JOBS ].Offset = offsetof( PRINTER_INFO_2, cJobs );
pColumns[MDIHEAD_PRINTER_PORT ].Offset = offsetof( PRINTER_INFO_2, pPortName );
pColumns[MDIHEAD_PRINTER_TYPE ].Offset = offsetof( PRINTER_INFO_2, pDriverName );
pColumns[MDIHEAD_PRINTER_PRINTER].Datatype = MDIDATA_PSZ;
pColumns[MDIHEAD_PRINTER_STATUS ].Datatype = MDIDATA_PRINTER_STATUS;
pColumns[MDIHEAD_PRINTER_JOBS ].Datatype = MDIDATA_DWORD;
pColumns[MDIHEAD_PRINTER_PORT ].Datatype = MDIDATA_PSZ;
pColumns[MDIHEAD_PRINTER_TYPE ].Datatype = MDIDATA_PSZ;
pInfo->WindowType = MDIWIN_SERVER;
pInfo->hwndList = NULL;
pInfo->cNumLines = 0;
pInfo->ppData = (PBYTE *)&pContext->pPrinters;
pInfo->DataSize = sizeof( PRINTER_INFO_2 );
pInfo->pcObjects = &pContext->cPrinters;
pInfo->cColumns = MDIHEAD_PRINTER_COUNT;
pInfo->pColumns = pColumns;
pInfo->IconStatus = offsetof( PRINTER_INFO_2, Status );
pInfo->pSelObjId = &pContext->SelPrinterId;
pInfo->ppSelData = (PBYTE *)&pContext->pSelPrinter;
pInfo->IdOffset = offsetof( PRINTER_INFO_2, pPrinterName );
pInfo->pFirstEnumObj = &pContext->FirstEnumPrinter;
pInfo->pcEnumObjs = &pContext->cEnumPrinters;
pInfo->DataMutex = CreateMutex( NULL, FALSE, NULL );
#ifdef SEP_WAITHANDLE
pInfo->phWaitObject = &pContext->hServerWait;
pInfo->phMain = &pContext->hServer;
#else
pInfo->phWaitObject = &pContext->hServer;
#endif
pInfo->WaitFlags = PRINTER_CHANGE_PRINTER;
pInfo->pfnRefresh = (REFRESHPROC)RefreshServerContext;
pInfo->pfnCheckQuit = NULL;
pInfo->pfnInitThread = (INITTHREADPROC)InitServerWindowThread;
// pInfo->SuspendRefresh = FALSE;
pInfo->RefreshSignal = CreateEvent( NULL,
EVENT_RESET_MANUAL,
EVENT_INITIAL_STATE_SIGNALED,
NULL );
pInfo->hicon = hiconServer;
if( pInfo->RefreshSignal == NULL )
DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
pInfo->pContext = pContext;
return pInfo;
}
/* DisplayStatusIcon
*
* This rather goes against the spirit of the data-driven model here,
* in that we need to know about the various states that documents and printers
* can be in.
*
* andrewbe - May 1992
*/
BOOL DisplayStatusIcon( HDC hdc, PRECT prect, int WindowType, PBYTE pData, BOOL Highlight )
{
BOOL DisplayIcon = TRUE;
int BitmapIndex;
DWORD Status;
int xBase;
int yBase;
int right;
Status = *(DWORD *)pData;
switch( WindowType )
{
case MDIWIN_LOCALPRINTER:
case MDIWIN_NETWORKPRINTER:
case MDIWIN_LOCALNETWORKPRINTER:
if( ( Status & JOB_STATUS_ERROR )
||( Status & JOB_STATUS_OFFLINE )
||( Status & JOB_STATUS_PAPEROUT ) )
BitmapIndex = BM_IND_DOCUMENT_ERROR;
else
if( Status & JOB_STATUS_PAUSED )
BitmapIndex = BM_IND_DOCUMENT_PAUSED;
else
if( ( Status & JOB_STATUS_PRINTING )
||( Status & JOB_STATUS_SPOOLING ) )
BitmapIndex = BM_IND_DOCUMENT_PRINTING;
else
DisplayIcon = FALSE;
xBase = BM_IND_STATUS_XBASE;
yBase = BM_IND_STATUS_YBASE;
break;
case MDIWIN_SERVER:
default:
if( Status & PRINTER_STATUS_ERROR )
BitmapIndex = BM_IND_PRINTER_ERROR;
else
if( Status & PRINTER_STATUS_PAUSED )
BitmapIndex = BM_IND_PRINTER_PAUSED;
else
BitmapIndex = BM_IND_PRINTER_READY;
xBase = BM_IND_STATUS_XBASE;
yBase = BM_IND_STATUS_YBASE;
break;
}
/* Remember the old right coordinate of the drawing area:
*/
right = prect->right;
if( DisplayIcon )
{
BitBlt( hdc, prect->left + STATUS_BITMAP_MARGIN,
prect->top,
STATUS_BITMAP_WIDTH,
STATUS_BITMAP_HEIGHT,
hdcMem,
( xBase + ( BitmapIndex * STATUS_BITMAP_WIDTH ) ),
( yBase + ( Highlight ? STATUS_BITMAP_HEIGHT : 0 ) ),
SRCCOPY );
/* Draw around it so we don't get a flashing effect on the highlight line:
*/
prect->right = ( prect->left + STATUS_BITMAP_MARGIN );
DrawLine( hdc, prect, TEXT(""), Highlight );
prect->left += STATUS_BITMAP_MARGIN + STATUS_BITMAP_WIDTH;
prect->right = prect->left + STATUS_BITMAP_MARGIN;
DrawLine( hdc, prect, TEXT(""), Highlight );
prect->left += STATUS_BITMAP_MARGIN;
}
else
{
prect->right = STATUS_BITMAP_SPACE;
DrawLine( hdc, prect, TEXT(""), Highlight );
prect->left += STATUS_BITMAP_SPACE;
}
/* Restore the right coordinate (left has now been updated to the new position):
*/
prect->right = right;
return DisplayIcon;
}
/* FormatData
*
* Takes a generic data pointer, along with the datatype to be formatted,
* and generates a string.
*
* andrewbe wrote it - April 1992
*/
VOID FormatData( PBYTE pData, int Datatype, LPTSTR string )
{
TCHAR FormattedSize[MAX_PATH];
LARGE_INTEGER liTemp;
switch( Datatype )
{
case MDIDATA_DWORD:
liTemp.LowPart = *(DWORD *)pData;
liTemp.HighPart = 0;
FormatFileSize (THOUSANDSEPSWITCH, &liTemp, 0, FormattedSize);
_stprintf( string, TEXT("%s"), FormattedSize );
break;
case MDIDATA_DWORD_BLANK_IF_ZERO:
if( *(PCHAR *)pData != 0 ) {
liTemp.LowPart = *(DWORD *)pData;
liTemp.HighPart = 0;
FormatFileSize (THOUSANDSEPSWITCH, &liTemp, 0, FormattedSize);
_stprintf( string, TEXT("%s"), FormattedSize );
}
else
*string = NULLC;
break;
case MDIDATA_PSZ:
if( *(PCHAR *)pData && **(PCHAR *)pData )
_stprintf( string, TEXT("%s"), *(PCHAR *)pData );
else
*string = NULLC;
break;
case MDIDATA_PSZ_UNTITLED_IF_NULL:
if( *(PCHAR *)pData && **(PCHAR *)pData )
_stprintf( string, TEXT("%s"), *(PCHAR *)pData );
else
_stprintf( string, TEXT("%s"), strUntitled );
break;
case MDIDATA_TIME:
ConvertSystemTimeToChar((SYSTEMTIME *)pData, string);
break;
case MDIDATA_SIZE:
liTemp.LowPart = *(DWORD *)pData;
liTemp.HighPart = 0;
FormatFileSize (THOUSANDSEPSWITCH, &liTemp, 0, FormattedSize);
_stprintf( string, szSizeFormat, FormattedSize );
break;
case MDIDATA_PRINTER_STATUS:
GetPrinterStatusString( (DWORD)*(PDWORD *)pData, string );
break;
case MDIDATA_JOB_STATUS:
GetJobStatusString( (DWORD)*(PDWORD *)pData, string );
}
}
/* GetPrinterStatusString
*
* Loads the resource string corresponding to the supplied status code.
*
* andrewbe wrote it - April 1992
*/
#define MAXLEN 40
int GetPrinterStatusString( DWORD Status, LPTSTR string )
{
int stringID;
if( Status & PRINTER_STATUS_ERROR )
stringID = IDS_ERROR;
else
if( Status & PRINTER_STATUS_PAPER_JAM )
stringID = IDS_PAPER_JAM;
else
if( Status & PRINTER_STATUS_PAPER_OUT )
stringID = IDS_PAPEROUT;
else
if( Status & PRINTER_STATUS_MANUAL_FEED )
stringID = IDS_MANUAL_FEED;
else
if( Status & PRINTER_STATUS_PAPER_PROBLEM )
stringID = IDS_PAPER_PROBLEM;
else
if( Status & PRINTER_STATUS_OFFLINE )
stringID = IDS_OFFLINE;
else
if( Status & PRINTER_STATUS_IO_ACTIVE )
stringID = IDS_IO_ACTIVE;
else
if( Status & PRINTER_STATUS_BUSY )
stringID = IDS_BUSY;
else
if( Status & PRINTER_STATUS_PRINTING )
stringID = IDS_PRINTING;
else
if( Status & PRINTER_STATUS_OUTPUT_BIN_FULL )
stringID = IDS_OUTPUT_BIN_FULL;
else
if( Status & PRINTER_STATUS_NOT_AVAILABLE )
stringID = IDS_NOT_AVAILABLE;
else
if( Status & PRINTER_STATUS_WAITING )
stringID = IDS_WAITING;
else
if( Status & PRINTER_STATUS_PROCESSING )
stringID = IDS_PROCESSING;
else
if( Status & PRINTER_STATUS_INITIALIZING )
stringID = IDS_INITIALIZING;
else
if( Status & PRINTER_STATUS_WARMING_UP )
stringID = IDS_WARMING_UP;
else
if( Status & PRINTER_STATUS_TONER_LOW )
stringID = IDS_TONER_LOW;
else
if( Status & PRINTER_STATUS_NO_TONER )
stringID = IDS_NO_TONER;
else
if( Status & PRINTER_STATUS_PAGE_PUNT )
stringID = IDS_PAGE_PUNT;
else
if( Status & PRINTER_STATUS_USER_INTERVENTION )
stringID = IDS_USER_INTERVENTION;
else
if( Status & PRINTER_STATUS_OUT_OF_MEMORY )
stringID = IDS_OUT_OF_MEMORY;
else
if( Status & PRINTER_STATUS_DOOR_OPEN )
stringID = IDS_DOOR_OPEN;
// else
// if( Status & PRINTER_STATUS_SERVER_UNKNOWN )
// stringID = IDS_SERVER_UNKNOWN;
else
if( Status & PRINTER_STATUS_PAUSED )
stringID = IDS_PAUSED;
else
if( Status & PRINTER_STATUS_PENDING_DELETION )
stringID = IDS_PENDING_DELETION;
else
if( Status & PRINTER_STATUS_ACCESS_DENIED )
stringID = IDS_ACCESS_DENIED;
else
if( Status & PRINTER_STATUS_UNKNOWN )
stringID = IDS_STATUS_UNKNOWN;
else
if( Status & PRINTER_STATUS_LOADING )
stringID = IDS_STATUS_LOADING;
//
// End
//
else
stringID = IDS_READY;
return LoadString( hInst, stringID, string, MAXLEN );
}
/* GetJobStatusString
*
* Loads the resource string corresponding to the supplied status code.
*
* andrewbe wrote it - April 1992
*/
int GetJobStatusString( DWORD Status, LPTSTR string )
{
int stringID;
if( Status & JOB_STATUS_ERROR )
stringID = IDS_ERROR;
else
if( Status & JOB_STATUS_OFFLINE )
stringID = IDS_OFFLINE;
else
if( Status & JOB_STATUS_PAPEROUT )
stringID = IDS_PAPEROUT;
else
if( Status & JOB_STATUS_DELETING )
stringID = IDS_DELETING;
else
if( Status & JOB_STATUS_PAUSED )
stringID = IDS_PAUSED;
else
if( ( Status & JOB_STATUS_SPOOLING ) && ( Status & JOB_STATUS_PRINTING ) )
stringID = IDS_PRINTANDSPOOL;
else
if( Status & JOB_STATUS_SPOOLING )
stringID = IDS_SPOOLING;
else
if( Status & JOB_STATUS_PRINTING )
stringID = IDS_PRINTING;
else
if( Status & JOB_STATUS_PRINTED )
stringID = IDS_PRINTED;
else
stringID = IDS_NOSTATUS;
return LoadString( hInst, stringID, string, MAXLEN );
}
VOID
SetWindowTypeIcon(
PQUEUE pQueue,
DWORD WindowType,
DWORD Flags)
{
pQueue->pMDIWinInfo->WindowType = WindowType;
switch( WindowType )
{
case MDIWIN_NETWORKPRINTER:
case MDIWIN_LOCALNETWORKPRINTER:
pQueue->pMDIWinInfo->hicon = hiconConnect;
break;
case MDIWIN_LOCALPRINTER:
default:
pQueue->pMDIWinInfo->hicon = ( ( Flags & CREATE_PRINTER_SHARED )
? hiconShared : hiconPrinter );
break;
}
}
/* --- Function: DrawLine() -------------------------------------------------
*
* Description:
* Only draws lines visible portion of Printer and Job status lines
* in window.
*
* ---------------------------------------------------------------------- */
void
DrawLine(
HDC hDC,
LPRECT pRect,
LPTSTR pStr,
BOOL bInvert
)
{
unsigned long PrevColour, PrevTextColour;
SIZE TextSize;
int x, y;
if (bInvert) {
PrevColour = SetBkColor(hDC, SysColorHighlight );
PrevTextColour = SetTextColor(hDC, SysColorHighlightText );
}
else
{
/* Hack around a USER bug that gives me the wrong colours:
*/
SetBkColor(hDC, SysColorWindow );
SetTextColor(hDC, SysColorWindowText );
}
GetTextExtentPoint(hDC, pStr, _tcslen(pStr), &TextSize);
x = pRect->left;
y = ( pRect->top + ( ( pRect->bottom - pRect->top - TextSize.cy ) / 2 ) );
ExtTextOut(hDC, x, y, ETO_OPAQUE | ETO_CLIPPED, pRect, pStr, _tcslen(pStr), NULL);
if (bInvert) {
SetBkColor(hDC, PrevColour);
SetTextColor(hDC, PrevTextColour);
}
}
long FrameWndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LONG lParam
)
{
if( message == WM_Help )
{
FrameHelp(hWnd, (UINT)lParam);
return 0;
}
switch(message)
{
case WM_CREATE:
return FrameCreate(hWnd, (LPCREATESTRUCT)lParam);
case WM_DELETE_PRINTER:
return FrameCommandDeletePrinterHelper(hWnd, (HWND)lParam, FALSE);
case WM_INIT_PRINTER_WINDOWS:
InitQueueChildWindows(hWnd);
return 0;
case WM_INIT_SERVER_WINDOWS:
InitServerChildWindows(hWnd);
return 0;
case WM_INITMENU:
return FrameInitMenu(hWnd);
case WM_MENUSELECT:
return FrameMenuSelect( hWnd, wParam, lParam );
case WM_PAINT:
return FramePaint(hWnd);
case WM_SIZE:
FrameSize(hWnd, wParam, lParam);
break;
case WM_CLOSE:
FrameClose(hWnd);
return DefFrameProc(hWnd, hwndClient, message, wParam, lParam);
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_CONNECTTOPRINTER:
return FrameCommandConnectToPrinter(hWnd);
case IDM_INSTALLPRINTER:
return FrameCommandCreatePrinter(hWnd);
case IDM_PROPERTIES:
return FrameCommandProperties(hWnd);
case IDM_REMOVECONNECTION: /* Toolbar button only */
case IDM_DELETEPRINTER:
return FrameCommandDeletePrinter(hWnd);
case IDM_PRINTER_PAUSE:
return FrameCommandPrinterPauseResume(hWnd, TRUE);
case IDM_PRINTER_RESUME:
return FrameCommandPrinterPauseResume(hWnd, FALSE);
case IDM_PURGEPRINTER:
return FrameCommandPurgePrinter(hWnd);
case IDM_FORMS:
return FrameCommandForms(hWnd);
case IDM_SERVERVIEWER:
return FrameCommandServerViewer(hWnd);
case IDM_EXIT:
SendMessage(hWnd, WM_CLOSE, 0, 0L);
return 0;
case IDM_REMOVEDOC:
return FrameCommandRemoveDoc(hWnd);
case IDM_DOCTAILS:
return FrameCommandDocDetails(hWnd);
case IDM_DOCUMENT_PAUSE:
return FrameCommandDocumentPauseResume(hWnd, IDM_DOCUMENT_PAUSE);
case IDM_DOCUMENT_RESUME:
return FrameCommandDocumentPauseResume(hWnd, IDM_DOCUMENT_RESUME);
case IDM_RESTART:
return FrameCommandRestart(hWnd);
#ifdef LATER
case IDM_FONT:
return FrameCommandFont(hWnd);
case IDM_REFRESHRATE:
return FrameCommandRefreshRate(hWnd);
#endif
case IDM_TOOLBAR:
return FrameCommandToolbar(hWnd);
case IDM_STATUSBAR:
return FrameCommandStatusbar(hWnd);
case IDM_SAVESETTINGS:
return FrameCommandSaveSettings(hWnd);
case IDM_PERMISSIONS:
return FrameCommandPermissions(hWnd);
case IDM_AUDITING:
return FrameCommandAuditing(hWnd);
case IDM_OWNER:
return FrameCommandOwner(hWnd);
case IDM_TILEHORZ:
SendMessage(hwndClient, WM_MDITILE, MDITILE_HORIZONTAL, 0L);
return 0;
case IDM_TILEVERT:
SendMessage(hwndClient, WM_MDITILE, MDITILE_VERTICAL, 0L);
return 0;
case IDM_CASCADE:
SendMessage(hwndClient, WM_MDICASCADE, 0, 0L);
return 0;
case IDM_ARRANGE:
SendMessage(hwndClient, WM_MDIICONARRANGE, 0, 0L);
return 0;
case IDM_REFRESH:
FrameCommandRefresh(hWnd);
return 0;
case IDM_CLOSE:
return FrameCommandClose(hWnd);
case IDM_HELP_CONTENTS:
ShowHelp(hWnd, HELP_INDEX, (DWORD)TEXT(""));
break;
case IDM_HELP_SEARCH:
ShowHelp(hWnd, HELP_PARTIALKEY, (DWORD)TEXT(""));
break;
case IDM_HELP_HOWTOUSE:
ShowHelp(hWnd, HELP_HELPONHELP, (DWORD)TEXT(""));
break;
case IDM_ABOUT:
return FrameCommandAbout(hWnd);
case IDM_RETURN:
return FrameCommandReturn();
case IDTB_CB_PRINTERS:
FrameCommandDefaultPrinter(hWnd, HIWORD(wParam));
break;
case ID_TOOLBAR:
FrameCommandToolbarNotify(hWnd, wParam, lParam);
break;
case IDC_TAB:
FrameCommandTab(hWnd);
break;
default:
return FrameCommandDefault(hWnd, wParam, lParam);
}
break;
#ifdef LATER
case WM_QUERYENDSESSION:
case WM_CLOSE:
SendMessage(hWnd, WM_COMMAND, IDM_CLOSEALL, 0L);
if (NULL != GetWindow(hwndClient, GW_CHILD))
return 0;
#endif
case WM_NOTIFY:
{
LPTOOLTIPTEXT lpTT = (LPTOOLTIPTEXT) lParam;
if (lpTT->hdr.code == TTN_NEEDTEXT) {
if (!LoadString (hInst, lpTT->hdr.idFrom, lpTT->szText, 80))
lpTT->szText[0] = TEXT('\0');
}
}
break;
case WM_SYSCOLORCHANGE:
FrameSysColorChange( );
break;
case WM_WININICHANGE:
FrameWinIniChange( hWnd, (LPTSTR)lParam );
break;
case WM_DROPOBJECT:
return 0x544E5250L; // 'PRNT' tells fm to print
case WM_UPDATE_DEFAULT:
UpdateDefaultList( );
return 0;
case WM_PRINTER_ADDED:
FramePrinterAdded(hWnd, wParam);
return 0;
case WM_REG_NOTIFY_CHANGE_KEY_VALUE:
FrameRegNotifyChangeKeyValue( hWnd, (HKEY)wParam );
return 0;
case WM_THREAD_ERROR:
FrameThreadError(hWnd, (PMDIWIN_INFO)lParam, wParam);
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
default:
return DefFrameProc(hWnd, hwndClient, message, wParam, lParam);
}
// Pass unprocessed msgs to DefFrameProc(not DefWindowProc)
return 0;
}
/*
* ROUTINES CALLED BY FrameWndProc:
*/
/*
*
*/
LONG FrameCreate(HWND hWnd, LPCREATESTRUCT pCreateStruct)
{
CLIENTCREATESTRUCT clientcreate;
HMENU hMenu;
HDC hDC;
RECT rc;
BOOL NetworkAccess;
DWORD ThreadId;
DWORD i;
SetWindowLong(hWnd, GWL_USERDATA, (LONG)pCreateStruct->lpCreateParams);
hwndFrame = hWnd;
hDC = GetDC(hWnd);
GetTextMetrics(hDC, &tm);
cy = tm.tmExternalLeading + tm.tmHeight;
cx = tm.tmAveCharWidth;
dyBorder = GetSystemMetrics(SM_CYBORDER);
dyBorderx2 = dyBorder * 2;
// dyStatus = tm.tmHeight + tm.tmExternalLeading + 7 * dyBorder;
dxStatPrtField = GetDeviceCaps(hDC, LOGPIXELSX) * 3; // 3 inches
dxStatProgField = GetDeviceCaps(hDC, LOGPIXELSX) * 3 / 2; // 1 1/2 inches
dxStatQueField = GetDeviceCaps(hDC, LOGPIXELSX) * 2; // 2 inches
ReleaseDC(hWnd, hDC);
// OpenPrinterForSpecifiedAccess( NULL, &hLocalServer,
// PRINTER_ACCESS_HIGHEST_PERMITTED,
// &LocalPermission );
GetMaximumServerAccess( NULL,
&LocalPermission,
&hLocalServer );
if( hLocalServer )
CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)LocalServerThread,
hLocalServer, 0, &ThreadId );
ThreadMessageWritten = CreateEvent( NULL,
EVENT_RESET_AUTOMATIC,
EVENT_INITIAL_STATE_NOT_SIGNALED,
NULL );
if( ThreadMessageWritten == NULL )
DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
ThreadMessageRead = CreateEvent( NULL,
EVENT_RESET_AUTOMATIC,
EVENT_INITIAL_STATE_SIGNALED,
NULL );
if( ThreadMessageRead == NULL )
DBGMSG( DBG_WARNING, ( "CreateEvent failed: Error %d\n", GetLastError( ) ) );
#if DBG
if( WaitForSingleObject( ThreadMessageRead, 0 ) != WAIT_OBJECT_0 )
DBGMSG( DBG_WARNING, ( "Event was not signaled!\n" ) );
SetEvent( ThreadMessageRead );
#endif /* DBG */
// Set initial state of some menu items
hMenu = GetMenu(hwndFrame);
if (bStatusBar)
CheckMenuItem(hMenu, IDM_STATUSBAR, MF_BYCOMMAND | MF_CHECKED);
if (bToolBar)
CheckMenuItem(hMenu, IDM_TOOLBAR, MF_BYCOMMAND | MF_CHECKED);
if (bSaveSettings)
CheckMenuItem(hMenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_CHECKED);
/* Get the handles of the popup menus:
*/
for( i = 0; i < POPUP_COUNT; i++ )
pMenuHelpIDs[i*2+3] = (DWORD)GetSubMenu( hMenu, i );
// Load resource strings
LoadString(hInst, IDS_UNTITLED, strUntitled,
sizeof(strUntitled) / sizeof(*strUntitled));
LoadString(hInst, IDS_BYTES, szSizeFormat,
sizeof(szSizeFormat) / sizeof(*szSizeFormat));
// CountryCode - krishnag
if (bJapan) {
// if we're NT-J
hfontHelv = NULL;
hfontHelvBold = NULL;
} else {
// we're not NT-J
hfontHelv = CreateFont(GetHeightFromPointsString(sz8), 0, 0, 0, 400, 0, 0, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, szHelv);
hfontHelvBold = CreateFont(GetHeightFromPointsString(sz8), 0, 0, 0, 700, 0, 0, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, szHelv);
}
CreateMDIDefaultColumns( hWnd, MDIHEAD_JOB_COUNT, IDS_FIRST_HEADER_PRINTER,
MDIPrinterDefaultColumn, MDIPrinterMinimumCharacterWidth );
CreateMDIDefaultColumns( hWnd, MDIHEAD_PRINTER_COUNT, IDS_FIRST_HEADER_SERVER,
MDIServerDefaultColumn, MDIServerMinimumCharacterWidth );
hcursorArrow = LoadCursor( NULL, IDC_ARROW );
hcursorWait = LoadCursor( NULL, IDC_WAIT );
hcursorReorder = LoadCursor( hInst, MAKEINTRESOURCE( IDC_REORDER ) );
InitializeInternationalTimeConstants( );
// Setup clientcreate struct for MDI windows and menu
clientcreate.hWindowMenu = GetSubMenu(GetMenu(hWnd), POPUP_WINDOW);
clientcreate.idFirstChild = IDM_FIRSTCHILD;
GetClientRect(hWnd, &rc);
NetworkAccess = UserHasNetworkAccess( );
NetworkInstalled = NetworkIsInstalled( );
if( !NetworkAccess )
RemoveNetworkMenuItems( hWnd );
// Make toolbar window
hwndToolbar = PMCreateToolbar( NetworkAccess );
if (!hwndToolbar)
return -1L;
hwndClient = CreateWindow(TEXT("MDICLIENT"), NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL,
-dyBorder, -dyBorder + ( bToolBar ? DYTOOLBAR : 0 ),
rc.right, rc.bottom, hWnd,
(HMENU)1, hInst, (LPTSTR)&clientcreate);
hwndStatus = CreateWindow(STATUSCLASSNAME, TEXT(""),
WS_CHILD | WS_BORDER |
( bStatusBar ? WS_VISIBLE : 0 ),
-100, -100, 10, 10, hWnd,
(HMENU) ID_STATUSBAR, hInst, NULL);
SendMessage( hwndStatus, WM_SIZE, 0, 0L );
// SetStatusMode( STATUS_MODE_NORMAL, FALSE );
if (!hwndClient)
return -1L;
DragAcceptFiles( hWnd, TRUE );
PostMessage( hWnd, WM_INIT_PRINTER_WINDOWS, 0, 0 );
if( NetworkAccess )
PostMessage( hWnd, WM_INIT_SERVER_WINDOWS, 0, 0 );
return 0;
}
VOID CreateMDIDefaultColumns( HWND hwnd, DWORD cColumns, DWORD idFirstHeader,
PCOLUMN pColumns, PINT pDefaultWidths )
{
DWORD i;
TCHAR string[40];
HDC hdc;
int dx;
SIZE TxtSize;
SIZE DefSize;
/* Test buffer to check extent of default character width of columns.
* Must contain at least as many characters as the largest value in
* Server/PrinterMinimumCharacterWidth:
*/
TCHAR TestBuffer[] = TEXT("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
/* Load the heading strings:
*/
for( i = 0; i < cColumns; i++ )
{
LoadString(hInst, idFirstHeader + i, string,
sizeof string / sizeof *string);
if( !( pColumns[i].Text = AllocSplStr( string ) ) )
pColumns[i].Text = szNULL;
}
// Create columnar heading text fields in window
hdc = GetDC(hwnd);
for (i = 0; i < cColumns; i++)
{
SelectObject(hdc, hfontHelv);
GetTextExtentPoint (hdc, pColumns[i].Text,
_tcslen(pColumns[i].Text),
&TxtSize);
// Allow for space on either side of char string
dx = TxtSize.cx + 4 * cx;
if( pDefaultWidths[i] )
GetTextExtentPoint (hdc, TestBuffer, pDefaultWidths[i], &DefSize);
else
DefSize.cx = 0;
dx = max( dx, DefSize.cx );
pColumns[i].Width = dx;
}
ReleaseDC(hwnd, hdc);
}
/*
*
*/
VOID GetSystemColors( VOID )
{
SysColorHighlight = GetSysColor( COLOR_HIGHLIGHT );
SysColorHighlightText = GetSysColor( COLOR_HIGHLIGHTTEXT );
SysColorWindow = GetSysColor( COLOR_WINDOW );
SysColorWindowText = GetSysColor( COLOR_WINDOWTEXT );
SysColorBtnFace = GetSysColor( COLOR_BTNFACE );
SysColorBtnText = GetSysColor( COLOR_BTNTEXT );
SysColorBtnHighlight = GetSysColor( COLOR_BTNHIGHLIGHT );
SysColorBtnShadow = GetSysColor( COLOR_BTNSHADOW );
SysColorWindowFrame = GetSysColor( COLOR_WINDOWFRAME );
}
/* UserHasNetworkAccess
*
* Looks in the registry to see whether the Value under "Network" is set to 1.
*
* Three scenarios handled:
*
* 1. Key found and value == 1: Access granted
*
* 2. Key not found because it isn't there: Access granted
*
* 3. Key not found because of some other error: Access denied
*
*
* Return value:
*
* Boolean
*
*/
BOOL UserHasNetworkAccess( VOID )
{
DWORD AccessFlag;
DWORD rc;
BOOL AccessGranted;
REGISTRY_ENTRY RegistryNetworkEntry = { REG_DWORD, sizeof(DWORD) };
rc = ReadRegistryData( NULL, TEXT("Network"), (LPBYTE)&AccessFlag, &RegistryNetworkEntry );
switch( rc )
{
case NO_ERROR:
AccessGranted = ( AccessFlag == 1 );
break;
case ERROR_FILE_NOT_FOUND:
AccessGranted = TRUE;
break;
default:
AccessGranted = FALSE;
}
return AccessGranted;
}
/* RemoveNetworkMenuItems
*
* Removes the following menu items in the Printer pull-down:
*
* Connect to Printer...
* Remove Printer Connection
* Server Viewer...
* ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ (separator)
*
*/
VOID RemoveNetworkMenuItems( HWND hwnd )
{
HMENU hSubMenu;
/* Get the handle of the Printer pull-down menu:
*/
hSubMenu = GetSubMenu( GetMenu( hwnd ), 0 );
DeleteMenu( hSubMenu, 13, MF_BYPOSITION );
DeleteMenu( hSubMenu, IDM_SERVERVIEWER, MF_BYCOMMAND );
DeleteMenu( hSubMenu, IDM_CONNECTTOPRINTER, MF_BYCOMMAND );
// DeleteMenu( hSubMenu, IDM_REMOVECONNECTION, MF_BYCOMMAND );
}
/* NetworkIsInstalled
*
* This routine checks to see whether there is a value in the registry
* which will indicate that the network is installed.
*
* The alternative would be to call WNetOpenEnum, but this drags in
* MPR and other stuff.
*/
BOOL NetworkIsInstalled( VOID )
{
DWORD Status;
HKEY hkeyNetworkProviderOrder;
DWORD Size;
BOOL rc = FALSE;
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order"),
0, KEY_READ, &hkeyNetworkProviderOrder );
if( Status == NO_ERROR )
{
Status = RegQueryValueEx( hkeyNetworkProviderOrder,
TEXT("ProviderOrder"),
0,
NULL,
NULL,
&Size );
if( Status == NO_ERROR )
rc = TRUE;
RegCloseKey( hkeyNetworkProviderOrder );
}
return rc;
}
/* SetStatusMode
*
*/
VOID SetStatusMode( int Mode, BOOL Update )
{
INT RightOfPane[SF_COUNT];
RightOfPane[0] = dxStatPrtField;
RightOfPane[1] = dxStatPrtField + dxStatProgField;
RightOfPane[2] = dxStatPrtField + dxStatProgField + dxStatQueField;
switch( Mode )
{
case STATUS_MODE_NORMAL:
SendMessage( hwndStatus, SB_SIMPLE, FALSE, 0 );
SendMessage( hwndStatus, SB_SETPARTS, SF_COUNT, (LPARAM)RightOfPane );
SendMessage( hwndStatus, WM_SIZE, 0, 0L );
break;
case STATUS_MODE_HELP:
SendMessage( hwndStatus, SB_SIMPLE, TRUE, 0 );
SendMessage( hwndStatus, WM_SIZE, 0, 0L );
break;
}
if( Update )
UpdateStatus( NULL );
}
//
// Used to display any error message from worker threads.
// (This ensures even synchronization of multiple error message
// boxes and prevents the worker thread from any calling user.)
//
// We also check dwError for bit 29 (CustomerBit), which the
// Sendee can use as an extra bit of info.
//
LONG
FrameThreadError(
HWND hWnd,
PMDIWIN_INFO pMDIWinInfo,
DWORD dwError)
{
LPTSTR pErrorString;
BOOL bCustomerCode = FALSE;
if (pMDIWinInfo->Alive)
{
if (dwError & (1<<29))
{
bCustomerCode = TRUE;
//
// Now turn the bit off so we can use it normally with
// FormatMessage();
//
dwError &= ~(1<<29);
}
pErrorString = GetErrorString(dwError);
switch(pMDIWinInfo->WindowType)
{
case MDIWIN_SERVER:
//
// In InitServerWindowThread, we set bit 29 if the error
// indicates we couldn't open the server for auto refresh,
// but we could enumerate.
//
Message( hWnd,
MSG_ERROR,
IDS_PRINTMANAGER,
#if 0
//
// Turned off in threads.c, so turn off
// here.
//
bCustomerCode ?
IDS_COULDNOTOPENSERVERREFRESH :
#endif
IDS_COULDNOTGETSERVERINFO,
((PSERVER_CONTEXT)pMDIWinInfo->pContext)->pServerName,
pErrorString );
break;
default:
Message( hWnd,
MSG_ERROR,
IDS_PRINTMANAGER,
IDS_OPEN_PRINTER_FAILED,
((PQUEUE)pMDIWinInfo->pContext)->pPrinterName,
pErrorString );
break;
}
FreeSplStr( pErrorString );
}
return 0;
}
/*
*
*/
LONG FrameInitMenu(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PQUEUE pQueue = NULL;
PSERVER_CONTEXT pServerContext = NULL;
UINT State;
HMENU hMenu;
PPRINTER_INFO_2 pPrinter;
BOOL PrinterExists;
BOOL PrinterPaused;
BOOL DocumentExists;
BOOL DocumentSelected;
BOOL DocumentPaused;
BOOL PrinterIsLocal; // Undefined if !PrinterExists
BOOL UserHasServerAdminAccess = FALSE;
BOOL UserHasPrinterAdminAccess = FALSE;
BOOL ShowSecurity = FALSE;
BOOL PermitAuditing = FALSE;
BOOL ForceRefresh = TRUE;
// Disable (Grey) some menu items if there are no printers
// or if there are no jobs selected (or no jobs at all) on
// the active printer
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
hMenu = GetMenu(hWnd);
if( hwndChild && (pMDIWinInfo = GETMDIWIN( hwndChild )))
{
ENTER_PROTECTED_DATA( pMDIWinInfo );
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
{
pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
PrinterExists = ( pServerContext->cPrinters > 0 );
if( PrinterExists )
{
PrinterIsLocal = TRUE; // because it's local to the server we're looking at
pPrinter = pServerContext->pSelPrinter;
PrinterPaused = ( pPrinter->Status & PRINTER_STATUS_PAUSED );
}
/* Can't manipulate jobs from Server windows:
*/
DocumentExists = FALSE;
DocumentSelected = FALSE;
DocumentPaused = FALSE;
/* Need to check for this:
*/
UserHasServerAdminAccess =
( pServerContext->AccessGranted & SERVER_ACCESS_ADMINISTER );
/* Check whether the Printer Pause button is enabled.
* If so, the user must have Administer access on the selected printer:
*/
UserHasPrinterAdminAccess = IS_BUTTON_ENABLED( IDM_PRINTER_PAUSE );
/* Don't show Security options for server windows:
*/
ForceRefresh = FALSE;
}
else
{
pQueue = (PQUEUE)pMDIWinInfo->pContext;
pPrinter = pQueue->pPrinter;
PrinterExists = TRUE;
PrinterIsLocal = ( ( pMDIWinInfo->WindowType == MDIWIN_LOCALPRINTER )
||( pMDIWinInfo->WindowType == MDIWIN_LOCALNETWORKPRINTER ) );
if( pPrinter )
PrinterPaused = ( pPrinter->Status & PRINTER_STATUS_PAUSED );
else
PrinterPaused = FALSE;
if( ( !pPrinter )
||( pQueue->SelJobId == 0 )
||( pPrinter->cJobs == 0 ) )
{
if( !pPrinter || ( pPrinter->cJobs == 0 ) )
DocumentExists = FALSE;
else
DocumentExists = TRUE;
DocumentSelected = FALSE;
DocumentPaused = FALSE;
}
else
{
DocumentExists = TRUE;
DocumentSelected = TRUE;
DocumentPaused = ( pQueue->pSelJob->Status
& JOB_STATUS_PAUSED );
}
/* Administer privilege on the server is needed to create a printer:
*/
UserHasServerAdminAccess =
( LocalPermission & SERVER_ACCESS_ADMINISTER );
/* Administer privilege on the printer is needed to delete a printer:
*/
UserHasPrinterAdminAccess =
( pQueue->AccessGranted & PRINTER_ACCESS_ADMINISTER );
/* Always enable the Permissions and Take Ownership options.
* The user requires READ_CONTROL to see them, which he probably
* has:
*/
ShowSecurity = TRUE;
/* Auditing actually requires ACCESS_SYSTEM_SECURITY privilege.
*/
PermitAuditing = TRUE;
}
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
else
{
PrinterExists = FALSE;
PrinterPaused = FALSE;
DocumentExists = FALSE;
DocumentSelected = FALSE;
DocumentPaused = FALSE;
UserHasServerAdminAccess =
( LocalPermission & SERVER_ACCESS_ADMINISTER );
}
State = MF_BYCOMMAND | ( PrinterExists ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_FORMS, State);
State = MF_BYCOMMAND | ( ( ( PrinterExists && PrinterIsLocal && UserHasPrinterAdminAccess
/* We need a handle to delete the printer. */
/* This may not be so if it's down: */
&& ( pQueue ? (BOOL)pQueue->hPrinter : TRUE ) )
||( PrinterExists && !PrinterIsLocal ) ) ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_DELETEPRINTER, State);
// State = MF_BYCOMMAND | ( ( PrinterExists && !PrinterIsLocal ) ? MF_ENABLED : MF_GRAYED );
// EnableMenuItem(hMenu, IDM_REMOVECONNECTION, State);
State = MF_BYCOMMAND | ( ( PrinterExists && pPrinter ) ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_PROPERTIES, State);
if( UserHasPrinterAdminAccess )
{
State = MF_BYCOMMAND | ( ( PrinterExists && !PrinterPaused ) ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_PRINTER_PAUSE, State);
State = MF_BYCOMMAND | ( ( PrinterExists && PrinterPaused ) ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_PRINTER_RESUME, State);
State = MF_BYCOMMAND | ( DocumentExists ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_PURGEPRINTER, State);
}
else
{
/* Grey out both Pause and Resume Printer menu items if no Admin priv:
*/
State = MF_BYCOMMAND | MF_GRAYED;
EnableMenuItem(hMenu, IDM_PRINTER_PAUSE, State);
EnableMenuItem(hMenu, IDM_PRINTER_RESUME, State);
EnableMenuItem(hMenu, IDM_PURGEPRINTER, State);
}
State = MF_BYCOMMAND | ( DocumentSelected ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_REMOVEDOC, State);
EnableMenuItem(hMenu, IDM_DOCTAILS, State);
EnableMenuItem(hMenu, IDM_RESTART, State);
/* We can't get enough information to determine whether the user had
* Administer Document privilege, so we'll just have to enable the
* Pause or Resume Document menu item;
*/
State = MF_BYCOMMAND | ( ( DocumentSelected && !DocumentPaused ) ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_DOCUMENT_PAUSE, State);
State = MF_BYCOMMAND | ( ( DocumentSelected && DocumentPaused ) ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_DOCUMENT_RESUME, State);
State = MF_BYCOMMAND | ( hwndChild ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_CASCADE, State);
EnableMenuItem(hMenu, IDM_TILEHORZ, State);
EnableMenuItem(hMenu, IDM_TILEVERT, State);
EnableMenuItem(hMenu, IDM_ARRANGE, State);
EnableMenuItem(hMenu, IDM_REFRESH, State);
State = MF_BYCOMMAND | ( UserHasServerAdminAccess ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_INSTALLPRINTER, State);
State = MF_BYCOMMAND | ( ShowSecurity ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_PERMISSIONS, State);
EnableMenuItem(hMenu, IDM_OWNER, State);
State = MF_BYCOMMAND | ( PermitAuditing ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_AUDITING, State);
State = MF_BYCOMMAND | ( ForceRefresh ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_REFRESH, State);
State = MF_BYCOMMAND | ( NetworkInstalled ? MF_ENABLED : MF_GRAYED );
EnableMenuItem(hMenu, IDM_CONNECTTOPRINTER, State);
EnableMenuItem(hMenu, IDM_SERVERVIEWER, State);
return 0;
}
/*
*
*/
LONG FrameMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
UINT ItemID;
UINT Flags;
HMENU hmenu;
ItemID = (UINT)LOWORD( wParam );
Flags = (UINT)HIWORD( wParam );
hmenu = (HMENU)lParam;
/* HACK:
*
* If the item is in the "Windows" popup, but isn't between "Cascade"
* and "Refresh" it must be the name of an MDI window added by the system.
* We don't know the IDs of these added menu items - can we find out?
*/
if( ( (DWORD)hmenu == pMenuHelpIDs[POPUP_WINDOW*2+3] )
&&( ( ItemID < IDM_CASCADE ) || ( ItemID > IDM_REFRESH ) ) )
{
ItemID = IDS_HELP_MDIWINDOW;
WinHelpMenuID = ID_HELP_MDIWINDOW;
}
/* Another hack:
*
* If the item selected is IDM_DELETEPRINTER and the active window
* is a network printer, change it to the now obsolete IDM_REMOVECONNECTION,
* since this has more appropriate help information:
*/
if( ItemID == IDM_DELETEPRINTER )
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
if( hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L) )
{
pMDIWinInfo = GETMDIWIN( hwndChild );
if( ( pMDIWinInfo->WindowType == MDIWIN_NETWORKPRINTER )
||( pMDIWinInfo->WindowType == MDIWIN_LOCALNETWORKPRINTER ) )
ItemID = IDM_REMOVECONNECTION;
}
}
MenuHelp( WM_MENUSELECT, MAKEWPARAM( ItemID, HIWORD( wParam ) ), lParam,
GetMenu( hwnd ), hInst, hwndStatus, pMenuHelpIDs);
if( ItemID && ( Flags & MF_SYSMENU ) )
WinHelpMenuID = ID_HELP_FRAME_SYSMENU;
else
WinHelpMenuID = ItemID;
return 0;
}
/*
*
*/
LONG FramePaint(HWND hWnd)
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
}
/*
*
*/
VOID FrameSize(HWND hWnd, WPARAM Type, long Dimensions)
{
RECT rc;
int dx, dy;
int yToolbar, dyTB, yClientTop;
int ToolbarHeight;
if (Type != SIZEICONIC)
{
// make things look good by putting WS_BORDER on the
// client, then adjust the thing so it gets clipped
dx = LOWORD(Dimensions) + dyBorderx2;
dy = HIWORD(Dimensions) + dyBorderx2;
if (bStatusBar)
{
GetWindowRect( hwndStatus, &rc );
dy -= ( rc.bottom - rc.top - 1);
}
GetWindowRect( hwndToolbar, &rc );
ToolbarHeight = ( rc.bottom - rc.top );
if (bToolBar)
{
dy -= ToolbarHeight + 1;
yToolbar = -dyBorder;
dyTB = ToolbarHeight + dyBorder;
yClientTop = ToolbarHeight - dyBorder;
}
else
{
dy += 1;
yToolbar = -2 * ToolbarHeight;
dyTB = ToolbarHeight;
yClientTop = -dyBorder;
}
// Size the MDI CLIENT window
MoveWindow(hwndClient, -dyBorder, yClientTop, dx, dy, TRUE);
// Size the TOOLBAR window
MoveWindow(hwndToolbar, -dyBorder, yToolbar, dx, dyTB, TRUE);
// if (bStatusBar)
// {
// GetClientRect(hwndFrame, &rc);
// rc.top = rc.bottom - dyStatus;
// InvalidateRect(hWnd, &rc, TRUE);
// }
SendMessage( hwndStatus, WM_SIZE, 0, 0L );
/* Bug #14592
* Make sure the combo-box doesn't get detached:
*/
SendMessage( hwndPrinterList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0 );
}
}
/*
*
*/
VOID FrameClose(HWND hwnd)
{
int i;
HWND hwndMDI;
DWORD Options;
REGISTRY_ENTRY RegistrySaveSettings = { REG_DWORD, sizeof(DWORD) };
TCHAR SaveSettings[40];
Options = 0;
if( !bToolBar )
Options |= OPTION_NOTOOLBAR;
if( !bStatusBar )
Options |= OPTION_NOSTATUSBAR;
if( !bSaveSettings )
Options |= OPTION_NOSAVESETTINGS;
if( bSaveSettings )
{
/* First delete the sections in the INI file, so we don't need to worry
* if queues have been deleted or printer names have been changed
* (since we use the printer name as the INI key name):
*/
DeleteRegistryValues( szRegPrinters );
DeleteRegistryValues( szRegServers );
SaveWindowPos( hwnd, Options, FALSE );
for( hwndMDI = GetWindow( hwndClient, GW_CHILD );
hwndMDI;
hwndMDI = GetWindow( hwndMDI, GW_HWNDNEXT ) )
{
SaveWindowPos( hwndMDI, 0, TRUE );
}
}
LoadString(hInst, IDS_SAVE_SETTINGS, SaveSettings,
sizeof SaveSettings / sizeof *SaveSettings);
WriteRegistryData( NULL, SaveSettings,
(LPBYTE)&bSaveSettings,
&RegistrySaveSettings );
ClosePrinter( hLocalServer );
/* Ensure that any help instances go away.
* This does nothing if help hasn't been invoked:
*/
ShowHelp(hwnd, HELP_QUIT, 0);
}
/*
*
*/
VOID FrameHelp(HWND hwnd, UINT HelpID)
{
if( HelpID != 0 )
ShowHelp(hwnd, HELP_CONTEXT, HelpID);
else
ShowHelp(hwnd, HELP_INDEX, (DWORD)TEXT(""));
}
/* SaveWindowPos
*
* Saves Print Manager window positions in the registry.
* MDIWindow is FALSE for the main window.
*
*/
VOID SaveWindowPos( HWND hwnd, DWORD Options, BOOL MDIWindow )
{
PMDIWIN_INFO pMDIWinInfo = NULL;
LPTSTR pWindowName;
TCHAR WindowName[40];
LPTSTR pWindowType;
DWORD cbRegistryData;
DWORD cHeaders;
PREGISTRY_DATA pRegistryData;
INT i;
/* Get the size of the fixed part of the registry data:
*/
cbRegistryData = ( sizeof( REGISTRY_DATA ) - sizeof( pRegistryData->Headers ) );
/* Check there's some text.
* (We can't rely on return from GETMDIWIN, because there are some
* children of the MDI client that aren't MDI windows,
* and this causes a (non-fatal) exception because of the
* invalid index for that window.)
*/
GetWindowText( hwnd, WindowName, sizeof WindowName/sizeof(TCHAR) );
if( !*WindowName )
return;
if( !MDIWindow )
{
pWindowName = GetString( IDS_PRINTMANAGER );
pWindowType = NULL;
cHeaders = 0;
}
else
{
/* Don't use the actual window text for MDI windows,
* since a paused printer has the additional string " - Paused"
* in the title.
*/
pMDIWinInfo = GETMDIWIN( hwnd );
switch( pMDIWinInfo->WindowType )
{
case MDIWIN_SERVER:
default:
pWindowType = szRegServers;
pWindowName = ( (PSERVER_CONTEXT)pMDIWinInfo->pContext )->pServerName;
cHeaders = pMDIWinInfo->cColumns;
break;
case MDIWIN_LOCALPRINTER:
case MDIWIN_NETWORKPRINTER:
case MDIWIN_LOCALNETWORKPRINTER:
pWindowType = szRegPrinters;
pWindowName = ( (PQUEUE)pMDIWinInfo->pContext )->pPrinterName;
cHeaders = pMDIWinInfo->cColumns;
break;
}
}
cbRegistryData += ( cHeaders * sizeof pRegistryData->Headers );
pRegistryData = AllocSplMem( cbRegistryData );
if( !pRegistryData )
return;
/* Make sure there's a window title for the key name:
*/
if( *pWindowName )
{
pRegistryData->WindowPlacement.length =
sizeof(pRegistryData->WindowPlacement);
if( GetWindowPlacement( hwnd, &pRegistryData->WindowPlacement ) )
{
pRegistryData->Options = Options;
RegistryEntries.Size = cbRegistryData;
if( MDIWindow )
{
for( i = 0; i < pMDIWinInfo->cColumns; i++ )
pRegistryData->Headers[i] = pMDIWinInfo->pColumns[i].Width;
}
WriteRegistryData( pWindowType, pWindowName,
(LPBYTE)pRegistryData,
&RegistryEntries );
}
}
FreeSplMem( pRegistryData );
if( !MDIWindow )
FreeSplStr( pWindowName );
}
/*
*
*/
LONG FrameCommandConnectToPrinter(HWND hWnd)
{
HANDLE hPrinter;
LPPRINTER_INFO_2 pPrinter = NULL;
DWORD cbPrinter = 0;
PQUEUE pQueue;
HWND hwndActive;
PMDIWIN_INFO pInfo = NULL;
HWND hwndPrinter;
LPWSTR pszPrinterName;
SetCursor( hcursorWait );
hPrinter = ConnectToPrinterDlg( hWnd, 0 );
if( hPrinter )
{
if( GetGeneric( (PROC)GetPrinter, 2, (PBYTE *)&pPrinter, cbPrinter,
&cbPrinter, (PVOID)hPrinter, NULL ) )
{
//
// If it's local and not remote, yet it begins with \\,
// remove the server name since the server is the local
// machine, and the printer window won't have the server name.
//
// This handles the case when we attempt to connect to
// a local printer.
//
if ((pPrinter->Attributes & PRINTER_ATTRIBUTE_LOCAL) &&
!(pPrinter->Attributes & PRINTER_ATTRIBUTE_NETWORK) &&
pPrinter->pPrinterName[0] == BACKSLASH &&
pPrinter->pPrinterName[1] == BACKSLASH)
{
pszPrinterName = _tcsrchr(&pPrinter->pPrinterName[2], BACKSLASH);
pszPrinterName++;
}
else
{
pszPrinterName = pPrinter->pPrinterName;
}
hwndPrinter = FindPrinterWindow( pszPrinterName );
/* Don't create a new window if we already have a connexion
* to this printer:
*/
if( hwndPrinter )
{
SendMessage( hwndClient, WM_MDIACTIVATE, (WPARAM)hwndPrinter, 0L );
if( IsIconic( hwndPrinter ) )
ShowWindow( hwndPrinter, SW_RESTORE );
}
else
{
pQueue = AllocQueue( pPrinter->pPrinterName );
if( pQueue )
{
pQueue->Error = OpenThreadObject(pQueue->pPrinterName,
&pQueue->hPrinter,
&pQueue->AccessGranted,
MDIWIN_NETWORKPRINTER);
if( !pQueue->Error )
{
DWORD WindowType;
DWORD Flags = 0;
pQueue->pServerName = AllocSplStr( pPrinter->pServerName );
if( ALL_FLAGS_ARE_SET( pPrinter->Attributes,
PRINTER_ATTRIBUTE_NETWORK
| PRINTER_ATTRIBUTE_LOCAL ) )
WindowType = MDIWIN_LOCALNETWORKPRINTER;
else
WindowType = MDIWIN_NETWORKPRINTER;
if( pPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED )
Flags |= CREATE_PRINTER_SHARED;
CreateQueueWindow( hwndClient, pQueue,
pPrinter->Status,
WindowType,
Flags );
}
}
}
FreeSplMem( pPrinter );
}
ClosePrinter( hPrinter );
hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if( hwndActive )
pInfo = GETMDIWIN( hwndActive );
if( pInfo )
{
ENTER_PROTECTED_DATA( pInfo );
UpdateDefaultList();
UpdateStatus( (HWND)TRUE );
LEAVE_PROTECTED_DATA( pInfo );
}
if( hwndActive )
EnableCheckTBButtons(hwndActive);
}
SetCursor( hcursorArrow );
return 0;
}
/*
*
*/
LONG FrameCommandCreatePrinter(HWND hWnd)
{
PQUEUE pNewQueue;
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PRT_PROP_DLG_DATA PrtPropDlgData;
LPPRINTER_INFO_2 pPrinter = NULL;
DWORD cbPrinter = 0;
BOOL Error = FALSE;
BOOL Remote = FALSE;
/* Create a new window for this Print Queue and get Printer
* Properties.
*/
if (!(pNewQueue = AllocQueue(TEXT(""))))
return 0;
hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0L);
/* If the active window is iconic, don't worry whether it's a Server Viewer,
* we'll assume that the user wants to create the printer locally:
*/
if( hwndChild && !IsIconic( hwndChild ) )
pMDIWinInfo = GETMDIWIN( hwndChild );
else
pMDIWinInfo = NULL;
ZERO_OUT( &PrtPropDlgData );
/* If this is a Server Viewer, set up the server name field.
* (Otherwise it's NULL.)
*/
if( pMDIWinInfo && ( pMDIWinInfo->WindowType == MDIWIN_SERVER ) )
{
PSERVER_CONTEXT pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
Remote = TRUE;
if( pServerContext->pServerName )
PrtPropDlgData.pServerName = AllocSplStr( pServerContext->pServerName );
}
else
{
PrtPropDlgData.pServerName = NULL;
}
SetCursor( hcursorWait );
if( EnumGeneric( (PROC)EnumPrintProcessors,
1,
(PBYTE *)&PrtPropDlgData.pPrintProcessors,
0,
&PrtPropDlgData.cbPrintProcessors,
&PrtPropDlgData.cPrintProcessors,
PrtPropDlgData.pServerName,
NULL, /* pEnvironment */
NULL ) ) /* (ignored) */
{
if( DialogBoxParam( hInst, MAKEINTRESOURCE( DLG_PRTPROP ), hWnd,
(DLGPROC)PrtPropDlg, (DWORD)&PrtPropDlgData ) == IDOK )
{
if( !Remote )
{
DWORD Flags = 0;
SetCursor( hcursorWait );
pNewQueue->pServerName = AllocSplStr(PrtPropDlgData.pServerName);
pNewQueue->pPrinterName = PrtPropDlgData.pPrinterName;
pNewQueue->hPrinter = PrtPropDlgData.hPrinter;
/* Save ourselves the bother of opening the printer again.
* We must have Admin privilege if we just created it:
*/
pNewQueue->AccessGranted |= PRINTER_ACCESS_ADMINISTER;
if( PrtPropDlgData.PrinterShared )
Flags |= CREATE_PRINTER_SHARED;
/* From here on, hwndChild is the new window:
*/
if( !( hwndChild = CreateQueueWindow( hWnd, pNewQueue, 0,
MDIWIN_LOCALPRINTER,
Flags ) ) )
Error = TRUE;
else
{
PrinterAdded = TRUE;
if( GetGeneric( (PROC)GetPrinter, 2, (PBYTE *)&pPrinter, cbPrinter,
&cbPrinter, (PVOID)pNewQueue->hPrinter, NULL ) )
{
/* Change the icon for shared printers:
*/
if( pPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED )
{
pMDIWinInfo = GETMDIWIN( hwndChild );
pMDIWinInfo->hicon = hiconShared;
}
FreeSplMem( pPrinter );
}
}
}
else
FreeQueue( pNewQueue );
}
else
Error = TRUE;
FreeSplMem( PrtPropDlgData.pPrintProcessors );
}
else
{
Message( hWnd, MSG_ERROR, IDS_PRINTMANAGER, IDS_NO_PRINT_PROCESSORS );
Error = TRUE;
}
if( Error )
{
FreeQueue (pNewQueue);
return 0;
}
if( PrtPropDlgData.pServerName )
FreeSplStr( PrtPropDlgData.pServerName );
if( !Remote )
{
PrinterProperties(hWnd, pNewQueue->hPrinter);
}
UpdateDefaultList();
SetCursor( hcursorArrow );
return 0;
}
/*
*
*/
LONG FrameCommandProperties(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PRT_PROP_DLG_DATA PrtPropDlgData;
PQUEUE pQueue;
PSERVER_CONTEXT pServerContext;
BOOL OK = FALSE;
DWORD OldAttributes;
hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pMDIWinInfo = GETMDIWIN( hwndChild );
ENTER_PROTECTED_DATA( pMDIWinInfo );
ZERO_OUT( &PrtPropDlgData );
SetCursor( hcursorWait );
EnumGeneric( (PROC)EnumPrintProcessors,
1,
(PBYTE *)&PrtPropDlgData.pPrintProcessors,
0,
&PrtPropDlgData.cbPrintProcessors,
&PrtPropDlgData.cPrintProcessors,
PrtPropDlgData.pServerName,
NULL, /* pEnvironment */
NULL ); /* (ignored) */
if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
{
pQueue = (PQUEUE)pMDIWinInfo->pContext;
/* Take a copy of the printer info, so that the dialog can scrawl
* over it without causing any problems.
* (This doesn't copy the strings and other buffers, only the pointers.)
*/
if( !( PrtPropDlgData.pPrinter = AllocSplMem( sizeof( PRINTER_INFO_2 ) ) ) )
return 0;
memcpy( PrtPropDlgData.pPrinter, pQueue->pPrinter, sizeof( PRINTER_INFO_2 ) );
PrtPropDlgData.pServerName = pQueue->pServerName;
PrtPropDlgData.pMDIWinInfo = pQueue->pMDIWinInfo;
PrtPropDlgData.hPrinter = pQueue->hPrinter;
PrtPropDlgData.AccessGranted = pQueue->AccessGranted;
PrtPropDlgData.ServerAccessGranted = LocalPermission;
OldAttributes = PrtPropDlgData.pPrinter->Attributes;
OK = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_PRTPROP), hWnd,
(DLGPROC)PrtPropDlg, (DWORD)&PrtPropDlgData );
if( PrtPropDlgData.DriverChanged )
PrinterProperties(hWnd, pQueue->hPrinter);
/* If this is a local printer, and the shared attribute has changed,
* change the window's icon:
*/
if( OK
&&( pMDIWinInfo->WindowType == MDIWIN_LOCALPRINTER )
&&( (BOOL)( OldAttributes & PRINTER_ATTRIBUTE_SHARED )
!=( PrtPropDlgData.PrinterShared ) ) )
{
if( PrtPropDlgData.PrinterShared )
pMDIWinInfo->hicon = hiconShared;
else
pMDIWinInfo->hicon = hiconPrinter;
/* If the printer's MDI window is in iconic state,
* ensure that it gets repainted with the new icon:
*/
if( IsIconic( hwndChild ) )
InvalidateRect( hwndChild, NULL, TRUE );
}
}
else
{
pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
if( ( pServerContext->pSelPrinter )
&&( OpenPrinterForSpecifiedAccess(
pServerContext->pSelPrinter->pPrinterName,
&PrtPropDlgData.hPrinter,
PRINTER_ACCESS_HIGHEST_PERMITTED,
&PrtPropDlgData.AccessGranted ) ) )
{
PrtPropDlgData.pServerName = pServerContext->pServerName;
if( !( PrtPropDlgData.pPrinter = AllocSplMem( sizeof( PRINTER_INFO_2 ) ) ) )
return 0;
memcpy( PrtPropDlgData.pPrinter, pServerContext->pSelPrinter,
sizeof( PRINTER_INFO_2 ) );
PrtPropDlgData.pMDIWinInfo = pServerContext->pMDIWinInfo;
PrtPropDlgData.ServerAccessGranted = pServerContext->AccessGranted;
OK = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_PRTPROP), hWnd,
(DLGPROC)PrtPropDlg, (DWORD)&PrtPropDlgData );
if( OK )
{
if( PrtPropDlgData.DriverChanged )
{
PrinterProperties(hWnd, PrtPropDlgData.hPrinter);
}
}
ClosePrinter( PrtPropDlgData.hPrinter );
}
else
{
ReportFailure( hWnd, 0, IDS_COULDNOTOPENPRINTER );
}
}
if( OK )
FreeSplStr( PrtPropDlgData.pPrinterName );
FreeSplMem( PrtPropDlgData.pPrinter );
if (PrtPropDlgData.pPrintProcessors)
FreeSplMem( PrtPropDlgData.pPrintProcessors );
LEAVE_PROTECTED_DATA( pMDIWinInfo );
return 0;
}
/*
*
*/
LONG
FrameCommandDeletePrinter(
HWND hWnd)
{
HWND hwndMDIActive;
DBG_UNREFERENCED_PARAMETER(hWnd);
hwndMDIActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndMDIActive)
return 0;
return FrameCommandDeletePrinterHelper(hWnd, hwndMDIActive, TRUE);
}
LONG
FrameCommandDeletePrinterHelper(
HWND hWnd,
HWND hwndMDI,
BOOL bConfirm)
{
BOOL OK = FALSE;
PVOID pContext;
PMDIWIN_INFO pMDIWinInfo = GETMDIWIN( hwndMDI );
if (!pMDIWinInfo)
return 0;
if (pMDIWinInfo->Status & PRINTER_STATUS_LOADING) {
Message( hWnd, MSG_INFORMATION, IDS_PRINTMANAGER, IDS_PRINTER_NOT_LOADED);
return 0;
}
ENTER_PROTECTED_DATA( pMDIWinInfo );
pContext = pMDIWinInfo->pContext;
switch( pMDIWinInfo->WindowType )
{
case MDIWIN_LOCALPRINTER:
OK = DeleteLocalPrinter(hWnd, hwndMDI, (PQUEUE)pContext, bConfirm);
break;
case MDIWIN_SERVER:
OK = DeleteRemotePrinter(hWnd, (PSERVER_CONTEXT)pContext, bConfirm);
break;
case MDIWIN_NETWORKPRINTER:
case MDIWIN_LOCALNETWORKPRINTER:
OK = DeleteConnection(hWnd, hwndMDI, (PQUEUE)pContext, bConfirm);
break;
}
LEAVE_PROTECTED_DATA( pMDIWinInfo );
if( OK )
{
UpdateDefaultList();
/* If this was the last printer, we need to update the toolbar buttons:
*/
if(!SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L))
{
EnableCheckTBButtons(NULL);
UpdateStatus(NULL);
}
else
{
hwndMDI = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
pMDIWinInfo = GETMDIWIN( hwndMDI );
ENTER_PROTECTED_DATA( pMDIWinInfo );
UpdateStatus(hwndMDI);
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
}
else
{
ReportFailure( hWnd,
IDS_INSUFFPRIV_DELETEPRINTER,
IDS_COULDNOTDELETEPRINTER );
}
return 0;
}
/*
*
*/
BOOL DeleteLocalPrinter(HWND hwnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm)
{
LPTSTR pPrinterName;
HANDLE hPrinter;
BOOL OK = TRUE;
pPrinterName = pQueue->pPrinterName;
hPrinter = pQueue->hPrinter;
/* Put up fairly innocuous confirmation message:
*/
if( !bConfirm || (Message( hwnd, MSG_YESNO, IDS_PRINTMANAGER, IDS_CONFIRMDELETE,
pPrinterName ) == IDYES) )
{
OK = DeletePrinter (hPrinter);
if( OK )
{
DBG_IN_PROTECTED_DATA( pQueue->pMDIWinInfo );
KillMDIWinInfo(pQueue->pMDIWinInfo);
if (SendMessage(hwndMDI, WM_QUERYENDSESSION, 0, 0L))
SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndMDI, 0L);
DBGMSG( DBG_TRACE, ( "Window destroyed\n" ) );
}
}
return OK;
}
/*
*
*/
BOOL
DeleteRemotePrinter(
HWND hwnd,
PSERVER_CONTEXT pServerContext,
BOOL bConfirm)
{
LPTSTR pPrinterName;
LPTSTR pServerName;
HANDLE hPrinter;
HWND hwndPrinter = NULL;
BOOL OK = TRUE;
pServerName = pServerContext->pServerName;
pPrinterName = pServerContext->pSelPrinter->pPrinterName;
/* Get a handle to the printer:
*/
if( OpenPrinterForSpecifiedAccess( pPrinterName, &hPrinter,
PRINTER_ALL_ACCESS, NULL ) )
{
/* Put up scary message up to make sure they're sure they're sure:
*/
if( !bConfirm || (Message( hwnd, MSG_YESNO | MB_DEFBUTTON2, IDS_PRINTMANAGER,
IDS_CONFIRMDELETEREMOTE,
pServerName, pPrinterName ) == IDYES) )
{
/* Do it:
*/
if( OK = DeletePrinter (hPrinter))
{
PMDIWIN_INFO pMDIWinInfo = GETMDIWIN( hwndPrinter );
/* Now see if we have any connections to this printer:
*/
hwndPrinter = FindPrinterWindow( pPrinterName );
if( hwndPrinter )
{
if( pMDIWinInfo )
{
DBG_IN_PROTECTED_DATA( pMDIWinInfo );
KillMDIWinInfo(pMDIWinInfo);
}
else
{
DBGMSG( DBG_WARNING, ( "No MDIWinInfo in DeleteRemotePrinter\n" ) );
}
/* Blow away the MDI window:
*/
if (SendMessage(hwndPrinter, WM_QUERYENDSESSION, 0, 0L))
SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndPrinter, 0L);
/* Get rid of the connection:
*/
DeletePrinterConnection( pPrinterName );
}
}
}
//
// Close it!
//
ClosePrinter(hPrinter);
}
return OK;
}
/*
*
*/
BOOL DeleteConnection(HWND hWnd, HWND hwndMDI, PQUEUE pQueue, BOOL bConfirm)
{
LPTSTR pPrinterName;
BOOL OK;
DBG_UNREFERENCED_PARAMETER(hWnd);
pPrinterName = pQueue->pPrinterName;
/* Put up fairly innocuous confirmation message:
*/
if( !bConfirm || (Message( hWnd, MSG_YESNO, IDS_PRINTMANAGER, IDS_CONFIRMDELETECONNECTION,
pPrinterName ) == IDYES) )
{
/* This is a special case of a local printer masquerading
* as a network printer.
*/
if( pQueue->pMDIWinInfo->WindowType == MDIWIN_LOCALNETWORKPRINTER ) {
OK = DeletePrinter( pQueue->hPrinter );
if (OK)
{
if (pQueue->pPrinter && pQueue->pPrinter->pPortName)
{
//
// ignore errors from below
//
(void)WNetCancelConnection(pQueue->pPrinter->pPortName,
TRUE) ;
(void)RemoveFromReconnectList(pQueue->pPrinter->pPortName) ;
}
}
} else
OK = DeletePrinterConnection( pPrinterName );
if( OK )
{
DBG_IN_PROTECTED_DATA( pQueue->pMDIWinInfo );
KillMDIWinInfo(pQueue->pMDIWinInfo);
if (SendMessage(hwndMDI, WM_QUERYENDSESSION, 0, 0L))
SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndMDI, 0L);
return TRUE;
}
else
return FALSE;
}
}
/* FindPrinterWindow
*
* Cycles through the MDI child windows until it finds a printer window
* whose name matches that supplied.
*
* andrewbe - April 1992
*/
HWND FindPrinterWindow( LPTSTR pPrinterName )
{
HWND hwndMDI;
BOOL Found;
PMDIWIN_INFO pMDIWinInfo;
for( hwndMDI = GetWindow( hwndClient, GW_CHILD ), Found = FALSE;
hwndMDI && !Found;
hwndMDI = Found ? hwndMDI : GetWindow( hwndMDI, GW_HWNDNEXT ) )
{
pMDIWinInfo = GETMDIWIN( hwndMDI );
if( pMDIWinInfo && ( pMDIWinInfo->WindowType != MDIWIN_SERVER ) )
if( !_tcscmp( ( (PQUEUE)pMDIWinInfo->pContext )->pPrinterName, pPrinterName ) )
Found = TRUE;
}
return (Found ? hwndMDI : NULL);
}
/*
*
*/
LONG
FrameCommandPrinterPauseResume(
HWND hWnd,
BOOL bPause)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PQUEUE pQueue;
PSERVER_CONTEXT pServerContext;
PPRINTER_INFO_2 pPrinter = NULL;
HANDLE hPrinter = NULL;
BOOL ErrorOccurred = FALSE;
DBG_UNREFERENCED_PARAMETER(hWnd);
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pMDIWinInfo = GETMDIWIN( hwndChild );
ENTER_PROTECTED_DATA( pMDIWinInfo );
if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
{
pQueue = (PQUEUE)pMDIWinInfo->pContext;
hPrinter = pQueue->hPrinter;
pPrinter = pQueue->pPrinter;
}
else
{
pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
pPrinter = pServerContext->pSelPrinter;
if( pPrinter )
OpenPrinterForSpecifiedAccess( pPrinter->pPrinterName, &hPrinter,
PRINTER_ALL_ACCESS, NULL );
}
if( pPrinter && hPrinter )
{
if(!SetPrinter(hPrinter,
0,
NULL,
bPause ?
PRINTER_CONTROL_PAUSE :
PRINTER_CONTROL_RESUME))
{
ErrorOccurred = TRUE;
CheckTBButton(bPause ?
IDM_PRINTER_RESUME :
IDM_PRINTER_PAUSE);
if( bPause )
ReportFailure( hWnd,
IDS_INSUFFPRIV_PAUSEPRINTER,
IDS_COULDNOTPAUSEPRINTER );
else
ReportFailure( hWnd,
IDS_INSUFFPRIV_RESUMEPRINTING,
IDS_COULDNOTRESUMEPRINTING );
}
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
{
ClosePrinter( hPrinter );
}
// /* For Printer windows, add or remove " - Paused" from the titlebar:
// */
// else if( !ErrorOccurred )
// {
// SetPrinterTitle( hwndChild, pQueue->pPrinterName,
// ( bPause
// ? PRINTER_STATUS_PAUSED : 0 ) );
// }
// Force a refresh of the queue window until spooler sends messages
// back to PrintMan
if( !ErrorOccurred )
CheckTBButton(bPause ?
IDM_PRINTER_PAUSE :
IDM_PRINTER_RESUME);
// UpdateStatus((HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L));
}
LEAVE_PROTECTED_DATA( pMDIWinInfo );
return 0;
}
/*
*
*/
BOOL SetPrinterTitle( HWND hwnd, PTCHAR pPrinterName, DWORD Status )
{
TCHAR Title[80];
TCHAR StatusString[40];
PTCHAR pTitle;
if( Status )
{
GetPrinterStatusString( Status, StatusString );
_stprintf( Title, szTitleFormat, pPrinterName, StatusString );
pTitle = Title;
}
else
pTitle = pPrinterName;
return SetWindowText( hwnd, pTitle );
}
/* SetMDITitle
*
* Sets the title, appending status information where appropriate.
*
*/
BOOL SetMDITitle( HWND hwnd, PMDIWIN_INFO pInfo )
{
TCHAR Title[80];
TCHAR StatusString[40];
if( pInfo->WindowType != MDIWIN_SERVER )
{
PQUEUE pPrinterContext = pInfo->pContext;
LPPRINTER_INFO_2 pPrinter;
if( pPrinter = pPrinterContext->pPrinter )
{
if( !pPrinter->pPrinterName )
{
/* This should not happen!!
* (It did.)
*/
DBGMSG( DBG_WARNING, ( "SetMDITitle for %ws called with NULL pPrinter->pPrinterName\n",
pPrinterContext->pPrinterName ) );
return FALSE;
}
/* Check whether the printer name has changed,
* and, if so, update it:
*/
if( _tcscmp( pPrinterContext->pPrinterName,
pPrinter->pPrinterName ) )
{
//
// We need to remove the old connection for remote cases
// (true connections only).
//
// It should do a rename, since at some later time we
// may want to store info like "created at 10:00."
//
//
if (pInfo->WindowType == MDIWIN_NETWORKPRINTER) {
DeletePrinterConnection(pPrinterContext->pPrinterName);
AddPrinterConnection(pPrinter->pPrinterName);
}
ReallocSplStr( &pPrinterContext->pPrinterName,
pPrinter->pPrinterName );
}
/* There is some information for this printer:
*/
if( pPrinter->Status )
{
GetPrinterStatusString( pPrinter->Status, StatusString );
_stprintf( Title, szTitleFormat, pPrinterContext->pPrinterName,
StatusString );
}
else
{
_tcscpy( Title, pPrinter->pPrinterName );
}
}
else
{
if( pPrinterContext->Error == ERROR_ACCESS_DENIED )
GetPrinterStatusString( PRINTER_STATUS_ACCESS_DENIED, StatusString );
else
GetPrinterStatusString( PRINTER_STATUS_UNKNOWN, StatusString );
_stprintf( Title, szTitleFormat, pPrinterContext->pPrinterName,
StatusString );
}
}
else
{
PSERVER_CONTEXT pServerContext = pInfo->pContext;
LPTSTR pServerViewerTitle;
TCHAR TempTitle[80];
/* Get "Server: %s":
*/
pServerViewerTitle = GetString( IDS_SERVERVIEWERTITLE );
if( pServerContext->Error )
{
_stprintf( TempTitle, pServerViewerTitle, pServerContext->pServerName );
GetPrinterStatusString( PRINTER_STATUS_UNKNOWN, StatusString );
_stprintf( Title, szTitleFormat, TempTitle,
StatusString );
}
else
{
_stprintf( Title, pServerViewerTitle, pServerContext->pServerName );
}
FreeSplStr( pServerViewerTitle );
}
return SetWindowText( hwnd, Title );
}
/*
*
*/
LONG FrameCommandPurgePrinter(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PQUEUE pQueue;
// Delete all the documents in the active window
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pMDIWinInfo = GETMDIWIN( hwndChild );
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
return 0;
ENTER_PROTECTED_DATA( pMDIWinInfo );
pQueue = GETQUEUE( hwndChild );
if( Message( hWnd, MSG_CONFIRMATION, IDS_PRINTMANAGER,
IDS_DELETEALLPRINTJOBS_S, pQueue->pPrinterName ) == IDOK )
{
if( !SetPrinter(pQueue->hPrinter, 0, NULL, PRINTER_CONTROL_PURGE))
{
ReportFailure( hWnd,
IDS_INSUFFPRIV_PURGEPRINTER,
IDS_COULDNOTPURGEPRINTER );
}
else
{
EnableCheckTBButtons(hwndChild);
UpdateStatus(hwndChild);
}
}
LEAVE_PROTECTED_DATA( pMDIWinInfo );
return 0;
}
/*
*
*/
LONG FrameCommandForms(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PQUEUE pQueue;
PSERVER_CONTEXT pServerContext;
PPRINTER_INFO_2 pPrinter;
FORMS_DLG_DATA FormsDlgData;
PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL,
SERVER_ALL_ACCESS };
HANDLE hServer = NULL;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pMDIWinInfo = GETMDIWIN( hwndChild );
ZERO_OUT( &FormsDlgData );
if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
{
pQueue = (PQUEUE)pMDIWinInfo->pContext;
FormsDlgData.pServerName = NULL;
FormsDlgData.hPrinter = pQueue->hPrinter;
if( pQueue->pServerName )
{
if (OpenPrinter(pQueue->pServerName,
&hServer,
&PrinterDefaults)) {
FormsDlgData.AccessGranted = SERVER_ACCESS_ADMINISTER;
} else {
FormsDlgData.AccessGranted = 0;
}
}
else
FormsDlgData.AccessGranted = LocalPermission;
}
else
{
pServerContext = (PSERVER_CONTEXT)pMDIWinInfo->pContext;
pPrinter = pServerContext->pSelPrinter;
if( pPrinter )
OpenPrinterForSpecifiedAccess( pPrinter->pPrinterName,
&FormsDlgData.hPrinter,
PRINTER_READ,
NULL );
FormsDlgData.pServerName = pServerContext->pServerName;
if( OpenPrinter( pServerContext->pServerName, &hServer,
&PrinterDefaults ) )
{
FormsDlgData.AccessGranted = SERVER_ACCESS_ADMINISTER;
}
}
if( FormsDlgData.hPrinter )
{
SetCursor( hcursorWait );
DialogBoxParam( hInst, MAKEINTRESOURCE( DLG_FORMS ), hWnd,
(DLGPROC)FormsDlg, (DWORD)&FormsDlgData );
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
{
ClosePrinter( FormsDlgData.hPrinter );
}
if( hServer )
{
ClosePrinter( hServer );
}
}
return 0;
}
/* Invoke a network browse dialog to set the focus on a
* particular computer
*/
LONG FrameCommandServerViewer(HWND hwnd)
{
HANDLE hLibrary;
LPFNI_SYSTEMFOCUSDIALOG lpfnI_SFD;
WCHAR ServerName[UNCLEN+1];
BOOL fOK;
DWORD Error;
HWND hwndActive;
PMDIWIN_INFO pMDIWinInfo;
SetCursor( hcursorWait );
lpfnI_SFD = (LPFNI_SYSTEMFOCUSDIALOG)LoadLibraryGetProcAddress(
hwnd, szNtLanMan, szI_SystemFocusDialog, &hLibrary);
if(lpfnI_SFD)
{
Error = (*lpfnI_SFD)(hwnd,
FOCUSDLG_SERVERS_ONLY | FOCUSDLG_BROWSE_ALL_DOMAINS,
(LPWSTR)ServerName,
sizeof(ServerName)/sizeof(WCHAR), &fOK, szLPrintManHlp,
ID_HELP_SERVERVIEWER );
SetCursor( hcursorWait );
if( Error == NO_ERROR )
{
if( fOK )
{
PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL,
SERVER_ALL_ACCESS };
HANDLE hServer = NULL;
/* Convert the string we received from NETUI to ANSI:
*/
wsprintf( ServerName, TEXT("%ls"), ServerName );
//
// Attempt to open the server. Trap the ERROR_ACCESS_DENIED
// error so that we can open servers that exist but
// we don't have auto-refresh access to.
//
if( !OpenPrinter( ServerName, &hServer, &PrinterDefaults ) )
{
LPTSTR pErrorString;
DWORD dwError;
dwError = GetLastError();
//
// Special case this error code into a success
// case, with hServer == -1 to indicate a failed
// OpenPrinter.
//
if (dwError == ERROR_ACCESS_DENIED)
{
hServer = (HANDLE)-1;
goto CreateServer;
}
pErrorString = GetErrorString( GetLastError( ) );
Message( hwnd, MSG_ERROR, IDS_PRINTMANAGER,
IDS_COULDNOTGETSERVERINFO, ServerName,
pErrorString );
FreeSplStr( pErrorString );
}
else
{
CreateServer:
CreateServerWindow( hwnd, ServerName, hServer );
}
}
}
FreeLibrary(hLibrary);
}
hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if( hwndActive )
{
pMDIWinInfo = GETMDIWIN( hwndActive );
ENTER_PROTECTED_DATA( pMDIWinInfo );
UpdateStatus(hwndActive);
EnableCheckTBButtons(hwndActive);
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
SetCursor( hcursorArrow );
return 0;
}
/*
*
*/
#ifdef LATER
LONG FrameCommandChangePrinter(HWND hWnd)
{
HWND hwndChild;
PQUEUE pQueue;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pQueue = GETQUEUE( hwndChild );
if (DialogBoxParam(hInst, TEXT("PRINTER"), hWnd, (DLGPROC)PrinterDlg,
(DWORD)pQueue) == IDOK)
{
if (pQueue->RedoPrinterProperties)
{
PrinterProperties(hWnd, pQueue->hPrinter);
pQueue->RedoPrinterProperties = FALSE;
}
}
return 0;
}
#endif /* LATER */
/*
*
*/
LONG FrameCommandRemoveDoc(HWND hWnd)
{
HWND hwndChild;
PQUEUE pQueue;
// Delete the selected document in the active window
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
if( ( GETMDIWIN( hwndChild ) )->WindowType == MDIWIN_SERVER )
return 0;
pQueue = GETQUEUE( hwndChild );
if( DeleteQJ(hwndChild, pQueue) != 0 )
{
ReportFailure( hWnd,
IDS_INSUFFPRIV_DELETEDOCUMENT,
IDS_COULDNOTREMOVEDOCUMENT );
}
// Force a refresh of the queue window until spooler sends messages
// back to PrintMan
EnableCheckTBButtons(hwndChild);
// UpdateStatus((HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L));
return 0;
}
/*
*
*/
LONG FrameCommandDocDetails(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PQUEUE pQueue;
// Invoke the document details dialog for selected doc in active window
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pMDIWinInfo = GETMDIWIN( hwndChild );
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
return 0;
ENTER_PROTECTED_DATA( pMDIWinInfo );
pQueue = GETQUEUE( hwndChild );
if (pQueue->pSelJob == NULL){
goto Done;
}
SetCursor( hcursorWait );
DialogBoxParam (hInst, MAKEINTRESOURCE(DLG_DOCTAILS), hWnd,
(DLGPROC)DocDetailsDlg, (DWORD)pQueue);
SetCursor( hcursorArrow );
Done:
LEAVE_PROTECTED_DATA( pMDIWinInfo );
return 0;
}
/*
*
*/
LONG FrameCommandDocumentPauseResume(HWND hWnd, WORD PauseResume)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PQUEUE pQueue;
DBG_UNREFERENCED_PARAMETER(hWnd);
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pMDIWinInfo = GETMDIWIN( hwndChild );
if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
{
ENTER_PROTECTED_DATA( pMDIWinInfo );
pQueue = (PQUEUE)pMDIWinInfo->pContext;
if( !pQueue->pSelJob )
{
/* This shouldn't happen, but did once!
*/
DBGMSG( DBG_WARNING, ( "FrameCommandDocumentPauseResume called with no job selected" ) );
}
else if (!SetJob(pQueue->hPrinter,
pQueue->pSelJob->JobId,
0, NULL,
( ( pQueue->pSelJob->Status & JOB_STATUS_PAUSED )
? JOB_CONTROL_RESUME
: JOB_CONTROL_PAUSE ) ) )
{
CheckTBButton( ( PauseResume == IDM_DOCUMENT_PAUSE )
? IDM_DOCUMENT_RESUME
: IDM_DOCUMENT_PAUSE );
if( PauseResume == IDM_DOCUMENT_PAUSE )
ReportFailure( hWnd,
IDS_INSUFFPRIV_PAUSEDOCUMENT,
IDS_COULDNOTPAUSEDOCUMENT );
else
ReportFailure( hWnd,
IDS_INSUFFPRIV_RESUMEDOCUMENT,
IDS_COULDNOTRESUMEDOCUMENT );
}
else
CheckTBButton(PauseResume);
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
return 0;
}
/*
*
*/
LONG FrameCommandRestart(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
PQUEUE pQueue;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
pMDIWinInfo = GETMDIWIN( hwndChild );
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
return 0;
pQueue = GETQUEUE( hwndChild );
if( pQueue->SelJobId )
{
ENTER_PROTECTED_DATA( pMDIWinInfo );
// Cancel the print job
if( !SetJob( pQueue->hPrinter,
pQueue->SelJobId,
0, NULL,
JOB_CONTROL_RESTART ) )
{
ReportFailure( hWnd,
IDS_INSUFFPRIV_RESTARTDOCUMENT,
IDS_COULDNOTRESTARTDOCUMENT );
}
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
// Force a refresh of the queue window until spooler sends messages
// back to PrintMan
EnableCheckTBButtons(hwndChild);
return 0;
}
/*
*
*/
LONG FrameCommandFont(HWND hWnd)
{
return 0;
UNREFERENCED_PARAMETER(hWnd);
}
/*
*
*/
LONG FrameCommandRefreshRate(HWND hWnd)
{
return 0;
UNREFERENCED_PARAMETER(hWnd);
}
/*
*
*/
LONG FrameCommandToolbar(HWND hWnd)
{
RECT rc;
bToolBar = !bToolBar;
ShowWindow( hwndToolbar, bToolBar ? SW_SHOW : SW_HIDE );
GetClientRect(hwndFrame, &rc);
SendMessage(hwndFrame, WM_SIZE, SIZENORMAL, MAKELONG(rc.right, rc.bottom));
InvalidateRect(hwndFrame, NULL, TRUE);
CheckMenuItem(GetMenu(hWnd), IDM_TOOLBAR,
MF_BYCOMMAND | (bToolBar ? MF_CHECKED : MF_UNCHECKED));
return 0;
}
/*
*
*/
LONG FrameCommandStatusbar(HWND hWnd)
{
PMDIWIN_INFO pInfo;
HWND hwndChild;
RECT rc;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
bStatusBar = !bStatusBar;
ShowWindow( hwndStatus, bStatusBar ? SW_SHOW : SW_HIDE );
GetClientRect(hwndFrame, &rc);
SendMessage(hwndFrame, WM_SIZE, SIZENORMAL, MAKELONG(rc.right, rc.bottom));
if( pInfo = GETMDIWIN( hwndChild ) )
{
ENTER_PROTECTED_DATA( pInfo );
UpdateStatus(hwndChild);
LEAVE_PROTECTED_DATA( pInfo );
}
InvalidateRect(hwndFrame, NULL, TRUE);
CheckMenuItem(GetMenu(hWnd), IDM_STATUSBAR,
MF_BYCOMMAND | (bStatusBar ? MF_CHECKED : MF_UNCHECKED));
return 0;
}
/*
*
*/
LONG FrameCommandSaveSettings(HWND hWnd)
{
bSaveSettings = !bSaveSettings;
CheckMenuItem(GetMenu(hWnd), IDM_SAVESETTINGS,
MF_BYCOMMAND | (bSaveSettings ? MF_CHECKED : MF_UNCHECKED));
return 0;
}
/*
*
*/
LONG FrameCommandPermissions(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pInfo;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if( hwndChild )
{
pInfo = GETMDIWIN( hwndChild );
if( pInfo->WindowType != MDIWIN_SERVER )
{
ENTER_PROTECTED_DATA( pInfo );
ENTER_PROTECTED_HANDLE( pInfo );
ResetEvent( pInfo->RefreshSignal );
CallDiscretionaryAclEditor( hWnd, pInfo->pContext );
SetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_HANDLE( pInfo );
LEAVE_PROTECTED_DATA( pInfo );
}
}
return 0;
}
/*
*
*/
LONG FrameCommandAuditing(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pInfo;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if( hwndChild )
{
pInfo = GETMDIWIN( hwndChild );
if( pInfo->WindowType != MDIWIN_SERVER )
{
ENTER_PROTECTED_DATA( pInfo );
ENTER_PROTECTED_HANDLE( pInfo );
ResetEvent( pInfo->RefreshSignal );
CallSystemAclEditor( hWnd, pInfo->pContext );
SetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_HANDLE( pInfo );
LEAVE_PROTECTED_DATA( pInfo );
}
}
return 0;
}
/*
*
*/
LONG FrameCommandOwner(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pInfo;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if( hwndChild )
{
pInfo = GETMDIWIN( hwndChild );
if( pInfo->WindowType != MDIWIN_SERVER )
{
ENTER_PROTECTED_DATA( pInfo );
ENTER_PROTECTED_HANDLE( pInfo );
ResetEvent( pInfo->RefreshSignal );
CallTakeOwnershipDialog( hWnd, pInfo->pContext );
SetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_HANDLE( pInfo );
LEAVE_PROTECTED_DATA( pInfo );
}
}
return 0;
}
/*
*
*/
VOID FrameCommandRefresh(HWND hWnd)
{
HWND hwndChild;
PMDIWIN_INFO pMDIWinInfo;
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if( hwndChild )
{
pMDIWinInfo = GETMDIWIN( hwndChild );
Refresh( hwndChild, pMDIWinInfo, REPAINT_FORCE );
}
UNREFERENCED_PARAMETER( hWnd );
}
/*
*
*/
LONG FrameCommandClose(HWND hWnd)
{
HWND hwndChild;
DBG_UNREFERENCED_PARAMETER(hWnd);
hwndChild = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
if (SendMessage(hwndChild, WM_QUERYENDSESSION, 0, 0L))
SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM) hwndChild, 0L);
return 0;
}
LONG
FrameCommandReturn()
{
HWND hwndActive;
hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (hwndActive && IsIconic(hwndActive)) {
SendMessage(hwndActive, WM_SYSCOMMAND, SC_RESTORE, 0L);
} else {
PMDIWIN_INFO pInfo;
pInfo = GETMDIWIN(hwndActive);
if( !pInfo )
return 0;
//
// If there's nothing selected or we're in the middle
// of a drag operation, don't do anything:
//
if( ( pInfo->ObjSelected == NOSELECTION )
||( pInfo->DragPosition != NOSELECTION ) )
{
}
else {
//
// Do the same as double-click:
//
MDICommandObjListDblClk( hwndActive );
}
}
return 0;
}
/*
*
*/
LONG FrameCommandAbout(HWND hWnd)
{
TCHAR Title[RESOURCE_STRING_LENGTH];
SetCursor( hcursorWait );
LoadString( hInst, IDS_PRINTMANAGER, Title,
sizeof Title / sizeof *Title );
ShellAbout( hWnd, Title, NULL, hiconPrinter );
SetCursor( hcursorArrow );
return 0;
}
/*
*
*/
VOID FrameCommandDefaultPrinter(HWND hwnd, WORD Command)
{
switch (Command)
{
case CBN_SELCHANGE:
ToolbarCommandSelChange(FALSE);
break;
/* F1 will bring up help on the Default Printer list,
* if it has the focus:
*/
case CBN_SETFOCUS:
WinHelpMenuID = ID_HELP_DEFAULT_PRINTER;
break;
case CBN_KILLFOCUS:
WinHelpMenuID = 0;
break;
}
}
/* Handle notification codes from the toolbar.
* Set the status bar help in response to TBN_BEGIN/ENDDRAG.
*/
VOID FrameCommandToolbarNotify( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
MenuHelp( WM_COMMAND, wParam, lParam, GetMenu( hwnd ),
hInst, hwndStatus, pMenuHelpIDs );
WinHelpMenuID = (DWORD)LOWORD( wParam );
}
/* Cause tab to toggle between the default printer list and the active
* MDI window, so that the keyboard can be used to select default printer.
*/
VOID FrameCommandTab(HWND hwnd)
{
HWND hwndActiveMDI;
PMDIWIN_INFO pMDIWinInfo;
HWND hwndFocus;
hwndActiveMDI = (HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if( hwndActiveMDI )
{
pMDIWinInfo = GETMDIWIN( hwndActiveMDI );
hwndFocus = GetFocus( );
if( hwndFocus == pMDIWinInfo->hwndList )
SetFocus( hwndPrinterList );
else
SetFocus( pMDIWinInfo->hwndList );
}
}
/*
*
*/
LONG FrameCommandDefault(HWND hWnd, WPARAM wParam, LONG lParam)
{
HWND hwndChild;
hwndChild =(HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
if (!hwndChild)
return 0;
if (IsWindow(hwndChild))
SendMessage(hwndChild, WM_COMMAND, wParam, lParam);
// Pass unprocessed WM_COMMAND messages to DefFrameProc
return DefFrameProc(hWnd, hwndClient, WM_COMMAND, wParam, lParam);
}
/*
*
*/
VOID FrameSysColorChange( )
{
DWORD OldSysColorHighlight;
DWORD OldSysColorHighlightText;
DWORD OldSysColorWindow;
DWORD OldSysColorBtnFace;
DWORD OldSysColorBtnText;
DWORD OldSysColorBtnHighlight;
DWORD OldSysColorBtnShadow;
OldSysColorHighlight = SysColorHighlight;
OldSysColorHighlightText = SysColorHighlightText;
OldSysColorWindow = SysColorWindow;
OldSysColorBtnFace = SysColorBtnFace;
OldSysColorBtnText = SysColorBtnText;
OldSysColorBtnHighlight = SysColorBtnHighlight;
OldSysColorBtnShadow = SysColorBtnShadow;
GetSystemColors( );
/* If the higlight or window colour has changed,
* we must fix up the bitmaps again.
* The easiest way to do this is by deleting the old stuff
* and reload the bitmaps from resources:
*/
if( ( OldSysColorHighlight != SysColorHighlight )
||( OldSysColorWindow != SysColorWindow ) )
{
SelectObject( hdcMem, hbmDefault );
DeleteObject( hbmBitmaps );
DeleteDC( hdcMem );
LoadBitmaps( );
}
}
/* RepaintWindow
*
* Callback function passed to EnumChildWindows by FrameWinIniChange.
* It is called on each MDI window in the event that international
* time formats might have changed.
* Enumeration continues while this function returns TRUE.
*
* Parameters:
*
* hwnd - The child window's handle
*
* lparam - Application-defined value (unused)
*
*
* Return:
*
* The return code from InvalidateRect
*
*/
BOOL CALLBACK RepaintWindow( HWND hwnd, LPARAM lparam )
{
UNREFERENCED_PARAMETER( lparam );
/* Repaint only windows with ID == ID_OBJLIST,
* i.e. the document lists in printer windows
* and printer lists in server windows:
*/
if( GetWindowLong( hwnd, GWL_ID ) == ID_OBJLIST )
return InvalidateRect( hwnd, NULL, TRUE );
else
return TRUE;
}
/* FrameWinIniChange
*
* Called in response to WM_WININICHANGE.
* If the section that has been changed is "intl", or if we don't know
* because NULL was passed (frowned upon but permitted),
* cause the child windows to be repainted so that any time values
* will be repainted.
* E.g., if the user has sensibly changed the time format from 12-hour
* to 24-hour, we want to repaint any times.
*
* Parameters:
*
* hwnd - The frame window handle
*
* pSection - A pointer to string specifying the section in the INI
* file that has changed. If this is NULL, play it safe,
* and assume that something might have changed.
*
*/
VOID FrameWinIniChange( HWND hwnd, LPTSTR pSection )
{
TCHAR Buffer[MAX_PATH];
PTCHAR pPrinterName;
INT iNewDefaultPrinter;
if( ( pSection == NULL )
||( _tcsicmp( pSection, szInternational ) == 0 ) )
{
InitializeInternationalTimeConstants( );
EnumChildWindows( hwnd, (WNDENUMPROC)RepaintWindow, (LPARAM)0 );
}
/* If an application has changed the windows.device section in
* WIN.INI, update the default printer:
*/
if( ( pSection == NULL )
||( _tcsicmp( pSection, TEXT("device") ) == 0 ) )
{
if( GetProfileString( szWindows, szDevice, TEXT(""), Buffer, sizeof Buffer ) )
{
pPrinterName = _tcstok( Buffer, TEXT(",") );
if( pPrinterName )
{
iNewDefaultPrinter = SendMessage( hwndPrinterList,
CB_FINDSTRINGEXACT,
(WPARAM)-1,
(LPARAM)pPrinterName );
if( iNewDefaultPrinter != CB_ERR )
{
if( SendMessage( hwndPrinterList,
CB_SETCURSEL,
(WPARAM)iNewDefaultPrinter,
0 ) == CB_ERR )
{
DBGMSG( DBG_WARNING, ( "Failed to set new default printer\n" ) );
}
}
else
{
DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with an unknown Windows Device\n" ) );
}
}
else
{
DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with a NULL Windows Device\n" ) );
}
}
else
{
DBGMSG( DBG_WARNING, ( "GetProfileString failed: Error %d\n", GetLastError( ) ) );
}
}
}
/* We get here when the thread monitoring the local server detects that
* a printer has been added. This may be because we've just added one,
* however it might also be because someone added one remotely.
* If we added it, we should have set the global PrinterAdded = TRUE.
* Otherwise we enumerate the printers and figure out which was new,
* then create an iconised window for the new printer.
*/
VOID
FramePrinterAdded(
HWND hwnd,
DWORD dwType)
{
PPRINTER_INFO_4 pPrinters = NULL;
DWORD cbPrinters = 0;
DWORD cPrinters;
LPTSTR pServerName = NULL;
LPTSTR pPrinterName = NULL;
DWORD i;
PQUEUE pQueue;
if( PrinterAdded )
{
/* We're expecting this, so forget it:
*/
PrinterAdded = FALSE;
return;
}
DBGMSG( DBG_TRACE, ( "A printer was added\n" ) );
if( ENUM_PRINTERS( dwType ?
PRINTER_ENUM_LOCAL :
PRINTER_ENUM_CONNECTIONS,
pServerName,
4,
pPrinters,
cbPrinters,
&cbPrinters,
&cPrinters ) )
{
for( i = 0; i < cPrinters; i++ )
{
if( !FindPrinterWindow( pPrinters[i].pPrinterName ) )
{
DBGMSG( DBG_TRACE, ( "Creating new printer: %s\n",
pPrinters[i].pPrinterName ) );
if( pQueue = AllocQueue( pPrinters[i].pPrinterName ) )
{
pQueue->Error = OpenThreadObject(pQueue->pPrinterName,
&pQueue->hPrinter,
&pQueue->AccessGranted,
MDIWIN_PRINTER);
if( !pQueue->Error )
{
DWORD Flags = CREATE_PRINTER_ICONIC;
HWND hwnd;
if( pPrinters[i].Attributes & PRINTER_ATTRIBUTE_SHARED )
Flags |= CREATE_PRINTER_SHARED;
hwnd = CreateQueueWindow( hwnd, pQueue,
PRINTER_STATUS_LOADING,
dwType ?
MDIWIN_LOCALPRINTER :
MDIWIN_NETWORKPRINTER,
Flags );
BringWindowToTop( hwnd );
FlashWindow( hwnd, FALSE );
}
else
{
FreeQueue( pQueue );
}
}
}
}
FreeSplMem( pPrinters );
}
else
{
DBGMSG( DBG_WARNING, ( "EnumPrinters failed: Error %d\n", GetLastError( ) ) );
}
}
/* FrameRegNotifyChangeKeyValue
*
* This routine will be called via a message posted from the main
* message dispatch loop when a change is made to the device key
* of the windows section in the registry WIN.INI mapping.
* This may be because an application has changed the default printer.
* We check whether this is the case by querying that value, parsing
* out the comma following the printer name in the entry, and ensuring
* that this is the current default printer.
* Hoping for a WM_WININICHANGE is not very reliable, since some apps
* (e.g. Lotus Improv) don't appear to broadcast it when they change
* WIN.INI.
*
* Parameters:
*
* hwnd - The frame window handle
*
* hWindowsKey - An open key to the registry WIN.INI mapping
*
*
* Note there is some redundancy here, since this will also be called
* if the user selects the default printer from Print Manager.
* This could be avoided by our setting a flag when we have caused
* the default printer to change.
*
*
* AndrewBe, 15 June 1993
*
*/
VOID FrameRegNotifyChangeKeyValue( HWND hwnd, HKEY hWindowsKey )
{
DWORD Status;
TCHAR Buffer[MAX_PATH];
PTCHAR pPrinterName;
INT iNewDefaultPrinter;
DWORD BufferSize;
BufferSize = sizeof Buffer*sizeof(TCHAR);
if( ( Status = RegQueryValueEx( hWindowsKey,
szDevice,
REG_OPTION_RESERVED,
NULL,
(LPBYTE)Buffer,
&BufferSize ) ) == NO_ERROR)
{
/* Hack out the comma from the buffer,
* which strtok helpfully does for us:
*/
pPrinterName = _tcstok( Buffer, TEXT(",") );
if( pPrinterName )
{
iNewDefaultPrinter = SendMessage( hwndPrinterList,
CB_FINDSTRING,
(WPARAM)-1,
(LPARAM)pPrinterName );
if( iNewDefaultPrinter != CB_ERR )
{
if( SendMessage( hwndPrinterList,
CB_SETCURSEL,
(WPARAM)iNewDefaultPrinter,
0 ) == CB_ERR )
{
DBGMSG( DBG_WARNING, ( "Failed to set new default printer\n" ) );
}
}
else
{
DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with an unknown Windows Device\n" ) );
}
}
else
{
DBGMSG( DBG_WARNING, ( "An application updated WIN.INI with a NULL Windows Device\n" ) );
}
}
else
{
DBGMSG( DBG_WARNING, ( "RegQueryValuEx failed: Error %d\n", Status ) );
}
}
/*
* END OF ROUTINES CALLED BY FrameWndProc
*/
//////////////////////////////////////////////////////////////////////
//
// UpdateStatus
//
// Load the status buffers with the appropriate stuff and invalidates
// the status area causing it to repaint.
//
// Updates the three global status strings for the currently active
// child window.
//
// strStatusName
// strStatusStatus
// strStatusWaiting
//
//////////////////////////////////////////////////////////////////////
VOID UpdateStatus( HWND hWnd )
{
PMDIWIN_INFO pMDIWinInfo;
PVOID pContext;
LPPRINTER_INFO_2 pPrinter;
LPJOB_INFO_2 pJobSelected;
DWORD JobSelected;
TCHAR szTemp[128];
LPTSTR pServerName = NULL; /* Non-null for server windows */
DWORD Error;
if (!bStatusBar)
return;
/* If hWnd is NULL, clear the status bar,
* otherwise get the active MDI window:
*/
if( !hWnd || !(hWnd = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L)))
{
*strStatusName = NULLC;
*strStatusStatus = NULLC;
*strStatusWaiting = NULLC;
}
else
{
if( !( pMDIWinInfo = GETMDIWIN( hWnd ) ) ) {
return;
}
ENTER_PROTECTED_DATA(pMDIWinInfo);
pContext = pMDIWinInfo->pContext;
if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
{
pPrinter = ( (PQUEUE)pContext )->pPrinter;
pJobSelected = ( (PQUEUE)pContext )->pSelJob;
JobSelected = pMDIWinInfo->ObjSelected;
Error = ( (PQUEUE)pContext )->Error;
}
else
{
pPrinter = ( (PSERVER_CONTEXT)pContext )->pSelPrinter;
pJobSelected = NULL;
JobSelected = NOSELECTION;
Error = ( (PSERVER_CONTEXT)pContext )->Error;
}
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
{
pServerName = ( (PSERVER_CONTEXT)pContext )->pServerName;
/* No job info for Server Viewer - should we show something?
*/
if( IsIconic( hWnd ) )
_tcscpy( strStatusName, pServerName );
else
{
if( pPrinter && pPrinter->pPrinterName )
_tcscpy( strStatusName, pPrinter->pPrinterName );
else
_tcscpy( strStatusName, pServerName );
}
}
else if( pPrinter )
{
if( JobSelected != NOSELECTION )
{
if( pJobSelected->pDocument && *pJobSelected->pDocument )
_tcscpy (strStatusName, pJobSelected->pDocument);
else
_tcscpy (strStatusName, strUntitled);
}
else if( ( (PQUEUE)pContext )->pPrinterName )
_tcscpy( strStatusName, ( (PQUEUE)pContext )->pPrinterName );
else
*strStatusName = NULLC;
}
else if( ( (PQUEUE)pContext )->pPrinterName )
_tcscpy( strStatusName, ( (PQUEUE)pContext )->pPrinterName );
else
*strStatusName = NULLC;
if( pServerName && IsIconic( hWnd ) )
{
*strStatusWaiting = NULLC;
*strStatusStatus = NULLC;
}
else if( pPrinter )
{
if( ( pPrinter->cJobs == 0 ) || ( JobSelected == NOSELECTION ) )
{
GetPrinterStatusString( pPrinter->Status, strStatusStatus );
LoadString (hInst, IDS_DOCUMENTSQUEUED_D, szTemp,
sizeof(szTemp) / sizeof(*szTemp));
wsprintf (strStatusWaiting, szTemp, pPrinter->cJobs);
}
else
{
if( ( pJobSelected->pStatus ) && ( *pJobSelected->pStatus ) )
_tcsncpy (strStatusStatus, pJobSelected->pStatus,
sizeof(strStatusStatus)/sizeof(TCHAR)-1);
else
GetJobStatusString( pJobSelected->Status, strStatusStatus );
LoadString (hInst, IDS_PAGESCOMPLETED_D, szTemp,
sizeof(szTemp) / sizeof(*szTemp));
wsprintf (strStatusWaiting, szTemp, pJobSelected->TotalPages );
}
}
else
{
if (Error == ERROR_ACCESS_DENIED) {
GetPrinterStatusString( PRINTER_STATUS_ACCESS_DENIED, strStatusStatus );
} else {
GetPrinterStatusString( PRINTER_STATUS_UNKNOWN, strStatusStatus );
}
*strStatusWaiting = NULLC;
}
LEAVE_PROTECTED_DATA(pMDIWinInfo);
}
// force the status area to update
SendMessage( hwndStatus, SB_SETTEXT, ISF_NAME, (LPARAM)strStatusName );
SendMessage( hwndStatus, SB_SETTEXT, ISF_STATUS, (LPARAM)strStatusStatus );
SendMessage( hwndStatus, SB_SETTEXT, ISF_WAITING, (LPARAM)strStatusWaiting );
}
BOOL
InitApplication(
HANDLE hInstance,
LPHANDLE lphAccel
)
{
WNDCLASS wc;
HCURSOR hcurArrow;
hInst = hInstance;
hcurArrow = LoadCursor(NULL, IDC_ARROW);
GetSystemColors( );
if (!LoadBitmaps())
return FALSE;
hiconPrinter = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_PRINTMAN ) );
hiconServer = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_SERVER ) );
hiconConnect = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_CONNECT ) );
hiconShared = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_SHARED ) );
// Register the main Print Manager frame window class
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = FrameWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = hiconPrinter;
wc.hCursor = hcurArrow;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = szMenuClass;
wc.lpszClassName = szPrintManagerClass;
if (!RegisterClass(&wc))
return FALSE;
// Register the Print Queue child window class
// You can't close a window of this class
// except if the corresponding printer is deleted.
// -------------------------------------------------------------------
// There is no icon defined for this class, since we want to change it
// based on whether the printer is shared or not.
// There is a user feature (for Win31 compatibility, apparently)
// which means that we can't do this by specifying an icon here
// then responding to the WM_PAINTICON message by calling DrawIcon,
// since somewhere in the guts of user it gets a zero-sized update
// region. So instead we don't define a default class icon,
// but put an icon handle in the MDI window's instance data,
// which we then use when we get a WM_PAINT message.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MDIWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LONG); // GWL_PMDIWIN
wc.hInstance = hInst;
wc.hIcon = NULL; // No icon -- put handle in MDIWinInfo
wc.hCursor = hcurArrow;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szChildClass;
if (!RegisterClass(&wc))
return FALSE;
*lphAccel = LoadAccelerators(hInst, TEXT("PrintManAccel"));
// Register window class for custom spinner dialog box control
if (!RegisterArrowClass (hInstance))
return FALSE;
return TRUE;
}
BOOL
InitQueueChildWindows(
HWND hWnd)
{
PQUEUE pQueue;
LPPRINTER_INFO_4 pPrinters = NULL;
DWORD cbPrinters;
DWORD cReturned = 0;
DWORD i;
TCHAR GettingPrinterInfo[80];
BOOL OK;
DWORD Flags;
DWORD WindowType;
DBGMSG( DBG_TRACE, ( "InitQueueChildWindows\n" ) )
cbPrinters = 0x1000;
if( !( pPrinters = AllocSplMem( cbPrinters ) ) )
cbPrinters = 0;
LoadString( hInst, IDS_GETTING_PRINTER_INFO, GettingPrinterInfo,
sizeof GettingPrinterInfo / sizeof *GettingPrinterInfo );
SendMessage( hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)GettingPrinterInfo );
SendMessage( hwndStatus, SB_SIMPLE, 1, 0L );
UpdateWindow( hwndStatus );
OK = ENUM_PRINTERS( PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL,
NULL,
4,
pPrinters,
cbPrinters,
&cbPrinters,
&cReturned );
DBGMSG( DBG_TRACE, ( "EnumPrinters returned %d printers\n", cReturned ) );
SetStatusMode( STATUS_MODE_NORMAL, FALSE );
if( !pPrinters && !OK )
{
Message( hWnd, MSG_ERROR, IDS_PRINTMANAGER, IDS_COULDNOTENUMERATEPRINTERS );
SendMessage( hWnd, WM_CLOSE, 0, 0 );
return FALSE;
}
// Process the list of printers returned by creating and initializing
// local data structures for these
for (i=0; i<cReturned; i++)
{
Flags = 0;
//
// We don't know if this printer is pending deletion,
// enumerate all of them.
//
DBGMSG( DBG_TRACE, ( "Initializing queue for %s\n",
pPrinters[i].pPrinterName ) );
if( pQueue = AllocQueue(pPrinters[i].pPrinterName))
{
if ( pPrinters[i].pServerName )
{
pQueue->pServerName = AllocSplStr( pPrinters[i].pServerName );
if ( !pQueue->pServerName )
{
//
// Fail... !! LATER !!
//
}
}
else
{
//
// Null implies a local printer
//
pQueue->pServerName = NULL;
}
if( ALL_FLAGS_ARE_SET( pPrinters[i].Attributes,
PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL ) )
WindowType = MDIWIN_LOCALNETWORKPRINTER;
else if( pPrinters[i].Attributes & PRINTER_ATTRIBUTE_NETWORK )
WindowType = MDIWIN_NETWORKPRINTER;
else
WindowType = MDIWIN_LOCALPRINTER;
if( pPrinters[i].Attributes & PRINTER_ATTRIBUTE_SHARED )
Flags = CREATE_PRINTER_SHARED;
CreateQueueWindow( hWnd, pQueue, PRINTER_STATUS_LOADING,
WindowType,
Flags );
}
}
if(cReturned == 0)
EnableCheckTBButtons(NULL);
else
EnableCheckTBButtons((HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L));
if( pPrinters )
FreeSplMem(pPrinters);
UpdateDefaultList();
return TRUE;
}
BOOL
InitServerChildWindows(
HWND hwnd
)
{
EnumRegistryValues( szRegServers,
(ENUMREGPROC)CreateServerWindow,
(PVOID)hwnd );
UpdateDefaultList();
return TRUE;
}
long
APIENTRY
MDIWndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LONG lParam
)
{
static POINT CursorPos;
if( message == WM_DragList )
{
return MDIDragList( hWnd, (LPDRAGLISTINFO)lParam );
}
switch (message) {
case WM_CREATE:
MDICreate( hWnd, lParam );
break;
case WM_PAINT:
return MDIPaint(hWnd, wParam, lParam);
case WM_ERASEBKGND:
if( MDIEraseBkgnd(hWnd, (HDC)wParam) )
return 1;
break;
case WM_QUERYDRAGICON:
return (long)MDIQueryDragIcon(hWnd);
case WM_MENUSELECT:
return MDIMenuSelect( hWnd, wParam, lParam );
case WM_COMMAND:
switch (WPARAM_ID(wParam))
{
case ID_OBJLIST:
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
MDICommandObjListSelChange(hWnd);
break;
case LBN_DBLCLK:
MDICommandObjListDblClk(hWnd);
break;
}
break;
}
return 0;
case WM_NOTIFY:
{
HD_NOTIFY * lpNot;
lpNot = (HD_NOTIFY *) lParam;
switch (wParam)
{
case ID_HEADER:
switch (lpNot->hdr.code)
{
case HDN_BEGINTRACK:
MDICommandHeaderBeginDrag(hWnd, &CursorPos);
break;
case HDN_TRACK:
MDICommandHeaderDragging(hWnd, &CursorPos, lpNot);
break;
case HDN_ENDTRACK:
MDICommandHeaderEndDrag(hWnd, &CursorPos, lpNot);
break;
}
break;
}
}
return 0;
case WM_SYSCOMMAND:
switch( wParam )
{
case SC_CLOSE:
if( !MDIClose(hWnd) )
{
SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, lParam);
return 0;
}
break;
}
break;
case WM_VKEYTOITEM:
switch( LOWORD( wParam ) )
{
case VK_SPACE:
MDIVKeyToItemSpace(hWnd);
return -2; // Means we handled everything
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
if( MDIVKeyToItemUpDown(hWnd, LOWORD( wParam) ) == -2 )
return -2;
break;
default:
MDIVKeyToItemDefault(hWnd);
break;
}
break;
case WM_PARENTNOTIFY:
switch( wParam )
{
case WM_RBUTTONDOWN:
MDIParentNotifyRButtonDown( hWnd, lParam );
return 0;
}
break;
case WM_SIZE:
MDISize( hWnd, (DWORD)lParam );
break; // WM_SIZE MUST also be processed by DefMDIChildProc
case WM_MDIACTIVATE:
if (wParam)
MDIMDIActivate( hWnd, (HWND)wParam, (HWND)lParam );
break;
case WM_NCACTIVATE:
if( !wParam )
MDINCActivate( hWnd );
break;
case WM_WINDOWPOSCHANGED:
return MDIWindowPosChanged( hWnd, wParam, lParam );
case WM_SETFOCUS:
MDISetFocus( hWnd );
return 0;
case WM_MEASUREITEM:
MDIMeasureItem( hWnd, (LPMEASUREITEMSTRUCT)lParam );
return 0;
case WM_DRAWITEM:
MDIDrawItem( hWnd, (LPDRAWITEMSTRUCT)lParam );
return TRUE;
case WM_TIMER: // Update Print Jobs for this queue.
MDITimer( hWnd );
return 0;
case WM_STATUS_CHANGED:
// MDIStatusChanged( hWnd );
return 0;
case WM_UPDATE_LIST:
MDIUpdateList( hWnd );
return 0;
case SB_SETPARTS:
MDISetParts( hWnd, wParam, lParam );
return 0;
#ifdef ALLOW_DROPS_ON_ALL_PRINTERS
case WM_DROPOBJECT:
MDIDropObject( hWnd );
return 0x544E5250L; // 'PRNT' tells fm to print
#endif /* ALLOW_DROPS_ON_ALL_PRINTERS */
case WM_CLOSE:
if( !MDIClose(hWnd) )
{
SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, lParam);
return 0;
}
break;
case WM_DESTROY:
MDIDestroy( hWnd );
return 0;
}
return DefMDIChildProc(hWnd, message, wParam, lParam);
}
/*
*
*/
VOID MDICreate( HWND hWnd, LONG lParam )
{
RECT rect;
DWORD xList;
DWORD yList;
DWORD cxList;
DWORD cyList;
PMDIWIN_INFO pMDIWinInfo;
RECT rectHeader;
INT i, ColumnWidths[MAX_HEADERS];
HD_ITEM hdi;
RECT rcParent;
HD_LAYOUT hdl;
WINDOWPOS wp;
DBGMSG( DBG_TRACE, ( "Enter MDICreate %08x\n", hWnd ) );
// The first time thru we have to pickup the pQueue value from
// the extra Params field of the CREATESTRUCT
pMDIWinInfo = (PMDIWIN_INFO)(((LPMDICREATESTRUCT)
(((LPCREATESTRUCT)lParam)->lpCreateParams))->lParam);
/* Store the MDIWIN_INFO struct pointer in the window struct for
* future use during other message processing by the WinProc.
*/
SetWindowLong(hWnd, GWL_PMDIWIN, (unsigned)pMDIWinInfo);
pMDIWinInfo->hwnd = hWnd;
pMDIWinInfo->Alive = TRUE;
CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)RefreshThread,
pMDIWinInfo, 0, &pMDIWinInfo->ThreadId );
pMDIWinInfo->hwndHeader = CreateWindow (WC_HEADER, TEXT(""),
WS_CHILD | WS_BORDER | CCS_TOP,
0,0,0,0, hWnd, (HMENU) ID_HEADER,
hInst, NULL);
GetClientRect(hWnd, &rcParent);
hdl.prc = &rcParent;
hdl.pwpos = &wp;
SendMessage(pMDIWinInfo->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hdl);
if (!bJapan) {
SendMessage( pMDIWinInfo->hwndHeader, WM_SETFONT, (WPARAM)hfontHelvBold, 1L );
}
for( i = 0; i < pMDIWinInfo->cColumns; i++ )
{
ColumnWidths[i] = pMDIWinInfo->pColumns[i].Width;
}
if( ColumnWidths[0] == CW_USEDEFAULT )
SetDefaultColumnWidths( hWnd, pMDIWinInfo, ColumnWidths );
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
hdi.fmt = HDF_LEFT | HDF_STRING;
for( i = 0; i < pMDIWinInfo->cColumns; i++ ) {
hdi.pszText = pMDIWinInfo->pColumns[i].Text;
hdi.cxy = ColumnWidths[i];
hdi.cchTextMax = lstrlen(hdi.pszText);
SendMessage(pMDIWinInfo->hwndHeader, HDM_INSERTITEM,
(WPARAM) pMDIWinInfo->cColumns+ 1, (LPARAM)&hdi);
}
SetWindowPos(pMDIWinInfo->hwndHeader, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy,
wp.flags | SWP_SHOWWINDOW);
/* Calculate width and height of the list box:
*/
GetWindowRect( pMDIWinInfo->hwndHeader, &rectHeader );
HeaderHeight = (rectHeader.bottom - rectHeader.top);
GetWindowRect(hWnd, &rect);
xList = 0;
yList = HeaderHeight;
cxList = rect.right;
cyList = rect.bottom - HeaderHeight;
yList = rectHeader.bottom;
cyList = rect.bottom - rectHeader.bottom;
/* Create Queue and Job Status list box control in client window
*/
pMDIWinInfo->hwndList = CreateWindow( TEXT("LISTBOX"), NULL,
WS_CHILD | WS_VISIBLE | WS_VSCROLL
| WS_CLIPSIBLINGS
| LBS_NOTIFY | LBS_OWNERDRAWFIXED
| LBS_NODATA | LBS_NOINTEGRALHEIGHT
| LBS_WANTKEYBOARDINPUT,
xList, yList, cxList, cyList,
hWnd,
(HMENU)ID_OBJLIST,
hInst,
NULL);
// CountryCode - krishnag
// #ifndef JAPAN
if (!bJapan) {
SendMessage( pMDIWinInfo->hwndList, WM_SETFONT, (WPARAM)hfontHelv, 1L );
}
// #endif
// SendMessage( pMDIWinInfo->hwndList, LB_SETCOUNT, *pMDIWinInfo->pcObjects, 0L );
if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
{
MakeDragList( pMDIWinInfo->hwndList );
if( !WM_DragList )
WM_DragList = RegisterWindowMessage( DRAGLISTMSGSTRING );
DefListboxWndProc = (WNDPROC)SetWindowLong( pMDIWinInfo->hwndList,
GWL_WNDPROC,
(LONG)SubclassListboxWndProc );
pMDIWinInfo->ObjSelected = NOSELECTION;
pMDIWinInfo->DragPosition = NOSELECTION;
}
else
{
SendMessage( pMDIWinInfo->hwndList, LB_SETCURSEL, 0, 0L );
pMDIWinInfo->ObjSelected = 0;
pMDIWinInfo->DragPosition = NOSELECTION;
*pMDIWinInfo->ppSelData = *pMDIWinInfo->ppData;
}
DBGMSG( DBG_TRACE, ( "Exit MDICreate %08x\n", hWnd ) );
}
/*
*
*/
VOID SetDefaultColumnWidths( HWND hwnd, PMDIWIN_INFO pMDIWinInfo,
PINT pColumnWidths )
{
RECT rect;
PCOLUMN pDefaultColumn;
INT i;
INT TotalWidth;
INT AvailableWidth;
GetWindowRect( hwnd, &rect );
AvailableWidth = ( rect.right - rect.left );
if( pMDIWinInfo->WindowType == MDIWIN_SERVER )
pDefaultColumn = MDIServerDefaultColumn;
else
pDefaultColumn = MDIPrinterDefaultColumn;
for( i = 0, TotalWidth = 0; i < pMDIWinInfo->cColumns; i++ )
TotalWidth += pDefaultColumn[i].Width;
/* Size the headers so that they use up the space available.
*/
for( i = 0; i < pMDIWinInfo->cColumns; i++ )
pColumnWidths[i] = pMDIWinInfo->pColumns[i].Width =
( pDefaultColumn[i].Width * AvailableWidth / TotalWidth );
}
/* MDIPaint
*
* Called in response to the WM_PAINT message.
*
* If the window is iconic, and we're going to draw our own icon, do it.
*
* If it isn't iconic, draw the status bar.
*/
LONG MDIPaint(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
PMDIWIN_INFO pMDIWinInfo;
HDC hdc;
PAINTSTRUCT ps;
LONG rc;
pMDIWinInfo = GETMDIWIN( hwnd );
hdc = BeginPaint(hwnd, &ps);
if (IsIconic(hwnd))
{
if( pMDIWinInfo->hicon )
DrawIcon( hdc, 0, 0, pMDIWinInfo->hicon );
EndPaint(hwnd, &ps);
}
else
{
EndPaint(hwnd, &ps);
rc = DefMDIChildProc(hwnd, WM_PAINT, wParam, lParam);
/* Do the default stuff, which should cause an initial paint,
* then fake a timer message to ensure the window is up to date.
* This may result in the window being painted twice, but at least
* there won't be an obvious delay while the job info gets refreshed.
*/
}
return rc;
}
/* MDIEraseBkgnd
*
* We're interested in the WM_ERASEBKGND message if we're drawing our own icon.
*
* Return:
*
* TRUE if the background was successfully painted.
* Otherwise, the message should be passed to the default procedure.
*
*/
BOOL MDIEraseBkgnd(HWND hwnd, HDC hdc)
{
PMDIWIN_INFO pMDIWinInfo;
HBRUSH hbrush;
RECT rect;
BOOL Painted = FALSE;
pMDIWinInfo = GETMDIWIN( hwnd );
if( IsIconic( hwnd ) && pMDIWinInfo->hicon )
{
hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ) );
GetWindowRect( hwnd, &rect );
/* rect is in screen coordinates.
* We must convert to client coordinates:
*/
ScreenToClient( hwnd, &((LPPOINT)&rect)[0] );
ScreenToClient( hwnd, &((LPPOINT)&rect)[1] );
Painted = FillRect( hdc, &rect, hbrush );
DeleteObject( hbrush );
}
return Painted;
}
/* MDIQueryDragIcon
*
* Called if the user is dragging an icon around.
* Just returns the icon handle for the window, which is non-null for
* icons that we draw ourselves.
*/
HICON MDIQueryDragIcon(HWND hwnd)
{
PMDIWIN_INFO pMDIWinInfo;
pMDIWinInfo = GETMDIWIN( hwnd );
return pMDIWinInfo->hicon;
}
/* Respond to system menu selections in MDI windows.
* Update the status bar correspondingly.
*/
LONG MDIMenuSelect( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
UINT ItemID;
UINT Flags;
ItemID = (UINT)LOWORD( wParam );
Flags = (UINT)HIWORD( wParam );
MenuHelp( WM_MENUSELECT, wParam, lParam, GetMenu( hwnd ),
hInst, hwndStatus, pMenuHelpIDs);
if( ItemID && ( Flags & MF_SYSMENU ) )
WinHelpMenuID = ID_HELP_MDI_SYSMENU;
else
WinHelpMenuID = ItemID;
return 0;
}
/* MDICommandObjListSelChange
*
* This routine will be called when a new selection is made in the list.
* It will also be called if the user just clicks on an already selected
* list item.
*
* If the user is clicking, we want to toggle selection of this item,
* otherwise reflect the change of selection in our instance data.
*
* If the user's been dragging a job in a printer window, and has now
* released the mouse back where it started, don't toggle.
*
*
*/
VOID MDICommandObjListSelChange( HWND hwnd )
{
PMDIWIN_INFO pInfo;
DWORD Selection;
if( !(pInfo = GETMDIWIN(hwnd) ) )
return;
Selection = (DWORD)GETLISTSELECT( hwnd, ID_OBJLIST );
ENTER_PROTECTED_DATA( pInfo );
if( ( Selection == pInfo->ObjSelected )
&&( pInfo->WindowType != MDIWIN_SERVER )
&&( pInfo->DragPosition == NOSELECTION ) )
{
Selection = NOSELECTION;
SETLISTSELECT( hwnd, ID_OBJLIST, Selection );
}
/* Beware, jobs may have gone away since USER sent us the message;
* ensure that the data is still valid:
*/
else if( !*pInfo->ppData )
{
Selection = NOSELECTION;
SETLISTSELECT( hwnd, ID_OBJLIST, Selection );
}
SetObjectSelection( pInfo, Selection );
EnableCheckTBButtons(hwnd);
UpdateStatus(hwnd);
LEAVE_PROTECTED_DATA( pInfo );
}
/* Set Print Manager's internal data structures to correspond to the selection:
*
*/
VOID SetObjectSelection( PMDIWIN_INFO pInfo, DWORD Selection )
{
DBG_IN_PROTECTED_DATA( pInfo );
if( Selection == NOSELECTION )
{
*pInfo->ppSelData = NULL;
*pInfo->pSelObjId = 0;
}
else
{
*pInfo->ppSelData = (PBYTE)( *pInfo->ppData
+ ( ( Selection - *pInfo->pFirstEnumObj )
* pInfo->DataSize ) );
*pInfo->pSelObjId = *(DWORD *)( *pInfo->ppSelData + pInfo->IdOffset );
}
pInfo->ObjSelected = Selection;
}
/*
*
*/
VOID MDICommandObjListDblClk( HWND hwnd )
{
PMDIWIN_INFO pMDIWinInfo;
PSERVER_CONTEXT pServerContext;
PQUEUE pQueue;
PPRINTER_INFO_2 pPrinterSelected;
HWND hwndPrinter;
pMDIWinInfo = (PMDIWIN_INFO)GetWindowLong(hwnd, GWL_PMDIWIN);
if( pMDIWinInfo->WindowType != MDIWIN_SERVER )
{
ENTER_PROTECTED_DATA( pMDIWinInfo );
pQueue = (PQUEUE)pMDIWinInfo->pContext;
if (pQueue->pSelJob)
DialogBoxParam (hInst, MAKEINTRESOURCE(DLG_DOCTAILS), hwnd,
(DLGPROC)DocDetailsDlg, (DWORD)pQueue);
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
else
{
WCHAR szPrinterName[MAX_PATH];
DWORD dwStatus;
/* This is a Server Viewer:
*/
pServerContext = pMDIWinInfo->pContext;
ENTER_PROTECTED_DATA( pMDIWinInfo );
/* See if there's already an MDI window for the printer name
* we just clicked on:
*
* !!! Actually we will probably have to combine it with the
* !!! server name.
*/
pPrinterSelected = pServerContext->pSelPrinter;
if (pPrinterSelected && pPrinterSelected->pPrinterName) {
wcscpy(szPrinterName, pPrinterSelected->pPrinterName);
dwStatus = pPrinterSelected->Status;
} else {
LEAVE_PROTECTED_DATA( pMDIWinInfo );
return;
}
LEAVE_PROTECTED_DATA( pMDIWinInfo );
hwndPrinter = FindPrinterWindow( szPrinterName );
/* If so, just bring it into focus:
*/
if( hwndPrinter )
{
SendMessage( hwndClient, WM_MDIACTIVATE, (WPARAM)hwndPrinter, 0L );
if( IsIconic( hwndPrinter ) )
ShowWindow( hwndPrinter, SW_RESTORE );
}
/* Otherwise create a new MDI window for this printer:
*/
else
{
SetCursor( hcursorWait );
if( AddPrinterConnection( szPrinterName ) )
{
if( pQueue = AllocQueue( szPrinterName ) )
{
pQueue->Error = OpenThreadObject(pQueue->pPrinterName,
&pQueue->hPrinter,
&pQueue->AccessGranted,
MDIWIN_PRINTER);
if( !pQueue->Error )
{
pQueue->pServerName = AllocSplStr( pServerContext->pServerName );
CreateQueueWindow( hwnd, pQueue, dwStatus,
MDIWIN_NETWORKPRINTER, FALSE );
UpdateDefaultList();
}
else
{
FreeQueue( pQueue );
ReportFailure( hwnd, 0, IDS_COULDNOTOPENPRINTER );
}
}
}
else
{
if( GetLastError( ) == ERROR_UNKNOWN_PRINTER_DRIVER )
Message( hwnd, MSG_ERROR, IDS_PRINTMANAGER, IDS_NO_DRIVER_ON_SERVER );
else
ReportFailure( hwnd, 0, IDS_COULDNOTCONNECTTOPRINTER );
}
SetCursor( hcursorArrow );
}
}
}
/* MDICommandHeaderBeginDrag
*
* Called when the user begins to drag a movable column in an MDI list.
* Queries the current position and marks the appropriate rectangle.
*
* Parameters:
*
* hwnd - The handle of the MDI window.
*
* pCursorPos - A pointer to the coordinates of the cursor.
* Initially undefined, it will be updated with the new coordinates.
*
*/
VOID MDICommandHeaderBeginDrag( HWND hwnd, PPOINT pCursorPos )
{
PMDIWIN_INFO pMDIWinInfo;
pMDIWinInfo = (PMDIWIN_INFO)GetWindowLong(hwnd, GWL_PMDIWIN);
/* Don't permit the window to be refreshed while we're dragging:
*/
ENTER_PROTECTED_DATA( pMDIWinInfo );
ResetEvent( pMDIWinInfo->RefreshSignal );
LEAVE_PROTECTED_DATA( pMDIWinInfo );
if( GetCursorPos( pCursorPos ) )
{
ScreenToClient( hwnd, pCursorPos );
InvertDragMark( hwnd, pCursorPos );
}
}
/* MDICommandHeaderDragging
*
* Called when the user is dragging a movable column in an MDI list.
* Calls InvertDragMark to clear the previous mark, then updates the current
* position and inverts the new mark area.
*
* Parameters:
*
* hwnd - The handle of the MDI window.
*
* pCursorPos - A pointer to the previous coordinates of the cursor.
* This will be updated with the new coordinates.
*
*/
VOID MDICommandHeaderDragging( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot )
{
InvertDragMark( hwnd, pCursorPos );
#ifdef DRAG_AS_WE_GO
/* This doesn't look too wonderful, cos there's a lot to do to keep up:
*/
UpdateColumns( hwnd, lpNot );
#endif /* DRAG_AS_WE_GO */
if( GetCursorPos( pCursorPos ) )
{
ScreenToClient( hwnd, pCursorPos );
InvertDragMark( hwnd, pCursorPos );
}
}
/* MDICommandHeaderEndDrag
*
* Called when the user releases the mouse button after dragging a movable
* column heading.
*
* Parameters:
*
* hwnd - The handle of the MDI window.
*
* pCursorPos - A pointer to the current coordinates of the cursor.
*
*
*/
VOID MDICommandHeaderEndDrag( HWND hwnd, PPOINT pCursorPos, HD_NOTIFY * lpNot )
{
PMDIWIN_INFO pMDIWinInfo;
pMDIWinInfo = GETMDIWIN(hwnd);
InvertDragMark( hwnd, pCursorPos );
UpdateColumns( hwnd, lpNot );
ENTER_PROTECTED_DATA( pMDIWinInfo );
SetEvent( pMDIWinInfo->RefreshSignal );
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
/* InvertDragMark
*
* Puts up a vertical mark to indicate where the user is dragging the movable
* headers of a list box.
* This function is called both to set and to clear the mark, since it simply
* inverts the mark rectangle.
*
* Parameters:
*
* hwnd - The handle of the MDI window.
*
* pCursorPos - A pointer to the current coordinates of the cursor.
*
*/
#define MARKERWIDTH 2
VOID InvertDragMark( HWND hwnd, PPOINT pCursorPos )
{
PMDIWIN_INFO pMDIWinInfo;
HWND hwndList;
RECT rcMark;
HDC hdc;
pMDIWinInfo = GETMDIWIN( hwnd );
hwndList = pMDIWinInfo->hwndList;
if( GetClientRect( hwnd, &rcMark ) )
{
rcMark.left = pCursorPos->x;
rcMark.right = ( rcMark.left + MARKERWIDTH );
hdc = GetDC( hwndList );
InvertRect( hdc, &rcMark );
ReleaseDC( hwndList, hdc );
}
}
/* UpdateColumns
*
* Finds out the new widths of the columns by sending
* HDM_GETITEM to the movable header control. Then updates the heading
* parameters in the window's instance data, and causes the list to repaint.
*
* Parameter:
*
* hwnd - The handle of the MDI window.
*
*/
VOID UpdateColumns( HWND hwnd, HD_NOTIFY * lpNot )
{
PMDIWIN_INFO pMDIWinInfo;
INT i, HeaderWidth[MAX_HEADERS];
INT cColumns;
PCOLUMN pColumn;
HD_ITEM hdi;
pMDIWinInfo = GETMDIWIN(hwnd);
cColumns = SendMessage( pMDIWinInfo->hwndHeader, HDM_GETITEMCOUNT,0,0);
pColumn = GETCOLUMN( hwnd );
hdi.mask = HDI_WIDTH;
for( i = 0; i < cColumns; i++ ) {
if (i != lpNot->iItem) {
Header_GetItem(pMDIWinInfo->hwndHeader, i, &hdi);
} else {
hdi.cxy = lpNot->pitem->cxy;
}
pColumn[i].Width = hdi.cxy;
}
InvalidateRect( pMDIWinInfo->hwndList, NULL, FALSE );
}
/* If someone's dropped a file on one of the MDI printer windows,
* we must ensure that the printer is default, since apps like File Manager
* just print to the default printer.
* Unfortunately, we can't revert to the previous default printer, because
* we won't know when the job has completed printing.
*/
VOID MDIDropObject( HWND hwnd )
{
PMDIWIN_INFO pInfo;
pInfo = GETMDIWIN(hwnd);
/* This should never be false:
*/
if( pInfo->WindowType != MDIWIN_SERVER )
{
/* Set the default printer and update the default combo */
}
}
/* Verify that we can close this MDI window with the system menu Close option.
* If not, an SC_MINIMIZE code should be sent to the window.
*/
BOOL MDIClose( HWND hwnd )
{
PMDIWIN_INFO pInfo;
pInfo = GETMDIWIN(hwnd);
if( !pInfo )
return FALSE;
/* We can close only server windows:
*/
if( pInfo->WindowType == MDIWIN_SERVER )
{
/* Just in case this is the last MDI window, clear the
* toolbar buttons and status bar:
*/
EnableCheckTBButtons(NULL);
UpdateStatus(NULL);
return TRUE;
}
else
return FALSE;
}
/* MDIVKeyToItemSpace
*
* Respond to spacebar presses by toggling document selection in printer
* windows.
*
*/
VOID MDIVKeyToItemSpace( HWND hwnd )
{
PMDIWIN_INFO pInfo;
DWORD Selection;
DWORD TopIndex;
RECT rcDragPosition;
pInfo = GETMDIWIN(hwnd);
if( !pInfo )
return;
if( pInfo->WindowType != MDIWIN_SERVER )
{
ENTER_PROTECTED_DATA( pInfo );
Selection = (DWORD)GETLISTSELECT( hwnd, ID_OBJLIST );
/* If there is no selection, retrieve the last selected guy,
* if it's in range:
*/
if( Selection == LB_ERR )
{
TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
if( ( pInfo->PrevSelection >= TopIndex )
&&( pInfo->PrevSelection <= ( TopIndex + pInfo->cNumLines ) ) )
pInfo->ObjSelected = pInfo->PrevSelection;
else
pInfo->ObjSelected = TopIndex;
/* Let's err on the side of caution;
* ensure that the data is still valid:
*/
if( !*pInfo->ppData )
{
Selection = NOSELECTION;
SETLISTSELECT( hwnd, ID_OBJLIST, Selection );
}
SetObjectSelection( pInfo, pInfo->ObjSelected );
pInfo->PrevSelection = 0;
}
else
{
pInfo->PrevSelection = Selection;
pInfo->ObjSelected = NOSELECTION;
pInfo->DragPosition = NOSELECTION;
*pInfo->pSelObjId = 0;
}
SETLISTSELECT( hwnd, ID_OBJLIST, pInfo->ObjSelected );
if( pInfo->DragPosition != NOSELECTION )
{
pInfo->DragPosition = NOSELECTION;
SendMessage( pInfo->hwndList, LB_GETITEMRECT, pInfo->DragPosition,
(LPARAM)&rcDragPosition );
InvalidateRect( pInfo->hwndList, &rcDragPosition, FALSE );
}
EnableCheckTBButtons(hwnd);
UpdateStatus(hwnd);
LEAVE_PROTECTED_DATA( pInfo );
}
}
/*
*
*/
VOID MDIParentNotifyRButtonDown( HWND hwnd, DWORD CursorPos )
{
PMDIWIN_INFO pInfo;
POINT ptCursor;
INT LBItem;
pInfo = GETMDIWIN(hwnd);
if( !pInfo )
return;
if( ( pInfo->WindowType != MDIWIN_SERVER )
&&( pInfo->DragPosition == NOSELECTION ) )
{
LONG2POINT( CursorPos, ptCursor );
ClientToScreen( hwnd, &ptCursor );
LBItem = LBItemFromPt( pInfo->hwndList, ptCursor, FALSE );
if( LBItem == (INT)pInfo->ObjSelected )
{
SETLISTSELECT( hwnd, ID_OBJLIST, NOSELECTION );
SendMessage( hwnd, WM_COMMAND,
GET_WM_COMMAND_MPS( GetDlgCtrlID( pInfo->hwndList ),
pInfo->hwndList, LBN_SELCHANGE ) );
}
}
}
/*
*
*/
VOID MDIVKeyToItemDefault( HWND hwnd )
{
PMDIWIN_INFO pInfo;
pInfo = GETMDIWIN(hwnd);
if( !pInfo )
return;
SendMessage( pInfo->hwndList, WM_RBUTTONDOWN, 0, 0L );
/* Clear any previous reorder mark:
*/
ClearDragPosition( pInfo );
}
/* ReorderJob
*
* Sets the job position to the value in the DragPosition field of pInfo,
* then forces a refresh of the job buffer.
*
*/
VOID ReorderJob( HWND hwnd, PMDIWIN_INFO pInfo, DWORD Position )
{
PQUEUE pQueue;
LPJOB_INFO_2 pJobReorder;
pQueue = (PQUEUE)pInfo->pContext;
if( !pQueue || !pQueue->pJobs )
return;
if( ( pInfo->ObjSelected == NOSELECTION ) || ( Position == NOSELECTION ) )
return;
ENTER_PROTECTED_DATA( pInfo );
pJobReorder = pQueue->pSelJob;
if( ( pJobReorder == NULL ) || ( pJobReorder == (LPJOB_INFO_2)NOSELECTION ) )
{
DBGMSG( DBG_ERROR, ( "Error: ReorderJob called with pSelJob == %d",
pJobReorder ) );
LEAVE_PROTECTED_DATA( pInfo );
return;
}
DBGMSG( DBG_INFO, ( "ReorderJob: JobId = %d; Position = %d\n",
pJobReorder->JobId, pJobReorder->Position ) );
if( pJobReorder )
{
BOOL OK;
/* Spooler order is 1-based:
*/
pJobReorder->Position = ( Position + 1 );
OK = SetJob( pQueue->hPrinter,
pJobReorder->JobId,
2, (LPBYTE)pJobReorder, 0 );
if( !OK )
ReportFailure( hwnd, 0, IDS_COULD_NOT_REORDER_JOB );
}
LEAVE_PROTECTED_DATA( pInfo );
}
/*
*
*/
VOID MarkPosition( PMDIWIN_INFO pInfo, DWORD Position )
{
DWORD OldPosition;
/* N.B. Ensure pInfo->DragPosition is updated before we do any repainting,
* since MDIDrawItem depends on it:
*/
if( pInfo->DragPosition != Position )
{
/* If the top index hasn't been reset, we need to force a repaint
* of the old and new reorder positions:
*/
OldPosition = pInfo->DragPosition;
pInfo->DragPosition = Position;
RepaintListboxItem( pInfo->hwndList, OldPosition );
if( Position != (DWORD) NOSELECTION )
RepaintListboxItem( pInfo->hwndList, Position );
}
}
/* MDIVKeyToItemUpDown
*
* Called when the user presses an up or down cursor.
* We're interested in this only if the control key is also depressed
* at the same time, otherwise we rely on the default system response.
*
* The Ctrl-Up or Ctrl-Down combination is used
*
*/
int MDIVKeyToItemUpDown( HWND hwnd, WORD VKey )
{
PMDIWIN_INFO pInfo;
DWORD Selection;
DWORD TopIndex;
DWORD DragPosition;
pInfo = GETMDIWIN(hwnd);
/* if the high-order bit of the SHORT returned from GetKeyState
* is on, the key is down:
*/
if( ( pInfo->WindowType != MDIWIN_SERVER )
&&( GetKeyState( VK_CONTROL ) & 0x8000 )
&&( pInfo->pContext )
&&( ( (PQUEUE)( pInfo->pContext ) )->AccessGranted & PRINTER_ACCESS_ADMINISTER ) )
{
ENTER_PROTECTED_DATA( pInfo );
ResetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_DATA( pInfo );
Selection = (DWORD)GETLISTSELECT( hwnd, ID_OBJLIST );
TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
DragPosition = pInfo->DragPosition;
if( DragPosition == NOSELECTION )
{
DragPosition = Selection;
pInfo->ObjSelected = Selection;
}
switch( VKey )
{
case VK_UP:
case VK_LEFT:
if( DragPosition > 0 )
DragPosition--;
break;
case VK_DOWN:
case VK_RIGHT:
if( DragPosition < ( *pInfo->pcObjects - 1 ) )
DragPosition++;
}
/* N.B. Ensure pInfo->DragPosition is updated before we do any repainting,
* since MDIDrawItem depends on it:
*/
if( pInfo->DragPosition != DragPosition )
{
MarkPosition( pInfo, DragPosition );
/* Scroll up a line if we've gone off the top:
*/
if( DragPosition < TopIndex )
SendMessage( pInfo->hwndList, LB_SETTOPINDEX, DragPosition, 0L );
/* Scroll down a line if we've gone off the bottom:
*/
else if( DragPosition >= ( TopIndex + pInfo->cNumLines ) )
SendMessage( pInfo->hwndList, LB_SETTOPINDEX, TopIndex+1, 0L );
}
LEAVE_PROTECTED_DATA( pInfo );
return -2;
}
else
{
if( pInfo->DragPosition != NOSELECTION )
{
pInfo->DragPosition = NOSELECTION;
RepaintListboxItem( pInfo->hwndList, pInfo->DragPosition );
}
return -1;
}
}
/*
*
*/
VOID RepaintListboxItem( HWND hwndListbox, DWORD ItemID )
{
RECT rcItem;
SendMessage( hwndListbox, LB_GETITEMRECT, ItemID, (LPARAM)&rcItem );
InvalidateRect( hwndListbox, &rcItem, FALSE );
}
/* Size the list in sync with the MDI window
*
*/
VOID MDISize( HWND hWnd, DWORD Coordinates )
{
PMDIWIN_INFO pMDIWinInfo;
DWORD cxList, cyList;
pMDIWinInfo = GETMDIWIN(hWnd);
cxList = LOWORD(Coordinates);
cyList = HIWORD(Coordinates) - HeaderHeight;
SetWindowPos (pMDIWinInfo->hwndHeader, 0, 0, 0, cxList,
HeaderHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
/* Count partial lines in the list box:
*/
pMDIWinInfo->cNumLines = ( cyList / STATUS_BITMAP_HEIGHT );
// Move listbox child window also
MoveWindow(pMDIWinInfo->hwndList, 0, HeaderHeight,
cxList, cyList, TRUE);
}
/*
*
*/
LONG MDIMDIActivate( HWND hwnd, HWND hwndDeactivate, HWND hwndActivate )
{
PMDIWIN_INFO pMDIWinInfo;
DWORD CurSel;
DWORD TopIndex;
if( hwnd == hwndActivate )
{
pMDIWinInfo = GETMDIWIN(hwnd);
ENTER_PROTECTED_DATA( pMDIWinInfo );
if( pMDIWinInfo )
{
CurSel = SendMessage( pMDIWinInfo->hwndList, LB_GETCURSEL, 0, 0L );
TopIndex = SendMessage( pMDIWinInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
if( ( TopIndex <= CurSel ) && ( CurSel < pMDIWinInfo->cNumLines ) )
SendMessage( pMDIWinInfo->hwndList, LB_SETCURSEL, CurSel, 0L );
}
EnableCheckTBButtons(hwnd);
UpdateStatus(hwnd);
LEAVE_PROTECTED_DATA( pMDIWinInfo );
}
else if (hwnd == hwndDeactivate){
pMDIWinInfo = GETMDIWIN(hwnd);
if (pMDIWinInfo) {
CurSel = SendMessage( pMDIWinInfo->hwndList, LB_GETCURSEL, 0, 0L);
SendMessage(pMDIWinInfo->hwndList, LB_SETCURSEL, CurSel, -1);
}
}
return 0;
}
/* MDINCActivate
*
* Forget about any drag operations that have been started
* if we're going inactive
*/
VOID MDINCActivate( HWND hwnd )
{
PMDIWIN_INFO pInfo;
pInfo = GETMDIWIN(hwnd);
if( !pInfo || ( pInfo->WindowType == MDIWIN_SERVER ) )
return;
SendMessage( pInfo->hwndList, WM_RBUTTONDOWN, 0, 0L );
/* Clear any previous reorder mark:
*/
ClearDragPosition( pInfo );
}
/*
*
*/
LONG MDIWindowPosChanged( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
HWND hwndActive;
PMDIWIN_INFO pInfo;
LONG rc;
PWINDOWPOS pWindowPos = (PWINDOWPOS)lParam;
rc = DefMDIChildProc(hwnd, WM_WINDOWPOSCHANGED, wParam, lParam);
if( !( pWindowPos->flags & SWP_HIDEWINDOW )
&&( hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L)))
{
if( pInfo = GETMDIWIN(hwndActive) )
{
ENTER_PROTECTED_DATA(pInfo);
UpdateStatus(hwndActive);
LEAVE_PROTECTED_DATA(pInfo);
}
}
return rc;
}
/*
*
*/
VOID ClearDragPosition( PMDIWIN_INFO pInfo )
{
DWORD OldDragPosition;
if( ( OldDragPosition = pInfo->DragPosition ) != NOSELECTION )
{
pInfo->DragPosition = NOSELECTION;
RepaintListboxItem( pInfo->hwndList, OldDragPosition );
ENTER_PROTECTED_DATA( pInfo );
SetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_DATA( pInfo );
}
}
/*
*
*/
VOID MDISetFocus( HWND hwnd )
{
PMDIWIN_INFO pMDIWinInfo;
pMDIWinInfo = GETMDIWIN(hwnd);
/* Ensure that keyboard input will be sent to the listbox:
*/
SetFocus( pMDIWinInfo->hwndList );
}
/*
*
*/
VOID MDIMeasureItem( HWND hwnd, LPMEASUREITEMSTRUCT pmis )
{
/* For now just specify the bitmap size.
* This will have to change if font selection becomes a reality:
*/
pmis->itemHeight = STATUS_BITMAP_HEIGHT;
}
#define LEFTMARGIN 2
#define MAXCOLUMNWIDTH 256
/*
*
*/
VOID MDIDrawItem( HWND hwnd, LPDRAWITEMSTRUCT pdis )
{
PMDIWIN_INFO pInfo;
RECT WindowRect, LineRect;
PCOLUMN pColumn;
TCHAR string[MAXCOLUMNWIDTH];
int i;
int j;
PBYTE pData;
BOOL ThisWindowIsActive;
BOOL Selected;
DWORD ColumnLeft;
pInfo = GETMDIWIN(hwnd);
if( !pInfo )
return;
if( pdis->itemID == (UINT)-1 )
{
DrawFocusRect( pdis->hDC, &pdis->rcItem );
return;
}
if( pdis->itemID == 0 )
pInfo->TopIndex = SendMessage( pdis->hwndItem, LB_GETTOPINDEX, 0, 0 );
ENTER_PROTECTED_DATA( pInfo );
GetWindowRect( hwnd, &WindowRect );
pColumn = pInfo->pColumns;
i = ( (int)pdis->itemID - (int)*pInfo->pFirstEnumObj );
/* If we've strayed outside our buffer of jobs, refresh the jobs list:
*/
if( ( i < 0 ) || ( (DWORD)i >= *pInfo->pcEnumObjs ) )
{
DBGMSG( DBG_TRACE, ( "MDIDrawItem calling GetJobs\n" ) );
/* This should always be true, since we're enumerating
* all the printers in a Server window:
*/
if( pInfo->WindowType != MDIWIN_SERVER )
{
DWORD TopIndex;
DWORD dwChangeJob;
TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
/* Enumerate a buffer big enough to page up once ...
*/
*pInfo->pFirstEnumObj = (DWORD)max( 0, (int)TopIndex - (int)pInfo->cNumLines );
SetCursor( hcursorWait );
ENTER_PROTECTED_DATA( pInfo );
dwChangeJob = PRINTER_CHANGE_JOB;
GetJobs( pInfo->pContext, &dwChangeJob );
LEAVE_PROTECTED_DATA( pInfo );
SetCursor( hcursorArrow );
}
i = ( (int)pdis->itemID - (int)*pInfo->pFirstEnumObj );
/* HARMLESS HACK:
*
* If there's a lot of scrolling going on at the moment,
* it sometimes still isn't in sync with the buffer,
* so bomb out to avoid attempting to reference a job
* we haven't got:
*/
if( ( i < 0 ) || ( (DWORD)i >= *pInfo->pcEnumObjs ) )
{
LEAVE_PROTECTED_DATA( pInfo );
return;
}
}
/* Maybe there was some sort of error last time we enumerated.
* If so, ppData should be NULL. Bomb out:
*/
if( !*pInfo->ppData )
{
LEAVE_PROTECTED_DATA( pInfo );
return;
}
pData = ( *pInfo->ppData + ( (DWORD)i * pInfo->DataSize ) );
/* See comment on CreateWindowInfo - we need to
determine whether printer status information is
being generated by the Status field in JOB_INFO_2
or the pStatus field in JOB_INFO_2. Also check to
see that the pInfo window type is not MDIWIN_SERVER
*/
if (pInfo->WindowType != MDIWIN_SERVER) {
if (((PJOB_INFO_2)pData)->pStatus != NULL) {
pInfo->pColumns[MDIHEAD_JOB_STATUS].Offset = offsetof(JOB_INFO_2, pStatus);
pInfo->pColumns[MDIHEAD_JOB_STATUS].Datatype = MDIDATA_PSZ;
}
else {
pInfo->pColumns[MDIHEAD_JOB_STATUS].Offset = offsetof(JOB_INFO_2, Status);
pInfo->pColumns[MDIHEAD_JOB_STATUS].Datatype = MDIDATA_JOB_STATUS;
}
}
LineRect = pdis->rcItem;
ThisWindowIsActive = ( hwnd == (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L) );
Selected = ( ThisWindowIsActive && ( pdis->itemState & ODS_SELECTED ) );
/* Special case the status icon and first column:
*/
DisplayStatusIcon( pdis->hDC, &LineRect, pInfo->WindowType,
( pData + pInfo->IconStatus ), Selected );
/* Pad some blanks at the left of the field:
*/
for( i = 0; i < LEFTMARGIN; i++ )
string[i] = SPACE;
ColumnLeft = 0;
for( j = 0; j < pInfo->cColumns; j++ )
{
FormatData( ( pData + pColumn[j].Offset ), pColumn[j].Datatype, &string[LEFTMARGIN-1] );
LineRect.left = ColumnLeft;
if( j == 0 )
LineRect.left += STATUS_BITMAP_SPACE;
LineRect.right = ( ColumnLeft + pColumn[j].Width );
DrawLine( pdis->hDC, &LineRect, string, Selected );
/* If this is the last column and this is a highlight line,
* continue the highlight to the right-hand side of the window:
*/
if( j == ( pInfo->cColumns - 1 ) )
{
LineRect.left = LineRect.right;
LineRect.right = WindowRect.right;
DrawLine( pdis->hDC, &LineRect, TEXT(""), Selected );
}
ColumnLeft += pColumn[j].Width;
}
if( pdis->itemState & ODS_FOCUS )
DrawFocusRect( pdis->hDC, &pdis->rcItem );
if( ( pInfo->WindowType != MDIWIN_SERVER )
&&( pdis->itemID == pInfo->DragPosition ) )
{
HBRUSH hbr;
if( hbr = CreateSolidBrush( GetSysColor( COLOR_HIGHLIGHT ) ) )
{
LineRect = pdis->rcItem;
if( pInfo->DragPosition > pInfo->ObjSelected )
LineRect.top = LineRect.bottom-1;
else
LineRect.bottom = LineRect.top+1;
FrameRect( pdis->hDC, &LineRect, hbr );
DeleteObject( hbr );
}
}
LEAVE_PROTECTED_DATA( pInfo );
}
/*
*
*/
VOID MDITimer( HWND hWnd )
{
PMDIWIN_INFO pInfo;
BOOL CheckStatus;
DWORD OldStatus;
DWORD NewStatus;
PQUEUE pQueue;
BOOL PrinterNameChanged = FALSE;
pInfo = GETMDIWIN( hWnd );
if( !pInfo )
return;
/* If the status of a printer has changed to/from Paused,
* we want to update the title (even if it's iconic).
* This may have happened even though the MDI window
* isn't active (e.g. through the Server Viewer).
*/
CheckStatus = ( pInfo->WindowType != MDIWIN_SERVER );
ENTER_PROTECTED_DATA( pInfo );
if( CheckStatus )
{
pQueue = (PQUEUE)pInfo->pContext;
if( !pQueue )
{
LEAVE_PROTECTED_DATA( pInfo );
return;
}
if( pQueue->pPrinter )
OldStatus = pQueue->pPrinter->Status;
else
OldStatus = PRINTER_STATUS_UNKNOWN;
}
if( !IsIconic( hwndFrame )
// && !pInfo->RefreshSignal && !IsIconic( hWnd )
/* && IsWindowReallyVisible( hWnd ) */ )
/* ^^^^^^^^^^^^^^^^^^^^^ watch this space for new API from scottlu */
{
if( hWnd == (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L))
EnableCheckTBButtons(hWnd);
}
LEAVE_PROTECTED_DATA( pInfo );
if( CheckStatus )
{
if( pQueue->pPrinter )
{
ENTER_PROTECTED_DATA( pInfo );
if( _tcscmp( pQueue->pPrinterName, pQueue->pPrinter->pPrinterName ) )
{
ReallocSplStr( &pQueue->pPrinterName, pQueue->pPrinter->pPrinterName );
PrinterNameChanged = TRUE;
}
NewStatus = pQueue->pPrinter->Status;
LEAVE_PROTECTED_DATA( pInfo );
}
else
{
//
// !! BUGBUG !!
//
// This GetLastError() call looks bogus.
//
if( GetLastError() == ERROR_ACCESS_DENIED )
NewStatus = PRINTER_STATUS_ACCESS_DENIED;
else
NewStatus = PRINTER_STATUS_UNKNOWN;
}
if( ( OldStatus != NewStatus ) || PrinterNameChanged )
{
ENTER_PROTECTED_DATA( pInfo );
SetPrinterTitle( hWnd, pQueue->pPrinterName, NewStatus );
LEAVE_PROTECTED_DATA( pInfo );
/* Hack to ensure listbox is redrawn when connexion is re-established:
*/
if( OldStatus == PRINTER_STATUS_UNKNOWN )
{
InvalidateRect( pQueue->pMDIWinInfo->hwndList, NULL, TRUE );
}
}
}
}
#ifdef OLDSTUFF
/*
*
*/
VOID MDIStatusChanged( HWND hwnd )
{
PMDIWIN_INFO pInfo;
PQUEUE pQueue;
pInfo = GETMDIWIN( hwnd );
if( pInfo->WindowType != MDIWIN_SERVER )
{
pQueue = (PQUEUE)pInfo->pContext;
ENTER_PROTECTED_DATA( pInfo );
SetPrinterTitle( hwnd, pQueue->pPrinterName,
pQueue->pPrinter->Status );
LEAVE_PROTECTED_DATA( pInfo );
}
}
#endif /* OLDSTUFF */
/*
*
*/
VOID MDIUpdateList( HWND hwnd )
{
PMDIWIN_INFO pInfo;
DWORD CurSel;
BOOL PrinterWasSet = FALSE;
RECT rcList;
DWORD TopIndex;
DWORD BottomIndex;
pInfo = GETMDIWIN( hwnd );
DBGMSG( DBG_TRACE, ( "WM_UPDATE_LIST\n" ) );
ENTER_PROTECTED_DATA( pInfo );
SendMessage( pInfo->hwndList, WM_SETREDRAW, 0, 0L );
/* Keep the listbox item count in sync with the number of objects on display:
*/
if( SendMessage( pInfo->hwndList, LB_GETCOUNT, 0, 0L ) != (int)*pInfo->pcObjects )
{
/* We have to go through hoops here since the nodata listbox
* is so brain dead. When you set the count, it invalidates
* the list and sets the top index to 0...
*/
CurSel = SendMessage( pInfo->hwndList, LB_GETCURSEL, 0, 0L );
SendMessage( pInfo->hwndList, LB_SETCOUNT, *pInfo->pcObjects, 0L );
SendMessage( pInfo->hwndList, LB_SETCURSEL, CurSel, 0L );
}
if( pInfo->ObjSelected == NOSELECTION )
{
SendMessage( pInfo->hwndList, LB_SETCURSEL, (WPARAM)-1, 0L );
}
/* If the selected item is currently visible, make sure it
* corresponds to the item that the system thinks is selected:
*/
else if( ( pInfo->ObjSelected >= *pInfo->pFirstEnumObj )
&&( pInfo->ObjSelected < ( *pInfo->pFirstEnumObj + pInfo->cNumLines ) )
&&( SendMessage( pInfo->hwndList, LB_GETCURSEL, 0, 0L )
!= (int)pInfo->ObjSelected ) )
{
SendMessage( pInfo->hwndList, LB_SETCURSEL, pInfo->ObjSelected, 0L );
}
ValidateRect( pInfo->hwndList, NULL );
SendMessage( pInfo->hwndList, WM_SETREDRAW, 1, 0L );
SetMDITitle( hwnd, pInfo );
/* Don't erase the background for the part of the listbox with items in it,
* but ensure that the rest is completely redrawn, otherwise we may leave
* things lying around:
*/
GetClientRect( pInfo->hwndList, &rcList );
TopIndex = (DWORD)SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
DBGMSG( DBG_TRACE, ( "Top Index: %d\n", TopIndex ) );
if( TopIndex != (DWORD)-1 )
{
BottomIndex = ( *pInfo->pcObjects - TopIndex );
DBGMSG( DBG_TRACE, ( "Bottom Index: %d\n", BottomIndex ) );
rcList.bottom = min( rcList.bottom,
(LONG)( BottomIndex * STATUS_BITMAP_HEIGHT ) );
DBGMSG( DBG_TRACE, ( "Invalidate %d, %d, %d, %d, FALSE\n",
rcList.left, rcList.top, rcList.right, rcList.bottom ) );
InvalidateRect( pInfo->hwndList, &rcList, FALSE );
UpdateWindow( pInfo->hwndList );
GetClientRect( pInfo->hwndList, &rcList );
rcList.top = min( rcList.bottom,
(LONG)( BottomIndex * STATUS_BITMAP_HEIGHT ) );
}
DBGMSG( DBG_TRACE, ( "Invalidate %d, %d, %d, %d, TRUE\n",
rcList.left, rcList.top, rcList.right, rcList.bottom ) );
InvalidateRect( pInfo->hwndList, &rcList, TRUE );
UpdateWindow( pInfo->hwndList );
if( pInfo->hwnd == (HWND)SendMessage( hwndClient, WM_MDIGETACTIVE, 0, 0L ) )
{
UpdateStatus( pInfo->hwnd );
EnableCheckTBButtons( pInfo->hwnd );
}
if( (!( pInfo->Changes & PRINTER_CHANGE_TIMEOUT ) )
&&( pInfo->Changes & PRINTER_CHANGE_SET_PRINTER ) )
PrinterWasSet = TRUE;
if( PrinterWasSet )
UpdateDefaultList();
LEAVE_PROTECTED_DATA( pInfo );
/* Ensure that any relevant changes (e.g. port for default printer)
* get updated in WIN.INI for the benefit of Win31 apps.
* Do this by faking a change in the default printer.
* (Fixes bug #6011.)
*
* Moved from PrtPropCommandOK().
*/
//
// szDefaultPrinter updated in the call to UpdateDefaultList above.
//
if( PrinterWasSet )
ToolbarCommandSelChange(TRUE);
}
/* MDISetParts
*
* Called after creation to set the column widths.
* Pass the message on to the header window.
*/
VOID MDISetParts( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
PMDIWIN_INFO pInfo;
if( pInfo = GETMDIWIN( hwnd ) )
{
SendMessage( pInfo->hwndHeader, SB_SETPARTS, wParam, lParam );
}
}
/*
*
*/
VOID MDIDestroy( HWND hwnd )
{
PMDIWIN_INFO pInfo;
pInfo = GETMDIWIN( hwnd );
ENTER_PROTECTED_DATA( pInfo );
KillMDIWinInfo(pInfo);
switch( pInfo->WindowType )
{
case MDIWIN_LOCALPRINTER:
case MDIWIN_NETWORKPRINTER:
case MDIWIN_LOCALNETWORKPRINTER:
if( ((PQUEUE)(pInfo->pContext))->hPrinter ) {
ClosePrinter( ((PQUEUE)(pInfo->pContext))->hPrinter );
((PQUEUE)(pInfo->pContext))->hPrinter = NULL;
}
break;
case MDIWIN_SERVER:
if( ((PSERVER_CONTEXT)(pInfo->pContext))->hServer ) {
ClosePrinter( ((PSERVER_CONTEXT)(pInfo->pContext))->hServer );
((PSERVER_CONTEXT)(pInfo->pContext))->hServer = NULL;
}
break;
}
LEAVE_PROTECTED_DATA( pInfo );
}
/*
*
*/
LONG MDIDragList( HWND hwnd, LPDRAGLISTINFO pDragInfo )
{
PMDIWIN_INFO pInfo;
PQUEUE pPrinterContext;
DWORD DragPosition;
if( !( pInfo = GETMDIWIN( hwnd ) ) )
return 0;
if( !( pPrinterContext = pInfo->pContext ) )
return 0;
/* You have to be an administrator on the printer to reorder jobs:
*/
if( !( pPrinterContext->AccessGranted & PRINTER_ACCESS_ADMINISTER ) )
return 0;
if( *pInfo->pcObjects < 1 )
return 0;
DragPosition = LBItemFromPt( pDragInfo->hWnd, pDragInfo->ptCursor, TRUE );
switch( pDragInfo->uNotification )
{
case DL_BEGINDRAG:
ENTER_PROTECTED_DATA( pInfo );
ResetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_DATA( pInfo );
return -1;
case DL_DRAGGING:
if( DragPosition < *pInfo->pcObjects )
{
MarkPosition( pInfo, DragPosition );
SetCursor( hcursorReorder );
return -1;
}
else
return DL_STOPCURSOR;
case DL_DROPPED:
if( DragPosition != pInfo->ObjSelected )
ReorderJob( hwnd, pInfo, DragPosition );
// drop through...
case DL_CANCELDRAG:
MarkPosition( pInfo, NOSELECTION );
ENTER_PROTECTED_DATA( pInfo );
SetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_DATA( pInfo );
}
return 0;
}
VOID SubclassListboxKeyDown( HWND hwnd, INT VKey );
VOID SubclassListboxKeyUp( HWND hwnd, INT VKey );
/* Subclass window procedure for MDI printer listbox containing jobs.
* Server viewers are not subclassed.
*/
long SubclassListboxWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LONG lParam
)
{
switch( message )
{
case WM_KEYDOWN:
SubclassListboxKeyDown( hwnd, (INT)wParam );
break;
case WM_KEYUP:
SubclassListboxKeyUp( hwnd, (INT)wParam );
break;
}
return CallWindowProc( DefListboxWndProc, hwnd, message, wParam, lParam );
}
/* This catches the delete key being pressed.
* If there is a job selected, go ahead and delete it.
* We don't respond if a printer currently has the focus.
*/
VOID SubclassListboxKeyDown( HWND hwnd, INT VKey )
{
PMDIWIN_INFO pInfo;
if( VKey == VK_DELETE )
{
pInfo = GETMDIWIN( GetParent( hwnd ) );
if( !pInfo )
return;
/* If there's a current selection, fake a Remove Document command:
*/
if( pInfo->ObjSelected != NOSELECTION )
SendMessage( hwndFrame, WM_COMMAND,
MAKEWPARAM( IDM_REMOVEDOC, 0 ), 0 );
}
}
/* This handles the case where the user releases the control key
* whilst dragging a job using the cursor keys.
* This completes the drag operation.
*/
VOID SubclassListboxKeyUp( HWND hwnd, INT VKey )
{
PMDIWIN_INFO pInfo;
DWORD NewPos;
if( VKey == VK_CONTROL )
{
pInfo = GETMDIWIN( GetParent( hwnd ) );
if( !pInfo )
return;
if( ( pInfo->DragPosition != NOSELECTION )
&&( pInfo->ObjSelected != pInfo->DragPosition ) )
{
NewPos = pInfo->DragPosition;
ReorderJob( GetParent( hwnd ), pInfo, pInfo->DragPosition );
MarkPosition( pInfo, NOSELECTION );
SETLISTSELECT( GetParent( hwnd ), ID_OBJLIST, NewPos );
SetEvent( pInfo->RefreshSignal );
LEAVE_PROTECTED_DATA( pInfo );
}
}
}
VOID
Refresh(
HWND hwnd,
PMDIWIN_INFO pInfo,
DWORD RepaintOption)
{
DWORD Changed;
DWORD TopIndex;
DWORD MutexStatus;
if( !pInfo )
return;
if (pInfo->WindowType == MDIWIN_SERVER) {
/* This can't happen, we've grayed out the menu-item for
* server mdi windows. Anyway, let's bomb out
*/
return;
}
//
// If still loading, return now since the worker thread
// is initializing and will refresh when it can.
//
if (pInfo->Status & PRINTER_STATUS_LOADING)
return;
/* access protected area of pInfo with "zero"
* timeout. if we couldn't access, then quit here
* RefreshThread is in the middle of an update.
* let it take care of the refreshing.
*/
MutexStatus = WaitForSingleObject(pInfo->DataMutex, 0);
if (MutexStatus == -1) {
// Couldn't acquire the mutex
return;
}
if (MutexStatus == WAIT_TIMEOUT) {
/* This means RefreshThread has ownership of the
mutex -- it will take care of updating -- return
*/
return;
}
/* We own the DataMutex at this point */
TopIndex = SendMessage( pInfo->hwndList, LB_GETTOPINDEX, 0, 0L );
/* Enumerate a buffer big enough to page up once ...
*/
*pInfo->pFirstEnumObj = (DWORD)max( 0, (int)TopIndex - (int)pInfo->cNumLines );
SetCursor( hcursorWait );
ENTER_PROTECTED_DATA(pInfo);
if( pInfo->pfnRefresh )
{
//
// *pInfo->phWaitObject should be NULL if the OpenPrinter
// fails... but OpenPrinter will succeed even if the
// remote printer is not available (probably for winword),
// So add unknown here also.
//
if (pInfo->Status & PRINTER_STATUS_UNKNOWN ||
!*pInfo->phWaitObject)
{
//
// We have an unknown connection; try and reopen
// when refresh, in case the admin gave us
// access recently. Or possibly the net was down...
//
if (*pInfo->phWaitObject) {
ClosePrinter(*pInfo->phWaitObject);
*pInfo->phWaitObject = NULL;
}
ReopenPrinter( pInfo->pContext, pInfo->WindowType, TRUE );
}
Changed = PRINTER_CHANGE_JOB|PRINTER_CHANGE_PRINTER;
(*pInfo->pfnRefresh)( pInfo->pContext, &Changed );
}
LEAVE_PROTECTED_DATA(pInfo);
SetCursor( hcursorArrow );
/* REPAINT_FORCE makes sense only when we definitely want the list
* to repaint even if there have been no changes to its contents.
* The only time this should happen is when the refresh is in response
* to the user's selecting the Refresh menu option:
*/
if( ( Changed && ( RepaintOption == REPAINT_IF_CHANGED ) )
||( RepaintOption == REPAINT_FORCE ) )
{
/* Keep the listbox item count in sync with the number of objects on display:
* Originally, this code was duplicating the MDIUpdateList function. So let's just
* send a WM_UPDATELIST message to the MDI window to take care of the rest.
*/
PostMessage(pInfo->hwnd, WM_UPDATE_LIST, (WPARAM)pInfo, 0L);
}
ReleaseMutex(pInfo->DataMutex);
return;
}
/*
*
*/
BOOL
RefreshServerContext(
PVOID pContext,
PDWORD pFlags )
{
PSERVER_CONTEXT pServerContext;
LPTSTR pCurrentSelection = NULL;
DWORD Error = NO_ERROR;
pServerContext = (PSERVER_CONTEXT)pContext;
ENTER_PROTECTED_DATA( pServerContext->pMDIWinInfo );
//
// Don't change the default printer here since the set printer
// was remote.
//
*pFlags &= ~PRINTER_CHANGE_SET_PRINTER;
/* We may end up having to reallocate the buffer, so make sure we keep track
* of the name of the currently selected printer:
*/
if( pServerContext->pSelPrinter )
pCurrentSelection = AllocSplStr( pServerContext->pSelPrinter->pPrinterName );
if( ENUM_PRINTERS( PRINTER_ENUM_NAME,
pServerContext->pServerName,
2,
pServerContext->pPrinters,
pServerContext->cbPrinters,
&pServerContext->cbPrinters,
&pServerContext->cPrinters ) )
{
DWORD i = 0;
pServerContext->cEnumPrinters = pServerContext->cPrinters;
/* Find the printer name that matches the current selection:
*/
if( pCurrentSelection )
{
while( ( i < pServerContext->cPrinters )
&& _tcscmp( pServerContext->pPrinters[i].pPrinterName,
pCurrentSelection ) )
i++;
}
if( i < pServerContext->cPrinters )
{
pServerContext->pSelPrinter = &pServerContext->pPrinters[i];
pServerContext->SelPrinterId = i;
pServerContext->pMDIWinInfo->ObjSelected = i;
}
else
{
pServerContext->pSelPrinter = &pServerContext->pPrinters[0];
pServerContext->SelPrinterId = 0;
}
}
else
{
pServerContext->SelPrinterId = 0;
pServerContext->pSelPrinter = NULL;
pServerContext->pMDIWinInfo->ObjSelected = NOSELECTION;
Error = GetLastError( );
}
if( pCurrentSelection )
FreeSplStr( pCurrentSelection );
pServerContext->Error = Error;
LEAVE_PROTECTED_DATA( pServerContext->pMDIWinInfo );
return ( Error == NO_ERROR );
}
/* Message
*
* Displays a message by loading the strings whose IDs are passed into
* the function, and substituting the supplied variable argument list
* using the varargs macros.
*
*/
int Message(HWND hwnd, DWORD Type, int CaptionID, int TextID, ...)
{
TCHAR MsgText[MAX_PATH*2];
TCHAR MsgFormat[520];
TCHAR MsgCaption[80];
va_list vargs;
if( ( LoadString( hInst, TextID, MsgFormat,
sizeof MsgFormat / sizeof *MsgFormat ) > 0 )
&& ( LoadString( hInst, CaptionID, MsgCaption,
sizeof MsgCaption / sizeof *MsgCaption ) > 0 ) )
{
va_start( vargs, TextID );
wvsprintf( MsgText, MsgFormat, vargs );
va_end( vargs );
return MessageBox(hwnd, MsgText, MsgCaption, Type);
}
else
return 0;
}
FARPROC LoadLibraryGetProcAddress(HWND hwnd, LPTSTR LibraryName, LPCSTR ProcName,
PHANDLE phLibrary)
{
HANDLE hLibrary;
FARPROC lpfn = NULL;
hLibrary = LoadLibrary(LibraryName);
if(hLibrary)
{
lpfn = GetProcAddress(hLibrary, ProcName);
if(!lpfn)
{
Message(hwnd, MSG_ERROR, IDS_PRINTMANAGER,
IDS_COULDNOTFINDPROCEDURE, ProcName, LibraryName);
FreeLibrary(hLibrary);
}
}
else
Message(hwnd, MSG_ERROR, IDS_PRINTMANAGER,
IDS_COULDNOTLOADLIBRARY, LibraryName);
*phLibrary = hLibrary;
return lpfn;
}
/* Returns the positions saved in the registry of windows and headers.
* Return code is TRUE if the information is found, FALSE otherwise.
* If there is no information found, default values are substituted
* for the window position, but no default header values are assigned.
*
*/
BOOL GetSavedWindowPos( LPTSTR pKey, LPTSTR WindowName, PSAVEDWINDOWPOS pswp,
DWORD cHeaders, PINT pHeaders )
{
PREGISTRY_DATA pRegistryData;
DWORD cbRegistryData;
DWORD rc;
DWORD i;
PINT pint;
/* Get the size of the fixed part of the registry data:
*/
cbRegistryData = ( sizeof( REGISTRY_DATA ) - sizeof( pRegistryData->Headers ) );
cbRegistryData += ( cHeaders * sizeof( pRegistryData->Headers ) );
pRegistryData = AllocSplMem( cbRegistryData );
RegistryEntries.Size = cbRegistryData;
rc = ReadRegistryData( pKey, WindowName, (LPBYTE)pRegistryData, &RegistryEntries );
if( rc == NO_ERROR )
{
pswp->left = pRegistryData->WindowPlacement.rcNormalPosition.left;
pswp->top = pRegistryData->WindowPlacement.rcNormalPosition.top;
pswp->width = pRegistryData->WindowPlacement.rcNormalPosition.right - pswp->left;
pswp->height = pRegistryData->WindowPlacement.rcNormalPosition.bottom - pswp->top;
pswp->xicon = pRegistryData->WindowPlacement.ptMinPosition.x;
pswp->yicon = pRegistryData->WindowPlacement.ptMinPosition.y;
pswp->sw = pRegistryData->WindowPlacement.showCmd;
pswp->options = pRegistryData->Options;
for( i = 0; i < cHeaders; i++ )
pHeaders[i] = pRegistryData->Headers[i];
}
else
{
/* No data retrieved from the registry:
* Substitute default values:
*/
pint = (PINT)pswp;
for( i = 0; i < RECTSIDES; i++ )
pint[i] = CW_USEDEFAULT;
for( i = RECTSIDES; i < INIVALUES; i++ )
pint[i] = 0;
pswp->sw = SW_NORMAL;
}
FreeSplMem( pRegistryData );
return ( rc == NO_ERROR );
}
// int _CRTAPI1
HWND GetRealParent( HWND hwnd )
{
// run up the parent chain until you find a hwnd
// that doesn't have WS_CHILD set
while( GetWindowLong( hwnd, GWL_STYLE ) & WS_CHILD )
hwnd = (HWND)GetWindowLong( hwnd, GWL_HWNDPARENT );
return hwnd;
}
#ifdef OLDSTUFF
/* MessageProc
*
* This is the callback routine which hooks F1 keypresses in menus and dialog boxes.
*
* Any such message will be repackaged as a WM_Help message and sent to the frame.
*
* Two codes are handled:
*
* MSGF_MENU - In this case, the message originates in a menu item,
* and the hwnd parameter of pMsg contains the menu handle.
* We get the ID of the currently selected menu item.
*
* MSGF_DIALOGBOX - In this case, the message originates in a dialog box,
* and the hwnd parameter of pMsg contains the dialog item handle.
* We get its control ID.
*
*
* See the Win32 API programming reference for a description of how this
* routine works.
*
* Andrew Bell (andrewbe) - 2 September 1992
*/
LRESULT CALLBACK MessageProc( int Code, WPARAM wParam, LPARAM lParam )
{
PMSG pMsg = (PMSG)lParam;
if( Code < 0 )
return CallNextHookEx( hhookMessage, Code, wParam, lParam );
switch( Code )
{
case MSGF_MENU:
if( ( pMsg->message == WM_KEYDOWN ) && ( pMsg->wParam == VK_F1 ) )
{
PostMessage( hwndFrame, WM_Help, (LPARAM)pMsg->hwnd,
WinHelpMenuID );
// GetCurrentMenuItemID( GetMenu( hwndFrame ) ) );
return 1;
}
break;
case MSGF_DIALOGBOX:
if( ( pMsg->message == WM_KEYDOWN ) && ( pMsg->wParam == VK_F1 ) )
{
PostMessage( GetRealParent( pMsg->hwnd ), WM_Help, (WPARAM)pMsg->hwnd, 0 );
return 1;
}
break;
}
return 0;
}
#endif /* OLDSTUFF */
/* GetMsgProc
*
* This is the callback routine which hooks F1 keypresses.
*
* Any such message will be repackaged as a WM_Help message and sent to the
* top window, which may be the frame window or a dialog box.
*
* See the Win32 API programming reference for a description of how this
* routine works.
*
* Changed from previous MessageProc so that F1 in the Default Printer combo
* will also be hooked.
*
* Andrew Bell (andrewbe) - 4 February 1993
*/
LRESULT CALLBACK GetMsgProc( int Code, WPARAM wParam, LPARAM lParam )
{
PMSG pMsg = (PMSG)lParam;
if( Code < 0 )
return CallNextHookEx( hhookGetMsg, Code, wParam, lParam );
if( ( pMsg->message == WM_KEYDOWN ) && ( pMsg->wParam == VK_F1 ) )
{
PostMessage( GetRealParent( pMsg->hwnd ), WM_Help,
(LPARAM)pMsg->hwnd, WinHelpMenuID );
}
return 0;
}
/* GetCurrentMenuItemID
*
* Returns the ID of the currently selected item in a menu.
*
* There's no easy way to do this, unfortunately, so we have to enumerate
* all the menu items until we find one with the MF_HILITE flag set.
*
* The routine scans only one level of menus, so you'll have to modify
* it if you want to use it for multiple-level menus.
*
* Parameter:
*
* hMenu - The handle of the menu to be searched.
*
* Returns:
*
* The ID of the highlighted menu item,
* or 0 if no highlighted item was found or if an error occurred.
*
* Andrew Bell (andrewbe) - 2 September 1992
*/
UINT GetCurrentMenuItemID( HMENU hMenu )
{
UINT MenuItemID = 0;
int MenuItemCount, iMain;
int SubMenuItemCount, iSub;
HMENU hSubMenu;
UINT MenuState;
/* Find out how many top-level pull-downs there are:
*/
MenuItemCount = GetMenuItemCount( hMenu );
/* If there was an error, just set the count to zero,
* and it will fall through:
*/
if( MenuItemCount == -1 )
MenuItemCount = 0;
iMain = 0;
/* Now go through each pull-down until we find a selected item:
*/
while( ( MenuItemID == 0 ) && ( iMain < MenuItemCount ) )
{
hSubMenu = GetSubMenu( hMenu, iMain );
SubMenuItemCount = GetMenuItemCount( hSubMenu );
if( SubMenuItemCount == -1 )
SubMenuItemCount = 0;
iSub = 0;
while( ( MenuItemID == 0 ) && ( iSub < SubMenuItemCount ) )
{
MenuState = GetMenuState( hSubMenu, iSub, MF_BYPOSITION );
if( MenuState != (UINT)-1 )
{
if( (BYTE)MenuState & MF_HILITE )
{
MenuItemID = GetMenuItemID( hSubMenu, iSub );
/* Hack for MDI windows listed under "Window".
* Return the generic help ID:
*/
if( ( iMain == POPUP_WINDOW )
&&( ( MenuItemID < IDM_CASCADE )
|| ( MenuItemID > IDM_REFRESH ) ) )
MenuItemID = ID_HELP_MDIWINDOW;
}
}
iSub++;
}
iMain++;
}
return MenuItemID;
}
VOID
KillMDIWinInfo( PMDIWIN_INFO pInfo)
{
pInfo->Alive = FALSE;
}
/* Checks to see whether there is already an instance of Print Manager running.
* If so, it brings it to the foreground and returns TRUE.
*
* Body of the function borrowed from WinFile.
*/
BOOL PreviousPrintManagerInstanceFound( )
{
HWND hwndPrev;
HWND hwnd;
hwndPrev = FindWindow (szPrintManagerClass, NULL);
if (hwndPrev != NULL)
{
hwnd = GetLastActivePopup(hwndPrev);
if (IsIconic(hwndPrev))
ShowWindow (hwndPrev, SW_RESTORE);
SetForegroundWindow (hwnd);
return TRUE;
}
return FALSE;
}
#define WAIT_OBJECT_MESSAGE_WRITTEN 0
#define WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE 1
#define WAIT_OBJECT_COUNT 2
int
#if !defined(_MIPS_) && !defined(_ALPHA_) && !defined(_PPC_)
_cdecl
#endif
main(
unsigned argc,
CHAR **argv
)
{
MSG msg;
HANDLE hInstance = NULL;
HANDLE hAccel;
SAVEDWINDOWPOS swp;
PRINTMAN_DATA PrintManData;
TCHAR strPrintManager[40];
DWORD EventId;
BOOL Quit = FALSE;
REGISTRY_ENTRY RegistrySaveSettings = { REG_DWORD, sizeof(DWORD) };
TCHAR SaveSettings[40];
HANDLE hWaitObjects[WAIT_OBJECT_COUNT];
HKEY hWindowsKey;
LCID lcid;
TCHAR szSystemDir[MAX_PATH];
STARTUPINFO si;
WCHAR Buffer[128];
#ifdef HEAPCHECK
HeapCheckInit();
#endif
lcid = GetThreadLocale();
bJapan = (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE);
if( PreviousPrintManagerInstanceFound( ) )
return FALSE;
ThousandSeparator = TEXT(',');
if (GetLocaleInfoW (lcid, LOCALE_STHOUSAND, Buffer, 128)) {
ThousandSeparator = Buffer[0];
}
hInstance = GetModuleHandle (NULL);
if (!InitApplication(hInstance, &hAccel))
return(FALSE);
// Might as well open the registry key now.
RegCreateKeyEx(HKEY_CURRENT_USER, szRegistryPrinter, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &hPrinterKey, NULL);
// Create the main Print Manager frame window
LoadString(hInstance, IDS_PRINTMANAGER, strPrintManager,
sizeof(strPrintManager) / sizeof(*strPrintManager));
GetSavedWindowPos( NULL, strPrintManager, &swp, 0, NULL );
bToolBar = !( swp.options & OPTION_NOTOOLBAR );
bStatusBar = !( swp.options & OPTION_NOSTATUSBAR );
bSaveSettings = TRUE;
LoadString(hInstance, IDS_SAVE_SETTINGS, SaveSettings,
sizeof SaveSettings / sizeof *SaveSettings);
ReadRegistryData( NULL, SaveSettings,
(LPBYTE)&bSaveSettings,
&RegistrySaveSettings );
hhookGetMsg = SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc, NULL,
GetCurrentThreadId( ) );
WM_Help = RegisterWindowMessage( TEXT("Print Manager Help Message") );
CreateWindow(szPrintManagerClass, strPrintManager,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
swp.left, swp.top, swp.width, swp.height,
NULL, NULL, hInstance, &PrintManData);
if (GetSystemDirectory(szSystemDir,
sizeof(szSystemDir)/sizeof(szSystemDir[0]))) {
SetCurrentDirectory(szSystemDir);
}
// Let the program manager over ride the saved window position
GetStartupInfo(&si);
if (si.wShowWindow == SW_MINIMIZE || si.wShowWindow == SW_SHOWMINNOACTIVE) {
ShowWindow(hwndFrame, si.wShowWindow);
} else {
ShowWindow(hwndFrame, swp.sw);
}
UpdateWindow(hwndFrame);
hWaitObjects[WAIT_OBJECT_MESSAGE_WRITTEN] = ThreadMessageWritten;
hWaitObjects[WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE] =
CreateEvent( NULL,
EVENT_RESET_AUTOMATIC,
EVENT_INITIAL_STATE_NOT_SIGNALED,
NULL );
if( RegOpenKey( HKEY_CURRENT_USER,
TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"),
&hWindowsKey ) != NO_ERROR )
{
DBGMSG( DBG_WARNING, ( "RegOpenKey failed\n" ) );
}
/* Ask for notification of changes to last write time of registry key.
* Empirically found to work. I'm buggered if I know why this works,
* whereas REG_NOTIFY_CHANGE_ATTRIBUTES and REG_NOTIFY_CHANGE_NAME
* don't seem to have any effect.
*/
if( RegNotifyChangeKeyValue( hWindowsKey, FALSE, REG_NOTIFY_CHANGE_LAST_SET,
hWaitObjects[WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE],
TRUE ) != NO_ERROR )
{
DBGMSG( DBG_WARNING, ( "RegNotifyChangeKeyValue failed\n" ) );
}
while( ( Quit == FALSE )
&&( ( EventId = MsgWaitForMultipleObjects( WAIT_OBJECT_COUNT,
hWaitObjects,
FALSE,
INFINITE,
QS_ALLEVENTS | QS_SENDMESSAGE
) ) != (DWORD)-1 ) )
{
if( EventId == WAIT_OBJECT_0 + WAIT_OBJECT_MESSAGE_WRITTEN )
{
DBGMSG( DBG_TRACE, ( "Dispatching message %08x\n", ThreadMessage.message ) );
DISPATCH_THREAD_MESSAGE( &ThreadMessage );
}
else if( EventId == ( WAIT_OBJECT_0 + WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE ) )
{
if( !ExpectingNotifyChangeKeyValue )
{
DBGMSG( DBG_TRACE, ( "NotifyChangeKeyValue received\n" ) );
PostMessage( hwndFrame, WM_REG_NOTIFY_CHANGE_KEY_VALUE, (WPARAM)hWindowsKey, 0 );
}
else
{
DBGMSG( DBG_TRACE, ( "NotifyChangeKeyValue received (expected)\n" ) );
ExpectingNotifyChangeKeyValue = FALSE;
}
RegNotifyChangeKeyValue( hWindowsKey, FALSE, REG_NOTIFY_CHANGE_LAST_SET,
hWaitObjects[WAIT_OBJECT_NOTIFY_CHANGE_KEY_VALUE],
TRUE );
}
else
{
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
//
// since we use RETURN as an accelerator we have to manually
// restore ourselves when we see VK_RETURN and we are minimized
//
if (msg.message == WM_SYSKEYDOWN &&
msg.wParam == VK_RETURN &&
IsIconic(hwndFrame))
{
ShowWindow(hwndFrame, SW_NORMAL);
}
else if( !TranslateMDISysAccel( hwndClient, &msg ) &&
!TranslateAccelerator( hwndFrame, hAccel, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
if( msg.message == WM_QUIT )
{
Quit = TRUE;
break;
}
}
}
}
CloseHandle( ThreadMessageWritten );
CloseHandle( ThreadMessageRead );
RegCloseKey(hWindowsKey);
RegCloseKey(hPrinterKey);
#ifdef HEAPCHECK
HeapCheckDump(0);
HeapCheckDestroy();
#endif
return msg.wParam;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
}