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.

1077 lines
32 KiB

  1. #include "precomp.h"
  2. //
  3. // This table translates a given TWTY code to it corresponding
  4. // size in bytes. The table is indexed by TWTY code.
  5. //
  6. const TW_UINT16 TWTY_STRFIRST = TWTY_STR32;
  7. const TW_UINT16 TWTY_STRLAST = TWTY_STR255;
  8. const TW_UINT32 LAST_ITEMTYPE = TWTY_STR255;
  9. const TW_UINT32 g_ItemSizeTable[LAST_ITEMTYPE + 1] =
  10. {
  11. sizeof(TW_INT8),
  12. sizeof(TW_INT16),
  13. sizeof(TW_INT32),
  14. sizeof(TW_UINT8),
  15. sizeof(TW_UINT16),
  16. sizeof(TW_UINT32),
  17. sizeof(TW_BOOL),
  18. sizeof(TW_FIX32),
  19. sizeof(TW_FRAME),
  20. sizeof(TW_STR32),
  21. sizeof(TW_STR64),
  22. sizeof(TW_STR128),
  23. sizeof(TW_STR255),
  24. };
  25. //
  26. // TWAIN capabilty class implemenation
  27. //
  28. TW_UINT16 CCap::ICap(PCAPDATA pCapData)
  29. {
  30. if (!pCapData || pCapData->ItemType > LAST_ITEMTYPE)
  31. return TWCC_BADVALUE;
  32. m_ItemSize = g_ItemSizeTable[pCapData->ItemType];
  33. if (m_ItemSize != pCapData->ItemSize)
  34. return TWCC_BADVALUE;
  35. //
  36. // StrData only applies to TW_STRxxx
  37. //
  38. if (pCapData->pStrData &&
  39. (pCapData->ItemSize < sizeof(TW_STR32) ||
  40. pCapData->ItemType < TWTY_STRFIRST ||
  41. pCapData->ItemType > TWTY_STRLAST)) {
  42. return TWCC_BADVALUE;
  43. }
  44. //
  45. // Itemlist only applies to TWON_ENUMERATION
  46. //
  47. if (pCapData->ItemList && TWON_ENUMERATION != pCapData->ConType)
  48. return TWCC_BADVALUE;
  49. m_ItemType = pCapData->ItemType;
  50. m_CapId = pCapData->CapId;
  51. m_ConType = pCapData->ConType;
  52. m_StepSize = pCapData->StepSize;
  53. m_CurrentValue = pCapData->Current;
  54. m_DefaultValue = pCapData->Default;
  55. m_BaseMinValue = m_CurMinValue = pCapData->MinValue;
  56. m_BaseMaxValue = m_CurMaxValue = pCapData->MaxValue;
  57. m_StepSize = pCapData->StepSize;
  58. m_CurNumItems = 0;
  59. m_ItemList = NULL;
  60. if (pCapData->pStrData && TWON_ONEVALUE == pCapData->ConType) {
  61. // string data
  62. return Set(pCapData->ItemSize, (BYTE*)pCapData->pStrData);
  63. }
  64. if (TWON_ENUMERATION == pCapData->ConType) {
  65. return Set(pCapData->Default, pCapData->Current,
  66. pCapData->MaxValue - pCapData->MinValue + 1,
  67. (BYTE *)pCapData->ItemList
  68. );
  69. }
  70. return TWCC_SUCCESS;
  71. }
  72. TW_UINT16 CCap::Reset()
  73. {
  74. m_CurMinValue = m_BaseMinValue;
  75. m_CurMaxValue = m_BaseMaxValue;
  76. m_CurrentValue = m_DefaultValue;
  77. if (TWON_ENUMERATION == m_ConType) {
  78. if(m_ResetItemList){
  79. ::LocalFree(m_ItemList);
  80. m_ItemList = NULL;
  81. //
  82. // restore original enumeration values
  83. //
  84. m_ItemList = m_ResetItemList;
  85. m_CurNumItems = m_ResetNumItems;
  86. m_CurrentValue = m_ResetCurIndex;
  87. m_DefaultValue = m_ResetDefIndex;
  88. m_BaseMinValue = 0;
  89. m_BaseMaxValue = m_ResetNumItems - 1;
  90. m_CurMinValue = m_BaseMinValue;
  91. m_CurMaxValue = m_BaseMaxValue;
  92. m_CurEnumMask = 0xFFFFFFFF >> (32 - m_ResetNumItems);
  93. m_CurNumItems = m_ResetNumItems;
  94. } else {
  95. //
  96. // re-establish the mask and the count
  97. //
  98. m_CurNumItems = m_BaseMaxValue - m_BaseMinValue + 1;
  99. }
  100. m_CurEnumMask = 0xFFFFFFFF >> (32 - m_CurNumItems);
  101. }
  102. return TWCC_SUCCESS;
  103. }
  104. #ifdef _USE_NONSPRINTF_CONVERSION
  105. float CCap::Fix32ToFloat(TW_FIX32 fix32)
  106. {
  107. float ffloat = 0.0f;
  108. int iexp = 1;
  109. int frac = fix32.Frac;
  110. while(frac/10 > 0){
  111. iexp++;
  112. frac = (frac/10);
  113. }
  114. ffloat = (float)fix32.Whole + (float) ( (float) fix32.Frac / (float) pow(10,iexp));
  115. return ffloat;
  116. }
  117. TW_FIX32 CCap::FloatToFix32(float ffloat)
  118. {
  119. TW_FIX32 fix32;
  120. memset(&fix32,0,sizeof(fix32));
  121. fix32.Whole = (TW_INT16)ffloat;
  122. float fVal = (ffloat - (float)fix32.Whole);
  123. fVal = (fVal * 100000.0f);
  124. fix32.Frac = (TW_UINT16)(fVal);
  125. return fix32;
  126. }
  127. #else // _USE_NONSPRINTF_CONVERSION
  128. TW_FIX32 CCap::FloatToFix32(float f)
  129. {
  130. char fstr[64];
  131. char *p = NULL;
  132. TW_FIX32 f32;
  133. sprintf(fstr, "%f", f);
  134. p = strchr(fstr, '.');
  135. if (p != NULL) {
  136. *p = '\0';
  137. f32.Whole = (TW_INT16)atoi(fstr);
  138. f32.Frac = (TW_UINT16)atoi(p + 1);
  139. }
  140. return f32;
  141. }
  142. float CCap::Fix32ToFloat(TW_FIX32 fix32)
  143. {
  144. return(float)fix32.Whole + (float)(fix32.Frac / 65536.0);
  145. }
  146. #endif // _USE_NONSPRINTF_CONVERSION
  147. TW_UINT32 CCap::ExtractValue(BYTE *pData)
  148. {
  149. TW_UINT32 Value = 0;
  150. if (pData) {
  151. switch (m_ItemType) {
  152. case TWTY_INT8:
  153. Value = *((TW_INT8 *)pData);
  154. break;
  155. case TWTY_UINT8:
  156. Value = *((TW_UINT8 *)pData);
  157. break;
  158. case TWTY_INT16:
  159. Value = *((TW_INT16 *)pData);
  160. break;
  161. case TWTY_UINT16:
  162. Value = *((TW_UINT16 *)pData);
  163. break;
  164. case TWTY_INT32:
  165. Value = *((TW_INT32 *)pData);
  166. break;
  167. case TWTY_UINT32:
  168. Value = *((TW_UINT32 *)pData);
  169. break;
  170. case TWTY_BOOL:
  171. Value = *((TW_BOOL *)pData);
  172. break;
  173. case TWTY_FIX32:
  174. Value = *((TW_UINT32 *)pData);
  175. break;
  176. default:
  177. break;
  178. }
  179. }
  180. return Value;
  181. }
  182. TW_UINT32 CCap::GetCurrent()
  183. {
  184. if (m_ItemSize > sizeof(TW_UINT32))
  185. return 0;
  186. if (TWON_ENUMERATION == m_ConType) {
  187. DBG_TRC(("CCap::GetCurrent(), Extracting %d index from TWON_ENUMERATION",m_CurrentValue));
  188. return ExtractValue(m_ItemList + m_CurrentValue * m_ItemSize);
  189. }
  190. return m_CurrentValue;
  191. }
  192. TW_UINT32 CCap::GetDefault()
  193. {
  194. if (m_ItemSize > sizeof(TW_UINT32))
  195. return 0;
  196. if (TWON_ENUMERATION == m_ConType) {
  197. return ExtractValue(m_ItemList + m_DefaultValue * m_ItemSize);
  198. }
  199. return m_DefaultValue;
  200. }
  201. TW_UINT16 CCap::Set(TW_UINT32 StrDataSize,BYTE *pStrData)
  202. {
  203. if (m_ItemSize != StrDataSize || TWTY_STRFIRST < m_ItemType ||
  204. TWTY_STRLAST < m_ItemType) {
  205. //
  206. // Only apply to string
  207. //
  208. return TWCC_BADVALUE;
  209. }
  210. if (!m_pStrData) {
  211. m_pStrData = new BYTE[StrDataSize];
  212. if (!m_pStrData)
  213. return TWCC_LOWMEMORY;
  214. }
  215. memcpy(m_pStrData, pStrData, StrDataSize);
  216. return TWCC_SUCCESS;
  217. }
  218. TW_UINT16 CCap::Set(TW_UINT32 DefValue,TW_UINT32 CurValue,TW_UINT32 MinValue,
  219. TW_UINT32 MaxValue,TW_UINT32 StepSize)
  220. {
  221. //
  222. // This is for TWON_ONEVALUE or TWON_RANGE container type only
  223. //
  224. if (TWON_ONEVALUE != m_ConType && TWON_RANGE != m_ConType)
  225. return TWCC_BADVALUE;
  226. m_BaseMinValue = m_CurMinValue = MinValue;
  227. m_BaseMaxValue = m_CurMaxValue = MaxValue;
  228. m_StepSize = StepSize;
  229. m_CurrentValue = CurValue;
  230. m_DefaultValue = DefValue;
  231. return TWCC_SUCCESS;
  232. }
  233. TW_UINT16 CCap::Set(TW_UINT32 DefIndex,TW_UINT32 CurIndex,TW_UINT32 NumItems,
  234. BYTE *ItemList,BOOL bForce)
  235. {
  236. //
  237. // Total number of items must be less or equal to 32
  238. // The container type must be TWON_ENUMERATION.
  239. //
  240. if(bForce){
  241. m_ConType = TWON_ENUMERATION;
  242. }
  243. return Set(DefIndex,CurIndex,NumItems,ItemList);
  244. }
  245. TW_UINT16 CCap::Set(TW_UINT32 DefIndex,TW_UINT32 CurIndex,TW_UINT32 NumItems,
  246. BYTE * ItemList)
  247. {
  248. //
  249. // The container type must be TWON_ENUMERATION.
  250. //
  251. if (TWON_ENUMERATION != m_ConType)
  252. return TWCC_BADVALUE;
  253. //
  254. // if we have an existing list, but not a backup
  255. // make a backup..
  256. //
  257. if (m_ItemList) {
  258. //
  259. // make a backup if one does not exist
  260. //
  261. if (NULL == m_ResetItemList) {
  262. //
  263. // save backup list and set current list pointer
  264. // to NULL
  265. //
  266. m_ResetItemList = m_ItemList;
  267. m_ResetDefIndex = DefIndex;
  268. m_ResetCurIndex = CurIndex;
  269. m_ResetNumItems = NumItems;
  270. m_ItemList = NULL;
  271. } else {
  272. ::LocalFree(m_ItemList);
  273. m_ItemList = NULL;
  274. }
  275. }
  276. m_BaseMinValue =
  277. m_BaseMaxValue =
  278. m_CurMinValue =
  279. m_CurMaxValue =
  280. m_DefaultValue =
  281. m_CurrentValue =
  282. m_CurEnumMask = 0;
  283. m_ItemList = NULL;
  284. m_CurNumItems = 0;
  285. if (NumItems && ItemList) {
  286. m_ItemList = (BYTE*)LocalAlloc(LPTR,(NumItems * m_ItemSize));
  287. if (!m_ItemList)
  288. return TWCC_LOWMEMORY;
  289. m_CurrentValue = CurIndex;
  290. m_DefaultValue = DefIndex;
  291. m_BaseMinValue = 0;
  292. m_BaseMaxValue = NumItems - 1;
  293. m_CurMinValue = m_BaseMinValue;
  294. m_CurMaxValue = m_BaseMaxValue;
  295. m_CurEnumMask = 0xFFFFFFFF >> (32 - NumItems);
  296. m_CurNumItems = NumItems;
  297. memcpy(m_ItemList, (BYTE*)ItemList, m_ItemSize * NumItems);
  298. }
  299. return TWCC_SUCCESS;
  300. }
  301. int CCap::CompareValue(TW_UINT32 valThis, TW_UINT32 valThat)
  302. {
  303. //
  304. // When they are equal, they are equal no matter they are signed or not.
  305. //
  306. if (valThis == valThat)
  307. return 0;
  308. switch (m_ItemType) {
  309. case TWTY_INT8:
  310. case TWTY_INT16:
  311. case TWTY_INT32:
  312. //
  313. // Signed.
  314. //
  315. return(TW_INT32)valThis > (TW_INT32)valThat ? 1 : -1;
  316. break;
  317. case TWTY_UINT8:
  318. case TWTY_UINT16:
  319. case TWTY_UINT32:
  320. //
  321. // Unsigned.
  322. //
  323. return valThis > valThat ? 1 : -1;
  324. break;
  325. case TWTY_FIX32:
  326. {
  327. TW_FIX32 fix32This;
  328. TW_FIX32 fix32That;
  329. memcpy(&fix32This, &valThis, sizeof(TW_UINT32));
  330. memcpy(&fix32That, &valThat, sizeof(TW_UINT32));
  331. return Fix32ToFloat(fix32This) > Fix32ToFloat(fix32That) ? 1 : -1;
  332. break;
  333. }
  334. case TWTY_BOOL:
  335. {
  336. //
  337. // eqaul or non-eqaul. Relational comparisons are meaningless
  338. //
  339. // valVal == valAgianst is handled up front.
  340. //
  341. if (valThis && valThat)
  342. return 0;
  343. //
  344. // We know they are non-eqaul but we can not tell which one
  345. // is larger.
  346. //
  347. return -2;
  348. break;
  349. }
  350. default:
  351. return -2;
  352. }
  353. }
  354. TW_UINT32 CCap::GetClosestValue(TW_UINT32 Value)
  355. {
  356. if (TWON_RANGE != m_ConType)
  357. return Value;
  358. TW_UINT32 ClosestValue = Value;
  359. if (TWON_RANGE == m_ConType) {
  360. if (CompareValue(ClosestValue, m_CurMinValue) >= 0 &&
  361. CompareValue(m_CurMaxValue, ClosestValue) >= 0) {
  362. TW_UINT32 AlignedValue;
  363. AlignedValue = m_CurMinValue;
  364. while (CompareValue(m_CurMaxValue, AlignedValue) >= 0) {
  365. if (CompareValue(AlignedValue, ClosestValue) >= 0) {
  366. //
  367. // either the values match or we found
  368. // the closest one
  369. //
  370. ClosestValue = AlignedValue;
  371. break;
  372. }
  373. AlignedValue += m_StepSize;
  374. }
  375. }
  376. }
  377. return ClosestValue;
  378. }
  379. TW_UINT16 CCap::SetCurrent(TW_UINT32 NewValue)
  380. {
  381. TW_UINT16 twCc = TWCC_SUCCESS;
  382. switch (m_ConType) {
  383. case TWON_ONEVALUE:
  384. if(m_ItemType == TWTY_BOOL){
  385. m_CurrentValue = NewValue;
  386. } else {
  387. if (m_CapId == CAP_XFERCOUNT){
  388. //
  389. // since we are dealing with unsigned values, just
  390. // allow the setting for CAP_XFERCOUNT to fall through.
  391. //
  392. m_CurrentValue = NewValue;
  393. } else {
  394. // The value must be between m_CurMinValue and m_CurMaxValue
  395. if (CompareValue(NewValue, m_CurMinValue) >= 0 &&
  396. CompareValue(m_CurMaxValue, NewValue) >= 0) {
  397. //
  398. // The value is okay. Set it
  399. //
  400. m_CurrentValue = NewValue;
  401. } else {
  402. twCc = TWCC_BADVALUE;
  403. }
  404. }
  405. }
  406. break;
  407. case TWON_RANGE:
  408. //
  409. // The value must be between m_CurMinValue and m_CurMaxValue.
  410. //
  411. if (CompareValue(NewValue, m_CurMinValue) >= 0 &&
  412. CompareValue(m_CurMaxValue, NewValue) >= 0) {
  413. m_CurrentValue = GetClosestValue(NewValue);
  414. } else {
  415. twCc = TWCC_BADVALUE;
  416. }
  417. break;
  418. default:
  419. twCc = TWCC_BADVALUE;
  420. break;
  421. }
  422. return twCc;
  423. }
  424. TW_UINT16 CCap::SetCurrent(VOID *pNewValue)
  425. {
  426. if (!pNewValue)
  427. return TWCC_BADVALUE;
  428. TW_UINT16 twCc;
  429. switch (m_ConType) {
  430. case TWON_ONEVALUE:
  431. if (m_ItemSize <= sizeof(TW_UINT32)) {
  432. // simple case, do it the easy way
  433. twCc = SetCurrent(*((TW_UINT32 *)pNewValue));
  434. } else {
  435. // this must be a string
  436. memcpy(m_pStrData, pNewValue, m_ItemSize);
  437. twCc = TWCC_SUCCESS;
  438. }
  439. break;
  440. case TWON_RANGE:
  441. twCc = SetCurrent(*((TW_UINT32 *)pNewValue));
  442. break;
  443. case TWON_ENUMERATION:
  444. {
  445. TW_UINT32 ui32;
  446. TW_UINT32 Mask;
  447. BYTE *ItemList;
  448. //
  449. // Presume guilty
  450. //
  451. twCc = TWCC_BADVALUE;
  452. Mask = m_CurEnumMask >> m_CurMinValue;
  453. //
  454. // Have an alias so that we can save some calculations
  455. //
  456. ItemList = m_ItemList + m_CurMinValue * m_ItemSize;
  457. for (ui32 = m_CurMinValue; ui32 <= m_CurMaxValue; ui32 ++) {
  458. if (Mask & 1) {
  459. //
  460. // This item is one of the possible selections
  461. //
  462. if (!memcmp(ItemList, (BYTE*)pNewValue, m_ItemSize)) {
  463. // The new value is within the selection and is
  464. // one of the selection. We do not find the
  465. // closes value for enumeration. Either they match or
  466. // they do not.
  467. m_CurrentValue = ui32;
  468. twCc = TWCC_SUCCESS;
  469. }
  470. }
  471. //
  472. // Advance the item data pointer
  473. //
  474. Mask >>= 1;
  475. ItemList += m_ItemSize;
  476. }
  477. break;
  478. }
  479. default:
  480. twCc = TWCC_BADVALUE;
  481. }
  482. return twCc;
  483. }
  484. TW_UINT16 CCap::GetOneValue(BOOL bDefault,TW_CAPABILITY *ptwCap)
  485. {
  486. if (!ptwCap)
  487. return TWCC_BADCAP;
  488. TW_UINT32 TheValue;
  489. TheValue = (bDefault) ? m_DefaultValue : m_CurrentValue;
  490. HGLOBAL hContainer;
  491. TW_UINT32 ExtraSize;
  492. ExtraSize = m_ItemSize <= sizeof(TW_UINT32) ? 0 : m_ItemSize;
  493. hContainer = GlobalAlloc(GHND, sizeof(TW_ONEVALUE) + ExtraSize);
  494. if (hContainer) {
  495. TW_ONEVALUE *pOneValue = (TW_ONEVALUE*)GlobalLock(hContainer);
  496. if (pOneValue) {
  497. pOneValue->ItemType = m_ItemType;
  498. ptwCap->ConType = TWON_ONEVALUE;
  499. if (!ExtraSize) {
  500. // simple data
  501. if (TWON_ENUMERATION == m_ConType) {
  502. pOneValue->Item = ExtractValue(m_ItemList + TheValue * m_ItemSize);
  503. } else
  504. pOneValue->Item = TheValue;
  505. } else {
  506. BYTE *pData;
  507. if (m_pStrData) {
  508. pData = m_pStrData;
  509. } else {
  510. // string data in enumeration
  511. pData = m_ItemList + TheValue * m_ItemSize;
  512. }
  513. memcpy(&pOneValue->Item, pData, m_ItemSize);
  514. }
  515. GlobalUnlock(hContainer);
  516. ptwCap->hContainer = hContainer;
  517. return TWCC_SUCCESS;
  518. } else {
  519. GlobalFree(hContainer);
  520. }
  521. }
  522. return TWCC_LOWMEMORY;
  523. }
  524. TW_UINT16 CCap::Get(TW_CAPABILITY *ptwCap)
  525. {
  526. if (!ptwCap)
  527. return TWCC_BADCAP;
  528. HGLOBAL hContainer = NULL;
  529. TW_UINT16 twCc = TWCC_SUCCESS;
  530. TW_RANGE *ptwRange = NULL;
  531. TW_ENUMERATION *ptwEnum = NULL;
  532. ptwCap->ConType = m_ConType;
  533. BYTE *pDst = NULL;
  534. BYTE *pSrc = NULL;
  535. TW_UINT32 Size = 0;
  536. TW_UINT32 Mask = 0;
  537. TW_UINT32 ui32 = 0;
  538. switch (m_ConType) {
  539. case TWON_ONEVALUE:
  540. twCc = GetCurrent(ptwCap);
  541. break;
  542. case TWON_RANGE:
  543. {
  544. hContainer = GlobalAlloc(GHND, sizeof(TW_RANGE));
  545. if (hContainer) {
  546. ptwRange = (TW_RANGE *)GlobalLock(hContainer);
  547. if (ptwRange) {
  548. ptwRange->ItemType = m_ItemType;
  549. ptwRange->MinValue = m_CurMinValue;
  550. ptwRange->MaxValue = m_CurMaxValue;
  551. ptwRange->StepSize = m_StepSize;
  552. ptwRange->DefaultValue = m_DefaultValue;
  553. ptwRange->CurrentValue = m_CurrentValue;
  554. GlobalUnlock(hContainer);
  555. ptwCap->hContainer = hContainer;
  556. twCc = TWCC_SUCCESS;
  557. } else {
  558. //
  559. // Unable to lock the memory.
  560. //
  561. GlobalFree(hContainer);
  562. twCc = TWCC_LOWMEMORY;
  563. }
  564. } else {
  565. //
  566. // Unable to allocate memory for the container
  567. //
  568. twCc = TWCC_LOWMEMORY;
  569. }
  570. break;
  571. }
  572. case TWON_ENUMERATION:
  573. {
  574. Size = sizeof(TW_ENUMERATION) + (m_CurNumItems * m_ItemSize);
  575. hContainer = GlobalAlloc(GHND, Size);
  576. if (hContainer) {
  577. ptwEnum = (TW_ENUMERATION *)GlobalLock(hContainer);
  578. if (ptwEnum) {
  579. ptwEnum->ItemType = m_ItemType;
  580. ptwEnum->NumItems = m_CurNumItems;
  581. ptwEnum->DefaultIndex = m_DefaultValue;
  582. ptwEnum->CurrentIndex = m_CurrentValue;
  583. pDst = &ptwEnum->ItemList[0];
  584. pSrc = m_ItemList + m_CurMinValue * m_ItemSize;
  585. Mask = m_CurEnumMask >> m_CurMinValue;
  586. for (ui32 = m_CurMinValue; ui32 <= m_CurMaxValue; ui32++) {
  587. if (Mask & 1) {
  588. //
  589. // got one to return. Copy it to the
  590. // returning buffer
  591. memcpy(pDst, pSrc, m_ItemSize);
  592. pDst += m_ItemSize;
  593. }
  594. pSrc += m_ItemSize;
  595. Mask >>= 1;
  596. }
  597. GlobalUnlock(ptwEnum);
  598. ptwCap->hContainer = hContainer;
  599. twCc = TWCC_SUCCESS;
  600. } else {
  601. twCc = TWCC_LOWMEMORY;
  602. GlobalFree(hContainer);
  603. }
  604. } else {
  605. twCc = TWCC_LOWMEMORY;
  606. }
  607. break;
  608. }
  609. default:
  610. twCc = TWCC_BADVALUE;
  611. break;
  612. }
  613. return twCc;
  614. }
  615. TW_UINT16 CCap::Set(TW_CAPABILITY *ptwCap)
  616. {
  617. if ((!ptwCap)||(NULL == ptwCap->hContainer)||(INVALID_HANDLE_VALUE == ptwCap->hContainer))
  618. return TWCC_BADCAP;
  619. TW_UINT16 twCc = TWCC_SUCCESS;
  620. TW_ONEVALUE *pOneValue = NULL;
  621. TW_RANGE *pRange = NULL;
  622. TW_ENUMERATION *ptwEnum = NULL;
  623. switch (ptwCap->ConType) {
  624. case TWON_ONEVALUE:
  625. {
  626. DBG_TRC(("CCap::Set(TW_CAPABILITY *ptwCap) -> TWON_ONEVALUE"));
  627. pOneValue = (TW_ONEVALUE*)GlobalLock(ptwCap->hContainer);
  628. if (pOneValue != NULL) {
  629. if (pOneValue->ItemType == m_ItemType) {
  630. twCc = SetCurrent(&pOneValue->Item);
  631. } else {
  632. pOneValue->ItemType = m_ItemType;
  633. twCc = SetCurrent(&pOneValue->Item);
  634. //twCc = TWCC_BADVALUE;
  635. }
  636. DBG_TRC(("Application wanted to set (%d) as the value.",pOneValue->Item));
  637. GlobalUnlock(ptwCap->hContainer);
  638. } else {
  639. twCc = TWCC_LOWMEMORY;
  640. }
  641. break;
  642. }
  643. case TWON_RANGE:
  644. {
  645. DBG_TRC(("CCap::Set(TW_CAPABILITY *ptwCap) -> TWON_RANGE"));
  646. pRange = (TW_RANGE*)GlobalLock(ptwCap->hContainer);
  647. if (pRange != NULL) {
  648. if (CompareValue(pRange->MinValue, m_BaseMinValue) < 0 ||
  649. CompareValue(pRange->MinValue, m_BaseMaxValue) > 0 ||
  650. CompareValue(pRange->MaxValue, m_BaseMinValue) < 0 ||
  651. CompareValue(pRange->MaxValue, m_BaseMaxValue) > 0 ||
  652. CompareValue(pRange->CurrentValue, pRange->MinValue) < 0 ||
  653. CompareValue(pRange->CurrentValue, pRange->MaxValue) > 0) {
  654. twCc = TWCC_BADVALUE;
  655. } else {
  656. //
  657. // Ignore StepSize since it does not make sense for
  658. // the application to change it.
  659. //
  660. m_CurMinValue = GetClosestValue(pRange->MinValue);
  661. m_CurMaxValue = GetClosestValue(pRange->MaxValue);
  662. m_CurrentValue = GetClosestValue(pRange->CurrentValue);
  663. twCc = TWCC_SUCCESS;
  664. }
  665. GlobalUnlock(ptwCap->hContainer);
  666. } else {
  667. twCc = TWCC_LOWMEMORY;
  668. }
  669. break;
  670. }
  671. case TWON_ENUMERATION:
  672. {
  673. DBG_TRC(("CCap::Set(TW_CAPABILITY *ptwCap) -> TWON_ENUMERATION"));
  674. twCc = TWCC_SUCCESS;
  675. ptwEnum = (TW_ENUMERATION *)GlobalLock(ptwCap->hContainer);
  676. if (ptwEnum != NULL) {
  677. DBG_TRC(("Application sent this Enumeration to be set:"));
  678. Debug_DumpEnumerationValues(ptwEnum);
  679. if (m_ConType == TWON_ENUMERATION) {
  680. DBG_TRC(("We are a natural TWON_ENUMERATION"));
  681. DBG_TRC(("Our List contains:"));
  682. Debug_DumpEnumerationValues(NULL);
  683. } else {
  684. DBG_TRC(("We are not a natural TWON_ENUMERATION."));
  685. //
  686. // fail at the moment, because I need to look up, to see if we should
  687. // construct an TWON_ENUMERATION to send back to the application.
  688. //
  689. twCc = TWCC_BADVALUE;
  690. //
  691. // "break" here to avoid accessing any bad list data, and to
  692. // continue the flow of execution
  693. //
  694. break;
  695. }
  696. //
  697. // assign the list pointers
  698. //
  699. BYTE *pDSList = m_ItemList;
  700. BYTE *pAppList = ptwEnum->ItemList;
  701. UINT ValueIndex = 0;
  702. //
  703. // Compare lists, if any value is requested that we don't support,
  704. // fail them, because the application is trying alter the sources
  705. // supported values..*smack* BAD APPLICATION!....fail them with
  706. // TWRC_FAILURE, TWCC_BADVALUE. That way they know that some value
  707. // in their enumeration list set was invalid.
  708. //
  709. BOOL bFoundItem = FALSE;
  710. BOOL bBuildEnumeration = TRUE;
  711. UINT NEWMaxValue = 0;
  712. UINT NEWMinValue = 0;
  713. UINT NEWEnumMask = 0;
  714. for (UINT AppListIndex = 0;AppListIndex < ptwEnum->NumItems;AppListIndex++) {
  715. //
  716. // reset Data Source's List pointer for searching
  717. //
  718. pDSList = m_ItemList;
  719. ValueIndex = 0;
  720. while ((ValueIndex < m_BaseMaxValue + 1 /* m_CurNumItems */) && (!bFoundItem)) {
  721. if(*pDSList == *pAppList){
  722. DBG_TRC(("Found Item %d!",*pAppList));
  723. bFoundItem = TRUE;
  724. //
  725. // set mask value
  726. //
  727. NEWEnumMask |= 1 << ValueIndex;
  728. //
  729. // update MIN/MAX values
  730. //
  731. if (ValueIndex > NEWMaxValue){
  732. NEWMaxValue = ValueIndex;
  733. }
  734. if (ValueIndex < NEWMinValue) {
  735. NEWMinValue = ValueIndex;
  736. }
  737. }
  738. ValueIndex++;
  739. pDSList += ValueSize(m_ItemType);
  740. }
  741. if(!bFoundItem) {
  742. //
  743. // we were not found, so break, and fail
  744. //
  745. DBG_TRC(("Could not find Item %d!",*pAppList));
  746. twCc = TWCC_BADVALUE;
  747. //
  748. // set build enumeration flag to false, because we don't want to
  749. // construct an enumeration with invalid entries
  750. //
  751. bBuildEnumeration = FALSE;
  752. break;
  753. } else {
  754. //
  755. // set found flag, and continue searching
  756. //
  757. bFoundItem = FALSE;
  758. }
  759. pAppList += ValueSize(ptwEnum->ItemType);
  760. }
  761. //
  762. // set the enumeration, if all values were found, and accounted for
  763. //
  764. if(bBuildEnumeration) {
  765. DBG_TRC(("Set the application's enumeration"));
  766. Set(ptwEnum->DefaultIndex,ptwEnum->CurrentIndex,ptwEnum->NumItems,(BYTE*)ptwEnum->ItemList);
  767. DBG_TRC(("What does our new enumeration look like?"));
  768. Debug_DumpEnumerationValues(NULL);
  769. }
  770. GlobalUnlock(ptwCap->hContainer);
  771. } else {
  772. twCc = TWCC_LOWMEMORY;
  773. }
  774. break;
  775. }
  776. default:
  777. DBG_TRC(("What is this container type [%X]???",ptwCap->ConType));
  778. twCc = TWCC_BADVALUE;
  779. break;
  780. }
  781. return twCc;
  782. }
  783. TW_UINT16 CCap::ValueSize(TW_UINT16 uTWAINType)
  784. {
  785. TW_UINT16 uSize = 0;
  786. switch(uTWAINType) {
  787. case TWTY_INT8:
  788. uSize = sizeof(TW_INT8);
  789. break;
  790. case TWTY_INT16:
  791. uSize = sizeof(TW_INT16);
  792. break;
  793. case TWTY_INT32:
  794. uSize = sizeof(TW_INT32);
  795. break;
  796. case TWTY_UINT8:
  797. uSize = sizeof(TW_UINT8);
  798. break;
  799. case TWTY_UINT16:
  800. uSize = sizeof(TW_UINT16);
  801. break;
  802. case TWTY_UINT32:
  803. uSize = sizeof(TW_UINT32);
  804. break;
  805. case TWTY_BOOL:
  806. uSize = sizeof(TW_BOOL);
  807. break;
  808. case TWTY_FIX32:
  809. uSize = sizeof(TW_FIX32);
  810. break;
  811. case TWTY_FRAME:
  812. uSize = sizeof(TW_FRAME);
  813. break;
  814. case TWTY_STR32:
  815. uSize = sizeof(TW_STR32);
  816. break;
  817. case TWTY_STR64:
  818. uSize = sizeof(TW_STR64);
  819. break;
  820. case TWTY_STR128:
  821. uSize = sizeof(TW_STR128);
  822. break;
  823. case TWTY_STR255:
  824. uSize = sizeof(TW_STR255);
  825. break;
  826. default:
  827. uSize = sizeof(TW_UINT16);
  828. break;
  829. }
  830. return uSize;
  831. }
  832. TW_UINT16 CCap::CalcEnumBitMask(TW_ENUMERATION *pEnum)
  833. {
  834. TW_UINT32 nBitMask = 0x0;
  835. TW_UINT16 twStatus = TWCC_SUCCESS;
  836. for(unsigned int nIndex=0;nIndex<pEnum->NumItems;nIndex++)
  837. {
  838. switch(pEnum->ItemType)
  839. {
  840. case TWTY_UINT8:
  841. {
  842. pTW_UINT8 pBits = pEnum->ItemList;
  843. nBitMask |= 1<<pBits[nIndex];
  844. }
  845. break;
  846. case TWTY_INT8:
  847. {
  848. pTW_INT8 pBits = (pTW_INT8)pEnum->ItemList;
  849. nBitMask |= 1<<pBits[nIndex];
  850. }
  851. break;
  852. case TWTY_UINT16:
  853. {
  854. pTW_UINT16 pBits = (pTW_UINT16)pEnum->ItemList;
  855. nBitMask |= 1<<pBits[nIndex];
  856. }
  857. break;
  858. case TWTY_INT16:
  859. {
  860. pTW_INT16 pBits = (pTW_INT16)pEnum->ItemList;
  861. nBitMask |= 1<<pBits[nIndex];
  862. }
  863. break;
  864. case TWTY_UINT32:
  865. {
  866. pTW_UINT32 pBits = (pTW_UINT32)pEnum->ItemList;
  867. nBitMask |= 1<<pBits[nIndex];
  868. }
  869. break;
  870. case TWTY_INT32:
  871. {
  872. pTW_INT32 pBits = (pTW_INT32)pEnum->ItemList;
  873. nBitMask |= 1<<pBits[nIndex];
  874. }
  875. break;
  876. case TWTY_BOOL:
  877. {
  878. pTW_BOOL pBits = (pTW_BOOL)pEnum->ItemList;
  879. nBitMask |= 1<<pBits[nIndex];
  880. }
  881. break;
  882. /*case TWTY_FIX32:
  883. {
  884. pTW_FIX32 pBits = pEnum->ItemList;
  885. nBitMask |= 1<<pBits[nIndex];
  886. }
  887. break;
  888. */
  889. case TWTY_STR32:
  890. {
  891. pTW_STR32 pBits = (pTW_STR32)pEnum->ItemList;
  892. nBitMask |= 1<<pBits[nIndex];
  893. }
  894. break;
  895. case TWTY_STR64:
  896. {
  897. pTW_STR64 pBits = (pTW_STR64)pEnum->ItemList;
  898. nBitMask |= 1<<pBits[nIndex];
  899. }
  900. break;
  901. case TWTY_STR128:
  902. {
  903. pTW_STR128 pBits = (pTW_STR128)pEnum->ItemList;
  904. nBitMask |= 1<<pBits[nIndex];
  905. }
  906. break;
  907. case TWTY_STR255:
  908. {
  909. pTW_STR255 pBits = (pTW_STR255)pEnum->ItemList;
  910. nBitMask |= 1<<pBits[nIndex];
  911. }
  912. break;
  913. default:
  914. twStatus = TWCC_BADVALUE;
  915. break;
  916. }
  917. }
  918. if(twStatus == TWCC_SUCCESS) {
  919. m_CurEnumMask = nBitMask;
  920. }
  921. return twStatus;
  922. }
  923. //
  924. // debug helpers
  925. //
  926. void CCap::Debug_DumpEnumerationValues(TW_ENUMERATION *ptwEnumeration)
  927. {
  928. BYTE *pList = NULL;
  929. UINT ValueIndex = 0;
  930. UINT iItemSize = 0;
  931. UINT iNumItems = 0;
  932. DBG_TRC(("CCap::Debug_DumpEnumerationValues(), Enumeration Value debug dump"));
  933. if(ptwEnumeration){
  934. pList = ptwEnumeration->ItemList;
  935. DBG_TRC(("Enumeration Values:"));
  936. DBG_TRC(("ItemType = %d",ptwEnumeration->ItemType));
  937. DBG_TRC(("NumItems = %d",ptwEnumeration->NumItems));
  938. DBG_TRC(("CurrentIndex = %d",ptwEnumeration->CurrentIndex));
  939. DBG_TRC(("DefaultIndex = %d",ptwEnumeration->DefaultIndex));
  940. iItemSize = ValueSize(ptwEnumeration->ItemType);
  941. iNumItems = ptwEnumeration->NumItems;
  942. } else {
  943. pList = m_ItemList;
  944. DBG_TRC(("Enumeration Values: (current internal settings)"));
  945. DBG_TRC(("ItemType = %d",m_ItemType));
  946. DBG_TRC(("NumItems = %d",m_CurNumItems));
  947. DBG_TRC(("CurrentIndex = %d",m_CurrentValue));
  948. DBG_TRC(("DefaultIndex = %d",m_DefaultValue));
  949. iItemSize = ValueSize(m_ItemType);
  950. iNumItems = m_CurNumItems;
  951. }
  952. #ifdef DEBUG
  953. DBG_TRC(("Values:"));
  954. for(ValueIndex = 0;ValueIndex < iNumItems;ValueIndex++) {
  955. DBG_TRC(("ItemList[%d] = %d",ValueIndex,*pList));
  956. pList += iItemSize;
  957. }
  958. #endif
  959. }