2 * Virtual Printers Folder
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2005 Huw Davies
7 * Copyright 2009 Andrew Hill
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 WINE_DEFAULT_DEBUG_CHANNEL (shell
);
30 /***********************************************************************
31 * Printers_IExtractIconW implementation
33 class CPrintersExtractIconW
:
34 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
41 CPrintersExtractIconW();
42 ~CPrintersExtractIconW();
43 HRESULT WINAPI
Initialize(LPCITEMIDLIST pidl
);
46 virtual HRESULT STDMETHODCALLTYPE
GetIconLocation(UINT uFlags
, LPWSTR szIconFile
, UINT cchMax
, int *piIndex
, UINT
*pwFlags
);
47 virtual HRESULT STDMETHODCALLTYPE
Extract(LPCWSTR pszFile
, UINT nIconIndex
, HICON
*phiconLarge
, HICON
*phiconSmall
, UINT nIconSize
);
50 virtual HRESULT STDMETHODCALLTYPE
GetIconLocation(UINT uFlags
, LPSTR szIconFile
, UINT cchMax
, int *piIndex
, UINT
*pwFlags
);
51 virtual HRESULT STDMETHODCALLTYPE
Extract(LPCSTR pszFile
, UINT nIconIndex
, HICON
*phiconLarge
, HICON
*phiconSmall
, UINT nIconSize
);
53 BEGIN_COM_MAP(CPrintersExtractIconW
)
54 COM_INTERFACE_ENTRY_IID(IID_IExtractIconW
, IExtractIconW
)
55 COM_INTERFACE_ENTRY_IID(IID_IExtractIconA
, IExtractIconA
)
59 static shvheader PrinterSFHeader
[] = {
60 {IDS_SHV_COLUMN8
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
61 {IDS_SHV_COLUMN_DOCUMENTS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
62 {IDS_SHV_COLUMN_STATUS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
63 {IDS_SHV_COLUMN_COMMENTS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
64 {IDS_SHV_COLUMN_LOCATION
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
65 {IDS_SHV_COLUMN_MODEL
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15}
69 #define COLUMN_DOCUMENTS 1
70 #define COLUMN_STATUS 2
71 #define COLUMN_COMMENTS 3
72 #define COLUMN_LOCATION 4
73 #define COLUMN_MODEL 5
76 #define PrinterSHELLVIEWCOLUMNS (6)
78 CPrintersExtractIconW::CPrintersExtractIconW()
83 CPrintersExtractIconW::~CPrintersExtractIconW()
85 TRACE(" destroying IExtractIcon(%p)\n", this);
89 HRESULT WINAPI
CPrintersExtractIconW::Initialize(LPCITEMIDLIST pidl
)
97 /**************************************************************************
98 * CPrintersExtractIconW::GetIconLocation
100 * mapping filetype to icon
102 HRESULT WINAPI
CPrintersExtractIconW::GetIconLocation(UINT uFlags
, /* GIL_ flags */
106 UINT
*pwFlags
) /* returned GIL_ flags */
108 TRACE("(%p) (flags=%u %p %u %p %p)\n", this, uFlags
, szIconFile
, cchMax
, piIndex
, pwFlags
);
113 lstrcpynW(szIconFile
, swShell32Name
, cchMax
);
114 *piIndex
= -IDI_SHELL_PRINTERS_FOLDER
; /* FIXME: other icons for default, network, print to file */
116 TRACE("-- %s %x\n", debugstr_w(szIconFile
), *piIndex
);
120 /**************************************************************************
121 * CPrintersExtractIconW::Extract
123 HRESULT WINAPI
CPrintersExtractIconW::Extract(LPCWSTR pszFile
,
124 UINT nIconIndex
, HICON
*phiconLarge
,
125 HICON
*phiconSmall
, UINT nIconSize
)
129 FIXME("(%p) (file=%p index=%d %p %p size=%x) semi-stub\n", this, debugstr_w(pszFile
),
130 (signed)nIconIndex
, phiconLarge
, phiconSmall
, nIconSize
);
132 index
= SIC_GetIconIndex(pszFile
, nIconIndex
, 0);
135 *phiconLarge
= ImageList_GetIcon(ShellBigIconList
, index
, ILD_TRANSPARENT
);
138 *phiconSmall
= ImageList_GetIcon(ShellSmallIconList
, index
, ILD_TRANSPARENT
);
143 /**************************************************************************
144 * CPrintersExtractIconW::GetIconLocation
146 HRESULT WINAPI
CPrintersExtractIconW::GetIconLocation(UINT uFlags
,
153 LPWSTR lpwstrFile
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, cchMax
* sizeof(WCHAR
));
155 TRACE("(%p) (flags=%u %p %u %p %p)\n", this, uFlags
, szIconFile
, cchMax
, piIndex
, pwFlags
);
157 ret
= GetIconLocation(uFlags
, lpwstrFile
, cchMax
, piIndex
, pwFlags
);
158 WideCharToMultiByte(CP_ACP
, 0, lpwstrFile
, -1, szIconFile
, cchMax
, NULL
, NULL
);
159 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
161 TRACE("-- %s %x\n", szIconFile
, *piIndex
);
164 /**************************************************************************
165 * CPrintersExtractIconW::Extract
167 HRESULT WINAPI
CPrintersExtractIconW::Extract(LPCSTR pszFile
,
168 UINT nIconIndex
, HICON
*phiconLarge
,
169 HICON
*phiconSmall
, UINT nIconSize
)
172 INT len
= MultiByteToWideChar(CP_ACP
, 0, pszFile
, -1, NULL
, 0);
173 LPWSTR lpwstrFile
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
175 TRACE("(%p) (file=%p index=%u %p %p size=%u)\n", this, pszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIconSize
);
177 MultiByteToWideChar(CP_ACP
, 0, pszFile
, -1, lpwstrFile
, len
);
178 ret
= Extract(lpwstrFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIconSize
);
179 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
183 /**************************************************************************
184 * IExtractIcon_Constructor
186 static HRESULT WINAPI
IEI_Printers_Constructor(LPCITEMIDLIST pidl
, REFIID riid
, IUnknown
**ppv
)
188 return ShellObjectCreatorInit
<CPrintersExtractIconW
>(pidl
, riid
, ppv
);
191 /***********************************************************************
192 * Printers folder implementation
195 class CPrintersEnum
: public IEnumIDListImpl
200 HRESULT WINAPI
Initialize(HWND hwndOwner
, DWORD dwFlags
);
201 BOOL
CreatePrintersEnumList(DWORD dwFlags
);
203 BEGIN_COM_MAP(CPrintersEnum
)
204 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
208 CPrintersEnum::CPrintersEnum()
212 CPrintersEnum::~CPrintersEnum()
216 HRESULT WINAPI
CPrintersEnum::Initialize(HWND hwndOwner
, DWORD dwFlags
)
218 if (CreatePrintersEnumList(dwFlags
) == FALSE
)
223 static LPITEMIDLIST
_ILCreatePrinterItem(PRINTER_INFO_4W
*pi
)
227 PIDLPrinterStruct
* p
;
228 int size0
= (char*)&tmp
.u
.cprinter
.szName
- (char*)&tmp
.u
.cprinter
;
232 tmp
.u
.cprinter
.dummy
= 0xFF;
233 if (pi
->pPrinterName
)
234 tmp
.u
.cprinter
.offsServer
= wcslen(pi
->pPrinterName
) + 1;
236 tmp
.u
.cprinter
.offsServer
= 1;
238 size
+= tmp
.u
.cprinter
.offsServer
* sizeof(WCHAR
);
240 size
+= (wcslen(pi
->pServerName
) + 1) * sizeof(WCHAR
);
242 size
+= sizeof(WCHAR
);
244 pidl
= (LPITEMIDLIST
)SHAlloc(size
+ 4);
248 pidl
->mkid
.cb
= size
+ 2;
249 memcpy(pidl
->mkid
.abID
, &tmp
, 2 + size0
);
251 p
= &((PIDLDATA
*)pidl
->mkid
.abID
)->u
.cprinter
;
253 p
->Attributes
= pi
->Attributes
;
254 if (pi
->pPrinterName
)
255 wcscpy(p
->szName
, pi
->pPrinterName
);
257 p
->szName
[0] = L
'\0';
260 wcscpy(p
->szName
+ p
->offsServer
, pi
->pServerName
);
262 p
->szName
[p
->offsServer
] = L
'\0';
264 *(WORD
*)((char*)pidl
+ (size
+ 2)) = 0;
268 /**************************************************************************
269 * CPrintersEnum::CreatePrintersEnumList()
271 BOOL
CPrintersEnum::CreatePrintersEnumList(DWORD dwFlags
)
275 TRACE("(%p)->(flags=0x%08lx) \n", this, dwFlags
);
277 /* enumerate the folders */
278 if (dwFlags
& SHCONTF_NONFOLDERS
)
280 DWORD needed
= 0, num
= 0, i
;
283 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 4, NULL
, 0, &needed
, &num
);
287 pi
= (PRINTER_INFO_4W
*)HeapAlloc(GetProcessHeap(), 0, needed
);
288 if(!EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 4, (LPBYTE
)pi
, needed
, &needed
, &num
)) {
289 HeapFree(GetProcessHeap(), 0, pi
);
293 for(i
= 0; i
< num
; i
++) {
294 LPITEMIDLIST pidl
= _ILCreatePrinterItem(&pi
[i
]);
297 if (!AddToEnumList(pidl
))
301 HeapFree(GetProcessHeap(), 0, pi
);
306 CPrinterFolder::CPrinterFolder()
313 CPrinterFolder::~CPrinterFolder()
315 TRACE("-- destroying IShellFolder(%p)\n", this);
320 HRESULT WINAPI
CPrinterFolder::FinalConstruct()
322 pidlRoot
= _ILCreatePrinters(); /* my qualified pidl */
323 if (pidlRoot
== NULL
)
324 return E_OUTOFMEMORY
;
328 /**************************************************************************
329 * CPrinterFolder::ParseDisplayName
331 * This is E_NOTIMPL in Windows too.
333 HRESULT WINAPI
CPrinterFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
334 DWORD
*pchEaten
, PIDLIST_RELATIVE
*ppidl
, DWORD
*pdwAttributes
)
336 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
337 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
338 pchEaten
, ppidl
, pdwAttributes
);
347 static PIDLPrinterStruct
* _ILGetPrinterStruct(LPCITEMIDLIST pidl
)
349 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
351 if (pdata
&& pdata
->type
== 0x00)
352 return (PIDLPrinterStruct
*) & (pdata
->u
.cfont
);
357 /**************************************************************************
358 * CPrinterFolder::EnumObjects
360 HRESULT WINAPI
CPrinterFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
* ppEnumIDList
)
362 return ShellObjectCreatorInit
<CPrintersEnum
>(hwndOwner
, dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
365 /**************************************************************************
366 * CPrinterFolder::BindToObject
368 HRESULT WINAPI
CPrinterFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
* ppvOut
)
370 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
371 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
373 return SHELL32_BindToChild(pidlRoot
, NULL
, pidl
, riid
, ppvOut
);
376 /**************************************************************************
377 * ISF_Printers_fnBindToStorage
379 HRESULT WINAPI
CPrinterFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
* ppvOut
)
381 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
382 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
388 /**************************************************************************
389 * CPrinterFolder::CompareIDs
391 HRESULT WINAPI
CPrinterFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
395 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam
, pidl1
, pidl2
);
396 nReturn
= SHELL32_CompareIDs (this, lParam
, pidl1
, pidl2
);
397 TRACE ("-- %i\n", nReturn
);
401 /**************************************************************************
402 * CPrinterFolder::CreateViewObject
404 HRESULT WINAPI
CPrinterFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
406 CComPtr
<IShellView
> pShellView
;
407 HRESULT hr
= E_INVALIDARG
;
409 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
410 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
417 if (IsEqualIID(riid
, IID_IDropTarget
))
419 WARN("IDropTarget not implemented\n");
422 else if(IsEqualIID(riid
, IID_IContextMenu
))
424 WARN("IContextMenu not implemented\n");
427 else if(IsEqualIID(riid
, IID_IShellView
))
429 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
432 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
433 pShellView
->Release();
436 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
440 /**************************************************************************
441 * CPrinterFolder::GetAttributesOf
443 HRESULT WINAPI
CPrinterFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
*rgfInOut
)
445 static const DWORD dwPrintersAttributes
=
446 SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_CANRENAME
| SFGAO_CANDELETE
;
449 FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
450 this, cidl
, apidl
, *rgfInOut
);
452 *rgfInOut
&= dwPrintersAttributes
;
454 *rgfInOut
&= ~SFGAO_VALIDATE
;
456 TRACE ("-- result=0x%08x\n", *rgfInOut
);
460 /**************************************************************************
461 * CPrinterFolder::GetUIObjectOf
464 * HWND hwndOwner, //[in ] Parent window for any output
465 * UINT cidl, //[in ] array size
466 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
467 * REFIID riid, //[in ] Requested Interface
468 * UINT* prgfInOut, //[ ] reserved
469 * LPVOID* ppvObject) //[out] Resulting Interface
472 HRESULT WINAPI
CPrinterFolder::GetUIObjectOf(HWND hwndOwner
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
473 REFIID riid
, UINT
* prgfInOut
, LPVOID
* ppvOut
)
475 IUnknown
*pObj
= NULL
;
476 HRESULT hr
= E_INVALIDARG
;
478 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
479 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
486 if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID(riid
, IID_IExtractIconW
)) && cidl
== 1)
487 hr
= IEI_Printers_Constructor(apidl
[0], riid
, &pObj
);
491 if (SUCCEEDED(hr
) && !pObj
)
495 TRACE ("(%p)->hr=0x%08lx\n", this, hr
);
499 /**************************************************************************
500 * CPrinterFolder::GetDisplayNameOf
503 HRESULT WINAPI
CPrinterFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
506 PIDLPrinterStruct
* p
;
508 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl
, dwFlags
, strRet
);
519 pszName
= (LPWSTR
)CoTaskMemAlloc(MAX_PATH
* sizeof(WCHAR
));
521 return E_OUTOFMEMORY
;
523 if (LoadStringW(shell32_hInstance
, IDS_PRINTERS
, pszName
, MAX_PATH
))
525 pszName
[MAX_PATH
-1] = L
'\0';
526 strRet
->uType
= STRRET_WSTR
;
527 strRet
->pOleStr
= pszName
;
530 CoTaskMemFree(pszName
);
534 p
= _ILGetPrinterStruct(pidl
);
537 WARN("no printer struct\n");
540 strRet
->pOleStr
= (LPWSTR
)SHAlloc(p
->offsServer
* sizeof(WCHAR
));
541 if (!strRet
->pOleStr
)
542 return E_OUTOFMEMORY
;
544 memcpy((LPVOID
)strRet
->pOleStr
, (LPVOID
)p
->szName
, p
->offsServer
* sizeof(WCHAR
));
545 TRACE("ret %s\n", debugstr_w(strRet
->pOleStr
));
550 /**************************************************************************
551 * CPrinterFolder::SetNameOf
552 * Changes the name of a file object or subfolder, possibly changing its item
553 * identifier in the process.
556 * HWND hwndOwner, //[in ] Owner window for output
557 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
558 * LPCOLESTR lpszName, //[in ] the items new display name
559 * DWORD dwFlags, //[in ] SHGNO formatting flags
560 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
562 HRESULT WINAPI
CPrinterFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
, /* simple pidl */
563 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
565 FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner
, pidl
,
566 debugstr_w (lpName
), dwFlags
, pPidlOut
);
571 HRESULT WINAPI
CPrinterFolder::GetDefaultSearchGUID(GUID
*pguid
)
573 FIXME("(%p)\n", this);
577 HRESULT WINAPI
CPrinterFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
579 FIXME("(%p)\n", this);
583 HRESULT WINAPI
CPrinterFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
593 HRESULT WINAPI
CPrinterFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
595 if (!pcsFlags
|| iColumn
>= PrinterSHELLVIEWCOLUMNS
)
597 *pcsFlags
= PrinterSFHeader
[iColumn
].pcsFlags
;
602 HRESULT WINAPI
CPrinterFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
604 FIXME("(%p): stub\n", this);
609 HRESULT WINAPI
CPrinterFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
611 WCHAR buffer
[MAX_PATH
] = {0};
614 TRACE("(%p)->(%p %i %p): stub\n", this, pidl
, iColumn
, psd
);
616 if (iColumn
>= PrinterSHELLVIEWCOLUMNS
)
619 psd
->fmt
= PrinterSFHeader
[iColumn
].fmt
;
620 psd
->cxChar
= PrinterSFHeader
[iColumn
].cxChar
;
623 psd
->str
.uType
= STRRET_WSTR
;
624 if (LoadStringW(shell32_hInstance
, PrinterSFHeader
[iColumn
].colnameid
, buffer
, MAX_PATH
))
625 hr
= SHStrDupW(buffer
, &psd
->str
.pOleStr
);
630 if (iColumn
== COLUMN_NAME
)
632 psd
->str
.uType
= STRRET_WSTR
;
633 return GetDisplayNameOf(pidl
, SHGDN_NORMAL
, &psd
->str
);
636 psd
->str
.uType
= STRRET_CSTR
;
637 psd
->str
.cStr
[0] = '\0';
642 HRESULT WINAPI
CPrinterFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
644 FIXME ("(%p): stub\n", this);
648 /************************************************************************
649 * CPrinterFolder::GetClassID
651 HRESULT WINAPI
CPrinterFolder::GetClassID(CLSID
*lpClassId
)
653 TRACE ("(%p)\n", this);
655 *lpClassId
= CLSID_Printers
;
660 /************************************************************************
661 * CPrinterFolder::Initialize
663 HRESULT WINAPI
CPrinterFolder::Initialize(LPCITEMIDLIST pidl
)
666 SHFree((LPVOID
)pidlRoot
);
668 pidlRoot
= ILClone(pidl
);
672 /**************************************************************************
673 * CPrinterFolder::GetCurFolder
675 HRESULT WINAPI
CPrinterFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
677 TRACE ("(%p)->(%p)\n", this, pidl
);
679 *pidl
= ILClone (pidlRoot
);