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.

634 lines
15 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dvcdb.cpp
  6. * Content:
  7. * This module contains the implementation of the compression
  8. * subsystem and the associated utility functions.
  9. *
  10. * History:
  11. * Date By Reason
  12. * ==== == ======
  13. * 08/29/99 rodtoll Created
  14. * 09/01/99 rodtoll Updated to add checks for valid read/write pointers
  15. * 09/07/99 rodtoll Removed bad assert and added dpf_modnames
  16. * Removed Create flag on registry opens
  17. * 09/10/99 rodtoll dwFlags check on call to DVCDB_CopyCompress...
  18. * 09/14/99 rodtoll Minor bugfix in compression info copy
  19. * 09/21/99 rodtoll Added OSInd and fixed memory leak
  20. * 10/07/99 rodtoll Added stubs for supporting new codecs
  21. * rodtoll Updated to use Unicode
  22. * 10/15/99 rodtoll Plugged some memory leaks
  23. * 10/28/99 rodtoll Updated to use new compression providers
  24. * 10/29/99 rodtoll Bug #113726 - Integrate Voxware Codecs, updating to use new
  25. * pluggable codec architecture.
  26. * 11/22/99 rodtoll Removed false error message when loading compression types
  27. * 12/16/99 rodtoll Removed asserts (which were not needed) exposed by compression
  28. * provider changes.
  29. * 02/10/2000 rodtoll Fixed crash if invalid registry entries are present.
  30. * 03/03/2000 rodtoll Updated to handle alternative gamevoice build.
  31. * 03/16/2000 rodtoll Updated converter create to check and return error code
  32. * 04/21/2000 rodtoll Bug #32889 - Does not run on Win2k w/o Admin
  33. * 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs
  34. * 06/28/2000 rodtoll Prefix Bug #38022
  35. * 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h, added STR_* and strutils.h
  36. * 08/31/2000 rodtoll Prefix Bug #171840
  37. * 10/05/2000 rodtoll Bug #46541 - DPVOICE: A/V linking to dpvoice.lib could cause application to fail init and crash
  38. *
  39. ***************************************************************************/
  40. #include "dxvutilspch.h"
  41. #undef DPF_SUBCOMP
  42. #define DPF_SUBCOMP DN_SUBCOMP_VOICE
  43. struct DVCDBProvider
  44. {
  45. GUID guidClassID;
  46. PDVFULLCOMPRESSIONINFO pInfo;
  47. DWORD dwNumElements;
  48. DVCDBProvider *pNext;
  49. };
  50. DVCDBProvider *g_dvcdbProviderList = NULL;
  51. #define REGISTRY_CDB_FORMAT L"Format"
  52. #define REGISTRY_WAVEFORMAT_RATE L"Rate"
  53. #define REGISTRY_WAVEFORMAT_BITS L"Bits"
  54. #define REGISTRY_WAVEFORMAT_CHANNELS L"Channels"
  55. #define REGISTRY_WAVEFORMAT_TAG L"Tag"
  56. #define REGISTRY_WAVEFORMAT_AVGPERSEC L"AvgPerSec"
  57. #define REGISTRY_WAVEFORMAT_BLOCKALIGN L"BlockAlign"
  58. #define REGISTRY_WAVEFORMAT_CBSIZE L"cbsize"
  59. #define REGISTRY_WAVEFORMAT_CBDATA L"cbdata"
  60. #undef DPF_MODNAME
  61. #define DPF_MODNAME "DVCDB_CalcUnCompressedFrameSize"
  62. DWORD DVCDB_CalcUnCompressedFrameSize( LPDVFULLCOMPRESSIONINFO lpdvInfo, LPWAVEFORMATEX lpwfxFormat )
  63. {
  64. DWORD frameSize;
  65. switch( lpwfxFormat->nSamplesPerSec )
  66. {
  67. case 8000: frameSize = lpdvInfo->dwFrame8Khz; break;
  68. case 11025: frameSize = lpdvInfo->dwFrame11Khz; break;
  69. case 22050: frameSize = lpdvInfo->dwFrame22Khz; break;
  70. case 44100: frameSize = lpdvInfo->dwFrame44Khz; break;
  71. default: return 0;
  72. }
  73. if( lpwfxFormat->wBitsPerSample == 16 )
  74. frameSize *= 2;
  75. frameSize *= lpwfxFormat->nChannels;
  76. return frameSize;
  77. }
  78. #undef DPF_MODNAME
  79. #define DPF_MODNAME "CREG_ReadAndAllocWaveFormatEx"
  80. HRESULT CREG_ReadAndAllocWaveFormatEx( HKEY hkeyReg, const LPWSTR path, LPWAVEFORMATEX *lpwfxFormat )
  81. {
  82. CRegistry waveKey;
  83. if( !waveKey.Open( hkeyReg, path, TRUE, FALSE ) )
  84. {
  85. return E_FAIL;
  86. }
  87. DWORD dwTmp;
  88. if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_CBSIZE, dwTmp ) )
  89. {
  90. return E_FAIL;
  91. }
  92. *lpwfxFormat = (LPWAVEFORMATEX) new BYTE[dwTmp+sizeof(WAVEFORMATEX)];
  93. LPWAVEFORMATEX tmpFormat = *lpwfxFormat;
  94. if( tmpFormat == NULL )
  95. {
  96. return E_OUTOFMEMORY;
  97. }
  98. tmpFormat->cbSize = (BYTE) dwTmp;
  99. if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_RATE, dwTmp ) )
  100. {
  101. goto READ_FAILURE;
  102. }
  103. tmpFormat->nSamplesPerSec = dwTmp;
  104. if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_BITS, dwTmp ) )
  105. {
  106. goto READ_FAILURE;
  107. }
  108. tmpFormat->wBitsPerSample = (WORD) dwTmp;
  109. if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_CHANNELS, dwTmp ) )
  110. {
  111. goto READ_FAILURE;
  112. }
  113. tmpFormat->nChannels = (INT) dwTmp;
  114. if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_TAG, dwTmp ) )
  115. {
  116. goto READ_FAILURE;
  117. }
  118. tmpFormat->wFormatTag = (WORD) dwTmp;
  119. if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_AVGPERSEC, dwTmp ) )
  120. {
  121. goto READ_FAILURE;
  122. }
  123. tmpFormat->nAvgBytesPerSec = (INT) dwTmp;
  124. if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_BLOCKALIGN, dwTmp ) )
  125. {
  126. goto READ_FAILURE;
  127. }
  128. tmpFormat->nBlockAlign = (INT) dwTmp;
  129. dwTmp = tmpFormat->cbSize;
  130. if( !waveKey.ReadBlob( REGISTRY_WAVEFORMAT_CBDATA, (LPBYTE) &tmpFormat[1], &dwTmp ) )
  131. {
  132. DPFX(DPFPREP, 0, "Error reading waveformat blob" );
  133. goto READ_FAILURE;
  134. }
  135. return S_OK;
  136. READ_FAILURE:
  137. delete [] *lpwfxFormat;
  138. *lpwfxFormat = NULL;
  139. return E_FAIL;
  140. }
  141. #undef DPF_MODNAME
  142. #define DPF_MODNAME "DVCDB_LoadCompressionInfo"
  143. HRESULT DVCDB_LoadCompressionInfo( const WCHAR *swzBaseRegistryPath )
  144. {
  145. CRegistry mainKey, subKey;
  146. LPWSTR keyName = NULL;
  147. DWORD dwIndex = 0;
  148. DWORD dwSize = 0;
  149. HRESULT hr;
  150. PDPVCOMPRESSIONPROVIDER pCompressionProvider = NULL;
  151. DVCDBProvider *pNewProvider = NULL;
  152. WCHAR wszPath[_MAX_PATH];
  153. if( swzBaseRegistryPath == NULL )
  154. {
  155. DPFX(DPFPREP, 0, "INTERNAL ERROR!" );
  156. return E_FAIL;
  157. }
  158. wcscpy( wszPath, swzBaseRegistryPath );
  159. wcscat( wszPath, DPVOICE_REGISTRY_CP );
  160. if( !mainKey.Open( HKEY_LOCAL_MACHINE, wszPath, TRUE, FALSE ) )
  161. {
  162. DPFX(DPFPREP, 0, "Error reading compression providers from the registry. Path doesn't exist" );
  163. return E_FAIL;
  164. }
  165. dwIndex = 0;
  166. keyName = NULL;
  167. dwSize = 0;
  168. LPSTR lpstrKeyName = NULL;
  169. GUID guidCP;
  170. // Enumerate the subkeys at this point in the tree
  171. while( 1 )
  172. {
  173. dwSize = 0;
  174. if( !mainKey.EnumKeys( keyName, &dwSize, dwIndex ) )
  175. {
  176. if( dwSize == 0 )
  177. {
  178. DPFX(DPFPREP, DVF_INFOLEVEL, "End of provider list" );
  179. break;
  180. }
  181. if( keyName != NULL )
  182. {
  183. delete [] keyName;
  184. }
  185. keyName = new wchar_t[dwSize];
  186. }
  187. if( !mainKey.EnumKeys( keyName, &dwSize, dwIndex ) )
  188. {
  189. delete [] keyName;
  190. break;
  191. }
  192. if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  193. {
  194. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error allocating memory" );
  195. break;
  196. }
  197. DPFX(DPFPREP, DVF_INFOLEVEL, "Reading provider: %s", lpstrKeyName );
  198. if( !subKey.Open( mainKey, keyName, TRUE, FALSE ) )
  199. {
  200. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error reading provider: %s", lpstrKeyName );
  201. goto SKIP_TO_NEXT;
  202. }
  203. delete [] keyName;
  204. keyName = NULL;
  205. dwSize = 0;
  206. // Read the GUID from the default key
  207. if( !subKey.ReadGUID( L"", guidCP ) )
  208. {
  209. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to read the provider's GUID" );
  210. goto SKIP_TO_NEXT;
  211. }
  212. // Attempt to create the provider
  213. hr = COM_CoCreateInstance( guidCP , NULL, CLSCTX_INPROC_SERVER, IID_IDPVCompressionProvider, (void **) &pCompressionProvider );
  214. if( FAILED( hr ) )
  215. {
  216. DPFX(DPFPREP, DVF_ERRORLEVEL, "FAILED to create 0x%x\n", hr );
  217. goto SKIP_TO_NEXT;
  218. }
  219. // Build a record for the provider
  220. pNewProvider = new DVCDBProvider;
  221. if( pNewProvider == NULL )
  222. {
  223. DPFX(DPFPREP, DVF_ERRORLEVEL, "Out of memory" );
  224. goto SKIP_TO_NEXT;
  225. }
  226. pNewProvider->guidClassID = guidCP;
  227. pNewProvider->pInfo = NULL;
  228. pNewProvider->dwNumElements = 0;
  229. dwSize = 0;
  230. // GetCompression Info for the provider
  231. hr = pCompressionProvider->EnumCompressionTypes( pNewProvider->pInfo, &dwSize, &pNewProvider->dwNumElements, 0 );
  232. if( hr != DVERR_BUFFERTOOSMALL )
  233. {
  234. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get compression info for provider: %s", lpstrKeyName );
  235. goto SKIP_TO_NEXT;
  236. }
  237. pNewProvider->pInfo = (DVFULLCOMPRESSIONINFO *) new BYTE[dwSize];
  238. if( pNewProvider->pInfo == NULL )
  239. {
  240. DPFX(DPFPREP, DVF_ERRORLEVEL, "Out of memory" );
  241. goto SKIP_TO_NEXT;
  242. }
  243. hr = pCompressionProvider->EnumCompressionTypes( pNewProvider->pInfo, &dwSize, &pNewProvider->dwNumElements, 0 );
  244. if( FAILED( hr ) )
  245. {
  246. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get compression info for %s hr=0x%x", lpstrKeyName, hr );
  247. goto SKIP_TO_NEXT;
  248. }
  249. // Add it to the list
  250. pNewProvider->pNext = g_dvcdbProviderList;
  251. g_dvcdbProviderList = pNewProvider;
  252. pNewProvider = NULL;
  253. SKIP_TO_NEXT:
  254. if( pCompressionProvider != NULL )
  255. {
  256. pCompressionProvider->Release();
  257. pCompressionProvider = NULL;
  258. }
  259. if( pNewProvider != NULL )
  260. {
  261. delete pNewProvider;
  262. pNewProvider = NULL;
  263. }
  264. if( lpstrKeyName != NULL )
  265. delete [] lpstrKeyName;
  266. if( keyName != NULL )
  267. delete [] keyName;
  268. lpstrKeyName = NULL;
  269. keyName = NULL;
  270. dwSize = 0;
  271. dwIndex++;
  272. continue;
  273. }
  274. if( lpstrKeyName != NULL )
  275. delete [] lpstrKeyName;
  276. if( keyName != NULL )
  277. delete [] keyName;
  278. return DV_OK;
  279. }
  280. #undef DPF_MODNAME
  281. #define DPF_MODNAME "DVCDB_FreeCompressionInfo"
  282. HRESULT DVCDB_FreeCompressionInfo()
  283. {
  284. DVCDBProvider *pTmpProvider, *pTmpNext;
  285. if( g_dvcdbProviderList == NULL )
  286. return DV_OK;
  287. pTmpProvider = g_dvcdbProviderList;
  288. while( pTmpProvider != NULL )
  289. {
  290. pTmpNext = pTmpProvider->pNext;
  291. delete [] pTmpProvider->pInfo;
  292. delete pTmpProvider;
  293. pTmpProvider = pTmpNext;
  294. }
  295. g_dvcdbProviderList = NULL;
  296. return DV_OK;
  297. }
  298. #undef DPF_MODNAME
  299. #define DPF_MODNAME "DVCDB_GetCompressionClassID"
  300. HRESULT DVCDB_GetCompressionClassID( GUID guidCT, GUID &guidClass )
  301. {
  302. DVCDBProvider *pTmpProvider;
  303. DWORD dwIndex;
  304. pTmpProvider = g_dvcdbProviderList;
  305. while( pTmpProvider != NULL )
  306. {
  307. for( dwIndex = 0; dwIndex < pTmpProvider->dwNumElements; dwIndex++ )
  308. {
  309. if( pTmpProvider->pInfo[dwIndex].guidType == guidCT )
  310. {
  311. guidClass = pTmpProvider->guidClassID;
  312. return DV_OK;
  313. }
  314. }
  315. pTmpProvider = pTmpProvider->pNext;
  316. }
  317. return DVERR_COMPRESSIONNOTSUPPORTED;
  318. }
  319. #undef DPF_MODNAME
  320. #define DPF_MODNAME "DVCDB_GetCompressionInfo"
  321. HRESULT DVCDB_GetCompressionInfo( GUID guidType, PDVFULLCOMPRESSIONINFO *lpdvfCompressionInfo )
  322. {
  323. DVCDBProvider *pTmpProvider;
  324. DWORD dwIndex;
  325. pTmpProvider = g_dvcdbProviderList;
  326. while( pTmpProvider != NULL )
  327. {
  328. for( dwIndex = 0; dwIndex < pTmpProvider->dwNumElements; dwIndex++ )
  329. {
  330. if( pTmpProvider->pInfo[dwIndex].guidType == guidType )
  331. {
  332. *lpdvfCompressionInfo = &pTmpProvider->pInfo[dwIndex];
  333. return DV_OK;
  334. }
  335. }
  336. pTmpProvider = pTmpProvider->pNext;
  337. }
  338. return DVERR_COMPRESSIONNOTSUPPORTED;
  339. }
  340. #undef DPF_MODNAME
  341. #define DPF_MODNAME "DVCDB_IsValidCompressionType"
  342. HRESULT DVCDB_IsValidCompressionType( GUID guidCT )
  343. {
  344. GUID guidDummy;
  345. return DVCDB_GetCompressionClassID( guidCT, guidDummy );
  346. }
  347. #undef DPF_MODNAME
  348. #define DPF_MODNAME "DVCDB_CreateConverter"
  349. HRESULT DVCDB_CreateConverter( WAVEFORMATEX *pwfxSrcFormat, GUID guidTarget, PDPVCOMPRESSOR *pConverter )
  350. {
  351. HRESULT hr;
  352. GUID guidProvider;
  353. PDPVCOMPRESSIONPROVIDER pCompressionProvider = NULL;
  354. hr = DVCDB_GetCompressionClassID( guidTarget, guidProvider );
  355. if( FAILED( hr ) )
  356. {
  357. DPFX(DPFPREP, DVF_ERRORLEVEL, "Requested compression type is not supported, hr=0x%x", hr );
  358. return hr;
  359. }
  360. hr = COM_CoCreateInstance( guidProvider , NULL, CLSCTX_INPROC_SERVER, IID_IDPVCompressionProvider, (void **) &pCompressionProvider );
  361. if( FAILED( hr ) )
  362. {
  363. DPFX(DPFPREP, DVF_ERRORLEVEL, "FAILED to create 0x%x\n", hr );
  364. return DVERR_COMPRESSIONNOTSUPPORTED;
  365. }
  366. hr = pCompressionProvider->CreateCompressor( pwfxSrcFormat, guidTarget, pConverter, 0 );
  367. if( FAILED( hr ) )
  368. {
  369. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error creating compressor hr=0x%x", hr );
  370. return hr;
  371. }
  372. pCompressionProvider->Release();
  373. return hr;
  374. }
  375. #undef DPF_MODNAME
  376. #define DPF_MODNAME "DVCDB_CreateConverter"
  377. HRESULT DVCDB_CreateConverter( GUID guidSrc, WAVEFORMATEX *pwfxTarget, PDPVCOMPRESSOR *pConverter )
  378. {
  379. HRESULT hr;
  380. GUID guidProvider;
  381. PDPVCOMPRESSIONPROVIDER pCompressionProvider = NULL;
  382. hr = DVCDB_GetCompressionClassID( guidSrc, guidProvider );
  383. if( FAILED( hr ) )
  384. {
  385. DPFX(DPFPREP, DVF_ERRORLEVEL, "Requested compression type is not supported, hr=0x%x", hr );
  386. return hr;
  387. }
  388. hr = COM_CoCreateInstance( guidProvider , NULL, CLSCTX_INPROC_SERVER, IID_IDPVCompressionProvider, (void **) &pCompressionProvider );
  389. if( FAILED( hr ) )
  390. {
  391. DPFX(DPFPREP, DVF_ERRORLEVEL, "FAILED to create 0x%x\n", hr );
  392. return DVERR_COMPRESSIONNOTSUPPORTED;
  393. }
  394. hr = pCompressionProvider->CreateDeCompressor( guidSrc, pwfxTarget, pConverter, 0 );
  395. if( FAILED( hr ) )
  396. {
  397. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error creating compressor hr=0x%x", hr );
  398. return hr;
  399. }
  400. pCompressionProvider->Release();
  401. return DV_OK;
  402. }
  403. #undef DPF_MODNAME
  404. #define DPF_MODNAME "DVCDB_CopyCompressionArrayToBuffer"
  405. HRESULT DVCDB_CopyCompressionArrayToBuffer( LPVOID lpBuffer, LPDWORD lpdwSize, LPDWORD lpdwNumElements, DWORD dwFlags )
  406. {
  407. if( lpdwNumElements == NULL || lpdwSize == NULL ||
  408. !DNVALID_READPTR(lpdwNumElements,sizeof(DWORD)) ||
  409. !DNVALID_READPTR(lpdwSize,sizeof(DWORD)) )
  410. {
  411. return E_POINTER;
  412. }
  413. if( dwFlags != 0 )
  414. {
  415. return DVERR_INVALIDFLAGS;
  416. }
  417. DWORD dwIndex, dwReadIndex;
  418. DWORD dwRequiredSize = 0;
  419. DWORD dwTmpSize;
  420. LPDVCOMPRESSIONINFO lpdvTargetList;
  421. LPBYTE lpbExtraLoc = (LPBYTE) lpBuffer;
  422. *lpdwNumElements = 0;
  423. DVCDBProvider *pTmpProvider;
  424. pTmpProvider = g_dvcdbProviderList;
  425. while( pTmpProvider != NULL )
  426. {
  427. for( dwIndex = 0; dwIndex < pTmpProvider->dwNumElements; dwIndex++ )
  428. {
  429. dwRequiredSize += DVCDB_GetCompressionInfoSize( (LPDVCOMPRESSIONINFO) &pTmpProvider->pInfo[dwIndex] );
  430. (*lpdwNumElements)++;
  431. }
  432. pTmpProvider = pTmpProvider->pNext;
  433. }
  434. if( *lpdwSize < dwRequiredSize )
  435. {
  436. *lpdwSize = dwRequiredSize;
  437. return DVERR_BUFFERTOOSMALL;
  438. }
  439. *lpdwSize = dwRequiredSize;
  440. if( lpBuffer == NULL || !DNVALID_WRITEPTR(lpBuffer,dwRequiredSize) )
  441. {
  442. return E_POINTER;
  443. }
  444. lpbExtraLoc += (*lpdwNumElements)*sizeof(DVCOMPRESSIONINFO);
  445. lpdvTargetList = (LPDVCOMPRESSIONINFO) lpBuffer;
  446. pTmpProvider = g_dvcdbProviderList;
  447. dwIndex = 0;
  448. while( pTmpProvider != NULL )
  449. {
  450. for( dwReadIndex = 0; dwReadIndex < pTmpProvider->dwNumElements; dwReadIndex++, dwIndex++ )
  451. {
  452. memcpy( &lpdvTargetList[dwIndex], &pTmpProvider->pInfo[dwReadIndex], sizeof(DVCOMPRESSIONINFO) );
  453. if( pTmpProvider->pInfo[dwReadIndex].lpszDescription != NULL )
  454. {
  455. dwTmpSize = (wcslen( pTmpProvider->pInfo[dwReadIndex].lpszDescription )*2)+2;
  456. memcpy( lpbExtraLoc, pTmpProvider->pInfo[dwReadIndex].lpszDescription, dwTmpSize );
  457. lpdvTargetList[dwIndex].lpszDescription = (LPWSTR) lpbExtraLoc;
  458. lpbExtraLoc += dwTmpSize;
  459. }
  460. if( pTmpProvider->pInfo[dwReadIndex].lpszName != NULL )
  461. {
  462. dwTmpSize = (wcslen( pTmpProvider->pInfo[dwReadIndex].lpszName )*2)+2;
  463. memcpy( lpbExtraLoc, pTmpProvider->pInfo[dwReadIndex].lpszName, dwTmpSize );
  464. lpdvTargetList[dwIndex].lpszName = (LPWSTR) lpbExtraLoc;
  465. lpbExtraLoc += dwTmpSize;
  466. }
  467. }
  468. pTmpProvider = pTmpProvider->pNext;
  469. }
  470. return DV_OK;
  471. }
  472. #undef DPF_MODNAME
  473. #define DPF_MODNAME "DVCDB_GetCompressionInfoSize"
  474. DWORD DVCDB_GetCompressionInfoSize( LPDVCOMPRESSIONINFO lpdvCompressionInfo )
  475. {
  476. DNASSERT( lpdvCompressionInfo != NULL );
  477. DWORD dwSize;
  478. dwSize = sizeof( DVCOMPRESSIONINFO );
  479. if( lpdvCompressionInfo->lpszDescription != NULL )
  480. {
  481. dwSize += (wcslen( lpdvCompressionInfo->lpszDescription )*2)+2;
  482. }
  483. if( lpdvCompressionInfo->lpszName != NULL )
  484. {
  485. dwSize += (wcslen( lpdvCompressionInfo->lpszName)*2)+2;
  486. }
  487. return dwSize;
  488. }