Reactos
at master 458 lines 12 kB view raw
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 23WINE_DEFAULT_DEBUG_CHANNEL(pidl); 24 25static inline BYTE _dbg_ILGetType(LPCITEMIDLIST pidl) 26{ 27 return pidl && pidl->mkid.cb >= 3 ? pidl->mkid.abID[0] : 0; 28} 29 30static 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 36static 37LPITEMIDLIST _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 52static 53BOOL _dbg_ILIsDesktop(LPCITEMIDLIST pidl) 54{ 55 return ( !pidl || (pidl && pidl->mkid.cb == 0x00) ); 56} 57 58static 59LPPIDLDATA _dbg_ILGetDataPointer(LPCITEMIDLIST pidl) 60{ 61 if(pidl && pidl->mkid.cb != 0x00) 62 return (LPPIDLDATA) &(pidl->mkid.abID); 63 return NULL; 64} 65 66static 67LPSTR _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 104static 105LPWSTR _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 149static 150LPSTR _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 171static 172LPWSTR _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 199static 200IID* _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 217static 218void _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 259static 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 322void pdump(LPCITEMIDLIST pidl) 323{ 324 if (!TRACE_ON(pidl)) return; 325 326 return pdump_impl(pidl); 327} 328 329 330void pdump_always(LPCITEMIDLIST pidl) 331{ 332 pdump_impl(pidl); 333} 334 335 336static 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 360BOOL 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 410static 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 438const 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 (UINT)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}