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 static shvheader PrinterSFHeader
[] = {
31 {IDS_SHV_COLUMN8
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
32 {IDS_SHV_COLUMN_DOCUMENTS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
33 {IDS_SHV_COLUMN_STATUS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
34 {IDS_SHV_COLUMN_COMMENTS
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
35 {IDS_SHV_COLUMN_LOCATION
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
36 {IDS_SHV_COLUMN_MODEL
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15}
40 #define COLUMN_DOCUMENTS 1
41 #define COLUMN_STATUS 2
42 #define COLUMN_COMMENTS 3
43 #define COLUMN_LOCATION 4
44 #define COLUMN_MODEL 5
46 #define PrinterSHELLVIEWCOLUMNS (6)
48 /**************************************************************************
49 * CPrintersExtractIconW_CreateInstane
51 * There is no CPrintersExtractIconW. We just initialize CExtractIcon properly to do our job.
53 HRESULT WINAPI
CPrintersExtractIconW_CreateInstane(LPCITEMIDLIST pidl
, REFIID riid
, LPVOID
*ppv
)
55 CComPtr
<IDefaultExtractIconInit
> initIcon
;
56 HRESULT hr
= SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit
,&initIcon
));
57 if (FAILED_UNEXPECTEDLY(hr
))
60 /* FIXME: other icons for default, network, print to file */
61 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_PRINTER
);
63 return initIcon
->QueryInterface(riid
,ppv
);
66 /***********************************************************************
67 * Printers folder implementation
70 class CPrintersEnum
: public CEnumIDListBase
75 HRESULT WINAPI
Initialize(HWND hwndOwner
, DWORD dwFlags
);
76 BOOL
CreatePrintersEnumList(DWORD dwFlags
);
78 BEGIN_COM_MAP(CPrintersEnum
)
79 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
83 CPrintersEnum::CPrintersEnum()
87 CPrintersEnum::~CPrintersEnum()
91 HRESULT WINAPI
CPrintersEnum::Initialize(HWND hwndOwner
, DWORD dwFlags
)
93 if (CreatePrintersEnumList(dwFlags
) == FALSE
)
98 static LPITEMIDLIST
_ILCreatePrinterItem(PRINTER_INFO_4W
*pi
)
102 PIDLPrinterStruct
* p
;
103 int size0
= (char*)&tmp
.u
.cprinter
.szName
- (char*)&tmp
.u
.cprinter
;
107 tmp
.u
.cprinter
.dummy
= 0xFF;
108 if (pi
->pPrinterName
)
109 tmp
.u
.cprinter
.offsServer
= wcslen(pi
->pPrinterName
) + 1;
111 tmp
.u
.cprinter
.offsServer
= 1;
113 size
+= tmp
.u
.cprinter
.offsServer
* sizeof(WCHAR
);
115 size
+= (wcslen(pi
->pServerName
) + 1) * sizeof(WCHAR
);
117 size
+= sizeof(WCHAR
);
119 pidl
= (LPITEMIDLIST
)SHAlloc(size
+ 4);
123 pidl
->mkid
.cb
= size
+ 2;
124 memcpy(pidl
->mkid
.abID
, &tmp
, 2 + size0
);
126 p
= &((PIDLDATA
*)pidl
->mkid
.abID
)->u
.cprinter
;
128 p
->Attributes
= pi
->Attributes
;
129 if (pi
->pPrinterName
)
130 wcscpy(p
->szName
, pi
->pPrinterName
);
132 p
->szName
[0] = L
'\0';
135 wcscpy(p
->szName
+ p
->offsServer
, pi
->pServerName
);
137 p
->szName
[p
->offsServer
] = L
'\0';
139 *(WORD
*)((char*)pidl
+ (size
+ 2)) = 0;
143 /**************************************************************************
144 * CPrintersEnum::CreatePrintersEnumList()
146 BOOL
CPrintersEnum::CreatePrintersEnumList(DWORD dwFlags
)
150 TRACE("(%p)->(flags=0x%08lx) \n", this, dwFlags
);
152 /* enumerate the folders */
153 if (dwFlags
& SHCONTF_NONFOLDERS
)
155 DWORD needed
= 0, num
= 0, i
;
158 EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 4, NULL
, 0, &needed
, &num
);
162 pi
= (PRINTER_INFO_4W
*)HeapAlloc(GetProcessHeap(), 0, needed
);
163 if(!EnumPrintersW(PRINTER_ENUM_LOCAL
, NULL
, 4, (LPBYTE
)pi
, needed
, &needed
, &num
)) {
164 HeapFree(GetProcessHeap(), 0, pi
);
168 for(i
= 0; i
< num
; i
++) {
169 LPITEMIDLIST pidl
= _ILCreatePrinterItem(&pi
[i
]);
172 if (!AddToEnumList(pidl
))
176 HeapFree(GetProcessHeap(), 0, pi
);
181 CPrinterFolder::CPrinterFolder()
188 CPrinterFolder::~CPrinterFolder()
190 TRACE("-- destroying IShellFolder(%p)\n", this);
195 /**************************************************************************
196 * CPrinterFolder::ParseDisplayName
198 * This is E_NOTIMPL in Windows too.
200 HRESULT WINAPI
CPrinterFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
201 DWORD
*pchEaten
, PIDLIST_RELATIVE
*ppidl
, DWORD
*pdwAttributes
)
203 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
204 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
205 pchEaten
, ppidl
, pdwAttributes
);
214 static PIDLPrinterStruct
* _ILGetPrinterStruct(LPCITEMIDLIST pidl
)
216 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
218 if (pdata
&& pdata
->type
== 0x00)
219 return (PIDLPrinterStruct
*) & (pdata
->u
.cfont
);
224 /**************************************************************************
225 * CPrinterFolder::EnumObjects
227 HRESULT WINAPI
CPrinterFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
* ppEnumIDList
)
229 return ShellObjectCreatorInit
<CPrintersEnum
>(hwndOwner
, dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
232 /**************************************************************************
233 * CPrinterFolder::BindToObject
235 HRESULT WINAPI
CPrinterFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
* ppvOut
)
240 /**************************************************************************
241 * ISF_Printers_fnBindToStorage
243 HRESULT WINAPI
CPrinterFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
* ppvOut
)
245 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
246 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
252 /**************************************************************************
253 * CPrinterFolder::CompareIDs
255 HRESULT WINAPI
CPrinterFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
257 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
260 /**************************************************************************
261 * CPrinterFolder::CreateViewObject
263 HRESULT WINAPI
CPrinterFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
265 CComPtr
<IShellView
> pShellView
;
266 HRESULT hr
= E_INVALIDARG
;
268 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
269 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
276 if (IsEqualIID(riid
, IID_IDropTarget
))
278 WARN("IDropTarget not implemented\n");
281 else if(IsEqualIID(riid
, IID_IContextMenu
))
283 WARN("IContextMenu not implemented\n");
286 else if(IsEqualIID(riid
, IID_IShellView
))
288 hr
= CDefView_Constructor(this, riid
, ppvOut
);
290 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
294 /**************************************************************************
295 * CPrinterFolder::GetAttributesOf
297 HRESULT WINAPI
CPrinterFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
*rgfInOut
)
299 static const DWORD dwPrintersAttributes
=
300 SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
| SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_CANRENAME
| SFGAO_CANDELETE
;
303 FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
304 this, cidl
, apidl
, *rgfInOut
);
306 *rgfInOut
&= dwPrintersAttributes
;
308 *rgfInOut
&= ~SFGAO_VALIDATE
;
310 TRACE ("-- result=0x%08x\n", *rgfInOut
);
314 /**************************************************************************
315 * CPrinterFolder::GetUIObjectOf
318 * HWND hwndOwner, //[in ] Parent window for any output
319 * UINT cidl, //[in ] array size
320 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
321 * REFIID riid, //[in ] Requested Interface
322 * UINT* prgfInOut, //[ ] reserved
323 * LPVOID* ppvObject) //[out] Resulting Interface
326 HRESULT WINAPI
CPrinterFolder::GetUIObjectOf(HWND hwndOwner
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
327 REFIID riid
, UINT
* prgfInOut
, LPVOID
* ppvOut
)
330 HRESULT hr
= E_INVALIDARG
;
332 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
333 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
340 if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID(riid
, IID_IExtractIconW
)) && cidl
== 1)
341 hr
= CPrintersExtractIconW_CreateInstane(apidl
[0], riid
, &pObj
);
345 if (SUCCEEDED(hr
) && !pObj
)
349 TRACE ("(%p)->hr=0x%08lx\n", this, hr
);
353 /**************************************************************************
354 * CPrinterFolder::GetDisplayNameOf
357 HRESULT WINAPI
CPrinterFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
359 PIDLPrinterStruct
* p
;
361 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl
, dwFlags
, strRet
);
370 p
= _ILGetPrinterStruct(pidl
);
373 ERR("no printer struct\n");
377 return SHSetStrRet(strRet
, p
->szName
);
380 /**************************************************************************
381 * CPrinterFolder::SetNameOf
382 * Changes the name of a file object or subfolder, possibly changing its item
383 * identifier in the process.
386 * HWND hwndOwner, //[in ] Owner window for output
387 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
388 * LPCOLESTR lpszName, //[in ] the items new display name
389 * DWORD dwFlags, //[in ] SHGNO formatting flags
390 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
392 HRESULT WINAPI
CPrinterFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
, /* simple pidl */
393 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
395 FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner
, pidl
,
396 debugstr_w (lpName
), dwFlags
, pPidlOut
);
401 HRESULT WINAPI
CPrinterFolder::GetDefaultSearchGUID(GUID
*pguid
)
403 FIXME("(%p)\n", this);
407 HRESULT WINAPI
CPrinterFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
409 FIXME("(%p)\n", this);
413 HRESULT WINAPI
CPrinterFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
423 HRESULT WINAPI
CPrinterFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
425 if (!pcsFlags
|| iColumn
>= PrinterSHELLVIEWCOLUMNS
)
427 *pcsFlags
= PrinterSFHeader
[iColumn
].pcsFlags
;
432 HRESULT WINAPI
CPrinterFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
434 FIXME("(%p): stub\n", this);
439 HRESULT WINAPI
CPrinterFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
441 TRACE("(%p)->(%p %i %p): stub\n", this, pidl
, iColumn
, psd
);
443 if (iColumn
>= PrinterSHELLVIEWCOLUMNS
)
446 psd
->fmt
= PrinterSFHeader
[iColumn
].fmt
;
447 psd
->cxChar
= PrinterSFHeader
[iColumn
].cxChar
;
449 return SHSetStrRet(&psd
->str
, PrinterSFHeader
[iColumn
].colnameid
);
451 if (iColumn
== COLUMN_NAME
)
452 return GetDisplayNameOf(pidl
, SHGDN_NORMAL
, &psd
->str
);
454 psd
->str
.uType
= STRRET_CSTR
;
455 psd
->str
.cStr
[0] = '\0';
460 HRESULT WINAPI
CPrinterFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
462 FIXME ("(%p): stub\n", this);
466 /************************************************************************
467 * CPrinterFolder::GetClassID
469 HRESULT WINAPI
CPrinterFolder::GetClassID(CLSID
*lpClassId
)
471 TRACE ("(%p)\n", this);
473 *lpClassId
= CLSID_Printers
;
478 /************************************************************************
479 * CPrinterFolder::Initialize
481 HRESULT WINAPI
CPrinterFolder::Initialize(LPCITEMIDLIST pidl
)
484 SHFree((LPVOID
)pidlRoot
);
486 pidlRoot
= ILClone(pidl
);
490 /**************************************************************************
491 * CPrinterFolder::GetCurFolder
493 HRESULT WINAPI
CPrinterFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
495 TRACE ("(%p)->(%p)\n", this, pidl
);
497 *pidl
= ILClone (pidlRoot
);