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.

726 lines
26 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: oledbutl.cpp
  7. //
  8. // Contents:
  9. //
  10. //
  11. // History: 07/10/96 RenatoB Created, lifted from EricJ code
  12. //
  13. //-----------------------------------------------------------------------------
  14. // Includes
  15. #include "oleds.hxx"
  16. // All the '256's below should be 4 (the length of a pointer to a string). Because
  17. // of a bug in the TempTable, this has been temporarily done.
  18. //
  19. // Note: Provider-specific types are returned as octet strings
  20. //
  21. MAPTYPE_STRUCT g_MapADsTypeToDBType[] = {
  22. {DBTYPE_NULL, 0}, /* ADSTYPE_INVALID = 0, */
  23. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_DN_STRING, */
  24. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_EXACT_STRING, */
  25. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_IGNORE_STRING, */
  26. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_PRINTABLE_STRING, */
  27. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_NUMERIC_STRING, */
  28. {DBTYPE_BOOL, 2}, /* ADSTYPE_BOOLEAN, */
  29. {DBTYPE_I4, 4}, /* ADSTYPE_INTEGER, */
  30. {DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_OCTET_STRING, */
  31. {DBTYPE_DATE, 8}, /* ADSTYPE_UTC_TIME, */
  32. {DBTYPE_VARIANT |DBTYPE_BYREF,16}, /* ADSTYPE_LARGE_INTEGER, */
  33. {DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_PROV_SPECIFIC */
  34. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_OBJECT_CLASS, */
  35. {DBTYPE_NULL, 0}, /* ADSTYPE_CASEIGNORE_LIST */
  36. {DBTYPE_NULL, 0}, /* ADSTYPE_OCTET_LIST */
  37. {DBTYPE_NULL, 0}, /* ADSTYPE_PATH */
  38. {DBTYPE_NULL, 0}, /* ADSTYPE_POSTALADDRESS */
  39. {DBTYPE_NULL, 0}, /* ADSTYPE_TIMESTAMP */
  40. {DBTYPE_NULL, 0}, /* ADSTYPE_BACKLINK */
  41. {DBTYPE_NULL, 0}, /* ADSTYPE_TYPEDNAME */
  42. {DBTYPE_NULL, 0}, /* ADSTYPE_HOLD */
  43. {DBTYPE_NULL, 0}, /* ADSTYPE_NETADDRESS */
  44. {DBTYPE_NULL, 0}, /* ADSTYPE_REPLICAPOINTER */
  45. {DBTYPE_NULL, 0}, /* ADSTYPE_FAXNUMBER */
  46. {DBTYPE_NULL, 0}, /* ADSTYPE_EMAIL */
  47. {DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_NT_SECURITY_DESC */
  48. {DBTYPE_NULL, 0}, /* ADSTYPE_UNKNOWN */
  49. {DBTYPE_VARIANT |DBTYPE_BYREF,16}, /* ADSTYPE_DN_WITH_BINARY */
  50. {DBTYPE_VARIANT |DBTYPE_BYREF,16} /* ADSTYPE_DN_WITH_STRING */
  51. };
  52. DWORD g_cMapADsTypeToDBType = (sizeof(g_MapADsTypeToDBType) /
  53. sizeof(g_MapADsTypeToDBType[0]));
  54. // The row object does not use IDirectorySearch when a direct bind or SELECT
  55. // * happens. In this case, it uses IADs::Get. It is possible that a variant
  56. // with VT_DISPATCH may be returned in this case - for ADSTYPE_NT_SECURITY_DESC
  57. // DNWithBin or DNWithStr. In this case, they cannot be converted to any other
  58. // DBTYPE. So, they will be returned as DBTYPE_VARIANT.
  59. MAPTYPE_STRUCT g_MapADsTypeToDBType2[] = {
  60. {DBTYPE_NULL, 0}, /* ADSTYPE_INVALID = 0, */
  61. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_DN_STRING, */
  62. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_EXACT_STRING, */
  63. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_IGNORE_STRING, */
  64. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_PRINTABLE_STRING, */
  65. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_NUMERIC_STRING, */
  66. {DBTYPE_BOOL, 2}, /* ADSTYPE_BOOLEAN, */
  67. {DBTYPE_I4, 4}, /* ADSTYPE_INTEGER, */
  68. {DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_OCTET_STRING, */
  69. {DBTYPE_DATE, 8}, /* ADSTYPE_UTC_TIME, */
  70. {DBTYPE_VARIANT, 16}, /* ADSTYPE_LARGE_INTEGER, */
  71. {DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_PROV_SPECIFIC */
  72. {DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_OBJECT_CLASS, */
  73. {DBTYPE_NULL, 0}, /* ADSTYPE_CASEIGNORE_LIST */
  74. {DBTYPE_NULL, 0}, /* ADSTYPE_OCTET_LIST */
  75. {DBTYPE_NULL, 0}, /* ADSTYPE_PATH */
  76. {DBTYPE_NULL, 0}, /* ADSTYPE_POSTALADDRESS */
  77. {DBTYPE_NULL, 0}, /* ADSTYPE_TIMESTAMP */
  78. {DBTYPE_NULL, 0}, /* ADSTYPE_BACKLINK */
  79. {DBTYPE_NULL, 0}, /* ADSTYPE_TYPEDNAME */
  80. {DBTYPE_NULL, 0}, /* ADSTYPE_HOLD */
  81. {DBTYPE_NULL, 0}, /* ADSTYPE_NETADDRESS */
  82. {DBTYPE_NULL, 0}, /* ADSTYPE_REPLICAPOINTER */
  83. {DBTYPE_NULL, 0}, /* ADSTYPE_FAXNUMBER */
  84. {DBTYPE_NULL, 0}, /* ADSTYPE_EMAIL */
  85. {DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_NT_SECURITY_DESC */
  86. {DBTYPE_NULL, 0}, /* ADSTYPE_UNKNOWN */
  87. {DBTYPE_VARIANT, 16}, /* ADSTYPE_DN_WITH_BINARY */
  88. {DBTYPE_VARIANT, 16} /* ADSTYPE_DN_WITH_STRING */
  89. };
  90. DWORD g_cMapADsTypeToDBType2 = (sizeof(g_MapADsTypeToDBType2) /
  91. sizeof(g_MapADsTypeToDBType2[0]));
  92. VARTYPE g_MapADsTypeToVarType[] = {
  93. VT_NULL, /* ADSTYPE_INVALID = 0, */
  94. VT_BSTR, /* ADSTYPE_DN_STRING, */
  95. VT_BSTR, /* ADSTYPE_CASE_EXACT_STRING, */
  96. VT_BSTR, /* ADSTYPE_CASE_IGNORE_STRING, */
  97. VT_BSTR, /* ADSTYPE_PRINTABLE_STRING, */
  98. VT_BSTR, /* ADSTYPE_NUMERIC_STRING, */
  99. VT_BOOL, /* ADSTYPE_BOOLEAN, */
  100. VT_I4, /* ADSTYPE_INTEGER, */
  101. VT_UI1 | VT_ARRAY, /* ADSTYPE_OCTET_STRING, */
  102. VT_DATE, /* ADSTYPE_UTC_TIME, */
  103. VT_DISPATCH, /* ADSTYPE_LARGE_INTEGER, */
  104. VT_UI1 | VT_ARRAY, /* ADSTYPE_PROV_SPECIFIC */
  105. VT_BSTR, /* ADSTYPE_OBJECT_CLASS */
  106. VT_NULL, /* ADSTYPE_CASEIGNORE_LIST */
  107. VT_NULL, /* ADSTYPE_OCTET_LIST */
  108. VT_NULL, /* ADSTYPE_PATH */
  109. VT_NULL, /* ADSTYPE_POSTALADDRESS */
  110. VT_NULL, /* ADSTYPE_TIMESTAMP */
  111. VT_NULL, /* ADSTYPE_BACKLINK */
  112. VT_NULL, /* ADSTYPE_TYPEDNAME */
  113. VT_NULL, /* ADSTYPE_HOLD */
  114. VT_NULL, /* ADSTYPE_NETADDRESS */
  115. VT_NULL, /* ADSTYPE_REPLICAPOINTER */
  116. VT_NULL, /* ADSTYPE_FAXNUMBER */
  117. VT_NULL, /* ADSTYPE_EMAIL */
  118. VT_UI1 | VT_ARRAY, /* ADSTYPE_NT_SECURITY_DESC */
  119. VT_NULL, /* ADSTYPE_UNKNOWN */
  120. VT_DISPATCH, /* ADSTYPE_DN_WITH_BINARY */
  121. VT_DISPATCH /* ADSTYPE_DN_WITH_STRING */
  122. };
  123. DWORD g_cMapADsTypeToVarType = (sizeof(g_MapADsTypeToVarType) /
  124. sizeof(g_MapADsTypeToVarType[0]));
  125. ADS_SEARCHPREF g_MapDBPropIdToSearchPref[] = {
  126. ADS_SEARCHPREF_ASYNCHRONOUS,
  127. ADS_SEARCHPREF_DEREF_ALIASES,
  128. ADS_SEARCHPREF_SIZE_LIMIT,
  129. ADS_SEARCHPREF_TIME_LIMIT,
  130. ADS_SEARCHPREF_ATTRIBTYPES_ONLY,
  131. ADS_SEARCHPREF_SEARCH_SCOPE,
  132. ADS_SEARCHPREF_TIMEOUT,
  133. ADS_SEARCHPREF_PAGESIZE,
  134. ADS_SEARCHPREF_PAGED_TIME_LIMIT,
  135. ADS_SEARCHPREF_CHASE_REFERRALS,
  136. ADS_SEARCHPREF_SORT_ON,
  137. ADS_SEARCHPREF_CACHE_RESULTS
  138. };
  139. DWORD g_cMapDBPropToSearchPref = (sizeof(g_MapDBPropIdToSearchPref) /
  140. sizeof(g_MapDBPropIdToSearchPref[0]));
  141. //+---------------------------------------------------------------------------
  142. //
  143. // Function: CpAccessors2Rowset
  144. //
  145. // Synopsis: @ffunc Implements inheritance of Accessors. Copies to
  146. // a Rowset the accessors existing on the command
  147. //
  148. // Called by: CRowset::Finit
  149. // Called when: At runtime.
  150. // Overridden: No. (Private)
  151. // Arguments:
  152. //
  153. //
  154. // Returns: @rdesc HRESULT
  155. // @flag S_OK | OK
  156. // @flag E_OUTOFMEMORY |could not get IMalloc
  157. // @flag E_FAIL| An accessor could not be created
  158. //
  159. //----------------------------------------------------------------------------
  160. HRESULT
  161. CpAccessors2Rowset(
  162. IAccessor *pAccessorCommand, //@parm IN |Command's IAccessor
  163. IAccessor *pAccessorRowset, //@parm IN |Rowset's IAccessor
  164. ULONG cAccessors, //@parm IN |Count,Commnands accessors
  165. HACCESSOR rgAccessors[], //@parm IN |Array,Command's accessors
  166. CImpIAccessor *pCAccessor //accessor object of rowset
  167. )
  168. {
  169. HRESULT hr;
  170. IMalloc * pMalloc = NULL;
  171. DBCOUNTITEM cBindings;
  172. DBBINDING * pBindings = NULL;
  173. DBBINDSTATUS * prgBindStatus = NULL;
  174. ULONG i,j;
  175. DBACCESSORFLAGS AccessorFlags;
  176. HACCESSOR hAccessor;
  177. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  178. BAIL_ON_FAILURE(hr);
  179. //for each of the command's accessors,
  180. // we create a Rowset accessor.
  181. // if anyone fails, return E_FAIL
  182. for (i=0; i<cAccessors; i++) {
  183. AccessorFlags = 0;
  184. hr=pAccessorCommand->GetBindings(
  185. rgAccessors[i],
  186. &AccessorFlags,
  187. &cBindings,
  188. &pBindings
  189. );
  190. // Not a valid accessor handle
  191. if (hr == DB_E_BADACCESSORHANDLE) {
  192. // Rowset will also inherit the bad accessor
  193. hr = pCAccessor->CreateBadAccessor();
  194. BAIL_ON_FAILURE( hr );
  195. continue;
  196. }
  197. BAIL_ON_FAILURE( hr );
  198. // Allocate memory for the Status values
  199. prgBindStatus = (DBBINDSTATUS*) pMalloc->Alloc((ULONG)(cBindings *
  200. sizeof(DBBINDSTATUS)));
  201. hr=pAccessorRowset->CreateAccessor(
  202. AccessorFlags,
  203. cBindings,
  204. pBindings,
  205. 0,
  206. &hAccessor,
  207. prgBindStatus
  208. );
  209. //
  210. // If CreateAccessor fails fixup DB_E_ERRORSOCCURRED
  211. //
  212. if (hr == DB_E_ERRORSOCCURRED ) {
  213. // Fixup the HResult
  214. for(j=0; j < cBindings; j++) {
  215. switch (prgBindStatus[j])
  216. {
  217. case DBBINDSTATUS_NOINTERFACE:
  218. BAIL_ON_FAILURE( hr=E_NOINTERFACE );
  219. case DBBINDSTATUS_BADBINDINFO:
  220. BAIL_ON_FAILURE( hr=DB_E_BADBINDINFO );
  221. case DBBINDSTATUS_BADORDINAL:
  222. BAIL_ON_FAILURE( hr=DB_E_BADORDINAL );
  223. case DBBINDSTATUS_BADSTORAGEFLAGS:
  224. BAIL_ON_FAILURE( hr=DB_E_BADSTORAGEFLAGS );
  225. case DBBINDSTATUS_UNSUPPORTEDCONVERSION:
  226. BAIL_ON_FAILURE( hr=DB_E_UNSUPPORTEDCONVERSION );
  227. case DBBINDSTATUS_MULTIPLESTORAGE:
  228. BAIL_ON_FAILURE( hr=DB_E_MULTIPLESTORAGE );
  229. case DBBINDSTATUS_OK:
  230. default:
  231. hr=E_FAIL;
  232. break;
  233. }
  234. }
  235. // Should never be E_FAIL
  236. ADsAssert(hr != E_FAIL);
  237. }
  238. BAIL_ON_FAILURE( hr );
  239. if( pBindings )
  240. pMalloc->Free(pBindings);
  241. pBindings = NULL;
  242. if( prgBindStatus )
  243. pMalloc->Free(prgBindStatus);
  244. prgBindStatus = NULL;
  245. };
  246. error:
  247. if( pBindings )
  248. pMalloc->Free(pBindings);
  249. if( prgBindStatus )
  250. pMalloc->Free(prgBindStatus);
  251. pMalloc->Release();
  252. RRETURN( hr );
  253. }
  254. HRESULT
  255. GetDSInterface(
  256. LPWSTR lpszPath,
  257. CCredentials& Credentials,
  258. REFIID iid,
  259. void FAR * FAR * ppObject
  260. )
  261. {
  262. HRESULT hr = E_FAIL;
  263. LPWSTR lpszUserName=NULL, lpszPassword=NULL;
  264. DWORD dwAuthFlags = 0;
  265. hr = Credentials.GetUserName(&lpszUserName);
  266. BAIL_ON_FAILURE( hr );
  267. hr = Credentials.GetPassword(&lpszPassword);
  268. BAIL_ON_FAILURE( hr );
  269. dwAuthFlags = Credentials.GetAuthFlags();
  270. hr = ADsOpenObject(
  271. lpszPath,
  272. lpszUserName,
  273. lpszPassword,
  274. dwAuthFlags,
  275. iid,
  276. ppObject
  277. );
  278. if( INVALID_CREDENTIALS_ERROR(hr) )
  279. BAIL_ON_FAILURE( hr=DB_SEC_E_PERMISSIONDENIED );
  280. if( FAILED(hr) )
  281. BAIL_ON_FAILURE( hr=DB_E_NOTABLE );
  282. error:
  283. if( lpszUserName )
  284. FreeADsMem(lpszUserName);
  285. if( lpszPassword )
  286. FreeADsMem(lpszPassword);
  287. RRETURN( hr );
  288. }
  289. //+---------------------------------------------------------------------------
  290. //
  291. // Function: GetCredentialsFromIAuthenticate
  292. //
  293. // Synopsis: Gets credentials (user name, password) from IAuthenticate
  294. // interface pointer.
  295. //
  296. // Returns: HRESULT
  297. //----------------------------------------------------------------------------
  298. HRESULT GetCredentialsFromIAuthenticate(
  299. IAuthenticate *pAuthenticate,
  300. CCredentials& refCredentials
  301. )
  302. {
  303. Assert(pAuthenticate);
  304. HRESULT hr = S_OK;
  305. HWND hwnd;
  306. PWSTR pszUsername;
  307. PWSTR pszPassword;
  308. if (pAuthenticate->Authenticate(&hwnd, &pszUsername, &pszPassword) != S_OK)
  309. RRETURN(E_INVALIDARG);
  310. if (hwnd != INVALID_HANDLE_VALUE) //don't know if and how to handle this case
  311. {
  312. RRETURN(S_OK);
  313. }
  314. else
  315. {
  316. hr = refCredentials.SetUserName(pszUsername);
  317. if (FAILED(hr))
  318. RRETURN(hr);
  319. hr = refCredentials.SetPassword(pszPassword);
  320. if (FAILED(hr))
  321. RRETURN(hr);
  322. }
  323. RRETURN(S_OK);
  324. }
  325. //+---------------------------------------------------------------------------
  326. //
  327. // Function: RemoveWhiteSpaces
  328. //
  329. // Synopsis: Removes the leading and trailing white spaces
  330. //
  331. // Arguments: pszText Text strings from which the leading
  332. // and trailing white spaces are to be
  333. // removed
  334. //
  335. // Returns: LPWSTR Pointer to the modified string
  336. //
  337. // Modifies:
  338. //
  339. // History: 08-15-96 ShankSh Created.
  340. //
  341. //----------------------------------------------------------------------------
  342. LPWSTR
  343. RemoveWhiteSpaces(LPWSTR pszText)
  344. {
  345. LPWSTR pChar;
  346. if( !pszText )
  347. return( pszText );
  348. while(*pszText && iswspace(*pszText))
  349. pszText++;
  350. for(pChar = pszText + wcslen(pszText) - 1; pChar >= pszText; pChar--) {
  351. if( !iswspace(*pChar) )
  352. break;
  353. else
  354. *pChar = L'\0';
  355. }
  356. return pszText;
  357. }
  358. //+---------------------------------------------------------------------------
  359. //
  360. // Function: CanConvertHelper
  361. //
  362. // Synopsis: Helper that tells the consumer if the conversion is supported.
  363. //
  364. // Arguments: DBTYPE wSrcType
  365. // DBTYPE wDstType
  366. //
  367. // Returns: HRESULT
  368. //
  369. // Modifies:
  370. //
  371. // History: 08-15-96 ShankSh Created.
  372. //
  373. //----------------------------------------------------------------------------
  374. //
  375. // Bitmask of supported conversions --
  376. // - src type is index into array,
  377. // - dst type is bit in that ULONG
  378. //
  379. static ULONG s_rgConvertBitmap[] =
  380. {
  381. // 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0.
  382. // 0 8 6 4 2 0 8 6 4 2 0 8 6 4 2 0.
  383. // 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0.
  384. // 1 9 7 5 3 1 9 7 5 3 1 9 7 5 3 1.
  385. // DBTYPE_EMPTY
  386. 0xe3bfd9ff, // 11100011101111111101100111111111
  387. // DBTYPE_NULL
  388. 0x60001002, // 01100000000000000001000000000010
  389. // DBTYPE_I2
  390. 0xdf9fd9ff, // 11011111100111111101100111111111
  391. // DBTYPE_I4
  392. 0xdfdfd9ff, // 11011111110111111101100111111111
  393. // DBTYPE_R4
  394. 0xdf9fd9ff, // 11011111100111111101100111111111
  395. // DBTYPE_R8
  396. 0xdf9fd9ff, // 11011111100111111101100111111111
  397. // DBTYPE_CY
  398. 0xc39fd97f, // 11000011100111111101100101111111
  399. // DBTYPE_DATE
  400. 0x7d9f99bf, // 01111101100111111001100110111111
  401. // DBTYPE_BSTR
  402. 0xffffd9ff, // 11111111111111111101100111111111
  403. // DBTYPE_IDISPATCH
  404. 0x4087fbff, // 01000000100001111111101111111111
  405. // DBTYPE_ERROR
  406. 0x01001500, // 00000001000000000001010100000000
  407. // DBTYPE_BOOL
  408. 0xc39fd9ff, // 11000011100111111101100111111111
  409. // DBTYPE_VARIANT
  410. 0xffffffff, // 11111111111111111111111111111111
  411. // DBTYPE_IUNKNOWN
  412. 0x00003203, // 00000000000000000011001000000011
  413. // DBTYPE_DECIMAL
  414. 0x9f9fd97f, // 10011111100111111101100101111111
  415. // DBTYPE_I1
  416. 0x9f9fd9ff, // 10011111100111111101100111111111
  417. // DBTYPE_UI1
  418. 0xdf9fd9ff, // 11011111100111111101100111111111
  419. // DBTYPE_UI2
  420. 0xdf9fd9ff, // 11011111100111111101100111111111
  421. // DBTYPE_UI4
  422. 0xdfdfd9ff, // 11011111110111111101100111111111
  423. // DBTYPE_I8
  424. 0x619fd13f, // 01100001100111111101000100111111
  425. // DBTYPE_UI8
  426. 0x619fd13f, // 01100001100111111101000100111111
  427. // DBTYPE_GUID
  428. 0x41a01103, // 01000001101000000001000100000011
  429. // DBTYPE_BYTES
  430. 0x41c4110b, // 01000001110001000001000100001011
  431. // DBTYPE_STR
  432. 0xffffd9ff, // 11111111111111111101100111111111
  433. // DBTYPE_WSTR
  434. 0xffffd9ff, // 11111111111111111101100111111111
  435. // DBTYPE_NUMERIC
  436. 0xc39fd97f, // 11000011100111111101100101111111
  437. // DBTYPE_DBDATE
  438. 0x3d801183, // 00111101100000000001000110000011
  439. // DBTYPE_DBTIME
  440. 0x3d801183, // 00111101100000000001000110000011
  441. // DBTYPE_DBTIMESTAMP
  442. 0x3d801183, // 00111101100000000001000110000011
  443. // DBTYPE_FILETIME
  444. 0x7d981183, // 01111101100110000001000110000011
  445. // DBTYPE_PROPVARIANT
  446. 0xffffffff, // 11111111111111111111111111111111
  447. // DBTYPE_VARNUMERIC
  448. 0x839fd97f, // 10000011100111111101100101111111
  449. };
  450. static HRESULT IsLegalDBtype(DBTYPE);
  451. static LONG IndexDBTYPE(DBTYPE wType);
  452. STDMETHODIMP
  453. CanConvertHelper(
  454. DBTYPE wSrcType,
  455. DBTYPE wDstType,
  456. DBCONVERTFLAGS dwConvertFlags
  457. )
  458. {
  459. //
  460. // Check in-params and NULL out-params in case of error
  461. //
  462. if( (dwConvertFlags &
  463. ~(DBCONVERTFLAGS_ISLONG |
  464. DBCONVERTFLAGS_ISFIXEDLENGTH |
  465. DBCONVERTFLAGS_FROMVARIANT)) != DBCONVERTFLAGS_COLUMN )
  466. RRETURN( DB_E_BADCONVERTFLAG );
  467. //
  468. // Make sure that we check that the type is a variant if they say so
  469. //
  470. if( dwConvertFlags & DBCONVERTFLAGS_FROMVARIANT ) {
  471. DBTYPE wVtType = wSrcType & VT_TYPEMASK;
  472. // Take out all of the Valid VT_TYPES (36 is VT_RECORD in VC 6)
  473. if( (wVtType > VT_DECIMAL && wVtType < VT_I1) ||
  474. ((wVtType > VT_LPWSTR && wVtType < VT_FILETIME) && wVtType !=36) ||
  475. (wVtType > VT_CLSID) )
  476. RRETURN( DB_E_BADTYPE );
  477. }
  478. //
  479. // Don't allow _ISLONG on fixed-length types
  480. //
  481. if( dwConvertFlags & DBCONVERTFLAGS_ISLONG ) {
  482. switch ( wSrcType & ~(DBTYPE_RESERVED|DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_BYREF) )
  483. {
  484. case DBTYPE_BYTES:
  485. case DBTYPE_STR:
  486. case DBTYPE_WSTR:
  487. case DBTYPE_VARNUMERIC:
  488. break;
  489. default:
  490. RRETURN( DB_E_BADCONVERTFLAG );
  491. }
  492. }
  493. // Check for valid types
  494. if( wSrcType > DBTYPE_DECIMAL )
  495. {
  496. if( FAILED(IsLegalDBtype(wSrcType)) )
  497. RRETURN( S_FALSE );
  498. }
  499. if( wDstType > DBTYPE_DECIMAL )
  500. {
  501. if( FAILED(IsLegalDBtype(wDstType)) )
  502. RRETURN( S_FALSE );
  503. }
  504. // Check for unsupported type modifiers
  505. if( (wSrcType & (DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_RESERVED)) ||
  506. (wDstType & (DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_RESERVED)) )
  507. RRETURN( S_FALSE );
  508. // Handle BYREF destination separately
  509. if( wDstType & DBTYPE_BYREF ) {
  510. // Turn off BYREF bit
  511. wDstType &= ~DBTYPE_BYREF;
  512. // We only allow BYREF destination for variable length types
  513. switch ( wDstType ) {
  514. case DBTYPE_BYTES:
  515. case DBTYPE_STR:
  516. case DBTYPE_WSTR:
  517. case DBTYPE_VARNUMERIC:
  518. break;
  519. default:
  520. // Fixed-length BYREFs are not supported
  521. RRETURN( S_FALSE );
  522. }
  523. }
  524. // Turn off BYREF bit
  525. wSrcType &= ~DBTYPE_BYREF;
  526. // Get the indices for the src and dst types
  527. LONG iSrc = IndexDBTYPE(wSrcType);
  528. ADsAssert(iSrc < NUMELEM(s_rgConvertBitmap)); // better not be larger than our array
  529. LONG iDst = IndexDBTYPE(wDstType);
  530. ADsAssert(iDst < (sizeof(ULONG) * 8) ); // or the number of bits in a ULONG
  531. // Make sure we have two supported types -- we don't support UDT
  532. if( iSrc < 0 || iDst < 0 )
  533. RRETURN( S_FALSE );
  534. // And do the lookup -- bit will be set if conversion supported
  535. if( s_rgConvertBitmap[iSrc] & (1 << iDst) )
  536. RRETURN( S_OK );
  537. // No bit, no support
  538. RRETURN( S_FALSE );
  539. }
  540. HRESULT IsLegalDBtype(DBTYPE dbtype)
  541. {
  542. // NOTE: optimized for speed, rather than for maintainablity
  543. if( dbtype & (DBTYPE_VECTOR|DBTYPE_BYREF|DBTYPE_ARRAY|DBTYPE_RESERVED) )
  544. dbtype &= ~(DBTYPE_VECTOR|DBTYPE_BYREF|DBTYPE_ARRAY|DBTYPE_RESERVED);
  545. if( (dbtype >= DBTYPE_EMPTY && dbtype <= DBTYPE_DECIMAL) ||
  546. (dbtype >= DBTYPE_I1 && dbtype <= DBTYPE_UI8) ||
  547. dbtype == DBTYPE_GUID ||
  548. (dbtype >= DBTYPE_BYTES && dbtype <= DBTYPE_DBTIMESTAMP) ||
  549. (dbtype >= DBTYPE_FILETIME && dbtype <= DBTYPE_VARNUMERIC) )
  550. RRETURN( S_OK );
  551. RRETURN( DB_E_BADBINDINFO );
  552. }
  553. LONG IndexDBTYPE(DBTYPE wType)
  554. {
  555. switch ( wType ) {
  556. case DBTYPE_EMPTY: // 0
  557. case DBTYPE_NULL: // 1
  558. case DBTYPE_I2: // 2
  559. case DBTYPE_I4: // 3
  560. case DBTYPE_R4: // 4
  561. case DBTYPE_R8: // 5
  562. case DBTYPE_CY: // 6
  563. case DBTYPE_DATE: // 7
  564. case DBTYPE_BSTR: // 8
  565. case DBTYPE_IDISPATCH: // 9
  566. case DBTYPE_ERROR: // 10
  567. case DBTYPE_BOOL: // 11
  568. case DBTYPE_VARIANT: // 12
  569. case DBTYPE_IUNKNOWN: // 13
  570. case DBTYPE_DECIMAL: // 14
  571. // 0 - 14
  572. return (ULONG)wType;
  573. case DBTYPE_I1: // 16
  574. case DBTYPE_UI1: // 17
  575. case DBTYPE_UI2: // 18
  576. case DBTYPE_UI4: // 19
  577. case DBTYPE_I8: // 20
  578. case DBTYPE_UI8: // 21
  579. // 15 - 20
  580. return (ULONG)(wType - 1);
  581. case DBTYPE_GUID: // 72
  582. // 21
  583. return 21;
  584. case DBTYPE_BYTES: // 128
  585. case DBTYPE_STR: // 129
  586. case DBTYPE_WSTR: // 130
  587. case DBTYPE_NUMERIC: // 131
  588. // 22 - 25
  589. return (ULONG)(wType - 106);
  590. case DBTYPE_DBDATE: // 133
  591. case DBTYPE_DBTIME: // 134
  592. case DBTYPE_DBTIMESTAMP:// 135
  593. // 26 - 28
  594. return (ULONG)(wType - 107);
  595. case DBTYPE_FILETIME: // 64
  596. // 29
  597. return wType - 35;
  598. case DBTYPE_PROPVARIANT:// 138
  599. case DBTYPE_VARNUMERIC: // 139
  600. // 30 - 31
  601. return (ULONG)(wType - 108);
  602. }
  603. // No match
  604. return -1;
  605. }
  606. BYTE SetPrecision(DBTYPE dbType)
  607. {
  608. switch(dbType)
  609. {
  610. case DBTYPE_I1:
  611. case DBTYPE_UI1:
  612. return 3;
  613. case DBTYPE_I2:
  614. case DBTYPE_UI2:
  615. return 5;
  616. case DBTYPE_I4:
  617. case DBTYPE_UI4:
  618. return 10;
  619. case DBTYPE_I8:
  620. return 19;
  621. case DBTYPE_UI8:
  622. return 20;
  623. case DBTYPE_R4:
  624. return 7;
  625. case DBTYPE_R8:
  626. return 15;
  627. case DBTYPE_CY:
  628. return 19;
  629. case DBTYPE_DECIMAL:
  630. return 29;
  631. case DBTYPE_NUMERIC:
  632. return 39;
  633. case DBTYPE_VARNUMERIC:
  634. return 255;
  635. default:
  636. return ((BYTE) (~0));
  637. }
  638. }