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.

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