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