Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1026 lines
30 KiB

  1. /*****************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 2000
  4. *
  5. * TITLE: xmltools.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: LazarI
  10. *
  11. * DGetATE: 10/18/00
  12. *
  13. * DESCRIPTION: Class which encapsulates XML DOM for implementing
  14. * wizard templates
  15. *
  16. *****************************************************************************/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. /////////////////////////////////
  20. // CPhotoTemplates impl.
  21. // global strings
  22. static const TCHAR gszVersionGUID[] = TEXT("{352A15C4-1D19-4e93-AF92-D939C2812491}");
  23. static const TCHAR gszPatternDefs[] = TEXT("template-def");
  24. static const TCHAR gszPatternLocale[] = TEXT("template-definitions[@measurements = \"%s\"]");
  25. static const TCHAR gszPatternLocaleInd[] = TEXT("template-definitions[@measurements = \"locale-independent\"]");
  26. static const TCHAR gszPatternGUID[] = TEXT("template-def[@guid = \"%s\"]");
  27. static const TCHAR gszGUID[] = TEXT("guid");
  28. static const LPCTSTR arrCommonPropNames[CTemplateInfo::PROP_LAST] =
  29. {
  30. TEXT("guid"),
  31. TEXT("group"),
  32. TEXT("title"),
  33. TEXT("description"),
  34. TEXT("repeat-photos"),
  35. TEXT("use-thumbnails-for-printing"),
  36. TEXT("print-filename"),
  37. TEXT("can-rotate"),
  38. TEXT("can-crop"),
  39. };
  40. /////////////////////////////////////////////////////////////////////////////////////////////////
  41. // utility functions
  42. template <class T>
  43. HRESULT _GetProp(IXMLDOMElement *pElement, LPCTSTR pszName, T &value);
  44. // number convertions
  45. HRESULT _ConvertTo(LPCTSTR pszValue, LONG &lValue);
  46. HRESULT _ConvertTo(LPCTSTR pszValue, double &dValue);
  47. HRESULT _ConvertTo(LPCTSTR pszValue, BOOL &bValue);
  48. // attributes access
  49. HRESULT _GetAttribute(IXMLDOMElement *pElement, LPCTSTR pszAttrName, CComBSTR &bstr);
  50. template <class T>
  51. HRESULT _GetProp(IXMLDOMElement *pElement, LPCTSTR pszName, T &value)
  52. {
  53. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_GetProp: %s"),(pszName ? pszName : TEXT("NULL POINTER!"))));
  54. HRESULT hr = E_FAIL;
  55. CComBSTR bstr;
  56. if( pElement &&
  57. SUCCEEDED(hr = _GetAttribute(pElement, pszName, bstr)) &&
  58. SUCCEEDED(hr = _ConvertTo(bstr, value)) )
  59. {
  60. hr = S_OK;
  61. }
  62. WIA_RETURN_HR(hr);
  63. }
  64. HRESULT _ConvertTo(LPCTSTR pszValue, LONG &lValue)
  65. {
  66. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_ConvertTo(LONG): %s"),(pszValue ? pszValue : TEXT("NULL POINTER!"))));
  67. HRESULT hr = E_INVALIDARG;
  68. if( pszValue )
  69. {
  70. hr = S_OK;
  71. TCHAR *endptr = NULL;
  72. lValue = _tcstol(pszValue, &endptr, 10);
  73. if( ERANGE == errno || *endptr )
  74. {
  75. // conversion failed
  76. lValue = 0;
  77. hr = E_FAIL;
  78. }
  79. }
  80. WIA_RETURN_HR(hr);
  81. }
  82. HRESULT _ConvertTo(LPCTSTR pszValue, double &dValue)
  83. {
  84. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_ConvertTo(double): %s"),(pszValue ? pszValue : TEXT("NULL POINTER!"))));
  85. HRESULT hr = E_INVALIDARG;
  86. if( pszValue )
  87. {
  88. hr = S_OK;
  89. TCHAR *endptr = NULL;
  90. dValue = _tcstod(pszValue, &endptr);
  91. if( ERANGE == errno || *endptr )
  92. {
  93. // conversion failed
  94. dValue = 0.0;
  95. hr = E_FAIL;
  96. }
  97. }
  98. WIA_RETURN_HR(hr);
  99. }
  100. HRESULT _ConvertTo(LPCTSTR pszValue, BOOL &bValue)
  101. {
  102. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_ConvertTo(bool): %s"),(pszValue ? pszValue : TEXT("NULL POINTER!"))));
  103. HRESULT hr = E_INVALIDARG;
  104. if( pszValue )
  105. {
  106. hr = S_OK;
  107. // check for true first
  108. if( 0 == lstrcmp(pszValue, TEXT("yes")) ||
  109. 0 == lstrcmp(pszValue, TEXT("on")) )
  110. {
  111. bValue = true;
  112. }
  113. else
  114. {
  115. // check for false next
  116. if( 0 == lstrcmp(pszValue, TEXT("no")) ||
  117. 0 == lstrcmp(pszValue, TEXT("off")) )
  118. {
  119. bValue = false;
  120. }
  121. else
  122. {
  123. // not a boolean
  124. hr = E_FAIL;
  125. }
  126. }
  127. }
  128. WIA_RETURN_HR(hr);
  129. }
  130. HRESULT _GetAttribute(IXMLDOMElement *pElement, LPCTSTR pszAttrName, CComBSTR &bstr)
  131. {
  132. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_GetAttribute(BSTR): %s"),(pszAttrName ? pszAttrName : TEXT("NULL POINTER!"))));
  133. HRESULT hr = E_INVALIDARG;
  134. CComVariant strAttr;
  135. if( pElement && pszAttrName &&
  136. SUCCEEDED(hr = pElement->getAttribute(CComBSTR(pszAttrName), &strAttr)) )
  137. {
  138. if( VT_BSTR == strAttr.vt )
  139. {
  140. bstr = strAttr.bstrVal;
  141. hr = S_OK;
  142. }
  143. else
  144. {
  145. hr = E_FAIL;
  146. }
  147. }
  148. WIA_RETURN_HR(hr);
  149. }
  150. HRESULT _GetChildElement(IXMLDOMElement *pElement, LPCTSTR pszName, IXMLDOMElement **ppChild)
  151. {
  152. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_GetChildElement( %s )"),(pszName ? pszName : TEXT("NULL POINTER!"))));
  153. HRESULT hr = E_INVALIDARG;
  154. if( pElement && pszName && ppChild )
  155. {
  156. CComPtr<IXMLDOMNode> pNode;
  157. if( SUCCEEDED(hr = pElement->selectSingleNode(CComBSTR(pszName), &pNode)) && pNode)
  158. {
  159. //
  160. // query for IXMLDOMElement interface
  161. //
  162. hr = pNode->QueryInterface(IID_IXMLDOMElement, (void **)ppChild);
  163. }
  164. }
  165. WIA_RETURN_HR(hr);
  166. }
  167. /////////////////////////////////////////////////////////////////////////////////////////////////
  168. // construction/destruction
  169. CPhotoTemplates::CPhotoTemplates():
  170. _Measure(MEASURE_UNKNOWN)
  171. {
  172. }
  173. INT MyTemplateDestroyCallback( LPVOID pItem, LPVOID lpData )
  174. {
  175. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("MyTemplateDestroyCallback( 0x%x, 0x%x )"),pItem,lpData));
  176. if (pItem)
  177. {
  178. delete (CTemplateInfo *)pItem;
  179. }
  180. return TRUE;
  181. }
  182. CPhotoTemplates::~CPhotoTemplates()
  183. {
  184. CAutoCriticalSection lock(_csList);
  185. DPA_DestroyCallback( _hdpaTemplates, MyTemplateDestroyCallback, NULL );
  186. _hdpaTemplates = NULL;
  187. }
  188. HRESULT CPhotoTemplates::AddTemplates(LPCTSTR pLocale)
  189. {
  190. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::AddTemplates( %s )"),pLocale));
  191. HRESULT hr = E_INVALIDARG;
  192. CComPtr<IXMLDOMNodeList> pTemplates;
  193. CComPtr<IXMLDOMNode> pLocaleNode;
  194. CComBSTR bstrGUID;
  195. //
  196. // Initialize things as needed
  197. //
  198. if (!pLocale || !_pRoot)
  199. {
  200. return hr;
  201. }
  202. CAutoCriticalSection lock(_csList);
  203. //
  204. // Select the correct locale node in the XML document
  205. //
  206. if (_pRoot)
  207. {
  208. hr = _pRoot->selectSingleNode( CComBSTR(pLocale), &pLocaleNode );
  209. WIA_CHECK_HR(hr,"AddTempaltes: _pRoot->selectSingleNode()");
  210. if (SUCCEEDED(hr) && pLocaleNode)
  211. {
  212. //
  213. // Select the templates sub-node
  214. //
  215. hr = pLocaleNode->selectNodes(CComBSTR(gszPatternDefs), &pTemplates);
  216. WIA_CHECK_HR(hr,"AddTemplates: pLocalNode->selectNodes( )");
  217. if (SUCCEEDED(hr) && pTemplates)
  218. {
  219. //
  220. // update the GUIDs of each template to be uppercase, so we can query later
  221. //
  222. GUID guid;
  223. TCHAR szGUID[128];
  224. LONG lCount = 0;
  225. hr = pTemplates->get_length(&lCount);
  226. WIA_CHECK_HR(hr,"AddTemplates: pTemplates->get_length(&lCount)");
  227. if (SUCCEEDED(hr) && lCount)
  228. {
  229. //
  230. // Loop through all the template and add them to the
  231. // the array of templates...
  232. //
  233. WIA_TRACE((TEXT("AddTemplates: loaded section, adding %d templates.."),lCount));
  234. for( LONG l = 0; SUCCEEDED(hr) && (l < lCount); l++ )
  235. {
  236. //
  237. // Get the actual XML item for the template...
  238. //
  239. CComPtr<IXMLDOMNode> pNode;
  240. hr = pTemplates->get_item(l, &pNode);
  241. WIA_CHECK_HR(hr,"LoadTemplate: pTemplates->get_item( lRelativeIndex )");
  242. if (SUCCEEDED(hr) && pNode)
  243. {
  244. //
  245. // query IXMLDOMElement interface
  246. //
  247. CComPtr<IXMLDOMElement> pTheTemplate;
  248. hr = pNode->QueryInterface(IID_IXMLDOMElement, (void **)&pTheTemplate);
  249. if (SUCCEEDED(hr) && pTheTemplate)
  250. {
  251. //
  252. // Create template for this item...
  253. //
  254. CTemplateInfo * pTemplateInfo = (CTemplateInfo *) new CTemplateInfo( pTheTemplate );
  255. if (pTemplateInfo)
  256. {
  257. INT iRes = -1;
  258. if (_hdpaTemplates)
  259. {
  260. iRes = DPA_AppendPtr( _hdpaTemplates, (LPVOID)pTemplateInfo );
  261. }
  262. if (iRes == -1)
  263. {
  264. //
  265. // The item was not added to the DPA, delete it...
  266. //
  267. delete pTemplateInfo;
  268. hr = E_FAIL;
  269. }
  270. }
  271. }
  272. }
  273. }
  274. }
  275. pTemplates = NULL;
  276. }
  277. pLocaleNode = NULL;
  278. }
  279. }
  280. WIA_RETURN_HR(hr);
  281. }
  282. // public interface
  283. HRESULT CPhotoTemplates::Init(IXMLDOMDocument *pDoc)
  284. {
  285. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::Init()")));
  286. HRESULT hr = E_INVALIDARG;
  287. CComBSTR bstrGUID;
  288. LONG lCountCommon = 0;
  289. CAutoCriticalSection lock(_csList);
  290. //
  291. // If the dpa of item isn't initialized, do it now...
  292. //
  293. if (!_hdpaTemplates)
  294. {
  295. _hdpaTemplates = DPA_Create(10);
  296. }
  297. //
  298. // if we're being called twice to initialize, make sure that works...
  299. //
  300. _pRoot = NULL;
  301. //
  302. // get the root element & the version guid
  303. //
  304. if( pDoc &&
  305. SUCCEEDED(hr = pDoc->get_documentElement(&_pRoot)) &&
  306. SUCCEEDED(hr = _GetAttribute(_pRoot, TEXT("guid"), bstrGUID)) )
  307. {
  308. // check the version
  309. if (0==lstrcmp(bstrGUID, gszVersionGUID))
  310. {
  311. //
  312. // Add the local-independent items first
  313. //
  314. hr = AddTemplates( gszPatternLocaleInd );
  315. //
  316. // Add the local-specific templates second
  317. //
  318. hr = _GetLocaleMeasurements( &_Measure );
  319. if (SUCCEEDED(hr))
  320. {
  321. TCHAR szLocale[MAX_PATH];
  322. *szLocale = 0;
  323. hr = _BuildLocaleQueryString(_Measure, szLocale, MAX_PATH);
  324. if (SUCCEEDED(hr))
  325. {
  326. hr = AddTemplates( szLocale );
  327. }
  328. }
  329. }
  330. }
  331. WIA_RETURN_HR(hr);
  332. }
  333. HRESULT CPhotoTemplates::InitForPrintTo()
  334. {
  335. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::Init()")));
  336. HRESULT hr = S_OK;
  337. //
  338. // Our job here is simple -- create 1 template that is the equivalent
  339. // of full page. Don't need any icons, etc., just the dimensions
  340. // and properties...
  341. //
  342. _hdpaTemplates = DPA_Create(1);
  343. if (_hdpaTemplates)
  344. {
  345. CTemplateInfo * pTemplateInfo = (CTemplateInfo *) new CTemplateInfo( );
  346. if (pTemplateInfo)
  347. {
  348. INT iRes = DPA_AppendPtr( _hdpaTemplates, (LPVOID)pTemplateInfo );
  349. if (iRes == -1)
  350. {
  351. //
  352. // The item was not added to the DPA, delete it...
  353. //
  354. delete pTemplateInfo;
  355. hr = E_FAIL;
  356. }
  357. }
  358. }
  359. WIA_RETURN_HR(hr);
  360. }
  361. LONG CPhotoTemplates::Count()
  362. {
  363. LONG lCount = 0;
  364. CAutoCriticalSection lock(_csList);
  365. if (_hdpaTemplates)
  366. {
  367. lCount = (LONG)DPA_GetPtrCount( _hdpaTemplates );
  368. }
  369. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::Count( returning count as %d )"),lCount));
  370. return lCount;
  371. }
  372. HRESULT CPhotoTemplates::_GetLocaleMeasurements(int *pMeasurements)
  373. {
  374. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::_GetLocalMeasurements()")));
  375. TCHAR szMeasure[5];
  376. if( GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, szMeasure, ARRAYSIZE(szMeasure)) )
  377. {
  378. *pMeasurements = (TEXT('0') == szMeasure[0] ? MEASURE_METRIC : MEASURE_US);
  379. return S_OK;
  380. }
  381. WIA_ERROR((TEXT("GetLocaleInfo failed w/GLE = %d"),GetLastError()));
  382. return E_FAIL;
  383. }
  384. HRESULT CPhotoTemplates::_BuildLocaleQueryString(int Measure, LPTSTR pStr, UINT cch)
  385. {
  386. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::_BuildLocaleQueryString()")));
  387. TCHAR szPatternString[255];
  388. HRESULT hr = E_INVALIDARG;
  389. LPCTSTR pszMeasure = MEASURE_METRIC == Measure ? TEXT("cm") :
  390. MEASURE_US == Measure ? TEXT("in") : NULL;
  391. WIA_TRACE((TEXT("pszMeasure = %s"),pszMeasure));
  392. // build simple XSL pattern query string based on the current locale measurements
  393. if( pszMeasure && -1 != wnsprintf(szPatternString, ARRAYSIZE(szPatternString), gszPatternLocale, pszMeasure) )
  394. {
  395. if (pStr && cch >= (UINT)(lstrlen(szPatternString)+1))
  396. {
  397. lstrcpy(pStr,szPatternString);
  398. hr = S_OK;
  399. }
  400. else
  401. {
  402. hr = E_INVALIDARG;
  403. }
  404. }
  405. else
  406. {
  407. hr = E_FAIL;
  408. }
  409. WIA_RETURN_HR(hr);
  410. }
  411. HRESULT CPhotoTemplates::_BuildGUIDQueryString(const GUID &guid, CComBSTR &bstr)
  412. {
  413. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::_BuildGUIDQueryString()")));
  414. TCHAR szGUID[128];
  415. HRESULT hr = StringFromGUID2(guid, szGUID, ARRAYSIZE(szGUID));
  416. if( SUCCEEDED(hr) )
  417. {
  418. TCHAR szPatternString[255];
  419. if( -1 != wnsprintf(szPatternString, ARRAYSIZE(szPatternString), gszPatternGUID, szGUID) )
  420. {
  421. bstr = szPatternString;
  422. hr = bstr ? S_OK : E_OUTOFMEMORY;
  423. }
  424. else
  425. {
  426. hr = E_FAIL;
  427. }
  428. }
  429. WIA_RETURN_HR(hr);
  430. }
  431. HRESULT CPhotoTemplates::GetTemplate(INT iIndex, CTemplateInfo ** ppTemplateInfo)
  432. {
  433. WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::GetTemplate()")));
  434. HRESULT hr = E_INVALIDARG;
  435. CAutoCriticalSection lock(_csList);
  436. if( ppTemplateInfo )
  437. {
  438. if ( _hdpaTemplates )
  439. {
  440. if (iIndex < DPA_GetPtrCount( _hdpaTemplates ))
  441. {
  442. //
  443. // Note: it's only okay to hand out pointers here because
  444. // we know that wizblob.cpp doesn't delete the CPhotoTemplates
  445. // class until all the background threads have exited, etc.
  446. //
  447. *ppTemplateInfo = (CTemplateInfo *) DPA_FastGetPtr( _hdpaTemplates, iIndex );
  448. hr = S_OK;
  449. }
  450. }
  451. else
  452. {
  453. hr = E_FAIL;
  454. }
  455. }
  456. WIA_RETURN_HR(hr);
  457. }
  458. // creates full page template info
  459. CTemplateInfo::CTemplateInfo()
  460. : _bRepeatPhotos(FALSE),
  461. _bUseThumbnailsToPrint(FALSE),
  462. _bPrintFilename(FALSE),
  463. _bCanRotate(TRUE),
  464. _bCanCrop(FALSE),
  465. _bPortrait(TRUE),
  466. _pStream(NULL)
  467. {
  468. //
  469. // Set imageable area
  470. //
  471. _rcImageableArea.left = -1;
  472. _rcImageableArea.top = -1;
  473. _rcImageableArea.right = -1;
  474. _rcImageableArea.bottom = -1;
  475. //
  476. // Set 1 item, takes up all of imageable area
  477. //
  478. RECT rcItem;
  479. rcItem.left = -1;
  480. rcItem.top = -1;
  481. rcItem.right = -1;
  482. rcItem.bottom = -1;
  483. _arrLayout.Append( rcItem );
  484. _strTitle.LoadString( IDS_FULL_PAGE_TITLE, g_hInst );
  485. _strDescription.LoadString( IDS_FULL_PAGE_DESC, g_hInst );
  486. }
  487. CTemplateInfo::CTemplateInfo( IXMLDOMElement * pTheTemplate )
  488. : _bRepeatPhotos(FALSE),
  489. _bUseThumbnailsToPrint(FALSE),
  490. _bPrintFilename(FALSE),
  491. _bCanRotate(FALSE),
  492. _bCanCrop(FALSE),
  493. _bPortrait(TRUE),
  494. _pStream(NULL)
  495. {
  496. HRESULT hr;
  497. if (pTheTemplate)
  498. {
  499. //
  500. // Make sure backing COM object doesn't go away on us...
  501. //
  502. pTheTemplate->AddRef();
  503. //
  504. // Get all the properties so we can construct an
  505. // initialized template for our list...
  506. //
  507. CComBSTR bstrGroup;
  508. CComBSTR bstrTitle;
  509. CComBSTR bstrDescription;
  510. hr = _GetAttribute( pTheTemplate, arrCommonPropNames[PROP_GROUP], bstrGroup );
  511. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_GROUP property");
  512. if (SUCCEEDED(hr))
  513. {
  514. _strGroup.Assign( CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrGroup)) );
  515. }
  516. hr = _GetAttribute( pTheTemplate, arrCommonPropNames[PROP_TITLE], bstrTitle );
  517. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_TITLE property");
  518. if (SUCCEEDED(hr))
  519. {
  520. _strTitle.Assign( CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrTitle)) );
  521. }
  522. hr = _GetAttribute( pTheTemplate, arrCommonPropNames[PROP_DESCRIPTION], bstrDescription );
  523. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_DESCRIPTION property");
  524. if (SUCCEEDED(hr))
  525. {
  526. _strDescription.Assign( CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrDescription)) );
  527. }
  528. hr = _GetProp<BOOL>( pTheTemplate, arrCommonPropNames[PROP_REPEAT_PHOTOS], _bRepeatPhotos );
  529. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_REPEAT_PHOTOS property");
  530. hr = _GetProp<BOOL>( pTheTemplate, arrCommonPropNames[PROP_USE_THUMBNAILS_TO_PRINT], _bUseThumbnailsToPrint );
  531. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_USE_THUMBNAILS_TO_PRINT property");
  532. hr = _GetProp<BOOL>( pTheTemplate, arrCommonPropNames[PROP_PRINT_FILENAME], _bPrintFilename );
  533. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_USE_THUMBNAILS_TO_PRINT property");
  534. hr = _GetProp<BOOL>( pTheTemplate, arrCommonPropNames[PROP_CAN_ROTATE], _bCanRotate );
  535. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_CAN_ROTATE property");
  536. hr = _GetProp<BOOL>( pTheTemplate, arrCommonPropNames[PROP_CAN_CROP], _bCanCrop );
  537. WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_CAN_CROP property");
  538. //
  539. // Get IStream to template preview (icon)
  540. //
  541. CComPtr<IXMLDOMElement> pImageInfo;
  542. hr = _GetChildElement(pTheTemplate, TEXT("preview-image"), &pImageInfo);
  543. WIA_CHECK_HR(hr,"_GetChildElement( preview-image ) failed");
  544. if( SUCCEEDED(hr) && pImageInfo )
  545. {
  546. CComBSTR bstrAttr;
  547. hr = _GetAttribute(pImageInfo, TEXT("url"), bstrAttr);
  548. if(SUCCEEDED(hr))
  549. {
  550. //
  551. // URL is provided - this overrides everything else
  552. //
  553. hr = CreateStreamFromURL(bstrAttr, &_pStream);
  554. WIA_CHECK_HR(hr,"CreateStreamFromURL failed!");
  555. }
  556. else
  557. {
  558. //
  559. // try getting resource info (module + resource name)
  560. //
  561. hr = _GetAttribute(pImageInfo, TEXT("res-name"), bstrAttr);
  562. if(SUCCEEDED(hr))
  563. {
  564. CComBSTR bstrModule, bstrType;
  565. LPCTSTR pszModule = SUCCEEDED(_GetAttribute(pImageInfo, TEXT("res-module"), bstrModule)) ? bstrModule : NULL;
  566. LPCTSTR pszType = SUCCEEDED(_GetAttribute(pImageInfo, TEXT("res-type"), bstrType)) ? bstrType : TEXT("HTML");
  567. //
  568. // filter out some of the standard resource types
  569. //
  570. pszType = (0 == lstrcmp(pszType, TEXT("HTML"))) ? RT_HTML :
  571. (0 == lstrcmp(pszType, TEXT("ICON"))) ? RT_ICON :
  572. (0 == lstrcmp(pszType, TEXT("BITMAP"))) ? RT_BITMAP : pszType;
  573. //
  574. // just create a memory stream on the specified resource
  575. //
  576. hr = CreateStreamFromResource(pszModule, pszType, bstrAttr, &_pStream);
  577. WIA_CHECK_HR(hr, "CreateStreamFromResource() failed");
  578. }
  579. }
  580. }
  581. //
  582. // Get the layout info for this template...
  583. //
  584. CComPtr<IXMLDOMElement> pLayoutInfo;
  585. hr = _GetChildElement( pTheTemplate, TEXT("layout"), &pLayoutInfo );
  586. WIA_CHECK_HR(hr,"_GetChildElement( layout ) failed");
  587. if (SUCCEEDED(hr) && pLayoutInfo)
  588. {
  589. //
  590. // Get imageable area for template...
  591. //
  592. CComPtr<IXMLDOMElement> pImageableArea;
  593. hr = _GetChildElement( pLayoutInfo, TEXT("imageable-area"), &pImageableArea );
  594. WIA_CHECK_HR(hr,"_GetChildElement( imageable-area ) failed");
  595. if (SUCCEEDED(hr) && pImageableArea)
  596. {
  597. ZeroMemory( &_rcImageableArea, sizeof(RECT) );
  598. hr = _GetProp<LONG>(pImageableArea, TEXT("x"), _rcImageableArea.left);
  599. WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.left ) failed");
  600. hr = _GetProp<LONG>(pImageableArea, TEXT("y"), _rcImageableArea.top);
  601. WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.top ) failed");
  602. hr = _GetProp<LONG>(pImageableArea, TEXT("w"), _rcImageableArea.right);
  603. WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.right ) failed");
  604. hr = _GetProp<LONG>(pImageableArea, TEXT("h"), _rcImageableArea.bottom);
  605. WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.bottom ) failed");
  606. //
  607. // Check for special case of all -1's, which
  608. // means to scale to full size of printable
  609. // area...
  610. //
  611. WIA_TRACE((TEXT("_rcImageableArea was read as (%d by %d) at (%d,%d)"),_rcImageableArea.right,_rcImageableArea.bottom,_rcImageableArea.left,_rcImageableArea.top));
  612. if ((-1 != _rcImageableArea.left) ||
  613. (-1 != _rcImageableArea.top) ||
  614. (-1 != _rcImageableArea.right) ||
  615. (-1 != _rcImageableArea.bottom))
  616. {
  617. //
  618. // convert w, h to right & bootom
  619. //
  620. _rcImageableArea.right += _rcImageableArea.left;
  621. _rcImageableArea.bottom += _rcImageableArea.top;
  622. }
  623. }
  624. //
  625. // Get individual item rectangles for this template...
  626. //
  627. CComPtr<IXMLDOMNodeList> pListLayout;
  628. hr = pLayoutInfo->selectNodes(TEXT("image-def"), &pListLayout);
  629. WIA_CHECK_HR(hr,"pLayoutInfo->selectNodes( image-def ) failed");
  630. if (SUCCEEDED(hr) && pListLayout)
  631. {
  632. LONG length = 0;
  633. hr = pListLayout->get_length(&length);
  634. WIA_CHECK_HR(hr,"pListLayout->get_length() failed");
  635. if (SUCCEEDED(hr))
  636. {
  637. if (length)
  638. {
  639. RECT rc;
  640. for( long l = 0; l < length; l++ )
  641. {
  642. CComPtr<IXMLDOMNode> pNode;
  643. CComPtr<IXMLDOMElement> pItem;
  644. hr = pListLayout->get_item(l, &pNode);
  645. WIA_CHECK_HR(hr,"pListLayout->get_item() failed");
  646. if (SUCCEEDED(hr) && pNode)
  647. {
  648. hr = pNode->QueryInterface(IID_IXMLDOMElement, (void **)&pItem);
  649. WIA_CHECK_HR(hr,"pNode->QI( item XMLDOMElement )");
  650. if (SUCCEEDED(hr) && pItem)
  651. {
  652. ZeroMemory( &rc, sizeof(rc) );
  653. hr = _GetProp<LONG>(pItem, TEXT("x"), rc.left);
  654. WIA_CHECK_HR(hr,"_GetProp( item x ) failed");
  655. hr = _GetProp<LONG>(pItem, TEXT("y"), rc.top);
  656. WIA_CHECK_HR(hr,"_GetProp( item y ) failed");
  657. hr = _GetProp<LONG>(pItem, TEXT("w"), rc.right);
  658. WIA_CHECK_HR(hr,"_GetProp( item w ) failed");
  659. hr = _GetProp<LONG>(pItem, TEXT("h"), rc.bottom);
  660. WIA_CHECK_HR(hr,"_GetProp( item h ) failed");
  661. //
  662. // Check for special case of all -1's, which
  663. // means to scale to full size of printable
  664. // area...
  665. //
  666. if ((-1 != rc.left) ||
  667. (-1 != rc.top) ||
  668. (-1 != rc.right) ||
  669. (-1 != rc.bottom))
  670. {
  671. // convert w, h to right & bootom
  672. rc.right += rc.left;
  673. rc.bottom += rc.top;
  674. }
  675. //
  676. // insert the image definition
  677. //
  678. if (-1 == _arrLayout.Append( rc ))
  679. {
  680. WIA_ERROR((TEXT("Error adding item rectangle to list")));
  681. }
  682. }
  683. }
  684. }
  685. }
  686. else
  687. {
  688. WIA_ERROR((TEXT("pListLayout->get_length() returned 0 length!")));
  689. }
  690. }
  691. }
  692. }
  693. //
  694. // Let go of backing COM object...
  695. //
  696. pTheTemplate->Release();
  697. }
  698. }
  699. CTemplateInfo::~CTemplateInfo()
  700. {
  701. if (_pStream)
  702. {
  703. _pStream->Release();
  704. _pStream = NULL;
  705. }
  706. }
  707. static void RotateHelper(RECT * pRect, int nNewImageWidth, int nNewImageHeight, BOOL bClockwise)
  708. {
  709. //
  710. // If we don't have a valid pointer, or all the coords are -1, then bail.
  711. // The -1 case denotes use all the area, and we don't want to muck with
  712. // that...
  713. //
  714. if (!pRect || ((pRect->left==-1) && (pRect->top==-1) && (pRect->right==-1) && (pRect->bottom==-1)))
  715. {
  716. return;
  717. }
  718. WIA_PUSH_FUNCTION_MASK((TRACE_TEMPLATE,TEXT("RotateHelper( pRect(%d,%d,%d,%d) nNewImageWidth=%d nImageHeight=%d bClockwise=%d )"),pRect->left,pRect->top,pRect->right,pRect->bottom,nNewImageWidth,nNewImageHeight,bClockwise));
  719. //
  720. // The incoming data is going to be 2 points -- first is the upper left
  721. // coord of the original rectangle. The second represents the
  722. // the width and the height. The first coord needs to be rotated
  723. // 90 degrees, and then put back to the upper left of the rectangle.
  724. //
  725. //
  726. // The width and the height need to be flipped.
  727. //
  728. int nNewItemWidth = pRect->bottom - pRect->top;
  729. int nNewItemHeight = pRect->right - pRect->left;
  730. int nNewX, nNewY;
  731. if (bClockwise)
  732. {
  733. nNewX = nNewImageWidth - pRect->bottom;
  734. nNewY = pRect->left;
  735. }
  736. else
  737. {
  738. nNewX = pRect->top;
  739. nNewY = nNewImageHeight - pRect->right;
  740. }
  741. pRect->left = nNewX;
  742. pRect->top = nNewY;
  743. pRect->right = nNewX + nNewItemWidth;
  744. pRect->bottom = nNewY + nNewItemHeight;
  745. WIA_TRACE((TEXT("On Exit: pRect(%d,%d,%d,%d)"),pRect->left,pRect->top,pRect->right,pRect->bottom));
  746. }
  747. HRESULT CTemplateInfo::RotateForLandscape()
  748. {
  749. HRESULT hr = S_OK;
  750. WIA_PUSH_FUNCTION_MASK((TRACE_TEMPLATE,TEXT("CTemplateInfo::RotateForLandscape()")));
  751. CAutoCriticalSection lock(_cs);
  752. if (_bPortrait)
  753. {
  754. //
  755. // We only want to change this if it's a defined rect
  756. // (i.e, not "use all area")
  757. //
  758. if ((_rcImageableArea.left != -1) &&
  759. (_rcImageableArea.top != -1) &&
  760. (_rcImageableArea.right != -1) &&
  761. (_rcImageableArea.bottom != -1))
  762. {
  763. //
  764. // The imageable area will just be a flip of width & height.
  765. // this relies on the fact the imageable area is always
  766. // described in terms of width & height (i.e., top & left
  767. // are always 0 in the RECT structure).
  768. //
  769. LONG oldWidth = _rcImageableArea.right;
  770. _rcImageableArea.right = _rcImageableArea.bottom;
  771. _rcImageableArea.bottom = oldWidth;
  772. }
  773. //
  774. // Now, map all the points for each item in the layout...
  775. //
  776. RECT * pRect;
  777. for (INT i=0; i < _arrLayout.Count(); i++)
  778. {
  779. pRect = &_arrLayout[i];
  780. RotateHelper( pRect, _rcImageableArea.right, _rcImageableArea.bottom, FALSE );
  781. }
  782. _bPortrait = FALSE;
  783. }
  784. else
  785. {
  786. WIA_TRACE((TEXT("Already in landscape mode, doing nothing...")));
  787. }
  788. WIA_RETURN_HR(hr);
  789. }
  790. HRESULT CTemplateInfo::RotateForPortrait()
  791. {
  792. HRESULT hr = S_OK;
  793. WIA_PUSH_FUNCTION_MASK((TRACE_TEMPLATE,TEXT("CTemplateInfo::RotateForPortrait()")));
  794. CAutoCriticalSection lock(_cs);
  795. if (!_bPortrait)
  796. {
  797. //
  798. // The imageable area will just be a flip of width & height.
  799. // this relies on the fact the imageable area is always
  800. // described in terms of width & height (i.e., top & left
  801. // are always 0 in the RECT structure).
  802. //
  803. LONG oldWidth = _rcImageableArea.right;
  804. _rcImageableArea.right = _rcImageableArea.bottom;
  805. _rcImageableArea.bottom = oldWidth;
  806. //
  807. // Now, map all the points for each item in the layout...
  808. //
  809. RECT * pRect;
  810. for (INT i=0; i < _arrLayout.Count(); i++)
  811. {
  812. pRect = &_arrLayout[i];
  813. RotateHelper( pRect, _rcImageableArea.right, _rcImageableArea.bottom, TRUE );
  814. }
  815. _bPortrait = TRUE;
  816. }
  817. else
  818. {
  819. WIA_TRACE((TEXT("Already in portrait mode, doing nothing...")));
  820. }
  821. WIA_RETURN_HR(hr);
  822. }