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.

3618 lines
105 KiB

  1. // Storage.cpp : Implementation of CStorage
  2. #include "stdafx.h"
  3. #include "mswmdm.h"
  4. #include "Storage.h"
  5. #include "scpinfo.h"
  6. #include "spinfo.h"
  7. #include "loghelp.h"
  8. #include "WMDMStorageEnum.h"
  9. #include "StorageGlobal.h"
  10. #include "scclient.h"
  11. #include "scserver.h"
  12. // We don't want to dll's using our lib to link to drmutil2.lib.
  13. // So disable DRM logging.
  14. #define DISABLE_DRM_LOG
  15. #include "drmerr.h"
  16. #include "wmsstd.h"
  17. #include "key.h"
  18. #include "MediaDevMgr.h"
  19. #include <WMDMUtil.h>
  20. //#define DUMP_FILE
  21. #ifdef DUMP_FILE
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #endif
  25. #define STRSAFE_NO_DEPRECATE
  26. #include "strsafe.h"
  27. #define WMDM_TRANSFER_BUFFER_SIZE 57344
  28. //65536
  29. //previous size 10240
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CWMDMStorage
  32. extern CSCPInfo **g_pSCPs;
  33. extern WORD g_wSCPCount;
  34. extern CSecureChannelServer *g_pAppSCServer;
  35. extern CSPInfo **g_pSPs;
  36. typedef struct __INSERTTHREADARGS
  37. {
  38. CWMDMStorage *pThis;
  39. UINT fuMode;
  40. LPWSTR pwszFileSource;
  41. LPWSTR pwszFileDest;
  42. IStream *pOperationStream;
  43. IStream *pProgressStream;
  44. IStream *pUnknownStream;
  45. IWMDMStorage **ppNewObject;
  46. } INSERTTHREADARGS;
  47. typedef struct __DELETETHREADARGS
  48. {
  49. CWMDMStorage *pThis;
  50. IStream *pProgressStream;
  51. UINT fuMode;
  52. } DELETETHREADARGS;
  53. typedef struct __RENAMETHREADARGS
  54. {
  55. CWMDMStorage *pThis;
  56. LPWSTR pwszNewName;
  57. IStream *pProgressStream;
  58. } RENAMETHREADARGS;
  59. typedef struct __READTHREADARGS
  60. {
  61. CWMDMStorage *pThis;
  62. UINT fuMode;
  63. LPWSTR pwszFile;
  64. IStream *pProgressStream;
  65. IStream *pOperationStream;
  66. } READTHREADARGS;
  67. // Construction / Destruction
  68. CWMDMStorage::CWMDMStorage()
  69. : m_pStorage(NULL), m_dwStatus(WMDM_STATUS_READY)
  70. {
  71. GlobalAddRef();
  72. m_pwszRevocationURL = NULL;
  73. m_dwRevocationURLLen = 0;
  74. m_dwRevocationBitFlag = 0;
  75. }
  76. CWMDMStorage::~CWMDMStorage()
  77. {
  78. SAFE_RELEASE(m_pStorage);
  79. CoTaskMemFree( m_pwszRevocationURL );
  80. GlobalRelease();
  81. }
  82. // IWMDMStorage
  83. HRESULT CWMDMStorage::SetAttributes(DWORD dwAttributes, _WAVEFORMATEX *pFormat)
  84. {
  85. HRESULT hr;
  86. if (g_pAppSCServer)
  87. {
  88. if(!g_pAppSCServer->fIsAuthenticated())
  89. {
  90. CORg( WMDM_E_NOTCERTIFIED );
  91. }
  92. }
  93. else
  94. {
  95. CORg( E_FAIL );
  96. }
  97. CORg( m_pStorage->SetAttributes(dwAttributes, pFormat) );
  98. Error:
  99. hrLogDWORD("IWMDMStorage::SetAttributes returned 0x%08lx", hr, hr);
  100. return hr;
  101. }
  102. HRESULT CWMDMStorage::GetStorageGlobals(IWMDMStorageGlobals **ppStorageGlobals)
  103. {
  104. HRESULT hr;
  105. CComObject<CWMDMStorageGlobal> *pStgGlobal = NULL;
  106. IMDSPStorageGlobals *pSPStgGlobal = NULL;
  107. if (g_pAppSCServer)
  108. {
  109. if(!g_pAppSCServer->fIsAuthenticated())
  110. {
  111. CORg( WMDM_E_NOTCERTIFIED );
  112. }
  113. }
  114. else
  115. {
  116. CORg( E_FAIL );
  117. }
  118. if (!ppStorageGlobals)
  119. {
  120. CORg( E_INVALIDARG );
  121. }
  122. CORg( m_pStorage->GetStorageGlobals(&pSPStgGlobal) );
  123. CORg( CComObject<CWMDMStorageGlobal>::CreateInstance(&pStgGlobal) );
  124. hr = pStgGlobal->QueryInterface(IID_IWMDMStorageGlobals, reinterpret_cast<void**>(ppStorageGlobals));
  125. if (FAILED(hr))
  126. {
  127. delete pStgGlobal;
  128. goto exit;
  129. }
  130. pStgGlobal->SetContainedPointer(pSPStgGlobal, m_wSPIndex);
  131. exit:
  132. Error:
  133. if (pSPStgGlobal)
  134. pSPStgGlobal->Release();
  135. hrLogDWORD("IWMDMStorage::GetStorageGlobals returned 0x%08lx", hr, hr);
  136. return hr;
  137. }
  138. HRESULT CWMDMStorage::GetAttributes(DWORD *pdwAttributes,
  139. _WAVEFORMATEX *pFormat)
  140. {
  141. HRESULT hr;
  142. if (g_pAppSCServer)
  143. {
  144. if(!g_pAppSCServer->fIsAuthenticated())
  145. {
  146. CORg( WMDM_E_NOTCERTIFIED );
  147. }
  148. }
  149. else
  150. {
  151. CORg( E_FAIL );
  152. }
  153. CORg( m_pStorage->GetAttributes(pdwAttributes, pFormat) );
  154. Error:
  155. hrLogDWORD("IWMDMStorage::GetAttributes returned 0x%08lx", hr, hr);
  156. return hr;
  157. }
  158. HRESULT CWMDMStorage::GetName(LPWSTR pwszName,
  159. UINT nMaxChars)
  160. {
  161. HRESULT hr;
  162. if (g_pAppSCServer)
  163. {
  164. if(!g_pAppSCServer->fIsAuthenticated())
  165. {
  166. CORg( WMDM_E_NOTCERTIFIED );
  167. }
  168. }
  169. else
  170. {
  171. CORg( E_FAIL );
  172. }
  173. CORg( m_pStorage->GetName(pwszName, nMaxChars) );
  174. Error:
  175. hrLogDWORD("IWMDMStorage::GetName returned 0x%08lx", hr, hr);
  176. return hr;
  177. }
  178. HRESULT CWMDMStorage::GetDate(PWMDMDATETIME pDateTimeUTC)
  179. {
  180. HRESULT hr;
  181. if (g_pAppSCServer)
  182. {
  183. if(!g_pAppSCServer->fIsAuthenticated())
  184. {
  185. CORg( WMDM_E_NOTCERTIFIED );
  186. }
  187. }
  188. else
  189. {
  190. CORg( E_FAIL );
  191. }
  192. CORg( m_pStorage->GetDate(pDateTimeUTC) );
  193. Error:
  194. hrLogDWORD("IWMDMStorage::GetDate returned 0x%08lx", hr, hr);
  195. return hr;
  196. }
  197. HRESULT CWMDMStorage::GetSize(DWORD *pdwSizeLow,
  198. DWORD *pdwSizeHigh)
  199. {
  200. HRESULT hr;
  201. if (g_pAppSCServer)
  202. {
  203. if(!g_pAppSCServer->fIsAuthenticated())
  204. {
  205. CORg( WMDM_E_NOTCERTIFIED );
  206. }
  207. }
  208. else
  209. {
  210. CORg( E_FAIL );
  211. }
  212. CORg( m_pStorage->GetSize(pdwSizeLow, pdwSizeHigh) );
  213. Error:
  214. hrLogDWORD("IWMDMStorage::GetSize returned 0x%08lx", hr, hr);
  215. return hr;
  216. }
  217. HRESULT CWMDMStorage::GetRights(PWMDMRIGHTS *ppRights, UINT *pnRightsCount, BYTE abMac[WMDM_MAC_LENGTH])
  218. {
  219. HRESULT hr;
  220. IMDSPStorageGlobals *pStgGlobals = NULL;
  221. IMDSPObject *pObject = NULL;
  222. ISCPSecureAuthenticate *pSecureAuth = NULL;
  223. ISCPSecureQuery *pSecQuery = NULL;
  224. WORD wCurSCP = 0;
  225. DWORD dwBytesRead;
  226. BYTE *pData = NULL;
  227. UINT fuFlags;
  228. DWORD dwExSize;
  229. DWORD dwMDSize;
  230. DWORD dwRightsSize;
  231. DWORD dwBufferSize=0;
  232. BOOL fUseSCP = FALSE;
  233. CSecureChannelClient *pSCClient = NULL;
  234. CSecureChannelClient *pSPClient = NULL;
  235. HMAC hMAC;
  236. BYTE abTempMAC[SAC_MAC_LEN];
  237. BYTE abMACVerify[SAC_MAC_LEN];
  238. UINT fuTempFlags;
  239. BYTE abSPSessionKey[SAC_SESSION_KEYLEN];
  240. DWORD dwSessionKeyLen = SAC_SESSION_KEYLEN;
  241. if (!ppRights || !pnRightsCount)
  242. {
  243. CORg( E_INVALIDARG );
  244. }
  245. if (g_pAppSCServer)
  246. {
  247. if(!g_pAppSCServer->fIsAuthenticated())
  248. {
  249. CORg( WMDM_E_NOTCERTIFIED );
  250. }
  251. }
  252. else
  253. {
  254. CORg( E_FAIL );
  255. }
  256. g_pSPs[m_wSPIndex]->GetSCClient(&pSPClient);
  257. if (!pSPClient)
  258. {
  259. CORg( E_FAIL );
  260. }
  261. hr = m_pStorage->GetRights(ppRights, pnRightsCount, abTempMAC);
  262. if (SUCCEEDED(hr))
  263. {
  264. // Verify MAC returned by GetRights on the SP
  265. CORg( pSPClient->MACInit(&hMAC) );
  266. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(*ppRights), sizeof(WMDMRIGHTS) * (*pnRightsCount)) );
  267. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(pnRightsCount), sizeof(*pnRightsCount)) );
  268. CORg( pSPClient->MACFinal(hMAC, abMACVerify) );
  269. if (memcmp(abMACVerify, abTempMAC, WMDM_MAC_LENGTH) != 0)
  270. {
  271. CORg( WMDM_E_MAC_CHECK_FAILED );
  272. }
  273. }
  274. // If the SP doesn't give us the rights then we should
  275. // try to use the SCP to get the rights.
  276. if ((E_NOTIMPL == hr) || (WMDM_E_NOTSUPPORTED == hr))
  277. {
  278. CORg( m_pStorage->GetStorageGlobals(&pStgGlobals) );
  279. if( g_pSCPs == NULL )
  280. {
  281. CMediaDevMgr::LoadSCPs();
  282. }
  283. for( wCurSCP = 0; wCurSCP < g_wSCPCount; wCurSCP ++ )
  284. {
  285. CORg( g_pSCPs[wCurSCP]->hrGetInterface(&pSecureAuth) );
  286. g_pSCPs[wCurSCP]->GetSCClient(&pSCClient);
  287. if (!pSCClient)
  288. {
  289. CORg( E_FAIL );
  290. }
  291. CORg( pSecureAuth->GetSecureQuery(&pSecQuery) );
  292. CORg( pSecQuery->GetDataDemands(&fuFlags, &dwRightsSize, &dwExSize, &dwMDSize, abTempMAC) );
  293. // Verify MAC returned by GetDataDemands
  294. CORg( pSCClient->MACInit(&hMAC) );
  295. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuFlags), sizeof(fuFlags)) );
  296. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwRightsSize), sizeof(dwRightsSize)) );
  297. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwExSize), sizeof(dwExSize)) );
  298. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwMDSize), sizeof(dwMDSize)) );
  299. CORg( pSCClient->MACFinal(hMAC, abMACVerify) );
  300. if (memcmp(abMACVerify, abTempMAC, WMDM_MAC_LENGTH) != 0)
  301. {
  302. CORg( WMDM_E_MAC_CHECK_FAILED );
  303. }
  304. if (!(fuFlags & WMDM_SCP_RIGHTS_DATA))
  305. {
  306. continue;
  307. }
  308. if (dwBufferSize < (dwExSize>dwRightsSize?dwExSize:dwRightsSize))
  309. {
  310. SAFE_ARRAY_DELETE(pData);
  311. dwBufferSize = dwExSize>dwRightsSize?dwExSize:dwRightsSize;
  312. pData = new BYTE[dwBufferSize];
  313. CPRg( pData );
  314. }
  315. CORg( m_pStorage->QueryInterface(IID_IMDSPObject, reinterpret_cast<void**>(&pObject)) );
  316. CORg( pObject->Open(MDSP_READ) );
  317. hr = WMDM_E_MOREDATA;
  318. while (hr == WMDM_E_MOREDATA)
  319. {
  320. dwBytesRead = dwBufferSize;
  321. CORg( pObject->Read(pData, &dwBytesRead, abTempMAC) );
  322. // BUGBUG: Copy this buffer before decrypting
  323. pSPClient->DecryptParam(pData, dwBytesRead);
  324. // Verify MAC returned by Read on the SP
  325. CORg( pSPClient->MACInit(&hMAC) );
  326. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)pData, dwBytesRead) );
  327. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  328. CORg( pSPClient->MACFinal(hMAC, abMACVerify) );
  329. if (memcmp(abMACVerify, abTempMAC, WMDM_MAC_LENGTH) != 0)
  330. {
  331. CORg( WMDM_E_MAC_CHECK_FAILED );
  332. }
  333. // Create the MAC to send to ExamineData
  334. CORg( pSCClient->MACInit(&hMAC) );
  335. fuTempFlags = WMDM_SCP_EXAMINE_DATA;
  336. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuTempFlags), sizeof(fuTempFlags)) );
  337. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwExSize) );
  338. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwExSize), sizeof(dwExSize)) );
  339. CORg( pSCClient->MACFinal(hMAC, abTempMAC) );
  340. // Encrypt the pData Parameter
  341. pSCClient->EncryptParam(pData, dwExSize);
  342. CORg( pSecQuery->ExamineData(WMDM_SCP_EXAMINE_DATA, NULL, pData, dwExSize, abTempMAC) );
  343. CORg( pSCClient->DecryptParam(pData, dwExSize) );
  344. }
  345. if (hr == S_OK)
  346. {
  347. pSPClient->GetSessionKey(abSPSessionKey);
  348. // Create the MAC to send to GetRights
  349. pSCClient->MACInit(&hMAC);
  350. pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwRightsSize);
  351. pSCClient->MACUpdate(hMAC, (BYTE*)(&dwRightsSize), sizeof(dwRightsSize));
  352. pSCClient->MACUpdate(hMAC, (BYTE*)(abSPSessionKey), dwSessionKeyLen);
  353. pSCClient->MACUpdate(hMAC, (BYTE*)(&dwSessionKeyLen), sizeof(dwSessionKeyLen));
  354. pSCClient->MACFinal(hMAC, abTempMAC);
  355. // Encrypt the pData Parameter
  356. CORg( pSCClient->EncryptParam(pData, dwRightsSize) );
  357. CORg( pSCClient->EncryptParam((BYTE*)abSPSessionKey, dwSessionKeyLen) );
  358. CORg( pSecQuery->GetRights(pData,
  359. dwRightsSize,
  360. (BYTE*)abSPSessionKey,
  361. dwSessionKeyLen,
  362. pStgGlobals,
  363. ppRights,
  364. pnRightsCount,
  365. abTempMAC) );
  366. // Verify MAC returned by GetRights
  367. pSCClient->MACInit(&hMAC);
  368. pSCClient->MACUpdate(hMAC, (BYTE*)(*ppRights), sizeof(WMDMRIGHTS) * (*pnRightsCount));
  369. pSCClient->MACUpdate(hMAC, (BYTE*)(pnRightsCount), sizeof(*pnRightsCount));
  370. pSCClient->MACFinal(hMAC, abMACVerify);
  371. if (memcmp(abMACVerify, abTempMAC, WMDM_MAC_LENGTH) != 0)
  372. {
  373. hr = WMDM_E_MAC_CHECK_FAILED;
  374. goto exit;
  375. }
  376. break;
  377. }
  378. pObject->Release();
  379. pObject = NULL;
  380. pSecQuery->Release();
  381. pSecQuery = NULL;
  382. }
  383. }
  384. if (SUCCEEDED(hr))
  385. {
  386. // Create the MAC to return to caller
  387. g_pAppSCServer->MACInit(&hMAC);
  388. g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(*ppRights), sizeof(WMDMRIGHTS) * (*pnRightsCount));
  389. g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pnRightsCount), sizeof(*pnRightsCount));
  390. g_pAppSCServer->MACFinal(hMAC, abMac);
  391. }
  392. Error:
  393. exit:
  394. SAFE_ARRAY_DELETE(pData);
  395. SAFE_RELEASE(pObject);
  396. SAFE_RELEASE(pSecureAuth);
  397. SAFE_RELEASE(pSecQuery);
  398. SAFE_RELEASE(pStgGlobals);
  399. hrLogDWORD("IWMDMStorage::GetRights returned 0x%08lx", hr, hr);
  400. return hr;
  401. }
  402. HRESULT CWMDMStorage::EnumStorage(IWMDMEnumStorage **ppEnumStorage)
  403. {
  404. HRESULT hr;
  405. CComObject<CWMDMStorageEnum> *pEnumObj = NULL;
  406. IMDSPEnumStorage *pEnumStg = NULL;
  407. if (g_pAppSCServer)
  408. {
  409. if(!g_pAppSCServer->fIsAuthenticated())
  410. {
  411. hr = WMDM_E_NOTCERTIFIED;
  412. goto exit;
  413. }
  414. }
  415. else
  416. {
  417. hr = E_FAIL;
  418. goto exit;
  419. }
  420. CARg( ppEnumStorage );
  421. CORg( m_pStorage->EnumStorage(&pEnumStg) );
  422. CORg( CComObject<CWMDMStorageEnum>::CreateInstance(&pEnumObj) );
  423. hr = pEnumObj->QueryInterface(IID_IWMDMEnumStorage, reinterpret_cast<void**>(ppEnumStorage));
  424. if (FAILED(hr))
  425. {
  426. delete pEnumObj;
  427. goto exit;
  428. }
  429. pEnumObj->SetContainedPointer(pEnumStg, m_wSPIndex);
  430. exit:
  431. Error:
  432. SAFE_RELEASE(pEnumStg);
  433. hrLogDWORD("IWMDMStorage::EnumStorage returned 0x%08lx", hr, hr);
  434. return hr;
  435. }
  436. HRESULT CWMDMStorage::SendOpaqueCommand(OPAQUECOMMAND *pCommand)
  437. {
  438. HRESULT hr;
  439. HMAC hMAC;
  440. BYTE abTempMAC[WMDM_MAC_LENGTH];
  441. CSecureChannelClient *pSPClient = NULL;
  442. if (g_pAppSCServer)
  443. {
  444. if(!g_pAppSCServer->fIsAuthenticated())
  445. {
  446. CORg( WMDM_E_NOTCERTIFIED );
  447. }
  448. }
  449. else
  450. {
  451. CORg( E_FAIL );
  452. }
  453. if( pCommand == NULL ||
  454. ((pCommand->pData == NULL) && (pCommand->dwDataLen > 0)) )
  455. {
  456. CORg( E_INVALIDARG );
  457. }
  458. g_pSPs[m_wSPIndex]->GetSCClient(&pSPClient);
  459. if (!pSPClient)
  460. {
  461. CORg( E_FAIL );
  462. }
  463. // Verify MAC on command
  464. CORg( g_pAppSCServer->MACInit(&hMAC) );
  465. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(pCommand->guidCommand)) );
  466. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) );
  467. if (pCommand->pData)
  468. {
  469. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) );
  470. }
  471. CORg( g_pAppSCServer->MACFinal(hMAC, (BYTE*)abTempMAC) );
  472. if (memcmp((BYTE*)(pCommand->abMAC), abTempMAC, WMDM_MAC_LENGTH) != 0)
  473. {
  474. CORg( WMDM_E_MAC_CHECK_FAILED );
  475. }
  476. // Convert the MAC for the SP
  477. CORg( pSPClient->MACInit(&hMAC) );
  478. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(pCommand->guidCommand)) );
  479. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) );
  480. if (pCommand->pData)
  481. {
  482. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) );
  483. }
  484. CORg( pSPClient->MACFinal(hMAC, (BYTE*)(pCommand->abMAC)) );
  485. CORg( m_pStorage->SendOpaqueCommand(pCommand) );
  486. // Verify the MAC returned by the SP
  487. CORg( pSPClient->MACInit(&hMAC) );
  488. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(pCommand->guidCommand)) );
  489. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) );
  490. if (pCommand->pData)
  491. {
  492. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) );
  493. }
  494. CORg( pSPClient->MACFinal(hMAC, (BYTE*)abTempMAC) );
  495. if (memcmp((BYTE*)(pCommand->abMAC), abTempMAC, WMDM_MAC_LENGTH) != 0)
  496. {
  497. CORg( WMDM_E_MAC_CHECK_FAILED );
  498. }
  499. // Convert the MAC to send back to the Application
  500. CORg( g_pAppSCServer->MACInit(&hMAC) );
  501. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(pCommand->guidCommand)) );
  502. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) );
  503. if (pCommand->pData)
  504. {
  505. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) );
  506. }
  507. CORg( g_pAppSCServer->MACFinal(hMAC, (BYTE*)(pCommand->abMAC)) );
  508. Error:
  509. hrLogDWORD("IWMDMStorage::SendOpaqueCommand returned 0x%08lx", hr, hr);
  510. return hr;
  511. }
  512. // IWMDMStorage2
  513. HRESULT CWMDMStorage::GetStorage( LPCWSTR pszStorageName, IWMDMStorage** ppStorage )
  514. {
  515. HRESULT hr;
  516. IMDSPStorage2* pStorage2 = NULL;
  517. IMDSPStorage* pMDSPStorageFound = NULL;
  518. IMDSPStorage* pMDSubStorage = NULL;
  519. CComObject<CWMDMStorage>* pStgObj = NULL;
  520. CARg( ppStorage );
  521. CARg( pszStorageName );
  522. if (g_pAppSCServer)
  523. {
  524. if(!g_pAppSCServer->fIsAuthenticated())
  525. {
  526. CORg( WMDM_E_NOTCERTIFIED );
  527. }
  528. }
  529. else
  530. {
  531. CORg( E_FAIL );
  532. }
  533. // Get the Storage pointer from the SP (as a IMDSPStorage2)
  534. hr = m_pStorage->QueryInterface(IID_IMDSPStorage2, reinterpret_cast<void**>(&pStorage2));
  535. if( SUCCEEDED(hr) )
  536. {
  537. hr = pStorage2->GetStorage( pszStorageName, &pMDSPStorageFound );
  538. }
  539. // This functionalty is not implemented by the SP. Find the storage by enumerating all storages
  540. if( hr == E_NOTIMPL || hr == E_NOINTERFACE )
  541. {
  542. IMDSPEnumStorage *pEnum = NULL;
  543. WCHAR pswzMDSubStorageName[MAX_PATH];
  544. ULONG ulFetched;
  545. CORg(m_pStorage->EnumStorage(&pEnum));
  546. while( S_OK == pEnum->Next(1, &pMDSubStorage, &ulFetched) )
  547. {
  548. hr = pMDSubStorage->GetName( pswzMDSubStorageName, MAX_PATH );
  549. if( SUCCEEDED(hr) && ( _wcsicmp( pswzMDSubStorageName, pszStorageName ) == 0 ) )
  550. {
  551. // We have found the storage we are looking for.
  552. pMDSPStorageFound = pMDSubStorage;
  553. break;
  554. }
  555. pMDSubStorage->Release();
  556. }
  557. pEnum->Release();
  558. }
  559. // Create a IWMDMStorage object and connect it to the the storage from the SP
  560. if( pMDSPStorageFound != NULL )
  561. {
  562. CORg( CComObject<CWMDMStorage>::CreateInstance(&pStgObj) );
  563. CORg( pStgObj->QueryInterface(IID_IWMDMStorage, reinterpret_cast<void**>(ppStorage)) );
  564. pStgObj->SetContainedPointer(pMDSPStorageFound, m_wSPIndex);
  565. }
  566. // Did not find a matching storage
  567. else if( SUCCEEDED(hr) )
  568. {
  569. hr = S_FALSE;
  570. }
  571. Error:
  572. SAFE_RELEASE(pStorage2);
  573. if( hr != S_OK )
  574. {
  575. ppStorage = NULL;
  576. SAFE_DELETE( pStgObj );
  577. }
  578. hrLogDWORD("IWMDMDevice2::GetStorage returned 0x%08lx", hr, hr);
  579. return hr;
  580. }
  581. HRESULT CWMDMStorage::SetAttributes2( DWORD dwAttributes,
  582. DWORD dwAttributesEx,
  583. _WAVEFORMATEX *pAudioFormat,
  584. _VIDEOINFOHEADER* pVideoFormat )
  585. {
  586. HRESULT hr;
  587. IMDSPStorage2* pStorage2 = NULL;
  588. if (g_pAppSCServer)
  589. {
  590. if(!g_pAppSCServer->fIsAuthenticated())
  591. {
  592. CORg( WMDM_E_NOTCERTIFIED );
  593. }
  594. }
  595. else
  596. {
  597. CORg( E_FAIL );
  598. }
  599. CORg( m_pStorage->QueryInterface( IID_IMDSPStorage2, reinterpret_cast<void**>(&pStorage2) ) );
  600. CORg( pStorage2->SetAttributes2(dwAttributes,
  601. dwAttributesEx,
  602. pAudioFormat,
  603. pVideoFormat) );
  604. Error:
  605. SAFE_RELEASE(pStorage2);
  606. hrLogDWORD("IWMDMStorage2::SetAttributes2 returned 0x%08lx", hr, hr);
  607. return hr;
  608. }
  609. HRESULT CWMDMStorage::GetAttributes2( DWORD *pdwAttributes,
  610. DWORD *pdwAttributesEx,
  611. _WAVEFORMATEX *pAudioFormat,
  612. _VIDEOINFOHEADER* pVideoFormat )
  613. {
  614. HRESULT hr;
  615. IMDSPStorage2* pStorage2 = NULL;
  616. if (g_pAppSCServer)
  617. {
  618. if(!g_pAppSCServer->fIsAuthenticated())
  619. {
  620. CORg( WMDM_E_NOTCERTIFIED );
  621. }
  622. }
  623. else
  624. {
  625. CORg( E_FAIL );
  626. }
  627. CORg( m_pStorage->QueryInterface( IID_IMDSPStorage2, reinterpret_cast<void**>(&pStorage2) ) );
  628. CORg( pStorage2->GetAttributes2( pdwAttributes,
  629. pdwAttributesEx,
  630. pAudioFormat,
  631. pVideoFormat) );
  632. Error:
  633. SAFE_RELEASE(pStorage2);
  634. hrLogDWORD("IWMDMStorage2::GetAttributes2 returned 0x%08lx", hr, hr);
  635. return hr;
  636. }
  637. // IWMDMStorageControl
  638. HRESULT CWMDMStorage::Insert(UINT fuMode,
  639. LPWSTR pwszFile,
  640. IWMDMOperation *pOperation,
  641. IWMDMProgress *pProgress,
  642. IWMDMStorage **ppNewObject)
  643. {
  644. HRESULT hr = S_OK;
  645. CORg( Insert2( fuMode,
  646. pwszFile,
  647. NULL,
  648. pOperation,
  649. pProgress,
  650. NULL,
  651. ppNewObject ) );
  652. Error:
  653. hrLogDWORD("IWMDMStorageControl::Insert returned 0x%08lx", hr, hr);
  654. return hr;
  655. }
  656. // IWMDMStorageControl2
  657. HRESULT CWMDMStorage::Insert2(UINT fuMode,
  658. LPWSTR pwszFileSource,
  659. LPWSTR pwszFileDest,
  660. IWMDMOperation* pOperation,
  661. IWMDMProgress* pProgress,
  662. IUnknown* pUnknown,
  663. IWMDMStorage** ppNewObject)
  664. {
  665. HRESULT hr = S_OK;
  666. HANDLE hThread;
  667. DWORD dwThreadID;
  668. INSERTTHREADARGS *pThreadArgs = NULL;
  669. if (g_pAppSCServer)
  670. {
  671. if(!g_pAppSCServer->fIsAuthenticated())
  672. {
  673. hr = WMDM_E_NOTCERTIFIED;
  674. goto exit;
  675. }
  676. }
  677. else
  678. {
  679. hr = E_FAIL;
  680. goto exit;
  681. }
  682. if (fuMode & WMDM_CONTENT_OPERATIONINTERFACE)
  683. {
  684. CARg(pOperation);
  685. }
  686. else
  687. {
  688. CARg(pwszFileSource);
  689. }
  690. if (fuMode & WMDM_MODE_BLOCK)
  691. {
  692. hr = InsertWorker(fuMode,
  693. pwszFileSource,
  694. pwszFileDest,
  695. pOperation,
  696. pProgress,
  697. pUnknown,
  698. ppNewObject);
  699. }
  700. else if (fuMode & WMDM_MODE_THREAD)
  701. {
  702. pThreadArgs = new INSERTTHREADARGS;
  703. CPRg(pThreadArgs);
  704. memset(pThreadArgs, 0, sizeof(INSERTTHREADARGS));
  705. pThreadArgs->pThis = this;
  706. pThreadArgs->fuMode = fuMode;
  707. if (!(fuMode & WMDM_CONTENT_OPERATIONINTERFACE))
  708. {
  709. pThreadArgs->pwszFileSource = new WCHAR[wcslen(pwszFileSource) + 1];
  710. CPRg( pThreadArgs->pwszFileSource );
  711. wcscpy(pThreadArgs->pwszFileSource, pwszFileSource );
  712. }
  713. else
  714. {
  715. // Need to mashal callback interfaces since we are passing it to another thread.
  716. hr = CoMarshalInterThreadInterfaceInStream( __uuidof(IWMDMOperation),
  717. pOperation,
  718. &pThreadArgs->pOperationStream );
  719. }
  720. if( pwszFileDest )
  721. {
  722. pThreadArgs->pwszFileDest = new WCHAR[wcslen(pwszFileDest) + 1];
  723. CPRg( pThreadArgs->pwszFileDest );
  724. wcscpy(pThreadArgs->pwszFileDest, pwszFileDest);
  725. }
  726. if (pProgress)
  727. {
  728. // Need to mashal callback interfaces since we are passing it to another thread.
  729. hr = CoMarshalInterThreadInterfaceInStream( __uuidof(IWMDMProgress),
  730. pProgress,
  731. &pThreadArgs->pProgressStream );
  732. }
  733. if (pUnknown)
  734. {
  735. // Need to mashal callback interfaces since we are passing it to another thread.
  736. hr = CoMarshalInterThreadInterfaceInStream( __uuidof(IUnknown),
  737. pUnknown,
  738. &pThreadArgs->pUnknownStream );
  739. }
  740. pThreadArgs->ppNewObject = ppNewObject;
  741. pThreadArgs->pThis->AddRef();
  742. hThread = CreateThread(NULL, 0, InsertThreadFunc, (void*)pThreadArgs, 0, &dwThreadID);
  743. if (!hThread)
  744. {
  745. pThreadArgs->pThis->Release();
  746. hr = E_FAIL;
  747. goto exit;
  748. }
  749. CloseHandle(hThread);
  750. }
  751. else
  752. {
  753. hr = E_INVALIDARG;
  754. goto exit;
  755. }
  756. exit:
  757. Error:
  758. if ((FAILED(hr)) && (pThreadArgs))
  759. {
  760. SAFE_DELETE(pThreadArgs->pwszFileSource);
  761. SAFE_DELETE(pThreadArgs->pwszFileDest);
  762. SAFE_RELEASE(pThreadArgs->pOperationStream);
  763. SAFE_RELEASE(pThreadArgs->pProgressStream);
  764. SAFE_RELEASE(pThreadArgs->pUnknownStream);
  765. delete pThreadArgs;
  766. }
  767. hrLogDWORD("IWMDMStorageControl::Insert returned 0x%08lx", hr, hr);
  768. return hr;
  769. }
  770. HRESULT CWMDMStorage::Delete(UINT fuMode, IWMDMProgress *pProgress)
  771. {
  772. HRESULT hr = S_OK;
  773. HANDLE hThread;
  774. DWORD dwThreadID;
  775. DELETETHREADARGS *pThreadArgs = NULL;
  776. if (g_pAppSCServer)
  777. {
  778. if(!g_pAppSCServer->fIsAuthenticated())
  779. {
  780. hr = WMDM_E_NOTCERTIFIED;
  781. goto exit;
  782. }
  783. }
  784. else
  785. {
  786. hr = E_FAIL;
  787. goto exit;
  788. }
  789. if (fuMode & WMDM_MODE_BLOCK)
  790. {
  791. hr = DeleteWorker(fuMode, pProgress);
  792. if (FAILED(hr))
  793. {
  794. goto exit;
  795. }
  796. }
  797. else if (fuMode & WMDM_MODE_THREAD)
  798. {
  799. pThreadArgs = new DELETETHREADARGS;
  800. if (!pThreadArgs)
  801. {
  802. hr = E_OUTOFMEMORY;
  803. goto exit;
  804. }
  805. memset( pThreadArgs, 0, sizeof(DELETETHREADARGS) );
  806. pThreadArgs->pThis = this;
  807. if (pProgress)
  808. {
  809. // Need to mashal callback interfaces since we are passing it to another thread.
  810. hr = CoMarshalInterThreadInterfaceInStream( __uuidof(IWMDMProgress),
  811. pProgress,
  812. &pThreadArgs->pProgressStream );
  813. }
  814. pThreadArgs->fuMode = fuMode;
  815. pThreadArgs->pThis->AddRef();
  816. hThread = CreateThread(NULL, 0, DeleteThreadFunc, (void *)pThreadArgs, 0, &dwThreadID);
  817. if (!hThread)
  818. {
  819. pThreadArgs->pThis->Release();
  820. hr = E_FAIL;
  821. goto exit;
  822. }
  823. CloseHandle(hThread);
  824. }
  825. else
  826. {
  827. hr = E_INVALIDARG;
  828. goto exit;
  829. }
  830. exit:
  831. if ((FAILED(hr)) && (pThreadArgs))
  832. {
  833. SAFE_RELEASE(pThreadArgs->pProgressStream);
  834. delete pThreadArgs;
  835. }
  836. hrLogDWORD("IWMDMStorageControl::Delete returned 0x%08lx", hr, hr);
  837. return hr;
  838. }
  839. HRESULT CWMDMStorage::Rename(UINT fuMode,
  840. LPWSTR pwszNewName,
  841. IWMDMProgress *pProgress)
  842. {
  843. HRESULT hr = S_OK;
  844. RENAMETHREADARGS *pThreadArgs = NULL;
  845. HANDLE hThread;
  846. DWORD dwThreadID;
  847. if (g_pAppSCServer)
  848. {
  849. if(!g_pAppSCServer->fIsAuthenticated())
  850. {
  851. hr = WMDM_E_NOTCERTIFIED;
  852. goto exit;
  853. }
  854. }
  855. else
  856. {
  857. hr = E_FAIL;
  858. goto exit;
  859. }
  860. if ((!pwszNewName) || (wcslen(pwszNewName) == 0))
  861. {
  862. hr = E_INVALIDARG;
  863. goto exit;
  864. }
  865. if (fuMode & WMDM_MODE_BLOCK)
  866. {
  867. CORg( RenameWorker(pwszNewName, pProgress) );
  868. }
  869. else if (fuMode & WMDM_MODE_THREAD)
  870. {
  871. pThreadArgs = new RENAMETHREADARGS;
  872. CPRg( pThreadArgs );
  873. memset( pThreadArgs, 0, sizeof(RENAMETHREADARGS) );
  874. pThreadArgs->pThis = this;
  875. pThreadArgs->pwszNewName = new WCHAR[wcslen(pwszNewName) + 1];
  876. CPRg( pThreadArgs->pwszNewName );
  877. wcscpy(pThreadArgs->pwszNewName, pwszNewName);
  878. if (pProgress)
  879. {
  880. // Need to mashal callback interfaces since we are passing it to another thread.
  881. hr = CoMarshalInterThreadInterfaceInStream( __uuidof(IWMDMProgress),
  882. pProgress,
  883. &pThreadArgs->pProgressStream );
  884. }
  885. pThreadArgs->pThis->AddRef();
  886. hThread = CreateThread(NULL, 0, RenameThreadFunc, (void *)pThreadArgs, 0, &dwThreadID);
  887. if (!hThread)
  888. {
  889. pThreadArgs->pThis->Release();
  890. hr = E_FAIL;
  891. goto exit;
  892. }
  893. CloseHandle(hThread);
  894. }
  895. else
  896. {
  897. hr = E_INVALIDARG;
  898. goto exit;
  899. }
  900. exit:
  901. Error:
  902. if ((FAILED(hr)) && (pThreadArgs))
  903. {
  904. SAFE_DELETE(pThreadArgs->pwszNewName);
  905. SAFE_RELEASE(pThreadArgs->pProgressStream);
  906. delete pThreadArgs;
  907. }
  908. hrLogDWORD("IWMDMStorageControl::Rename returned 0x%08lx", hr, hr);
  909. return hr;
  910. }
  911. HRESULT CWMDMStorage::Read(UINT fuMode,
  912. LPWSTR pwszFile,
  913. IWMDMProgress *pProgress,
  914. IWMDMOperation *pOperation)
  915. {
  916. HRESULT hr = S_OK;
  917. READTHREADARGS *pThreadArgs = NULL;
  918. HANDLE hThread;
  919. DWORD dwThreadID;
  920. if (g_pAppSCServer)
  921. {
  922. if(!g_pAppSCServer->fIsAuthenticated())
  923. {
  924. hr = WMDM_E_NOTCERTIFIED;
  925. goto exit;
  926. }
  927. }
  928. else
  929. {
  930. hr = E_FAIL;
  931. goto exit;
  932. }
  933. if (fuMode & WMDM_MODE_BLOCK)
  934. {
  935. CORg( ReadWorker(fuMode, pwszFile, pProgress, pOperation) );
  936. }
  937. else if (fuMode & WMDM_MODE_THREAD)
  938. {
  939. pThreadArgs = new READTHREADARGS;
  940. CPRg( pThreadArgs );
  941. memset( pThreadArgs, 0, sizeof(READTHREADARGS));
  942. pThreadArgs->pThis = this;
  943. pThreadArgs->pwszFile = new WCHAR[wcslen(pwszFile) + 1];
  944. CPRg( pThreadArgs->pwszFile );
  945. wcscpy(pThreadArgs->pwszFile, pwszFile);
  946. if (pProgress)
  947. {
  948. // Need to mashal callback interfaces since we are passing it to another thread.
  949. hr = CoMarshalInterThreadInterfaceInStream( __uuidof(IWMDMProgress),
  950. pProgress,
  951. &pThreadArgs->pProgressStream );
  952. }
  953. if (pOperation)
  954. {
  955. // Need to mashal callback interfaces since we are passing it to another thread.
  956. hr = CoMarshalInterThreadInterfaceInStream( __uuidof(IWMDMOperation),
  957. pOperation,
  958. &pThreadArgs->pOperationStream );
  959. }
  960. pThreadArgs->pThis->AddRef();
  961. hThread = CreateThread(NULL, 0, ReadThreadFunc, (void *)pThreadArgs, 0, &dwThreadID);
  962. if (!hThread)
  963. {
  964. pThreadArgs->pThis->Release();
  965. hr = E_FAIL;
  966. goto exit;
  967. }
  968. CloseHandle(hThread);
  969. }
  970. else
  971. {
  972. hr = E_INVALIDARG;
  973. goto exit;
  974. }
  975. exit:
  976. Error:
  977. if ((FAILED(hr)) && (pThreadArgs))
  978. {
  979. SAFE_DELETE(pThreadArgs->pwszFile);
  980. SAFE_RELEASE(pThreadArgs->pProgressStream);
  981. SAFE_RELEASE(pThreadArgs->pOperationStream);
  982. delete pThreadArgs;
  983. }
  984. hrLogDWORD("IWMDMStorageControl::Read returned 0x%08lx", hr, hr);
  985. return hr;
  986. }
  987. HRESULT CWMDMStorage::Move(UINT fuMode,
  988. IWMDMStorage *pTargetObject,
  989. IWMDMProgress *pProgress)
  990. {
  991. HRESULT hr = S_OK;
  992. IMDSPObject *pObject = NULL;
  993. IMDSPStorage *pTargetStg = NULL;
  994. CComObject<CWMDMStorage> *pNewMDMStorage = NULL;
  995. if (g_pAppSCServer)
  996. {
  997. if(!g_pAppSCServer->fIsAuthenticated())
  998. {
  999. hr = WMDM_E_NOTCERTIFIED;
  1000. goto exit;
  1001. }
  1002. }
  1003. else
  1004. {
  1005. hr = E_FAIL;
  1006. goto exit;
  1007. }
  1008. CPRg(pTargetObject);
  1009. CORg( m_pStorage->QueryInterface(IID_IMDSPObject, reinterpret_cast<void**>(&pObject)) );
  1010. ((CWMDMStorage *)pTargetObject)->GetContainedPointer(&pTargetStg);
  1011. CORg( pObject->Move(fuMode,
  1012. pProgress,
  1013. pTargetStg) );
  1014. exit:
  1015. Error:
  1016. SAFE_RELEASE(pTargetStg);
  1017. SAFE_RELEASE(pObject);
  1018. hrLogDWORD("IWMDMStorageControl::Move returned 0x%08lx", hr, hr);
  1019. return hr;
  1020. }
  1021. // IWMDMObjectInfo
  1022. HRESULT CWMDMStorage::GetPlayLength(DWORD *pdwLength)
  1023. {
  1024. HRESULT hr;
  1025. IMDSPObjectInfo *pInfo = NULL;
  1026. if (g_pAppSCServer)
  1027. {
  1028. if(!g_pAppSCServer->fIsAuthenticated())
  1029. {
  1030. hr = WMDM_E_NOTCERTIFIED;
  1031. goto exit;
  1032. }
  1033. }
  1034. else
  1035. {
  1036. hr = E_FAIL;
  1037. goto exit;
  1038. }
  1039. CARg(pdwLength);
  1040. CORg( m_pStorage->QueryInterface(IID_IMDSPObjectInfo, reinterpret_cast<void**>(&pInfo)) );
  1041. CORg( pInfo->GetPlayLength(pdwLength) );
  1042. exit:
  1043. Error:
  1044. SAFE_RELEASE(pInfo);
  1045. hrLogDWORD("IWMDMObjectInfo::GetPlayLength returned 0x%08lx", hr, hr);
  1046. return hr;
  1047. }
  1048. HRESULT CWMDMStorage::SetPlayLength(DWORD dwLength)
  1049. {
  1050. HRESULT hr;
  1051. IMDSPObjectInfo *pInfo = NULL;
  1052. if (g_pAppSCServer)
  1053. {
  1054. if(!g_pAppSCServer->fIsAuthenticated())
  1055. {
  1056. hr = WMDM_E_NOTCERTIFIED;
  1057. goto exit;
  1058. }
  1059. }
  1060. else
  1061. {
  1062. hr = E_FAIL;
  1063. goto exit;
  1064. }
  1065. CORg( m_pStorage->QueryInterface(IID_IMDSPObjectInfo, reinterpret_cast<void**>(&pInfo)) );
  1066. CORg( pInfo->SetPlayLength(dwLength) );
  1067. exit:
  1068. Error:
  1069. SAFE_RELEASE(pInfo);
  1070. hrLogDWORD("IWMDMObjectInfo::SetPlayLength returned 0x%08lx", hr, hr);
  1071. return hr;
  1072. }
  1073. HRESULT CWMDMStorage::GetPlayOffset(DWORD *pdwOffset)
  1074. {
  1075. HRESULT hr;
  1076. IMDSPObjectInfo *pInfo = NULL;
  1077. if (g_pAppSCServer)
  1078. {
  1079. if(!g_pAppSCServer->fIsAuthenticated())
  1080. {
  1081. hr = WMDM_E_NOTCERTIFIED;
  1082. goto exit;
  1083. }
  1084. }
  1085. else
  1086. {
  1087. hr = E_FAIL;
  1088. goto exit;
  1089. }
  1090. CARg(pdwOffset);
  1091. CORg( m_pStorage->QueryInterface(IID_IMDSPObjectInfo, reinterpret_cast<void**>(&pInfo)) );
  1092. CORg( pInfo->GetPlayOffset(pdwOffset) );
  1093. exit:
  1094. Error:
  1095. SAFE_RELEASE(pInfo);
  1096. hrLogDWORD("IWMDMObjectInfo::GetPlayOffset returned 0x%08lx", hr, hr);
  1097. return hr;
  1098. }
  1099. HRESULT CWMDMStorage::SetPlayOffset(DWORD dwOffset)
  1100. {
  1101. HRESULT hr;
  1102. IMDSPObjectInfo *pInfo = NULL;
  1103. if (g_pAppSCServer)
  1104. {
  1105. if(!g_pAppSCServer->fIsAuthenticated())
  1106. {
  1107. hr = WMDM_E_NOTCERTIFIED;
  1108. goto exit;
  1109. }
  1110. }
  1111. else
  1112. {
  1113. hr = E_FAIL;
  1114. goto exit;
  1115. }
  1116. CORg( m_pStorage->QueryInterface(IID_IMDSPObjectInfo, reinterpret_cast<void**>(&pInfo)) );
  1117. CORg( pInfo->SetPlayOffset(dwOffset) );
  1118. exit:
  1119. Error:
  1120. SAFE_RELEASE(pInfo);
  1121. hrLogDWORD("IWMDMObjectInfo::SetPlayOffset returned 0x%08lx", hr, hr);
  1122. return hr;
  1123. }
  1124. HRESULT CWMDMStorage::GetTotalLength(DWORD *pdwLength)
  1125. {
  1126. HRESULT hr;
  1127. IMDSPObjectInfo *pInfo = NULL;
  1128. if (g_pAppSCServer)
  1129. {
  1130. if(!g_pAppSCServer->fIsAuthenticated())
  1131. {
  1132. hr = WMDM_E_NOTCERTIFIED;
  1133. goto exit;
  1134. }
  1135. }
  1136. else
  1137. {
  1138. hr = E_FAIL;
  1139. goto exit;
  1140. }
  1141. CARg( pdwLength);
  1142. CORg( m_pStorage->QueryInterface(IID_IMDSPObjectInfo, reinterpret_cast<void**>(&pInfo)) );
  1143. CORg( pInfo->GetTotalLength(pdwLength) );
  1144. exit:
  1145. Error:
  1146. if (pInfo)
  1147. pInfo->Release();
  1148. hrLogDWORD("IWMDMObjectInfo::GetTotalLength returned 0x%08lx", hr, hr);
  1149. return hr;
  1150. }
  1151. HRESULT CWMDMStorage::GetLastPlayPosition(DWORD *pdwLastPos)
  1152. {
  1153. HRESULT hr;
  1154. IMDSPObjectInfo *pInfo = NULL;
  1155. if (g_pAppSCServer)
  1156. {
  1157. if(!g_pAppSCServer->fIsAuthenticated())
  1158. {
  1159. hr = WMDM_E_NOTCERTIFIED;
  1160. goto exit;
  1161. }
  1162. }
  1163. else
  1164. {
  1165. hr = E_FAIL;
  1166. goto exit;
  1167. }
  1168. if (!pdwLastPos)
  1169. {
  1170. hr = E_INVALIDARG;
  1171. goto exit;
  1172. }
  1173. CORg( m_pStorage->QueryInterface(IID_IMDSPObjectInfo, reinterpret_cast<void**>(&pInfo)) );
  1174. CORg( pInfo->GetLastPlayPosition(pdwLastPos) );
  1175. exit:
  1176. Error:
  1177. if (pInfo)
  1178. pInfo->Release();
  1179. hrLogDWORD("IWMDMObjectInfo::GetLastPlayPosition returned 0x%08lx", hr, hr);
  1180. return hr;
  1181. }
  1182. HRESULT CWMDMStorage::GetLongestPlayPosition(DWORD *pdwLongestPos)
  1183. {
  1184. HRESULT hr;
  1185. IMDSPObjectInfo *pInfo = NULL;
  1186. if (g_pAppSCServer)
  1187. {
  1188. if(!g_pAppSCServer->fIsAuthenticated())
  1189. {
  1190. hr = WMDM_E_NOTCERTIFIED;
  1191. goto exit;
  1192. }
  1193. }
  1194. else
  1195. {
  1196. hr = E_FAIL;
  1197. goto exit;
  1198. }
  1199. CARg( pdwLongestPos);
  1200. CORg( m_pStorage->QueryInterface(IID_IMDSPObjectInfo, reinterpret_cast<void**>(&pInfo)) );
  1201. CORg( pInfo->GetLongestPlayPosition(pdwLongestPos) );
  1202. exit:
  1203. Error:
  1204. if (pInfo)
  1205. pInfo->Release();
  1206. hrLogDWORD("IWMDMObjectInfo::GetLongestPlayPosition returned 0x%08lx", hr, hr);
  1207. return hr;
  1208. }
  1209. void CWMDMStorage::SetContainedPointer(IMDSPStorage *pStorage, WORD wSPIndex)
  1210. {
  1211. m_pStorage = pStorage;
  1212. m_pStorage->AddRef();
  1213. m_wSPIndex = wSPIndex;
  1214. return;
  1215. }
  1216. void CWMDMStorage::GetContainedPointer(IMDSPStorage **ppStorage)
  1217. {
  1218. *ppStorage = m_pStorage;
  1219. (*ppStorage)->AddRef();
  1220. return;
  1221. }
  1222. HRESULT CWMDMStorage::hrCopyToStorageFromFile( UINT fuMode, LPWSTR pwszFileName,
  1223. UINT uNewStorageMode, LPWCH wszNewStorageName,
  1224. IWMDMStorage*& pNewIWMDMStorage,
  1225. IWMDMProgress *pProgress,
  1226. IUnknown* pUnknown, BOOL fQuery)
  1227. {
  1228. USES_CONVERSION;
  1229. HRESULT hr;
  1230. HANDLE hFile = INVALID_HANDLE_VALUE;
  1231. DWORD dwBytesRead;
  1232. DWORD dwBytesWrite;
  1233. BYTE *pData = NULL;
  1234. BOOL fRetVal;
  1235. CComObject<CWMDMStorage> *pNewWMDMStorage = NULL;
  1236. IMDSPStorage *pNewSPStorage = NULL;
  1237. ISCPSecureAuthenticate *pSecureAuth = NULL;
  1238. ISCPSecureQuery *pSecQuery = NULL;
  1239. ISCPSecureQuery2 *pSecQuery2 = NULL;
  1240. ISCPSecureExchange *pSecExch = NULL;
  1241. IMDSPObject *pObject = NULL;
  1242. IMDSPStorageGlobals *pStgGlobals = NULL;
  1243. IMDSPDevice *pDevice = NULL;
  1244. IMDSPStorage2* pStorage2 = NULL;
  1245. WORD wCurSCP=0;
  1246. UINT fuFlags;
  1247. DWORD dwExSize;
  1248. DWORD dwMDSize;
  1249. DWORD dwRightsSize;
  1250. DWORD dwBufferSize=WMDM_TRANSFER_BUFFER_SIZE;
  1251. BOOL fUseSCP = FALSE; // Should data be passed throw an SCP?
  1252. BOOL fUsedSCP = FALSE; // Was an SCP used to do the file transfer?
  1253. UINT fuReadyFlags;
  1254. DWORD dwType;
  1255. ULONGLONG qwFileSizeSource;
  1256. ULONGLONG qwFileSizeDest;
  1257. DWORD dwTicks = 0;
  1258. UINT nDecideFlags;
  1259. CSecureChannelClient *pSCClient = NULL;
  1260. CSecureChannelClient *pSPClient = NULL;
  1261. HMAC hMAC;
  1262. BYTE abMAC[WMDM_MAC_LENGTH];
  1263. BYTE abMACVerify[WMDM_MAC_LENGTH];
  1264. UINT fuTempFlags;
  1265. DWORD dwAppSec;
  1266. BOOL fBeginCalled = FALSE;
  1267. DWORD dwSPAppSec;
  1268. DWORD dwAPPAppSec;
  1269. LPWSTR pwszFileExt = NULL;
  1270. DWORD dwSessionKeyLen = SAC_SESSION_KEYLEN;
  1271. BYTE abSPSessionKey[SAC_SESSION_KEYLEN];
  1272. BOOL fOpen = FALSE;
  1273. DWORD dwVersion;
  1274. BOOL bEOF = FALSE;
  1275. BOOL bFlushSCP = FALSE;
  1276. DWORD dwAppAppCertLen; // Length of AppCert of application
  1277. DWORD dwSPAppCertLen; // Length of AppCert of SP
  1278. BYTE* pAppAppCert = NULL; // Buffer to hold App AppCert
  1279. BYTE* pSPAppCert = NULL; // Buffer to hold SP AppCert
  1280. #ifdef DUMP_FILE
  1281. FILE *hFileDump = NULL;
  1282. #endif
  1283. // Clear revocation status
  1284. CoTaskMemFree( m_pwszRevocationURL );
  1285. m_pwszRevocationURL = NULL;
  1286. m_dwRevocationURLLen = 0;
  1287. m_dwRevocationBitFlag = 0;
  1288. pData = new BYTE[WMDM_TRANSFER_BUFFER_SIZE];
  1289. if (!pData)
  1290. {
  1291. hr = E_OUTOFMEMORY;
  1292. goto exit;
  1293. }
  1294. g_pSPs[m_wSPIndex]->GetSCClient(&pSPClient);
  1295. if (!pSPClient)
  1296. {
  1297. hr = E_FAIL;
  1298. goto exit;
  1299. }
  1300. dwVersion = GetVersion();
  1301. if (dwVersion < 0x80000000)
  1302. {
  1303. hFile = CreateFileW(pwszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1304. }
  1305. else
  1306. {
  1307. hFile = CreateFileA(W2A(pwszFileName), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1308. }
  1309. if (hFile == INVALID_HANDLE_VALUE)
  1310. {
  1311. hr = HRESULT_FROM_WIN32(GetLastError());
  1312. goto exit;
  1313. }
  1314. // If we are reporting progress then we need to tell the app how many ticks we think there will be
  1315. qwFileSizeSource = (ULONGLONG)GetFileSize(hFile, NULL);
  1316. if (pProgress)
  1317. {
  1318. fBeginCalled = TRUE;
  1319. hr = pProgress->Begin((DWORD)qwFileSizeSource);
  1320. if (FAILED(hr))
  1321. {
  1322. goto exit;
  1323. }
  1324. }
  1325. CORg( m_pStorage->GetStorageGlobals(&pStgGlobals) );
  1326. if( g_pSCPs == NULL )
  1327. {
  1328. CMediaDevMgr::LoadSCPs();
  1329. }
  1330. // Find the right scp
  1331. for( wCurSCP = 0; wCurSCP < g_wSCPCount; wCurSCP++ )
  1332. {
  1333. hr = g_pSCPs[wCurSCP]->hrGetInterface(&pSecureAuth);
  1334. if (FAILED(hr))
  1335. {
  1336. goto exit;
  1337. }
  1338. g_pSCPs[wCurSCP]->GetSCClient(&pSCClient);
  1339. if (!pSCClient)
  1340. {
  1341. hr = E_FAIL;
  1342. goto exit;
  1343. }
  1344. CORg( pSecureAuth->GetSecureQuery(&pSecQuery) );
  1345. pSecureAuth->Release();
  1346. pSecureAuth = NULL;
  1347. // GetDataDemands has no incoming MAC so lets clear the buffer.
  1348. CORg( pSecQuery->GetDataDemands(&fuFlags, &dwRightsSize, &dwExSize, &dwMDSize, abMAC));
  1349. // Verify MAC returned by GetDataDemands
  1350. CORg( pSCClient->MACInit(&hMAC) );
  1351. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuFlags), sizeof(fuFlags)));
  1352. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwRightsSize), sizeof(dwRightsSize)));
  1353. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwExSize), sizeof(dwExSize)) );
  1354. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwMDSize), sizeof(dwMDSize)) );
  1355. CORg( pSCClient->MACFinal(hMAC, abMACVerify) );
  1356. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  1357. {
  1358. hr = WMDM_E_MAC_CHECK_FAILED;
  1359. goto exit;
  1360. }
  1361. if (!(fuFlags & (WMDM_SCP_EXAMINE_DATA | WMDM_SCP_DECIDE_DATA | WMDM_SCP_EXAMINE_EXTENSION)))
  1362. {
  1363. continue;
  1364. }
  1365. // If the SCP asked for the file extension then get it from the File
  1366. if (fuFlags & WMDM_SCP_EXAMINE_EXTENSION)
  1367. {
  1368. // Only get the file extension once
  1369. if (!pwszFileExt)
  1370. {
  1371. pwszFileExt = new WCHAR[64];
  1372. if (!pwszFileExt)
  1373. {
  1374. hr = E_OUTOFMEMORY;
  1375. goto exit;
  1376. }
  1377. if (NULL != wcschr(pwszFileName, L'.'))
  1378. {
  1379. wcsncpy(pwszFileExt, (LPWSTR)(wcsrchr(pwszFileName, L'.') + 1), 64);
  1380. }
  1381. else
  1382. {
  1383. SAFE_ARRAY_DELETE(pwszFileExt);
  1384. }
  1385. }
  1386. }
  1387. if (dwBufferSize < (dwExSize>dwMDSize?dwExSize:dwMDSize))
  1388. {
  1389. SAFE_ARRAY_DELETE(pData);
  1390. dwBufferSize = dwExSize>dwMDSize?dwExSize:dwMDSize;
  1391. pData = new BYTE[dwBufferSize];
  1392. if (!pData)
  1393. {
  1394. hr = E_OUTOFMEMORY;
  1395. goto exit;
  1396. }
  1397. }
  1398. // ExamineData
  1399. hr = WMDM_E_MOREDATA;
  1400. while (hr == WMDM_E_MOREDATA)
  1401. {
  1402. fRetVal = ReadFile(hFile, pData, dwBufferSize, &dwBytesRead, NULL);
  1403. if (!fRetVal)
  1404. {
  1405. hr = E_FAIL;
  1406. goto exit;
  1407. }
  1408. // Create the MAC to send to ExamineData
  1409. CORg( pSCClient->MACInit(&hMAC) );
  1410. fuTempFlags = WMDM_SCP_EXAMINE_DATA;
  1411. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuTempFlags), sizeof(fuTempFlags)));
  1412. if (pwszFileExt)
  1413. {
  1414. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pwszFileExt), 2 * wcslen(pwszFileExt)));
  1415. }
  1416. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesRead) );
  1417. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)));
  1418. CORg( pSCClient->MACFinal(hMAC, abMAC) );
  1419. // Encrypt the pData Parameter
  1420. CORg( pSCClient->EncryptParam(pData, dwBytesRead));
  1421. CORg( pSecQuery->ExamineData(fuTempFlags, pwszFileExt, pData, dwBytesRead, abMAC));
  1422. }
  1423. if (0xffffffff == SetFilePointer(hFile, 0, NULL, FILE_BEGIN))
  1424. {
  1425. goto exit;
  1426. }
  1427. // MakeDecision
  1428. if (hr == S_OK)
  1429. {
  1430. nDecideFlags = WMDM_SCP_DECIDE_DATA;
  1431. if(fuMode & WMDM_MODE_TRANSFER_UNPROTECTED)
  1432. {
  1433. nDecideFlags |= WMDM_SCP_UNPROTECTED_OUTPUT;
  1434. }
  1435. if(fuMode & WMDM_MODE_TRANSFER_PROTECTED)
  1436. {
  1437. nDecideFlags |= WMDM_SCP_PROTECTED_OUTPUT;
  1438. }
  1439. // If the SCP supports ISCPSecQuery2 use it as a first choice
  1440. hr = pSecQuery->QueryInterface( IID_ISCPSecureQuery2, (void**)(&pSecQuery2) );
  1441. CORg( g_pAppSCServer->GetAppSec(NULL, &dwAPPAppSec));
  1442. CORg( pSPClient->GetAppSec(NULL, &dwSPAppSec));
  1443. // Appsec = min(appsec app, appsec SP )
  1444. dwAppSec = dwSPAppSec>dwAPPAppSec?dwAPPAppSec:dwSPAppSec;
  1445. hr = WMDM_E_MOREDATA;
  1446. while (hr == WMDM_E_MOREDATA)
  1447. {
  1448. fRetVal = ReadFile(hFile, pData, dwBufferSize, &dwBytesRead, NULL);
  1449. if (!fRetVal)
  1450. {
  1451. hr = E_FAIL;
  1452. goto exit;
  1453. }
  1454. CORg( pSPClient->GetSessionKey((BYTE*)abSPSessionKey));
  1455. CORg( pSCClient->MACInit(&hMAC) );
  1456. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&nDecideFlags), sizeof(nDecideFlags)));
  1457. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesRead) );
  1458. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  1459. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwAppSec), sizeof(dwAppSec)));
  1460. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(abSPSessionKey), dwSessionKeyLen));
  1461. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwSessionKeyLen), sizeof(dwSessionKeyLen)));
  1462. // Encrypt the pData Parameter
  1463. CORg( pSCClient->EncryptParam(pData, dwBytesRead) );
  1464. CORg( pSCClient->EncryptParam((BYTE*)abSPSessionKey, dwSessionKeyLen));
  1465. // Use MakeDecision2 and pass in AppCerts of App, SP to check for revocation
  1466. if( pSecQuery2 && (hr == S_OK) )
  1467. {
  1468. // Get the AppCert of the App
  1469. g_pAppSCServer->GetRemoteAppCert( NULL, &dwAppAppCertLen );
  1470. CFRg( dwAppAppCertLen != NULL );
  1471. SAFE_ARRAY_DELETE(pAppAppCert);
  1472. pAppAppCert = new BYTE[dwAppAppCertLen];
  1473. CPRg( pAppAppCert );
  1474. g_pAppSCServer->GetRemoteAppCert( pAppAppCert, &dwAppAppCertLen );
  1475. // Get the AppCert of the SP
  1476. pSPClient->GetRemoteAppCert( NULL, &dwSPAppCertLen );
  1477. CFRg( dwSPAppCertLen != NULL )
  1478. SAFE_ARRAY_DELETE(pSPAppCert);
  1479. pSPAppCert = new BYTE[dwSPAppCertLen];
  1480. CPRg( pSPAppCert );
  1481. pSPClient->GetRemoteAppCert( pSPAppCert, &dwSPAppCertLen );
  1482. // Update mac:ing with the AppCert parameters
  1483. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pAppAppCert), dwAppAppCertLen));
  1484. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwAppAppCertLen), sizeof(dwAppAppCertLen)));
  1485. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pSPAppCert), dwSPAppCertLen ));
  1486. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwSPAppCertLen ), sizeof(dwSPAppCertLen)));
  1487. CORg( pSCClient->MACFinal(hMAC, abMAC));
  1488. // Encrypt the 2 AppCerts
  1489. CORg( pSCClient->EncryptParam(pAppAppCert, dwAppAppCertLen));
  1490. CORg( pSCClient->EncryptParam(pSPAppCert, dwSPAppCertLen) );
  1491. qwFileSizeDest = qwFileSizeSource;
  1492. hr = pSecQuery2->MakeDecision2( nDecideFlags,
  1493. pData,
  1494. dwBytesRead,
  1495. dwAppSec,
  1496. (BYTE*)abSPSessionKey,
  1497. dwSessionKeyLen,
  1498. pStgGlobals,
  1499. pAppAppCert, dwAppAppCertLen, // AppCert App
  1500. pSPAppCert, dwSPAppCertLen, // AppCert SP
  1501. &m_pwszRevocationURL, // LPSTR - revocation update URL
  1502. &m_dwRevocationURLLen, // Length of URL string passed in
  1503. &m_dwRevocationBitFlag, // revocation component bitflag
  1504. &qwFileSizeDest, pUnknown, // File size, App IUnknown
  1505. &pSecExch, // Secure exchange
  1506. abMAC);
  1507. if( hr == WMDM_E_REVOKED )
  1508. {
  1509. // If the SP is revoked give it a chance to specify an URL.
  1510. UpdateRevocationURL( &m_pwszRevocationURL,
  1511. &m_dwRevocationURLLen,
  1512. &m_dwRevocationBitFlag );
  1513. }
  1514. CORg(hr);
  1515. }
  1516. else
  1517. {
  1518. CORg( pSCClient->MACFinal(hMAC, abMAC));
  1519. qwFileSizeDest = 0;
  1520. // Use old MakeDecision call without AppCert revocation check
  1521. CORg( pSecQuery->MakeDecision(nDecideFlags,
  1522. pData,
  1523. dwBytesRead,
  1524. dwAppSec,
  1525. (BYTE*)abSPSessionKey,
  1526. dwSessionKeyLen,
  1527. pStgGlobals,
  1528. &pSecExch,
  1529. abMAC) );
  1530. }
  1531. }
  1532. if (0xffffffff == SetFilePointer(hFile, 0, NULL, FILE_BEGIN))
  1533. {
  1534. hr = E_FAIL;
  1535. goto exit;
  1536. }
  1537. if (hr == S_OK)
  1538. {
  1539. fUseSCP = TRUE;
  1540. if( pSecExch == NULL ) CORg(E_FAIL);
  1541. break;
  1542. }
  1543. else
  1544. {
  1545. // If the SCP returns S_FALSE then we don't have rights to do the transfer
  1546. hr = WMDM_E_NORIGHTS;
  1547. goto exit;
  1548. }
  1549. }
  1550. SAFE_RELEASE( pSecQuery );
  1551. SAFE_RELEASE( pSecQuery2 );
  1552. }
  1553. // If this is only a query then we should just return without copying the file
  1554. if (fQuery)
  1555. {
  1556. hr = S_OK;
  1557. goto exit;
  1558. }
  1559. if (!fUseSCP)
  1560. {
  1561. CORg( pStgGlobals->GetDevice(&pDevice) );
  1562. CORg( pDevice->GetType(&dwType) );
  1563. // Do not allow content without and SCP to be transferred to an SDMI only device.
  1564. if ((dwType & WMDM_DEVICE_TYPE_SDMI) && (!(dwType & WMDM_DEVICE_TYPE_NONSDMI)))
  1565. {
  1566. hr = WMDM_E_NORIGHTS;
  1567. goto exit;
  1568. }
  1569. qwFileSizeDest = qwFileSizeSource;
  1570. }
  1571. // Create the storage we are going to write to.
  1572. {
  1573. hr = m_pStorage->QueryInterface( __uuidof(IMDSPStorage2), reinterpret_cast<void**>(&pStorage2) );
  1574. if( SUCCEEDED(hr) && pStorage2 )
  1575. {
  1576. hr = pStorage2->CreateStorage2( uNewStorageMode, 0, NULL, NULL, wszNewStorageName, qwFileSizeDest, &pNewSPStorage);
  1577. if( hr == E_NOTIMPL )
  1578. {
  1579. CORg( m_pStorage->CreateStorage(uNewStorageMode, NULL, wszNewStorageName, &pNewSPStorage) );
  1580. }
  1581. else CORg( hr );
  1582. }
  1583. else CORg( m_pStorage->CreateStorage(uNewStorageMode, NULL, wszNewStorageName, &pNewSPStorage) );
  1584. }
  1585. CORg( CComObject<CWMDMStorage>::CreateInstance(&pNewWMDMStorage) );
  1586. hr = pNewWMDMStorage->QueryInterface(IID_IWMDMStorage, reinterpret_cast<void**>(&pNewIWMDMStorage));
  1587. if (FAILED(hr))
  1588. {
  1589. delete pNewWMDMStorage;
  1590. goto exit;
  1591. }
  1592. pNewWMDMStorage->SetContainedPointer(pNewSPStorage, m_wSPIndex);
  1593. CORg( pNewSPStorage->QueryInterface(IID_IMDSPObject, reinterpret_cast<void**>(&pObject)) );
  1594. CORg( pObject->Open(MDSP_WRITE) );
  1595. fOpen = TRUE;
  1596. fUsedSCP = fUseSCP;
  1597. #ifdef DUMP_FILE
  1598. hFileDump = fopen("\\Write.wma", "wb");
  1599. #endif
  1600. // Copy file
  1601. while( !bEOF || bFlushSCP )
  1602. {
  1603. dwBytesWrite = 0;
  1604. dwBytesRead = 0;
  1605. fuReadyFlags = 0;
  1606. // Read data from file
  1607. if( !bEOF && !bFlushSCP )
  1608. {
  1609. dwBytesRead = WMDM_TRANSFER_BUFFER_SIZE;
  1610. fRetVal = ReadFile(hFile, pData, WMDM_TRANSFER_BUFFER_SIZE, &dwBytesRead, NULL);
  1611. if( dwBytesRead == 0 )
  1612. {
  1613. break;
  1614. }
  1615. dwBytesWrite = dwBytesRead;
  1616. if (!fRetVal)
  1617. {
  1618. hr = E_FAIL;
  1619. goto exit;
  1620. }
  1621. bEOF = (WMDM_TRANSFER_BUFFER_SIZE != dwBytesRead);
  1622. bFlushSCP = bEOF && fUseSCP;
  1623. // Pass file-data to the SCP
  1624. if( fUseSCP )
  1625. {
  1626. // Calculate the MAC to send to the SCP
  1627. CORg( pSCClient->MACInit(&hMAC) );
  1628. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesRead) );
  1629. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  1630. CORg( pSCClient->MACFinal(hMAC, abMAC) );
  1631. // Encrypt the pData Parameter
  1632. CORg( pSCClient->EncryptParam(pData, dwBytesRead) );
  1633. CORg( pSecExch->TransferContainerData(pData, dwBytesRead, &fuReadyFlags, abMAC) );
  1634. // Verify the MAC on the return parameters
  1635. CORg( pSCClient->MACInit(&hMAC) );
  1636. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuReadyFlags), sizeof(fuReadyFlags)));
  1637. CORg( pSCClient->MACFinal(hMAC, abMACVerify) );
  1638. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  1639. {
  1640. hr = WMDM_E_MAC_CHECK_FAILED;
  1641. goto exit;
  1642. }
  1643. // Are we done passing data to the SCP?
  1644. bFlushSCP = ((fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) &&
  1645. (fuReadyFlags & WMDM_SCP_NO_MORE_CHANGES))
  1646. ? TRUE : FALSE;
  1647. // The SCP was not interesed in this data, use original data from the file.
  1648. if( (fuReadyFlags & WMDM_SCP_NO_MORE_CHANGES) &&
  1649. !(fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) )
  1650. {
  1651. // Decrypt the original file data
  1652. CORg( pSCClient->DecryptParam(pData, dwBytesRead) );
  1653. fUseSCP = FALSE;
  1654. }
  1655. }
  1656. }
  1657. // Get data back from SCP
  1658. if( fUseSCP && (( fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) || bFlushSCP ))
  1659. {
  1660. dwBytesWrite = dwBufferSize;
  1661. // Calculate the MAC to send to the SCP
  1662. CORg( pSCClient->MACInit(&hMAC) );
  1663. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesWrite), sizeof(dwBytesWrite)));
  1664. CORg( pSCClient->MACFinal(hMAC, abMAC) );
  1665. CORg( pSecExch->ObjectData(pData, &dwBytesWrite, abMAC) );
  1666. if(dwBytesWrite == 0)
  1667. {
  1668. if( bFlushSCP )
  1669. {
  1670. bFlushSCP = FALSE;
  1671. fUseSCP = FALSE; // Done using the SCP
  1672. }
  1673. continue;
  1674. }
  1675. // Decrypt the pData Parameter
  1676. CORg( pSCClient->DecryptParam(pData, dwBytesWrite) );
  1677. // Verify the MAC on the return parameters
  1678. CORg( pSCClient->MACInit(&hMAC) );
  1679. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesWrite) );
  1680. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesWrite), sizeof(dwBytesWrite)));
  1681. CORg( pSCClient->MACFinal(hMAC, abMACVerify) );
  1682. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  1683. {
  1684. hr = WMDM_E_MAC_CHECK_FAILED;
  1685. goto exit;
  1686. }
  1687. }
  1688. // Write data to SP
  1689. if ( ((!fUseSCP) || (fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) || bFlushSCP )
  1690. && dwBytesWrite > 0 )
  1691. {
  1692. #ifdef DUMP_FILE
  1693. fwrite(pData, sizeof(BYTE), dwBytesWrite, hFileDump);
  1694. #endif
  1695. // Create MAC to send to SP
  1696. CORg( pSPClient->MACInit(&hMAC) );
  1697. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesWrite) );
  1698. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&dwBytesWrite), sizeof(dwBytesWrite)));
  1699. CORg( pSPClient->MACFinal(hMAC, abMAC) );
  1700. CORg( pSPClient->EncryptParam(pData, dwBytesWrite) );
  1701. CORg( pObject->Write(pData, &dwBytesWrite, abMAC) );
  1702. if (pProgress)
  1703. {
  1704. dwTicks += dwBytesRead;
  1705. hr = pProgress->Progress(dwTicks);
  1706. if (FAILED(hr))
  1707. {
  1708. goto exit;
  1709. }
  1710. }
  1711. }
  1712. } // Copy file
  1713. #ifdef DUMP_FILE
  1714. fclose(hFileDump);
  1715. #endif
  1716. // Close content file
  1717. if (pObject && fOpen)
  1718. {
  1719. HRESULT hr2 = pObject->Close();
  1720. hr = FAILED(hr)?hr:hr2;
  1721. fOpen = FALSE;
  1722. }
  1723. // SCP::TransferComplete()
  1724. if (fUsedSCP)
  1725. {
  1726. CORg( pSecExch->TransferComplete() );
  1727. }
  1728. Error:
  1729. exit:
  1730. if (pObject && fOpen)
  1731. {
  1732. HRESULT hr2 = pObject->Close();
  1733. hr = FAILED(hr)?hr:hr2;
  1734. fOpen = FALSE;
  1735. }
  1736. // Delete new storage file if the copy operation failed.
  1737. if( FAILED(hr) && pObject )
  1738. {
  1739. pObject->Delete(0, NULL);
  1740. }
  1741. if (pProgress)
  1742. {
  1743. if (!fBeginCalled)
  1744. {
  1745. pProgress->Begin(1);
  1746. }
  1747. // pProgress->End(); // This is done by the caller
  1748. }
  1749. if (hFile != INVALID_HANDLE_VALUE)
  1750. CloseHandle(hFile);
  1751. SAFE_ARRAY_DELETE(pAppAppCert);
  1752. SAFE_ARRAY_DELETE(pSPAppCert);
  1753. SAFE_ARRAY_DELETE(pData);
  1754. SAFE_ARRAY_DELETE(pwszFileExt);
  1755. SAFE_RELEASE(pDevice);
  1756. SAFE_RELEASE(pStgGlobals);
  1757. SAFE_RELEASE(pSecureAuth);
  1758. SAFE_RELEASE(pSecQuery);
  1759. SAFE_RELEASE(pSecQuery2);
  1760. SAFE_RELEASE(pStorage2);
  1761. SAFE_RELEASE(pSecExch);
  1762. SAFE_RELEASE(pObject);
  1763. SAFE_RELEASE(pNewSPStorage);
  1764. hrLogDWORD("CWMDMStorage::hrCopyToStorageFromFile returned 0x%08lx", hr, hr);
  1765. return hr;
  1766. }
  1767. HRESULT CWMDMStorage::hrCopyToOperationFromStorage(IWMDMOperation *pOperation, IWMDMProgress *pProgress, IMDSPObject *pObject)
  1768. {
  1769. //USES_CONVERSION;
  1770. HRESULT hr;
  1771. BYTE *pData = NULL;
  1772. DWORD dwBytes;
  1773. DWORD dwTotalBytes = 0;
  1774. HMAC hMAC;
  1775. BYTE abMAC[WMDM_MAC_LENGTH];
  1776. BYTE abMACVerify[WMDM_MAC_LENGTH];
  1777. CSecureChannelClient *pSPClient = NULL;
  1778. BOOL fOpen = FALSE;
  1779. CARg(pOperation);
  1780. CARg(pObject);
  1781. pData = new BYTE[WMDM_TRANSFER_BUFFER_SIZE];
  1782. CPRg(pData);
  1783. CORg( pObject->Open(MDSP_READ) );
  1784. fOpen = TRUE;
  1785. CORg( pOperation->BeginRead() );
  1786. g_pSPs[m_wSPIndex]->GetSCClient(&pSPClient);
  1787. if (!pSPClient)
  1788. {
  1789. CORg( E_FAIL );
  1790. }
  1791. // Copy file
  1792. dwBytes = WMDM_TRANSFER_BUFFER_SIZE;
  1793. while ((WMDM_TRANSFER_BUFFER_SIZE == dwBytes))
  1794. {
  1795. dwBytes = WMDM_TRANSFER_BUFFER_SIZE;
  1796. CORg( pObject->Read(pData, &dwBytes, abMAC) );
  1797. CORg( pSPClient->DecryptParam(pData, dwBytes) );
  1798. // Verify MAC returned by Read on the SP
  1799. CORg( pSPClient->MACInit(&hMAC) );
  1800. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytes) );
  1801. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&dwBytes), sizeof(dwBytes)));
  1802. CORg( pSPClient->MACFinal(hMAC, abMACVerify) );
  1803. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  1804. {
  1805. hr = WMDM_E_MAC_CHECK_FAILED;
  1806. goto exit;
  1807. }
  1808. // Calculate MAC to hand to operation
  1809. CORg( g_pAppSCServer->MACInit(&hMAC) );
  1810. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pData), dwBytes) );
  1811. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&dwBytes), sizeof(dwBytes)) );
  1812. CORg( g_pAppSCServer->MACFinal(hMAC, abMAC) );
  1813. // Encrypt the data parameter
  1814. CORg( g_pAppSCServer->EncryptParam(pData, dwBytes) );
  1815. CORg( pOperation->TransferObjectData(pData, &dwBytes, abMAC) );
  1816. dwTotalBytes+=dwBytes;
  1817. if (pProgress)
  1818. {
  1819. CORg( pProgress->Progress(dwTotalBytes) );
  1820. }
  1821. }
  1822. Error:
  1823. exit:
  1824. HRESULT hr2;
  1825. hr2 = pOperation->End(&hr, NULL);
  1826. hr = FAILED(hr)?hr:hr2;
  1827. if (pObject && fOpen)
  1828. {
  1829. hr2 = pObject->Close();
  1830. hr = FAILED(hr)?hr:hr2;
  1831. }
  1832. SAFE_ARRAY_DELETE(pData);
  1833. hrLogDWORD("CWMDMStorage::hrCopyToOperationFromStorage returned 0x%08lx", hr, hr);
  1834. return hr;
  1835. }
  1836. HRESULT CWMDMStorage::hrCopyToStorageFromOperation(UINT fuMode, IWMDMOperation *pOperation,
  1837. UINT uNewStorageMode, LPWCH wszNewStorageName,
  1838. IWMDMStorage*& pNewIWMDMStorage,
  1839. IWMDMProgress *pProgress,
  1840. IUnknown* pUnknown, BOOL fQuery)
  1841. {
  1842. HRESULT hr;
  1843. BYTE *pData = NULL;
  1844. CComObject<CWMDMStorage> *pNewWMDMStorage = NULL;
  1845. IMDSPObject *pObject = NULL;
  1846. IMDSPStorage *pNewSPStorage = NULL;
  1847. IMDSPStorage2 *pStorage2 = NULL;
  1848. IMDSPStorageGlobals *pStgGlobals = NULL;
  1849. IMDSPDevice *pDevice = NULL;
  1850. ISCPSecureAuthenticate *pSecureAuth = NULL;
  1851. ISCPSecureQuery *pSecQuery = NULL;
  1852. ISCPSecureQuery2 *pSecQuery2 = NULL;
  1853. ISCPSecureExchange *pSecExch = NULL;
  1854. DWORD dwRightsSize;
  1855. DWORD dwExSize;
  1856. DWORD dwMDSize;
  1857. UINT fuFlags;
  1858. UINT fuReadyFlags;
  1859. WORD wCurSCP = 0;
  1860. BOOL fUseSCP = FALSE; // Should data be passed throw an SCP?
  1861. BOOL fUsedSCP = FALSE; // Was an SCP used to do the file transfer?
  1862. DWORD dwBufferSize = 0;
  1863. DWORD dwBytesRead;
  1864. DWORD dwBytesWrite;
  1865. DWORD dwType;
  1866. ULONGLONG qwFileSizeSource;
  1867. ULONGLONG qwFileSizeDest;
  1868. UINT nDecideFlags;
  1869. DWORD dwTicks = 0;
  1870. DWORD dwBufferEnd = 0;
  1871. BYTE *pTempData = NULL;
  1872. DWORD dwBufferIncrement;
  1873. CSecureChannelClient *pSCClient = NULL;
  1874. CSecureChannelClient *pSPClient = NULL;
  1875. DWORD dwAppSec;
  1876. HMAC hMAC;
  1877. BYTE abMAC[WMDM_MAC_LENGTH];
  1878. BYTE abMACVerify[WMDM_MAC_LENGTH];
  1879. UINT fuTempFlags;
  1880. BOOL fBeginCalled = FALSE;
  1881. DWORD dwSPAppSec;
  1882. DWORD dwAPPAppSec;
  1883. LPWSTR pwszFileExt = NULL;
  1884. // LPWSTR pwszFileName = NULL;
  1885. DWORD dwSessionKeyLen = SAC_SESSION_KEYLEN;
  1886. BYTE abSPSessionKey[SAC_SESSION_KEYLEN];
  1887. BOOL fOpen = FALSE; // Flag indicating if the IMDSPObject::Open has been called
  1888. BOOL bEOF = FALSE;
  1889. BOOL bFlushSCP = FALSE;
  1890. DWORD dwAppAppCertLen; // Length of AppCert of application
  1891. DWORD dwSPAppCertLen; // Length of AppCert of SP
  1892. BYTE* pAppAppCert = NULL; // Buffer to hold App AppCert
  1893. BYTE* pSPAppCert = NULL; // Buffer to hold SP AppCert
  1894. // Clear revocation
  1895. CoTaskMemFree( m_pwszRevocationURL );
  1896. m_pwszRevocationURL = NULL;
  1897. m_dwRevocationURLLen = 0;
  1898. m_dwRevocationBitFlag = 0;
  1899. CARg( pOperation );
  1900. // pwszFileName = new WCHAR[512];
  1901. // CPRg( pwszFileName );
  1902. g_pSPs[m_wSPIndex]->GetSCClient(&pSPClient);
  1903. if (!pSPClient)
  1904. {
  1905. CORg( E_FAIL );
  1906. }
  1907. CORg( m_pStorage->GetStorageGlobals(&pStgGlobals) );
  1908. // Get size of source file
  1909. DWORD dwFileSizeLow;
  1910. DWORD dwFileSizeHigh;
  1911. hr = pOperation->GetObjectTotalSize( &dwFileSizeLow, &dwFileSizeHigh );
  1912. if( FAILED(hr) ) qwFileSizeSource = 0;
  1913. else qwFileSizeSource = dwFileSizeLow + ((ULONGLONG)dwFileSizeHigh << 32);
  1914. if( g_pSCPs == NULL )
  1915. {
  1916. CMediaDevMgr::LoadSCPs();
  1917. }
  1918. // Find the right SCP
  1919. for( wCurSCP = 0; wCurSCP < g_wSCPCount; wCurSCP++ )
  1920. {
  1921. CORg( g_pSCPs[wCurSCP]->hrGetInterface(&pSecureAuth));
  1922. g_pSCPs[wCurSCP]->GetSCClient(&pSCClient);
  1923. if (!pSCClient)
  1924. {
  1925. CORg( E_FAIL );
  1926. }
  1927. CORg( pSecureAuth->GetSecureQuery(&pSecQuery) );
  1928. pSecureAuth->Release();
  1929. pSecureAuth = NULL;
  1930. CORg( pSecQuery->GetDataDemands(&fuFlags, &dwRightsSize, &dwExSize, &dwMDSize, abMAC) );
  1931. // Verify MAC returned by GetDataDemands
  1932. CORg( pSCClient->MACInit(&hMAC) );
  1933. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuFlags), sizeof(fuFlags)) );
  1934. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwRightsSize), sizeof(dwRightsSize)) );
  1935. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwExSize), sizeof(dwExSize)) );
  1936. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwMDSize), sizeof(dwMDSize)) );
  1937. CORg( pSCClient->MACFinal(hMAC, abMACVerify) );
  1938. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  1939. {
  1940. hr = WMDM_E_MAC_CHECK_FAILED;
  1941. goto exit;
  1942. }
  1943. if (!(fuFlags & (WMDM_SCP_EXAMINE_DATA | WMDM_SCP_DECIDE_DATA | WMDM_SCP_EXAMINE_EXTENSION)))
  1944. {
  1945. continue;
  1946. }
  1947. // If the SCP asked for the file extension then get it from the file name passed in
  1948. if (fuFlags & WMDM_SCP_EXAMINE_EXTENSION)
  1949. {
  1950. // Only get the file extension once
  1951. if (!pwszFileExt)
  1952. {
  1953. pwszFileExt = new WCHAR[64];
  1954. CARg( pwszFileExt);
  1955. if (NULL != wcschr(wszNewStorageName, L'.'))
  1956. {
  1957. wcsncpy(pwszFileExt, (LPWSTR)(wcsrchr(wszNewStorageName, L'.') + 1), 64);
  1958. }
  1959. else
  1960. {
  1961. SAFE_ARRAY_DELETE(pwszFileExt);
  1962. }
  1963. }
  1964. }
  1965. if (dwBufferSize < (dwExSize>dwMDSize?dwExSize:dwMDSize))
  1966. {
  1967. SAFE_ARRAY_DELETE(pData);
  1968. dwBufferSize = dwExSize>dwMDSize?dwExSize:dwMDSize;
  1969. pData = new BYTE[dwBufferSize];
  1970. CARg( pData );
  1971. }
  1972. // ExamineData
  1973. hr = WMDM_E_MOREDATA;
  1974. dwBufferIncrement = dwBufferSize;
  1975. while (hr == WMDM_E_MOREDATA)
  1976. {
  1977. dwBytesRead = dwBufferSize - dwBufferEnd;
  1978. // Calculate MAC to send to TransferObjectData
  1979. CORg( g_pAppSCServer->MACInit(&hMAC) );
  1980. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pData + dwBufferEnd), dwBytesRead) );
  1981. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  1982. CORg( g_pAppSCServer->MACFinal(hMAC, abMAC) );
  1983. // Encrypt the data parameter
  1984. CORg( g_pAppSCServer->EncryptParam(pData + dwBufferEnd, dwBytesRead) );
  1985. CORg( pOperation->TransferObjectData((BYTE *)(pData + dwBufferEnd), &dwBytesRead, abMAC) );
  1986. if (dwBytesRead == 0)
  1987. {
  1988. // BUGBUG: Do we really want to return E_FAIL here?
  1989. // If they app returns S_FALSE then there is no more data to transfer
  1990. // Since the SCP couldn't decide yet we must fail.
  1991. hr = E_FAIL;
  1992. break;
  1993. }
  1994. // Decrypt the data parameter
  1995. CORg( g_pAppSCServer->DecryptParam(pData + dwBufferEnd, dwBytesRead) );
  1996. CORg( g_pAppSCServer->MACInit(&hMAC) );
  1997. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pData + dwBufferEnd), dwBytesRead) );
  1998. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  1999. CORg( g_pAppSCServer->MACFinal(hMAC, abMACVerify) );
  2000. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  2001. {
  2002. hr = WMDM_E_MAC_CHECK_FAILED;
  2003. goto exit;
  2004. }
  2005. // Create the MAC to send to ExamineData
  2006. CORg( pSCClient->MACInit(&hMAC) );
  2007. fuTempFlags = WMDM_SCP_EXAMINE_DATA;
  2008. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuTempFlags), sizeof(fuTempFlags)) );
  2009. if (pwszFileExt)
  2010. {
  2011. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pwszFileExt), 2 * wcslen(pwszFileExt)) );
  2012. }
  2013. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData + dwBufferEnd), dwBytesRead) );
  2014. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  2015. CORg( pSCClient->MACFinal(hMAC, abMAC) );
  2016. // Encrypt the pData Parameter
  2017. CORg( pSCClient->EncryptParam(pData + dwBufferEnd, dwBytesRead) );
  2018. CORg( pSecQuery->ExamineData(fuTempFlags, pwszFileExt, (BYTE *)(pData + dwBufferEnd), dwBytesRead, abMAC) );
  2019. // Decrypt the data parameter
  2020. pSCClient->DecryptParam(pData + dwBufferEnd, dwBytesRead);
  2021. if (hr == WMDM_E_MOREDATA)
  2022. {
  2023. dwBufferSize += dwBufferIncrement;
  2024. pTempData = new BYTE[dwBufferSize];
  2025. CARg( pTempData );
  2026. dwBufferEnd += dwBytesRead;
  2027. memcpy(pTempData, pData, dwBufferEnd);
  2028. SAFE_ARRAY_DELETE(pData);
  2029. pData = pTempData;
  2030. pTempData = NULL;
  2031. }
  2032. }
  2033. // MakeDecision
  2034. if (hr == S_OK)
  2035. {
  2036. if (fuMode & WMDM_MODE_TRANSFER_UNPROTECTED)
  2037. {
  2038. nDecideFlags = WMDM_SCP_DECIDE_DATA | WMDM_SCP_UNPROTECTED_OUTPUT;
  2039. }
  2040. else
  2041. {
  2042. nDecideFlags = WMDM_SCP_DECIDE_DATA | WMDM_SCP_PROTECTED_OUTPUT;
  2043. }
  2044. // If the SCP supports ISCPSecQuery2 use it as a first choice
  2045. hr = pSecQuery->QueryInterface( IID_ISCPSecureQuery2, (void**)(&pSecQuery2) );
  2046. CORg( g_pAppSCServer->GetAppSec(NULL, &dwAPPAppSec) );
  2047. CORg( pSPClient->GetAppSec(NULL, &dwSPAppSec) );
  2048. // Appsec = min(appsec app, appsec SP )
  2049. dwAppSec = dwSPAppSec>dwAPPAppSec?dwAPPAppSec:dwSPAppSec;
  2050. hr = WMDM_E_MOREDATA;
  2051. dwBytesRead += dwBufferEnd;
  2052. dwBufferEnd = 0;
  2053. while (hr == WMDM_E_MOREDATA)
  2054. {
  2055. CORg( pSPClient->GetSessionKey((BYTE*)abSPSessionKey) );
  2056. CORg( pSCClient->MACInit(&hMAC) );
  2057. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&nDecideFlags), sizeof(nDecideFlags)) );
  2058. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData + dwBufferEnd), dwBytesRead) );
  2059. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  2060. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwAppSec), sizeof(dwAppSec)) );
  2061. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(abSPSessionKey), dwSessionKeyLen) );
  2062. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwSessionKeyLen), sizeof(dwSessionKeyLen)) );
  2063. // Encrypt the pData Parameter
  2064. CORg( pSCClient->EncryptParam(pData + dwBufferEnd, dwBytesRead) );
  2065. CORg( pSCClient->EncryptParam((BYTE*)abSPSessionKey, dwSessionKeyLen) );
  2066. // Use MakeDecision2 and pass in AppCerts of App, SP to check for revocation
  2067. if( pSecQuery2 )
  2068. {
  2069. // Get the AppCert of the App
  2070. g_pAppSCServer->GetRemoteAppCert( NULL, &dwAppAppCertLen );
  2071. CFRg( dwAppAppCertLen != NULL );
  2072. SAFE_ARRAY_DELETE(pAppAppCert);
  2073. pAppAppCert = new BYTE[dwAppAppCertLen];
  2074. CPRg( pAppAppCert );
  2075. g_pAppSCServer->GetRemoteAppCert( pAppAppCert, &dwAppAppCertLen );
  2076. // Get the AppCert of the SP
  2077. pSPClient->GetRemoteAppCert( NULL, &dwSPAppCertLen );
  2078. CFRg( dwSPAppCertLen != NULL )
  2079. SAFE_ARRAY_DELETE(pSPAppCert);
  2080. pSPAppCert = new BYTE[dwSPAppCertLen];
  2081. CPRg( pSPAppCert );
  2082. pSPClient->GetRemoteAppCert( pSPAppCert, &dwSPAppCertLen );
  2083. // Update mac:ing with the AppCert parameters
  2084. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pAppAppCert), dwAppAppCertLen));
  2085. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwAppAppCertLen), sizeof(dwAppAppCertLen)));
  2086. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pSPAppCert), dwSPAppCertLen ));
  2087. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwSPAppCertLen ), sizeof(dwSPAppCertLen)));
  2088. CORg( pSCClient->MACFinal(hMAC, abMAC));
  2089. // Encrypt the 2 AppCerts
  2090. CORg( pSCClient->EncryptParam(pAppAppCert, dwAppAppCertLen));
  2091. CORg( pSCClient->EncryptParam(pSPAppCert, dwSPAppCertLen) );
  2092. qwFileSizeDest = qwFileSizeSource;
  2093. hr = pSecQuery2->MakeDecision2( nDecideFlags,
  2094. pData,
  2095. dwBytesRead,
  2096. dwAppSec,
  2097. (BYTE*)abSPSessionKey,
  2098. dwSessionKeyLen,
  2099. pStgGlobals,
  2100. pAppAppCert, dwAppAppCertLen, // AppCert App
  2101. pSPAppCert, dwSPAppCertLen, // AppCert SP
  2102. &m_pwszRevocationURL, // String - revocation update URL
  2103. &m_dwRevocationURLLen, // Length of URL string passed in
  2104. &m_dwRevocationBitFlag, // revocatoin component bitflag
  2105. &qwFileSizeDest, pUnknown,
  2106. &pSecExch,
  2107. abMAC);
  2108. if( hr == WMDM_E_REVOKED )
  2109. {
  2110. // If the SP is revoked give it a chance to specify an URL.
  2111. UpdateRevocationURL( &m_pwszRevocationURL,
  2112. &m_dwRevocationURLLen,
  2113. &m_dwRevocationBitFlag );
  2114. }
  2115. CORg(hr);
  2116. }
  2117. else
  2118. {
  2119. // If this SCP does not support the new ISCPSecureQuery2 interface use the old MakeDecision
  2120. CORg( pSCClient->MACFinal(hMAC, abMAC));
  2121. qwFileSizeDest = 0;
  2122. CORg( pSecQuery->MakeDecision(nDecideFlags,
  2123. (BYTE *)(pData + dwBufferEnd),
  2124. dwBytesRead,
  2125. dwAppSec,
  2126. (BYTE*)abSPSessionKey,
  2127. dwSessionKeyLen,
  2128. pStgGlobals,
  2129. &pSecExch,
  2130. abMAC) );
  2131. }
  2132. // Decrypt the data parameter
  2133. CORg( pSCClient->DecryptParam(pData + dwBufferEnd, dwBytesRead) );
  2134. // SCP needs more data for MakeDecision
  2135. if (hr == WMDM_E_MOREDATA)
  2136. {
  2137. dwBufferSize += dwBufferIncrement;
  2138. pTempData = new BYTE[dwBufferSize];
  2139. CARg( pTempData );
  2140. dwBufferEnd += dwBytesRead;
  2141. memcpy(pTempData, pData, dwBufferEnd);
  2142. SAFE_ARRAY_DELETE(pData);
  2143. pData = pTempData;
  2144. pTempData = NULL;
  2145. dwBytesRead = dwBufferSize - dwBufferEnd;
  2146. // Calculate MAC to send to TransferObjectData
  2147. CORg( g_pAppSCServer->MACInit(&hMAC) );
  2148. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pData + dwBufferEnd), dwBytesRead) );
  2149. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  2150. CORg( g_pAppSCServer->MACFinal(hMAC, abMAC) );
  2151. // Encrypt the data parameter
  2152. CORg( g_pAppSCServer->EncryptParam(pData + dwBufferEnd, dwBytesRead) );
  2153. CORg( pOperation->TransferObjectData((BYTE *)(pData + dwBufferEnd), &dwBytesRead, abMAC) );
  2154. if (dwBytesRead == 0)
  2155. {
  2156. // BUGBUG: Do we really want to return E_FAIL here?
  2157. // If they app returns S_FALSE then there is no more data to transfer
  2158. // Since the SCP couldn't decide yet we must fail.
  2159. hr = E_FAIL;
  2160. break;
  2161. }
  2162. // Decrypt the data parameter
  2163. CORg( g_pAppSCServer->DecryptParam(pData + dwBufferEnd, dwBytesRead) );
  2164. CORg( g_pAppSCServer->MACInit(&hMAC) );
  2165. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pData + dwBufferEnd), dwBytesRead) );
  2166. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  2167. CORg( g_pAppSCServer->MACFinal(hMAC, abMACVerify) );
  2168. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  2169. {
  2170. hr = WMDM_E_MAC_CHECK_FAILED;
  2171. goto exit;
  2172. }
  2173. }
  2174. }
  2175. dwBytesRead += dwBufferEnd;
  2176. if (hr == S_OK)
  2177. {
  2178. fUseSCP = TRUE;
  2179. if( pSecExch == NULL ) CORg(E_FAIL);
  2180. break;
  2181. }
  2182. else
  2183. {
  2184. // If the SCP returns S_FALSE then we don't have rights to do the transfer
  2185. hr = WMDM_E_NORIGHTS;
  2186. goto exit;
  2187. }
  2188. }
  2189. pSecQuery->Release();
  2190. pSecQuery = NULL;
  2191. }
  2192. if (!fUseSCP)
  2193. {
  2194. CORg( pStgGlobals->GetDevice(&pDevice) );
  2195. CORg( pDevice->GetType(&dwType) );
  2196. // Do not allow content without and SCP to be transferred to an SDMI only device.
  2197. if ((dwType & WMDM_DEVICE_TYPE_SDMI) && (!(dwType & WMDM_DEVICE_TYPE_NONSDMI)))
  2198. {
  2199. hr = WMDM_E_NORIGHTS;
  2200. goto exit;
  2201. }
  2202. qwFileSizeDest = qwFileSizeSource;
  2203. }
  2204. // Create the storage to write to.
  2205. {
  2206. hr = m_pStorage->QueryInterface( __uuidof(IMDSPStorage2), reinterpret_cast<void**>(&pStorage2) );
  2207. if( SUCCEEDED(hr) && pStorage2 )
  2208. {
  2209. hr = pStorage2->CreateStorage2( uNewStorageMode, 0, NULL, NULL, wszNewStorageName, qwFileSizeDest, &pNewSPStorage);
  2210. if( hr == E_NOTIMPL )
  2211. {
  2212. CORg( m_pStorage->CreateStorage(uNewStorageMode, NULL, wszNewStorageName, &pNewSPStorage) );
  2213. }
  2214. else CORg( hr );
  2215. }
  2216. else CORg( m_pStorage->CreateStorage(uNewStorageMode, NULL, wszNewStorageName, &pNewSPStorage) );
  2217. }
  2218. CORg( CComObject<CWMDMStorage>::CreateInstance(&pNewWMDMStorage) );
  2219. hr = pNewWMDMStorage->QueryInterface(IID_IWMDMStorage, reinterpret_cast<void**>(&pNewIWMDMStorage));
  2220. if (FAILED(hr))
  2221. {
  2222. delete pNewWMDMStorage;
  2223. goto exit;
  2224. }
  2225. pNewWMDMStorage->SetContainedPointer(pNewSPStorage, m_wSPIndex);
  2226. CORg( pNewSPStorage->QueryInterface(IID_IMDSPObject, reinterpret_cast<void **>(&pObject)) );
  2227. CORg( pObject->Open(MDSP_WRITE) );
  2228. fOpen = TRUE;
  2229. // If we are reporting progress then we need to tell the app how many ticks we think there will be
  2230. if (pProgress)
  2231. {
  2232. fBeginCalled = TRUE;
  2233. CORg( pProgress->Begin((DWORD)qwFileSizeSource) );
  2234. }
  2235. fUsedSCP = fUseSCP;
  2236. // Copy file
  2237. while( !bEOF || bFlushSCP )
  2238. {
  2239. dwBytesWrite = dwBytesRead;
  2240. fuReadyFlags = 0;
  2241. // Pass file-data to the SCP
  2242. if (fUseSCP && dwBytesRead > 0)
  2243. {
  2244. CORg( pSCClient->MACInit(&hMAC) );
  2245. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesRead) );
  2246. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  2247. CORg( pSCClient->MACFinal(hMAC, abMAC) );
  2248. CORg( pSCClient->EncryptParam(pData, dwBytesRead) );
  2249. CORg( pSecExch->TransferContainerData(pData, dwBytesRead, &fuReadyFlags, abMAC) );
  2250. CORg( pSCClient->MACInit(&hMAC) );
  2251. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&fuReadyFlags), sizeof(fuReadyFlags)) );
  2252. CORg( pSCClient->MACFinal(hMAC, abMACVerify) );
  2253. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  2254. {
  2255. hr = WMDM_E_MAC_CHECK_FAILED;
  2256. goto exit;
  2257. }
  2258. // Are we done passing data to the SCP?
  2259. bFlushSCP = ((fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) &&
  2260. (fuReadyFlags & WMDM_SCP_NO_MORE_CHANGES))
  2261. ? TRUE : FALSE;
  2262. // The SCP was not interesed in this data, use original data from the file.
  2263. if( (fuReadyFlags & WMDM_SCP_NO_MORE_CHANGES) &&
  2264. !(fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) )
  2265. {
  2266. // Decrypt the original file data
  2267. CORg( pSCClient->DecryptParam(pData, dwBytesRead) );
  2268. fUseSCP = FALSE;
  2269. }
  2270. }
  2271. // Get data back from SCP
  2272. if( fUseSCP && (( fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) || bFlushSCP ))
  2273. {
  2274. dwBytesWrite = dwBufferSize;
  2275. // Calculate the MAC to send to the SCP
  2276. CORg( pSCClient->MACInit(&hMAC) );
  2277. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesWrite), sizeof(dwBytesWrite)) );
  2278. CORg( pSCClient->MACFinal(hMAC, abMAC) );
  2279. // Get and decrypt data from SCP
  2280. CORg( pSecExch->ObjectData(pData, &dwBytesWrite, abMAC) );
  2281. if(dwBytesWrite == 0)
  2282. {
  2283. if( bFlushSCP )
  2284. {
  2285. bFlushSCP = FALSE;
  2286. fUseSCP = FALSE; // Done using the SCP
  2287. }
  2288. continue;
  2289. }
  2290. // Decrypt the pData Parameter
  2291. CORg( pSCClient->DecryptParam(pData, dwBytesWrite) );
  2292. CORg( pSCClient->MACInit(&hMAC) );
  2293. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesWrite) );
  2294. CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&dwBytesWrite), sizeof(dwBytesWrite)) );
  2295. CORg( pSCClient->MACFinal(hMAC, abMACVerify) );
  2296. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  2297. {
  2298. hr = WMDM_E_MAC_CHECK_FAILED;
  2299. goto exit;
  2300. }
  2301. }
  2302. // Write data to SP
  2303. if ( ((!fUseSCP) || (fuReadyFlags & WMDM_SCP_TRANSFER_OBJECTDATA) || bFlushSCP )
  2304. && dwBytesWrite > 0 )
  2305. {
  2306. // Create MAC to send to SP
  2307. CORg( pSPClient->MACInit(&hMAC) );
  2308. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytesWrite) );
  2309. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&dwBytesWrite), sizeof(dwBytesWrite)) );
  2310. CORg( pSPClient->MACFinal(hMAC, abMAC) );
  2311. CORg( pSPClient->EncryptParam(pData, dwBytesWrite) );
  2312. CORg( pObject->Write(pData, &dwBytesWrite, abMAC) );
  2313. if (pProgress)
  2314. {
  2315. dwTicks += dwBytesRead;
  2316. CORg( pProgress->Progress(dwTicks) );
  2317. }
  2318. }
  2319. // No valid file data to send to SCP.
  2320. dwBytesRead = 0;
  2321. // Read new file data
  2322. if( !bEOF && !bFlushSCP )
  2323. {
  2324. dwBytesRead = dwBufferSize;
  2325. CORg( g_pAppSCServer->MACInit(&hMAC) );
  2326. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pData), dwBytesRead) );
  2327. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  2328. CORg( g_pAppSCServer->MACFinal(hMAC, abMAC) );
  2329. CORg( g_pAppSCServer->EncryptParam(pData, dwBytesRead) );
  2330. CORg( pOperation->TransferObjectData(pData, &dwBytesRead, abMAC) );
  2331. bEOF = (S_FALSE == hr) || (dwBytesRead == 0);
  2332. bFlushSCP = bEOF && fUseSCP;
  2333. if ((S_FALSE == hr) || (dwBytesRead == 0))
  2334. {
  2335. // If they app returns S_FALSE then there is no more data to transfer
  2336. hr = S_OK;
  2337. continue;
  2338. }
  2339. CORg( g_pAppSCServer->DecryptParam(pData, dwBytesRead) );
  2340. CORg( g_pAppSCServer->MACInit(&hMAC) );
  2341. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pData), dwBytesRead) );
  2342. CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&dwBytesRead), sizeof(dwBytesRead)) );
  2343. CORg( g_pAppSCServer->MACFinal(hMAC, abMACVerify) );
  2344. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  2345. {
  2346. CORg( WMDM_E_MAC_CHECK_FAILED );
  2347. }
  2348. }
  2349. } // Copy file
  2350. // Close content file
  2351. if (pObject && fOpen)
  2352. {
  2353. HRESULT hr2 = pObject->Close();
  2354. hr = FAILED(hr)?hr:hr2;
  2355. fOpen = FALSE;
  2356. }
  2357. // SCP::TransferComplete()
  2358. if (fUsedSCP)
  2359. {
  2360. CORg( pSecExch->TransferComplete() );
  2361. }
  2362. Error:
  2363. exit:
  2364. if (pObject && fOpen)
  2365. {
  2366. HRESULT hr2 = pObject->Close();
  2367. hr = FAILED(hr)?hr:hr2;
  2368. }
  2369. // Delete new storage file if the copy operation failed.
  2370. if( FAILED(hr) && pObject )
  2371. {
  2372. pObject->Delete(0, NULL);
  2373. }
  2374. if (pProgress)
  2375. {
  2376. if (!fBeginCalled)
  2377. {
  2378. pProgress->Begin(1);
  2379. }
  2380. // pProgress->End(); This is done by the caller
  2381. }
  2382. SAFE_ARRAY_DELETE(pAppAppCert);
  2383. SAFE_ARRAY_DELETE(pSPAppCert);
  2384. SAFE_ARRAY_DELETE(pTempData);
  2385. SAFE_ARRAY_DELETE(pData);
  2386. SAFE_ARRAY_DELETE(pwszFileExt);
  2387. // SAFE_ARRAY_DELETE(pwszFileName);
  2388. SAFE_RELEASE(pDevice);
  2389. SAFE_RELEASE(pStorage2);
  2390. SAFE_RELEASE(pStgGlobals);
  2391. SAFE_RELEASE(pObject);
  2392. SAFE_RELEASE(pSecureAuth);
  2393. SAFE_RELEASE(pSecQuery);
  2394. SAFE_RELEASE(pSecQuery2);
  2395. SAFE_RELEASE(pSecExch);
  2396. SAFE_RELEASE(pNewSPStorage);
  2397. hrLogDWORD("CWMDMStorage::hrCopyToStorageFromOperation returned 0x%08lx", hr, hr);
  2398. return hr;
  2399. }
  2400. HRESULT CWMDMStorage::hrCopyToFileFromStorage(LPWSTR pwszFileName, IWMDMProgress *pProgress, IMDSPObject *pObject)
  2401. {
  2402. USES_CONVERSION;
  2403. HRESULT hr;
  2404. HANDLE hFile = INVALID_HANDLE_VALUE;
  2405. BYTE *pData = NULL;
  2406. DWORD dwBytes;
  2407. DWORD dwBytesWritten;
  2408. DWORD dwTotalBytes = 0;
  2409. HMAC hMAC;
  2410. BYTE abMAC[WMDM_MAC_LENGTH];
  2411. BYTE abMACVerify[WMDM_MAC_LENGTH];
  2412. CSecureChannelClient *pSPClient = NULL;
  2413. BOOL fOpen = FALSE;
  2414. DWORD dwVersion;
  2415. pData = new BYTE[WMDM_TRANSFER_BUFFER_SIZE];
  2416. if (!pData)
  2417. {
  2418. hr = E_OUTOFMEMORY;
  2419. goto exit;
  2420. }
  2421. dwVersion = GetVersion();
  2422. if (dwVersion < 0x80000000)
  2423. {
  2424. hFile = CreateFileW(pwszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  2425. }
  2426. else
  2427. {
  2428. hFile = CreateFileA(W2A(pwszFileName), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  2429. }
  2430. if (hFile == INVALID_HANDLE_VALUE)
  2431. {
  2432. hr = HRESULT_FROM_WIN32(GetLastError());
  2433. goto exit;
  2434. }
  2435. CORg( pObject->Open(MDSP_READ) );
  2436. fOpen = TRUE;
  2437. g_pSPs[m_wSPIndex]->GetSCClient(&pSPClient);
  2438. if (!pSPClient)
  2439. {
  2440. hr = E_FAIL;
  2441. goto exit;
  2442. }
  2443. dwBytesWritten = WMDM_TRANSFER_BUFFER_SIZE;
  2444. while ((WMDM_TRANSFER_BUFFER_SIZE == dwBytesWritten))
  2445. {
  2446. dwBytes = WMDM_TRANSFER_BUFFER_SIZE;
  2447. CORg( pObject->Read(pData, &dwBytes, abMAC) );
  2448. CORg( pSPClient->DecryptParam(pData, dwBytes) );
  2449. // Verify MAC returned by SP
  2450. CORg( pSPClient->MACInit(&hMAC) );
  2451. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(pData), dwBytes) );
  2452. CORg( pSPClient->MACUpdate(hMAC, (BYTE*)(&dwBytes), sizeof(dwBytes)) );
  2453. CORg( pSPClient->MACFinal(hMAC, abMACVerify) );
  2454. if (memcmp(abMACVerify, abMAC, WMDM_MAC_LENGTH) != 0)
  2455. {
  2456. hr = WMDM_E_MAC_CHECK_FAILED;
  2457. goto exit;
  2458. }
  2459. CFRg( WriteFile(hFile, pData, dwBytes, &dwBytesWritten, NULL) );
  2460. dwTotalBytes+=dwBytesWritten;
  2461. if (pProgress)
  2462. {
  2463. CORg( pProgress->Progress(dwTotalBytes) );
  2464. }
  2465. }
  2466. exit:
  2467. Error:
  2468. if (hFile != INVALID_HANDLE_VALUE)
  2469. {
  2470. CloseHandle(hFile);
  2471. }
  2472. if (pObject && fOpen)
  2473. {
  2474. HRESULT hr2 = pObject->Close();
  2475. hr = FAILED(hr)?hr:hr2;
  2476. }
  2477. SAFE_ARRAY_DELETE(pData);
  2478. hrLogDWORD("CWMDMStorage::hrCopyToFileFromStorage returned 0x%08lx", hr, hr);
  2479. return hr;
  2480. }
  2481. DWORD InsertThreadFunc(void *pData)
  2482. {
  2483. INSERTTHREADARGS *pThreadArgs = NULL;
  2484. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  2485. if (SUCCEEDED(hr))
  2486. {
  2487. pThreadArgs = (INSERTTHREADARGS *)pData;
  2488. // We need to marshal the interfaces that the application passes down to us.
  2489. // These interfaces can come from an STA and we will make callabacks on them.
  2490. IWMDMOperation *pOperation = NULL;
  2491. IWMDMProgress *pProgress = NULL;
  2492. IUnknown *pUnknown = NULL;
  2493. if( pThreadArgs->pOperationStream )
  2494. {
  2495. hr = CoGetInterfaceAndReleaseStream( pThreadArgs->pOperationStream,
  2496. __uuidof(IWMDMOperation),
  2497. (void**)&pOperation );
  2498. }
  2499. if (SUCCEEDED(hr) && pThreadArgs->pProgressStream )
  2500. {
  2501. hr = CoGetInterfaceAndReleaseStream( pThreadArgs->pProgressStream,
  2502. __uuidof(IWMDMProgress),
  2503. (void**)&pProgress );
  2504. }
  2505. if (SUCCEEDED(hr) && pThreadArgs->pUnknownStream )
  2506. {
  2507. hr = CoGetInterfaceAndReleaseStream( pThreadArgs->pUnknownStream,
  2508. __uuidof(IUnknown),
  2509. (void**)&pUnknown );
  2510. }
  2511. if (SUCCEEDED(hr))
  2512. {
  2513. hr = ((CWMDMStorage *)(pThreadArgs->pThis))->InsertWorker(pThreadArgs->fuMode,
  2514. pThreadArgs->pwszFileSource,
  2515. pThreadArgs->pwszFileDest,
  2516. pOperation,
  2517. pProgress,
  2518. pUnknown,
  2519. pThreadArgs->ppNewObject);
  2520. }
  2521. SAFE_RELEASE( pOperation );
  2522. SAFE_RELEASE( pProgress );
  2523. SAFE_RELEASE( pUnknown );
  2524. CoUninitialize();
  2525. }
  2526. if (pThreadArgs)
  2527. {
  2528. SAFE_DELETE( pThreadArgs->pwszFileSource);
  2529. SAFE_DELETE( pThreadArgs->pwszFileDest);
  2530. SAFE_RELEASE( pThreadArgs->pThis );
  2531. }
  2532. delete pData;
  2533. return SUCCEEDED(hr)?0:-1;
  2534. }
  2535. HRESULT CWMDMStorage::InsertWorker(UINT fuMode,
  2536. LPWSTR pwszFileSource,
  2537. LPWSTR pwszFileDest,
  2538. IWMDMOperation *pOperation,
  2539. IWMDMProgress *pProgress,
  2540. IUnknown* pUnknown,
  2541. IWMDMStorage **ppNewObject)
  2542. {
  2543. HRESULT hr;
  2544. HRESULT hr2;
  2545. IMDSPStorage *pNewSPStorage = NULL;
  2546. CComObject<CWMDMStorage> *pNewWMDMStorage = NULL;
  2547. IWMDMStorage *pNewIWMDMStorage = NULL;
  2548. UINT fuNewMode = 0;
  2549. WCHAR wszDest[512];
  2550. BOOL fQuery;
  2551. BOOL fOperation;
  2552. DWORD dwAttributes;
  2553. BOOL fIsFile;
  2554. IMDSPObject *pObject = NULL;
  2555. // BUGBUG: Fix this to a normal WAVEFORMATEX
  2556. _WAVEFORMATEX Format;
  2557. BOOL fBeginCalled = FALSE;
  2558. // Update storage status
  2559. m_dwStatus &= WMDM_STATUS_STORAGECONTROL_INSERTING;
  2560. fOperation = fuMode & WMDM_CONTENT_OPERATIONINTERFACE;
  2561. fIsFile = fuMode & WMDM_CONTENT_FILE;
  2562. fuNewMode = fuMode & (WMDM_STORAGECONTROL_INSERTINTO | WMDM_STORAGECONTROL_INSERTAFTER | WMDM_STORAGECONTROL_INSERTBEFORE);
  2563. if ((fOperation) && (!pOperation))
  2564. {
  2565. hr = E_INVALIDARG;
  2566. goto exit;
  2567. }
  2568. // BUGBUG: Deal with WAVEFORMATEX
  2569. if (!fOperation)
  2570. {
  2571. if (!pwszFileSource)
  2572. {
  2573. hr = E_INVALIDARG;
  2574. goto exit;
  2575. }
  2576. // Get output file name
  2577. if( pwszFileDest != NULL )
  2578. {
  2579. // Use name passed in
  2580. wcsncpy(wszDest, pwszFileDest, sizeof(wszDest)/sizeof(wszDest[0]));
  2581. }
  2582. else
  2583. {
  2584. // Use same as source name
  2585. if (NULL != wcschr(pwszFileSource, L'\\'))
  2586. {
  2587. // Copy source name from last '\'
  2588. wcsncpy(wszDest, (LPWSTR)(wcsrchr(pwszFileSource, L'\\') + 1), sizeof(wszDest)/sizeof(wszDest[0]) );
  2589. }
  2590. else
  2591. {
  2592. wcsncpy(wszDest, pwszFileSource, sizeof(wszDest)/sizeof(wszDest[0]) );
  2593. }
  2594. }
  2595. if (fuMode & WMDM_CONTENT_FILE)
  2596. {
  2597. fuNewMode |= WMDM_FILE_ATTR_FILE;
  2598. }
  2599. else if (fuMode & WMDM_CONTENT_FOLDER)
  2600. {
  2601. fuNewMode |= WMDM_FILE_ATTR_FOLDER;
  2602. }
  2603. else
  2604. {
  2605. hr = E_INVALIDARG;
  2606. goto exit;
  2607. }
  2608. if (fuMode & WMDM_FILE_CREATE_OVERWRITE)
  2609. {
  2610. fuNewMode |= WMDM_FILE_CREATE_OVERWRITE;
  2611. }
  2612. }
  2613. else
  2614. {
  2615. CORg( pOperation->BeginWrite() );
  2616. if( pwszFileDest != NULL )
  2617. {
  2618. // Use name passed in
  2619. wcsncpy(wszDest, pwszFileDest, sizeof(wszDest)/sizeof(wszDest[0]) );
  2620. }
  2621. else
  2622. {
  2623. CORg( pOperation->GetObjectName(wszDest, 512) );
  2624. }
  2625. CORg( pOperation->GetObjectAttributes(&dwAttributes, &Format) );
  2626. fIsFile = dwAttributes & WMDM_FILE_ATTR_FILE;
  2627. fuNewMode |= dwAttributes;
  2628. }
  2629. fQuery = fuMode & WMDM_MODE_QUERY;
  2630. if (fIsFile)
  2631. {
  2632. if (fOperation)
  2633. {
  2634. fBeginCalled = TRUE;
  2635. hr = hrCopyToStorageFromOperation(fuMode, pOperation,
  2636. fuNewMode, wszDest,
  2637. pNewIWMDMStorage,
  2638. pProgress, pUnknown,
  2639. fQuery);
  2640. CORg( hr );
  2641. }
  2642. else
  2643. {
  2644. fBeginCalled = TRUE;
  2645. hr = hrCopyToStorageFromFile(fuMode, pwszFileSource,
  2646. fuNewMode, wszDest,
  2647. pNewIWMDMStorage,
  2648. pProgress, pUnknown,
  2649. fQuery);
  2650. CORg( hr );
  2651. }
  2652. }
  2653. else
  2654. {
  2655. // Create the folder
  2656. CORg( m_pStorage->CreateStorage(fuNewMode, NULL, wszDest, &pNewSPStorage) );
  2657. CORg( CComObject<CWMDMStorage>::CreateInstance(&pNewWMDMStorage) );
  2658. CORg( pNewWMDMStorage->QueryInterface(IID_IWMDMStorage, reinterpret_cast<void**>(&pNewIWMDMStorage)) );
  2659. pNewWMDMStorage->SetContainedPointer(pNewSPStorage, m_wSPIndex);
  2660. }
  2661. exit:
  2662. Error:
  2663. if (SUCCEEDED(hr) && ppNewObject && pNewIWMDMStorage)
  2664. {
  2665. // If they gave us a pointer then they want the new storage pointer back
  2666. *ppNewObject = pNewIWMDMStorage;
  2667. (*ppNewObject)->AddRef();
  2668. }
  2669. else if(ppNewObject) *ppNewObject = NULL;
  2670. if( FAILED(hr) )
  2671. {
  2672. SAFE_RELEASE( pNewSPStorage );
  2673. SAFE_DELETE( pNewWMDMStorage );
  2674. }
  2675. SAFE_RELEASE( pNewIWMDMStorage );
  2676. if (fOperation)
  2677. {
  2678. if (FAILED(hr))
  2679. {
  2680. pOperation->End(&hr, NULL);
  2681. }
  2682. else
  2683. {
  2684. if (pNewIWMDMStorage)
  2685. {
  2686. pNewIWMDMStorage->AddRef();
  2687. }
  2688. pOperation->End(&hr, ppNewObject?*ppNewObject:NULL);
  2689. }
  2690. }
  2691. if (pProgress)
  2692. {
  2693. hr2 = S_OK;
  2694. if (!fBeginCalled)
  2695. {
  2696. hr2 = pProgress->Begin(1);
  2697. }
  2698. if (SUCCEEDED(hr2))
  2699. {
  2700. IWMDMProgress2 *pProgress2 = NULL;
  2701. HRESULT hrQI;
  2702. // Try to use End2 of IWMDMProgress2 interface to report error code back to caller.
  2703. hrQI = pProgress->QueryInterface( IID_IWMDMProgress2, (void**)(&pProgress2) );
  2704. if( hrQI == S_OK && pProgress2 != NULL )
  2705. {
  2706. pProgress2->End2(hr);
  2707. SAFE_RELEASE( pProgress2 );
  2708. }
  2709. else
  2710. {
  2711. pProgress->End();
  2712. }
  2713. }
  2714. }
  2715. SAFE_RELEASE(pObject);
  2716. // Update storage status
  2717. m_dwStatus &= !WMDM_STATUS_STORAGECONTROL_INSERTING;
  2718. hrLogDWORD("CWMDMStorage::InsertWorker returned 0x%08lx", hr, hr);
  2719. return hr;
  2720. }
  2721. DWORD DeleteThreadFunc(void *pData)
  2722. {
  2723. DELETETHREADARGS *pThreadArgs = NULL;
  2724. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  2725. if (SUCCEEDED(hr))
  2726. {
  2727. IWMDMProgress* pProgress = NULL;
  2728. pThreadArgs = (DELETETHREADARGS *)pData;
  2729. if( pThreadArgs->pProgressStream )
  2730. {
  2731. hr = CoGetInterfaceAndReleaseStream( pThreadArgs->pProgressStream,
  2732. __uuidof(IWMDMProgress),
  2733. (void**)&pProgress );
  2734. }
  2735. hr = ((CWMDMStorage *)(pThreadArgs->pThis))->DeleteWorker( pThreadArgs->fuMode,
  2736. pProgress );
  2737. SAFE_RELEASE( pProgress );
  2738. CoUninitialize();
  2739. }
  2740. if (pThreadArgs)
  2741. {
  2742. SAFE_RELEASE( pThreadArgs->pThis );
  2743. }
  2744. delete pData;
  2745. return SUCCEEDED(hr)?0:-1;
  2746. }
  2747. HRESULT CWMDMStorage::DeleteWorker(UINT fuMode, IWMDMProgress *pProgress)
  2748. {
  2749. HRESULT hr;
  2750. IMDSPObject *pObject = NULL;
  2751. // Update storage status
  2752. m_dwStatus &= WMDM_STATUS_STORAGECONTROL_DELETING;
  2753. hr = m_pStorage->QueryInterface(IID_IMDSPObject, reinterpret_cast<void**>(&pObject));
  2754. if (FAILED(hr))
  2755. {
  2756. goto exit;
  2757. }
  2758. hr = pObject->Delete(fuMode, pProgress);
  2759. if (FAILED(hr))
  2760. {
  2761. goto exit;
  2762. }
  2763. exit:
  2764. if (pObject)
  2765. pObject->Release();
  2766. // Update storage status
  2767. m_dwStatus &= !WMDM_STATUS_STORAGECONTROL_DELETING;
  2768. hrLogDWORD("CWMDMStorage::DeleteWorker returned 0x%08lx", hr, hr);
  2769. return hr;
  2770. }
  2771. DWORD RenameThreadFunc(void *pData)
  2772. {
  2773. RENAMETHREADARGS *pThreadArgs = NULL;
  2774. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  2775. if (SUCCEEDED(hr))
  2776. {
  2777. IWMDMProgress* pProgress = NULL;
  2778. pThreadArgs = (RENAMETHREADARGS *)pData;
  2779. if( pThreadArgs->pProgressStream )
  2780. {
  2781. hr = CoGetInterfaceAndReleaseStream( pThreadArgs->pProgressStream,
  2782. __uuidof(IWMDMProgress),
  2783. (void**)&pProgress );
  2784. }
  2785. hr = ((CWMDMStorage *)(pThreadArgs->pThis))->RenameWorker(pThreadArgs->pwszNewName,
  2786. pProgress );
  2787. SAFE_RELEASE( pProgress );
  2788. CoUninitialize();
  2789. }
  2790. if (pThreadArgs)
  2791. {
  2792. if (pThreadArgs->pwszNewName)
  2793. delete pThreadArgs->pwszNewName;
  2794. SAFE_RELEASE( pThreadArgs->pThis );
  2795. }
  2796. delete pData;
  2797. return SUCCEEDED(hr)?0:-1;
  2798. }
  2799. HRESULT CWMDMStorage::RenameWorker(LPWSTR pwszNewName,
  2800. IWMDMProgress *pProgress)
  2801. {
  2802. HRESULT hr;
  2803. IMDSPObject *pObject = NULL;
  2804. if ((!pwszNewName) || (wcslen(pwszNewName) == 0))
  2805. {
  2806. hr = E_INVALIDARG;
  2807. goto exit;
  2808. }
  2809. hr = m_pStorage->QueryInterface(IID_IMDSPObject, reinterpret_cast<void**>(&pObject));
  2810. if (SUCCEEDED(hr))
  2811. {
  2812. hr = pObject->Rename(pwszNewName, pProgress);
  2813. pObject->Release();
  2814. }
  2815. exit:
  2816. hrLogDWORD("CWMDMStorage::RenameWorker returned 0x%08lx", hr, hr);
  2817. return hr;
  2818. }
  2819. DWORD ReadThreadFunc(void *pData)
  2820. {
  2821. READTHREADARGS *pThreadArgs = NULL;
  2822. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  2823. if (SUCCEEDED(hr))
  2824. {
  2825. IWMDMOperation* pOperation = NULL;
  2826. IWMDMProgress* pProgress = NULL;
  2827. pThreadArgs = (READTHREADARGS *)pData;
  2828. if( pThreadArgs->pOperationStream )
  2829. {
  2830. hr = CoGetInterfaceAndReleaseStream( pThreadArgs->pOperationStream,
  2831. __uuidof(IWMDMOperation),
  2832. (void**)&pOperation );
  2833. }
  2834. if (SUCCEEDED(hr) && pThreadArgs->pProgressStream )
  2835. {
  2836. hr = CoGetInterfaceAndReleaseStream( pThreadArgs->pProgressStream,
  2837. __uuidof(IWMDMProgress),
  2838. (void**)&pProgress );
  2839. }
  2840. hr = ((CWMDMStorage *)(pThreadArgs->pThis))->ReadWorker(pThreadArgs->fuMode,
  2841. pThreadArgs->pwszFile,
  2842. pProgress,
  2843. pOperation);
  2844. SAFE_RELEASE(pOperation);
  2845. SAFE_RELEASE(pProgress);
  2846. CoUninitialize();
  2847. }
  2848. if (pThreadArgs)
  2849. {
  2850. if (pThreadArgs->pwszFile)
  2851. delete pThreadArgs->pwszFile;
  2852. SAFE_RELEASE( pThreadArgs->pThis );
  2853. }
  2854. delete pData;
  2855. return SUCCEEDED(hr)?0:-1;
  2856. }
  2857. HRESULT CWMDMStorage::ReadWorker(UINT fuMode,
  2858. LPWSTR pwszFile,
  2859. IWMDMProgress *pProgress,
  2860. IWMDMOperation *pOperation)
  2861. {
  2862. HRESULT hr;
  2863. IMDSPObject *pObject = NULL;
  2864. DWORD dwFileSize;
  2865. DWORD dwFileSizeHigh;
  2866. BOOL fBeginCalled = FALSE;
  2867. // Update Storage status
  2868. m_dwStatus &= WMDM_STATUS_STORAGECONTROL_READING;
  2869. hr = m_pStorage->GetSize(&dwFileSize, &dwFileSizeHigh);
  2870. if (FAILED(hr))
  2871. {
  2872. goto exit;
  2873. }
  2874. if (pProgress)
  2875. {
  2876. hr = pProgress->Begin(dwFileSize);
  2877. fBeginCalled = TRUE;
  2878. if (FAILED(hr))
  2879. {
  2880. goto exit;
  2881. }
  2882. }
  2883. hr = m_pStorage->QueryInterface(IID_IMDSPObject, reinterpret_cast<void**>(&pObject));
  2884. if (FAILED(hr))
  2885. {
  2886. goto exit;
  2887. }
  2888. if (fuMode & WMDM_CONTENT_OPERATIONINTERFACE)
  2889. {
  2890. if (!pOperation)
  2891. {
  2892. hr = E_INVALIDARG;
  2893. goto exit;
  2894. }
  2895. hr = hrCopyToOperationFromStorage(pOperation, pProgress, pObject);
  2896. if (FAILED(hr))
  2897. {
  2898. goto exit;
  2899. }
  2900. }
  2901. else
  2902. {
  2903. if (!pwszFile)
  2904. {
  2905. hr = E_INVALIDARG;
  2906. goto exit;
  2907. }
  2908. hr = hrCopyToFileFromStorage(pwszFile, pProgress, pObject);
  2909. if (FAILED(hr))
  2910. {
  2911. goto exit;
  2912. }
  2913. }
  2914. exit:
  2915. if (pObject)
  2916. pObject->Release();
  2917. if (pProgress)
  2918. {
  2919. IWMDMProgress2 *pProgress2 = NULL;
  2920. HRESULT hrQI;
  2921. if (!fBeginCalled)
  2922. {
  2923. pProgress->Begin(1);
  2924. }
  2925. // Try to use End2 of IWMDMProgress2 interface to report error code back to caller.
  2926. hrQI = pProgress->QueryInterface( IID_IWMDMProgress2, (void**)(&pProgress2) );
  2927. if( hrQI == S_OK && pProgress2 != NULL )
  2928. {
  2929. pProgress2->End2(hr);
  2930. SAFE_RELEASE( pProgress2 );
  2931. }
  2932. else
  2933. {
  2934. pProgress->End();
  2935. }
  2936. }
  2937. // Update Storage status
  2938. m_dwStatus &= !WMDM_STATUS_STORAGECONTROL_READING;
  2939. hrLogDWORD("CWMDMStorage::ReadWorker returned 0x%08lx", hr, hr);
  2940. return hr;
  2941. }
  2942. // IWMDMRevoked
  2943. HRESULT CWMDMStorage::GetRevocationURL( LPWSTR* ppwszRevocationURL,
  2944. DWORD* pdwBufferLen,
  2945. OUT DWORD* pdwRevokedBitFlag )
  2946. {
  2947. HRESULT hr = S_OK;
  2948. CARg( ppwszRevocationURL );
  2949. CARg( pdwBufferLen );
  2950. CARg( pdwRevokedBitFlag );
  2951. // Is the buffer passed in big enough?
  2952. if( *pdwBufferLen < wcslen( m_pwszRevocationURL ) || *ppwszRevocationURL == NULL )
  2953. {
  2954. // Allocate new buffer
  2955. *pdwBufferLen = wcslen( m_pwszRevocationURL ) + 1;
  2956. CoTaskMemFree( *ppwszRevocationURL );
  2957. *ppwszRevocationURL = (LPWSTR)CoTaskMemAlloc( *pdwBufferLen * sizeof(WCHAR) );
  2958. if( *ppwszRevocationURL == NULL )
  2959. {
  2960. hr = E_OUTOFMEMORY;
  2961. goto Error;
  2962. }
  2963. }
  2964. wcscpy( *ppwszRevocationURL, m_pwszRevocationURL );
  2965. *pdwRevokedBitFlag = m_dwRevocationBitFlag;
  2966. Error:
  2967. return hr;
  2968. }
  2969. // We might change the URL given to us by the SCP if the WMDM client or the SP is revoked
  2970. HRESULT CWMDMStorage::UpdateRevocationURL( IN OUT LPWSTR* ppwszRevocationURL,
  2971. IN OUT DWORD* pdwBufferLen,
  2972. IN DWORD* pdwRevocationBitFlag )
  2973. {
  2974. HRESULT hr = S_OK;
  2975. IMDServiceProvider* pSP = NULL;
  2976. IMDSPRevoked* pIMDSPRevoked = NULL;
  2977. BOOL bUpdateOK = FALSE;
  2978. LPWSTR pszTempURL;
  2979. DWORD dwTempLen = *pdwBufferLen;
  2980. // Work with a temp url so that we don't destroy a good url if something fails
  2981. pszTempURL = (LPWSTR)CoTaskMemAlloc( *pdwBufferLen * sizeof(WCHAR) );
  2982. CPRg( pszTempURL );
  2983. wcscpy( pszTempURL, *ppwszRevocationURL );
  2984. // If the SP has been revoked give it a chance to specify an URL of it's own.
  2985. if( *pdwRevocationBitFlag & WMDM_SP_REVOKED )
  2986. {
  2987. CORg( g_pSPs[m_wSPIndex]->hrGetInterface(&pSP) );
  2988. hr = pSP->QueryInterface( IID_IMDSPRevoked, (void**)&pIMDSPRevoked );
  2989. if( SUCCEEDED(hr) && pIMDSPRevoked )
  2990. {
  2991. hr = pIMDSPRevoked->GetRevocationURL( &pszTempURL, &dwTempLen );
  2992. if( hr != S_OK)
  2993. {
  2994. // We failed to update the string, reset it to initial value
  2995. dwTempLen = *pdwBufferLen;
  2996. CoTaskMemFree( pszTempURL );
  2997. pszTempURL = (LPWSTR)CoTaskMemAlloc( *pdwBufferLen * sizeof(WCHAR) );
  2998. CPRg( pszTempURL );
  2999. wcscpy( pszTempURL, *ppwszRevocationURL );
  3000. }
  3001. else
  3002. {
  3003. bUpdateOK = TRUE;
  3004. }
  3005. }
  3006. }
  3007. // If the WMDM client is revoked we should go to the MS update URL
  3008. if( (*pdwRevocationBitFlag & WMDM_WMDM_REVOKED) &&
  3009. ::IsMicrosoftRevocationURL(pszTempURL) == FALSE )
  3010. {
  3011. DWORD pdwSubjectIDs[2];
  3012. pdwSubjectIDs[0] = ::GetSubjectIDFromAppCert( *(APPCERT*)g_abAppCert );
  3013. pdwSubjectIDs[1] = 0;
  3014. hr = ::BuildRevocationURL( pdwSubjectIDs, &pszTempURL, &dwTempLen );
  3015. if(hr == S_OK)
  3016. {
  3017. bUpdateOK = TRUE;
  3018. }
  3019. }
  3020. // URL has changed, update out param.
  3021. if( bUpdateOK && wcscmp( pszTempURL, *ppwszRevocationURL ) != 0 )
  3022. {
  3023. *pdwBufferLen = dwTempLen;
  3024. CoTaskMemFree( *ppwszRevocationURL );
  3025. *ppwszRevocationURL = (LPWSTR)CoTaskMemAlloc( dwTempLen * sizeof(WCHAR) );
  3026. CPRg( *ppwszRevocationURL );
  3027. wcscpy( *ppwszRevocationURL, pszTempURL );
  3028. }
  3029. Error:
  3030. if( pszTempURL != NULL )
  3031. {
  3032. CoTaskMemFree( pszTempURL );
  3033. }
  3034. SAFE_RELEASE(pSP);
  3035. SAFE_RELEASE(pIMDSPRevoked);
  3036. return hr;
  3037. }