[SHELL] IPersistFolder::Initialize takes a PCIDLIST_ABSOLUTE. CORE-16385
[reactos.git] / dll / win32 / shell32 / folders / CPrinterFolder.cpp
1 /*
2 * Virtual Printers Folder
3 *
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2005 Huw Davies
7 * Copyright 2009 Andrew Hill
8 *
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.
13 *
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.
18 *
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
22 */
23
24 #include <precomp.h>
25
26 #include <winspool.h>
27
28 WINE_DEFAULT_DEBUG_CHANNEL (shell);
29
30 static shvheader PrinterSFHeader[] = {
31 {IDS_SHV_COLUMN_NAME, 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}
37 };
38
39 #define COLUMN_NAME 0
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
45
46 #define PrinterSHELLVIEWCOLUMNS (6)
47
48 /**************************************************************************
49 * CPrintersExtractIconW_CreateInstane
50 *
51 * There is no CPrintersExtractIconW. We just initialize CExtractIcon properly to do our job.
52 */
53 HRESULT WINAPI CPrintersExtractIconW_CreateInstane(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv)
54 {
55 CComPtr<IDefaultExtractIconInit> initIcon;
56 HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit,&initIcon));
57 if (FAILED_UNEXPECTEDLY(hr))
58 return hr;
59
60 /* FIXME: other icons for default, network, print to file */
61 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_PRINTER);
62
63 return initIcon->QueryInterface(riid,ppv);
64 }
65
66 /***********************************************************************
67 * Printers folder implementation
68 */
69
70 class CPrintersEnum: public CEnumIDListBase
71 {
72 public:
73 CPrintersEnum();
74 ~CPrintersEnum();
75 HRESULT WINAPI Initialize(HWND hwndOwner, DWORD dwFlags);
76 BOOL CreatePrintersEnumList(DWORD dwFlags);
77
78 BEGIN_COM_MAP(CPrintersEnum)
79 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
80 END_COM_MAP()
81 };
82
83 CPrintersEnum::CPrintersEnum()
84 {
85 }
86
87 CPrintersEnum::~CPrintersEnum()
88 {
89 }
90
91 HRESULT WINAPI CPrintersEnum::Initialize(HWND hwndOwner, DWORD dwFlags)
92 {
93 if (CreatePrintersEnumList(dwFlags) == FALSE)
94 return E_FAIL;
95 return S_OK;
96 }
97
98 static LPITEMIDLIST _ILCreatePrinterItem(PRINTER_INFO_4W *pi)
99 {
100 PIDLDATA tmp;
101 LPITEMIDLIST pidl;
102 PIDLPrinterStruct * p;
103 int size0 = (char*)&tmp.u.cprinter.szName - (char*)&tmp.u.cprinter;
104 int size = size0;
105
106 tmp.type = 0x00;
107 tmp.u.cprinter.dummy = 0xFF;
108 if (pi->pPrinterName)
109 tmp.u.cprinter.offsServer = wcslen(pi->pPrinterName) + 1;
110 else
111 tmp.u.cprinter.offsServer = 1;
112
113 size += tmp.u.cprinter.offsServer * sizeof(WCHAR);
114 if (pi->pServerName)
115 size += (wcslen(pi->pServerName) + 1) * sizeof(WCHAR);
116 else
117 size += sizeof(WCHAR);
118
119 pidl = (LPITEMIDLIST)SHAlloc(size + 4);
120 if (!pidl)
121 return pidl;
122
123 pidl->mkid.cb = size + 2;
124 memcpy(pidl->mkid.abID, &tmp, 2 + size0);
125
126 p = &((PIDLDATA*)pidl->mkid.abID)->u.cprinter;
127
128 p->Attributes = pi->Attributes;
129 if (pi->pPrinterName)
130 wcscpy(p->szName, pi->pPrinterName);
131 else
132 p->szName[0] = L'\0';
133
134 if (pi->pServerName)
135 wcscpy(p->szName + p->offsServer, pi->pServerName);
136 else
137 p->szName[p->offsServer] = L'\0';
138
139 *(WORD*)((char*)pidl + (size + 2)) = 0;
140 return pidl;
141 }
142
143 /**************************************************************************
144 * CPrintersEnum::CreatePrintersEnumList()
145 */
146 BOOL CPrintersEnum::CreatePrintersEnumList(DWORD dwFlags)
147 {
148 BOOL ret = TRUE;
149
150 TRACE("(%p)->(flags=0x%08lx) \n", this, dwFlags);
151
152 /* enumerate the folders */
153 if (dwFlags & SHCONTF_NONFOLDERS)
154 {
155 DWORD needed = 0, num = 0, i;
156 PRINTER_INFO_4W *pi;
157
158 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &needed, &num);
159 if (!needed)
160 return ret;
161
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);
165 return FALSE;
166 }
167
168 for(i = 0; i < num; i++) {
169 LPITEMIDLIST pidl = _ILCreatePrinterItem(&pi[i]);
170 if (pidl)
171 {
172 if (!AddToEnumList(pidl))
173 SHFree(pidl);
174 }
175 }
176 HeapFree(GetProcessHeap(), 0, pi);
177 }
178 return ret;
179 }
180
181 CPrinterFolder::CPrinterFolder()
182 {
183 pidlRoot = NULL;
184 dwAttributes = 0;
185 pclsid = NULL;
186 }
187
188 CPrinterFolder::~CPrinterFolder()
189 {
190 TRACE("-- destroying IShellFolder(%p)\n", this);
191 if (pidlRoot)
192 SHFree(pidlRoot);
193 }
194
195 /**************************************************************************
196 * CPrinterFolder::ParseDisplayName
197 *
198 * This is E_NOTIMPL in Windows too.
199 */
200 HRESULT WINAPI CPrinterFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
201 DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
202 {
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);
206
207 *ppidl = 0;
208 if (pchEaten)
209 *pchEaten = 0;
210
211 return E_NOTIMPL;
212 }
213
214 static PIDLPrinterStruct * _ILGetPrinterStruct(LPCITEMIDLIST pidl)
215 {
216 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
217
218 if (pdata && pdata->type == 0x00)
219 return (PIDLPrinterStruct*) & (pdata->u.cfont);
220
221 return NULL;
222 }
223
224 /**************************************************************************
225 * CPrinterFolder::EnumObjects
226 */
227 HRESULT WINAPI CPrinterFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
228 {
229 return ShellObjectCreatorInit<CPrintersEnum>(hwndOwner, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
230 }
231
232 /**************************************************************************
233 * CPrinterFolder::BindToObject
234 */
235 HRESULT WINAPI CPrinterFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
236 {
237 return E_NOTIMPL;
238 }
239
240 /**************************************************************************
241 * ISF_Printers_fnBindToStorage
242 */
243 HRESULT WINAPI CPrinterFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
244 {
245 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
246 this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
247
248 *ppvOut = NULL;
249 return E_NOTIMPL;
250 }
251
252 /**************************************************************************
253 * CPrinterFolder::CompareIDs
254 */
255 HRESULT WINAPI CPrinterFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
256 {
257 return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
258 }
259
260 /**************************************************************************
261 * CPrinterFolder::CreateViewObject
262 */
263 HRESULT WINAPI CPrinterFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
264 {
265 CComPtr<IShellView> pShellView;
266 HRESULT hr = E_INVALIDARG;
267
268 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
269 hwndOwner, shdebugstr_guid (&riid), ppvOut);
270
271 if (!ppvOut)
272 return hr;
273
274 *ppvOut = NULL;
275
276 if (IsEqualIID(riid, IID_IDropTarget))
277 {
278 WARN("IDropTarget not implemented\n");
279 hr = E_NOTIMPL;
280 }
281 else if(IsEqualIID(riid, IID_IContextMenu))
282 {
283 WARN("IContextMenu not implemented\n");
284 hr = E_NOTIMPL;
285 }
286 else if(IsEqualIID(riid, IID_IShellView))
287 {
288 SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this};
289 hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
290 }
291 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
292 return hr;
293 }
294
295 /**************************************************************************
296 * CPrinterFolder::GetAttributesOf
297 */
298 HRESULT WINAPI CPrinterFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
299 {
300 static const DWORD dwPrintersAttributes =
301 SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
302 HRESULT hr = S_OK;
303
304 FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
305 this, cidl, apidl, *rgfInOut);
306
307 *rgfInOut &= dwPrintersAttributes;
308
309 *rgfInOut &= ~SFGAO_VALIDATE;
310
311 TRACE ("-- result=0x%08x\n", *rgfInOut);
312 return hr;
313 }
314
315 /**************************************************************************
316 * CPrinterFolder::GetUIObjectOf
317 *
318 * PARAMETERS
319 * HWND hwndOwner, //[in ] Parent window for any output
320 * UINT cidl, //[in ] array size
321 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
322 * REFIID riid, //[in ] Requested Interface
323 * UINT* prgfInOut, //[ ] reserved
324 * LPVOID* ppvObject) //[out] Resulting Interface
325 *
326 */
327 HRESULT WINAPI CPrinterFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
328 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
329 {
330 LPVOID pObj = NULL;
331 HRESULT hr = E_INVALIDARG;
332
333 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
334 this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
335
336 if (!ppvOut)
337 return hr;
338
339 *ppvOut = NULL;
340
341 if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && cidl == 1)
342 hr = CPrintersExtractIconW_CreateInstane(apidl[0], riid, &pObj);
343 else
344 hr = E_NOINTERFACE;
345
346 if (SUCCEEDED(hr) && !pObj)
347 hr = E_OUTOFMEMORY;
348
349 *ppvOut = pObj;
350 TRACE ("(%p)->hr=0x%08lx\n", this, hr);
351 return hr;
352 }
353
354 /**************************************************************************
355 * CPrinterFolder::GetDisplayNameOf
356 *
357 */
358 HRESULT WINAPI CPrinterFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
359 {
360 PIDLPrinterStruct * p;
361
362 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl, dwFlags, strRet);
363 pdump (pidl);
364
365 if (!strRet)
366 {
367 WARN("no strRet\n");
368 return E_INVALIDARG;
369 }
370
371 p = _ILGetPrinterStruct(pidl);
372 if (!p)
373 {
374 ERR("no printer struct\n");
375 return E_INVALIDARG;
376 }
377
378 return SHSetStrRet(strRet, p->szName);
379 }
380
381 /**************************************************************************
382 * CPrinterFolder::SetNameOf
383 * Changes the name of a file object or subfolder, possibly changing its item
384 * identifier in the process.
385 *
386 * PARAMETERS
387 * HWND hwndOwner, //[in ] Owner window for output
388 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
389 * LPCOLESTR lpszName, //[in ] the items new display name
390 * DWORD dwFlags, //[in ] SHGNO formatting flags
391 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
392 */
393 HRESULT WINAPI CPrinterFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /* simple pidl */
394 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
395 {
396 FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner, pidl,
397 debugstr_w (lpName), dwFlags, pPidlOut);
398
399 return E_FAIL;
400 }
401
402 HRESULT WINAPI CPrinterFolder::GetDefaultSearchGUID(GUID *pguid)
403 {
404 FIXME("(%p)\n", this);
405 return E_NOTIMPL;
406 }
407
408 HRESULT WINAPI CPrinterFolder::EnumSearches(IEnumExtraSearch **ppenum)
409 {
410 FIXME("(%p)\n", this);
411 return E_NOTIMPL;
412 }
413
414 HRESULT WINAPI CPrinterFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
415 {
416 if (pSort)
417 *pSort = 0;
418 if (pDisplay)
419 *pDisplay = 0;
420
421 return S_OK;
422 }
423
424 HRESULT WINAPI CPrinterFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
425 {
426 if (!pcsFlags || iColumn >= PrinterSHELLVIEWCOLUMNS)
427 return E_INVALIDARG;
428 *pcsFlags = PrinterSFHeader[iColumn].pcsFlags;
429 return S_OK;
430
431 }
432
433 HRESULT WINAPI CPrinterFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
434 {
435 FIXME("(%p): stub\n", this);
436
437 return E_NOTIMPL;
438 }
439
440 HRESULT WINAPI CPrinterFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
441 {
442 TRACE("(%p)->(%p %i %p): stub\n", this, pidl, iColumn, psd);
443
444 if (iColumn >= PrinterSHELLVIEWCOLUMNS)
445 return E_FAIL;
446
447 psd->fmt = PrinterSFHeader[iColumn].fmt;
448 psd->cxChar = PrinterSFHeader[iColumn].cxChar;
449 if (pidl == NULL)
450 return SHSetStrRet(&psd->str, PrinterSFHeader[iColumn].colnameid);
451
452 if (iColumn == COLUMN_NAME)
453 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
454
455 psd->str.uType = STRRET_CSTR;
456 psd->str.cStr[0] = '\0';
457
458 return E_NOTIMPL;
459 }
460
461 HRESULT WINAPI CPrinterFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
462 {
463 FIXME ("(%p): stub\n", this);
464 return E_NOTIMPL;
465 }
466
467 /************************************************************************
468 * CPrinterFolder::GetClassID
469 */
470 HRESULT WINAPI CPrinterFolder::GetClassID(CLSID *lpClassId)
471 {
472 TRACE ("(%p)\n", this);
473
474 *lpClassId = CLSID_Printers;
475
476 return S_OK;
477 }
478
479 /************************************************************************
480 * CPrinterFolder::Initialize
481 */
482 HRESULT WINAPI CPrinterFolder::Initialize(PCIDLIST_ABSOLUTE pidl)
483 {
484 if (pidlRoot)
485 SHFree((LPVOID)pidlRoot);
486
487 pidlRoot = ILClone(pidl);
488 return S_OK;
489 }
490
491 /**************************************************************************
492 * CPrinterFolder::GetCurFolder
493 */
494 HRESULT WINAPI CPrinterFolder::GetCurFolder(PIDLIST_ABSOLUTE * pidl)
495 {
496 TRACE ("(%p)->(%p)\n", this, pidl);
497
498 *pidl = ILClone (pidlRoot);
499 return S_OK;
500 }