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_LEFT
, 15},
61 {IDS_SHV_COLUMN_DOCUMENTS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
62 {IDS_SHV_COLUMN_STATUS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
63 {IDS_SHV_COLUMN_COMMENTS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
64 {IDS_SHV_COLUMN_LOCATION
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
65 {IDS_SHV_COLUMN_MODEL
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 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
)
128 HIMAGELIST big_icons
, small_icons
;
130 FIXME("(%p) (file=%p index=%d %p %p size=%x) semi-stub\n", this, debugstr_w(pszFile
),
131 (signed)nIconIndex
, phiconLarge
, phiconSmall
, nIconSize
);
133 index
= SIC_GetIconIndex(pszFile
, nIconIndex
, 0);
135 Shell_GetImageLists(&big_icons
, &small_icons
);
138 *phiconLarge
= ImageList_GetIcon(big_icons
, index
, ILD_TRANSPARENT
);
141 *phiconSmall
= ImageList_GetIcon(small_icons
, index
, ILD_TRANSPARENT
);
146 /**************************************************************************
147 * CPrintersExtractIconW::GetIconLocation
149 HRESULT WINAPI
CPrintersExtractIconW::GetIconLocation(UINT uFlags
,
156 LPWSTR lpwstrFile
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, cchMax
* sizeof(WCHAR
));
158 TRACE("(%p) (flags=%u %p %u %p %p)\n", this, uFlags
, szIconFile
, cchMax
, piIndex
, pwFlags
);
160 ret
= GetIconLocation(uFlags
, lpwstrFile
, cchMax
, piIndex
, pwFlags
);
161 WideCharToMultiByte(CP_ACP
, 0, lpwstrFile
, -1, szIconFile
, cchMax
, NULL
, NULL
);
162 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
164 TRACE("-- %s %x\n", szIconFile
, *piIndex
);
167 /**************************************************************************
168 * CPrintersExtractIconW::Extract
170 HRESULT WINAPI
CPrintersExtractIconW::Extract(LPCSTR pszFile
,
171 UINT nIconIndex
, HICON
*phiconLarge
,
172 HICON
*phiconSmall
, UINT nIconSize
)
175 INT len
= MultiByteToWideChar(CP_ACP
, 0, pszFile
, -1, NULL
, 0);
176 LPWSTR lpwstrFile
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
178 TRACE("(%p) (file=%p index=%u %p %p size=%u)\n", this, pszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIconSize
);
180 MultiByteToWideChar(CP_ACP
, 0, pszFile
, -1, lpwstrFile
, len
);
181 ret
= Extract(lpwstrFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIconSize
);
182 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
186 /**************************************************************************
187 * IExtractIcon_Constructor
189 static HRESULT WINAPI
IEI_Printers_Constructor(LPCITEMIDLIST pidl
, REFIID riid
, IUnknown
**ppv
)
191 return ShellObjectCreatorInit
<CPrintersExtractIconW
>(pidl
, riid
, ppv
);
194 /***********************************************************************
195 * Printers folder implementation
198 class CPrintersEnum
: public CEnumIDListBase
203 HRESULT WINAPI
Initialize(HWND hwndOwner
, DWORD dwFlags
);
204 BOOL
CreatePrintersEnumList(DWORD dwFlags
);
206 BEGIN_COM_MAP(CPrintersEnum
)
207 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
211 CPrintersEnum::CPrintersEnum()
215 CPrintersEnum::~CPrintersEnum()
219 HRESULT WINAPI
CPrintersEnum::Initialize(HWND hwndOwner
, DWORD dwFlags
)
221 if (CreatePrintersEnumList(dwFlags
) == FALSE
)
226 static LPITEMIDLIST
_ILCreatePrinterItem(PRINTER_INFO_4W
*pi
)
230 PIDLPrinterStruct
* p
;
231 int size0
= (char*)&tmp
.u
.cprinter
.szName
- (char*)&tmp
.u
.cprinter
;
235 tmp
.u
.cprinter
.dummy
= 0xFF;
236 if (pi
->pPrinterName
)
237 tmp
.u
.cprinter
.offsServer
= wcslen(pi
->pPrinterName
) + 1;
239 tmp
.u
.cprinter
.offsServer
= 1;
241 size
+= tmp
.u
.cprinter
.offsServer
* sizeof(WCHAR
);
243 size
+= (wcslen(pi
->pServerName
) + 1) * sizeof(WCHAR
);
245 size
+= sizeof(WCHAR
);
247 pidl
= (LPITEMIDLIST
)SHAlloc(size
+ 4);
251 pidl
->mkid
.cb
= size
+ 2;
252 memcpy(pidl
->mkid
.abID
, &tmp
, 2 + size0
);
254 p
= &((PIDLDATA
*)pidl
->mkid
.abID
)->u
.cprinter
;
256 p
->Attributes
= pi
->Attributes
;
257 if (pi
->pPrinterName
)
258 wcscpy(p
->szName
, pi
->pPrinterName
);
260 p
->szName
[0] = L
'\0';
263 wcscpy(p
->szName
+ p
->offsServer
, pi
->pServerName
);
265 p
->szName
[p
->offsServer
] = L
'\0';
267 *(WORD
*)((char*)pidl
+ (size
+ 2)) = 0;
271 /**************************************************************************
272 * CPrintersEnum::CreatePrintersEnumList()
274 BOOL
CPrintersEnum::CreatePrintersEnumList(DWORD dwFlags
)
278 TRACE("(%p)->(flags=0x%08lx) \n", this, dwFlags
);
280 /* enumerate the folders */
281 if (dwFlags
& SHCONTF_NONFOLDERS
)
283 DWORD needed
= 0, num
= 0, i
;
286 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 4, NULL
, 0, &needed
, &num
);
290 pi
= (PRINTER_INFO_4W
*)HeapAlloc(GetProcessHeap(), 0, needed
);
291 if(!EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 4, (LPBYTE
)pi
, needed
, &needed
, &num
)) {
292 HeapFree(GetProcessHeap(), 0, pi
);
296 for(i
= 0; i
< num
; i
++) {
297 LPITEMIDLIST pidl
= _ILCreatePrinterItem(&pi
[i
]);
300 if (!AddToEnumList(pidl
))
304 HeapFree(GetProcessHeap(), 0, pi
);
309 CPrinterFolder::CPrinterFolder()
316 CPrinterFolder::~CPrinterFolder()
318 TRACE("-- destroying IShellFolder(%p)\n", this);
323 HRESULT WINAPI
CPrinterFolder::FinalConstruct()
325 pidlRoot
= _ILCreatePrinters(); /* my qualified pidl */
326 if (pidlRoot
== NULL
)
327 return E_OUTOFMEMORY
;
331 /**************************************************************************
332 * CPrinterFolder::ParseDisplayName
334 * This is E_NOTIMPL in Windows too.
336 HRESULT WINAPI
CPrinterFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
337 DWORD
*pchEaten
, PIDLIST_RELATIVE
*ppidl
, DWORD
*pdwAttributes
)
339 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
340 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
341 pchEaten
, ppidl
, pdwAttributes
);
350 static PIDLPrinterStruct
* _ILGetPrinterStruct(LPCITEMIDLIST pidl
)
352 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
354 if (pdata
&& pdata
->type
== 0x00)
355 return (PIDLPrinterStruct
*) & (pdata
->u
.cfont
);
360 /**************************************************************************
361 * CPrinterFolder::EnumObjects
363 HRESULT WINAPI
CPrinterFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
* ppEnumIDList
)
365 return ShellObjectCreatorInit
<CPrintersEnum
>(hwndOwner
, dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
368 /**************************************************************************
369 * CPrinterFolder::BindToObject
371 HRESULT WINAPI
CPrinterFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
* 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
)
393 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
396 /**************************************************************************
397 * CPrinterFolder::CreateViewObject
399 HRESULT WINAPI
CPrinterFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
401 CComPtr
<IShellView
> pShellView
;
402 HRESULT hr
= E_INVALIDARG
;
404 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
405 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
412 if (IsEqualIID(riid
, IID_IDropTarget
))
414 WARN("IDropTarget not implemented\n");
417 else if(IsEqualIID(riid
, IID_IContextMenu
))
419 WARN("IContextMenu not implemented\n");
422 else if(IsEqualIID(riid
, IID_IShellView
))
424 hr
= CDefView_Constructor(this, riid
, ppvOut
);
426 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
430 /**************************************************************************
431 * CPrinterFolder::GetAttributesOf
433 HRESULT WINAPI
CPrinterFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
*rgfInOut
)
435 static const DWORD dwPrintersAttributes
=
436 SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_CANRENAME
| SFGAO_CANDELETE
;
439 FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
440 this, cidl
, apidl
, *rgfInOut
);
442 *rgfInOut
&= dwPrintersAttributes
;
444 *rgfInOut
&= ~SFGAO_VALIDATE
;
446 TRACE ("-- result=0x%08x\n", *rgfInOut
);
450 /**************************************************************************
451 * CPrinterFolder::GetUIObjectOf
454 * HWND hwndOwner, //[in ] Parent window for any output
455 * UINT cidl, //[in ] array size
456 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
457 * REFIID riid, //[in ] Requested Interface
458 * UINT* prgfInOut, //[ ] reserved
459 * LPVOID* ppvObject) //[out] Resulting Interface
462 HRESULT WINAPI
CPrinterFolder::GetUIObjectOf(HWND hwndOwner
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
463 REFIID riid
, UINT
* prgfInOut
, LPVOID
* ppvOut
)
465 IUnknown
*pObj
= NULL
;
466 HRESULT hr
= E_INVALIDARG
;
468 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
469 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
476 if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID(riid
, IID_IExtractIconW
)) && cidl
== 1)
477 hr
= IEI_Printers_Constructor(apidl
[0], riid
, &pObj
);
481 if (SUCCEEDED(hr
) && !pObj
)
485 TRACE ("(%p)->hr=0x%08lx\n", this, hr
);
489 /**************************************************************************
490 * CPrinterFolder::GetDisplayNameOf
493 HRESULT WINAPI
CPrinterFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
496 PIDLPrinterStruct
* p
;
498 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl
, dwFlags
, strRet
);
509 pszName
= (LPWSTR
)CoTaskMemAlloc(MAX_PATH
* sizeof(WCHAR
));
511 return E_OUTOFMEMORY
;
513 if (LoadStringW(shell32_hInstance
, IDS_PRINTERS
, pszName
, MAX_PATH
))
515 pszName
[MAX_PATH
-1] = L
'\0';
516 strRet
->uType
= STRRET_WSTR
;
517 strRet
->pOleStr
= pszName
;
520 CoTaskMemFree(pszName
);
524 p
= _ILGetPrinterStruct(pidl
);
527 WARN("no printer struct\n");
530 strRet
->pOleStr
= (LPWSTR
)SHAlloc(p
->offsServer
* sizeof(WCHAR
));
531 if (!strRet
->pOleStr
)
532 return E_OUTOFMEMORY
;
534 memcpy((LPVOID
)strRet
->pOleStr
, (LPVOID
)p
->szName
, p
->offsServer
* sizeof(WCHAR
));
535 TRACE("ret %s\n", debugstr_w(strRet
->pOleStr
));
540 /**************************************************************************
541 * CPrinterFolder::SetNameOf
542 * Changes the name of a file object or subfolder, possibly changing its item
543 * identifier in the process.
546 * HWND hwndOwner, //[in ] Owner window for output
547 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
548 * LPCOLESTR lpszName, //[in ] the items new display name
549 * DWORD dwFlags, //[in ] SHGNO formatting flags
550 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
552 HRESULT WINAPI
CPrinterFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
, /* simple pidl */
553 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
555 FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner
, pidl
,
556 debugstr_w (lpName
), dwFlags
, pPidlOut
);
561 HRESULT WINAPI
CPrinterFolder::GetDefaultSearchGUID(GUID
*pguid
)
563 FIXME("(%p)\n", this);
567 HRESULT WINAPI
CPrinterFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
569 FIXME("(%p)\n", this);
573 HRESULT WINAPI
CPrinterFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
583 HRESULT WINAPI
CPrinterFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
585 if (!pcsFlags
|| iColumn
>= PrinterSHELLVIEWCOLUMNS
)
587 *pcsFlags
= PrinterSFHeader
[iColumn
].pcsFlags
;
592 HRESULT WINAPI
CPrinterFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
594 FIXME("(%p): stub\n", this);
599 HRESULT WINAPI
CPrinterFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
601 WCHAR buffer
[MAX_PATH
] = {0};
604 TRACE("(%p)->(%p %i %p): stub\n", this, pidl
, iColumn
, psd
);
606 if (iColumn
>= PrinterSHELLVIEWCOLUMNS
)
609 psd
->fmt
= PrinterSFHeader
[iColumn
].fmt
;
610 psd
->cxChar
= PrinterSFHeader
[iColumn
].cxChar
;
613 psd
->str
.uType
= STRRET_WSTR
;
614 if (LoadStringW(shell32_hInstance
, PrinterSFHeader
[iColumn
].colnameid
, buffer
, MAX_PATH
))
615 hr
= SHStrDupW(buffer
, &psd
->str
.pOleStr
);
620 if (iColumn
== COLUMN_NAME
)
622 psd
->str
.uType
= STRRET_WSTR
;
623 return GetDisplayNameOf(pidl
, SHGDN_NORMAL
, &psd
->str
);
626 psd
->str
.uType
= STRRET_CSTR
;
627 psd
->str
.cStr
[0] = '\0';
632 HRESULT WINAPI
CPrinterFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
634 FIXME ("(%p): stub\n", this);
638 /************************************************************************
639 * CPrinterFolder::GetClassID
641 HRESULT WINAPI
CPrinterFolder::GetClassID(CLSID
*lpClassId
)
643 TRACE ("(%p)\n", this);
645 *lpClassId
= CLSID_Printers
;
650 /************************************************************************
651 * CPrinterFolder::Initialize
653 HRESULT WINAPI
CPrinterFolder::Initialize(LPCITEMIDLIST pidl
)
656 SHFree((LPVOID
)pidlRoot
);
658 pidlRoot
= ILClone(pidl
);
662 /**************************************************************************
663 * CPrinterFolder::GetCurFolder
665 HRESULT WINAPI
CPrinterFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
667 TRACE ("(%p)->(%p)\n", this, pidl
);
669 *pidl
= ILClone (pidlRoot
);