|
|
// this is really private data to CPrinterFolder
typedef struct { USHORT cb; USHORT uFlags;
#define PRINTER_MAGIC 0xBEBADB00
DWORD dwMagic; DWORD dwType; WCHAR cName[MAXNAMELENBUFFER]; USHORT uTerm; } IDPRINTER; typedef UNALIGNED IDPRINTER *LPIDPRINTER; typedef const UNALIGNED IDPRINTER *LPCIDPRINTER;
// W95 IDPrinter structure
typedef struct { USHORT cb; char cName[32]; // Win9x limitation
USHORT uTerm; } W95IDPRINTER; typedef const UNALIGNED W95IDPRINTER *LPW95IDPRINTER;
//
// Constants
//
const UINT kDNSMax = INTERNET_MAX_HOST_NAME_LENGTH; const UINT kServerBufMax = kDNSMax + 2 + 1;
//
// Max printer name should really be MAX_PATH, but if you create
// a max path printer and connect to it remotely, win32spl prepends
// "\\server\" to it, causing it to exceed max path. The new UI
// therefore makes the max path MAX_PATH-kServerLenMax, but we still
// allow the old case to work.
//
const UINT kPrinterBufMax = MAX_PATH + kServerBufMax + 1;
class CPrinterFolder : public IRemoteComputer, public IPrinterFolder, public IFolderNotify, public IShellFolder2, public IPersistFolder2, public IContextMenuCB, public IShellIconOverlay { friend class CPrintersEnum; friend class CPrinterFolderViewCB; public: CPrinterFolder();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// IShellFolder
STDMETHODIMP BindToObject(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void** ppvOut); STDMETHODIMP BindToStorage(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void** ppvOut); STDMETHODIMP CompareIDs(LPARAM iCol, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); STDMETHODIMP CreateViewObject(HWND hwnd, REFIID riid, void** ppvOut); STDMETHODIMP EnumObjects(HWND hwndOwner, DWORD grfFlags, IEnumIDList** ppenum); STDMETHODIMP GetAttributesOf(UINT cidl, LPCITEMIDLIST* apidl, ULONG* prgfInOut); STDMETHODIMP GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName); STDMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST* apidl, REFIID riid, UINT* prgfInOut, void** ppvOut); STDMETHODIMP ParseDisplayName(HWND hwnd, LPBC pbc, LPOLESTR lpszDisplayName, ULONG* pchEaten, LPITEMIDLIST* ppidl, ULONG* pdwAttributes); STDMETHODIMP SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl, LPCOLESTR lpszName, DWORD dwReserved, LPITEMIDLIST* ppidlOut);
// IShellFolder2
STDMETHODIMP EnumSearches(IEnumExtraSearch **ppenum); STDMETHODIMP GetDefaultColumn(DWORD dwRes, ULONG* pSort, ULONG* pDisplay); STDMETHODIMP GetDefaultColumnState(UINT iColumn, DWORD* pdwState); STDMETHODIMP GetDefaultSearchGUID(LPGUID pGuid); STDMETHODIMP GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID* pscid, VARIANT* pv); STDMETHODIMP GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS* pDetails); STDMETHODIMP MapColumnToSCID(UINT iCol, SHCOLUMNID* pscid);
// IPersistFolder2
STDMETHODIMP GetCurFolder(LPITEMIDLIST *ppidl); STDMETHODIMP Initialize(LPCITEMIDLIST pidl); STDMETHODIMP GetClassID(LPCLSID lpClassID);
// IShellIconOverlay
STDMETHODIMP GetOverlayIndex(LPCITEMIDLIST pidl, int* pIndex); STDMETHODIMP GetOverlayIconIndex(LPCITEMIDLIST pidl, int *pIndex);
// IRemoteComputer
STDMETHODIMP Initialize(const WCHAR *pszMachine, BOOL bEnumerating);
// IPrinterFolder
STDMETHODIMP_(BOOL) IsPrinter(LPCITEMIDLIST pidl);
// IFolderNotify
STDMETHODIMP_(BOOL) ProcessNotify(FOLDER_NOTIFY_TYPE NotifyType, LPCWSTR pszName, LPCWSTR pszNewName);
// IContextMenuCB
STDMETHODIMP CallBack(IShellFolder *psf, HWND hwnd,IDataObject *pdo, UINT uMsg, WPARAM wParam, LPARAM lParam);
// DUI webview impl.
HRESULT GetWebViewLayout(IUnknown *pv, UINT uViewMode, SFVM_WEBVIEW_LAYOUT_DATA* pData); HRESULT GetWebViewContent(IUnknown *pv, SFVM_WEBVIEW_CONTENT_DATA* pData); HRESULT GetWebViewTasks(IUnknown *pv, SFVM_WEBVIEW_TASKSECTION_DATA* pTasks);
// mask passsed to _IsContextMenuVerbEnabled to determine the selection type in which
// this command is applicable
enum { // nothing is selected
SEL_NONE = 0x0000, // nothing is selected
// single selection types
SEL_SINGLE_ADDPRN = 0x0001, // the add printer wizard object is selected
SEL_SINGLE_PRINTER = 0x0002, // 1 printer is selected
SEL_SINGLE_LINK = 0x0004, // 1 link is selected
// any single selection type
SEL_SINGLE_ANY = SEL_SINGLE_ADDPRN | SEL_SINGLE_PRINTER | SEL_SINGLE_LINK,
// multi selection types
SEL_MULTI_PRINTER = 0x0010, // 2+ printers are selected
SEL_MULTI_LINK = 0x0020, // 2+ links are selected
SEL_MULTI_MIXED = 0x0040, // 2+ objects of any type are selected
// any link in the selection
SEL_LINK_ANY = SEL_SINGLE_LINK | SEL_MULTI_LINK | SEL_MULTI_MIXED,
// any printer in the selection
SEL_PRINTER_ANY = SEL_SINGLE_ADDPRN | SEL_SINGLE_ADDPRN | SEL_MULTI_PRINTER | SEL_MULTI_MIXED, // any multi selection type
SEL_MULTI_ANY = SEL_MULTI_PRINTER | SEL_MULTI_LINK | SEL_MULTI_MIXED,
// any selection type
SEL_ANY = SEL_SINGLE_ANY | SEL_MULTI_ANY, };
// split the selection into its parts (printers and links) and determine the
// selection type (see the enum above)
HRESULT SplitSelection(IDataObject *pdo, UINT *puSelType, IDataObject **ppdoPrinters, IDataObject **ppdoLinks);
// webview verbs
enum WV_VERB { // standard verbs
WVIDM_DELETE, WVIDM_RENAME, WVIDM_PROPERTIES,
// common verbs
WVIDM_ADDPRINTERWIZARD, WVIDM_SERVERPROPERTIES, WVIDM_SETUPFAXING, WVIDM_CREATELOCALFAX, WVIDM_SENDFAXWIZARD,
// special common verbs
WVIDM_TROUBLESHOOTER, WVIDM_GOTOSUPPORT,
// printer verbs
WVIDM_OPENPRN, WVIDM_NETPRN_INSTALL, WVIDM_SETDEFAULTPRN, WVIDM_DOCUMENTDEFAULTS, WVIDM_PAUSEPRN, WVIDM_RESUMEPRN, WVIDM_PURGEPRN, WVIDM_SHARING, WVIDM_WORKOFFLINE, WVIDM_WORKONLINE,
// special commands
WVIDM_VENDORURL, WVIDM_PRINTERURL,
WVIDM_COUNT, };
// webview support - core APIs
HRESULT _WebviewVerbIsEnabled(WV_VERB eVerbID, UINT uSelMask, BOOL *pbEnabled); HRESULT _WebviewVerbInvoke(WV_VERB eVerbID, IUnknown* pv, IShellItemArray *psiItemArray); HRESULT _WebviewCheckToUpdateDataObjectCache(IDataObject *pdo);
private: virtual ~CPrinterFolder();
// data access
LPCTSTR GetServer() { return _pszServer; } HANDLE GetFolder() { CheckToRegisterNotify(); return _hFolder; } BOOL GetAdminAccess() { CheckToRegisterNotify(); return _bAdminAccess; }
static LPCTSTR GetStatusString(PFOLDER_PRINTER_DATA pData, LPTSTR pBuff, UINT uSize); static INT GetCompareDisplayName(LPCTSTR pName1, LPCTSTR pName2); INT CompareData(LPCIDPRINTER pidp1, LPCIDPRINTER pidp2, LPARAM iCol); static ReduceToLikeKinds(UINT *pcidl, LPCITEMIDLIST **papidl, BOOL fPrintObjects); DWORD SpoolerVersion(); void CheckToRegisterNotify(); void CheckToRefresh(); void RequestRefresh(); HRESULT _GetFullIDList(LPCWSTR pszPrinter, LPITEMIDLIST *ppidl); static HRESULT _Parse(LPCWSTR pszPrinter, LPITEMIDLIST *ppidl, DWORD dwType = 0, USHORT uFlags = 0); static void _FillPidl(LPIDPRINTER pidl, LPCTSTR szName, DWORD dwType = 0, USHORT uFlags = 0); LPCTSTR _BuildPrinterName(LPTSTR pszFullPrinter, LPCIDPRINTER pidp, LPCTSTR pszPrinter); void _MergeMenu(LPQCMINFO pqcm, LPCTSTR pszPrinter); HRESULT _InvokeCommand(HWND hwnd, LPCIDPRINTER pidp, WPARAM wParam, LPARAM lParam, LPBOOL pfChooseNewDefault); HRESULT _InvokeCommandRunAs(HWND hwnd, LPCIDPRINTER pidp, WPARAM wParam, LPARAM lParam, LPBOOL pfChooseNewDefault); BOOL _PurgePrinter(HWND hwnd, LPCTSTR pszFullPrinter, UINT uAction, BOOL bQuietMode); LPTSTR _FindIcon(LPCTSTR pszPrinterName, LPTSTR pszModule, ULONG cbModule, int *piIcon, int *piShortcutIcon); static HRESULT CALLBACK _DFMCallBack(IShellFolder *psf, HWND hwnd, IDataObject *pdo, UINT uMsg, WPARAM wParam, LPARAM lParam); HRESULT _PrinterObjectsCallBack(HWND hwnd, UINT uSelType, IDataObject *pdo, UINT uMsg, WPARAM wParam, LPARAM lParam); static LPTSTR _ItemName(LPCIDPRINTER pidp, LPTSTR pszName, UINT cch); static BOOL _IsAddPrinter(LPCIDPRINTER pidp); HRESULT _UpdateDataObjectCache(); HRESULT _AssocCreate(REFIID riid, void **ppv); HRESULT _OnRefresh(BOOL bPriorRefresh);
LONG _cRef; // ref count
LPITEMIDLIST _pidl; // the PIDL of this folder
LPTSTR _pszServer; // the print server this folder is browsing (NULL means local PF)
DWORD _dwSpoolerVersion; // the spooler version
HANDLE _hFolder; // handle to the printer folder cache (in printui)
BOOL _bAdminAccess; // TRUE if you have admin access to this print server
BOOL _bReqRefresh; // whether we should request a full refresh during the next enum
// our webview get command state cache. we have 35+ commands and unpacking
// the same data object each time we need to verify the state of a command
// can be very expensive! we are going to maintain a cache with each command
// state and update the cache each time the data object gets changed, so
// the get state callbacks will finish very quickly just by consulting
// the cache.
IDataObject *_pdoCache; // current data object
UINT _uSelCurrent; // current selection type
BOOL _aWVCommandStates[WVIDM_COUNT]; // commands state cache
// the folder has to be MT safe
CCSLock _csLock;
// slow data. this members below should refresh every time the selection changes,
// but we should do this in a separate thread since updating them can take a while
enum ESlowWebviewDataType { WV_SLOW_DATA_OEM_SUPPORT_URL, WV_SLOW_DATA_PRINTER_WEB_URL,
WV_SLOW_DATA_COUNT, };
enum { // in miliseconds
WV_SLOW_DATA_CACHE_TIMEOUT = 5000, };
class CSlowWVDataCacheEntry { public: CSlowWVDataCacheEntry(CPrinterFolder *ppf): _ppf(ppf), _bDataPending(TRUE), _nLastTimeUpdated(0) {}
HRESULT Initialize(LPCTSTR pszPrinterName) { HRESULT hr = S_OK; if (pszPrinterName) { _bstrPrinterName = pszPrinterName; hr = _bstrPrinterName ? S_OK : E_OUTOFMEMORY; } else { hr = E_INVALIDARG; } return hr; }
CPrinterFolder *_ppf; BOOL _bDataPending; DWORD _nLastTimeUpdated; CComBSTR _bstrPrinterName; CComBSTR _arrData[WV_SLOW_DATA_COUNT]; };
static DWORD WINAPI _SlowWebviewData_WorkerProc(LPVOID lpParameter); static HRESULT _SlowWVDataRetrieve(LPCTSTR pszPrinterName, BSTR *pbstrSupportUrl, BSTR *pbstrPrinterWebUrl); static int _CompareSlowWVDataCacheEntries(CSlowWVDataCacheEntry *p1, CSlowWVDataCacheEntry *p2, LPARAM lParam);
HRESULT _GetSelectedPrinter(BSTR *pbstrVal); HRESULT _GetSlowWVDataForCurrentPrinter(ESlowWebviewDataType eType, BSTR *pbstrVal); HRESULT _GetSlowWVData(LPCTSTR pszPrinterName, ESlowWebviewDataType eType, BSTR *pbstrVal); HRESULT _UpdateSlowWVDataCacheEntry(CSlowWVDataCacheEntry *pCacheEntry); HRESULT _SlowWVDataUpdateWebviewPane(); HRESULT _SlowWVDataCacheResetUnsafe(); HRESULT _GetCustomSupportURL(BSTR *pbstrVal);
CComBSTR _bstrSelectedPrinter; CDPA<CSlowWVDataCacheEntry> _dpaSlowWVDataCache;
// fax support...
static HRESULT _GetFaxControl(IDispatch **ppDisp); static HRESULT _GetFaxCommand(UINT_PTR *puCmd); static HRESULT _InvokeFaxControlMethod(LPCTSTR pszMethodName); static DWORD WINAPI _ThreadProc_InstallFaxService(LPVOID lpParameter); static DWORD WINAPI _ThreadProc_InstallLocalFaxPrinter(LPVOID lpParameter); };
STDAPI CPrinterFolderDropTarget_CreateInstance(HWND hwnd, IDropTarget **ppdropt);
|