[SHELL32]
[reactos.git] / reactos / 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_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}
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(hr))
58 return NULL;
59
60 /* FIXME: other icons for default, network, print to file */
61 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_PRINTERS_FOLDER);
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 HRESULT WINAPI CPrinterFolder::FinalConstruct()
196 {
197 pidlRoot = _ILCreatePrinters(); /* my qualified pidl */
198 if (pidlRoot == NULL)
199 return E_OUTOFMEMORY;
200 return S_OK;
201 }
202
203 /**************************************************************************
204 * CPrinterFolder::ParseDisplayName
205 *
206 * This is E_NOTIMPL in Windows too.
207 */
208 HRESULT WINAPI CPrinterFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
209 DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
210 {
211 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
212 this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
213 pchEaten, ppidl, pdwAttributes);
214
215 *ppidl = 0;
216 if (pchEaten)
217 *pchEaten = 0;
218
219 return E_NOTIMPL;
220 }
221
222 static PIDLPrinterStruct * _ILGetPrinterStruct(LPCITEMIDLIST pidl)
223 {
224 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
225
226 if (pdata && pdata->type == 0x00)
227 return (PIDLPrinterStruct*) & (pdata->u.cfont);
228
229 return NULL;
230 }
231
232 /**************************************************************************
233 * CPrinterFolder::EnumObjects
234 */
235 HRESULT WINAPI CPrinterFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
236 {
237 return ShellObjectCreatorInit<CPrintersEnum>(hwndOwner, dwFlags, IID_IEnumIDList, ppEnumIDList);
238 }
239
240 /**************************************************************************
241 * CPrinterFolder::BindToObject
242 */
243 HRESULT WINAPI CPrinterFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
244 {
245 return E_NOTIMPL;
246 }
247
248 /**************************************************************************
249 * ISF_Printers_fnBindToStorage
250 */
251 HRESULT WINAPI CPrinterFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
252 {
253 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
254 this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
255
256 *ppvOut = NULL;
257 return E_NOTIMPL;
258 }
259
260 /**************************************************************************
261 * CPrinterFolder::CompareIDs
262 */
263 HRESULT WINAPI CPrinterFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
264 {
265 return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
266 }
267
268 /**************************************************************************
269 * CPrinterFolder::CreateViewObject
270 */
271 HRESULT WINAPI CPrinterFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
272 {
273 CComPtr<IShellView> pShellView;
274 HRESULT hr = E_INVALIDARG;
275
276 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
277 hwndOwner, shdebugstr_guid (&riid), ppvOut);
278
279 if (!ppvOut)
280 return hr;
281
282 *ppvOut = NULL;
283
284 if (IsEqualIID(riid, IID_IDropTarget))
285 {
286 WARN("IDropTarget not implemented\n");
287 hr = E_NOTIMPL;
288 }
289 else if(IsEqualIID(riid, IID_IContextMenu))
290 {
291 WARN("IContextMenu not implemented\n");
292 hr = E_NOTIMPL;
293 }
294 else if(IsEqualIID(riid, IID_IShellView))
295 {
296 hr = CDefView_Constructor(this, riid, ppvOut);
297 }
298 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
299 return hr;
300 }
301
302 /**************************************************************************
303 * CPrinterFolder::GetAttributesOf
304 */
305 HRESULT WINAPI CPrinterFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
306 {
307 static const DWORD dwPrintersAttributes =
308 SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
309 HRESULT hr = S_OK;
310
311 FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
312 this, cidl, apidl, *rgfInOut);
313
314 *rgfInOut &= dwPrintersAttributes;
315
316 *rgfInOut &= ~SFGAO_VALIDATE;
317
318 TRACE ("-- result=0x%08x\n", *rgfInOut);
319 return hr;
320 }
321
322 /**************************************************************************
323 * CPrinterFolder::GetUIObjectOf
324 *
325 * PARAMETERS
326 * HWND hwndOwner, //[in ] Parent window for any output
327 * UINT cidl, //[in ] array size
328 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
329 * REFIID riid, //[in ] Requested Interface
330 * UINT* prgfInOut, //[ ] reserved
331 * LPVOID* ppvObject) //[out] Resulting Interface
332 *
333 */
334 HRESULT WINAPI CPrinterFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
335 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
336 {
337 LPVOID pObj = NULL;
338 HRESULT hr = E_INVALIDARG;
339
340 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
341 this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
342
343 if (!ppvOut)
344 return hr;
345
346 *ppvOut = NULL;
347
348 if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && cidl == 1)
349 hr = CPrintersExtractIconW_CreateInstane(apidl[0], riid, &pObj);
350 else
351 hr = E_NOINTERFACE;
352
353 if (SUCCEEDED(hr) && !pObj)
354 hr = E_OUTOFMEMORY;
355
356 *ppvOut = pObj;
357 TRACE ("(%p)->hr=0x%08lx\n", this, hr);
358 return hr;
359 }
360
361 /**************************************************************************
362 * CPrinterFolder::GetDisplayNameOf
363 *
364 */
365 HRESULT WINAPI CPrinterFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
366 {
367 PIDLPrinterStruct * p;
368
369 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl, dwFlags, strRet);
370 pdump (pidl);
371
372 if (!strRet)
373 {
374 WARN("no strRet\n");
375 return E_INVALIDARG;
376 }
377
378 if (!pidl->mkid.cb)
379 return SHSetStrRet(strRet, IDS_PRINTERS);
380
381 p = _ILGetPrinterStruct(pidl);
382 if (!p)
383 {
384 WARN("no printer struct\n");
385 return E_INVALIDARG;
386 }
387
388 return SHSetStrRet(strRet, p->szName);
389 }
390
391 /**************************************************************************
392 * CPrinterFolder::SetNameOf
393 * Changes the name of a file object or subfolder, possibly changing its item
394 * identifier in the process.
395 *
396 * PARAMETERS
397 * HWND hwndOwner, //[in ] Owner window for output
398 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
399 * LPCOLESTR lpszName, //[in ] the items new display name
400 * DWORD dwFlags, //[in ] SHGNO formatting flags
401 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
402 */
403 HRESULT WINAPI CPrinterFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /* simple pidl */
404 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
405 {
406 FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner, pidl,
407 debugstr_w (lpName), dwFlags, pPidlOut);
408
409 return E_FAIL;
410 }
411
412 HRESULT WINAPI CPrinterFolder::GetDefaultSearchGUID(GUID *pguid)
413 {
414 FIXME("(%p)\n", this);
415 return E_NOTIMPL;
416 }
417
418 HRESULT WINAPI CPrinterFolder::EnumSearches(IEnumExtraSearch **ppenum)
419 {
420 FIXME("(%p)\n", this);
421 return E_NOTIMPL;
422 }
423
424 HRESULT WINAPI CPrinterFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
425 {
426 if (pSort)
427 *pSort = 0;
428 if (pDisplay)
429 *pDisplay = 0;
430
431 return S_OK;
432 }
433
434 HRESULT WINAPI CPrinterFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
435 {
436 if (!pcsFlags || iColumn >= PrinterSHELLVIEWCOLUMNS)
437 return E_INVALIDARG;
438 *pcsFlags = PrinterSFHeader[iColumn].pcsFlags;
439 return S_OK;
440
441 }
442
443 HRESULT WINAPI CPrinterFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
444 {
445 FIXME("(%p): stub\n", this);
446
447 return E_NOTIMPL;
448 }
449
450 HRESULT WINAPI CPrinterFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
451 {
452 TRACE("(%p)->(%p %i %p): stub\n", this, pidl, iColumn, psd);
453
454 if (iColumn >= PrinterSHELLVIEWCOLUMNS)
455 return E_FAIL;
456
457 psd->fmt = PrinterSFHeader[iColumn].fmt;
458 psd->cxChar = PrinterSFHeader[iColumn].cxChar;
459 if (pidl == NULL)
460 return SHSetStrRet(&psd->str, PrinterSFHeader[iColumn].colnameid);
461
462 if (iColumn == COLUMN_NAME)
463 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
464
465 psd->str.uType = STRRET_CSTR;
466 psd->str.cStr[0] = '\0';
467
468 return E_NOTIMPL;
469 }
470
471 HRESULT WINAPI CPrinterFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
472 {
473 FIXME ("(%p): stub\n", this);
474 return E_NOTIMPL;
475 }
476
477 /************************************************************************
478 * CPrinterFolder::GetClassID
479 */
480 HRESULT WINAPI CPrinterFolder::GetClassID(CLSID *lpClassId)
481 {
482 TRACE ("(%p)\n", this);
483
484 *lpClassId = CLSID_Printers;
485
486 return S_OK;
487 }
488
489 /************************************************************************
490 * CPrinterFolder::Initialize
491 */
492 HRESULT WINAPI CPrinterFolder::Initialize(LPCITEMIDLIST pidl)
493 {
494 if (pidlRoot)
495 SHFree((LPVOID)pidlRoot);
496
497 pidlRoot = ILClone(pidl);
498 return S_OK;
499 }
500
501 /**************************************************************************
502 * CPrinterFolder::GetCurFolder
503 */
504 HRESULT WINAPI CPrinterFolder::GetCurFolder(LPITEMIDLIST * pidl)
505 {
506 TRACE ("(%p)->(%p)\n", this, pidl);
507
508 *pidl = ILClone (pidlRoot);
509 return S_OK;
510 }