c7df54fc79cc40921d6e79f8e2bc116ed0c5c85c
[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_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_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 hr = CDefView_Constructor(this, riid, ppvOut);
289 }
290 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
291 return hr;
292 }
293
294 /**************************************************************************
295 * CPrinterFolder::GetAttributesOf
296 */
297 HRESULT WINAPI CPrinterFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
298 {
299 static const DWORD dwPrintersAttributes =
300 SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
301 HRESULT hr = S_OK;
302
303 FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
304 this, cidl, apidl, *rgfInOut);
305
306 *rgfInOut &= dwPrintersAttributes;
307
308 *rgfInOut &= ~SFGAO_VALIDATE;
309
310 TRACE ("-- result=0x%08x\n", *rgfInOut);
311 return hr;
312 }
313
314 /**************************************************************************
315 * CPrinterFolder::GetUIObjectOf
316 *
317 * PARAMETERS
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
324 *
325 */
326 HRESULT WINAPI CPrinterFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
327 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
328 {
329 LPVOID pObj = NULL;
330 HRESULT hr = E_INVALIDARG;
331
332 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
333 this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
334
335 if (!ppvOut)
336 return hr;
337
338 *ppvOut = NULL;
339
340 if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && cidl == 1)
341 hr = CPrintersExtractIconW_CreateInstane(apidl[0], riid, &pObj);
342 else
343 hr = E_NOINTERFACE;
344
345 if (SUCCEEDED(hr) && !pObj)
346 hr = E_OUTOFMEMORY;
347
348 *ppvOut = pObj;
349 TRACE ("(%p)->hr=0x%08lx\n", this, hr);
350 return hr;
351 }
352
353 /**************************************************************************
354 * CPrinterFolder::GetDisplayNameOf
355 *
356 */
357 HRESULT WINAPI CPrinterFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
358 {
359 PIDLPrinterStruct * p;
360
361 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl, dwFlags, strRet);
362 pdump (pidl);
363
364 if (!strRet)
365 {
366 WARN("no strRet\n");
367 return E_INVALIDARG;
368 }
369
370 p = _ILGetPrinterStruct(pidl);
371 if (!p)
372 {
373 ERR("no printer struct\n");
374 return E_INVALIDARG;
375 }
376
377 return SHSetStrRet(strRet, p->szName);
378 }
379
380 /**************************************************************************
381 * CPrinterFolder::SetNameOf
382 * Changes the name of a file object or subfolder, possibly changing its item
383 * identifier in the process.
384 *
385 * PARAMETERS
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
391 */
392 HRESULT WINAPI CPrinterFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /* simple pidl */
393 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
394 {
395 FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner, pidl,
396 debugstr_w (lpName), dwFlags, pPidlOut);
397
398 return E_FAIL;
399 }
400
401 HRESULT WINAPI CPrinterFolder::GetDefaultSearchGUID(GUID *pguid)
402 {
403 FIXME("(%p)\n", this);
404 return E_NOTIMPL;
405 }
406
407 HRESULT WINAPI CPrinterFolder::EnumSearches(IEnumExtraSearch **ppenum)
408 {
409 FIXME("(%p)\n", this);
410 return E_NOTIMPL;
411 }
412
413 HRESULT WINAPI CPrinterFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
414 {
415 if (pSort)
416 *pSort = 0;
417 if (pDisplay)
418 *pDisplay = 0;
419
420 return S_OK;
421 }
422
423 HRESULT WINAPI CPrinterFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
424 {
425 if (!pcsFlags || iColumn >= PrinterSHELLVIEWCOLUMNS)
426 return E_INVALIDARG;
427 *pcsFlags = PrinterSFHeader[iColumn].pcsFlags;
428 return S_OK;
429
430 }
431
432 HRESULT WINAPI CPrinterFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
433 {
434 FIXME("(%p): stub\n", this);
435
436 return E_NOTIMPL;
437 }
438
439 HRESULT WINAPI CPrinterFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
440 {
441 TRACE("(%p)->(%p %i %p): stub\n", this, pidl, iColumn, psd);
442
443 if (iColumn >= PrinterSHELLVIEWCOLUMNS)
444 return E_FAIL;
445
446 psd->fmt = PrinterSFHeader[iColumn].fmt;
447 psd->cxChar = PrinterSFHeader[iColumn].cxChar;
448 if (pidl == NULL)
449 return SHSetStrRet(&psd->str, PrinterSFHeader[iColumn].colnameid);
450
451 if (iColumn == COLUMN_NAME)
452 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
453
454 psd->str.uType = STRRET_CSTR;
455 psd->str.cStr[0] = '\0';
456
457 return E_NOTIMPL;
458 }
459
460 HRESULT WINAPI CPrinterFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
461 {
462 FIXME ("(%p): stub\n", this);
463 return E_NOTIMPL;
464 }
465
466 /************************************************************************
467 * CPrinterFolder::GetClassID
468 */
469 HRESULT WINAPI CPrinterFolder::GetClassID(CLSID *lpClassId)
470 {
471 TRACE ("(%p)\n", this);
472
473 *lpClassId = CLSID_Printers;
474
475 return S_OK;
476 }
477
478 /************************************************************************
479 * CPrinterFolder::Initialize
480 */
481 HRESULT WINAPI CPrinterFolder::Initialize(LPCITEMIDLIST pidl)
482 {
483 if (pidlRoot)
484 SHFree((LPVOID)pidlRoot);
485
486 pidlRoot = ILClone(pidl);
487 return S_OK;
488 }
489
490 /**************************************************************************
491 * CPrinterFolder::GetCurFolder
492 */
493 HRESULT WINAPI CPrinterFolder::GetCurFolder(LPITEMIDLIST * pidl)
494 {
495 TRACE ("(%p)->(%p)\n", this, pidl);
496
497 *pidl = ILClone (pidlRoot);
498 return S_OK;
499 }