xref: /reactos/dll/win32/shell32/debughlp.cpp (revision 7d75bfb4)
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