- Fix several bugs in printer ' IShellFolder implementation
[reactos.git] / reactos / dll / win32 / shell32 / shfldr_printers.c
1 /*
2 * Virtual Printers Folder
3 *
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2005 Huw Davies
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include <precomp.h>
24
25 WINE_DEFAULT_DEBUG_CHANNEL (shell);
26
27 /***********************************************************************
28 * Printers_IExtractIconW implementation
29 */
30 typedef struct
31 {
32 IExtractIconWVtbl *lpVtbl;
33 IExtractIconAVtbl *lpvtblExtractIconA;
34 volatile LONG ref;
35 LPITEMIDLIST pidl;
36 } IExtractIconWImpl;
37
38 #define _IExtractIconA_Offset ((int)(&(((IExtractIconWImpl*)0)->lpvtblExtractIconA)))
39 #define _ICOM_THIS_From_IExtractIconA(class, name) class* This = (class*)(((char*)name)-_IExtractIconA_Offset);
40
41 static shvheader PrinterSFHeader[] = {
42 {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
43 {IDS_SHV_COLUMN_DOCUMENTS , SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
44 {IDS_SHV_COLUMN_STATUS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
45 {IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
46 {IDS_SHV_COLUMN_LOCATION, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
47 {IDS_SHV_COLUMN_MODEL, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}
48 };
49
50 #define COLUMN_NAME 0
51 #define COLUMN_DOCUMENTS 1
52 #define COLUMN_STATUS 2
53 #define COLUMN_COMMENTS 3
54 #define COLUMN_LOCATION 4
55 #define COLUMN_MODEL 5
56
57
58 #define PrinterSHELLVIEWCOLUMNS (6)
59
60
61 /**************************************************************************
62 * IExtractIconW_QueryInterface
63 */
64 static HRESULT WINAPI IEI_Printers_fnQueryInterface(IExtractIconW *iface, REFIID riid, LPVOID *ppvObj)
65 {
66 IExtractIconWImpl *This = (IExtractIconWImpl *)iface;
67
68 TRACE("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid(riid), ppvObj);
69
70 *ppvObj = NULL;
71
72 if (IsEqualIID(riid, &IID_IUnknown))
73 {
74 *ppvObj = This;
75 }
76 else if (IsEqualIID(riid, &IID_IExtractIconW))
77 {
78 *ppvObj = (IExtractIconW*)This;
79 }
80 else if (IsEqualIID(riid, &IID_IExtractIconA))
81 {
82 *ppvObj = (IExtractIconA*)&(This->lpvtblExtractIconA);
83 }
84
85 if(*ppvObj)
86 {
87 ((IExtractIconW*)*ppvObj)->lpVtbl->AddRef(*ppvObj);
88 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
89 return S_OK;
90 }
91 TRACE("-- Interface: E_NOINTERFACE\n");
92 return E_NOINTERFACE;
93 }
94
95 /**************************************************************************
96 * IExtractIconW_AddRef
97 */
98 static ULONG WINAPI IEI_Printers_fnAddRef(IExtractIconW * iface)
99 {
100 IExtractIconWImpl *This = (IExtractIconWImpl *)iface;
101 ULONG refCount = InterlockedIncrement(&This->ref);
102
103 TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
104
105 return refCount;
106 }
107
108 /**************************************************************************
109 * IExtractIconW_Release
110 */
111 static ULONG WINAPI IEI_Printers_fnRelease(IExtractIconW * iface)
112 {
113 IExtractIconWImpl *This = (IExtractIconWImpl *)iface;
114 ULONG refCount = InterlockedDecrement(&This->ref);
115
116 TRACE("(%p)->(count=%lu)\n", This, refCount + 1);
117
118 if (!refCount)
119 {
120 TRACE(" destroying IExtractIcon(%p)\n",This);
121 SHFree(This->pidl);
122 HeapFree(GetProcessHeap(),0,This);
123 return 0;
124 }
125 return refCount;
126 }
127
128 /**************************************************************************
129 * IExtractIconW_GetIconLocation
130 *
131 * mapping filetype to icon
132 */
133 static HRESULT WINAPI IEI_Printers_fnGetIconLocation(
134 IExtractIconW * iface,
135 UINT uFlags, /* GIL_ flags */
136 LPWSTR szIconFile,
137 UINT cchMax,
138 int *piIndex,
139 UINT *pwFlags) /* returned GIL_ flags */
140 {
141 IExtractIconWImpl *This = (IExtractIconWImpl *)iface;
142
143 TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags);
144
145 if (pwFlags)
146 *pwFlags = 0;
147
148 lstrcpynW(szIconFile, swShell32Name, cchMax);
149 *piIndex = -IDI_SHELL_PRINTERS_FOLDER; /* FIXME: other icons for default, network, print to file */
150
151 TRACE("-- %s %x\n", debugstr_w(szIconFile), *piIndex);
152 return NOERROR;
153 }
154
155 /**************************************************************************
156 * IExtractIconW_Extract
157 */
158 static HRESULT WINAPI IEI_Printers_fnExtract(IExtractIconW *iface, LPCWSTR pszFile,
159 UINT nIconIndex, HICON *phiconLarge,
160 HICON *phiconSmall, UINT nIconSize)
161 {
162 IExtractIconWImpl *This = (IExtractIconWImpl *)iface;
163 int index;
164
165 FIXME("(%p) (file=%p index=%d %p %p size=%x) semi-stub\n", This, debugstr_w(pszFile),
166 (signed)nIconIndex, phiconLarge, phiconSmall, nIconSize);
167
168 index = SIC_GetIconIndex(pszFile, nIconIndex, 0);
169
170 if (phiconLarge)
171 *phiconLarge = ImageList_GetIcon(ShellBigIconList, index, ILD_TRANSPARENT);
172
173 if (phiconSmall)
174 *phiconSmall = ImageList_GetIcon(ShellSmallIconList, index, ILD_TRANSPARENT);
175
176 return S_OK;
177 }
178
179 static struct IExtractIconWVtbl eivt =
180 {
181 IEI_Printers_fnQueryInterface,
182 IEI_Printers_fnAddRef,
183 IEI_Printers_fnRelease,
184 IEI_Printers_fnGetIconLocation,
185 IEI_Printers_fnExtract
186 };
187
188 /**************************************************************************
189 * IExtractIconA_QueryInterface
190 */
191 static HRESULT WINAPI IEIA_Printers_fnQueryInterface(IExtractIconA * iface, REFIID riid, LPVOID *ppvObj)
192 {
193 _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
194
195 return This->lpVtbl->QueryInterface(This, riid, ppvObj);
196 }
197
198 /**************************************************************************
199 * IExtractIconA_AddRef
200 */
201 static ULONG WINAPI IEIA_Printers_fnAddRef(IExtractIconA * iface)
202 {
203 _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
204
205 return This->lpVtbl->AddRef(This);
206 }
207 /**************************************************************************
208 * IExtractIconA_Release
209 */
210 static ULONG WINAPI IEIA_Printers_fnRelease(IExtractIconA * iface)
211 {
212 _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
213
214 return This->lpVtbl->AddRef(This);
215 }
216
217 /**************************************************************************
218 * IExtractIconA_GetIconLocation
219 */
220 static HRESULT WINAPI IEIA_Printers_fnGetIconLocation(
221 IExtractIconA * iface,
222 UINT uFlags,
223 LPSTR szIconFile,
224 UINT cchMax,
225 int * piIndex,
226 UINT * pwFlags)
227 {
228 HRESULT ret;
229 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, cchMax * sizeof(WCHAR));
230 _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
231
232 TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags);
233
234 ret = This->lpVtbl->GetIconLocation(This, uFlags, lpwstrFile, cchMax, piIndex, pwFlags);
235 WideCharToMultiByte(CP_ACP, 0, lpwstrFile, -1, szIconFile, cchMax, NULL, NULL);
236 HeapFree(GetProcessHeap(), 0, lpwstrFile);
237
238 TRACE("-- %s %x\n", szIconFile, *piIndex);
239 return ret;
240 }
241 /**************************************************************************
242 * IExtractIconA_Extract
243 */
244 static HRESULT WINAPI IEIA_Printers_fnExtract(IExtractIconA *iface, LPCSTR pszFile,
245 UINT nIconIndex, HICON *phiconLarge,
246 HICON *phiconSmall, UINT nIconSize)
247 {
248 HRESULT ret;
249 INT len = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0);
250 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
251 _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
252
253 TRACE("(%p) (file=%p index=%u %p %p size=%u)\n", This, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
254
255 MultiByteToWideChar(CP_ACP, 0, pszFile, -1, lpwstrFile, len);
256 ret = This->lpVtbl->Extract(This, lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
257 HeapFree(GetProcessHeap(), 0, lpwstrFile);
258 return ret;
259 }
260
261 static struct IExtractIconAVtbl eiavt =
262 {
263 IEIA_Printers_fnQueryInterface,
264 IEIA_Printers_fnAddRef,
265 IEIA_Printers_fnRelease,
266 IEIA_Printers_fnGetIconLocation,
267 IEIA_Printers_fnExtract
268 };
269
270 /**************************************************************************
271 * IExtractIcon_Constructor
272 */
273 static IUnknown *IEI_Printers_Constructor(LPCITEMIDLIST pidl)
274 {
275 IExtractIconWImpl* ei;
276
277 TRACE("%p\n", pidl);
278
279 ei = HeapAlloc(GetProcessHeap(),0,sizeof(IExtractIconWImpl));
280 ei->ref = 1;
281 ei->lpVtbl = &eivt;
282 ei->lpvtblExtractIconA = &eiavt;
283 ei->pidl=ILClone(pidl);
284
285 pdump(pidl);
286
287 TRACE("(%p)\n", ei);
288 return (IUnknown *)ei;
289 }
290
291 /***********************************************************************
292 * Printers folder implementation
293 */
294
295 typedef struct {
296 IShellFolder2Vtbl *lpVtbl;
297 IPersistFolder2Vtbl *lpVtblPersistFolder2;
298
299 LONG ref;
300
301 CLSID *pclsid;
302
303 LPITEMIDLIST pidlRoot; /* absolute pidl */
304
305 int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */
306 } IGenericSFImpl;
307
308 #define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2)))
309 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
310
311 #define _IUnknown_(This) (IShellFolder*)&(This->lpVtbl)
312 #define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl)
313
314 #define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2)
315 #define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2)
316 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2)
317
318 /**************************************************************************
319 * ISF_Printers_fnQueryInterface
320 *
321 * NOTE does not support IPersist/IPersistFolder
322 */
323 static HRESULT WINAPI ISF_Printers_fnQueryInterface(
324 IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
325 {
326 IGenericSFImpl *This = (IGenericSFImpl *)iface;
327
328 TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
329
330 *ppvObj = NULL;
331
332 if (IsEqualIID (riid, &IID_IUnknown) ||
333 IsEqualIID (riid, &IID_IShellFolder) ||
334 IsEqualIID (riid, &IID_IShellFolder2))
335 {
336 *ppvObj = _IShellFolder_(This);
337 }
338
339 else if (IsEqualIID (riid, &IID_IPersist) ||
340 IsEqualIID (riid, &IID_IPersistFolder) ||
341 IsEqualIID (riid, &IID_IPersistFolder2))
342 {
343 *ppvObj = _IPersistFolder2_ (This);
344 }
345
346 if (*ppvObj)
347 {
348 IUnknown_AddRef ((IUnknown *) (*ppvObj));
349 TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
350 return S_OK;
351 }
352 TRACE ("-- Interface: E_NOINTERFACE\n");
353 return E_NOINTERFACE;
354 }
355
356 static ULONG WINAPI ISF_Printers_fnAddRef (IShellFolder2 * iface)
357 {
358 IGenericSFImpl *This = (IGenericSFImpl *)iface;
359 ULONG refCount = InterlockedIncrement(&This->ref);
360
361 TRACE ("(%p)->(count=%lu)\n", This, refCount - 1);
362
363 return refCount;
364 }
365
366 static ULONG WINAPI ISF_Printers_fnRelease (IShellFolder2 * iface)
367 {
368 IGenericSFImpl *This = (IGenericSFImpl *)iface;
369 ULONG refCount = InterlockedDecrement(&This->ref);
370
371 TRACE ("(%p)->(count=%lu)\n", This, refCount + 1);
372
373 if (!refCount)
374 {
375 TRACE ("-- destroying IShellFolder(%p)\n", This);
376 if (This->pidlRoot)
377 SHFree (This->pidlRoot);
378 LocalFree ((HLOCAL) This);
379 return 0;
380 }
381 return refCount;
382 }
383
384 /**************************************************************************
385 * ISF_Printers_fnParseDisplayName
386 *
387 * This is E_NOTIMPL in Windows too.
388 */
389 static HRESULT WINAPI ISF_Printers_fnParseDisplayName (IShellFolder2 * iface,
390 HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
391 DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
392 {
393 IGenericSFImpl *This = (IGenericSFImpl *)iface;
394
395 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
396 This, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
397 pchEaten, ppidl, pdwAttributes);
398
399 *ppidl = 0;
400 if (pchEaten)
401 *pchEaten = 0;
402
403 return E_NOTIMPL;
404 }
405
406 static LPITEMIDLIST _ILCreatePrinterItem(PRINTER_INFO_4W *pi)
407 {
408 PIDLDATA tmp;
409 LPITEMIDLIST pidl;
410 PIDLPrinterStruct * p;
411 int size0 = (char*)&tmp.u.cprinter.szName-(char*)&tmp.u.cprinter;
412 int size = size0;
413
414 tmp.type = 0x00;
415 tmp.u.cprinter.dummy = 0xFF;
416 if (pi->pPrinterName)
417 tmp.u.cprinter.offsServer = wcslen(pi->pPrinterName) + 1;
418 else
419 tmp.u.cprinter.offsServer = 1;
420
421 size += tmp.u.cprinter.offsServer * sizeof(WCHAR);
422 if (pi->pServerName)
423 size += ( + wcslen(pi->pServerName) + 1) * sizeof(WCHAR);
424 else
425 size += sizeof(WCHAR);
426
427 pidl = (LPITEMIDLIST)SHAlloc(size + 4);
428 if (!pidl)
429 return pidl;
430
431 pidl->mkid.cb = size+2;
432 memcpy(pidl->mkid.abID, &tmp, 2+size0);
433
434 p = &((PIDLDATA*)pidl->mkid.abID)->u.cprinter;
435
436 p->Attributes = pi->Attributes;
437 if (pi->pPrinterName)
438 wcscpy(p->szName, pi->pPrinterName);
439 else
440 p->szName[0] = L'\0';
441
442 if (pi->pServerName)
443 wcscpy(p->szName + p->offsServer, pi->pServerName);
444 else
445 p->szName[p->offsServer] = L'\0';
446
447 *(WORD*)((char*)pidl+(size+2)) = 0;
448 return pidl;
449 }
450
451 static PIDLPrinterStruct * _ILGetPrinterStruct(LPCITEMIDLIST pidl)
452 {
453 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
454
455 if (pdata && pdata->type==0x00)
456 return (PIDLPrinterStruct*)&(pdata->u.cfont);
457
458 return NULL;
459 }
460
461 /**************************************************************************
462 * CreatePrintersEnumList()
463 */
464 static BOOL CreatePrintersEnumList(IEnumIDList *list, DWORD dwFlags)
465 {
466 BOOL ret = TRUE;
467
468 TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags);
469
470 /* enumerate the folders */
471 if (dwFlags & SHCONTF_NONFOLDERS)
472 {
473 DWORD needed = 0, num = 0, i;
474 PRINTER_INFO_4W *pi;
475
476 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &needed, &num);
477 if (!needed)
478 return ret;
479
480 pi = HeapAlloc(GetProcessHeap(), 0, needed);
481 if(!EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 4, (LPBYTE)pi, needed, &needed, &num)) {
482 HeapFree(GetProcessHeap(), 0, pi);
483 return FALSE;
484 }
485
486 for(i = 0; i < num; i++) {
487 LPITEMIDLIST pidl = _ILCreatePrinterItem(&pi[i]);
488 if (pidl)
489 {
490 if (!AddToEnumList(list, pidl))
491 SHFree(pidl);
492 }
493 }
494 HeapFree(GetProcessHeap(), 0, pi);
495 }
496 return ret;
497 }
498
499 /**************************************************************************
500 * ISF_Printers_fnEnumObjects
501 */
502 static HRESULT WINAPI ISF_Printers_fnEnumObjects (IShellFolder2 * iface,
503 HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
504 {
505 IGenericSFImpl *This = (IGenericSFImpl *)iface;
506
507 TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n",
508 This, hwndOwner, dwFlags, ppEnumIDList);
509
510 if(!ppEnumIDList) return E_OUTOFMEMORY;
511 *ppEnumIDList = IEnumIDList_Constructor();
512 if (*ppEnumIDList)
513 CreatePrintersEnumList(*ppEnumIDList, dwFlags);
514
515 TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
516
517 return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
518 }
519
520 /**************************************************************************
521 * ISF_Printers_fnBindToObject
522 */
523 static HRESULT WINAPI ISF_Printers_fnBindToObject (IShellFolder2 * iface,
524 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
525 {
526 IGenericSFImpl *This = (IGenericSFImpl *)iface;
527
528 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This,
529 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
530
531 return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
532 }
533
534 /**************************************************************************
535 * ISF_Printers_fnBindToStorage
536 */
537 static HRESULT WINAPI ISF_Printers_fnBindToStorage (IShellFolder2 * iface,
538 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
539 {
540 IGenericSFImpl *This = (IGenericSFImpl *)iface;
541
542 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
543 This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
544
545 *ppvOut = NULL;
546 return E_NOTIMPL;
547 }
548
549 /**************************************************************************
550 * ISF_Printers_fnCompareIDs
551 */
552 static HRESULT WINAPI ISF_Printers_fnCompareIDs (IShellFolder2 * iface,
553 LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
554 {
555 IGenericSFImpl *This = (IGenericSFImpl *)iface;
556 int nReturn;
557
558 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
559 nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
560 TRACE ("-- %i\n", nReturn);
561 return nReturn;
562 }
563
564 /**************************************************************************
565 * ISF_Printers_fnCreateViewObject
566 */
567 static HRESULT WINAPI ISF_Printers_fnCreateViewObject (IShellFolder2 * iface,
568 HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
569 {
570
571 LPSHELLVIEW pShellView;
572 HRESULT hr = E_INVALIDARG;
573 IGenericSFImpl *This = (IGenericSFImpl *)iface;
574
575 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This,
576 hwndOwner, shdebugstr_guid (riid), ppvOut);
577
578 if (!ppvOut)
579 return hr;
580
581 *ppvOut = NULL;
582
583 if (IsEqualIID (riid, &IID_IDropTarget))
584 {
585 WARN ("IDropTarget not implemented\n");
586 hr = E_NOTIMPL;
587 }
588 else if (IsEqualIID (riid, &IID_IContextMenu))
589 {
590 WARN ("IContextMenu not implemented\n");
591 hr = E_NOTIMPL;
592 }
593 else if (IsEqualIID (riid, &IID_IShellView))
594 {
595 pShellView = IShellView_Constructor ((IShellFolder *) iface);
596 if (pShellView)
597 {
598 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
599 IShellView_Release (pShellView);
600 }
601 }
602 TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
603 return hr;
604 }
605
606 /**************************************************************************
607 * ISF_Printers_fnGetAttributesOf
608 */
609 static HRESULT WINAPI ISF_Printers_fnGetAttributesOf (IShellFolder2 * iface,
610 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
611 {
612 static const DWORD dwPrintersAttributes =
613 SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
614 HRESULT hr = S_OK;
615 IGenericSFImpl *This = (IGenericSFImpl *)iface;
616
617 FIXME ("(%p)->(cidl=%d apidl=%p mask=0x%08lx): stub\n",
618 This, cidl, apidl, *rgfInOut);
619
620 *rgfInOut &= dwPrintersAttributes;
621
622 *rgfInOut &= ~SFGAO_VALIDATE;
623
624 TRACE ("-- result=0x%08x\n", *rgfInOut);
625 return hr;
626 }
627
628 /**************************************************************************
629 * ISF_Printers_fnGetUIObjectOf
630 *
631 * PARAMETERS
632 * HWND hwndOwner, //[in ] Parent window for any output
633 * UINT cidl, //[in ] array size
634 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
635 * REFIID riid, //[in ] Requested Interface
636 * UINT* prgfInOut, //[ ] reserved
637 * LPVOID* ppvObject) //[out] Resulting Interface
638 *
639 */
640 static HRESULT WINAPI ISF_Printers_fnGetUIObjectOf (IShellFolder2 * iface,
641 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl,
642 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
643 {
644 IGenericSFImpl *This = (IGenericSFImpl *)iface;
645 IUnknown *pObj = NULL;
646 HRESULT hr = E_INVALIDARG;
647
648 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
649 This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
650
651 if (!ppvOut)
652 return hr;
653
654 *ppvOut = NULL;
655
656 if ((IsEqualIID (riid, &IID_IExtractIconA) || IsEqualIID(riid, &IID_IExtractIconW)) && (cidl == 1))
657 {
658 IUnknown *pUnk = IEI_Printers_Constructor(apidl[0]);
659 hr = IUnknown_QueryInterface(pUnk, riid, (void**)&pObj);
660 IUnknown_Release(pUnk);
661 }
662 else
663 hr = E_NOINTERFACE;
664
665 if (SUCCEEDED(hr) && !pObj)
666 hr = E_OUTOFMEMORY;
667
668 *ppvOut = pObj;
669 TRACE ("(%p)->hr=0x%08lx\n", This, hr);
670 return hr;
671 }
672
673 /**************************************************************************
674 * ISF_Printers_fnGetDisplayNameOf
675 *
676 */
677 static HRESULT WINAPI ISF_Printers_fnGetDisplayNameOf (IShellFolder2 * iface,
678 LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
679 {
680 LPWSTR pszName;
681 IGenericSFImpl *This = (IGenericSFImpl *)iface;
682 PIDLPrinterStruct * p;
683
684 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
685 pdump (pidl);
686
687 if (!strRet)
688 {
689 WARN("no strRet\n");
690 return E_INVALIDARG;
691 }
692
693 if (_ILIsPrinter(pidl))
694 {
695 pszName = CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
696 if (!pszName)
697 return E_OUTOFMEMORY;
698
699 if (LoadStringW(shell32_hInstance, IDS_PRINTERS, pszName, MAX_PATH))
700 {
701 pszName[MAX_PATH-1] = L'\0';
702 strRet->uType = STRRET_WSTR;
703 strRet->u.pOleStr = pszName;
704 return S_OK;
705 }
706 CoTaskMemFree(pszName);
707 return E_FAIL;
708 }
709
710 p = _ILGetPrinterStruct(pidl);
711 if (!p)
712 {
713 WARN("no printer struct\n");
714 return E_INVALIDARG;
715 }
716 strRet->u.pOleStr = SHAlloc(p->offsServer * sizeof(WCHAR));
717 if (!strRet->u.pOleStr)
718 return E_OUTOFMEMORY;
719
720 memcpy((LPVOID)strRet->u.pOleStr, (LPVOID)p->szName, p->offsServer * sizeof(WCHAR));
721 TRACE("ret %s\n", debugstr_w(strRet->u.pOleStr));
722
723 return S_OK;
724 }
725
726 /**************************************************************************
727 * ISF_Printers_fnSetNameOf
728 * Changes the name of a file object or subfolder, possibly changing its item
729 * identifier in the process.
730 *
731 * PARAMETERS
732 * HWND hwndOwner, //[in ] Owner window for output
733 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
734 * LPCOLESTR lpszName, //[in ] the items new display name
735 * DWORD dwFlags, //[in ] SHGNO formatting flags
736 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
737 */
738 static HRESULT WINAPI ISF_Printers_fnSetNameOf (IShellFolder2 * iface,
739 HWND hwndOwner, LPCITEMIDLIST pidl, /* simple pidl */
740 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
741 {
742 IGenericSFImpl *This = (IGenericSFImpl *)iface;
743
744 FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl,
745 debugstr_w (lpName), dwFlags, pPidlOut);
746
747 return E_FAIL;
748 }
749
750 static HRESULT WINAPI ISF_Printers_fnGetDefaultSearchGUID(IShellFolder2 *iface,
751 GUID * pguid)
752 {
753 IGenericSFImpl *This = (IGenericSFImpl *)iface;
754
755 FIXME ("(%p)\n", This);
756 return E_NOTIMPL;
757 }
758
759 static HRESULT WINAPI ISF_Printers_fnEnumSearches (IShellFolder2 *iface,
760 IEnumExtraSearch ** ppenum)
761 {
762 IGenericSFImpl *This = (IGenericSFImpl *)iface;
763 FIXME ("(%p)\n", This);
764 return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI ISF_Printers_fnGetDefaultColumn (IShellFolder2 * iface,
768 DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
769 {
770 if (pSort)
771 *pSort = 0;
772 if (pDisplay)
773 *pDisplay = 0;
774
775 return S_OK;
776 }
777 static HRESULT WINAPI ISF_Printers_fnGetDefaultColumnState (
778 IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
779 {
780 if (!pcsFlags || iColumn >= PrinterSHELLVIEWCOLUMNS)
781 return E_INVALIDARG;
782 *pcsFlags = PrinterSFHeader[iColumn].pcsFlags;
783 return S_OK;
784
785 }
786
787 static HRESULT WINAPI ISF_Printers_fnGetDetailsEx (IShellFolder2 * iface,
788 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
789 {
790 IGenericSFImpl *This = (IGenericSFImpl *)iface;
791 FIXME ("(%p): stub\n", This);
792
793 return E_NOTIMPL;
794 }
795
796 static HRESULT WINAPI ISF_Printers_fnGetDetailsOf (IShellFolder2 * iface,
797 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
798 {
799 IGenericSFImpl *This = (IGenericSFImpl *)iface;
800 WCHAR buffer[MAX_PATH] = {0};
801 HRESULT hr = E_FAIL;
802
803 TRACE("(%p)->(%p %i %p): stub\n", This, pidl, iColumn, psd);
804
805 if (iColumn >= PrinterSHELLVIEWCOLUMNS)
806 return E_FAIL;
807
808 psd->fmt = PrinterSFHeader[iColumn].fmt;
809 psd->cxChar = PrinterSFHeader[iColumn].cxChar;
810 if (pidl == NULL)
811 {
812 psd->str.uType = STRRET_WSTR;
813 if (LoadStringW(shell32_hInstance, PrinterSFHeader[iColumn].colnameid, buffer, MAX_PATH))
814 hr = SHStrDupW(buffer, &psd->str.u.pOleStr);
815
816 return hr;
817 }
818
819 if (iColumn == COLUMN_NAME)
820 {
821 psd->str.uType = STRRET_WSTR;
822 return IShellFolder2_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL, &psd->str);
823 }
824
825 psd->str.uType = STRRET_CSTR;
826 psd->str.u.cStr[0] = '\0';
827
828 return E_NOTIMPL;
829 }
830
831 static HRESULT WINAPI ISF_Printers_fnMapColumnToSCID (
832 IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid)
833 {
834 IGenericSFImpl *This = (IGenericSFImpl *)iface;
835 FIXME ("(%p): stub\n", This);
836 return E_NOTIMPL;
837 }
838
839 static IShellFolder2Vtbl vt_ShellFolder2 =
840 {
841 ISF_Printers_fnQueryInterface,
842 ISF_Printers_fnAddRef,
843 ISF_Printers_fnRelease,
844 ISF_Printers_fnParseDisplayName,
845 ISF_Printers_fnEnumObjects,
846 ISF_Printers_fnBindToObject,
847 ISF_Printers_fnBindToStorage,
848 ISF_Printers_fnCompareIDs,
849 ISF_Printers_fnCreateViewObject,
850 ISF_Printers_fnGetAttributesOf,
851 ISF_Printers_fnGetUIObjectOf,
852 ISF_Printers_fnGetDisplayNameOf,
853 ISF_Printers_fnSetNameOf,
854 /* ShellFolder2 */
855 ISF_Printers_fnGetDefaultSearchGUID,
856 ISF_Printers_fnEnumSearches,
857 ISF_Printers_fnGetDefaultColumn,
858 ISF_Printers_fnGetDefaultColumnState,
859 ISF_Printers_fnGetDetailsEx,
860 ISF_Printers_fnGetDetailsOf,
861 ISF_Printers_fnMapColumnToSCID
862 };
863
864 /************************************************************************
865 * IPF_Printers_QueryInterface
866 */
867 static HRESULT WINAPI IPF_Printers_QueryInterface (
868 IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj)
869 {
870 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
871
872 TRACE ("(%p)\n", This);
873
874 return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj);
875 }
876
877 /************************************************************************
878 * IPF_Printers_AddRef
879 */
880 static ULONG WINAPI IPF_Printers_AddRef (IPersistFolder2 * iface)
881 {
882 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
883
884 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
885
886 return IUnknown_AddRef (_IUnknown_ (This));
887 }
888
889 /************************************************************************
890 * IPF_Printers_Release
891 */
892 static ULONG WINAPI IPF_Printers_Release (IPersistFolder2 * iface)
893 {
894 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
895
896 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
897
898 return IUnknown_Release (_IUnknown_ (This));
899 }
900
901 /************************************************************************
902 * IPF_Printers_GetClassID
903 */
904 static HRESULT WINAPI IPF_Printers_GetClassID (
905 IPersistFolder2 * iface, CLSID * lpClassId)
906 {
907 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
908
909 TRACE ("(%p)\n", This);
910
911 *lpClassId = CLSID_Printers;
912
913 return S_OK;
914 }
915
916 /************************************************************************
917 * IPF_Printers_Initialize
918 *
919 */
920 static HRESULT WINAPI IPF_Printers_Initialize (
921 IPersistFolder2 * iface, LPCITEMIDLIST pidl)
922 {
923 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
924 if (This->pidlRoot)
925 SHFree((LPVOID)This->pidlRoot);
926
927 This->pidlRoot = ILClone(pidl);
928 return S_OK;
929 }
930
931 /**************************************************************************
932 * IPF_Printers_fnGetCurFolder
933 */
934 static HRESULT WINAPI IPF_Printers_GetCurFolder (
935 IPersistFolder2 * iface, LPITEMIDLIST * pidl)
936 {
937 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
938
939 TRACE ("(%p)->(%p)\n", This, pidl);
940
941 *pidl = ILClone (This->pidlRoot);
942 return S_OK;
943 }
944
945 static IPersistFolder2Vtbl vt_PersistFolder2 =
946 {
947 IPF_Printers_QueryInterface,
948 IPF_Printers_AddRef,
949 IPF_Printers_Release,
950 IPF_Printers_GetClassID,
951 IPF_Printers_Initialize,
952 IPF_Printers_GetCurFolder
953 };
954
955 /**************************************************************************
956 * ISF_Printers_Constructor
957 */
958 HRESULT WINAPI ISF_Printers_Constructor (
959 IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
960 {
961 IGenericSFImpl *sf;
962 HRESULT hr;
963
964 TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
965
966 if (pUnkOuter)
967 return CLASS_E_NOAGGREGATION;
968
969 sf = HeapAlloc( GetProcessHeap(), 0, sizeof(*sf) );
970 if (!sf)
971 return E_OUTOFMEMORY;
972
973 sf->ref = 1;
974 sf->lpVtbl = &vt_ShellFolder2;
975 sf->lpVtblPersistFolder2 = &vt_PersistFolder2;
976
977 sf->pidlRoot = _ILCreatePrinters(); /* my qualified pidl */
978
979 hr = IUnknown_QueryInterface( _IUnknown_(sf), riid, ppv );
980 IUnknown_Release( _IUnknown_(sf) );
981
982 TRACE ("--(%p)\n", *ppv);
983 return hr;
984 }