Leaked source code of windows server 2003
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.

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