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.

595 lines
12 KiB

  1. #include "stdafx.h"
  2. #include "imgutil.h"
  3. #include "cmimeid.h"
  4. static CRITICAL_SECTION g_csMIMEIdentifier;
  5. static CMIMEIdentifier* g_pMIMEIdentifier = NULL;
  6. void InitMIMEIdentifier()
  7. {
  8. InitializeCriticalSection( &g_csMIMEIdentifier );
  9. }
  10. void CleanupMIMEIdentifier()
  11. {
  12. DeleteCriticalSection(&g_csMIMEIdentifier);
  13. }
  14. STDAPI GetMaxMIMEIDBytes( ULONG* pnMaxBytes )
  15. {
  16. HRESULT hResult;
  17. if( pnMaxBytes != NULL )
  18. {
  19. *pnMaxBytes = 0;
  20. }
  21. if( pnMaxBytes == NULL )
  22. {
  23. return( E_POINTER );
  24. }
  25. EnterCriticalSection( &g_csMIMEIdentifier );
  26. if( g_pMIMEIdentifier == NULL )
  27. {
  28. g_pMIMEIdentifier = new CMIMEIdentifier;
  29. hResult = g_pMIMEIdentifier->InitFromRegistry();
  30. if( FAILED( hResult ) )
  31. {
  32. delete g_pMIMEIdentifier;
  33. g_pMIMEIdentifier = NULL;
  34. LeaveCriticalSection( &g_csMIMEIdentifier );
  35. return( hResult );
  36. }
  37. }
  38. *pnMaxBytes = g_pMIMEIdentifier->GetMaxBytes();
  39. LeaveCriticalSection( &g_csMIMEIdentifier );
  40. return( S_OK );
  41. }
  42. STDAPI IdentifyMIMEType( const BYTE* pbBytes, ULONG nBytes,
  43. UINT* pnFormat )
  44. {
  45. HRESULT hResult;
  46. if( pnFormat != NULL )
  47. {
  48. *pnFormat = 0;
  49. }
  50. if( pbBytes == NULL )
  51. {
  52. return( E_INVALIDARG );
  53. }
  54. if( pnFormat == NULL )
  55. {
  56. return( E_POINTER );
  57. }
  58. EnterCriticalSection( &g_csMIMEIdentifier );
  59. if( g_pMIMEIdentifier == NULL )
  60. {
  61. g_pMIMEIdentifier = new CMIMEIdentifier;
  62. hResult = g_pMIMEIdentifier->InitFromRegistry();
  63. if( FAILED( hResult ) )
  64. {
  65. delete g_pMIMEIdentifier;
  66. g_pMIMEIdentifier = NULL;
  67. LeaveCriticalSection( &g_csMIMEIdentifier );
  68. return( hResult );
  69. }
  70. }
  71. hResult = g_pMIMEIdentifier->Identify( pbBytes, nBytes, pnFormat );
  72. LeaveCriticalSection( &g_csMIMEIdentifier );
  73. return( hResult );
  74. }
  75. STDAPI SniffStream( IStream* pInStream, UINT* pnFormat,
  76. IStream** ppOutStream )
  77. {
  78. HRESULT hResult;
  79. HRESULT hIDResult;
  80. CComPtr< ISniffStream > pSniffStream;
  81. if( pnFormat != NULL )
  82. {
  83. *pnFormat = 0;
  84. }
  85. if( ppOutStream != NULL )
  86. {
  87. *ppOutStream = NULL;
  88. }
  89. if( pInStream == NULL )
  90. {
  91. return( E_INVALIDARG );
  92. }
  93. if( pnFormat == NULL )
  94. {
  95. return( E_POINTER );
  96. }
  97. if( ppOutStream == NULL )
  98. {
  99. return( E_POINTER );
  100. }
  101. hResult = pInStream->QueryInterface( IID_ISniffStream,
  102. (void**)&pSniffStream );
  103. if( FAILED( hResult ) && (hResult != E_NOINTERFACE) )
  104. {
  105. return( hResult );
  106. }
  107. if( hResult == E_NOINTERFACE )
  108. {
  109. hResult = CoCreateInstance( CLSID_CoSniffStream, NULL,
  110. CLSCTX_INPROC_SERVER, IID_ISniffStream, (void**)&pSniffStream );
  111. if( FAILED( hResult ) )
  112. {
  113. return( hResult );
  114. }
  115. hResult = pSniffStream->Init( pInStream );
  116. if( FAILED( hResult ) )
  117. {
  118. return( hResult );
  119. }
  120. }
  121. EnterCriticalSection( &g_csMIMEIdentifier );
  122. if( g_pMIMEIdentifier == NULL )
  123. {
  124. g_pMIMEIdentifier = new CMIMEIdentifier;
  125. hResult = g_pMIMEIdentifier->InitFromRegistry();
  126. if( FAILED( hResult ) )
  127. {
  128. delete g_pMIMEIdentifier;
  129. g_pMIMEIdentifier = NULL;
  130. LeaveCriticalSection( &g_csMIMEIdentifier );
  131. return( hResult );
  132. }
  133. }
  134. hIDResult = g_pMIMEIdentifier->IdentifyStream( pSniffStream, pnFormat );
  135. LeaveCriticalSection( &g_csMIMEIdentifier );
  136. if( FAILED( hIDResult ) )
  137. {
  138. return( hIDResult );
  139. }
  140. hResult = pSniffStream->QueryInterface( IID_IStream, (void**)ppOutStream );
  141. if( FAILED( hResult ) )
  142. {
  143. return( hResult );
  144. }
  145. return( hIDResult );
  146. }
  147. const LPCTSTR MIME_DATABASE_ROOT = _T( "MIME\\Database\\Content Type" );
  148. CMIMEBitMatcher::CMIMEBitMatcher() :
  149. m_pNext( NULL ),
  150. m_nOffset( 0 ),
  151. m_nBytes( 0 ),
  152. m_pMask( NULL ),
  153. m_pData( NULL )
  154. {
  155. memcpy( m_achSignature, "NoLK", 4 );
  156. }
  157. CMIMEBitMatcher::~CMIMEBitMatcher()
  158. {
  159. delete m_pMask;
  160. delete m_pData;
  161. }
  162. HRESULT CMIMEBitMatcher::InitFromBinary( const BYTE* pData, ULONG nBytes,
  163. ULONG* pnBytesToMatch )
  164. {
  165. const BYTE* pTrav;
  166. #ifdef BIG_ENDIAN
  167. BYTE pTravBig[4];
  168. #endif
  169. _ASSERTE( pData != NULL );
  170. _ASSERTE( pnBytesToMatch != NULL );
  171. if( nBytes <= sizeof( ULONG ) )
  172. {
  173. return( E_FAIL );
  174. }
  175. pTrav = pData;
  176. #ifdef BIG_ENDIAN
  177. pTravBig[0] = pTrav[3];
  178. pTravBig[1] = pTrav[2];
  179. pTravBig[2] = pTrav[1];
  180. pTravBig[3] = pTrav[0];
  181. m_nBytes = *(ULONG*)pTravBig;
  182. #else
  183. m_nBytes = *(const ULONG*)(pTrav);
  184. #endif
  185. pTrav += sizeof( ULONG );
  186. if( nBytes != (2*m_nBytes)+sizeof( ULONG ) )
  187. {
  188. return( E_FAIL );
  189. }
  190. m_pMask = new BYTE[m_nBytes];
  191. if( m_pMask == NULL )
  192. {
  193. return( E_OUTOFMEMORY );
  194. }
  195. m_pData = new BYTE[m_nBytes];
  196. if( m_pData == NULL )
  197. {
  198. return( E_OUTOFMEMORY );
  199. }
  200. memcpy( m_pMask, pTrav, m_nBytes );
  201. pTrav += m_nBytes;
  202. memcpy( m_pData, pTrav, m_nBytes );
  203. *pnBytesToMatch = m_nBytes;
  204. return( S_OK );
  205. }
  206. HRESULT CMIMEBitMatcher::Match( const BYTE* pBytes, ULONG nBytes ) const
  207. {
  208. ULONG iByte;
  209. ULONG nBytesToMatch;
  210. _ASSERTE( m_nBytes > 0 );
  211. nBytesToMatch = min( nBytes, m_nBytes );
  212. for( iByte = 0; iByte < nBytesToMatch; iByte++ )
  213. {
  214. if( (pBytes[iByte]&m_pMask[iByte]) != m_pData[iByte] )
  215. {
  216. // The bits definitely don't match
  217. return( S_FALSE );
  218. }
  219. }
  220. if( nBytes < m_nBytes )
  221. {
  222. // We could have a match, but we need more data to be sure.
  223. return( E_PENDING );
  224. }
  225. // We have a match
  226. return( S_OK );
  227. }
  228. CMIMEType::CMIMEType() :
  229. m_pNext( NULL ),
  230. m_nClipboardFormat( 0 ),
  231. m_lpBitMatchers( NULL ),
  232. m_nMaxBytes( 0 )
  233. {
  234. memcpy( m_achSignature, "NoLK", 4 );
  235. }
  236. CMIMEType::~CMIMEType()
  237. {
  238. CMIMEBitMatcher* pBitMatcher;
  239. while( m_lpBitMatchers != NULL )
  240. {
  241. pBitMatcher = m_lpBitMatchers;
  242. m_lpBitMatchers = m_lpBitMatchers->m_pNext;
  243. delete pBitMatcher;
  244. }
  245. }
  246. UINT CMIMEType::GetClipboardFormat() const
  247. {
  248. return( m_nClipboardFormat );
  249. }
  250. HRESULT CMIMEType::InitFromKey( HKEY hKey, LPCTSTR pszName, ULONG* pnMaxBytes )
  251. {
  252. LONG nResult;
  253. HRESULT hResult;
  254. HKEY hBitsKey;
  255. DWORD dwValueType;
  256. BYTE* pData;
  257. ULONG nBytes = 0;
  258. ULONG nBytesToMatch;
  259. CMIMEBitMatcher* pBitMatcher;
  260. _ASSERTE( hKey != NULL );
  261. _ASSERTE( pszName != NULL );
  262. _ASSERTE( pnMaxBytes != NULL );
  263. nResult = RegOpenKeyEx( hKey, _T( "Bits" ), 0, KEY_READ, &hBitsKey );
  264. if( nResult != ERROR_SUCCESS )
  265. {
  266. return( E_FAIL );
  267. }
  268. nResult = RegQueryValueEx( hBitsKey, _T( "0" ), NULL, &dwValueType, NULL,
  269. &nBytes );
  270. if( (nResult != ERROR_SUCCESS) || (dwValueType != REG_BINARY) || nBytes > 8192 )
  271. {
  272. RegCloseKey( hBitsKey );
  273. return( E_FAIL );
  274. }
  275. pData = LPBYTE( _alloca( nBytes ) );
  276. nResult = RegQueryValueEx( hBitsKey, _T( "0" ), NULL, &dwValueType, pData,
  277. &nBytes );
  278. if( nResult != ERROR_SUCCESS )
  279. {
  280. RegCloseKey( hBitsKey );
  281. return( E_FAIL );
  282. }
  283. RegCloseKey( hBitsKey );
  284. pBitMatcher = new CMIMEBitMatcher;
  285. if( pBitMatcher == NULL )
  286. {
  287. return( E_OUTOFMEMORY );
  288. }
  289. hResult = pBitMatcher->InitFromBinary( pData, nBytes, &nBytesToMatch );
  290. if( FAILED( hResult ) )
  291. {
  292. delete pBitMatcher;
  293. return( hResult );
  294. }
  295. m_nMaxBytes = max( m_nMaxBytes, nBytesToMatch );
  296. m_lpBitMatchers = pBitMatcher;
  297. m_nClipboardFormat = RegisterClipboardFormat( pszName );
  298. if( m_nClipboardFormat == 0 )
  299. {
  300. return( E_FAIL );
  301. }
  302. *pnMaxBytes = m_nMaxBytes;
  303. return( S_OK );
  304. }
  305. HRESULT CMIMEType::Match( const BYTE* pBytes, ULONG nBytes ) const
  306. {
  307. HRESULT hResult;
  308. HRESULT hResultSoFar;
  309. CMIMEBitMatcher* pBitMatcher;
  310. _ASSERTE( pBytes != NULL );
  311. _ASSERTE( m_nClipboardFormat != 0 );
  312. _ASSERTE( m_lpBitMatchers != NULL );
  313. hResultSoFar = S_FALSE;
  314. for( pBitMatcher = m_lpBitMatchers; pBitMatcher != NULL; pBitMatcher =
  315. pBitMatcher->m_pNext )
  316. {
  317. hResult = pBitMatcher->Match( pBytes, nBytes );
  318. switch( hResult )
  319. {
  320. case S_OK:
  321. return( S_OK );
  322. break;
  323. case E_PENDING:
  324. hResultSoFar = E_PENDING;
  325. break;
  326. case S_FALSE:
  327. break;
  328. default:
  329. return( hResult );
  330. break;
  331. }
  332. }
  333. return( hResultSoFar );
  334. }
  335. CMIMEIdentifier::CMIMEIdentifier() :
  336. m_lpTypes( NULL ),
  337. m_nMaxBytes( 0 )
  338. {
  339. memcpy( m_achSignature, "NoLK", 4 );
  340. }
  341. CMIMEIdentifier::~CMIMEIdentifier()
  342. {
  343. CMIMEType* pType;
  344. while( m_lpTypes != NULL )
  345. {
  346. pType = m_lpTypes;
  347. m_lpTypes = m_lpTypes->m_pNext;
  348. delete pType;
  349. }
  350. }
  351. ULONG CMIMEIdentifier::GetMaxBytes() const
  352. {
  353. return( m_nMaxBytes );
  354. }
  355. HRESULT CMIMEIdentifier::Identify( const BYTE* pbBytes, ULONG nBytes,
  356. UINT* pnFormat )
  357. {
  358. HRESULT hResultSoFar;
  359. CMIMEType* pType;
  360. HRESULT hResult;
  361. if( pnFormat != NULL )
  362. {
  363. *pnFormat = 0;
  364. }
  365. if( pbBytes == NULL )
  366. {
  367. return( E_INVALIDARG );
  368. }
  369. if( pnFormat == NULL )
  370. {
  371. return( E_POINTER );
  372. }
  373. hResultSoFar = S_FALSE;
  374. for( pType = m_lpTypes; pType != NULL; pType = pType->m_pNext )
  375. {
  376. hResult = pType->Match( pbBytes, nBytes );
  377. switch( hResult )
  378. {
  379. case S_OK:
  380. *pnFormat = pType->GetClipboardFormat();
  381. return( S_OK );
  382. break;
  383. case E_PENDING:
  384. hResultSoFar = E_PENDING;
  385. break;
  386. case S_FALSE:
  387. break;
  388. default:
  389. return( hResult );
  390. break;
  391. }
  392. }
  393. return( hResultSoFar );
  394. }
  395. HRESULT CMIMEIdentifier::IdentifyStream( ISniffStream* pSniffStream,
  396. UINT* pnFormat )
  397. {
  398. HRESULT hResult;
  399. HRESULT hPeekResult;
  400. BYTE* pbBytes;
  401. ULONG nBytesRead;
  402. UINT nFormat;
  403. if( pnFormat != NULL )
  404. {
  405. *pnFormat = 0;
  406. }
  407. if( pSniffStream == NULL )
  408. {
  409. return( E_INVALIDARG );
  410. }
  411. if( pnFormat == NULL )
  412. {
  413. return( E_POINTER );
  414. }
  415. pbBytes = LPBYTE( _alloca( m_nMaxBytes ) );
  416. hPeekResult = pSniffStream->Peek( pbBytes, m_nMaxBytes, &nBytesRead );
  417. if( FAILED( hPeekResult ) && (hPeekResult != E_PENDING) )
  418. {
  419. return( hPeekResult );
  420. }
  421. hResult = Identify( pbBytes, nBytesRead, &nFormat );
  422. if( hResult == S_OK )
  423. {
  424. *pnFormat = nFormat;
  425. }
  426. if( (hResult == E_PENDING) && (hPeekResult == S_FALSE) )
  427. {
  428. return( S_FALSE );
  429. }
  430. return( hResult );
  431. }
  432. HRESULT CMIMEIdentifier::InitFromRegistry()
  433. {
  434. LONG nResult;
  435. HKEY hKey;
  436. ULONG iSubkey;
  437. HKEY hSubkey;
  438. TCHAR szKeyName[MAX_PATH+1];
  439. ULONG nNameLength;
  440. FILETIME time;
  441. BOOL bDone;
  442. CMIMEType* pType;
  443. HRESULT hResult;
  444. ULONG nMaxBytes;
  445. if( m_lpTypes != NULL )
  446. {
  447. return( E_FAIL );
  448. }
  449. nResult = RegOpenKeyEx( HKEY_CLASSES_ROOT, MIME_DATABASE_ROOT, 0, KEY_READ,
  450. &hKey );
  451. if( nResult != ERROR_SUCCESS )
  452. {
  453. return( E_FAIL );
  454. }
  455. iSubkey = 0;
  456. bDone = FALSE;
  457. while( !bDone )
  458. {
  459. nNameLength = sizeof( szKeyName )/sizeof( *szKeyName );
  460. nResult = RegEnumKeyEx( hKey, iSubkey, szKeyName, &nNameLength, NULL,
  461. NULL, NULL, &time );
  462. if( (nResult != ERROR_SUCCESS) && (nResult != ERROR_NO_MORE_ITEMS) )
  463. {
  464. RegCloseKey( hKey );
  465. return( E_FAIL );
  466. }
  467. if( nResult == ERROR_SUCCESS )
  468. {
  469. nResult = RegOpenKeyEx( hKey, szKeyName, 0, KEY_READ, &hSubkey );
  470. if( nResult != ERROR_SUCCESS )
  471. {
  472. RegCloseKey( hKey );
  473. return( E_FAIL );
  474. }
  475. pType = new CMIMEType;
  476. if( pType == NULL )
  477. {
  478. return( E_OUTOFMEMORY );
  479. }
  480. hResult = pType->InitFromKey( hSubkey, szKeyName, &nMaxBytes );
  481. if( SUCCEEDED( hResult ) )
  482. {
  483. m_nMaxBytes = max( m_nMaxBytes, nMaxBytes );
  484. pType->m_pNext = m_lpTypes;
  485. m_lpTypes = pType;
  486. }
  487. else
  488. {
  489. delete pType;
  490. }
  491. RegCloseKey( hSubkey );
  492. }
  493. else
  494. {
  495. bDone = TRUE;
  496. }
  497. iSubkey++;
  498. }
  499. return( S_OK );
  500. }