1 /*
2 * Helper functions for debugging
3 *
4 * Copyright 1998, 2002 Juergen Schmied
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "precomp.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(pidl);
24
_dbg_ILGetType(LPCITEMIDLIST pidl)25 static inline BYTE _dbg_ILGetType(LPCITEMIDLIST pidl)
26 {
27 return pidl && pidl->mkid.cb >= 3 ? pidl->mkid.abID[0] : 0;
28 }
29
_dbg_ILGetFSType(LPCITEMIDLIST pidl)30 static inline BYTE _dbg_ILGetFSType(LPCITEMIDLIST pidl)
31 {
32 const BYTE type = _dbg_ILGetType(pidl);
33 return (type & PT_FOLDERTYPEMASK) == PT_FS ? type : 0;
34 }
35
36 static
_dbg_ILGetNext(LPCITEMIDLIST pidl)37 LPITEMIDLIST _dbg_ILGetNext(LPCITEMIDLIST pidl)
38 {
39 WORD len;
40
41 if(pidl)
42 {
43 len = pidl->mkid.cb;
44 if (len)
45 {
46 return (LPITEMIDLIST) (((LPBYTE)pidl)+len);
47 }
48 }
49 return NULL;
50 }
51
52 static
_dbg_ILIsDesktop(LPCITEMIDLIST pidl)53 BOOL _dbg_ILIsDesktop(LPCITEMIDLIST pidl)
54 {
55 return ( !pidl || (pidl && pidl->mkid.cb == 0x00) );
56 }
57
58 static
_dbg_ILGetDataPointer(LPCITEMIDLIST pidl)59 LPPIDLDATA _dbg_ILGetDataPointer(LPCITEMIDLIST pidl)
60 {
61 if(pidl && pidl->mkid.cb != 0x00)
62 return (LPPIDLDATA) &(pidl->mkid.abID);
63 return NULL;
64 }
65
66 static
_dbg_ILGetTextPointer(LPCITEMIDLIST pidl)67 LPSTR _dbg_ILGetTextPointer(LPCITEMIDLIST pidl)
68 {
69 LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl);
70
71 if (pdata)
72 {
73 switch (pdata->type)
74 {
75 case PT_GUID:
76 case PT_SHELLEXT:
77 case PT_YAGUID:
78 return NULL;
79
80 case PT_DRIVE:
81 case PT_DRIVE1:
82 case PT_DRIVE2:
83 case PT_DRIVE3:
84 return (LPSTR)&(pdata->u.drive.szDriveName);
85
86 case PT_FOLDER:
87 case PT_FOLDER1:
88 case PT_VALUE:
89 case PT_IESPECIAL1:
90 case PT_IESPECIAL2:
91 return (LPSTR)&(pdata->u.file.szNames);
92
93 case PT_WORKGRP:
94 case PT_COMP:
95 case PT_NETWORK:
96 case PT_NETPROVIDER:
97 case PT_SHARE:
98 return (LPSTR)&(pdata->u.network.szNames);
99 }
100 }
101 return NULL;
102 }
103
104 static
_dbg_ILGetTextPointerW(LPCITEMIDLIST pidl)105 LPWSTR _dbg_ILGetTextPointerW(LPCITEMIDLIST pidl)
106 {
107 LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl);
108
109 if (pdata)
110 {
111 if (_dbg_ILGetFSType(pidl) & PT_FS_UNICODE_FLAG)
112 return (LPWSTR)&(pdata->u.file.szNames);
113
114 switch (pdata->type)
115 {
116 case PT_GUID:
117 case PT_SHELLEXT:
118 case PT_YAGUID:
119 return NULL;
120
121 case PT_DRIVE:
122 case PT_DRIVE1:
123 case PT_DRIVE2:
124 case PT_DRIVE3:
125 /* return (LPSTR)&(pdata->u.drive.szDriveName);*/
126 return NULL;
127
128 case PT_FOLDER:
129 case PT_FOLDER1:
130 case PT_VALUE:
131 case PT_IESPECIAL1:
132 case PT_IESPECIAL2:
133 /* return (LPSTR)&(pdata->u.file.szNames); */
134 return NULL;
135
136 case PT_WORKGRP:
137 case PT_COMP:
138 case PT_NETWORK:
139 case PT_NETPROVIDER:
140 case PT_SHARE:
141 /* return (LPSTR)&(pdata->u.network.szNames); */
142 return NULL;
143 }
144 }
145 return NULL;
146 }
147
148
149 static
_dbg_ILGetSTextPointer(LPCITEMIDLIST pidl)150 LPSTR _dbg_ILGetSTextPointer(LPCITEMIDLIST pidl)
151 {
152 LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl);
153
154 if (pdata)
155 {
156 switch (pdata->type)
157 {
158 case PT_FOLDER:
159 case PT_VALUE:
160 case PT_IESPECIAL1:
161 case PT_IESPECIAL2:
162 return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1);
163
164 case PT_WORKGRP:
165 return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1);
166 }
167 }
168 return NULL;
169 }
170
171 static
_dbg_ILGetSTextPointerW(LPCITEMIDLIST pidl)172 LPWSTR _dbg_ILGetSTextPointerW(LPCITEMIDLIST pidl)
173 {
174 LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl);
175
176 if (pdata)
177 {
178 switch (pdata->type)
179 {
180 case PT_FOLDER:
181 case PT_VALUE:
182 case PT_IESPECIAL1:
183 case PT_IESPECIAL2:
184 /*return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1); */
185 return NULL;
186
187 case PT_WORKGRP:
188 /* return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1); */
189 return NULL;
190
191 case PT_VALUEW:
192 return (LPWSTR)(pdata->u.file.szNames + wcslen ((LPWSTR)pdata->u.file.szNames) + 1);
193 }
194 }
195 return NULL;
196 }
197
198
199 static
_dbg_ILGetGUIDPointer(LPCITEMIDLIST pidl)200 IID* _dbg_ILGetGUIDPointer(LPCITEMIDLIST pidl)
201 {
202 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
203
204 if (pdata)
205 {
206 switch (pdata->type)
207 {
208 case PT_SHELLEXT:
209 case PT_GUID:
210 case PT_YAGUID:
211 return &(pdata->u.guid.guid);
212 }
213 }
214 return NULL;
215 }
216
217 static
_dbg_ILSimpleGetText(LPCITEMIDLIST pidl,LPSTR szOut,UINT uOutSize)218 void _dbg_ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
219 {
220 LPSTR szSrc;
221 LPWSTR szSrcW;
222 GUID const * riid;
223
224 if (!pidl) return;
225
226 if (szOut)
227 *szOut = 0;
228
229 if (_dbg_ILIsDesktop(pidl))
230 {
231 /* desktop */
232 if (szOut) lstrcpynA(szOut, "Desktop", uOutSize);
233 }
234 else if (( szSrc = _dbg_ILGetTextPointer(pidl) ))
235 {
236 /* filesystem */
237 if (szOut) lstrcpynA(szOut, szSrc, uOutSize);
238 }
239 else if (( szSrcW = _dbg_ILGetTextPointerW(pidl) ))
240 {
241 CHAR tmp[MAX_PATH];
242 /* unicode filesystem */
243 WideCharToMultiByte(CP_ACP,0,szSrcW, -1, tmp, MAX_PATH, NULL, NULL);
244 if (szOut) lstrcpynA(szOut, tmp, uOutSize);
245 }
246 else if (( riid = _dbg_ILGetGUIDPointer(pidl) ))
247 {
248 if (szOut)
249 sprintf( szOut, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
250 riid->Data1, riid->Data2, riid->Data3,
251 riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
252 riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] );
253 }
254 }
255
256
257
258
pdump_impl(LPCITEMIDLIST pidl)259 static void pdump_impl (LPCITEMIDLIST pidl)
260 {
261 LPCITEMIDLIST pidltemp = pidl;
262
263
264 if (! pidltemp)
265 {
266 MESSAGE ("-------- pidl=NULL (Desktop)\n");
267 }
268 else
269 {
270 MESSAGE ("-------- pidl=%p\n", pidl);
271 if (pidltemp->mkid.cb)
272 {
273 do
274 {
275 if (_ILIsUnicode(pidltemp))
276 {
277 DWORD dwAttrib = 0;
278 LPPIDLDATA pData = _dbg_ILGetDataPointer(pidltemp);
279 DWORD type = pData ? pData->type : 0;
280 LPWSTR szLongName = _dbg_ILGetTextPointerW(pidltemp);
281 LPWSTR szShortName = _dbg_ILGetSTextPointerW(pidltemp);
282 char szName[MAX_PATH];
283
284 _dbg_ILSimpleGetText(pidltemp, szName, MAX_PATH);
285 if (_dbg_ILGetFSType(pidltemp))
286 dwAttrib = pData->u.file.uFileAttribs;
287
288 MESSAGE ("[%p] size=%04u type=%x attr=0x%08x name=%s (%s,%s)\n",
289 pidltemp, pidltemp->mkid.cb, type, dwAttrib,
290 debugstr_a(szName), debugstr_w(szLongName), debugstr_w(szShortName));
291 }
292 else
293 {
294 DWORD dwAttrib = 0;
295 LPPIDLDATA pData = _dbg_ILGetDataPointer(pidltemp);
296 DWORD type = pData ? pData->type : 0;
297 LPSTR szLongName = _dbg_ILGetTextPointer(pidltemp);
298 LPSTR szShortName = _dbg_ILGetSTextPointer(pidltemp);
299 char szName[MAX_PATH];
300
301 _dbg_ILSimpleGetText(pidltemp, szName, MAX_PATH);
302 if (_dbg_ILGetFSType(pidltemp))
303 dwAttrib = pData->u.file.uFileAttribs;
304
305 MESSAGE ("[%p] size=%04u type=%x attr=0x%08x name=%s (%s,%s)\n",
306 pidltemp, pidltemp->mkid.cb, type, dwAttrib,
307 debugstr_a(szName), debugstr_a(szLongName), debugstr_a(szShortName));
308 }
309
310 pidltemp = _dbg_ILGetNext(pidltemp);
311
312 } while (pidltemp && pidltemp->mkid.cb);
313 }
314 else
315 {
316 MESSAGE ("empty pidl (Desktop)\n");
317 }
318 pcheck(pidl);
319 }
320 }
321
pdump(LPCITEMIDLIST pidl)322 void pdump(LPCITEMIDLIST pidl)
323 {
324 if (!TRACE_ON(pidl)) return;
325
326 return pdump_impl(pidl);
327 }
328
329
pdump_always(LPCITEMIDLIST pidl)330 void pdump_always(LPCITEMIDLIST pidl)
331 {
332 pdump_impl(pidl);
333 }
334
335
dump_pidl_hex(LPCITEMIDLIST pidl)336 static void dump_pidl_hex( LPCITEMIDLIST pidl )
337 {
338 const unsigned char *p = (const unsigned char *)pidl;
339 const int max_bytes = 0x80;
340 #define max_line 0x10
341 char szHex[max_line*3+1], szAscii[max_line+1];
342 int i, n;
343
344 n = pidl->mkid.cb;
345 if( n>max_bytes )
346 n = max_bytes;
347 for( i=0; i<n; i++ )
348 {
349 sprintf( &szHex[ (i%max_line)*3 ], "%02X ", p[i] );
350 szAscii[ (i%max_line) ] = isprint( p[i] ) ? p[i] : '.';
351
352 /* print out at the end of each line and when we're finished */
353 if( i!=(n-1) && (i%max_line) != (max_line-1) )
354 continue;
355 szAscii[ (i%max_line)+1 ] = 0;
356 ERR("%-*s %s\n", max_line*3, szHex, szAscii );
357 }
358 }
359
pcheck(LPCITEMIDLIST pidl)360 BOOL pcheck( LPCITEMIDLIST pidl )
361 {
362 DWORD type;
363 LPCITEMIDLIST pidltemp = pidl;
364
365 while( pidltemp && pidltemp->mkid.cb )
366 {
367 LPPIDLDATA pidlData = _dbg_ILGetDataPointer(pidltemp);
368
369 if (pidlData)
370 {
371 type = pidlData->type;
372 switch( type )
373 {
374 case PT_CPLAPPLET:
375 case PT_GUID:
376 case PT_SHELLEXT:
377 case PT_DRIVE:
378 case PT_DRIVE1:
379 case PT_DRIVE2:
380 case PT_DRIVE3:
381 case PT_FOLDER:
382 case PT_VALUE:
383 case PT_VALUEW:
384 case PT_FOLDER1:
385 case PT_WORKGRP:
386 case PT_COMP:
387 case PT_NETPROVIDER:
388 case PT_NETWORK:
389 case PT_IESPECIAL1:
390 case PT_YAGUID:
391 case PT_IESPECIAL2:
392 case PT_SHARE:
393 break;
394 default:
395 ERR("unknown IDLIST %p [%p] size=%u type=%x\n",
396 pidl, pidltemp, pidltemp->mkid.cb,type );
397 dump_pidl_hex( pidltemp );
398 return FALSE;
399 }
400 pidltemp = _dbg_ILGetNext(pidltemp);
401 }
402 else
403 {
404 return FALSE;
405 }
406 }
407 return TRUE;
408 }
409
410 static const struct {
411 REFIID riid;
412 const char *name;
413 } InterfaceDesc[] = {
414 {IID_IUnknown, "IID_IUnknown"},
415 {IID_IClassFactory, "IID_IClassFactory"},
416 {IID_IShellView, "IID_IShellView"},
417 {IID_IOleCommandTarget, "IID_IOleCommandTarget"},
418 {IID_IDropTarget, "IID_IDropTarget"},
419 {IID_IDropSource, "IID_IDropSource"},
420 {IID_IViewObject, "IID_IViewObject"},
421 {IID_IContextMenu, "IID_IContextMenu"},
422 {IID_IShellExtInit, "IID_IShellExtInit"},
423 {IID_IShellFolder, "IID_IShellFolder"},
424 {IID_IShellFolder2, "IID_IShellFolder2"},
425 {IID_IPersist, "IID_IPersist"},
426 {IID_IPersistFolder, "IID_IPersistFolder"},
427 {IID_IPersistFolder2, "IID_IPersistFolder2"},
428 {IID_IPersistFolder3, "IID_IPersistFolder3"},
429 {IID_IExtractIconA, "IID_IExtractIconA"},
430 {IID_IExtractIconW, "IID_IExtractIconW"},
431 {IID_IDataObject, "IID_IDataObject"},
432 {IID_IAutoComplete, "IID_IAutoComplete"},
433 {IID_IAutoComplete2, "IID_IAutoComplete2"},
434 {IID_IShellLinkA, "IID_IShellLinkA"},
435 {IID_IShellLinkW, "IID_IShellLinkW"},
436 };
437
shdebugstr_guid(const struct _GUID * id)438 const char * shdebugstr_guid( const struct _GUID *id )
439 {
440 unsigned int i;
441 const char* name = NULL;
442 char clsidbuf[100];
443
444 if (!id) return "(null)";
445
446 for (i=0; i < sizeof(InterfaceDesc) / sizeof(InterfaceDesc[0]); i++) {
447 if (IsEqualIID(InterfaceDesc[i].riid, *id)) name = InterfaceDesc[i].name;
448 }
449 if (!name) {
450 if (HCR_GetClassNameA(*id, clsidbuf, 100))
451 name = clsidbuf;
452 }
453
454 return wine_dbg_sprintf( "\n\t{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} (%s)",
455 id->Data1, id->Data2, id->Data3,
456 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
457 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7], name ? name : "unknown" );
458 }
459