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.

2393 lines
46 KiB

  1. #include "nwcompat.hxx"
  2. #pragma hdrstop
  3. FILTERS Filters[] = {
  4. {L"computer", NWCOMPAT_COMPUTER_ID},
  5. {L"user", NWCOMPAT_USER_ID},
  6. {L"group", NWCOMPAT_GROUP_ID},
  7. {L"service", NWCOMPAT_SERVICE_ID},
  8. {L"printqueue", NWCOMPAT_PRINTER_ID},
  9. {L"fileshare", NWCOMPAT_FILESHARE_ID},
  10. {L"class", NWCOMPAT_CLASS_ID},
  11. {L"syntax", NWCOMPAT_SYNTAX_ID},
  12. {L"property", NWCOMPAT_PROPERTY_ID}
  13. };
  14. #define MAX_FILTERS (sizeof(Filters)/sizeof(FILTERS))
  15. HRESULT
  16. CreatePropEntry(
  17. LPWSTR szPropName,
  18. ADSTYPE dwADsType,
  19. VARIANT varData,
  20. REFIID riid,
  21. LPVOID * ppDispatch
  22. );
  23. PFILTERS gpFilters = Filters;
  24. DWORD gdwMaxFilters = MAX_FILTERS;
  25. extern WCHAR * szProviderName;
  26. //+------------------------------------------------------------------------
  27. //
  28. // Class: Common
  29. //
  30. // Purpose: Contains NWCOMPAT routines and properties that are common to
  31. // all NWCOMPAT objects. NWCOMPAT objects get the routines and
  32. // properties through C++ inheritance.
  33. //
  34. //-------------------------------------------------------------------------
  35. HRESULT
  36. MakeUncName(
  37. LPWSTR szSrcBuffer,
  38. LPWSTR szTargBuffer
  39. )
  40. {
  41. ADsAssert(szSrcBuffer && *szSrcBuffer);
  42. wcscpy(szTargBuffer, L"\\\\");
  43. wcscat(szTargBuffer, szSrcBuffer);
  44. RRETURN(S_OK);
  45. }
  46. HRESULT
  47. ValidateOutParameter(
  48. BSTR * retval
  49. )
  50. {
  51. if (!retval) {
  52. RRETURN(E_ADS_BAD_PARAMETER);
  53. }
  54. RRETURN(S_OK);
  55. }
  56. HRESULT
  57. BuildADsPath(
  58. BSTR Parent,
  59. BSTR Name,
  60. BSTR *pADsPath
  61. )
  62. {
  63. WCHAR ADsPath[MAX_PATH];
  64. WCHAR ProviderName[MAX_PATH];
  65. HRESULT hr = S_OK;
  66. LPWSTR pszDisplayName = NULL;
  67. //
  68. // We will assert if bad parameters are passed to us.
  69. // This is because this should never be the case. This
  70. // is an internal call
  71. //
  72. ADsAssert(Parent && Name);
  73. ADsAssert(pADsPath);
  74. hr = GetDisplayName(
  75. Name,
  76. &pszDisplayName
  77. );
  78. BAIL_ON_FAILURE(hr);
  79. //
  80. // Special case the Namespace object; if
  81. // the parent is L"ADs:", then Name = ADsPath
  82. //
  83. if (!_wcsicmp(Parent, L"ADs:")) {
  84. hr = ADsAllocString(Name, pADsPath);
  85. BAIL_ON_FAILURE(hr);
  86. goto cleanup;
  87. }
  88. //
  89. // The rest of the cases we expect valid data,
  90. // Path, Parent and Name are read-only, the end-user
  91. // cannot modify this data
  92. //
  93. //
  94. // For the first object, the domain object we do not add
  95. // the first backslash; so we examine that the parent is
  96. // L"NWCOMPAT:" and skip the slash otherwise we start with
  97. // the slash
  98. //
  99. wsprintf(ProviderName, L"%s:", szProviderName);
  100. wcscpy(ADsPath, Parent);
  101. if (_wcsicmp(ADsPath, ProviderName)) {
  102. wcscat(ADsPath, L"/");
  103. }
  104. else {
  105. wcscat(ADsPath, L"//");
  106. }
  107. wcscat(ADsPath, Name);
  108. hr = ADsAllocString(ADsPath, pADsPath);
  109. cleanup:
  110. error:
  111. if (pszDisplayName) {
  112. FreeADsMem(pszDisplayName);
  113. }
  114. RRETURN(hr);
  115. }
  116. HRESULT
  117. BuildSchemaPath(
  118. BSTR Parent,
  119. BSTR Name,
  120. BSTR Schema,
  121. BSTR *pSchemaPath
  122. )
  123. {
  124. WCHAR SchemaPath[MAX_PATH];
  125. WCHAR ProviderName[MAX_PATH];
  126. HRESULT hr = S_OK;
  127. long i;
  128. OBJECTINFO ObjectInfo;
  129. POBJECTINFO pObjectInfo = &ObjectInfo;
  130. CLexer Lexer(Parent);
  131. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  132. //
  133. // We will assert if bad parameters are passed to us.
  134. // This is because this should never be the case. This
  135. // is an internal call
  136. //
  137. ADsAssert(Parent);
  138. ADsAssert(pSchemaPath);
  139. //
  140. // If no schema name is passed in, then there is no schema path
  141. //
  142. if ( Schema == NULL || *Schema == 0 ){
  143. RRETURN(ADsAllocString(L"", pSchemaPath));
  144. }
  145. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  146. hr = Object(&Lexer, pObjectInfo);
  147. BAIL_ON_FAILURE(hr);
  148. wsprintf(SchemaPath, L"%s://", szProviderName);
  149. if (!pObjectInfo->NumComponents) {
  150. wcscat(SchemaPath, Name);
  151. }else{
  152. wcscat(SchemaPath, pObjectInfo->DisplayComponentArray[0]);
  153. }
  154. wcscat( SchemaPath, L"/");
  155. wcscat( SchemaPath, SCHEMA_NAME );
  156. wcscat( SchemaPath, L"/");
  157. wcscat( SchemaPath, Schema );
  158. hr = ADsAllocString(SchemaPath, pSchemaPath);
  159. error:
  160. FreeObjectInfo( &ObjectInfo, TRUE );
  161. RRETURN(hr);
  162. }
  163. HRESULT
  164. BuildADsGuid(
  165. REFCLSID clsid,
  166. BSTR *pADsClass
  167. )
  168. {
  169. WCHAR ADsClass[MAX_PATH];
  170. if (!StringFromGUID2(clsid, ADsClass, MAX_PATH)) {
  171. //
  172. // MAX_PATH should be more than enough for the GUID.
  173. //
  174. ADsAssert(!"GUID too big !!!");
  175. RRETURN(E_FAIL);
  176. }
  177. RRETURN(ADsAllocString(ADsClass, pADsClass));
  178. }
  179. HRESULT
  180. BuildObjectInfo(
  181. BSTR ADsParent,
  182. BSTR Name,
  183. POBJECTINFO * ppObjectInfo
  184. )
  185. {
  186. WCHAR szBuffer[MAX_PATH];
  187. HRESULT hr;
  188. POBJECTINFO pObjectInfo = NULL;
  189. wcscpy(szBuffer, ADsParent);
  190. wcscat(szBuffer, L"/");
  191. wcscat(szBuffer, Name);
  192. CLexer Lexer(szBuffer);
  193. pObjectInfo = (POBJECTINFO)AllocADsMem(sizeof(OBJECTINFO));
  194. if (!pObjectInfo) {
  195. hr = E_OUTOFMEMORY;
  196. BAIL_ON_FAILURE(hr);
  197. }
  198. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  199. hr = Object(&Lexer, pObjectInfo);
  200. BAIL_ON_FAILURE(hr);
  201. *ppObjectInfo = pObjectInfo;
  202. RRETURN(hr);
  203. error:
  204. if (pObjectInfo) {
  205. FreeObjectInfo(pObjectInfo);
  206. }
  207. *ppObjectInfo = NULL;
  208. RRETURN(hr);
  209. }
  210. HRESULT
  211. BuildObjectInfo(
  212. BSTR ADsPath,
  213. POBJECTINFO * ppObjectInfo
  214. )
  215. {
  216. HRESULT hr;
  217. POBJECTINFO pObjectInfo = NULL;
  218. CLexer Lexer(ADsPath);
  219. pObjectInfo = (POBJECTINFO)AllocADsMem(sizeof(OBJECTINFO));
  220. if (!pObjectInfo) {
  221. hr = E_OUTOFMEMORY;
  222. BAIL_ON_FAILURE(hr);
  223. }
  224. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  225. hr = Object(&Lexer, pObjectInfo);
  226. BAIL_ON_FAILURE(hr);
  227. *ppObjectInfo = pObjectInfo;
  228. RRETURN(hr);
  229. error:
  230. if (pObjectInfo) {
  231. FreeObjectInfo(pObjectInfo);
  232. }
  233. *ppObjectInfo = NULL;
  234. RRETURN(hr);
  235. }
  236. VOID
  237. FreeObjectInfo(
  238. POBJECTINFO pObjectInfo,
  239. BOOL fStatic
  240. )
  241. {
  242. DWORD i = 0;
  243. if (!pObjectInfo) {
  244. return;
  245. }
  246. FreeADsStr(pObjectInfo->ProviderName);
  247. for (i = 0; i < pObjectInfo->NumComponents; i++ ) {
  248. FreeADsStr(pObjectInfo->ComponentArray[i]);
  249. FreeADsStr(pObjectInfo->DisplayComponentArray[i]);
  250. }
  251. if ( !fStatic ) {
  252. FreeADsMem(pObjectInfo);
  253. }
  254. }
  255. HRESULT
  256. ValidateObject(
  257. DWORD dwObjectType,
  258. POBJECTINFO pObjectInfo,
  259. CCredentials &Credentials
  260. )
  261. {
  262. switch (dwObjectType) {
  263. case NWCOMPAT_USER_ID:
  264. RRETURN(ValidateUserObject(pObjectInfo, Credentials));
  265. case NWCOMPAT_GROUP_ID:
  266. RRETURN(ValidateGroupObject(pObjectInfo, Credentials));
  267. case NWCOMPAT_PRINTER_ID:
  268. RRETURN(ValidatePrinterObject(pObjectInfo));
  269. default:
  270. RRETURN(E_FAIL);
  271. }
  272. }
  273. HRESULT
  274. GetObjectType(
  275. PFILTERS pFilters,
  276. DWORD dwMaxFilters,
  277. BSTR ClassName,
  278. PDWORD pdwObjectType
  279. )
  280. {
  281. DWORD i = 0;
  282. ADsAssert(pdwObjectType);
  283. for (i = 0; i < dwMaxFilters; i++) {
  284. if (!_wcsicmp(ClassName, (pFilters + i)->szObjectName)) {
  285. *pdwObjectType = (pFilters + i)->dwFilterId;
  286. RRETURN(S_OK);
  287. }
  288. }
  289. *pdwObjectType = 0;
  290. RRETURN(E_FAIL);
  291. }
  292. HRESULT
  293. ValidateProvider(
  294. POBJECTINFO pObjectInfo
  295. )
  296. {
  297. //
  298. // The provider name is case-sensitive. This is a restriction that OLE
  299. // has put on us.
  300. //
  301. if (!(wcscmp(pObjectInfo->ProviderName, szProviderName))) {
  302. RRETURN(S_OK);
  303. }
  304. RRETURN(E_FAIL);
  305. }
  306. HRESULT
  307. ConvertSystemTimeToDATE(
  308. SYSTEMTIME Time,
  309. DATE * pdaTime
  310. )
  311. {
  312. FILETIME ft;
  313. BOOL fRetval = FALSE;
  314. USHORT wDosDate;
  315. USHORT wDosTime;
  316. SYSTEMTIME LocalTime;
  317. //
  318. // Get Time-zone specific local time.
  319. //
  320. fRetval = SystemTimeToTzSpecificLocalTime(
  321. NULL,
  322. &Time,
  323. &LocalTime
  324. );
  325. if(!fRetval){
  326. RRETURN(HRESULT_FROM_WIN32(GetLastError()));
  327. }
  328. //
  329. // System Time To File Time.
  330. //
  331. fRetval = SystemTimeToFileTime(&LocalTime,
  332. &ft);
  333. if(!fRetval){
  334. RRETURN(HRESULT_FROM_WIN32(GetLastError()));
  335. }
  336. //
  337. // File Time to DosDateTime.
  338. //
  339. fRetval = FileTimeToDosDateTime(&ft,
  340. &wDosDate,
  341. &wDosTime);
  342. if(!fRetval){
  343. RRETURN(HRESULT_FROM_WIN32(GetLastError()));
  344. }
  345. //
  346. // DosDateTime to VariantTime.
  347. //
  348. fRetval = DosDateTimeToVariantTime(wDosDate,
  349. wDosTime,
  350. pdaTime );
  351. if(!fRetval){
  352. RRETURN(HRESULT_FROM_WIN32(GetLastError()));
  353. }
  354. RRETURN(S_OK);
  355. }
  356. HRESULT
  357. ConvertDATEToSYSTEMTIME(
  358. DATE daDate,
  359. SYSTEMTIME *pSysTime
  360. )
  361. {
  362. HRESULT hr;
  363. FILETIME ft;
  364. FILETIME lft; //local file time
  365. BOOL fRetval = FALSE;
  366. SYSTEMTIME LocalTime;
  367. USHORT wDosDate;
  368. USHORT wDosTime;
  369. fRetval = VariantTimeToDosDateTime(daDate,
  370. &wDosDate,
  371. &wDosTime );
  372. if(!fRetval){
  373. hr = HRESULT_FROM_WIN32(GetLastError());
  374. RRETURN(hr);
  375. }
  376. fRetval = DosDateTimeToFileTime(wDosDate,
  377. wDosTime,
  378. &lft);
  379. if(!fRetval){
  380. hr = HRESULT_FROM_WIN32(GetLastError());
  381. RRETURN(hr);
  382. }
  383. //
  384. // convert local file time to filetime
  385. //
  386. fRetval = LocalFileTimeToFileTime(&lft,
  387. &ft );
  388. if(!fRetval){
  389. hr = HRESULT_FROM_WIN32(GetLastError());
  390. RRETURN(hr);
  391. }
  392. fRetval = FileTimeToSystemTime(&ft,
  393. pSysTime );
  394. if(!fRetval){
  395. hr = HRESULT_FROM_WIN32(GetLastError());
  396. RRETURN(hr);
  397. }
  398. RRETURN(S_OK);
  399. }
  400. HRESULT
  401. ConvertDATEToDWORD(
  402. DATE daDate,
  403. DWORD *pdwDate
  404. )
  405. {
  406. BOOL fBool = TRUE;
  407. WORD wDOSDate = 0;
  408. WORD wDOSTime = 0;
  409. WORD wHour = 0;
  410. WORD wMinute = 0;
  411. //
  412. // Break up Variant date.
  413. //
  414. fBool = VariantTimeToDosDateTime(
  415. (DOUBLE) daDate,
  416. &wDOSDate,
  417. &wDOSTime
  418. );
  419. if (fBool == FALSE) {
  420. goto error;
  421. }
  422. //
  423. // Convert DOS time into DWORD time which expresses time as the number of
  424. // minutes elapsed since mid-night.
  425. //
  426. wHour = wDOSTime >> 11;
  427. wMinute = (wDOSTime >> 5) - (wHour << 6);
  428. //
  429. // Return.
  430. //
  431. *pdwDate = wHour * 60 + wMinute;
  432. error:
  433. RRETURN(S_OK);
  434. }
  435. HRESULT
  436. ConvertDWORDToDATE(
  437. DWORD dwTime,
  438. DATE * pdaTime
  439. )
  440. {
  441. BOOL fBool = TRUE;
  442. DOUBLE vTime = 0;
  443. SYSTEMTIME SysTime = {1980,1,0,1,0,0,0,0};
  444. SYSTEMTIME LocalTime = {1980,1,0,1,0,0,0,0};
  445. WORD wDOSDate = 0;
  446. WORD wDOSTime = 0;
  447. WORD wHour = 0;
  448. WORD wMinute = 0;
  449. WORD wSecond = 0;
  450. //
  451. // Get Hour and Minute from DWORD.
  452. //
  453. SysTime.wHour = (WORD) (dwTime / 60);
  454. SysTime.wMinute = (WORD) (dwTime % 60);
  455. //
  456. // Get Time-zone specific local time.
  457. //
  458. fBool = SystemTimeToTzSpecificLocalTime(
  459. NULL,
  460. &SysTime,
  461. &LocalTime
  462. );
  463. if (fBool == FALSE) {
  464. RRETURN(HRESULT_FROM_WIN32(GetLastError()));
  465. }
  466. wHour = LocalTime.wHour;
  467. wMinute = LocalTime.wMinute;
  468. wSecond = LocalTime.wSecond;
  469. //
  470. // Set a dummy date.
  471. //
  472. wDOSDate = DATE_1980_JAN_1;
  473. //
  474. // Shift data to correct bit as required by the DOS date & time format.
  475. //
  476. wHour = wHour << 11;
  477. wMinute = wMinute << 5;
  478. //
  479. // Put them in DOS format.
  480. //
  481. wDOSTime = wHour | wMinute | wSecond;
  482. //
  483. // Convert into VariantTime.
  484. //
  485. fBool = DosDateTimeToVariantTime(
  486. wDOSDate,
  487. wDOSTime,
  488. &vTime
  489. );
  490. //
  491. // Return.
  492. //
  493. if (fBool == TRUE) {
  494. *pdaTime = vTime;
  495. RRETURN(S_OK);
  496. }
  497. else {
  498. RRETURN(E_FAIL);
  499. }
  500. }
  501. HRESULT
  502. ConvertNW312DateToSYSTEMTIME(
  503. BYTE byDateTime[],
  504. SYSTEMTIME *pSysTime
  505. )
  506. {
  507. HRESULT hr = S_OK;
  508. WORD wYear;
  509. //
  510. // Subtract 80 from wYear for NWApiMakeSYSTEMTIME.
  511. //
  512. wYear = (WORD)byDateTime[0];
  513. if (wYear != 0) {
  514. wYear -= 80;
  515. }
  516. //
  517. // Convert into SYSTEMTIME.
  518. //
  519. hr = NWApiMakeSYSTEMTIME(
  520. pSysTime,
  521. (WORD)byDateTime[2],
  522. (WORD)byDateTime[1],
  523. wYear,
  524. 0,0,0
  525. );
  526. RRETURN(hr);
  527. }
  528. HRESULT
  529. DelimitedStringToVariant(
  530. LPTSTR pszString,
  531. VARIANT *pvar,
  532. TCHAR Delimiter
  533. )
  534. {
  535. SAFEARRAYBOUND sabound[1];
  536. DWORD dwElements;
  537. LPTSTR pszCurrPos = pszString;
  538. LPTSTR *rgszStrings = NULL;
  539. SAFEARRAY *psa = NULL;
  540. VARIANT v;
  541. HRESULT hr = S_OK;
  542. LONG i;
  543. //
  544. // This function converts a delimited string into a VARIANT of
  545. // safe arrays.
  546. //
  547. // Assumption: a valid string are passed to this function
  548. // note that the input string gets destroyed in the process
  549. //
  550. //
  551. // scan the delimited string once to find out the dimension
  552. //
  553. //
  554. // in order to filter for NULL input values do a sanity check for
  555. // length of input string.
  556. //
  557. //
  558. // take care of null case first for sanity's sake
  559. //
  560. if (!pszString){
  561. sabound[0].cElements = 0;
  562. sabound[0].lLbound = 0;
  563. psa = SafeArrayCreate(VT_VARIANT, 1, sabound);
  564. if (psa == NULL){
  565. hr = E_OUTOFMEMORY;
  566. goto error;
  567. }
  568. VariantInit(pvar);
  569. V_VT(pvar) = VT_ARRAY|VT_VARIANT;
  570. V_ARRAY(pvar) = psa;
  571. goto error;
  572. }
  573. dwElements = (wcslen(pszString) == 0) ? 0: 1 ;
  574. while(!(*pszCurrPos == TEXT('\0'))){
  575. if(*pszCurrPos == Delimiter){
  576. dwElements++;
  577. *pszCurrPos = TEXT('\0');
  578. }
  579. pszCurrPos++;
  580. }
  581. rgszStrings = (LPTSTR *)AllocADsMem(sizeof(LPTSTR)*dwElements);
  582. if(!rgszStrings){
  583. hr = E_OUTOFMEMORY;
  584. goto error;
  585. }
  586. //
  587. // scan string again and put the appropriate pointers
  588. //
  589. pszCurrPos = pszString;
  590. if(rgszStrings != NULL){
  591. (*rgszStrings) = pszCurrPos;
  592. }
  593. i = 1;
  594. while(i < (LONG)dwElements){
  595. if(*pszCurrPos == TEXT('\0')){
  596. *(rgszStrings+i) = ++pszCurrPos;
  597. i++;
  598. }
  599. pszCurrPos++;
  600. }
  601. //
  602. // create the safearray
  603. //
  604. sabound[0].cElements = dwElements;
  605. sabound[0].lLbound = 0;
  606. psa = SafeArrayCreate(VT_VARIANT, 1, sabound);
  607. if (psa == NULL){
  608. hr = E_OUTOFMEMORY;
  609. goto error;
  610. }
  611. for(i=0; i<(LONG)dwElements; i++){
  612. VariantInit(&v);
  613. V_VT(&v) = VT_BSTR;
  614. hr = ADsAllocString(*(rgszStrings+i), &(V_BSTR(&v)));
  615. BAIL_ON_FAILURE(hr);
  616. //
  617. // Stick the caller provided data into the end of the SafeArray
  618. //
  619. hr = SafeArrayPutElement(psa, &i, &v);
  620. VariantClear(&v);
  621. BAIL_ON_FAILURE(hr);
  622. }
  623. //
  624. // convert this safearray into a VARIANT
  625. //
  626. VariantInit(pvar);
  627. V_VT(pvar) = VT_ARRAY|VT_VARIANT;
  628. V_ARRAY(pvar) = psa;
  629. error:
  630. if(rgszStrings && dwElements != 0){
  631. FreeADsMem(rgszStrings);
  632. }
  633. RRETURN(hr);
  634. }
  635. HRESULT
  636. VariantToDelimitedString(
  637. VARIANT var,
  638. LPTSTR *ppszString,
  639. TCHAR Delimiter
  640. )
  641. {
  642. LONG lIndices;
  643. ULONG cElements;
  644. ULONG ulRequiredLength=0;
  645. SAFEARRAY *psa = NULL;
  646. BSTR bstrElement = NULL;
  647. VARIANT vElement;
  648. LPTSTR pszCurrPos = NULL;
  649. HRESULT hr = S_OK;
  650. ULONG i;
  651. //
  652. // converts the safearray in a variant to a delimited string
  653. //
  654. *ppszString = NULL;
  655. if(!(V_VT(&var) == (VT_VARIANT|VT_ARRAY))) {
  656. RRETURN(E_FAIL);
  657. }
  658. psa = V_ARRAY(&var);
  659. //
  660. // Check that there is only one dimension in this array
  661. //
  662. if (psa->cDims != 1) {
  663. hr = E_FAIL;
  664. BAIL_ON_FAILURE(hr);
  665. }
  666. //
  667. // Check that there is atleast one element in this array
  668. //
  669. cElements = psa->rgsabound[0].cElements;
  670. if (cElements == 0){
  671. hr = E_FAIL;
  672. goto error;
  673. }
  674. //
  675. // We know that this is a valid single dimension array
  676. //
  677. lIndices= 0;
  678. for(i=0; i< cElements; i++){
  679. lIndices = i;
  680. hr = SafeArrayGetElement(psa, &lIndices, &vElement);
  681. BAIL_ON_FAILURE(hr);
  682. if(!(V_VT(&vElement) == VT_BSTR)){
  683. RRETURN(E_FAIL);
  684. }
  685. //
  686. // unpack the BSTR in the VARIANT
  687. //
  688. hr = ADsAllocString( vElement.bstrVal, &bstrElement);
  689. BAIL_ON_FAILURE(hr);
  690. ulRequiredLength+= wcslen(bstrElement)+1;
  691. }
  692. ulRequiredLength +=2;
  693. *ppszString = (LPTSTR)AllocADsMem( ulRequiredLength*sizeof(TCHAR));
  694. if(*ppszString == NULL){
  695. hr = E_OUTOFMEMORY;
  696. goto error;
  697. }
  698. lIndices= 0;
  699. pszCurrPos = *ppszString;
  700. for(i=0; i< cElements; i++){
  701. lIndices = i;
  702. hr = SafeArrayGetElement(psa, &lIndices, &vElement);
  703. BAIL_ON_FAILURE(hr);
  704. if(!(V_VT(&vElement) == VT_BSTR)){
  705. RRETURN(E_FAIL);
  706. }
  707. //
  708. // unpack the BSTR in the VARIANT
  709. //
  710. hr = ADsAllocString( vElement.bstrVal, &bstrElement);
  711. wcscpy(pszCurrPos, (LPTSTR)bstrElement);
  712. pszCurrPos += wcslen(bstrElement);
  713. if(i < cElements-1){
  714. *pszCurrPos = Delimiter;
  715. }
  716. pszCurrPos++;
  717. ADsFreeString(bstrElement);
  718. }
  719. *pszCurrPos = L'\0';
  720. RRETURN(S_OK);
  721. error:
  722. RRETURN(hr);
  723. }
  724. HRESULT
  725. VariantToNulledString(
  726. VARIANT var,
  727. LPTSTR *ppszString
  728. )
  729. {
  730. LONG lIndices;
  731. ULONG cElements;
  732. ULONG ulRequiredLength=0;
  733. SAFEARRAY *psa = NULL;
  734. BSTR bstrElement = NULL;
  735. VARIANT vElement;
  736. LPTSTR szCurrPos = NULL;
  737. HRESULT hr = S_OK;
  738. ULONG i;
  739. //
  740. //converts the safearray in a variant to a double nulled string
  741. //
  742. *ppszString = NULL;
  743. if (!(V_VT(&var) == (VT_VARIANT|VT_ARRAY))) {
  744. RRETURN(E_FAIL);
  745. }
  746. psa = V_ARRAY(&var);
  747. //
  748. // Check that there is only one dimension in this array
  749. //
  750. if (psa->cDims != 1) {
  751. hr = E_FAIL;
  752. BAIL_ON_FAILURE(hr);
  753. }
  754. //
  755. // Check that there is atleast one element in this array
  756. //
  757. cElements = psa->rgsabound[0].cElements;
  758. if (cElements == 0){
  759. hr = E_FAIL;
  760. BAIL_ON_FAILURE(hr);
  761. }
  762. //
  763. // We know that this is a valid single dimension array
  764. //
  765. lIndices= 0;
  766. for(i=0; i< cElements; i++){
  767. lIndices = i;
  768. hr = SafeArrayGetElement(psa, &lIndices, &vElement);
  769. BAIL_ON_FAILURE(hr);
  770. if(!(V_VT(&vElement) == VT_BSTR)){
  771. RRETURN(E_FAIL);
  772. }
  773. //
  774. // unpack the BSTR in the VARIANT
  775. //
  776. hr = ADsAllocString( vElement.bstrVal, &bstrElement);
  777. BAIL_ON_FAILURE(hr);
  778. ulRequiredLength+= wcslen(bstrElement)+1;
  779. ADsFreeString(bstrElement);
  780. }
  781. ulRequiredLength +=2;
  782. *ppszString = (LPTSTR)AllocADsMem( ulRequiredLength*sizeof(TCHAR));
  783. if(*ppszString == NULL){
  784. hr = E_OUTOFMEMORY;
  785. goto error;
  786. }
  787. lIndices= 0;
  788. szCurrPos = *ppszString;
  789. for(i=0; i< cElements; i++){
  790. lIndices = i;
  791. hr = SafeArrayGetElement(psa, &lIndices, &vElement);
  792. BAIL_ON_FAILURE(hr);
  793. if(!(V_VT(&vElement) == VT_BSTR)){
  794. RRETURN(E_FAIL);
  795. }
  796. //
  797. // unpack the BSTR in the VARIANT
  798. //
  799. hr = ADsAllocString( vElement.bstrVal, &bstrElement);
  800. wcscpy(szCurrPos, (LPTSTR)bstrElement);
  801. szCurrPos += wcslen(bstrElement)+1;
  802. ADsFreeString(bstrElement);
  803. }
  804. *szCurrPos = L'\0';
  805. RRETURN(S_OK);
  806. error:
  807. RRETURN(hr);
  808. }
  809. HRESULT
  810. NulledStringToVariant(
  811. LPTSTR pszString,
  812. VARIANT *pvar
  813. )
  814. {
  815. SAFEARRAYBOUND sabound[1];
  816. DWORD dwElements = 0;
  817. LPTSTR pszCurrPos = pszString;
  818. BOOL foundNULL = FALSE;
  819. LPTSTR *rgszStrings = NULL;
  820. SAFEARRAY *psa = NULL;
  821. VARIANT v;
  822. HRESULT hr = S_OK;
  823. LONG i;
  824. //
  825. // This function converts a double nulled string into a VARIANT of
  826. // safe arrays.
  827. //
  828. // Assumption: Valid double nulled strings are passed to this function
  829. //
  830. //
  831. // scan the double nulled string once to find out the dimension
  832. //
  833. while(!(*pszCurrPos == L'\0' && foundNULL)){
  834. if(*pszCurrPos == L'\0'){
  835. dwElements++;
  836. foundNULL = TRUE;
  837. }
  838. else{
  839. foundNULL = FALSE;
  840. }
  841. pszCurrPos++;
  842. }
  843. if(dwElements){
  844. rgszStrings = (LPTSTR *)AllocADsMem(sizeof(LPTSTR)*dwElements);
  845. }
  846. //
  847. // scan string again and put the appropriate pointers
  848. //
  849. pszCurrPos = pszString;
  850. if(rgszStrings != NULL){
  851. (*rgszStrings) = pszCurrPos;
  852. }
  853. foundNULL = FALSE;
  854. i = 1;
  855. while(i < (LONG)dwElements){
  856. if(foundNULL){
  857. *(rgszStrings+i) = pszCurrPos;
  858. i++;
  859. }
  860. if(*pszCurrPos == L'\0'){
  861. foundNULL = TRUE;
  862. }
  863. else{
  864. foundNULL = FALSE;
  865. }
  866. pszCurrPos++;
  867. }
  868. //
  869. // create the safearray
  870. //
  871. sabound[0].cElements = dwElements;
  872. sabound[0].lLbound = 0;
  873. psa = SafeArrayCreate(VT_VARIANT, 1, sabound);
  874. if (psa == NULL){
  875. hr = E_OUTOFMEMORY;
  876. goto error;
  877. }
  878. for(i=0; i<(LONG)dwElements; i++){
  879. VariantInit(&v);
  880. V_VT(&v) = VT_BSTR;
  881. hr = ADsAllocString(*(rgszStrings+i), &(V_BSTR(&v)));
  882. BAIL_ON_FAILURE(hr);
  883. //
  884. // Stick the caller provided data into the end of the SafeArray
  885. //
  886. hr = SafeArrayPutElement(psa, &i, &v);
  887. VariantClear(&v);
  888. BAIL_ON_FAILURE(hr);
  889. }
  890. //
  891. // convert this safearray into a VARIANT
  892. //
  893. VariantInit(pvar);
  894. V_VT(pvar) = VT_ARRAY|VT_VARIANT;
  895. V_ARRAY(pvar) = psa;
  896. error:
  897. if(rgszStrings){
  898. FreeADsMem(rgszStrings);
  899. }
  900. RRETURN(hr);
  901. }
  902. STDMETHODIMP
  903. GenericGetPropertyManager(
  904. CPropertyCache * pPropertyCache,
  905. THIS_ BSTR bstrName,
  906. VARIANT FAR* pvProp
  907. )
  908. {
  909. HRESULT hr = S_OK;
  910. DWORD dwSyntaxId;
  911. DWORD dwNumValues;
  912. DWORD dwInfoLevel;
  913. LPNTOBJECT pNtSrcObjects = NULL;
  914. //
  915. // retrieve data object from cache; if one exists
  916. hr = pPropertyCache->getproperty(
  917. bstrName,
  918. &dwSyntaxId,
  919. &dwNumValues,
  920. &pNtSrcObjects
  921. );
  922. BAIL_ON_FAILURE(hr);
  923. //
  924. // translate the Nt objects to variants
  925. //
  926. if (dwNumValues == 1) {
  927. hr = NtTypeToVarTypeCopy(
  928. pNtSrcObjects,
  929. pvProp
  930. );
  931. }else {
  932. hr = NtTypeToVarTypeCopyConstruct(
  933. pNtSrcObjects,
  934. dwNumValues,
  935. pvProp
  936. );
  937. }
  938. BAIL_ON_FAILURE(hr);
  939. error:
  940. if (pNtSrcObjects) {
  941. NTTypeFreeNTObjects(
  942. pNtSrcObjects,
  943. dwNumValues
  944. );
  945. }
  946. RRETURN(hr);
  947. }
  948. STDMETHODIMP
  949. GenericPutPropertyManager(
  950. CPropertyCache * pPropertyCache,
  951. PPROPERTYINFO pSchemaProps,
  952. DWORD dwSchemaPropSize,
  953. THIS_ BSTR bstrName,
  954. VARIANT vProp
  955. )
  956. {
  957. HRESULT hr = S_OK;
  958. DWORD dwSyntaxId = 0;
  959. DWORD dwIndex = 0;
  960. LPNTOBJECT pNtDestObjects = NULL;
  961. //
  962. // Issue: How do we handle multi-valued support
  963. //
  964. DWORD dwNumValues = 1;
  965. //
  966. // check if this is a legal property for this object,
  967. //
  968. //
  969. hr = ValidatePropertyinSchemaClass(
  970. pSchemaProps,
  971. dwSchemaPropSize,
  972. bstrName,
  973. &dwSyntaxId
  974. );
  975. BAIL_ON_FAILURE(hr);
  976. //
  977. // check if this is a writeable property
  978. //
  979. hr = ValidateIfWriteableProperty(
  980. pSchemaProps,
  981. dwSchemaPropSize,
  982. bstrName
  983. );
  984. BAIL_ON_FAILURE(hr);
  985. //
  986. // check if the variant maps to the syntax of this property
  987. //
  988. hr = VarTypeToNtTypeCopyConstruct(
  989. dwSyntaxId,
  990. &vProp,
  991. 1,
  992. &pNtDestObjects
  993. );
  994. BAIL_ON_FAILURE(hr);
  995. //
  996. // Find this property in the cache
  997. //
  998. hr = pPropertyCache->findproperty(
  999. bstrName,
  1000. &dwIndex
  1001. );
  1002. //
  1003. // If this property does not exist in the
  1004. // cache, add this property into the cache.
  1005. //
  1006. if (FAILED(hr)) {
  1007. hr = pPropertyCache->addproperty(
  1008. bstrName,
  1009. dwSyntaxId,
  1010. dwNumValues,
  1011. pNtDestObjects
  1012. );
  1013. //
  1014. // If the operation fails for some reason
  1015. // move on to the next property
  1016. //
  1017. BAIL_ON_FAILURE(hr);
  1018. }
  1019. //
  1020. // Now update the property in the cache
  1021. // Should use putproperty, not updateproperty -> unmarshalling from svr only
  1022. //
  1023. hr = pPropertyCache->putproperty(
  1024. bstrName,
  1025. dwSyntaxId,
  1026. dwNumValues,
  1027. pNtDestObjects
  1028. );
  1029. BAIL_ON_FAILURE(hr);
  1030. error:
  1031. if (pNtDestObjects) {
  1032. NTTypeFreeNTObjects(
  1033. pNtDestObjects,
  1034. dwNumValues
  1035. );
  1036. }
  1037. RRETURN(hr);
  1038. }
  1039. HRESULT
  1040. BuildPrinterNameFromADsPath(
  1041. LPWSTR pszADsParent,
  1042. LPWSTR pszPrinterName,
  1043. LPWSTR pszUncPrinterName
  1044. )
  1045. {
  1046. POBJECTINFO pObjectInfo = NULL;
  1047. CLexer Lexer(pszADsParent);
  1048. HRESULT hr;
  1049. pObjectInfo = (POBJECTINFO)AllocADsMem(sizeof(OBJECTINFO));
  1050. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  1051. hr = Object(&Lexer, pObjectInfo);
  1052. BAIL_ON_FAILURE(hr);
  1053. wsprintf(
  1054. pszUncPrinterName,
  1055. L"\\\\%s\\%s",
  1056. pObjectInfo->ComponentArray[0],
  1057. pszPrinterName
  1058. );
  1059. error:
  1060. if(pObjectInfo){
  1061. FreeObjectInfo(pObjectInfo);
  1062. }
  1063. RRETURN(hr);
  1064. }
  1065. STDMETHODIMP
  1066. GenericGetExPropertyManager(
  1067. DWORD dwObjectState,
  1068. CPropertyCache * pPropertyCache,
  1069. THIS_ BSTR bstrName,
  1070. VARIANT FAR* pvProp
  1071. )
  1072. {
  1073. HRESULT hr = S_OK;
  1074. DWORD dwSyntaxId;
  1075. DWORD dwNumValues;
  1076. LPNTOBJECT pNtSrcObjects = NULL;
  1077. //
  1078. // retrieve data object from cache; if one exis
  1079. //
  1080. if (dwObjectState == ADS_OBJECT_UNBOUND) {
  1081. hr = pPropertyCache->unboundgetproperty(
  1082. bstrName,
  1083. &dwSyntaxId,
  1084. &dwNumValues,
  1085. &pNtSrcObjects
  1086. );
  1087. BAIL_ON_FAILURE(hr);
  1088. }else {
  1089. hr = pPropertyCache->getproperty(
  1090. bstrName,
  1091. &dwSyntaxId,
  1092. &dwNumValues,
  1093. &pNtSrcObjects
  1094. );
  1095. BAIL_ON_FAILURE(hr);
  1096. }
  1097. //
  1098. // translate the Nds objects to variants
  1099. //
  1100. hr = NtTypeToVarTypeCopyConstruct(
  1101. pNtSrcObjects,
  1102. dwNumValues,
  1103. pvProp
  1104. );
  1105. BAIL_ON_FAILURE(hr);
  1106. error:
  1107. if (pNtSrcObjects) {
  1108. NTTypeFreeNTObjects(
  1109. pNtSrcObjects,
  1110. dwNumValues
  1111. );
  1112. }
  1113. RRETURN(hr);
  1114. }
  1115. STDMETHODIMP
  1116. GenericPutExPropertyManager(
  1117. CPropertyCache * pPropertyCache,
  1118. PPROPERTYINFO pSchemaProps,
  1119. DWORD dwSchemaPropSize,
  1120. THIS_ BSTR bstrName,
  1121. VARIANT vProp
  1122. )
  1123. {
  1124. HRESULT hr = S_OK;
  1125. DWORD dwSyntaxId = 0;
  1126. DWORD dwIndex = 0;
  1127. DWORD dwNumValues = 0;
  1128. LPNTOBJECT pNtDestObjects = NULL;
  1129. VARIANT * pVarArray = NULL;
  1130. VARIANT * pvProp = NULL;
  1131. //
  1132. // Issue: How do we handle multi-valued support
  1133. //
  1134. //
  1135. // A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
  1136. // We should dereference a VT_BYREF|VT_VARIANT once and see
  1137. // what's inside.
  1138. //
  1139. pvProp = &vProp;
  1140. if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) {
  1141. pvProp = V_VARIANTREF(&vProp);
  1142. }
  1143. if ((V_VT(pvProp) == (VT_VARIANT|VT_ARRAY)) ||
  1144. (V_VT(&vProp) == (VT_VARIANT|VT_ARRAY|VT_BYREF))) {
  1145. hr = ConvertByRefSafeArrayToVariantArray(
  1146. *pvProp,
  1147. &pVarArray,
  1148. &dwNumValues
  1149. );
  1150. BAIL_ON_FAILURE(hr);
  1151. pvProp = pVarArray;
  1152. }else {
  1153. hr = E_FAIL;
  1154. BAIL_ON_FAILURE(hr);
  1155. }
  1156. //
  1157. // check if this is a legal property for this object,
  1158. //
  1159. //
  1160. hr = ValidatePropertyinSchemaClass(
  1161. pSchemaProps,
  1162. dwSchemaPropSize,
  1163. bstrName,
  1164. &dwSyntaxId
  1165. );
  1166. BAIL_ON_FAILURE(hr);
  1167. //
  1168. // check if this is a writeable property
  1169. //
  1170. hr = ValidateIfWriteableProperty(
  1171. pSchemaProps,
  1172. dwSchemaPropSize,
  1173. bstrName
  1174. );
  1175. BAIL_ON_FAILURE(hr);
  1176. //
  1177. // check if the variant maps to the syntax of this property
  1178. //
  1179. hr = VarTypeToNtTypeCopyConstruct(
  1180. dwSyntaxId,
  1181. pvProp,
  1182. dwNumValues,
  1183. &pNtDestObjects
  1184. );
  1185. BAIL_ON_FAILURE(hr);
  1186. //
  1187. // Find this property in the cache
  1188. //
  1189. hr = pPropertyCache->findproperty(
  1190. bstrName,
  1191. &dwIndex
  1192. );
  1193. //
  1194. // If this property does not exist in the
  1195. // cache, add this property into the cache.
  1196. //
  1197. if (FAILED(hr)) {
  1198. hr = pPropertyCache->addproperty(
  1199. bstrName,
  1200. dwSyntaxId,
  1201. dwNumValues,
  1202. pNtDestObjects
  1203. );
  1204. //
  1205. // If the operation fails for some reason
  1206. // move on to the next property
  1207. //
  1208. BAIL_ON_FAILURE(hr);
  1209. }
  1210. //
  1211. // Now update the property in the cache
  1212. //
  1213. hr = pPropertyCache->putproperty(
  1214. bstrName,
  1215. dwSyntaxId,
  1216. dwNumValues,
  1217. pNtDestObjects
  1218. );
  1219. BAIL_ON_FAILURE(hr);
  1220. error:
  1221. if (pNtDestObjects) {
  1222. NTTypeFreeNTObjects(
  1223. pNtDestObjects,
  1224. dwNumValues
  1225. );
  1226. }
  1227. if (pVarArray) {
  1228. DWORD i = 0;
  1229. for (i = 0; i < dwNumValues; i++) {
  1230. VariantClear(pVarArray + i);
  1231. }
  1232. FreeADsMem(pVarArray);
  1233. }
  1234. RRETURN(hr);
  1235. }
  1236. HRESULT
  1237. GenericPropCountPropertyManager(
  1238. CPropertyCache * pPropertyCache,
  1239. PLONG plCount
  1240. )
  1241. {
  1242. HRESULT hr = E_FAIL;
  1243. if (pPropertyCache) {
  1244. hr = pPropertyCache->get_PropertyCount((PDWORD)plCount);
  1245. }
  1246. RRETURN(hr);
  1247. }
  1248. HRESULT
  1249. GenericNextPropertyManager(
  1250. CPropertyCache * pPropertyCache,
  1251. VARIANT FAR *pVariant
  1252. )
  1253. {
  1254. HRESULT hr = E_FAIL;
  1255. DWORD dwSyntaxId = 0;
  1256. DWORD dwNumValues = 0;
  1257. LPNTOBJECT pNtSrcObjects = NULL;
  1258. VARIANT varData;
  1259. IDispatch * pDispatch = NULL;
  1260. VariantInit(&varData);
  1261. hr = pPropertyCache->unboundgetproperty(
  1262. pPropertyCache->get_CurrentIndex(),
  1263. &dwSyntaxId,
  1264. &dwNumValues,
  1265. &pNtSrcObjects
  1266. );
  1267. BAIL_ON_FAILURE(hr);
  1268. //
  1269. // translate the Nt objects to variants
  1270. //
  1271. hr = ConvertNtValuesToVariant(
  1272. pPropertyCache->get_CurrentPropName(),
  1273. pNtSrcObjects,
  1274. dwNumValues,
  1275. pVariant
  1276. );
  1277. BAIL_ON_FAILURE(hr);
  1278. //
  1279. // We're successful so far, now skip by 1
  1280. //
  1281. pPropertyCache->skip_propindex(
  1282. 1
  1283. );
  1284. error:
  1285. if (pNtSrcObjects) {
  1286. NTTypeFreeNTObjects(
  1287. pNtSrcObjects,
  1288. dwNumValues
  1289. );
  1290. }
  1291. RRETURN(hr);
  1292. }
  1293. HRESULT
  1294. GenericSkipPropertyManager(
  1295. CPropertyCache * pPropertyCache,
  1296. ULONG cElements
  1297. )
  1298. {
  1299. pPropertyCache->skip_propindex(
  1300. cElements
  1301. );
  1302. RRETURN(S_OK);
  1303. }
  1304. HRESULT
  1305. GenericResetPropertyManager(
  1306. CPropertyCache * pPropertyCache
  1307. )
  1308. {
  1309. pPropertyCache->reset_propindex();
  1310. RRETURN(S_OK);
  1311. }
  1312. HRESULT
  1313. GenericDeletePropertyManager(
  1314. CPropertyCache * pPropertyCache,
  1315. VARIANT varEntry
  1316. )
  1317. {
  1318. HRESULT hr = S_OK;
  1319. DWORD dwIndex = 0;
  1320. switch (V_VT(&varEntry)) {
  1321. case VT_BSTR:
  1322. hr = pPropertyCache->findproperty(
  1323. V_BSTR(&varEntry),
  1324. &dwIndex
  1325. );
  1326. BAIL_ON_FAILURE(hr);
  1327. break;
  1328. case VT_I4:
  1329. dwIndex = V_I4(&varEntry);
  1330. break;
  1331. case VT_I2:
  1332. dwIndex = V_I2(&varEntry);
  1333. break;
  1334. default:
  1335. hr = E_FAIL;
  1336. BAIL_ON_FAILURE(hr);
  1337. }
  1338. hr = pPropertyCache->deleteproperty(
  1339. dwIndex
  1340. );
  1341. error:
  1342. RRETURN(hr);
  1343. }
  1344. HRESULT
  1345. GenericPutPropItemPropertyManager(
  1346. CPropertyCache * pPropertyCache,
  1347. PPROPERTYINFO pSchemaProps,
  1348. DWORD dwSchemaPropSize,
  1349. VARIANT varData
  1350. )
  1351. {
  1352. HRESULT hr = S_OK;
  1353. DWORD dwSyntaxId = 0;
  1354. DWORD dwIndex = 0;
  1355. WCHAR szPropertyName[MAX_PATH];
  1356. LPNTOBJECT pNtDestObjects = NULL;
  1357. DWORD dwNumValues = 0;
  1358. DWORD dwControlCode = 0;
  1359. hr = ConvertVariantToNtValues(
  1360. varData,
  1361. pSchemaProps,
  1362. dwSchemaPropSize,
  1363. szPropertyName,
  1364. &pNtDestObjects,
  1365. &dwNumValues,
  1366. &dwSyntaxId,
  1367. &dwControlCode
  1368. );
  1369. BAIL_ON_FAILURE(hr);
  1370. if (dwControlCode != ADS_PROPERTY_UPDATE) {
  1371. RRETURN(E_ADS_BAD_PARAMETER);
  1372. }
  1373. //
  1374. // Find this property in the cache
  1375. //
  1376. hr = pPropertyCache->findproperty(
  1377. szPropertyName,
  1378. &dwIndex
  1379. );
  1380. //
  1381. // If this property does not exist in the
  1382. // cache, add this property into the cache.
  1383. //
  1384. if (FAILED(hr)) {
  1385. hr = pPropertyCache->addproperty(
  1386. szPropertyName,
  1387. dwSyntaxId,
  1388. dwNumValues,
  1389. pNtDestObjects
  1390. );
  1391. //
  1392. // If the operation fails for some reason
  1393. // move on to the next property
  1394. //
  1395. BAIL_ON_FAILURE(hr);
  1396. }
  1397. //
  1398. // Now update the property in the cache
  1399. //
  1400. hr = pPropertyCache->putproperty(
  1401. szPropertyName,
  1402. dwSyntaxId,
  1403. dwNumValues,
  1404. pNtDestObjects
  1405. );
  1406. BAIL_ON_FAILURE(hr);
  1407. error:
  1408. if (pNtDestObjects) {
  1409. NTTypeFreeNTObjects(
  1410. pNtDestObjects,
  1411. dwNumValues
  1412. );
  1413. }
  1414. RRETURN(hr);
  1415. }
  1416. HRESULT
  1417. GenericGetPropItemPropertyManager(
  1418. CPropertyCache * pPropertyCache,
  1419. DWORD dwObjectState,
  1420. BSTR bstrName,
  1421. LONG lnADsType,
  1422. VARIANT * pVariant
  1423. )
  1424. {
  1425. HRESULT hr = S_OK;
  1426. DWORD dwSyntaxId;
  1427. DWORD dwNumValues;
  1428. LPNTOBJECT pNtSrcObjects = NULL;
  1429. //
  1430. // retrieve data object from cache; if one exis
  1431. //
  1432. if (dwObjectState == ADS_OBJECT_UNBOUND) {
  1433. hr = pPropertyCache->unboundgetproperty(
  1434. bstrName,
  1435. &dwSyntaxId,
  1436. &dwNumValues,
  1437. &pNtSrcObjects
  1438. );
  1439. BAIL_ON_FAILURE(hr);
  1440. }else {
  1441. hr = pPropertyCache->getproperty(
  1442. bstrName,
  1443. &dwSyntaxId,
  1444. &dwNumValues,
  1445. &pNtSrcObjects
  1446. );
  1447. BAIL_ON_FAILURE(hr);
  1448. }
  1449. //
  1450. // translate the Nds objects to variants
  1451. //
  1452. hr = ConvertNtValuesToVariant(
  1453. bstrName,
  1454. pNtSrcObjects,
  1455. dwNumValues,
  1456. pVariant
  1457. );
  1458. BAIL_ON_FAILURE(hr);
  1459. error:
  1460. if (pNtSrcObjects) {
  1461. NTTypeFreeNTObjects(
  1462. pNtSrcObjects,
  1463. dwNumValues
  1464. );
  1465. }
  1466. RRETURN(hr);
  1467. }
  1468. HRESULT
  1469. GenericItemPropertyManager(
  1470. CPropertyCache * pPropertyCache,
  1471. DWORD dwObjectState,
  1472. VARIANT varIndex,
  1473. VARIANT *pVariant
  1474. )
  1475. {
  1476. HRESULT hr = S_OK;
  1477. DWORD dwSyntaxId;
  1478. DWORD dwNumValues;
  1479. LPNTOBJECT pNtSrcObjects = NULL;
  1480. LPWSTR szPropName = NULL;
  1481. //
  1482. // retrieve data object from cache; if one exis
  1483. //
  1484. switch (V_VT(&varIndex)) {
  1485. case VT_BSTR:
  1486. if (dwObjectState == ADS_OBJECT_UNBOUND) {
  1487. hr = pPropertyCache->unboundgetproperty(
  1488. V_BSTR(&varIndex),
  1489. &dwSyntaxId,
  1490. &dwNumValues,
  1491. &pNtSrcObjects
  1492. );
  1493. BAIL_ON_FAILURE(hr);
  1494. }else {
  1495. hr = pPropertyCache->getproperty(
  1496. V_BSTR(&varIndex),
  1497. &dwSyntaxId,
  1498. &dwNumValues,
  1499. &pNtSrcObjects
  1500. );
  1501. BAIL_ON_FAILURE(hr);
  1502. }
  1503. hr = ConvertNtValuesToVariant(
  1504. V_BSTR(&varIndex),
  1505. pNtSrcObjects,
  1506. dwNumValues,
  1507. pVariant
  1508. );
  1509. BAIL_ON_FAILURE(hr);
  1510. break;
  1511. case VT_I4:
  1512. hr = pPropertyCache->unboundgetproperty(
  1513. V_I4(&varIndex),
  1514. &dwSyntaxId,
  1515. &dwNumValues,
  1516. &pNtSrcObjects
  1517. );
  1518. BAIL_ON_FAILURE(hr);
  1519. szPropName = pPropertyCache->get_PropName(V_I4(&varIndex));
  1520. hr = ConvertNtValuesToVariant(
  1521. szPropName,
  1522. pNtSrcObjects,
  1523. dwNumValues,
  1524. pVariant
  1525. );
  1526. BAIL_ON_FAILURE(hr);
  1527. break;
  1528. case VT_I2:
  1529. hr = pPropertyCache->unboundgetproperty(
  1530. (DWORD)V_I2(&varIndex),
  1531. &dwSyntaxId,
  1532. &dwNumValues,
  1533. &pNtSrcObjects
  1534. );
  1535. BAIL_ON_FAILURE(hr);
  1536. szPropName = pPropertyCache->get_PropName(V_I2(&varIndex));
  1537. hr = ConvertNtValuesToVariant(
  1538. szPropName,
  1539. pNtSrcObjects,
  1540. dwNumValues,
  1541. pVariant
  1542. );
  1543. BAIL_ON_FAILURE(hr);
  1544. break;
  1545. default:
  1546. hr = E_FAIL;
  1547. BAIL_ON_FAILURE(hr);
  1548. }
  1549. error:
  1550. if (pNtSrcObjects) {
  1551. NTTypeFreeNTObjects(
  1552. pNtSrcObjects,
  1553. dwNumValues
  1554. );
  1555. }
  1556. RRETURN(hr);
  1557. }
  1558. HRESULT
  1559. GenericPurgePropertyManager(
  1560. CPropertyCache * pPropertyCache
  1561. )
  1562. {
  1563. pPropertyCache->flushpropcache();
  1564. RRETURN(S_OK);
  1565. }
  1566. HRESULT
  1567. CreatePropEntry(
  1568. LPWSTR szPropName,
  1569. ADSTYPE dwADsType,
  1570. VARIANT varData,
  1571. REFIID riid,
  1572. LPVOID * ppDispatch
  1573. )
  1574. {
  1575. HRESULT hr = S_OK;
  1576. IADsPropertyEntry * pPropEntry = NULL;
  1577. hr = CoCreateInstance(
  1578. CLSID_PropertyEntry,
  1579. NULL,
  1580. CLSCTX_INPROC_SERVER,
  1581. IID_IADsPropertyEntry,
  1582. (void **)&pPropEntry
  1583. );
  1584. BAIL_ON_FAILURE(hr);
  1585. hr = pPropEntry->put_Name(szPropName);
  1586. BAIL_ON_FAILURE(hr);
  1587. hr = pPropEntry->put_Values(varData);
  1588. BAIL_ON_FAILURE(hr);
  1589. hr = pPropEntry->put_ADsType(dwADsType);
  1590. BAIL_ON_FAILURE(hr);
  1591. hr = pPropEntry->QueryInterface(
  1592. riid,
  1593. ppDispatch
  1594. );
  1595. BAIL_ON_FAILURE(hr);
  1596. error:
  1597. if (pPropEntry) {
  1598. pPropEntry->Release();
  1599. }
  1600. RRETURN(hr);
  1601. }
  1602. HRESULT
  1603. ConvertNtValuesToVariant(
  1604. LPWSTR szPropertyName,
  1605. PNTOBJECT pNtSrcObject,
  1606. DWORD dwNumValues,
  1607. PVARIANT pVariant
  1608. )
  1609. {
  1610. HRESULT hr = S_OK;
  1611. VARIANT varData;
  1612. IDispatch * pDispatch = NULL;
  1613. PADSVALUE pAdsValues = NULL;
  1614. ADSTYPE dwADsType = ADSTYPE_INVALID;
  1615. VariantInit(&varData);
  1616. VariantInit(pVariant);
  1617. if (dwNumValues>0) {
  1618. hr = NTTypeToAdsTypeCopyConstruct(
  1619. pNtSrcObject,
  1620. dwNumValues,
  1621. &pAdsValues
  1622. );
  1623. if (SUCCEEDED(hr)){
  1624. hr = AdsTypeToPropVariant(
  1625. pAdsValues,
  1626. dwNumValues,
  1627. &varData
  1628. );
  1629. BAIL_ON_FAILURE(hr);
  1630. dwADsType = pAdsValues->dwType;
  1631. }
  1632. else if (hr==E_OUTOFMEMORY) {
  1633. BAIL_ON_FAILURE(hr);
  1634. }
  1635. // failed because of NTType is not supported yet (e.g. NulledString)
  1636. // in NTTypeToAdsTypeCopyConstruct() conversion yet
  1637. // -> use empty variant now.
  1638. else {
  1639. VariantInit(&varData);
  1640. }
  1641. }
  1642. hr = CreatePropEntry(
  1643. szPropertyName,
  1644. dwADsType,
  1645. varData,
  1646. IID_IDispatch,
  1647. (void **)&pDispatch
  1648. );
  1649. BAIL_ON_FAILURE(hr);
  1650. V_DISPATCH(pVariant) = pDispatch;
  1651. V_VT(pVariant) = VT_DISPATCH;
  1652. error:
  1653. VariantClear(&varData);
  1654. if (pAdsValues) {
  1655. AdsFreeAdsValues(
  1656. pAdsValues,
  1657. dwNumValues
  1658. );
  1659. FreeADsMem( pAdsValues);
  1660. }
  1661. RRETURN(hr);
  1662. }
  1663. HRESULT
  1664. ConvertVariantToVariantArray(
  1665. VARIANT varData,
  1666. VARIANT ** ppVarArray,
  1667. DWORD * pdwNumValues
  1668. )
  1669. {
  1670. DWORD dwNumValues = 0;
  1671. VARIANT * pVarArray = NULL;
  1672. HRESULT hr = S_OK;
  1673. VARIANT * pVarData = NULL;
  1674. *ppVarArray = NULL;
  1675. *pdwNumValues = 0;
  1676. //
  1677. // A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
  1678. // We should dereference a VT_BYREF|VT_VARIANT once and see
  1679. // what's inside.
  1680. //
  1681. pVarData = &varData;
  1682. if (V_VT(pVarData) == (VT_BYREF|VT_VARIANT)) {
  1683. pVarData = V_VARIANTREF(&varData);
  1684. }
  1685. if ((V_VT(pVarData) == (VT_VARIANT|VT_ARRAY|VT_BYREF)) ||
  1686. (V_VT(pVarData) == (VT_VARIANT|VT_ARRAY))) {
  1687. hr = ConvertSafeArrayToVariantArray(
  1688. varData,
  1689. &pVarArray,
  1690. &dwNumValues
  1691. );
  1692. BAIL_ON_FAILURE(hr);
  1693. } else {
  1694. pVarArray = NULL;
  1695. dwNumValues = 0;
  1696. }
  1697. *ppVarArray = pVarArray;
  1698. *pdwNumValues = dwNumValues;
  1699. error:
  1700. RRETURN(hr);
  1701. }
  1702. void
  1703. FreeVariantArray(
  1704. VARIANT * pVarArray,
  1705. DWORD dwNumValues
  1706. )
  1707. {
  1708. if (pVarArray) {
  1709. DWORD i = 0;
  1710. for (i = 0; i < dwNumValues; i++) {
  1711. VariantClear(pVarArray + i);
  1712. }
  1713. FreeADsMem(pVarArray);
  1714. }
  1715. }
  1716. HRESULT
  1717. ConvertVariantToNtValues(
  1718. VARIANT varData,
  1719. PPROPERTYINFO pSchemaProps,
  1720. DWORD dwSchemaPropSize,
  1721. LPWSTR szPropertyName,
  1722. PNTOBJECT *ppNtDestObjects,
  1723. PDWORD pdwNumValues,
  1724. PDWORD pdwSyntaxId,
  1725. PDWORD pdwControlCode
  1726. )
  1727. {
  1728. HRESULT hr = S_OK;
  1729. IADsPropertyEntry * pPropEntry = NULL;
  1730. IDispatch * pDispatch = NULL;
  1731. BSTR bstrPropName = NULL;
  1732. DWORD dwControlCode = 0;
  1733. DWORD dwAdsType = 0;
  1734. VARIANT varValues;
  1735. VARIANT * pVarArray = NULL;
  1736. DWORD dwNumValues = 0;
  1737. PADSVALUE pAdsValues = NULL;
  1738. DWORD dwAdsValues = 0;
  1739. PNTOBJECT pNtDestObjects = 0;
  1740. DWORD dwNumNtObjects = 0;
  1741. DWORD dwNtSyntaxId = 0;
  1742. if (V_VT(&varData) != VT_DISPATCH) {
  1743. RRETURN (hr = DISP_E_TYPEMISMATCH);
  1744. }
  1745. pDispatch = V_DISPATCH(&varData);
  1746. hr = pDispatch->QueryInterface(
  1747. IID_IADsPropertyEntry,
  1748. (void **)&pPropEntry
  1749. );
  1750. BAIL_ON_FAILURE(hr);
  1751. VariantInit(&varValues);
  1752. VariantClear(&varValues);
  1753. hr = pPropEntry->get_Name(&bstrPropName);
  1754. BAIL_ON_FAILURE(hr);
  1755. wcscpy(szPropertyName, bstrPropName);
  1756. hr = pPropEntry->get_ControlCode((long *)&dwControlCode);
  1757. BAIL_ON_FAILURE(hr);
  1758. *pdwControlCode = dwControlCode;
  1759. hr = pPropEntry->get_ADsType((long *)&dwAdsType);
  1760. BAIL_ON_FAILURE(hr);
  1761. hr = pPropEntry->get_Values(&varValues);
  1762. BAIL_ON_FAILURE(hr);
  1763. hr = ConvertVariantToVariantArray(
  1764. varValues,
  1765. &pVarArray,
  1766. &dwNumValues
  1767. );
  1768. BAIL_ON_FAILURE(hr);
  1769. if (dwNumValues) {
  1770. hr = PropVariantToAdsType(
  1771. pVarArray,
  1772. dwNumValues,
  1773. &pAdsValues,
  1774. &dwAdsValues
  1775. );
  1776. BAIL_ON_FAILURE(hr);
  1777. hr = AdsTypeToNTTypeCopyConstruct(
  1778. pAdsValues,
  1779. dwAdsValues,
  1780. &pNtDestObjects,
  1781. &dwNumNtObjects,
  1782. &dwNtSyntaxId
  1783. );
  1784. BAIL_ON_FAILURE(hr);
  1785. }
  1786. *pdwNumValues = dwNumValues;
  1787. *ppNtDestObjects = pNtDestObjects;
  1788. *pdwSyntaxId = dwNtSyntaxId;
  1789. error:
  1790. if (pVarArray) {
  1791. FreeVariantArray(
  1792. pVarArray,
  1793. dwNumValues
  1794. );
  1795. }
  1796. RRETURN(hr);
  1797. }
  1798. HRESULT
  1799. ConvertNtValuesToVariant(
  1800. BSTR bstrName,
  1801. LPNTOBJECT pNtSrcObjects,
  1802. DWORD dwNumValues,
  1803. VARIANT * pVariant
  1804. );
  1805. HRESULT
  1806. ConvertVariantToVariantArray(
  1807. VARIANT varData,
  1808. VARIANT ** ppVarArray,
  1809. DWORD * pdwNumValues
  1810. );
  1811. void
  1812. FreeVariantArray(
  1813. VARIANT * pVarArray,
  1814. DWORD dwNumValues
  1815. );
  1816. HRESULT
  1817. ConvertVariantToNtValues(
  1818. VARIANT varData,
  1819. PPROPERTYINFO pSchemaProps,
  1820. DWORD dwSchemaPropSize,
  1821. LPWSTR szPropertyName,
  1822. PNTOBJECT *ppNtDestObjects,
  1823. PDWORD pdwNumValues,
  1824. PDWORD pdwSyntaxId
  1825. );
  1826. HRESULT
  1827. CheckAndSetExtendedError(
  1828. DWORD dwRetval
  1829. )
  1830. {
  1831. DWORD dwLastError;
  1832. WCHAR pszError[MAX_PATH];
  1833. WCHAR pszProviderName[MAX_PATH];
  1834. INT numChars;
  1835. HRESULT hr =S_OK;
  1836. wcscpy(pszError, L"");
  1837. wcscpy(pszProviderName, L"");
  1838. if (NWCCODE_SUCCESS(dwRetval)){
  1839. hr = S_OK;
  1840. } else {
  1841. hr = HRESULT_FROM_WIN32(ERROR_EXTENDED_ERROR);
  1842. numChars = LoadString( g_hInst,
  1843. NW_PROVIDER_ID,
  1844. pszProviderName,
  1845. MAX_PATH -1);
  1846. //
  1847. // Set the default error string
  1848. wsprintf (pszError, L"NW ccode = %x", dwRetval);
  1849. ADsSetLastError(
  1850. dwRetval,
  1851. pszError,
  1852. pszProviderName
  1853. );
  1854. }
  1855. RRETURN(hr);
  1856. }
  1857. HRESULT
  1858. InitializeNWLibrary(
  1859. void
  1860. )
  1861. {
  1862. NWDSCCODE ccode;
  1863. HRESULT hr = S_OK;
  1864. LCONV lConvInfo;
  1865. ccode = NWCallsInit(NULL, NULL);
  1866. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1867. ccode = NWCLXInit(NULL, NULL);
  1868. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1869. error:
  1870. RRETURN(hr);
  1871. }