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.

2092 lines
44 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997
  5. //
  6. // File: common.cxx
  7. //
  8. // Contents: Microsoft ADs IIS Common routines
  9. //
  10. // History: 28-Feb-97 SophiaC Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "iis.hxx"
  14. extern SERVER_CACHE * g_pServerCache;
  15. extern WIN32_CRITSEC * g_pGlobalLock;
  16. #pragma hdrstop
  17. FILTERS Filters[] = {
  18. {L"user", IIS_USER_ID},
  19. {L"group", IIS_GROUP_ID},
  20. {L"queue", IIS_PRINTER_ID},
  21. {L"domain", IIS_DOMAIN_ID},
  22. {L"computer", IIS_COMPUTER_ID},
  23. {L"service", IIS_SERVICE_ID},
  24. {L"fileservice", IIS_FILESERVICE_ID},
  25. {L"fileshare", IIS_FILESHARE_ID},
  26. {L"class", IIS_CLASS_ID},
  27. {L"functionalset", IIS_FUNCTIONALSET_ID},
  28. {L"syntax", IIS_SYNTAX_ID},
  29. {L"property", IIS_PROPERTY_ID},
  30. {L"tree", IIS_TREE_ID},
  31. {L"Organizational Unit", IIS_OU_ID},
  32. {L"Organization", IIS_O_ID},
  33. {L"Locality", IIS_LOCALITY_ID}
  34. };
  35. #define MAX_FILTERS (sizeof(Filters)/sizeof(FILTERS))
  36. #define DEFAULT_TIMEOUT_VALUE 30000
  37. PFILTERS gpFilters = Filters;
  38. DWORD gdwMaxFilters = MAX_FILTERS;
  39. extern WCHAR * szProviderName;
  40. //+------------------------------------------------------------------------
  41. //
  42. // Class: Common
  43. //
  44. // Purpose: Contains Winnt routines and properties that are common to
  45. // all Winnt objects. Winnt objects get the routines and
  46. // properties through C++ inheritance.
  47. //
  48. //-------------------------------------------------------------------------
  49. HRESULT
  50. BuildADsPath(
  51. BSTR Parent,
  52. BSTR Name,
  53. BSTR *pADsPath
  54. )
  55. {
  56. LPWSTR lpADsPath = NULL;
  57. WCHAR ProviderName[MAX_PATH];
  58. HRESULT hr = S_OK;
  59. DWORD dwLen = 0;
  60. //
  61. // We will assert if bad parameters are passed to us.
  62. // This is because this should never be the case. This
  63. // is an internal call
  64. //
  65. ADsAssert(Parent && Name);
  66. ADsAssert(pADsPath);
  67. //
  68. // Special case the Namespace object; if
  69. // the parent is L"ADs:", then Name = ADsPath
  70. //
  71. if (!_wcsicmp(Parent, L"ADs:")) {
  72. RRETURN(ADsAllocString( Name, pADsPath));
  73. }
  74. //
  75. // Allocate the right side buffer
  76. // 2 for // + a buffer of MAX_PATH
  77. //
  78. dwLen = wcslen(Parent) + wcslen(Name) + 2 + MAX_PATH;
  79. lpADsPath = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
  80. if (!lpADsPath) {
  81. RRETURN(E_OUTOFMEMORY);
  82. }
  83. //
  84. // The rest of the cases we expect valid data,
  85. // Path, Parent and Name are read-only, the end-user
  86. // cannot modify this data
  87. //
  88. //
  89. // For the first object, the domain object we do not add
  90. // the first backslash; so we examine that the parent is
  91. // L"WinNT:" and skip the slash otherwise we start with
  92. // the slash
  93. //
  94. wsprintf(ProviderName, L"%s:", szProviderName);
  95. wcscpy(lpADsPath, Parent);
  96. if (_wcsicmp(lpADsPath, ProviderName)) {
  97. wcscat(lpADsPath, L"/");
  98. }else {
  99. wcscat(lpADsPath, L"//");
  100. }
  101. wcscat(lpADsPath, Name);
  102. hr = ADsAllocString( lpADsPath, pADsPath);
  103. if (lpADsPath) {
  104. FreeADsMem(lpADsPath);
  105. }
  106. RRETURN(hr);
  107. }
  108. HRESULT
  109. BuildSchemaPath(
  110. BSTR bstrADsPath,
  111. BSTR bstrClass,
  112. BSTR *pSchemaPath
  113. )
  114. {
  115. WCHAR ADsSchema[MAX_PATH];
  116. OBJECTINFO ObjectInfo;
  117. POBJECTINFO pObjectInfo = &ObjectInfo;
  118. CLexer Lexer(bstrADsPath);
  119. HRESULT hr = S_OK;
  120. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  121. wcscpy(ADsSchema, L"");
  122. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  123. if (bstrClass && *bstrClass) {
  124. hr = ADsObject(&Lexer, pObjectInfo);
  125. BAIL_ON_FAILURE(hr);
  126. if (pObjectInfo->TreeName) {
  127. wsprintf(ADsSchema,L"%s://",pObjectInfo->ProviderName);
  128. wcscat(ADsSchema, pObjectInfo->TreeName);
  129. wcscat(ADsSchema,L"/schema/");
  130. wcscat(ADsSchema, bstrClass);
  131. }
  132. }
  133. hr = ADsAllocString( ADsSchema, pSchemaPath);
  134. error:
  135. if (pObjectInfo) {
  136. FreeObjectInfo( pObjectInfo );
  137. }
  138. RRETURN(hr);
  139. }
  140. HRESULT
  141. BuildADsGuid(
  142. REFCLSID clsid,
  143. BSTR *pADsClass
  144. )
  145. {
  146. WCHAR ADsClass[MAX_PATH];
  147. StringFromGUID2(clsid, ADsClass, 256);
  148. RRETURN(ADsAllocString( ADsClass, pADsClass));
  149. }
  150. HRESULT
  151. ValidateOutParameter(
  152. BSTR * retval
  153. )
  154. {
  155. if (!retval) {
  156. RRETURN(E_ADS_BAD_PARAMETER);
  157. }
  158. RRETURN(S_OK);
  159. }
  160. HRESULT
  161. OpenAdminBaseKey(
  162. IN LPWSTR pszServerName,
  163. IN LPWSTR pszPathName,
  164. IN DWORD dwAccessType,
  165. IN OUT IMSAdminBase **ppAdminBase,
  166. OUT METADATA_HANDLE *phHandle
  167. )
  168. {
  169. HRESULT hr;
  170. IMSAdminBase *pAdminBase = *ppAdminBase;
  171. METADATA_HANDLE RootHandle = NULL;
  172. DWORD dwThreadId;
  173. hr = pAdminBase->OpenKey(
  174. METADATA_MASTER_ROOT_HANDLE,
  175. pszPathName,
  176. dwAccessType,
  177. DEFAULT_TIMEOUT_VALUE,
  178. &RootHandle
  179. );
  180. if (FAILED(hr)) {
  181. if ((HRESULT_CODE(hr) == RPC_S_SERVER_UNAVAILABLE) ||
  182. ((HRESULT_CODE(hr) >= RPC_S_NO_CALL_ACTIVE) &&
  183. (HRESULT_CODE(hr) <= RPC_S_CALL_FAILED_DNE)) ||
  184. hr == RPC_E_DISCONNECTED) {
  185. SERVER_CACHE_ITEM * item = NULL;
  186. IMSAdminBase * pOldAdminBase = pAdminBase;
  187. //
  188. // RPC error, try to recover connection
  189. //
  190. hr = InitAdminBase(pszServerName, &pAdminBase);
  191. BAIL_ON_FAILURE(hr);
  192. *ppAdminBase = pAdminBase;
  193. hr = pAdminBase->OpenKey(
  194. METADATA_MASTER_ROOT_HANDLE,
  195. pszPathName,
  196. dwAccessType,
  197. DEFAULT_TIMEOUT_VALUE,
  198. &RootHandle
  199. );
  200. //
  201. // update cache item
  202. //
  203. dwThreadId = GetCurrentThreadId();
  204. item = g_pServerCache->Find(pszServerName, dwThreadId);
  205. ASSERT(item != NULL);
  206. if (item != NULL)
  207. {
  208. UninitAdminBase(pOldAdminBase);
  209. item->UpdateAdminBase(pAdminBase, dwThreadId);
  210. }
  211. }
  212. }
  213. error :
  214. if (FAILED(hr)) {
  215. if (pAdminBase && RootHandle) {
  216. pAdminBase->CloseKey(RootHandle);
  217. }
  218. }
  219. else {
  220. *phHandle = RootHandle;
  221. }
  222. RRETURN(hr);
  223. }
  224. VOID
  225. CloseAdminBaseKey(
  226. IN IMSAdminBase *pAdminBase,
  227. IN METADATA_HANDLE hHandle
  228. )
  229. {
  230. HRESULT hr;
  231. if (pAdminBase) {
  232. hr = pAdminBase->CloseKey(hHandle);
  233. }
  234. return;
  235. }
  236. HRESULT
  237. MetaBaseGetAllData(
  238. IN IMSAdminBase *pAdminBase,
  239. IN METADATA_HANDLE hObjHandle,
  240. IN LPWSTR pszIISPathName,
  241. IN DWORD dwMDAttributes,
  242. IN DWORD dwMDUserType,
  243. IN DWORD dwMDDataType,
  244. OUT PDWORD pdwMDNumDataEntries,
  245. OUT PDWORD pdwMDDataSetNumber,
  246. OUT LPBYTE * ppBuffer
  247. )
  248. {
  249. LPBYTE pBuffer = NULL;
  250. HRESULT hr = S_OK;
  251. DWORD dwBufferSize = 0;
  252. DWORD dwReqdBufferSize = 0;
  253. hr = pAdminBase->GetAllData(
  254. hObjHandle,
  255. pszIISPathName,
  256. dwMDAttributes,
  257. dwMDUserType,
  258. dwMDDataType,
  259. pdwMDNumDataEntries,
  260. pdwMDDataSetNumber,
  261. dwBufferSize,
  262. (LPBYTE)"",
  263. &dwReqdBufferSize
  264. );
  265. pBuffer = (LPBYTE) AllocADsMem(dwReqdBufferSize);
  266. if (!pBuffer) {
  267. hr = HRESULT_FROM_WIN32(GetLastError());
  268. BAIL_ON_FAILURE(hr);
  269. }
  270. dwBufferSize = dwReqdBufferSize;
  271. hr = pAdminBase->GetAllData(
  272. hObjHandle,
  273. pszIISPathName,
  274. dwMDAttributes,
  275. dwMDUserType,
  276. dwMDDataType,
  277. pdwMDNumDataEntries,
  278. pdwMDDataSetNumber,
  279. dwBufferSize,
  280. pBuffer,
  281. &dwReqdBufferSize
  282. );
  283. BAIL_ON_FAILURE(hr);
  284. *ppBuffer = pBuffer;
  285. RRETURN(hr);
  286. error:
  287. if (pBuffer) {
  288. FreeADsMem(pBuffer);
  289. }
  290. RRETURN(hr);
  291. }
  292. HRESULT
  293. MetaBaseSetAllData(
  294. IN IMSAdminBase *pAdminBase,
  295. IN METADATA_HANDLE hObjHandle,
  296. IN LPWSTR pszIISPathName,
  297. IN PMETADATA_RECORD pMetaDataArray,
  298. IN DWORD dwNumEntries
  299. )
  300. {
  301. HRESULT hr = S_OK;
  302. PMETADATA_RECORD pTemp = NULL;
  303. METADATA_RECORD mdrMDData;
  304. DWORD i;
  305. //
  306. // Set each METADATA record one at a time
  307. //
  308. for (i = 0; i < dwNumEntries; i++) {
  309. pTemp = pMetaDataArray + i;
  310. mdrMDData.dwMDIdentifier = pTemp->dwMDIdentifier;
  311. mdrMDData.dwMDAttributes = pTemp->dwMDAttributes;
  312. mdrMDData.dwMDUserType = pTemp->dwMDUserType;
  313. mdrMDData.dwMDDataType = pTemp->dwMDDataType;
  314. mdrMDData.dwMDDataLen = pTemp->dwMDDataLen;
  315. mdrMDData.dwMDDataTag = pTemp->dwMDDataTag;
  316. mdrMDData.pbMDData = pTemp->pbMDData;
  317. hr = pAdminBase->SetData(
  318. hObjHandle,
  319. pszIISPathName,
  320. &mdrMDData
  321. );
  322. BAIL_ON_FAILURE(hr);
  323. }
  324. error:
  325. RRETURN(hr);
  326. }
  327. HRESULT
  328. MetaBaseDeleteObject(
  329. IN IMSAdminBase * pAdminBase,
  330. IN METADATA_HANDLE hObjHandle,
  331. IN LPWSTR pszIISPathName
  332. )
  333. {
  334. HRESULT hr = S_OK;
  335. hr = pAdminBase->DeleteKey(
  336. hObjHandle,
  337. pszIISPathName
  338. );
  339. RRETURN(hr);
  340. }
  341. HRESULT
  342. MetaBaseCreateObject(
  343. IN IMSAdminBase * pAdminBase,
  344. IN METADATA_HANDLE hObjHandle,
  345. IN LPWSTR pszIISPathName
  346. )
  347. {
  348. HRESULT hr = S_OK;
  349. hr = pAdminBase->AddKey(
  350. hObjHandle,
  351. pszIISPathName
  352. );
  353. RRETURN(hr);
  354. }
  355. HRESULT
  356. MetaBaseCopyObject(
  357. IN IMSAdminBase * pAdminBase,
  358. IN METADATA_HANDLE hSrcObjHandle,
  359. IN LPWSTR pszIISSrcPathName,
  360. IN METADATA_HANDLE hDestObjHandle,
  361. IN LPWSTR pszIISDestPathName
  362. )
  363. {
  364. HRESULT hr = S_OK;
  365. hr = pAdminBase->CopyKey(
  366. hSrcObjHandle,
  367. pszIISSrcPathName,
  368. hDestObjHandle,
  369. pszIISDestPathName,
  370. TRUE,
  371. TRUE
  372. );
  373. RRETURN(hr);
  374. }
  375. HRESULT
  376. MetaBaseMoveObject(
  377. IN IMSAdminBase * pAdminBase,
  378. IN METADATA_HANDLE hSrcObjHandle,
  379. IN LPWSTR pszIISSrcPathName,
  380. IN METADATA_HANDLE hDestObjHandle,
  381. IN LPWSTR pszIISDestPathName
  382. )
  383. {
  384. HRESULT hr = S_OK;
  385. hr = pAdminBase->CopyKey(
  386. hSrcObjHandle,
  387. pszIISSrcPathName,
  388. hDestObjHandle,
  389. pszIISDestPathName,
  390. FALSE,
  391. FALSE
  392. );
  393. RRETURN(hr);
  394. }
  395. HRESULT
  396. MetaBaseGetAdminACL(
  397. IN IMSAdminBase * pAdminBase,
  398. IN METADATA_HANDLE hObjHandle,
  399. IN LPWSTR pszIISPathName,
  400. OUT LPBYTE *ppBuffer
  401. )
  402. {
  403. HRESULT hr = S_OK;
  404. DWORD dwBufferSize = 0;
  405. METADATA_RECORD mdrMDData;
  406. LPBYTE pBuffer = NULL;
  407. MD_SET_DATA_RECORD(&mdrMDData,
  408. MD_ADMIN_ACL, // admin acl
  409. METADATA_INHERIT,
  410. IIS_MD_UT_FILE,
  411. BINARY_METADATA,
  412. dwBufferSize,
  413. pBuffer);
  414. hr = pAdminBase->GetData(
  415. hObjHandle,
  416. pszIISPathName,
  417. &mdrMDData,
  418. &dwBufferSize
  419. );
  420. pBuffer = (LPBYTE) AllocADsMem(dwBufferSize);
  421. if (!pBuffer) {
  422. hr = HRESULT_FROM_WIN32(GetLastError());
  423. BAIL_ON_FAILURE(hr);
  424. }
  425. MD_SET_DATA_RECORD(&mdrMDData,
  426. MD_ADMIN_ACL, // admin acl
  427. METADATA_INHERIT,
  428. IIS_MD_UT_FILE,
  429. BINARY_METADATA,
  430. dwBufferSize,
  431. pBuffer);
  432. hr = pAdminBase->GetData(
  433. hObjHandle,
  434. pszIISPathName,
  435. &mdrMDData,
  436. &dwBufferSize
  437. );
  438. BAIL_ON_FAILURE(hr);
  439. *ppBuffer = pBuffer;
  440. RRETURN(hr);
  441. error:
  442. if (pBuffer) {
  443. FreeADsMem(pBuffer);
  444. }
  445. RRETURN(hr);
  446. }
  447. HRESULT
  448. MetaBaseDetectKey(
  449. IN IMSAdminBase *pAdminBase,
  450. IN LPCWSTR pszIISPathName
  451. )
  452. {
  453. HRESULT hr = S_OK;
  454. FILETIME ft;
  455. hr = pAdminBase->GetLastChangeTime( METADATA_MASTER_ROOT_HANDLE,
  456. pszIISPathName,
  457. &ft,
  458. FALSE
  459. );
  460. RRETURN(hr);
  461. }
  462. HRESULT
  463. MetaBaseGetADsClass(
  464. IN IMSAdminBase *pAdminBase,
  465. IN LPWSTR pszIISPathName,
  466. IN IIsSchema *pSchema,
  467. OUT LPWSTR pszDataBuffer,
  468. IN DWORD dwBufferLen
  469. )
  470. /*++
  471. Routine Description:
  472. Get the ADsClass from the metabase path.
  473. Arguments:
  474. IN pAdminBase : the metabase
  475. IN pszIISPathName : the full metabase path (may be upcased)
  476. IN pSchema : schema against which to validate
  477. OUT pszDataBuffer : the class name
  478. IN dwBufferLen : number of characters allocated for class name
  479. Return Value:
  480. --*/
  481. {
  482. // CODEWORK - There are at least two other places that do essentially
  483. // the same thing. It should be possible to replace that code with a
  484. // call to this routine
  485. HRESULT hr = S_OK;
  486. METADATA_HANDLE hObjHandle = NULL;
  487. METADATA_RECORD mdrData;
  488. DWORD dwReqdBufferLen = 0;
  489. hr = pAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  490. pszIISPathName,
  491. METADATA_PERMISSION_READ,
  492. DEFAULT_TIMEOUT_VALUE,
  493. &hObjHandle
  494. );
  495. BAIL_ON_FAILURE(hr);
  496. //
  497. // Find out Class Name
  498. //
  499. mdrData.dwMDIdentifier = MD_KEY_TYPE;
  500. mdrData.dwMDDataType = STRING_METADATA;
  501. mdrData.dwMDUserType = ALL_METADATA;
  502. mdrData.dwMDAttributes = METADATA_INHERIT;
  503. mdrData.dwMDDataLen = dwBufferLen * sizeof(WCHAR);
  504. mdrData.pbMDData = (PBYTE)pszDataBuffer;
  505. hr = pAdminBase->GetData(
  506. hObjHandle,
  507. L"",
  508. &mdrData,
  509. &dwReqdBufferLen
  510. );
  511. if (FAILED(hr))
  512. {
  513. if (hr == MD_ERROR_DATA_NOT_FOUND)
  514. {
  515. //
  516. // If the key does not have a KeyType we will do our best
  517. // to guess. This is pretty bogus, but there is existing code
  518. // that depends on this behavior.
  519. //
  520. _wcsupr(pszIISPathName);
  521. if (wcsstr(pszIISPathName, L"W3SVC") != NULL)
  522. {
  523. wcscpy( pszDataBuffer, WEBDIR_CLASS_W );
  524. }
  525. else if (wcsstr(pszIISPathName, L"MSFTPSVC") != NULL)
  526. {
  527. wcscpy( pszDataBuffer, FTPVDIR_CLASS_W );
  528. }
  529. else
  530. {
  531. wcscpy( pszDataBuffer, DEFAULT_SCHEMA_CLASS_W );
  532. }
  533. hr = S_FALSE;
  534. }
  535. else
  536. {
  537. BAIL_ON_FAILURE(hr);
  538. }
  539. }
  540. else
  541. {
  542. hr = pSchema->ValidateClassName( pszDataBuffer );
  543. if (hr == E_ADS_UNKNOWN_OBJECT)
  544. {
  545. wcscpy( pszDataBuffer, DEFAULT_SCHEMA_CLASS_W );
  546. }
  547. }
  548. error:
  549. //
  550. // Close the handle now
  551. //
  552. if (hObjHandle)
  553. {
  554. CloseAdminBaseKey(pAdminBase, hObjHandle);
  555. hObjHandle = NULL;
  556. }
  557. RRETURN(hr);
  558. }
  559. static HRESULT
  560. GetSchema(
  561. LPWSTR machineNameW,
  562. IIsSchema **out
  563. )
  564. /*++
  565. Routine Description:
  566. Creates and initializes a new IIsSchema object.
  567. Arguments:
  568. Return Value:
  569. Notes:
  570. This routine should only be used internally. If it is necessary
  571. to get a reference to the schema for the current machine, use
  572. InitServerInfo().
  573. --*/
  574. {
  575. IIsSchema *schema=NULL;
  576. HRESULT hr = S_OK;
  577. schema = new IIsSchema();
  578. if (schema) {
  579. hr = schema->InitSchema(machineNameW);
  580. if (FAILED(hr)) {
  581. delete schema;
  582. schema = 0;
  583. *out = 0;
  584. return hr;
  585. }
  586. }
  587. else {
  588. return E_OUTOFMEMORY;
  589. }
  590. *out = schema;
  591. return hr;
  592. }
  593. HRESULT
  594. FreeMetaDataRecordArray(
  595. PMETADATA_RECORD pMetaDataArray,
  596. DWORD dwNumEntries
  597. )
  598. {
  599. DWORD i;
  600. DWORD dwIISType;
  601. PMETADATA_RECORD pMetaData;
  602. for (i = 0; i < dwNumEntries; i++ ) {
  603. pMetaData = pMetaDataArray + i;
  604. dwIISType = pMetaData->dwMDDataType;
  605. switch(dwIISType) {
  606. case DWORD_METADATA:
  607. break;
  608. case STRING_METADATA:
  609. case EXPANDSZ_METADATA:
  610. FreeADsStr((LPWSTR)pMetaData->pbMDData);
  611. break;
  612. case MULTISZ_METADATA:
  613. case BINARY_METADATA:
  614. FreeADsMem(pMetaData->pbMDData);
  615. break;
  616. default:
  617. break;
  618. }
  619. }
  620. FreeADsMem(pMetaDataArray);
  621. RRETURN(S_OK);
  622. }
  623. HRESULT
  624. InitAdminBase(
  625. IN LPWSTR pszServerName,
  626. OUT IMSAdminBase **ppAdminBase
  627. )
  628. {
  629. HRESULT hr = S_OK;
  630. COSERVERINFO csiName;
  631. COSERVERINFO *pcsiParam = &csiName;
  632. IClassFactory * pcsfFactory = NULL;
  633. IMSAdminBase * pAdminBase = NULL;
  634. IMSAdminBase * pAdminBaseT = NULL;
  635. memset(pcsiParam, 0, sizeof(COSERVERINFO));
  636. //
  637. // special case to handle "localhost" to work-around ole32 bug
  638. //
  639. if (pszServerName == NULL || _wcsicmp(pszServerName,L"localhost") == 0) {
  640. pcsiParam->pwszName = NULL;
  641. }
  642. else {
  643. pcsiParam->pwszName = pszServerName;
  644. }
  645. csiName.pAuthInfo = NULL;
  646. pcsiParam = &csiName;
  647. hr = CoGetClassObject(
  648. CLSID_MSAdminBase,
  649. CLSCTX_SERVER,
  650. pcsiParam,
  651. IID_IClassFactory,
  652. (void**) &pcsfFactory
  653. );
  654. BAIL_ON_FAILURE(hr);
  655. hr = pcsfFactory->CreateInstance(
  656. NULL,
  657. IID_IMSAdminBase,
  658. (void **) &pAdminBaseT
  659. );
  660. BAIL_ON_FAILURE(hr);
  661. hr = pAdminBaseT->UnmarshalInterface((IMSAdminBaseW **)&pAdminBase);
  662. pAdminBaseT->Release();
  663. pAdminBaseT = NULL;
  664. BAIL_ON_FAILURE(hr);
  665. *ppAdminBase = pAdminBase;
  666. error:
  667. if (pcsfFactory) {
  668. pcsfFactory->Release();
  669. }
  670. RRETURN(hr);
  671. }
  672. VOID
  673. UninitAdminBase(
  674. IN IMSAdminBase * pAdminBase
  675. )
  676. {
  677. if (pAdminBase != NULL) {
  678. pAdminBase->Release();
  679. }
  680. }
  681. HRESULT
  682. InitServerInfo(
  683. IN LPWSTR pszServerName,
  684. OUT IMSAdminBase ** ppObject,
  685. OUT IIsSchema **ppSchema
  686. )
  687. {
  688. HRESULT hr = S_OK;
  689. IMSAdminBase * pAdminBase = NULL;
  690. IIsSchema * pSchema = NULL;
  691. SERVER_CACHE_ITEM * item;
  692. BOOL Success;
  693. DWORD dwThreadId;
  694. ASSERT(g_pServerCache != NULL);
  695. //
  696. // We'll return the localhost machine config to the users if
  697. // pszServerName == NULL, e.g. IIS:
  698. //
  699. if (pszServerName == NULL) {
  700. pszServerName = L"Localhost";
  701. }
  702. dwThreadId = GetCurrentThreadId();
  703. if ((item = g_pServerCache->Find(pszServerName, dwThreadId)) == NULL) {
  704. //
  705. // get pAdminBase and pSchema
  706. //
  707. hr = InitAdminBase(pszServerName, &pAdminBase);
  708. BAIL_ON_FAILURE(hr);
  709. hr = GetSchema(pszServerName, &pSchema);
  710. if( ERROR_PATH_NOT_FOUND == HRESULT_CODE(hr) ||
  711. MD_ERROR_DATA_NOT_FOUND == hr
  712. )
  713. {
  714. // Return custom error.
  715. hr = MD_ERROR_IISAO_INVALID_SCHEMA;
  716. }
  717. BAIL_ON_FAILURE(hr);
  718. item = new SERVER_CACHE_ITEM(pszServerName,
  719. pAdminBase,
  720. pSchema,
  721. dwThreadId,
  722. Success);
  723. if (item == NULL || !Success) {
  724. if (item != NULL) {
  725. delete pSchema;
  726. UninitAdminBase(pAdminBase);
  727. delete item;
  728. }
  729. RRETURN(E_OUTOFMEMORY); // OUT_OF_MEMORY;
  730. }
  731. if (g_pServerCache->Insert(item) == FALSE) {
  732. delete pSchema;
  733. UninitAdminBase(pAdminBase);
  734. delete item;
  735. RRETURN(E_OUTOFMEMORY); // OUT_OF_MEMORY;
  736. }
  737. }
  738. *ppSchema = item->pSchema;
  739. *ppObject = item->pAdminBase;
  740. error :
  741. RRETURN(hr);
  742. }
  743. HRESULT
  744. MetaBaseGetDataPaths(
  745. IN IMSAdminBase *pAdminBase,
  746. IN METADATA_HANDLE hObjHandle,
  747. IN DWORD dwMDMetaID,
  748. OUT LPBYTE * ppBuffer
  749. )
  750. {
  751. LPBYTE pBuffer = NULL;
  752. HRESULT hr = S_OK;
  753. DWORD dwBufferSize = 0;
  754. DWORD dwReqdBufferSize = 0;
  755. hr = pAdminBase->GetDataPaths(
  756. hObjHandle,
  757. (LPWSTR)L"",
  758. dwMDMetaID,
  759. ALL_METADATA,
  760. dwBufferSize,
  761. (LPWSTR)L"",
  762. &dwReqdBufferSize
  763. );
  764. pBuffer = (LPBYTE) AllocADsMem(dwReqdBufferSize*sizeof(WCHAR));
  765. if (!pBuffer) {
  766. hr = HRESULT_FROM_WIN32(GetLastError());
  767. BAIL_ON_FAILURE(hr);
  768. }
  769. dwBufferSize = dwReqdBufferSize;
  770. hr = pAdminBase->GetDataPaths(
  771. hObjHandle,
  772. (LPWSTR)L"",
  773. dwMDMetaID,
  774. ALL_METADATA,
  775. dwBufferSize,
  776. (LPWSTR)pBuffer,
  777. &dwReqdBufferSize
  778. );
  779. BAIL_ON_FAILURE(hr);
  780. *ppBuffer = pBuffer;
  781. RRETURN(hr);
  782. error:
  783. if (pBuffer) {
  784. FreeADsMem(pBuffer);
  785. }
  786. RRETURN(hr);
  787. }
  788. HRESULT
  789. MakeVariantFromStringArray(
  790. LPWSTR pszStr,
  791. LPWSTR pszList,
  792. VARIANT *pvVariant
  793. )
  794. {
  795. HRESULT hr = S_OK;
  796. SAFEARRAY *aList = NULL;
  797. SAFEARRAYBOUND aBound;
  798. LPWSTR pszStrList;
  799. WCHAR wchPath[MAX_PATH];
  800. if (pszList != NULL)
  801. {
  802. long nCount = 0;
  803. long i = 0;
  804. pszStrList = pszList;
  805. if (*pszStrList == L'\0') {
  806. nCount = 1;
  807. pszStrList++;
  808. }
  809. while (*pszStrList != L'\0') {
  810. while (*pszStrList != L'\0') {
  811. pszStrList++;
  812. }
  813. nCount++;
  814. pszStrList++;
  815. }
  816. aBound.lLbound = 0;
  817. aBound.cElements = nCount;
  818. aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
  819. if ( aList == NULL )
  820. {
  821. hr = E_OUTOFMEMORY;
  822. BAIL_ON_FAILURE(hr);
  823. }
  824. pszStrList = pszList;
  825. for (i = 0; i < nCount; i++ )
  826. {
  827. VARIANT v;
  828. VariantInit(&v);
  829. V_VT(&v) = VT_BSTR;
  830. if (pszStr) {
  831. wcscpy((LPWSTR)wchPath, pszStr);
  832. wcscat((LPWSTR)wchPath, pszStrList);
  833. hr = ADsAllocString((LPWSTR)wchPath, &(V_BSTR(&v)));
  834. }
  835. else {
  836. hr = ADsAllocString( pszStrList, &(V_BSTR(&v)));
  837. }
  838. BAIL_ON_FAILURE(hr);
  839. hr = SafeArrayPutElement( aList, &i, &v );
  840. VariantClear(&v);
  841. BAIL_ON_FAILURE(hr);
  842. pszStrList += wcslen(pszStrList) + 1;
  843. }
  844. VariantInit( pvVariant );
  845. V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
  846. V_ARRAY(pvVariant) = aList;
  847. }
  848. else
  849. {
  850. aBound.lLbound = 0;
  851. aBound.cElements = 0;
  852. aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
  853. if ( aList == NULL )
  854. {
  855. hr = E_OUTOFMEMORY;
  856. BAIL_ON_FAILURE(hr);
  857. }
  858. VariantInit( pvVariant );
  859. V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
  860. V_ARRAY(pvVariant) = aList;
  861. }
  862. return S_OK;
  863. error:
  864. if ( aList )
  865. SafeArrayDestroy( aList );
  866. return hr;
  867. }
  868. HRESULT
  869. MakeVariantFromPathArray(
  870. LPWSTR pszStr,
  871. LPWSTR pszList,
  872. VARIANT *pvVariant
  873. )
  874. {
  875. HRESULT hr = S_OK;
  876. SAFEARRAY *aList = NULL;
  877. SAFEARRAYBOUND aBound;
  878. LPWSTR pszStrList;
  879. LPWSTR pszConcatBuffer = NULL;
  880. DWORD cbConcatBuffer = 0;
  881. DWORD cbRequiredConcatBuffer = 0;
  882. DWORD nStrLen = 0;
  883. DWORD nPathStrLen = 0;
  884. if (pszList != NULL)
  885. {
  886. //
  887. // Count strings in pszList
  888. //
  889. long nCount = 0;
  890. long i = 0;
  891. pszStrList = pszList;
  892. while (*pszStrList != L'\0') {
  893. while (*pszStrList != L'\0') {
  894. pszStrList++;
  895. }
  896. nCount++;
  897. pszStrList++;
  898. }
  899. //
  900. // Allocate output array
  901. //
  902. aBound.lLbound = 0;
  903. aBound.cElements = nCount;
  904. aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
  905. if ( aList == NULL )
  906. {
  907. hr = E_OUTOFMEMORY;
  908. BAIL_ON_FAILURE(hr);
  909. }
  910. //
  911. // Prepare to copy our values from pszList to aList
  912. //
  913. if( pszStr )
  914. {
  915. nStrLen = wcslen( pszStr );
  916. }
  917. pszStrList = pszList;
  918. while ( *pszStrList != L'\0' )
  919. {
  920. VARIANT v;
  921. VariantInit(&v);
  922. V_VT(&v) = VT_BSTR;
  923. if (pszStr)
  924. {
  925. //
  926. // Reallocate our string buffer. Since the strings are
  927. // generally increasing in size, we'll allocate more space
  928. // than we need so we don't have to reallocate every time.
  929. //
  930. nPathStrLen = wcslen(pszStrList);
  931. cbRequiredConcatBuffer = ( nStrLen + nPathStrLen + 1 )
  932. * sizeof(WCHAR);
  933. if( cbRequiredConcatBuffer > cbConcatBuffer )
  934. {
  935. pszConcatBuffer = (LPWSTR)ReallocADsMem(
  936. pszConcatBuffer,
  937. cbConcatBuffer,
  938. 2 * cbRequiredConcatBuffer
  939. );
  940. if( pszConcatBuffer == NULL )
  941. {
  942. hr = E_OUTOFMEMORY;
  943. BAIL_ON_FAILURE(hr);
  944. }
  945. if( cbConcatBuffer == 0 )
  946. {
  947. // This is our first time through.
  948. wcscpy(pszConcatBuffer, pszStr);
  949. }
  950. cbConcatBuffer = 2 * cbRequiredConcatBuffer;
  951. }
  952. //
  953. // Copy the returned value into the buffer.
  954. //
  955. wcscpy(pszConcatBuffer + nStrLen, pszStrList);
  956. if (pszConcatBuffer[nStrLen + nPathStrLen - 1] == L'/')
  957. {
  958. pszConcatBuffer[nStrLen + nPathStrLen - 1] = L'\0';
  959. }
  960. hr = ADsAllocString(pszConcatBuffer, &(V_BSTR(&v)));
  961. }
  962. else {
  963. hr = ADsAllocString( pszStrList, &(V_BSTR(&v)));
  964. }
  965. BAIL_ON_FAILURE(hr);
  966. hr = SafeArrayPutElement( aList, &i, &v );
  967. VariantClear(&v);
  968. BAIL_ON_FAILURE(hr);
  969. pszStrList += wcslen(pszStrList) + 1;
  970. i++;
  971. }
  972. VariantInit( pvVariant );
  973. V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
  974. V_ARRAY(pvVariant) = aList;
  975. }
  976. else
  977. {
  978. aBound.lLbound = 0;
  979. aBound.cElements = 0;
  980. aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
  981. if ( aList == NULL )
  982. {
  983. hr = E_OUTOFMEMORY;
  984. BAIL_ON_FAILURE(hr);
  985. }
  986. VariantInit( pvVariant );
  987. V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
  988. V_ARRAY(pvVariant) = aList;
  989. }
  990. if( pszConcatBuffer )
  991. {
  992. FreeADsMem( pszConcatBuffer );
  993. }
  994. return S_OK;
  995. error:
  996. if( pszConcatBuffer )
  997. {
  998. FreeADsMem( pszConcatBuffer );
  999. }
  1000. if ( aList )
  1001. SafeArrayDestroy( aList );
  1002. return hr;
  1003. }
  1004. HRESULT
  1005. InitWamAdmin(
  1006. IN LPWSTR pszServerName,
  1007. OUT IWamAdmin2 **ppWamAdmin
  1008. )
  1009. {
  1010. HRESULT hr = S_OK;
  1011. COSERVERINFO csiName;
  1012. COSERVERINFO *pcsiParam = &csiName;
  1013. IClassFactory * pcsfFactory = NULL;
  1014. IWamAdmin2 * pWamAdmin = NULL;
  1015. memset(pcsiParam, 0, sizeof(COSERVERINFO));
  1016. //
  1017. // special case to handle "localhost" to work-around ole32 bug
  1018. //
  1019. if (pszServerName == NULL || _wcsicmp(pszServerName,L"localhost") == 0) {
  1020. pcsiParam->pwszName = NULL;
  1021. }
  1022. else {
  1023. pcsiParam->pwszName = pszServerName;
  1024. }
  1025. csiName.pAuthInfo = NULL;
  1026. pcsiParam = &csiName;
  1027. hr = CoGetClassObject(
  1028. CLSID_WamAdmin,
  1029. CLSCTX_SERVER,
  1030. pcsiParam,
  1031. IID_IClassFactory,
  1032. (void**) &pcsfFactory
  1033. );
  1034. BAIL_ON_FAILURE(hr);
  1035. hr = pcsfFactory->CreateInstance(
  1036. NULL,
  1037. IID_IWamAdmin2,
  1038. (void **) &pWamAdmin
  1039. );
  1040. BAIL_ON_FAILURE(hr);
  1041. *ppWamAdmin = pWamAdmin;
  1042. error:
  1043. if (pcsfFactory) {
  1044. pcsfFactory->Release();
  1045. }
  1046. RRETURN(hr);
  1047. }
  1048. VOID
  1049. UninitWamAdmin(
  1050. IN IWamAdmin2 *pWamAdmin
  1051. )
  1052. {
  1053. if (pWamAdmin != NULL) {
  1054. pWamAdmin->Release();
  1055. }
  1056. }
  1057. HRESULT
  1058. ConvertArrayToVariantArray(
  1059. VARIANT varSafeArray,
  1060. PVARIANT * ppVarArray,
  1061. PDWORD pdwNumVariants
  1062. )
  1063. {
  1064. HRESULT hr = S_OK;
  1065. DWORD dwSLBound = 0;
  1066. DWORD dwSUBound = 0;
  1067. DWORD dwNumVariants = 0;
  1068. DWORD i = 0;
  1069. VARIANT * pVarArray = NULL;
  1070. SAFEARRAY * pArray = NULL;
  1071. *pdwNumVariants = 0;
  1072. *ppVarArray = 0;
  1073. if(!(V_ISARRAY(&varSafeArray)))
  1074. RRETURN(E_FAIL);
  1075. //
  1076. // This handles by-ref and regular SafeArrays.
  1077. //
  1078. if (V_VT(&varSafeArray) & VT_BYREF)
  1079. pArray = *(V_ARRAYREF(&varSafeArray));
  1080. else
  1081. pArray = V_ARRAY(&varSafeArray);
  1082. //
  1083. // Check that there is only one dimension in this array
  1084. //
  1085. if (pArray && pArray->cDims != 1) {
  1086. hr = E_FAIL;
  1087. BAIL_ON_FAILURE(hr);
  1088. }
  1089. //
  1090. // Check that there is at least one element in this array
  1091. //
  1092. if (!pArray ||
  1093. ( pArray->rgsabound[0].cElements == 0) ) {
  1094. dwNumVariants = 1;
  1095. pVarArray = (PVARIANT)AllocADsMem(
  1096. sizeof(VARIANT)*dwNumVariants
  1097. );
  1098. if (!pVarArray) {
  1099. hr = E_OUTOFMEMORY;
  1100. BAIL_ON_FAILURE(hr);
  1101. }
  1102. VariantInit(pVarArray);
  1103. pVarArray->vt = VT_BSTR;
  1104. pVarArray->bstrVal = NULL;
  1105. }
  1106. else {
  1107. //
  1108. // We know that this is a valid single dimension array
  1109. //
  1110. hr = SafeArrayGetLBound(pArray,
  1111. 1,
  1112. (long FAR *)&dwSLBound
  1113. );
  1114. BAIL_ON_FAILURE(hr);
  1115. hr = SafeArrayGetUBound(pArray,
  1116. 1,
  1117. (long FAR *)&dwSUBound
  1118. );
  1119. BAIL_ON_FAILURE(hr);
  1120. dwNumVariants = dwSUBound - dwSLBound + 1;
  1121. pVarArray = (PVARIANT)AllocADsMem(
  1122. sizeof(VARIANT)*dwNumVariants
  1123. );
  1124. if (!pVarArray) {
  1125. hr = E_OUTOFMEMORY;
  1126. BAIL_ON_FAILURE(hr);
  1127. }
  1128. for (i = dwSLBound; i <= dwSUBound; i++) {
  1129. VariantInit(pVarArray + i);
  1130. hr = SafeArrayGetElement(pArray,
  1131. (long FAR *)&i,
  1132. (pVarArray + i)
  1133. );
  1134. CONTINUE_ON_FAILURE(hr);
  1135. }
  1136. }
  1137. *ppVarArray = pVarArray;
  1138. *pdwNumVariants = dwNumVariants;
  1139. error:
  1140. RRETURN(hr);
  1141. }
  1142. //
  1143. // Property helper functions
  1144. //
  1145. //
  1146. #define VALIDATE_PTR(pPtr) \
  1147. if (!pPtr) { \
  1148. hr = E_ADS_BAD_PARAMETER;\
  1149. }\
  1150. BAIL_ON_FAILURE(hr);
  1151. HRESULT
  1152. put_BSTR_Property(
  1153. IADs * pADsObject,
  1154. BSTR bstrPropertyName,
  1155. BSTR pSrcStringProperty
  1156. )
  1157. {
  1158. HRESULT hr = S_OK;
  1159. VARIANT varInputData;
  1160. hr = PackStringinVariant(
  1161. pSrcStringProperty,
  1162. &varInputData
  1163. );
  1164. BAIL_ON_FAILURE(hr);
  1165. hr = pADsObject->Put(
  1166. bstrPropertyName,
  1167. varInputData
  1168. );
  1169. BAIL_ON_FAILURE(hr);
  1170. error:
  1171. VariantClear( &varInputData );
  1172. RRETURN(hr);
  1173. }
  1174. HRESULT
  1175. get_BSTR_Property(
  1176. IADs * pADsObject,
  1177. BSTR bstrPropertyName,
  1178. BSTR *ppDestStringProperty
  1179. )
  1180. {
  1181. HRESULT hr = S_OK;
  1182. VARIANT varOutputData;
  1183. VALIDATE_PTR( ppDestStringProperty );
  1184. VariantInit( &varOutputData );
  1185. hr = pADsObject->Get(
  1186. bstrPropertyName,
  1187. &varOutputData
  1188. );
  1189. BAIL_ON_FAILURE(hr);
  1190. hr = UnpackStringfromVariant(
  1191. varOutputData,
  1192. ppDestStringProperty
  1193. );
  1194. BAIL_ON_FAILURE(hr);
  1195. error:
  1196. VariantClear( &varOutputData );
  1197. RRETURN(hr);
  1198. }
  1199. HRESULT
  1200. put_LONG_Property(
  1201. IADs * pADsObject,
  1202. BSTR bstrPropertyName,
  1203. LONG lSrcProperty
  1204. )
  1205. {
  1206. HRESULT hr = S_OK;
  1207. VARIANT varInputData;
  1208. hr = PackLONGinVariant(
  1209. lSrcProperty,
  1210. &varInputData
  1211. );
  1212. BAIL_ON_FAILURE(hr);
  1213. hr = pADsObject->Put(
  1214. bstrPropertyName,
  1215. varInputData
  1216. );
  1217. BAIL_ON_FAILURE(hr);
  1218. error:
  1219. VariantClear( &varInputData );
  1220. RRETURN(hr);
  1221. }
  1222. HRESULT
  1223. get_LONG_Property(
  1224. IADs * pADsObject,
  1225. BSTR bstrPropertyName,
  1226. PLONG plDestProperty
  1227. )
  1228. {
  1229. HRESULT hr = S_OK;
  1230. VARIANT varOutputData;
  1231. VALIDATE_PTR( plDestProperty );
  1232. VariantInit( &varOutputData );
  1233. hr = pADsObject->Get(
  1234. bstrPropertyName,
  1235. &varOutputData
  1236. );
  1237. BAIL_ON_FAILURE(hr);
  1238. hr = UnpackLONGfromVariant(
  1239. varOutputData,
  1240. plDestProperty
  1241. );
  1242. BAIL_ON_FAILURE(hr);
  1243. error:
  1244. VariantClear( &varOutputData );
  1245. RRETURN(hr);
  1246. }
  1247. HRESULT
  1248. put_DATE_Property(
  1249. IADs * pADsObject,
  1250. BSTR bstrPropertyName,
  1251. DATE daSrcProperty
  1252. )
  1253. {
  1254. HRESULT hr = S_OK;
  1255. VARIANT varInputData;
  1256. hr = PackDATEinVariant(
  1257. daSrcProperty,
  1258. &varInputData
  1259. );
  1260. BAIL_ON_FAILURE(hr);
  1261. hr = pADsObject->Put(
  1262. bstrPropertyName,
  1263. varInputData
  1264. );
  1265. BAIL_ON_FAILURE(hr);
  1266. error:
  1267. VariantClear( &varInputData );
  1268. RRETURN(hr);
  1269. }
  1270. HRESULT
  1271. put_VARIANT_BOOL_Property(
  1272. IADs * pADsObject,
  1273. BSTR bstrPropertyName,
  1274. VARIANT_BOOL fSrcProperty
  1275. )
  1276. {
  1277. HRESULT hr = S_OK;
  1278. VARIANT varInputData;
  1279. hr = PackVARIANT_BOOLinVariant(
  1280. fSrcProperty,
  1281. &varInputData
  1282. );
  1283. BAIL_ON_FAILURE(hr);
  1284. hr = pADsObject->Put(
  1285. bstrPropertyName,
  1286. varInputData
  1287. );
  1288. BAIL_ON_FAILURE(hr);
  1289. error:
  1290. VariantClear( &varInputData );
  1291. RRETURN(hr);
  1292. }
  1293. HRESULT
  1294. get_VARIANT_BOOL_Property(
  1295. IADs * pADsObject,
  1296. BSTR bstrPropertyName,
  1297. PVARIANT_BOOL pfDestProperty
  1298. )
  1299. {
  1300. HRESULT hr = S_OK;
  1301. VARIANT varOutputData;
  1302. VALIDATE_PTR( pfDestProperty );
  1303. VariantInit( &varOutputData );
  1304. hr = pADsObject->Get(
  1305. bstrPropertyName,
  1306. &varOutputData
  1307. );
  1308. BAIL_ON_FAILURE(hr);
  1309. hr = UnpackVARIANT_BOOLfromVariant(
  1310. varOutputData,
  1311. pfDestProperty
  1312. );
  1313. BAIL_ON_FAILURE(hr);
  1314. error:
  1315. VariantClear( &varOutputData );
  1316. RRETURN(hr);
  1317. }
  1318. HRESULT
  1319. put_VARIANT_Property(
  1320. IADs * pADsObject,
  1321. BSTR bstrPropertyName,
  1322. VARIANT vSrcProperty
  1323. )
  1324. {
  1325. HRESULT hr = S_OK;
  1326. VARIANT varInputData;
  1327. hr = PackVARIANTinVariant(
  1328. vSrcProperty,
  1329. &varInputData
  1330. );
  1331. BAIL_ON_FAILURE(hr);
  1332. hr = pADsObject->Put(
  1333. bstrPropertyName,
  1334. varInputData
  1335. );
  1336. BAIL_ON_FAILURE(hr);
  1337. error:
  1338. VariantClear( &varInputData );
  1339. RRETURN(hr);
  1340. }
  1341. HRESULT
  1342. get_VARIANT_Property(
  1343. IADs * pADsObject,
  1344. BSTR bstrPropertyName,
  1345. PVARIANT pvDestProperty
  1346. )
  1347. {
  1348. HRESULT hr = S_OK;
  1349. VARIANT varOutputData;
  1350. VALIDATE_PTR( pvDestProperty );
  1351. VariantInit( &varOutputData );
  1352. hr = pADsObject->Get(
  1353. bstrPropertyName,
  1354. &varOutputData
  1355. );
  1356. BAIL_ON_FAILURE(hr);
  1357. hr = UnpackVARIANTfromVariant(
  1358. varOutputData,
  1359. pvDestProperty
  1360. );
  1361. BAIL_ON_FAILURE(hr);
  1362. error:
  1363. VariantClear( &varOutputData );
  1364. RRETURN(hr);
  1365. }
  1366. HRESULT
  1367. MetaBaseGetStringData(
  1368. IN IMSAdminBase * pAdminBase,
  1369. IN METADATA_HANDLE hObjHandle,
  1370. IN LPWSTR pszIISPathName,
  1371. IN DWORD dwMetaId,
  1372. OUT LPBYTE *ppBuffer
  1373. )
  1374. {
  1375. HRESULT hr = S_OK;
  1376. DWORD dwBufferSize = 0;
  1377. METADATA_RECORD mdrMDData;
  1378. LPBYTE pBuffer = NULL;
  1379. MD_SET_DATA_RECORD(&mdrMDData,
  1380. dwMetaId,
  1381. METADATA_NO_ATTRIBUTES,
  1382. ALL_METADATA,
  1383. STRING_METADATA,
  1384. dwBufferSize,
  1385. pBuffer);
  1386. hr = pAdminBase->GetData(
  1387. hObjHandle,
  1388. pszIISPathName,
  1389. &mdrMDData,
  1390. &dwBufferSize
  1391. );
  1392. pBuffer = (LPBYTE) AllocADsMem(dwBufferSize);
  1393. if (!pBuffer) {
  1394. hr = HRESULT_FROM_WIN32(GetLastError());
  1395. BAIL_ON_FAILURE(hr);
  1396. }
  1397. MD_SET_DATA_RECORD(&mdrMDData,
  1398. dwMetaId,
  1399. METADATA_NO_ATTRIBUTES,
  1400. ALL_METADATA,
  1401. STRING_METADATA,
  1402. dwBufferSize,
  1403. pBuffer);
  1404. hr = pAdminBase->GetData(
  1405. hObjHandle,
  1406. pszIISPathName,
  1407. &mdrMDData,
  1408. &dwBufferSize
  1409. );
  1410. BAIL_ON_FAILURE(hr);
  1411. *ppBuffer = pBuffer;
  1412. RRETURN(hr);
  1413. error:
  1414. if (pBuffer) {
  1415. FreeADsMem(pBuffer);
  1416. }
  1417. RRETURN(hr);
  1418. }
  1419. HRESULT
  1420. MetaBaseGetDwordData(
  1421. IN IMSAdminBase * pAdminBase,
  1422. IN METADATA_HANDLE hObjHandle,
  1423. IN LPWSTR pszIISPathName,
  1424. IN DWORD dwMetaId,
  1425. OUT PDWORD pdwData
  1426. )
  1427. {
  1428. HRESULT hr = S_OK;
  1429. DWORD dwBufferSize = sizeof(DWORD);
  1430. METADATA_RECORD mdrMDData;
  1431. LPBYTE pBuffer = (LPBYTE)pdwData;
  1432. MD_SET_DATA_RECORD(&mdrMDData,
  1433. dwMetaId,
  1434. METADATA_NO_ATTRIBUTES,
  1435. IIS_MD_UT_SERVER,
  1436. DWORD_METADATA,
  1437. dwBufferSize,
  1438. pBuffer);
  1439. hr = pAdminBase->GetData(
  1440. hObjHandle,
  1441. pszIISPathName,
  1442. &mdrMDData,
  1443. &dwBufferSize
  1444. );
  1445. RRETURN(hr);
  1446. }
  1447. HRESULT
  1448. MakeStringFromVariantArray(
  1449. VARIANT *pvVariant,
  1450. LPBYTE* ppBuffer
  1451. )
  1452. {
  1453. HRESULT hr = S_OK;
  1454. DWORD i;
  1455. DWORD dwLen = 0;
  1456. VARIANT *pVar;
  1457. LPBYTE pBuffer = NULL;
  1458. DWORD dwNumVars = 0;
  1459. VARIANT * pVarArray = NULL;
  1460. pVar = pvVariant;
  1461. if (pVar->vt == VT_EMPTY) {
  1462. RRETURN(S_OK);
  1463. }
  1464. hr = ConvertArrayToVariantArray(
  1465. *pVar,
  1466. &pVarArray,
  1467. &dwNumVars
  1468. );
  1469. BAIL_ON_FAILURE(hr);
  1470. if (dwNumVars == 0) {
  1471. RRETURN(S_OK);
  1472. }
  1473. //
  1474. // find out total length
  1475. //
  1476. pVar = pVarArray;
  1477. for (i = 0; i < dwNumVars; i++ ) {
  1478. //
  1479. // add 1 for comma
  1480. //
  1481. if (pVar->vt == VT_BSTR || pVar->vt == VT_EMPTY) {
  1482. if (pVar->bstrVal && *(pVar->bstrVal)) {
  1483. //
  1484. // validate parameter; check for ','
  1485. //
  1486. if (wcschr(pVar->bstrVal, L',')) {
  1487. hr = E_ADS_BAD_PARAMETER;
  1488. BAIL_ON_FAILURE(hr);
  1489. }
  1490. dwLen += (wcslen(pVar->bstrVal) + 1);
  1491. }
  1492. }
  1493. else {
  1494. hr = E_ADS_CANT_CONVERT_DATATYPE;
  1495. BAIL_ON_FAILURE(hr);
  1496. }
  1497. pVar++;
  1498. }
  1499. //
  1500. // if there are non-empty entries found in the array, copy them to buffer
  1501. //
  1502. if (dwLen != 0) {
  1503. pBuffer = (LPBYTE) AllocADsMem(dwLen*sizeof(WCHAR));
  1504. if (!pBuffer) {
  1505. hr = E_OUTOFMEMORY;
  1506. BAIL_ON_FAILURE(hr);
  1507. }
  1508. *ppBuffer = pBuffer;
  1509. pVar = pVarArray;
  1510. for (i = 0; i < dwNumVars; i++, pVar++ ) {
  1511. if (pVar->bstrVal && *(pVar->bstrVal)) {
  1512. memcpy(pBuffer, pVar->bstrVal,
  1513. wcslen(pVar->bstrVal)*sizeof(WCHAR));
  1514. pBuffer = pBuffer + wcslen(pVar->bstrVal)*sizeof(WCHAR);
  1515. if (i != dwNumVars -1) {
  1516. memcpy(pBuffer, L",", sizeof(WCHAR));
  1517. pBuffer = pBuffer + sizeof(WCHAR);
  1518. }
  1519. }
  1520. }
  1521. if (*ppBuffer == pBuffer - dwLen*sizeof(WCHAR)) {
  1522. pBuffer -= sizeof(WCHAR);
  1523. *pBuffer = L'\0';
  1524. }
  1525. else {
  1526. *pBuffer = L'\0';
  1527. }
  1528. }
  1529. error:
  1530. if (pVarArray) {
  1531. for (i = 0; i < dwNumVars; i++) {
  1532. VariantClear(pVarArray + i);
  1533. }
  1534. FreeADsMem(pVarArray);
  1535. }
  1536. if (FAILED(hr) && pBuffer) {
  1537. FreeADsMem(pBuffer);
  1538. }
  1539. RRETURN(hr);
  1540. }
  1541. HRESULT
  1542. CheckVariantDataType(
  1543. PVARIANT pVar,
  1544. VARTYPE vt
  1545. )
  1546. {
  1547. HRESULT hr;
  1548. hr = VariantChangeType(pVar,
  1549. pVar,
  1550. 0,
  1551. vt);
  1552. if (FAILED(hr)) {
  1553. if (hr == E_OUTOFMEMORY) {
  1554. RRETURN(hr);
  1555. }
  1556. RRETURN(hr = E_ADS_CANT_CONVERT_DATATYPE);
  1557. }
  1558. RRETURN(hr);
  1559. }
  1560. HRESULT
  1561. MakeMultiStringFromVariantArray(
  1562. VARIANT *pvVariant,
  1563. LPBYTE* ppBuffer
  1564. )
  1565. {
  1566. HRESULT hr = S_OK;
  1567. DWORD i;
  1568. DWORD dwLen = 0;
  1569. VARIANT *pVar;
  1570. LPBYTE pBuffer = NULL;
  1571. DWORD dwNumVars = 0;
  1572. VARIANT * pVarArray = NULL;
  1573. pVar = pvVariant;
  1574. if (pVar->vt == VT_EMPTY) {
  1575. RRETURN(S_OK);
  1576. }
  1577. hr = ConvertArrayToVariantArray(
  1578. *pVar,
  1579. &pVarArray,
  1580. &dwNumVars
  1581. );
  1582. BAIL_ON_FAILURE(hr);
  1583. if (dwNumVars == 0) {
  1584. RRETURN(S_OK);
  1585. }
  1586. //
  1587. // find out total length
  1588. //
  1589. pVar = pVarArray;
  1590. for (i = 0; i < dwNumVars; i++ ) {
  1591. if (pVar->vt == VT_BSTR) {
  1592. if (pVar->bstrVal && *(pVar->bstrVal)) {
  1593. dwLen += (wcslen(pVar->bstrVal) + 1);
  1594. }
  1595. else {
  1596. //
  1597. // add 1 for \0
  1598. //
  1599. dwLen++;
  1600. }
  1601. }
  1602. else {
  1603. hr = E_ADS_CANT_CONVERT_DATATYPE;
  1604. BAIL_ON_FAILURE(hr);
  1605. }
  1606. pVar++;
  1607. }
  1608. //
  1609. // +1 for extra \0
  1610. //
  1611. dwLen++;
  1612. //
  1613. // copy entries to buffer
  1614. //
  1615. if (dwLen != 0) {
  1616. pBuffer = (LPBYTE) AllocADsMem(dwLen*sizeof(WCHAR));
  1617. if (!pBuffer) {
  1618. hr = E_OUTOFMEMORY;
  1619. BAIL_ON_FAILURE(hr);
  1620. }
  1621. *ppBuffer = pBuffer;
  1622. pVar = pVarArray;
  1623. for (i = 0; i < dwNumVars; i++, pVar++ ) {
  1624. if (pVar->bstrVal && *(pVar->bstrVal)) {
  1625. memcpy(pBuffer, pVar->bstrVal,
  1626. wcslen(pVar->bstrVal)*sizeof(WCHAR));
  1627. pBuffer = pBuffer + wcslen(pVar->bstrVal)*sizeof(WCHAR);
  1628. }
  1629. memcpy(pBuffer, L"\0", sizeof(WCHAR));
  1630. pBuffer = pBuffer + sizeof(WCHAR);
  1631. }
  1632. *pBuffer = L'\0';
  1633. }
  1634. error:
  1635. if (pVarArray) {
  1636. for (i = 0; i < dwNumVars; i++) {
  1637. VariantClear(pVarArray + i);
  1638. }
  1639. FreeADsMem(pVarArray);
  1640. }
  1641. if (FAILED(hr) && pBuffer) {
  1642. FreeADsMem(pBuffer);
  1643. }
  1644. RRETURN(hr);
  1645. }