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.

746 lines
27 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. if (NULL == prgBindStatus)
  202. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  203. hr=pAccessorRowset->CreateAccessor(
  204. AccessorFlags,
  205. cBindings,
  206. pBindings,
  207. 0,
  208. &hAccessor,
  209. prgBindStatus
  210. );
  211. //
  212. // If CreateAccessor fails fixup DB_E_ERRORSOCCURRED
  213. //
  214. if (hr == DB_E_ERRORSOCCURRED) {
  215. // Fixup the HResult
  216. for(j=0; j < cBindings; j++) {
  217. switch (prgBindStatus[j])
  218. {
  219. case DBBINDSTATUS_NOINTERFACE:
  220. BAIL_ON_FAILURE( hr=E_NOINTERFACE );
  221. case DBBINDSTATUS_BADBINDINFO:
  222. BAIL_ON_FAILURE( hr=DB_E_BADBINDINFO );
  223. case DBBINDSTATUS_BADORDINAL:
  224. BAIL_ON_FAILURE( hr=DB_E_BADORDINAL );
  225. case DBBINDSTATUS_BADSTORAGEFLAGS:
  226. BAIL_ON_FAILURE( hr=DB_E_BADSTORAGEFLAGS );
  227. case DBBINDSTATUS_UNSUPPORTEDCONVERSION:
  228. BAIL_ON_FAILURE( hr=DB_E_UNSUPPORTEDCONVERSION );
  229. case DBBINDSTATUS_MULTIPLESTORAGE:
  230. BAIL_ON_FAILURE( hr=DB_E_MULTIPLESTORAGE );
  231. case DBBINDSTATUS_OK:
  232. default:
  233. hr=E_FAIL;
  234. break;
  235. }
  236. }
  237. // Should never be E_FAIL
  238. ADsAssert(hr != E_FAIL);
  239. }
  240. BAIL_ON_FAILURE( hr );
  241. if( pBindings )
  242. pMalloc->Free(pBindings);
  243. pBindings = NULL;
  244. if( prgBindStatus )
  245. pMalloc->Free(prgBindStatus);
  246. prgBindStatus = NULL;
  247. };
  248. error:
  249. if (pMalloc)
  250. {
  251. if( pBindings )
  252. pMalloc->Free(pBindings);
  253. if( prgBindStatus )
  254. pMalloc->Free(prgBindStatus);
  255. pMalloc->Release();
  256. }
  257. RRETURN( hr );
  258. }
  259. HRESULT
  260. GetDSInterface(
  261. LPWSTR lpszPath,
  262. CCredentials& Credentials,
  263. REFIID iid,
  264. void FAR * FAR * ppObject
  265. )
  266. {
  267. HRESULT hr = E_FAIL;
  268. LPWSTR lpszUserName=NULL, lpszPassword=NULL;
  269. DWORD dwAuthFlags = 0;
  270. hr = Credentials.GetUserName(&lpszUserName);
  271. BAIL_ON_FAILURE( hr );
  272. hr = Credentials.GetPassword(&lpszPassword);
  273. BAIL_ON_FAILURE( hr );
  274. dwAuthFlags = Credentials.GetAuthFlags();
  275. hr = ADsOpenObject(
  276. lpszPath,
  277. lpszUserName,
  278. lpszPassword,
  279. dwAuthFlags,
  280. iid,
  281. ppObject
  282. );
  283. if( INVALID_CREDENTIALS_ERROR(hr) )
  284. BAIL_ON_FAILURE( hr=DB_SEC_E_PERMISSIONDENIED );
  285. if( FAILED(hr) )
  286. BAIL_ON_FAILURE( hr=DB_E_NOTABLE );
  287. error:
  288. if( lpszUserName )
  289. FreeADsMem(lpszUserName);
  290. if( lpszPassword )
  291. {
  292. SecureZeroMemory(lpszPassword, wcslen(lpszPassword) * sizeof(WCHAR));
  293. FreeADsMem(lpszPassword);
  294. }
  295. RRETURN( hr );
  296. }
  297. //+---------------------------------------------------------------------------
  298. //
  299. // Function: GetCredentialsFromIAuthenticate
  300. //
  301. // Synopsis: Gets credentials (user name, password) from IAuthenticate
  302. // interface pointer.
  303. //
  304. // Returns: HRESULT
  305. //----------------------------------------------------------------------------
  306. HRESULT GetCredentialsFromIAuthenticate(
  307. IAuthenticate *pAuthenticate,
  308. CCredentials& refCredentials
  309. )
  310. {
  311. Assert(pAuthenticate);
  312. HRESULT hr = S_OK;
  313. HWND hwnd;
  314. PWSTR pszUsername = NULL;
  315. PWSTR pszPassword = NULL;
  316. if (pAuthenticate->Authenticate(&hwnd, &pszUsername, &pszPassword) != S_OK)
  317. RRETURN(E_INVALIDARG);
  318. if ((hwnd != INVALID_HANDLE_VALUE) &&
  319. (hwnd != 0))
  320. {
  321. //don't know if and how to handle this case
  322. RRETURN(S_OK);
  323. }
  324. else
  325. {
  326. hr = refCredentials.SetUserName(pszUsername);
  327. if (SUCCEEDED(hr))
  328. {
  329. hr = refCredentials.SetPassword(pszPassword);
  330. }
  331. if (pszPassword)
  332. {
  333. SecureZeroMemory(pszPassword, wcslen(pszPassword) * sizeof(WCHAR));
  334. CoTaskMemFree(pszPassword);
  335. }
  336. if (pszUsername)
  337. {
  338. CoTaskMemFree(pszUsername);
  339. }
  340. }
  341. RRETURN(hr);
  342. }
  343. //+---------------------------------------------------------------------------
  344. //
  345. // Function: RemoveWhiteSpaces
  346. //
  347. // Synopsis: Removes the leading and trailing white spaces
  348. //
  349. // Arguments: pszText Text strings from which the leading
  350. // and trailing white spaces are to be
  351. // removed
  352. //
  353. // Returns: LPWSTR Pointer to the modified string
  354. //
  355. // Modifies:
  356. //
  357. // History: 08-15-96 ShankSh Created.
  358. //
  359. //----------------------------------------------------------------------------
  360. LPWSTR
  361. RemoveWhiteSpaces(LPWSTR pszText)
  362. {
  363. LPWSTR pChar;
  364. if( !pszText )
  365. return( pszText );
  366. while(*pszText && iswspace(*pszText))
  367. pszText++;
  368. for(pChar = pszText + wcslen(pszText) - 1; pChar >= pszText; pChar--) {
  369. if( !iswspace(*pChar) )
  370. break;
  371. else
  372. *pChar = L'\0';
  373. }
  374. return pszText;
  375. }
  376. //+---------------------------------------------------------------------------
  377. //
  378. // Function: CanConvertHelper
  379. //
  380. // Synopsis: Helper that tells the consumer if the conversion is supported.
  381. //
  382. // Arguments: DBTYPE wSrcType
  383. // DBTYPE wDstType
  384. //
  385. // Returns: HRESULT
  386. //
  387. // Modifies:
  388. //
  389. // History: 08-15-96 ShankSh Created.
  390. //
  391. //----------------------------------------------------------------------------
  392. //
  393. // Bitmask of supported conversions --
  394. // - src type is index into array,
  395. // - dst type is bit in that ULONG
  396. //
  397. static ULONG s_rgConvertBitmap[] =
  398. {
  399. // 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0.
  400. // 0 8 6 4 2 0 8 6 4 2 0 8 6 4 2 0.
  401. // 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0.
  402. // 1 9 7 5 3 1 9 7 5 3 1 9 7 5 3 1.
  403. // DBTYPE_EMPTY
  404. 0xe3bfd9ff, // 11100011101111111101100111111111
  405. // DBTYPE_NULL
  406. 0x60001002, // 01100000000000000001000000000010
  407. // DBTYPE_I2
  408. 0xdf9fd9ff, // 11011111100111111101100111111111
  409. // DBTYPE_I4
  410. 0xdfdfd9ff, // 11011111110111111101100111111111
  411. // DBTYPE_R4
  412. 0xdf9fd9ff, // 11011111100111111101100111111111
  413. // DBTYPE_R8
  414. 0xdf9fd9ff, // 11011111100111111101100111111111
  415. // DBTYPE_CY
  416. 0xc39fd97f, // 11000011100111111101100101111111
  417. // DBTYPE_DATE
  418. 0x7d9f99bf, // 01111101100111111001100110111111
  419. // DBTYPE_BSTR
  420. 0xffffd9ff, // 11111111111111111101100111111111
  421. // DBTYPE_IDISPATCH
  422. 0x4087fbff, // 01000000100001111111101111111111
  423. // DBTYPE_ERROR
  424. 0x01001500, // 00000001000000000001010100000000
  425. // DBTYPE_BOOL
  426. 0xc39fd9ff, // 11000011100111111101100111111111
  427. // DBTYPE_VARIANT
  428. 0xffffffff, // 11111111111111111111111111111111
  429. // DBTYPE_IUNKNOWN
  430. 0x00003203, // 00000000000000000011001000000011
  431. // DBTYPE_DECIMAL
  432. 0x9f9fd97f, // 10011111100111111101100101111111
  433. // DBTYPE_I1
  434. 0x9f9fd9ff, // 10011111100111111101100111111111
  435. // DBTYPE_UI1
  436. 0xdf9fd9ff, // 11011111100111111101100111111111
  437. // DBTYPE_UI2
  438. 0xdf9fd9ff, // 11011111100111111101100111111111
  439. // DBTYPE_UI4
  440. 0xdfdfd9ff, // 11011111110111111101100111111111
  441. // DBTYPE_I8
  442. 0x619fd13f, // 01100001100111111101000100111111
  443. // DBTYPE_UI8
  444. 0x619fd13f, // 01100001100111111101000100111111
  445. // DBTYPE_GUID
  446. 0x41a01103, // 01000001101000000001000100000011
  447. // DBTYPE_BYTES
  448. 0x41c4110b, // 01000001110001000001000100001011
  449. // DBTYPE_STR
  450. 0xffffd9ff, // 11111111111111111101100111111111
  451. // DBTYPE_WSTR
  452. 0xffffd9ff, // 11111111111111111101100111111111
  453. // DBTYPE_NUMERIC
  454. 0xc39fd97f, // 11000011100111111101100101111111
  455. // DBTYPE_DBDATE
  456. 0x3d801183, // 00111101100000000001000110000011
  457. // DBTYPE_DBTIME
  458. 0x3d801183, // 00111101100000000001000110000011
  459. // DBTYPE_DBTIMESTAMP
  460. 0x3d801183, // 00111101100000000001000110000011
  461. // DBTYPE_FILETIME
  462. 0x7d981183, // 01111101100110000001000110000011
  463. // DBTYPE_PROPVARIANT
  464. 0xffffffff, // 11111111111111111111111111111111
  465. // DBTYPE_VARNUMERIC
  466. 0x839fd97f, // 10000011100111111101100101111111
  467. };
  468. static HRESULT IsLegalDBtype(DBTYPE);
  469. static LONG IndexDBTYPE(DBTYPE wType);
  470. STDMETHODIMP
  471. CanConvertHelper(
  472. DBTYPE wSrcType,
  473. DBTYPE wDstType,
  474. DBCONVERTFLAGS dwConvertFlags
  475. )
  476. {
  477. //
  478. // Check in-params and NULL out-params in case of error
  479. //
  480. if( (dwConvertFlags &
  481. ~(DBCONVERTFLAGS_ISLONG |
  482. DBCONVERTFLAGS_ISFIXEDLENGTH |
  483. DBCONVERTFLAGS_FROMVARIANT)) != DBCONVERTFLAGS_COLUMN )
  484. RRETURN( DB_E_BADCONVERTFLAG );
  485. //
  486. // Make sure that we check that the type is a variant if they say so
  487. //
  488. if( dwConvertFlags & DBCONVERTFLAGS_FROMVARIANT ) {
  489. DBTYPE wVtType = wSrcType & VT_TYPEMASK;
  490. // Take out all of the Valid VT_TYPES (36 is VT_RECORD in VC 6)
  491. if( (wVtType > VT_DECIMAL && wVtType < VT_I1) ||
  492. ((wVtType > VT_LPWSTR && wVtType < VT_FILETIME) && wVtType !=36) ||
  493. (wVtType > VT_CLSID) )
  494. RRETURN( DB_E_BADTYPE );
  495. }
  496. //
  497. // Don't allow _ISLONG on fixed-length types
  498. //
  499. if( dwConvertFlags & DBCONVERTFLAGS_ISLONG ) {
  500. switch ( wSrcType & ~(DBTYPE_RESERVED|DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_BYREF) )
  501. {
  502. case DBTYPE_BYTES:
  503. case DBTYPE_STR:
  504. case DBTYPE_WSTR:
  505. case DBTYPE_VARNUMERIC:
  506. break;
  507. default:
  508. RRETURN( DB_E_BADCONVERTFLAG );
  509. }
  510. }
  511. // Check for valid types
  512. if( wSrcType > DBTYPE_DECIMAL )
  513. {
  514. if( FAILED(IsLegalDBtype(wSrcType)) )
  515. RRETURN( S_FALSE );
  516. }
  517. if( wDstType > DBTYPE_DECIMAL )
  518. {
  519. if( FAILED(IsLegalDBtype(wDstType)) )
  520. RRETURN( S_FALSE );
  521. }
  522. // Check for unsupported type modifiers
  523. if( (wSrcType & (DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_RESERVED)) ||
  524. (wDstType & (DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_RESERVED)) )
  525. RRETURN( S_FALSE );
  526. // Handle BYREF destination separately
  527. if( wDstType & DBTYPE_BYREF ) {
  528. // Turn off BYREF bit
  529. wDstType &= ~DBTYPE_BYREF;
  530. // We only allow BYREF destination for variable length types
  531. switch ( wDstType ) {
  532. case DBTYPE_BYTES:
  533. case DBTYPE_STR:
  534. case DBTYPE_WSTR:
  535. case DBTYPE_VARNUMERIC:
  536. break;
  537. default:
  538. // Fixed-length BYREFs are not supported
  539. RRETURN( S_FALSE );
  540. }
  541. }
  542. // Turn off BYREF bit
  543. wSrcType &= ~DBTYPE_BYREF;
  544. // Get the indices for the src and dst types
  545. LONG iSrc = IndexDBTYPE(wSrcType);
  546. ADsAssert(iSrc < NUMELEM(s_rgConvertBitmap)); // better not be larger than our array
  547. LONG iDst = IndexDBTYPE(wDstType);
  548. ADsAssert(iDst < (sizeof(ULONG) * 8) ); // or the number of bits in a ULONG
  549. // Make sure we have two supported types -- we don't support UDT
  550. if( iSrc < 0 || iDst < 0 )
  551. RRETURN( S_FALSE );
  552. // And do the lookup -- bit will be set if conversion supported
  553. if( s_rgConvertBitmap[iSrc] & (1 << iDst) )
  554. RRETURN( S_OK );
  555. // No bit, no support
  556. RRETURN( S_FALSE );
  557. }
  558. HRESULT IsLegalDBtype(DBTYPE dbtype)
  559. {
  560. // NOTE: optimized for speed, rather than for maintainablity
  561. if( dbtype & (DBTYPE_VECTOR|DBTYPE_BYREF|DBTYPE_ARRAY|DBTYPE_RESERVED) )
  562. dbtype &= ~(DBTYPE_VECTOR|DBTYPE_BYREF|DBTYPE_ARRAY|DBTYPE_RESERVED);
  563. if( (dbtype >= DBTYPE_EMPTY && dbtype <= DBTYPE_DECIMAL) ||
  564. (dbtype >= DBTYPE_I1 && dbtype <= DBTYPE_UI8) ||
  565. dbtype == DBTYPE_GUID ||
  566. (dbtype >= DBTYPE_BYTES && dbtype <= DBTYPE_DBTIMESTAMP) ||
  567. (dbtype >= DBTYPE_FILETIME && dbtype <= DBTYPE_VARNUMERIC) )
  568. RRETURN( S_OK );
  569. RRETURN( DB_E_BADBINDINFO );
  570. }
  571. LONG IndexDBTYPE(DBTYPE wType)
  572. {
  573. switch ( wType ) {
  574. case DBTYPE_EMPTY: // 0
  575. case DBTYPE_NULL: // 1
  576. case DBTYPE_I2: // 2
  577. case DBTYPE_I4: // 3
  578. case DBTYPE_R4: // 4
  579. case DBTYPE_R8: // 5
  580. case DBTYPE_CY: // 6
  581. case DBTYPE_DATE: // 7
  582. case DBTYPE_BSTR: // 8
  583. case DBTYPE_IDISPATCH: // 9
  584. case DBTYPE_ERROR: // 10
  585. case DBTYPE_BOOL: // 11
  586. case DBTYPE_VARIANT: // 12
  587. case DBTYPE_IUNKNOWN: // 13
  588. case DBTYPE_DECIMAL: // 14
  589. // 0 - 14
  590. return (ULONG)wType;
  591. case DBTYPE_I1: // 16
  592. case DBTYPE_UI1: // 17
  593. case DBTYPE_UI2: // 18
  594. case DBTYPE_UI4: // 19
  595. case DBTYPE_I8: // 20
  596. case DBTYPE_UI8: // 21
  597. // 15 - 20
  598. return (ULONG)(wType - 1);
  599. case DBTYPE_GUID: // 72
  600. // 21
  601. return 21;
  602. case DBTYPE_BYTES: // 128
  603. case DBTYPE_STR: // 129
  604. case DBTYPE_WSTR: // 130
  605. case DBTYPE_NUMERIC: // 131
  606. // 22 - 25
  607. return (ULONG)(wType - 106);
  608. case DBTYPE_DBDATE: // 133
  609. case DBTYPE_DBTIME: // 134
  610. case DBTYPE_DBTIMESTAMP:// 135
  611. // 26 - 28
  612. return (ULONG)(wType - 107);
  613. case DBTYPE_FILETIME: // 64
  614. // 29
  615. return wType - 35;
  616. case DBTYPE_PROPVARIANT:// 138
  617. case DBTYPE_VARNUMERIC: // 139
  618. // 30 - 31
  619. return (ULONG)(wType - 108);
  620. }
  621. // No match
  622. return -1;
  623. }
  624. BYTE SetPrecision(DBTYPE dbType)
  625. {
  626. switch(dbType)
  627. {
  628. case DBTYPE_I1:
  629. case DBTYPE_UI1:
  630. return 3;
  631. case DBTYPE_I2:
  632. case DBTYPE_UI2:
  633. return 5;
  634. case DBTYPE_I4:
  635. case DBTYPE_UI4:
  636. return 10;
  637. case DBTYPE_I8:
  638. return 19;
  639. case DBTYPE_UI8:
  640. return 20;
  641. case DBTYPE_R4:
  642. return 7;
  643. case DBTYPE_R8:
  644. return 15;
  645. case DBTYPE_CY:
  646. return 19;
  647. case DBTYPE_DECIMAL:
  648. return 29;
  649. case DBTYPE_NUMERIC:
  650. return 39;
  651. case DBTYPE_VARNUMERIC:
  652. return 255;
  653. default:
  654. return ((BYTE) (~0));
  655. }
  656. }