Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

898 lines
23 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include "shguidp.h"
  4. #include "..\..\shell32\pidl.h"
  5. #include "..\..\shell32\shitemid.h"
  6. // We never want assertions since we are the debugger extension!
  7. #undef DBG
  8. #undef DEBUG
  9. #include "..\..\lib\idhidden.cpp"
  10. extern "C"
  11. {
  12. #include <stdexts.h>
  13. };
  14. UNALIGNED WCHAR * ualstrcpyW(UNALIGNED WCHAR * dst, UNALIGNED const WCHAR * src)
  15. {
  16. UNALIGNED WCHAR * cp = dst;
  17. while( *cp++ = *src++ )
  18. NULL ;
  19. return( dst );
  20. }
  21. ///////////////////////////////////////////////////////////////////////////////
  22. // Pidl Cracking function //
  23. // //
  24. // returns fSuccess //
  25. // //
  26. // History: //
  27. // 11/4/97 Created by cdturner //
  28. // //
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // NOTE: the options are autovalidate before they are passed to us
  31. typedef enum _PidlTypes
  32. {
  33. PIDL_UNKNOWN,
  34. PIDL_ROOT,
  35. PIDL_FILESYS,
  36. PIDL_DRIVES,
  37. PIDL_NET,
  38. PIDL_INTERNET,
  39. PIDL_FAVORITES
  40. } PIDLTYPE;
  41. #define PIDL_BUFFER_SIZE 400
  42. class CPidlBreaker
  43. {
  44. public:
  45. CPidlBreaker( LPVOID pArg );
  46. ~CPidlBreaker( );
  47. void SetVerbose() {_fVerbose = TRUE;};
  48. VOID SetType( PIDLTYPE eType );
  49. BOOL FillBuffer( DWORD cbSize, BOOL fAppend );
  50. VOID ResetBuffer( void );
  51. WORD FetchWord();
  52. DWORD FetchDWORD();
  53. LPBYTE GetBuffer( int iPos = 0);
  54. PIDLTYPE CrackType( BYTE bType );
  55. void PrintType( PIDLTYPE eType );
  56. BOOL PrintPidl();
  57. BOOL PrintRootPidl();
  58. BOOL PrintDrivePidl();
  59. BOOL PrintFileSysPidl();
  60. BOOL PrintInternetPidl();
  61. BOOL PrintNetworkPidl();
  62. BOOL GetSHIDFlags( BYTE bFlags, CHAR * pszBuffer, DWORD cbSize );
  63. void CLSIDToString( CHAR * pszBuffer, DWORD cbSize, REFCLSID rclsid );
  64. BOOL GetCLSIDText( const CHAR * pszCLSID, CHAR * pszBuffer, DWORD cbSize );
  65. private:
  66. PIDLTYPE _eType;
  67. LPVOID _pArg;
  68. BYTE _rgBuffer[PIDL_BUFFER_SIZE];
  69. int _iCurrent;
  70. int _iMax;
  71. BOOL _fVerbose;
  72. // used to display slashes right when we are not in verbose mode...
  73. BOOL _fSlash;
  74. };
  75. extern "C" BOOL Ipidl( DWORD dwOpts,
  76. LPVOID pArg )
  77. {
  78. PIDLTYPE eType = PIDL_UNKNOWN;
  79. CPidlBreaker Breaker( pArg );
  80. if ( dwOpts & OFLAG(r))
  81. {
  82. Breaker.SetType( PIDL_ROOT );
  83. }
  84. else if ( dwOpts & OFLAG(f))
  85. {
  86. Breaker.SetType( PIDL_FILESYS );
  87. }
  88. if (dwOpts & OFLAG(v))
  89. {
  90. Breaker.SetVerbose();
  91. }
  92. BOOL bRes = FALSE;
  93. __try
  94. {
  95. bRes = Breaker.PrintPidl();
  96. }
  97. __except( EXCEPTION_EXECUTE_HANDLER )
  98. {
  99. Print( "Exception caught in !pidl\n");
  100. }
  101. if ( !(dwOpts & OFLAG(v)) )
  102. Print( "\n" );
  103. return bRes;
  104. }
  105. VOID CPidlBreaker::SetType( PIDLTYPE eType )
  106. {
  107. _eType = eType;
  108. }
  109. CPidlBreaker::CPidlBreaker( LPVOID pArg )
  110. {
  111. _pArg = pArg;
  112. _iCurrent = 0;
  113. _iMax = 0;
  114. _eType = PIDL_UNKNOWN;
  115. _fVerbose = FALSE;
  116. _fSlash = FALSE;
  117. }
  118. CPidlBreaker::~CPidlBreaker( )
  119. {
  120. }
  121. BOOL CPidlBreaker::FillBuffer( DWORD cbSize, BOOL fAppend )
  122. {
  123. if ( !fAppend )
  124. {
  125. _iCurrent = 0;
  126. _iMax = 0;
  127. }
  128. int iStart = fAppend ? _iMax : 0;
  129. if ( cbSize + iStart > PIDL_BUFFER_SIZE )
  130. {
  131. return FALSE;
  132. }
  133. #ifdef DEBUG
  134. char szBuffer[50];
  135. sprintf( szBuffer, "****Moving %d from %8X\n", cbSize, _pArg );
  136. Print( szBuffer );
  137. #endif
  138. if ( tryMoveBlock( _rgBuffer + iStart, _pArg, cbSize ))
  139. {
  140. #ifdef DEBUG
  141. for ( int iByte = 0; iByte < (int) cbSize; iByte ++ )
  142. {
  143. sprintf( szBuffer, "Byte %2x\n", _rgBuffer[iByte + iStart] );
  144. Print( szBuffer );
  145. }
  146. #endif
  147. _pArg = (LPBYTE) _pArg + cbSize;
  148. _iMax += cbSize;
  149. return TRUE;
  150. }
  151. else
  152. {
  153. return FALSE;
  154. }
  155. }
  156. WORD CPidlBreaker::FetchWord()
  157. {
  158. // assume that the buffer has been filled...
  159. if ( _iCurrent + 1 >= _iMax )
  160. {
  161. return 0;
  162. }
  163. WORD wRet = MAKEWORD( _rgBuffer[_iCurrent], _rgBuffer[_iCurrent + 1]);
  164. _iCurrent += 2;
  165. #ifdef DEBUG
  166. char szBuffer[200];
  167. sprintf( szBuffer, "FetchWord() == %4X\n", wRet );
  168. Print( szBuffer );
  169. #endif
  170. return wRet;
  171. }
  172. DWORD CPidlBreaker::FetchDWORD()
  173. {
  174. // assume that the buffer has been filled...
  175. if ( _iCurrent + 3 >= _iMax )
  176. {
  177. return 0;
  178. }
  179. DWORD dwRet = MAKELONG( MAKEWORD( _rgBuffer[_iCurrent], _rgBuffer[_iCurrent + 1]),
  180. MAKEWORD( _rgBuffer[_iCurrent + 2], _rgBuffer[_iCurrent + 3] ));
  181. _iCurrent += 4;
  182. #ifdef DEBUG
  183. char szBuffer[200];
  184. sprintf( szBuffer, "FetchDWord() == %8X\n", dwRet );
  185. Print( szBuffer );
  186. #endif
  187. return dwRet;
  188. }
  189. LPBYTE CPidlBreaker::GetBuffer(int iPos)
  190. {
  191. return _rgBuffer + _iCurrent + iPos;
  192. }
  193. VOID CPidlBreaker::ResetBuffer( )
  194. {
  195. _iCurrent = 0;
  196. _iMax = 0;
  197. }
  198. BOOL CPidlBreaker::PrintRootPidl()
  199. {
  200. CHAR szBuffer[200];
  201. if ( !FillBuffer( sizeof( WORD ), FALSE ))
  202. {
  203. Print( "ERROR Unable to get the pidl size\n");
  204. return FALSE;
  205. }
  206. // get the size of the first chunk
  207. WORD wSize = FetchWord();
  208. // root pidls always have the size field as 14
  209. if ( wSize != sizeof( IDREGITEM ))
  210. {
  211. sprintf( szBuffer, "Pidl Size %d seems bogus for a regitem\n", wSize );
  212. Print( szBuffer );
  213. return FALSE;
  214. }
  215. else
  216. {
  217. if ( !FillBuffer( wSize - sizeof(WORD) , TRUE ))
  218. {
  219. sprintf( szBuffer, "Error: unable to access the data for the pidl of size %d\n", wSize );
  220. Print( szBuffer );
  221. return FALSE;
  222. }
  223. LPBYTE pBuf = GetBuffer(- ((int) sizeof(WORD)));
  224. char szBuffer2[200];
  225. if ( pBuf[2] != SHID_ROOT_REGITEM )
  226. {
  227. Print( "Pidl has incorrect flags, should have SHID_ROOT_REGITEM\n");
  228. }
  229. // now map it to a Root structure
  230. LPIDREGITEM pRegItem = (LPIDREGITEM) pBuf;
  231. GetSHIDFlags( pRegItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2 ));
  232. Print( "RegItem Pidl:\n");
  233. if ( _fVerbose )
  234. {
  235. sprintf( szBuffer, " bFlags = %d (%s)\n", pRegItem->bFlags, szBuffer2 );
  236. Print( szBuffer );
  237. sprintf( szBuffer, " bOrder = %d\n", pRegItem->bOrder );
  238. Print( szBuffer );
  239. }
  240. CHAR szCLSID[40];
  241. CLSIDToString( szCLSID, ARRAYSIZE( szCLSID ), pRegItem->clsid );
  242. sprintf( szBuffer, " CLSID = %s ", szCLSID );
  243. Print( szBuffer );
  244. if ( GetCLSIDText( szCLSID, szBuffer2 + 1, ARRAYSIZE( szBuffer2 ) -2))
  245. {
  246. szBuffer2[0] = '(';
  247. lstrcatA( szBuffer2, ")\n" );
  248. Print( szBuffer2 );
  249. }
  250. if ( _fVerbose )
  251. Print( "\n" );
  252. ResetBuffer();
  253. if ( pRegItem->clsid == CLSID_ShellNetwork )
  254. {
  255. PrintNetworkPidl();
  256. }
  257. else if ( pRegItem->clsid == CLSID_ShellInetRoot )
  258. {
  259. // internet root
  260. PrintInternetPidl();
  261. }
  262. else if ( pRegItem->clsid == CLSID_ShellDrives )
  263. {
  264. // file system pidls ...
  265. PrintDrivePidl();
  266. }
  267. else
  268. {
  269. // unknown pidl type ....
  270. Print( "unknown pidl type, can't crack any further\n");
  271. }
  272. }
  273. return TRUE;
  274. }
  275. void _SprintDosDateTime(LPSTR szBuffer, LPCSTR pszType, WORD wDate, WORD wTime)
  276. {
  277. sprintf( szBuffer, " date/time %s = 0x%04x/%04x = %04d/%02d/%02d %02d:%02d:%02d\n",
  278. pszType,
  279. wDate, wTime,
  280. ((wDate & 0xFE00) >> 9)+1980,
  281. (wDate & 0x01E0) >> 5,
  282. (wDate & 0x001F) >> 0,
  283. (wTime & 0xF800) >> 11,
  284. (wTime & 0x07E0) >> 5,
  285. (wTime & 0x001F) << 1 );
  286. }
  287. BOOL CPidlBreaker::PrintFileSysPidl()
  288. {
  289. CHAR szBuffer[200];
  290. CHAR szBuffer2[200];
  291. if ( !FillBuffer( sizeof( WORD ), FALSE ))
  292. {
  293. Print( "ERROR Unable to get the pidl size\n");
  294. return FALSE;
  295. }
  296. // get the size of the first chunk
  297. WORD wSize = FetchWord();
  298. if ( wSize == 0 )
  299. {
  300. // end of the pidl chain....
  301. return TRUE;
  302. }
  303. if ( !FillBuffer( wSize - sizeof(WORD) , TRUE ))
  304. {
  305. sprintf( szBuffer, "Error: unable to access the data for the pidl of size %d\n", wSize );
  306. Print( szBuffer );
  307. return FALSE;
  308. }
  309. LPBYTE pBuf = GetBuffer(- ((int)sizeof(WORD)));
  310. if (( pBuf[2] & SHID_FS ) != SHID_FS )
  311. {
  312. sprintf( szBuffer, "Error, Unknown Pidl flag, use !db %8X\n", (DWORD_PTR) _pArg - wSize);
  313. Print( szBuffer );
  314. return FALSE;
  315. }
  316. if ((( pBuf[2] & SHID_FS_UNICODE ) == SHID_FS_UNICODE ) && wSize > sizeof( IDFOLDER ) )
  317. {
  318. sprintf( szBuffer, "Error, size to big for a UNICODE FileSys Pidl, use !db %8X\n", (DWORD_PTR) _pArg - wSize);
  319. Print( szBuffer );
  320. return FALSE;
  321. }
  322. if ((( pBuf[2] & SHID_FS_UNICODE) != SHID_FS_UNICODE ) && wSize > sizeof( IDFOLDER ))
  323. {
  324. sprintf( szBuffer, "Error, size to big for a ANSI FileSys Pidl, use !db %8X\n", (DWORD_PTR) _pArg - wSize);
  325. Print( szBuffer );
  326. return FALSE;
  327. }
  328. if ( _fVerbose )
  329. Print("FileSystem pidl:\n");
  330. LPIDFOLDER pItem = (LPIDFOLDER) pBuf;
  331. if ( _fVerbose )
  332. {
  333. GetSHIDFlags( pItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2));
  334. sprintf( szBuffer, " bFlags = %d (%s)\n", pItem->bFlags, szBuffer2 );
  335. Print( szBuffer );
  336. sprintf( szBuffer, " dwSize = %d,\tattrs = 0x%X\n", pItem->dwSize, pItem->wAttrs );
  337. Print( szBuffer );
  338. _SprintDosDateTime(szBuffer, "modified", pItem->dateModified, pItem->timeModified);
  339. Print( szBuffer );
  340. }
  341. BOOL fPathShown = FALSE;
  342. PIDFOLDEREX pidlx = (PIDFOLDEREX)ILFindHiddenIDOn((LPITEMIDLIST)pBuf, IDLHID_IDFOLDEREX, FALSE);
  343. if (pidlx && pidlx->hid.cb >= sizeof(IDFOLDEREX))
  344. {
  345. LPBYTE pbMax = pBuf + wSize;
  346. if (_fVerbose)
  347. {
  348. _SprintDosDateTime(szBuffer, "created", pidlx->dsCreate.wDate, pidlx->dsCreate.wTime);
  349. Print(szBuffer);
  350. _SprintDosDateTime(szBuffer, "accessed", pidlx->dsAccess.wDate, pidlx->dsAccess.wTime);
  351. Print(szBuffer);
  352. if (pidlx->offResourceA)
  353. {
  354. LPSTR pszResourceA = (LPSTR)pidlx + pidlx->offResourceA;
  355. if ((LPBYTE)pszResourceA < pbMax)
  356. {
  357. Print(" MUI = ");
  358. Print(pszResourceA);
  359. Print("\n");
  360. }
  361. }
  362. }
  363. // Do a "cheap" UnicodeToAnsi because
  364. //
  365. // 1. There's really no point in getting it right, since there
  366. // is no guarantee that the debugger is running the same
  367. // codepage as the app, and...
  368. // 2. The string is unaligned so we have to walk it manually anyway.
  369. //
  370. if (pidlx->offNameW)
  371. {
  372. LPBYTE pbName = (LPBYTE)pidlx + pidlx->offNameW;
  373. int i = 0;
  374. while (pbName < pbMax && *pbName && i < ARRAYSIZE(szBuffer2) - 1)
  375. {
  376. szBuffer2[i++] = *pbName;
  377. pbName += 2;
  378. }
  379. szBuffer2[i] = TEXT('\0');
  380. }
  381. if (_fVerbose)
  382. {
  383. Print(" NameW = ");
  384. Print(szBuffer2);
  385. Print("\n");
  386. }
  387. else
  388. {
  389. fPathShown = TRUE;
  390. if ( !_fSlash )
  391. Print( "\\" );
  392. Print( szBuffer2 );
  393. }
  394. }
  395. if (( pItem->bFlags & SHID_FS_UNICODE ) == SHID_FS_UNICODE )
  396. {
  397. WCHAR szTemp[MAX_PATH];
  398. ualstrcpyW( szTemp, (LPCWSTR)pItem->cFileName );
  399. WideCharToMultiByte( CP_ACP, 0, szTemp, -1, szBuffer2, ARRAYSIZE( szBuffer2 ),0 ,0 );
  400. if ( _fVerbose )
  401. {
  402. sprintf( szBuffer, " cFileName = %s\n", szBuffer2 );
  403. Print( szBuffer );
  404. }
  405. else if (!fPathShown)
  406. {
  407. fPathShown = TRUE;
  408. if ( !_fSlash )
  409. Print( "\\" );
  410. Print( szBuffer2 );
  411. }
  412. }
  413. else
  414. {
  415. // assume to be ansi ...
  416. if ( _fVerbose )
  417. {
  418. sprintf( szBuffer, " cFileName = %s\n", pItem->cFileName);
  419. Print( szBuffer );
  420. }
  421. else if (!fPathShown)
  422. {
  423. fPathShown = TRUE;
  424. if ( !_fSlash )
  425. Print( "\\" );
  426. Print( pItem->cFileName );
  427. }
  428. if ( _fVerbose )
  429. {
  430. int cLen = lstrlenA( pItem->cFileName);
  431. sprintf( szBuffer, " cAltName = %s\n", pItem->cFileName + cLen + 1);
  432. Print( szBuffer );
  433. }
  434. }
  435. if ( pItem->bFlags & SHID_JUNCTION )
  436. {
  437. // it is a junction point, so the CLASSID is tagged on the end
  438. /*[TODO]*/
  439. }
  440. _fSlash = FALSE;
  441. ResetBuffer();
  442. PrintFileSysPidl();
  443. return TRUE;
  444. }
  445. BOOL CPidlBreaker::PrintPidl()
  446. {
  447. if ( _eType == PIDL_UNKNOWN )
  448. {
  449. LPVOID pPrevArg = _pArg;
  450. // check the 3rd byte in, it might be a SHID value...
  451. if ( !FillBuffer(3, FALSE ))
  452. {
  453. Print( "Unable to access the memory\n");
  454. return FALSE;
  455. }
  456. LPBYTE pBuf = GetBuffer();
  457. _eType = CrackType( pBuf[2] );
  458. ResetBuffer();
  459. _pArg = pPrevArg;
  460. }
  461. PrintType( _eType );
  462. return TRUE;
  463. }
  464. BOOL CPidlBreaker::PrintInternetPidl()
  465. {
  466. return TRUE;
  467. }
  468. BOOL CPidlBreaker::PrintNetworkPidl()
  469. {
  470. return TRUE;
  471. }
  472. BOOL CPidlBreaker::PrintDrivePidl()
  473. {
  474. CHAR szBuffer[200];
  475. CHAR szBuffer2[200];
  476. if ( !FillBuffer( sizeof( WORD ), FALSE ))
  477. {
  478. Print( "ERROR Unable to get the pidl size\n");
  479. return FALSE;
  480. }
  481. // get the size of the first chunk
  482. WORD wSize = FetchWord();
  483. if ( wSize == 0 )
  484. {
  485. return TRUE;
  486. }
  487. if ( !FillBuffer( wSize - sizeof(WORD) , TRUE ))
  488. {
  489. sprintf( szBuffer, "Error: unable to access the data for the pidl of size %d\n", wSize );
  490. Print( szBuffer );
  491. return FALSE;
  492. }
  493. LPBYTE pBuf = GetBuffer(- ((int)sizeof(WORD)));
  494. // need to check to see if it is an IDDrive structure or a regitem ....
  495. if ( wSize == sizeof( IDDRIVE ) || wSize == FIELD_OFFSET(IDDRIVE, clsid) )
  496. {
  497. // must be a drive structure....
  498. if ( _fVerbose )
  499. Print( "(My Computer) Drives Pidl:\n");
  500. else
  501. Print( "Path = ");
  502. LPIDDRIVE pDriveItem = (LPIDDRIVE) pBuf;
  503. if ( _fVerbose )
  504. {
  505. GetSHIDFlags( pDriveItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2 ));
  506. sprintf( szBuffer, " bFlags = %d (%s)\n", pDriveItem->bFlags, szBuffer2 );
  507. Print( szBuffer );
  508. sprintf( szBuffer, " cName = %s\n", pDriveItem->cName );
  509. Print( szBuffer );
  510. sprintf( szBuffer, " qwSize = 0x%lX\tqwFree = 0x%lX\n", pDriveItem->qwSize, pDriveItem->qwFree );
  511. Print( szBuffer );
  512. sprintf( szBuffer, " wSig = 0x%X\n\n", pDriveItem->wSig);
  513. Print( szBuffer );
  514. if ( wSize == sizeof( IDDRIVE ) )
  515. {
  516. CHAR szCLSID[40];
  517. CLSIDToString( szCLSID, ARRAYSIZE( szCLSID ), pDriveItem->clsid );
  518. sprintf( szBuffer, " CLSID = %s ", szCLSID );
  519. Print( szBuffer );
  520. }
  521. }
  522. else
  523. Print( pDriveItem->cName );
  524. // coming from a drive, we already have a slash at the start
  525. _fSlash = TRUE;
  526. // assume the next pidl is a standard file-sys one...
  527. PrintFileSysPidl();
  528. }
  529. else if ( wSize == sizeof( IDREGITEM ))
  530. {
  531. // must be a reg item like control panel or printers...
  532. Print( "Drives (My Computer) RegItem Pidl\n");
  533. if ( pBuf[2] != SHID_COMPUTER_REGITEM )
  534. {
  535. Print( "Pidl has incorrect flags, should have SHID_ROOT_REGITEM\n");
  536. }
  537. // now map it to a Root structure
  538. LPIDREGITEM pRegItem = (LPIDREGITEM) pBuf;
  539. GetSHIDFlags( pRegItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2 ));
  540. Print( "RegItem Pidl:\n");
  541. if ( _fVerbose )
  542. {
  543. sprintf( szBuffer, " bFlags = %d (%s)\n", pRegItem->bFlags, szBuffer2 );
  544. Print( szBuffer );
  545. sprintf( szBuffer, " bOrder = %d\n", pRegItem->bOrder );
  546. Print( szBuffer );
  547. }
  548. CHAR szCLSID[40];
  549. CLSIDToString( szCLSID, ARRAYSIZE( szCLSID ), pRegItem->clsid );
  550. sprintf( szBuffer, " CLSID = %s ", szCLSID );
  551. Print( szBuffer );
  552. if ( GetCLSIDText( szCLSID, szBuffer2 + 1, ARRAYSIZE( szBuffer2 ) -2))
  553. {
  554. szBuffer2[0] = '(';
  555. lstrcatA( szBuffer2, ")\n" );
  556. Print( szBuffer2 );
  557. }
  558. ResetBuffer();
  559. LPVOID _pPrevArg = _pArg;
  560. if ( !FillBuffer( sizeof( WORD ), FALSE ))
  561. {
  562. Print( "Error unable to access next pidl section\n");
  563. }
  564. if ( FetchWord() != 0 )
  565. {
  566. // unknown hierarchy pidl type
  567. sprintf( szBuffer, "Unknown Pidl Type contents, use !db %8X\n", (DWORD_PTR) _pPrevArg );
  568. }
  569. _pArg = _pPrevArg;
  570. }
  571. else
  572. {
  573. Print( "Unknown Drives pidl type\n");
  574. return FALSE;
  575. }
  576. return TRUE;
  577. }
  578. PIDLTYPE CPidlBreaker::CrackType( BYTE bType )
  579. {
  580. PIDLTYPE eType = PIDL_UNKNOWN;
  581. switch( bType & 0xf0 )
  582. {
  583. case SHID_ROOT:
  584. eType = PIDL_ROOT;
  585. break;
  586. case SHID_COMPUTER:
  587. eType = PIDL_DRIVES;
  588. break;
  589. case SHID_FS:
  590. eType = PIDL_FILESYS;
  591. break;
  592. case SHID_NET:
  593. eType = PIDL_NET;
  594. break;
  595. case 0x60: // SHID_INTERNET
  596. eType = PIDL_INTERNET;
  597. break;
  598. }
  599. return eType;
  600. }
  601. void CPidlBreaker::PrintType( PIDLTYPE eType )
  602. {
  603. switch( eType )
  604. {
  605. case PIDL_ROOT:
  606. PrintRootPidl();
  607. break;
  608. case PIDL_FILESYS:
  609. PrintFileSysPidl();
  610. break;
  611. case PIDL_DRIVES:
  612. PrintDrivePidl();
  613. break;
  614. case PIDL_NET:
  615. case PIDL_INTERNET:
  616. default:
  617. Print( "Unknown Pidl Type\n");
  618. break;
  619. }
  620. }
  621. typedef struct _tagSHIDs
  622. {
  623. BYTE bFlag;
  624. LPCSTR pszText;
  625. } SHIDFLAGS;
  626. SHIDFLAGS g_argSHID[] =
  627. {
  628. {SHID_ROOT, "SHID_ROOT" },
  629. {SHID_ROOT_REGITEM, "SHID_ROOT_REGITEM"},
  630. {SHID_COMPUTER, "SHID_COMPUTER"},
  631. {SHID_COMPUTER_1, "SHID_COMPUTER_1"},
  632. {SHID_COMPUTER_REMOVABLE, "SHID_COMPUTER_REMOVABLE"},
  633. {SHID_COMPUTER_FIXED, "SHID_COMPUTER_FIXED"},
  634. {SHID_COMPUTER_REMOTE, "SHID_COMPUTER_REMOTE"},
  635. {SHID_COMPUTER_CDROM, "SHID_COMPUTER_CDROM"},
  636. {SHID_COMPUTER_RAMDISK, "SHID_COMPUTER_RAMDISK"},
  637. {SHID_COMPUTER_7, "SHID_COMPUTER_7"},
  638. {SHID_COMPUTER_DRIVE525, "SHID_COMPUTER_DRIVE525"},
  639. {SHID_COMPUTER_DRIVE35, "SHID_COMPUTER_DRIVE35"},
  640. {SHID_COMPUTER_NETDRIVE, "SHID_COMPUTER_NETDRIVE"},
  641. {SHID_COMPUTER_NETUNAVAIL, "SHID_COMPUTER_NETUNAVAIL"},
  642. {SHID_COMPUTER_C, "SHID_COMPUTER_C"},
  643. {SHID_COMPUTER_D, "SHID_COMPUTER_D"},
  644. {SHID_COMPUTER_REGITEM, "SHID_COMPUTER_REGITEM"},
  645. {SHID_COMPUTER_MISC, "SHID_COMPUTER_MISC"},
  646. {SHID_FS, "SHID_FS"},
  647. {SHID_FS_TYPEMASK, "SHID_FS_TYPEMASK"},
  648. {SHID_FS_DIRECTORY, "SHID_FS_DIRECTORY"},
  649. {SHID_FS_FILE, "SHID_FS_FILE"},
  650. {SHID_FS_UNICODE, "SHID_FS_UNICODE"},
  651. {SHID_FS_DIRUNICODE, "SHID_FS_DIRUNICODE"},
  652. {SHID_FS_FILEUNICODE, "SHID_FS_FILEUNICODE"},
  653. {SHID_NET, "SHID_NET"},
  654. {SHID_NET_DOMAIN, "SHID_NET_DOMAIN"},
  655. {SHID_NET_SERVER, "SHID_NET_SERVER"},
  656. {SHID_NET_SHARE, "SHID_NET_SHARE"},
  657. {SHID_NET_FILE, "SHID_NET_FILE"},
  658. {SHID_NET_GROUP, "SHID_NET_GROUP"},
  659. {SHID_NET_NETWORK, "SHID_NET_NETWORK"},
  660. {SHID_NET_RESTOFNET, "SHID_NET_RESTOFNET"},
  661. {SHID_NET_SHAREADMIN, "SHID_NET_SHAREADMIN"},
  662. {SHID_NET_DIRECTORY, "SHID_NET_DIRECTORY"},
  663. {SHID_NET_TREE, "SHID_NET_TREE"},
  664. {SHID_NET_REGITEM, "SHID_NET_REGITEM"},
  665. {SHID_NET_PRINTER, "SHID_NET_PRINTER"}
  666. };
  667. BOOL CPidlBreaker::GetSHIDFlags( BYTE bFlags, CHAR * pszBuffer, DWORD cbSize )
  668. {
  669. LPCSTR pszText = NULL;
  670. for ( int iFlag = 0; iFlag < ARRAYSIZE( g_argSHID ); iFlag ++ )
  671. {
  672. if ( g_argSHID[iFlag].bFlag == ( bFlags & SHID_TYPEMASK ))
  673. {
  674. pszText = g_argSHID[iFlag].pszText;
  675. break;
  676. }
  677. }
  678. if ( pszText == NULL )
  679. {
  680. sprintf( pszBuffer, "unknown SHID value %2X", bFlags );
  681. return FALSE;
  682. }
  683. else
  684. {
  685. lstrcpyA( pszBuffer, pszText );
  686. }
  687. if (bFlags & SHID_JUNCTION)
  688. {
  689. lstrcatA(pszBuffer, " | SHID_JUNCTION");
  690. }
  691. return TRUE;
  692. }
  693. void CPidlBreaker::CLSIDToString( CHAR * pszBuffer, DWORD cbSize, REFCLSID rclsid )
  694. {
  695. WCHAR szBuffer[40];
  696. StringFromGUID2( rclsid, szBuffer, ARRAYSIZE( szBuffer ));
  697. WideCharToMultiByte( CP_ACP, 0, szBuffer, -1, pszBuffer, cbSize, 0, 0 );
  698. }
  699. //
  700. // Some CLSIDs have "known" names which are used if there is no custom name
  701. // in the registry.
  702. //
  703. typedef struct KNOWNCLSIDS
  704. {
  705. LPCSTR pszCLSID;
  706. LPCSTR pszName;
  707. } KNOWNCLSIDS;
  708. const KNOWNCLSIDS c_kcKnown[] = {
  709. { "{20D04FE0-3AEA-1069-A2D8-08002B30309D}", "My Computer" },
  710. { "{21EC2020-3AEA-1069-A2DD-08002B30309D}", "Control Panel" },
  711. { "{645FF040-5081-101B-9F08-00AA002F954E}", "Recycle Bin" },
  712. { "{450D8FBA-AD25-11D0-98A8-0800361B1103}", "My Documents" },
  713. { "{871C5380-42A0-1069-A2EA-08002B30309D}", "The Internet" },
  714. };
  715. BOOL CPidlBreaker::GetCLSIDText( const CHAR * pszCLSID, CHAR * pszBuffer, DWORD cbSize )
  716. {
  717. int i;
  718. for (i = 0; i < ARRAYSIZE(c_kcKnown); i++)
  719. {
  720. if (lstrcmpiA(c_kcKnown[i].pszCLSID, pszCLSID) == 0)
  721. {
  722. lstrcpynA(pszBuffer, c_kcKnown[i].pszName, cbSize);
  723. return TRUE;
  724. }
  725. }
  726. HKEY hKey;
  727. LONG lRes = RegOpenKeyA( HKEY_CLASSES_ROOT, "CLSID", &hKey );
  728. if ( ERROR_SUCCESS == lRes )
  729. {
  730. LONG lSize = cbSize;
  731. lRes = RegQueryValueA( hKey, pszCLSID, pszBuffer, &lSize );
  732. return ( ERROR_SUCCESS == lRes );
  733. }
  734. return FALSE;
  735. }