WMInformation.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. #include "main.h"
  2. #include "WMInformation.h"
  3. #include "resource.h"
  4. #include <exception>
  5. #include <strsafe.h>
  6. class AutoByte
  7. {
  8. public:
  9. AutoByte(size_t bytes)
  10. : data(0)
  11. {
  12. data = new BYTE[bytes];
  13. }
  14. ~AutoByte()
  15. {
  16. if (data)
  17. delete[] data;
  18. data = 0;
  19. }
  20. operator void *()
  21. {
  22. return (void *)data;
  23. }
  24. BYTE *data;
  25. };
  26. static void StoreData(WMT_ATTR_DATATYPE type, BYTE *value, DWORD length, wchar_t *valueStr, size_t len)
  27. {
  28. switch (type)
  29. {
  30. case WMT_TYPE_DWORD:
  31. StringCchPrintf(valueStr, len, L"%lu", *(DWORD *)value);
  32. break;
  33. case WMT_TYPE_STRING:
  34. lstrcpyn(valueStr, (wchar_t *)value, len);
  35. break;
  36. case -1: // hack // if (attrName == L"WM/Text")
  37. StringCchPrintf(valueStr, len, L"%s/%s", UserTextDescription(value, length), UserTextString(value, length));
  38. break;
  39. case WMT_TYPE_BINARY:
  40. BinaryString(value, length, valueStr, len);
  41. break;
  42. case WMT_TYPE_BOOL:
  43. if (*(BOOL *)value)
  44. {
  45. lstrcpyn(valueStr, L"True", len);
  46. }
  47. else
  48. {
  49. lstrcpyn(valueStr, L"False", len);
  50. }
  51. break;
  52. case WMT_TYPE_QWORD:
  53. StringCchPrintf(valueStr, len, L"%I64u", *(QWORD *)value);
  54. break;
  55. case WMT_TYPE_WORD:
  56. StringCchPrintf(valueStr, len, L"%hu", *(WORD *)value);
  57. break;
  58. case WMT_TYPE_GUID:
  59. GuidString(*(GUID *)value, valueStr, len);
  60. break;
  61. default:
  62. WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN,valueStr,len);
  63. break;
  64. }
  65. }
  66. WMInformation::WMInformation(const wchar_t *fileName, bool noBlock)
  67. : editor(0), editor2(0), header(0), header3(0), reader(0), header2(0), openError(false)
  68. {
  69. if (fileName && fileName[0]
  70. && WMCreateEditor(&editor) == S_OK)
  71. {
  72. if (SUCCEEDED(editor->QueryInterface(&editor2)))
  73. {
  74. if (SUCCEEDED(editor2->OpenEx(fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE)))
  75. {
  76. // good to go
  77. editor2->QueryInterface(&header);
  78. editor->QueryInterface(&header2);
  79. editor2->QueryInterface(&header3);
  80. return ;
  81. }
  82. }
  83. else
  84. {
  85. editor2 = 0;
  86. if (SUCCEEDED(editor->Open(fileName)))
  87. {
  88. // good to go
  89. editor->QueryInterface(&header);
  90. editor->QueryInterface(&header2);
  91. editor->QueryInterface(&header3);
  92. return ;
  93. }
  94. }
  95. // can't open it through the metadata editor interface, let's open a reader
  96. if (editor)
  97. editor->Release();
  98. editor = 0;
  99. if (editor2)
  100. editor2->Release();
  101. editor2 = 0;
  102. if (FAILED(WMCreateReader(0, WMT_RIGHT_PLAYBACK, &reader)))
  103. {
  104. reader = 0;
  105. return ;
  106. }
  107. hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  108. callback >> this;
  109. if (FAILED(reader->Open(fileName, &callback, 0)))
  110. {
  111. reader->Release();
  112. reader = 0;
  113. return ;
  114. }
  115. if (noBlock)
  116. WaitForEvent(hEvent, INFINITE);
  117. else
  118. WaitForSingleObject(hEvent, INFINITE);
  119. CloseHandle(hEvent);
  120. if (openError)
  121. {
  122. reader->Release();
  123. reader = 0;
  124. }
  125. else
  126. {
  127. reader->QueryInterface(&header);
  128. reader->QueryInterface(&header2);
  129. reader->QueryInterface(&header3);
  130. }
  131. }
  132. }
  133. WMInformation::WMInformation(IWMReader *_reader)
  134. : reader(0), // reader is if we create an internal reader, we don't want to save the passed one (so we don't close it on someone else :)
  135. editor(0), editor2(0), header(0),
  136. header3(0), header2(0),
  137. openError(false), hEvent(NULL)
  138. {
  139. if (FAILED(_reader->QueryInterface(&header)))
  140. header = 0;
  141. if (FAILED(_reader->QueryInterface(&header2)))
  142. header2 = 0;
  143. if (FAILED(_reader->QueryInterface(&header3)))
  144. header3 = 0; // this error is OK, we can deal with it.
  145. }
  146. /*
  147. WMInformation::WMInformation(IWMSyncReader *reader)
  148. : editor(0), editor2(0), header(0), header3(0)
  149. {
  150. reader->QueryInterface(&header);
  151. reader->QueryInterface(&header3);
  152. }*/
  153. WMInformation::WMInformation(IWMMetadataEditor *_editor)
  154. : editor(_editor), editor2(0), header(0),
  155. header3(0), reader(0), header2(0),
  156. openError(false), hEvent(NULL)
  157. {
  158. editor->AddRef();
  159. editor->QueryInterface(&editor2);
  160. editor->QueryInterface(&header);
  161. editor->QueryInterface(&header2);
  162. editor->QueryInterface(&header3);
  163. }
  164. WMInformation::~WMInformation()
  165. {
  166. if (editor)
  167. {
  168. editor->Close();
  169. editor->Release();
  170. editor = 0;
  171. }
  172. if (editor2)
  173. editor2->Release();
  174. editor2 = 0;
  175. if (header)
  176. header->Release();
  177. header = 0;
  178. if (header2)
  179. header2->Release();
  180. header2 = 0;
  181. if (header3)
  182. header3->Release();
  183. header3 = 0;
  184. if (reader)
  185. {
  186. reader->Close();
  187. reader->Release();
  188. reader = 0;
  189. }
  190. }
  191. bool WMInformation::GetDataType(const wchar_t *name, WMT_ATTR_DATATYPE &type)
  192. {
  193. if (!name)
  194. return false;
  195. WORD stream = 0;
  196. WORD dataLen = 0;
  197. if (header && SUCCEEDED(header->GetAttributeByName(&stream, name, &type, 0, &dataLen)))
  198. return true;
  199. else
  200. return false;
  201. }
  202. void WMInformation::DeleteAttribute(const wchar_t *attrName)
  203. {
  204. WORD indexCount = 0;
  205. if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, attrName, NULL, 0, &indexCount)))
  206. {
  207. WORD *indices = new WORD[indexCount];
  208. if (SUCCEEDED(header3->GetAttributeIndices(0, attrName, NULL, indices, &indexCount)))
  209. {
  210. for (size_t i = 0;i != indexCount;i++)
  211. {
  212. header3->DeleteAttribute(0, indices[i]);
  213. }
  214. }
  215. }
  216. }
  217. void WMInformation::SetAttribute_BinString(const wchar_t *attrName, wchar_t *value)
  218. {
  219. if (!header || !attrName || !value)
  220. return ;
  221. if (!*value)
  222. {
  223. DeleteAttribute(attrName);
  224. return ;
  225. }
  226. AutoChar data(value);
  227. header->SetAttribute(0, attrName, WMT_TYPE_BINARY, (BYTE *)(char *)data, (WORD)strlen(data));
  228. }
  229. void WMInformation::GetAttribute_BinString(const wchar_t attrName[], wchar_t *valueStr, size_t len)
  230. {
  231. if (!header)
  232. {
  233. valueStr[0]=0;
  234. return ;
  235. }
  236. WMT_ATTR_DATATYPE type;
  237. WORD length = 0;
  238. HRESULT hr;
  239. WORD streamNum = 0;
  240. if (!header || FAILED(header->GetAttributeByName(&streamNum,
  241. attrName,
  242. &type,
  243. 0,
  244. &length)))
  245. {
  246. valueStr[0]=0;
  247. return ;
  248. }
  249. AutoByte v(length);
  250. BYTE *value = v.data;
  251. hr = header->GetAttributeByName(&streamNum,
  252. attrName,
  253. &type,
  254. value,
  255. &length);
  256. if (FAILED(hr))
  257. {
  258. valueStr[0]=0;
  259. return ;
  260. }
  261. int converted = MultiByteToWideChar(CP_ACP, 0, (const char *)value, length, valueStr, len-1);
  262. valueStr[converted]=0;
  263. }
  264. void WMInformation::SetAttribute(const wchar_t *attrName, wchar_t *value, WMT_ATTR_DATATYPE defaultType)
  265. {
  266. if (!header || !attrName || !value)
  267. return ;
  268. if (!*value)
  269. {
  270. DeleteAttribute(attrName);
  271. return ;
  272. }
  273. WMT_ATTR_DATATYPE type;
  274. if (!GetDataType(attrName, type))
  275. type = defaultType;
  276. switch (type)
  277. {
  278. case WMT_TYPE_DWORD:
  279. {
  280. DWORD dwordValue = wcstoul(value, 0, 10);
  281. header->SetAttribute(0, attrName, WMT_TYPE_DWORD, (BYTE *) &dwordValue, sizeof(dwordValue));
  282. }
  283. break;
  284. case WMT_TYPE_STRING:
  285. {
  286. WORD size = static_cast<WORD>((lstrlen(value) + 1) * sizeof(wchar_t));
  287. header->SetAttribute(0, attrName, WMT_TYPE_STRING, (BYTE *)value, size);
  288. }
  289. break;
  290. case WMT_TYPE_BINARY:
  291. {
  292. // TODO
  293. }
  294. break;
  295. case WMT_TYPE_BOOL:
  296. {
  297. BOOL boolValue;
  298. if (!_wcsicmp(L"true", value))
  299. boolValue = TRUE;
  300. else
  301. boolValue = FALSE;
  302. header->SetAttribute(0, attrName, WMT_TYPE_BOOL, (BYTE *)&boolValue, sizeof(boolValue));
  303. }
  304. break;
  305. case WMT_TYPE_QWORD:
  306. {
  307. {
  308. QWORD qwordValue = _wcstoui64(value, 0, 10);
  309. header->SetAttribute(0, attrName, WMT_TYPE_QWORD, (BYTE *) &qwordValue, sizeof(qwordValue));
  310. }
  311. }
  312. break;
  313. case WMT_TYPE_WORD:
  314. {
  315. {
  316. WORD wordValue = static_cast<WORD>(wcstoul(value, 0, 10));
  317. header->SetAttribute(0, attrName, WMT_TYPE_WORD, (BYTE *) &wordValue, sizeof(wordValue));
  318. }
  319. }
  320. break;
  321. case WMT_TYPE_GUID:
  322. {
  323. GUID guidValue = StringGUID(value);
  324. header->SetAttribute(0, attrName, WMT_TYPE_GUID, (BYTE *) &guidValue, sizeof(guidValue));
  325. }
  326. break;
  327. }
  328. }
  329. bool WMInformation::GetAttributeSize(const wchar_t *name, size_t &size)
  330. {
  331. WORD stream = 0;
  332. WORD resultSize;
  333. WMT_ATTR_DATATYPE type;
  334. if (!header || FAILED(header->GetAttributeByName(&stream, name, &type, 0, &resultSize)))
  335. {
  336. return false;
  337. }
  338. size = resultSize;
  339. return true;
  340. }
  341. DWORD WMInformation::GetDWORDAttr(const wchar_t name[])
  342. {
  343. WORD stream = 0;
  344. DWORD result;
  345. WORD resultSizeWord = sizeof(result);
  346. DWORD resultSize = sizeof(result);
  347. WMT_ATTR_DATATYPE type = WMT_TYPE_DWORD;
  348. WORD count = 1;
  349. WORD indices[1] = {0};
  350. if ((!header3
  351. || FAILED(header3->GetAttributeIndices(0, name, NULL, indices, &count))
  352. || FAILED(header3->GetAttributeByIndexEx(0, indices[0], 0, 0, &type, NULL, (BYTE *) &result, &resultSize)))
  353. &&
  354. (!header || FAILED(header->GetAttributeByName(&stream, name, &type, (BYTE *)&result, &resultSizeWord))))
  355. return 0;
  356. else
  357. return result;
  358. }
  359. long WMInformation::GetLongAttr(const wchar_t name[])
  360. {
  361. WORD stream = 0;
  362. long result;
  363. WORD resultSize = sizeof(result);
  364. WMT_ATTR_DATATYPE type;
  365. if (!header || FAILED(header->GetAttributeByName(&stream, name, &type, (BYTE *)&result, &resultSize)))
  366. {
  367. return 0;
  368. }
  369. return result;
  370. }
  371. bool WMInformation::GetBoolAttr(const wchar_t name[])
  372. {
  373. WORD stream = 0;
  374. BOOL result;
  375. WORD resultSize = sizeof(result);
  376. WMT_ATTR_DATATYPE type;
  377. if (!header || FAILED(header->GetAttributeByName(&stream, name, &type, (BYTE *)&result, &resultSize)))
  378. {
  379. return false;
  380. }
  381. return !!result;
  382. }
  383. bool WMInformation::IsSeekable()
  384. {
  385. return GetBoolAttr(g_wszWMSeekable);
  386. }
  387. long WMInformation::GetLengthMilliseconds()
  388. {
  389. WORD stream = 0;
  390. long long duration = 0;
  391. WORD resultSize = sizeof(duration);
  392. WMT_ATTR_DATATYPE type;
  393. if (!header || FAILED(header->GetAttributeByName(&stream, g_wszWMDuration, &type, (BYTE *)&duration, &resultSize)))
  394. {
  395. return -1000;
  396. }
  397. duration /= 10000LL;
  398. return (long)duration;
  399. }
  400. long WMInformation::GetBitrate()
  401. {
  402. return GetDWORDAttr(g_wszWMCurrentBitrate);
  403. }
  404. WORD WMInformation::GetNumberAttributes()
  405. {
  406. WORD numAttr = 0;
  407. if ((!header3 || FAILED(header3->GetAttributeCountEx(0, &numAttr)))
  408. && (!header || FAILED(header->GetAttributeCount(0, &numAttr))))
  409. return 0;
  410. else
  411. return numAttr;
  412. }
  413. void WMInformation::GetAttribute(WORD index, wchar_t *attrName, size_t attrLen, wchar_t *valueStr, size_t valueStrLen)
  414. {
  415. wchar_t _attrName[1025] = {0};
  416. WORD nameLen = sizeof(_attrName) / sizeof(_attrName[0]);
  417. WMT_ATTR_DATATYPE type;
  418. WORD lang;
  419. WORD stream = 0;
  420. DWORD length = 0;
  421. WORD lengthWord = 0;
  422. if ((!header3 || FAILED(header3->GetAttributeByIndexEx(0, index, _attrName, &nameLen, &type, &lang, 0, &length)))
  423. && (!header || FAILED(header->GetAttributeByIndex(index, &stream, _attrName, &nameLen, &type, 0, &lengthWord))))
  424. {
  425. attrName[0]=0;
  426. valueStr[0]=0;
  427. return ;
  428. }
  429. if (lengthWord)
  430. length = lengthWord;
  431. AutoByte v(length);
  432. BYTE *value = v.data;
  433. lstrcpyn(attrName, _attrName, attrLen);
  434. if ((!header3 || FAILED(header3->GetAttributeByIndexEx(0, index, _attrName, &nameLen, &type, &lang, value, &length)))
  435. && (!header || FAILED(header->GetAttributeByIndex(index, &stream, _attrName, &nameLen, &type, value, &lengthWord))))
  436. {
  437. attrName[0]=0;
  438. valueStr[0]=0;
  439. return ;
  440. }
  441. if (attrName == L"WM/Text")
  442. {
  443. type = (WMT_ATTR_DATATYPE)-1; // hack
  444. StringCchCat(attrName, attrLen, L":");
  445. StringCchCat(attrName, attrLen, UserTextDescription(value, length));
  446. }
  447. StoreData(type, value, length, valueStr, valueStrLen);
  448. }
  449. void WMInformation::GetAttribute(const wchar_t attrName[], wchar_t *valueStr, size_t len)
  450. {
  451. if (!header)
  452. {
  453. valueStr[0]=0;
  454. return ;
  455. }
  456. WMT_ATTR_DATATYPE type;
  457. WORD length = 0;
  458. HRESULT hr;
  459. WORD streamNum = 0;
  460. if (!header || FAILED(header->GetAttributeByName(&streamNum,
  461. attrName,
  462. &type,
  463. 0,
  464. &length)))
  465. {
  466. valueStr[0]=0;
  467. return ;
  468. }
  469. AutoByte v(length);
  470. BYTE *value = v.data;
  471. hr = header->GetAttributeByName(&streamNum,
  472. attrName,
  473. &type,
  474. value,
  475. &length);
  476. if (FAILED(hr))
  477. {
  478. valueStr[0]=0;
  479. return ;
  480. }
  481. if (attrName == L"WM/Text")
  482. type = (WMT_ATTR_DATATYPE)-1; // hack
  483. StoreData(type, value, length, valueStr, len);
  484. }
  485. bool WMInformation::MakeWritable(const wchar_t *fileName)
  486. {
  487. if (!editor || !editor2)
  488. return false;
  489. if (FAILED(editor2->OpenEx(fileName, GENERIC_READ | GENERIC_WRITE, 0)))
  490. {
  491. return false;
  492. }
  493. return true;
  494. }
  495. bool WMInformation::Flush()
  496. {
  497. if (!editor2 || FAILED(editor->Flush()))
  498. return false;
  499. return true;
  500. }
  501. bool WMInformation::IsAttribute(const wchar_t attrName[])
  502. {
  503. WMT_ATTR_DATATYPE type = WMT_TYPE_BOOL;
  504. WORD length = sizeof(BOOL);
  505. WORD streamNum = 0;
  506. BOOL value;
  507. if (!header || FAILED(header->GetAttributeByName(&streamNum,
  508. attrName,
  509. &type,
  510. (BYTE *)&value,
  511. &length)))
  512. {
  513. return false;
  514. }
  515. else
  516. {
  517. return !!value;
  518. }
  519. }
  520. bool WMInformation::IsNotAttribute(const wchar_t attrName[])
  521. {
  522. if (!header)
  523. {
  524. return false;
  525. }
  526. WMT_ATTR_DATATYPE type = WMT_TYPE_BOOL;
  527. WORD length = sizeof(BOOL);
  528. WORD streamNum = 0;
  529. BOOL value;
  530. if (!header || FAILED(header->GetAttributeByName(&streamNum,
  531. attrName,
  532. &type,
  533. (BYTE *)&value,
  534. &length)))
  535. {
  536. return false;
  537. }
  538. else
  539. {
  540. return !value;
  541. }
  542. }
  543. bool WMInformation::MakeReadOnly(const wchar_t *fileName)
  544. {
  545. if (!editor || !editor2)
  546. return false;
  547. //editor->Close();
  548. if (FAILED(editor2->OpenEx(fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE)))
  549. {
  550. return false;
  551. }
  552. return true;
  553. }
  554. bool WMInformation::NonWritable()
  555. {
  556. if (!editor2)
  557. return true;
  558. else
  559. return false;
  560. }
  561. void WMInformation::DeleteUserText(const wchar_t *description)
  562. {
  563. WORD indexCount = 0;
  564. WMT_ATTR_DATATYPE type = WMT_TYPE_BOOL;
  565. WORD nameLen = 128;
  566. if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, L"WM/Text", NULL, 0, &indexCount)))
  567. {
  568. WORD *indices = new WORD[indexCount];
  569. if (SUCCEEDED(header3->GetAttributeIndices(0, L"WM/Text", NULL, indices, &indexCount)))
  570. {
  571. for (size_t index = 0;index != indexCount;index++)
  572. {
  573. WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
  574. WORD lang = 0;
  575. DWORD length = 0;
  576. wchar_t _attrName[128] = L"WM/Text";
  577. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
  578. {
  579. AutoByte v(length);
  580. BYTE *value = v.data;
  581. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
  582. {
  583. if (UserTextDescription(value, length) == description)
  584. {
  585. header3->DeleteAttribute(0, indices[index]);
  586. }
  587. }
  588. }
  589. }
  590. }
  591. }
  592. }
  593. void WMInformation::SetUserText(const wchar_t *description, const wchar_t *valueStr)
  594. {
  595. if (!header3 || !description || !valueStr)
  596. return;
  597. WM_USER_TEXT userText;
  598. userText.pwszDescription = (LPWSTR)description;
  599. userText.pwszText = (LPWSTR) valueStr;
  600. WORD index;
  601. header3->AddAttribute(0, L"WM/Text", &index, WMT_TYPE_BINARY, 0, (BYTE *) &userText, sizeof(userText));
  602. }
  603. void WMInformation::ClearAllAttributes()
  604. {
  605. WORD numAttrs;
  606. header3->GetAttributeCountEx(0xFFFF, &numAttrs);
  607. while (numAttrs--)
  608. {
  609. header3->DeleteAttribute(0xFFFF, numAttrs);
  610. }
  611. }
  612. bool WMInformation::GetCodecName(wchar_t *storage, size_t len)
  613. {
  614. if (!header2)
  615. return false;
  616. DWORD codecs=0;
  617. header2->GetCodecInfoCount(&codecs);
  618. for (DWORD i=0;i!=codecs;i++)
  619. {
  620. WORD nameLen=0, descriptionLen=0, infoLen = 0;
  621. WMT_CODEC_INFO_TYPE type;
  622. header2->GetCodecInfo(i, &nameLen, 0, &descriptionLen, 0, &type, &infoLen, 0);
  623. if (type == WMT_CODECINFO_AUDIO)
  624. {
  625. wchar_t *name = new wchar_t[nameLen];
  626. wchar_t *description = new wchar_t[descriptionLen];
  627. BYTE *info = new BYTE[infoLen];
  628. header2->GetCodecInfo(i, &nameLen, name, &descriptionLen, description, &type, &infoLen, info);
  629. lstrcpynW(storage, name, len);
  630. delete[] name;
  631. delete[]description;
  632. delete[] info;
  633. return true;
  634. }
  635. }
  636. return false;
  637. }
  638. bool WMInformation::GetPicture(void **data, size_t *len, wchar_t **mimeType, int pictype)
  639. {
  640. WORD indexCount = 0;
  641. WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
  642. WORD nameLen = 128;
  643. if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, 0, &indexCount)))
  644. {
  645. WORD *indices = new WORD[indexCount];
  646. if (SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, indices, &indexCount)))
  647. {
  648. for (size_t index = 0;index != indexCount;index++)
  649. {
  650. WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
  651. WORD lang = 0;
  652. DWORD length = 0;
  653. wchar_t _attrName[128] = {0};
  654. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
  655. {
  656. AutoByte v(length);
  657. BYTE *value = v.data;
  658. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
  659. {
  660. WM_PICTURE *picture = (WM_PICTURE *)value;
  661. if (picture->bPictureType == pictype)
  662. {
  663. *len = picture->dwDataLen;
  664. *data = WASABI_API_MEMMGR->sysMalloc(*len);
  665. memcpy(*data, picture->pbData, *len);
  666. wchar_t *type=0;
  667. if (picture->pwszMIMEType)
  668. type = wcschr(picture->pwszMIMEType, L'/');
  669. if (type && *type)
  670. {
  671. type++;
  672. wchar_t *type2 = wcschr(type, L'/');
  673. if (type2 && *type2) type2++;
  674. else type2 = type;
  675. size_t mimelen = wcslen(type2)+1;
  676. *mimeType = (wchar_t *)WASABI_API_MEMMGR->sysMalloc(mimelen*sizeof(wchar_t));
  677. StringCchCopyW(*mimeType, mimelen, type2);
  678. }
  679. else
  680. *mimeType = 0; // unknown!
  681. delete[] indices;
  682. return true;
  683. }
  684. }
  685. }
  686. }
  687. }
  688. delete[] indices;
  689. }
  690. return false;
  691. }
  692. bool WMInformation::SetPicture(void *data, size_t len, const wchar_t *mimeType, int type)
  693. {
  694. WM_PICTURE picture;
  695. picture.bPictureType = type;
  696. picture.dwDataLen = len;
  697. picture.pbData = (BYTE *)data;
  698. picture.pwszDescription=L"";
  699. wchar_t mt[32] = {0};
  700. if (wcsstr(mimeType, L"/") != 0)
  701. {
  702. StringCchCopyW(mt, 32, mimeType);
  703. }
  704. else
  705. {
  706. StringCchPrintfW(mt, 32, L"image/%s", mimeType);
  707. }
  708. picture.pwszMIMEType = mt;
  709. return SUCCEEDED(header->SetAttribute(0, g_wszWMPicture, WMT_TYPE_BINARY, (const BYTE *)&picture, sizeof(picture)));
  710. }
  711. bool WMInformation::HasPicture(int pictype)
  712. {
  713. WORD indexCount = 0;
  714. WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
  715. WORD nameLen = 128;
  716. if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, 0, &indexCount)))
  717. {
  718. WORD *indices = new WORD[indexCount];
  719. if (SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, indices, &indexCount)))
  720. {
  721. for (size_t index = 0;index != indexCount;index++)
  722. {
  723. WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
  724. WORD lang = 0;
  725. DWORD length = 0;
  726. wchar_t _attrName[128] = {0};
  727. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
  728. {
  729. AutoByte v(length);
  730. BYTE *value = v.data;
  731. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
  732. {
  733. WM_PICTURE *picture = (WM_PICTURE *)value;
  734. if (picture->bPictureType == pictype)
  735. {
  736. delete[] indices;
  737. return true;
  738. }
  739. }
  740. }
  741. }
  742. }
  743. delete[] indices;
  744. }
  745. return false;
  746. }
  747. bool WMInformation::DeletePicture(int pictype)
  748. {
  749. WORD indexCount = 0;
  750. WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
  751. WORD nameLen = 128;
  752. if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, 0, &indexCount)))
  753. {
  754. WORD *indices = new WORD[indexCount];
  755. if (SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, indices, &indexCount)))
  756. {
  757. for (size_t index = 0;index != indexCount;index++)
  758. {
  759. WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
  760. WORD lang = 0;
  761. DWORD length = 0;
  762. wchar_t _attrName[128] = {0};
  763. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
  764. {
  765. AutoByte v(length);
  766. BYTE *value = v.data;
  767. if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
  768. {
  769. WM_PICTURE *picture = (WM_PICTURE *)value;
  770. if (picture->bPictureType == pictype)
  771. {
  772. header3->DeleteAttribute(0, indices[index]);
  773. delete[] indices;
  774. return true;
  775. }
  776. }
  777. }
  778. }
  779. }
  780. delete[] indices;
  781. }
  782. return false;
  783. }