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.

1797 lines
44 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: cadssec.cxx
  7. //
  8. // Contents: This file contains the support ADsSecurityUtility class
  9. // implementation and the support routines it requires. The
  10. // default interface for the ADsSecurityClassUtility class
  11. // is IADsSecurityUtility.
  12. //
  13. // History: 10-11-00 AjayR Created.
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "oleds.hxx"
  17. //
  18. // Helper functions.
  19. //
  20. //+---------------------------------------------------------------------------
  21. // Function: GetServerAndResource - Helper routine.
  22. //
  23. // Synopsis: Splits the string into a serverName piece and rest piece.
  24. // This is used for fileshare paths like \\Computer\share to return
  25. // \\computer and share. In the case of registry a string like
  26. // \\Computer\HKLM\Microsoft will be split into \\Computer and
  27. // HKLM\Microsoft. if there is no computer name specified, then
  28. // the serverName will be NULL.
  29. //
  30. // Arguments: pszName - Name to be split.
  31. // ppszServer - Return value for server name.
  32. // ppszResource - Return value for rest of string.
  33. //
  34. // Returns: S_OK or any appropriate error code.
  35. //
  36. // Modifies: ppSD and pdwLength on success.
  37. //
  38. //----------------------------------------------------------------------------
  39. HRESULT
  40. GetServerAndResource(
  41. LPWSTR pszName,
  42. LPWSTR *ppszServer,
  43. LPWSTR *ppszResource
  44. )
  45. {
  46. HRESULT hr = S_OK;
  47. DWORD dwLength = wcslen(pszName);
  48. LPWSTR pszTemp = pszName;
  49. LPWSTR pszServer = NULL;
  50. LPWSTR pszResource = NULL;
  51. DWORD dwLen = 0;
  52. BOOL fNoServer = FALSE;
  53. *ppszServer = NULL;
  54. *ppszResource = NULL;
  55. //
  56. // If we have just 1 \ or no \'s there is no server name.
  57. //
  58. if ((dwLength < 2)
  59. || (pszName[0] != L'\\')
  60. || (pszName[1] != L'\\')
  61. ) {
  62. fNoServer = TRUE;
  63. }
  64. if (fNoServer) {
  65. //
  66. // Name is the entire string passed in.
  67. //
  68. pszResource = AllocADsStr(pszName);
  69. if (!pszResource) {
  70. BAIL_ON_FAILURE(hr = E_FAIL);
  71. }
  72. *ppszResource = pszResource;
  73. RRETURN(hr);
  74. }
  75. //
  76. // Make sure that the first 2 chars are \\
  77. //
  78. if (pszTemp[0] != L'\\'
  79. || pszTemp[1] != L'\\' )
  80. {
  81. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  82. }
  83. pszTemp += 2;
  84. while (pszTemp && *pszTemp != L'\\') {
  85. dwLen++;
  86. pszTemp++;
  87. }
  88. if (!pszTemp
  89. || !*pszTemp
  90. || !dwLen
  91. ) {
  92. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  93. }
  94. dwLen += 2; // the 2 \\ in the serverName
  95. //
  96. // Advance past the \ in \\testShare\FileShare.
  97. //
  98. pszTemp++;
  99. if (!pszTemp || !*pszTemp) {
  100. BAIL_ON_FAILURE(hr = E_INVALIDARG)
  101. }
  102. //
  103. // If we get here we have valid server and share names.
  104. //
  105. pszServer = (LPWSTR) AllocADsMem((dwLen+1) * sizeof(WCHAR));
  106. if (!pszServer) {
  107. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  108. }
  109. wcsncpy(pszServer, pszName, dwLen);
  110. pszResource = AllocADsStr(pszTemp);
  111. if (!pszResource) {
  112. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  113. }
  114. *ppszServer = pszServer;
  115. *ppszResource = pszResource;
  116. error:
  117. if (FAILED(hr)) {
  118. if (pszResource) {
  119. FreeADsMem(pszResource);
  120. }
  121. if (pszServer) {
  122. FreeADsMem(pszServer);
  123. }
  124. }
  125. RRETURN(hr);
  126. }
  127. //+---------------------------------------------------------------------------
  128. // Function: GetKeyRootAndSubKey - Helper routine.
  129. //
  130. // Synopsis: Gets the root (such as HKLM) from the registry key path. This
  131. // is needed when we open a handle to the key. The rest of the path
  132. // constitutes the SubKey name.
  133. //
  134. // Arguments: pszKeyName - Name of the key we need to open.
  135. // ppszSubKey - Return value for the subKey
  136. // phKey - Return value for key root to open.
  137. //
  138. // Returns: S_OK or any appropriate error code.
  139. //
  140. // Modifies: phKey, NULL on failure and one of
  141. // HKEY_USERS, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG,
  142. // HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT
  143. // or HKEY_PERFORMANCE_DATA on success.
  144. //
  145. //----------------------------------------------------------------------------
  146. HRESULT
  147. GetKeyRootAndSubKey(
  148. LPWSTR pszKeyName,
  149. LPWSTR * ppszSubKey,
  150. HKEY * phKey
  151. )
  152. {
  153. HRESULT hr = S_OK;
  154. HKEY hKey = NULL;
  155. LPWSTR pszRoot = NULL;
  156. LPWSTR pszTemp = pszKeyName;
  157. LPWSTR pszSubKey = NULL;
  158. DWORD dwLen = 0;
  159. *phKey = NULL;
  160. *ppszSubKey = NULL;
  161. while (pszTemp
  162. && *pszTemp
  163. && *pszTemp != L'\\') {
  164. dwLen++;
  165. pszTemp++;
  166. }
  167. //
  168. // If the length is less than 3 something is wrong.
  169. //
  170. if ((dwLen < 3)
  171. || !pszTemp
  172. || !*pszTemp
  173. ) {
  174. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  175. }
  176. //
  177. // To get the subkey, we need to move past the \.
  178. //
  179. pszTemp++;
  180. if (pszTemp && *pszTemp) {
  181. pszSubKey = AllocADsStr(pszTemp);
  182. if (!pszSubKey) {
  183. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  184. }
  185. }
  186. pszRoot = (LPWSTR) AllocADsMem((dwLen+1) * sizeof(WCHAR));
  187. if (!pszRoot) {
  188. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  189. }
  190. //
  191. // Copy over the root so we can use it in the subsequent comparisions.
  192. //
  193. wcsncpy(pszRoot, pszKeyName, dwLen);
  194. if (_wcsicmp( pszRoot, L"HKEY_CLASSES_ROOT") == 0
  195. || _wcsicmp( pszRoot, L"HKCR") == 0
  196. ) {
  197. hKey = HKEY_CLASSES_ROOT;
  198. }
  199. else if (_wcsicmp( pszRoot, L"HKEY_LOCAL_MACHINE") == 0
  200. || _wcsicmp( pszRoot, L"HKLM") == 0
  201. ) {
  202. hKey = HKEY_LOCAL_MACHINE;
  203. }
  204. else if (_wcsicmp(pszRoot, L"HKEY_CURRENT_CONFIG") == 0
  205. || _wcsicmp(pszRoot, L"HKCC") == 0
  206. ) {
  207. hKey = HKEY_CURRENT_CONFIG;
  208. }
  209. else if (_wcsicmp(pszRoot, L"HKEY_CURRENT_USER" ) == 0
  210. || _wcsicmp( pszRoot, L"HKCU") == 0
  211. ) {
  212. hKey = HKEY_CURRENT_USER;
  213. }
  214. else if (_wcsicmp(pszRoot, L"HKEY_USERS") == 0
  215. || _wcsicmp(pszRoot, L"HKU")
  216. ) {
  217. hKey = HKEY_USERS;
  218. }
  219. else if ( _wcsicmp(pszRoot, L"HKEY_PERFORMANCE_DATA") == 0) {
  220. hKey = HKEY_PERFORMANCE_DATA;
  221. }
  222. else {
  223. //
  224. // Has to be one of the above.
  225. //
  226. BAIL_ON_FAILURE(hr = E_FAIL);
  227. }
  228. *phKey = hKey;
  229. *ppszSubKey = pszSubKey;
  230. error:
  231. if (pszRoot) {
  232. FreeADsStr(pszRoot);
  233. }
  234. if (FAILED(hr) && pszSubKey) {
  235. FreeADsStr(pszSubKey);
  236. }
  237. RRETURN(hr);
  238. }
  239. //+---------------------------------------------------------------------------
  240. // Function: ConvertRawSDToBinary - Helper routine.
  241. //
  242. // Synopsis: Converts the binary SD to a VT_UI1 | VT_ARRAY.
  243. //
  244. // Arguments: pSecurityDescriptor - Binary sd to convert.
  245. // dwLength - Length of SD.
  246. // pVariant - Return value.
  247. //
  248. // Returns: S_OK or any appropriate error code.
  249. //
  250. // Modifies: pVariant to point to IID_IADsSecurityDescriptor on success.
  251. //
  252. //----------------------------------------------------------------------------
  253. HRESULT
  254. ConvertRawSDToBinary(
  255. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  256. DWORD dwLength,
  257. VARIANT *pVariant
  258. )
  259. {
  260. HRESULT hr = S_OK;
  261. SAFEARRAY * aList = NULL;
  262. SAFEARRAYBOUND aBound;
  263. CHAR HUGEP *pArray = NULL;
  264. aBound.lLbound = 0;
  265. aBound.cElements = dwLength;
  266. aList = SafeArrayCreate( VT_UI1, 1, &aBound );
  267. if (!aList) {
  268. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  269. }
  270. hr = SafeArrayAccessData( aList, (void HUGEP * FAR *) &pArray );
  271. BAIL_ON_FAILURE(hr);
  272. memcpy( pArray, pSecurityDescriptor, aBound.cElements );
  273. SafeArrayUnaccessData( aList );
  274. V_VT(pVariant) = VT_ARRAY | VT_UI1;
  275. V_ARRAY(pVariant) = aList;
  276. RRETURN(hr);
  277. error:
  278. if ( aList ) {
  279. SafeArrayDestroy( aList );
  280. }
  281. RRETURN(hr);
  282. }
  283. //+---------------------------------------------------------------------------
  284. // Function: ConvertRawSDToHexString - Helper routine.
  285. //
  286. // Synopsis: Converts the binary SD to a VT_BSTR in hex string format.
  287. //
  288. // Arguments: pSecurityDescriptor - Binary sd to convert.
  289. // dwLength - Length of SD.
  290. // pVariant - Return value for VT_BSTR.
  291. //
  292. // Returns: S_OK or any appropriate error code.
  293. //
  294. // Modifies: pVariant to point to IID_IADsSecurityDescriptor on success.
  295. //
  296. //----------------------------------------------------------------------------
  297. HRESULT
  298. ConvertRawSDToHexString(
  299. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  300. DWORD dwLength,
  301. VARIANT *pVariant
  302. )
  303. {
  304. HRESULT hr = S_OK;
  305. LPWSTR pszHexStr = NULL;
  306. BSTR bstrHexSD = NULL;
  307. WCHAR szSmallStr[10];
  308. pszHexStr = (LPWSTR) AllocADsMem((dwLength+1) * 2 * sizeof(WCHAR));
  309. if (!pszHexStr) {
  310. BAIL_ON_FAILURE(hr);
  311. }
  312. for (DWORD dwCtr = 0; dwCtr < dwLength; dwCtr++) {
  313. wsprintf(
  314. szSmallStr,
  315. L"%02x",
  316. ((BYTE*)pSecurityDescriptor)[dwCtr]
  317. );
  318. wcscat(pszHexStr, szSmallStr);
  319. }
  320. hr = ADsAllocString(pszHexStr, &bstrHexSD);
  321. if (SUCCEEDED(hr)) {
  322. pVariant->vt = VT_BSTR;
  323. pVariant->bstrVal = bstrHexSD;
  324. }
  325. error:
  326. if (pszHexStr) {
  327. FreeADsMem(pszHexStr);
  328. }
  329. RRETURN(hr);
  330. }
  331. //+---------------------------------------------------------------------------
  332. // Function: ConvertHexSDToRawSD - Helper routine.
  333. //
  334. // Synopsis: Converts the hex string SD to a binary SD.
  335. //
  336. // Arguments: pVarHexSD - Variant with hex string.
  337. // ppSecurityDescriptor - Return value for binary SD
  338. // pdwLength - Return value for length of SD.
  339. //
  340. // Returns: S_OK or any appropriate error code.
  341. //
  342. // Modifies: ppSecurityDescriptor and pdwLength updated accordingly.
  343. //
  344. //----------------------------------------------------------------------------
  345. HRESULT
  346. ConvertHexSDToRawSD(
  347. PVARIANT pVarHexSD,
  348. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  349. DWORD *pdwLength
  350. )
  351. {
  352. HRESULT hr = S_OK;
  353. LPWSTR pszHexSD = V_BSTR(pVarHexSD);
  354. DWORD dwLen;
  355. LPBYTE lpByte = NULL;
  356. *ppSecurityDescriptor = NULL;
  357. *pdwLength = 0;
  358. if (!pszHexSD
  359. || ((dwLen = wcslen(pszHexSD)) == 0)
  360. ) {
  361. //
  362. // NULL SD.
  363. //
  364. RRETURN(S_OK);
  365. }
  366. dwLen = wcslen(pszHexSD);
  367. //
  368. // Length has to be even.
  369. //
  370. if (((dwLen/2) * 2) != dwLen) {
  371. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  372. }
  373. dwLen /= 2;
  374. if (dwLen) {
  375. lpByte = (LPBYTE) AllocADsMem(dwLen);
  376. if (!lpByte) {
  377. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  378. }
  379. //
  380. // Go through and read one 2 hex chars at a time.
  381. //
  382. for (
  383. DWORD dwCtr = 0;
  384. (dwCtr < dwLen) && (pszHexSD && *pszHexSD);
  385. dwCtr++ ) {
  386. DWORD dwCount, dwHexVal;
  387. dwCount = swscanf(pszHexSD, L"%02x", &dwHexVal);
  388. //
  389. // The read has to be successful and the data valid.
  390. //
  391. if (dwCount != 1) {
  392. BAIL_ON_FAILURE(hr = E_FAIL);
  393. }
  394. //
  395. // Make sure that the value is in the correct range.
  396. //
  397. if (dwHexVal & (0xFFFFFF00)) {
  398. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  399. }
  400. lpByte[dwCtr] = (BYTE) dwHexVal;
  401. pszHexSD++;
  402. if (!pszHexSD) {
  403. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  404. }
  405. pszHexSD++;
  406. } // for loop
  407. //
  408. // The sd translation was succesful.
  409. //
  410. *ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)(LPVOID) lpByte;
  411. *pdwLength = dwLen;
  412. } // if the string had any data in it.
  413. error:
  414. if (FAILED(hr) && lpByte) {
  415. FreeADsMem(lpByte);
  416. }
  417. RRETURN(hr);
  418. }
  419. //+---------------------------------------------------------------------------
  420. // Function: ConvertBinarySDToRawSD - Helper routine.
  421. //
  422. // Synopsis: Converts a VT_UI1 | VT_ARRAY to a binary SD.
  423. //
  424. // Arguments: pvVarBinSD - The input variant array to convert.
  425. // ppSecurityDescriptor - Return value for binary sd.
  426. // pdwLength - Return value for length of binary sd.
  427. //
  428. // Returns: S_OK or any appropriate error code.
  429. //
  430. // Modifies: ppSecurityDescriptor and pdwLength modified appropriately.
  431. //
  432. //----------------------------------------------------------------------------
  433. HRESULT
  434. ConvertBinarySDToRawSD(
  435. PVARIANT pvVarBinSD,
  436. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  437. DWORD *pdwLength
  438. )
  439. {
  440. HRESULT hr = S_OK;
  441. LPVOID lpMem = NULL;
  442. long lBoundLower = -1;
  443. long lBoundUpper = -1;
  444. CHAR HUGEP *pArray = NULL;
  445. *ppSecurityDescriptor = NULL;
  446. *pdwLength = 0;
  447. //
  448. // Make sure we have an array and then get length.
  449. //
  450. if( pvVarBinSD->vt != (VT_ARRAY | VT_UI1)) {
  451. RRETURN(hr = E_ADS_CANT_CONVERT_DATATYPE);
  452. }
  453. hr = SafeArrayGetLBound(
  454. V_ARRAY(pvVarBinSD),
  455. 1,
  456. &lBoundLower
  457. );
  458. BAIL_ON_FAILURE(hr);
  459. hr = SafeArrayGetUBound(
  460. V_ARRAY(pvVarBinSD),
  461. 1,
  462. &lBoundUpper
  463. );
  464. BAIL_ON_FAILURE(hr);
  465. if ((lBoundUpper == -1)
  466. && (lBoundLower == -1)
  467. ) {
  468. //
  469. // Nothing further to do in this case.
  470. //
  471. ;
  472. }
  473. else {
  474. long lLength;
  475. lLength = (lBoundUpper - lBoundLower) + 1;
  476. lpMem = AllocADsMem(lLength);
  477. if (!lpMem) {
  478. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  479. }
  480. hr = SafeArrayAccessData(
  481. V_ARRAY(pvVarBinSD),
  482. (void HUGEP * FAR *) &pArray
  483. );
  484. BAIL_ON_FAILURE(hr);
  485. memcpy(lpMem, pArray, lLength);
  486. SafeArrayUnaccessData(V_ARRAY(pvVarBinSD));
  487. *ppSecurityDescriptor = (PSECURITY_DESCRIPTOR) lpMem;
  488. *pdwLength = (DWORD) lLength;
  489. }
  490. error:
  491. if (FAILED(hr) && lpMem) {
  492. FreeADsMem(lpMem);
  493. }
  494. RRETURN(hr);
  495. }
  496. //+---------------------------------------------------------------------------
  497. // Function: GetRawSDFromFile - Helper routine.
  498. //
  499. // Synopsis: Gets the security descriptor from the file in binary format.
  500. //
  501. // Arguments: pszFileName - Name of file to get sd from.
  502. // secInfo - Security mask to use for the operation.
  503. // ppSD - Return value for the SD.
  504. // pdwLength - Return value for the lenght of the SD.
  505. //
  506. // Returns: S_OK or any appropriate error code.
  507. //
  508. // Modifies: ppSD and pdwLength on success.
  509. //
  510. //----------------------------------------------------------------------------
  511. HRESULT
  512. GetRawSDFromFile(
  513. LPWSTR pszFileName,
  514. SECURITY_INFORMATION secInfo,
  515. PSECURITY_DESCRIPTOR *ppSD,
  516. PDWORD pdwLength
  517. )
  518. {
  519. HRESULT hr = S_OK;
  520. DWORD dwLength = 0;
  521. PSECURITY_DESCRIPTOR pSD = NULL;
  522. *ppSD = NULL;
  523. *pdwLength = 0;
  524. //
  525. // Get the length of the SD.
  526. //
  527. if (!GetFileSecurity(
  528. pszFileName,
  529. secInfo,
  530. NULL,
  531. 0,
  532. &dwLength
  533. )
  534. && (dwLength == 0)
  535. ) {
  536. //
  537. // There was an error.
  538. //
  539. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  540. }
  541. if (dwLength == 0) {
  542. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  543. }
  544. pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength);
  545. if (!pSD) {
  546. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  547. }
  548. if (!GetFileSecurity(
  549. pszFileName,
  550. secInfo,
  551. pSD,
  552. dwLength,
  553. &dwLength
  554. )
  555. ) {
  556. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  557. }
  558. *pdwLength = dwLength;
  559. *ppSD = pSD;
  560. error:
  561. if (FAILED(hr) && pSD) {
  562. FreeADsMem(pSD);
  563. }
  564. RRETURN(hr);
  565. }
  566. //+---------------------------------------------------------------------------
  567. // Function: SetRawSDToFile - Helper routine.
  568. //
  569. // Synopsis: Sets the binary security descriptor on the file.
  570. //
  571. // Arguments: pszFileName - Name of file to set sd on.
  572. // secInfo - Security mask to use for the operation.
  573. // pSD - Value of SD to set.
  574. // dwLength - Length of the sd.
  575. //
  576. // Returns: S_OK or any appropriate error code.
  577. //
  578. // Modifies: N/A.
  579. //
  580. //----------------------------------------------------------------------------
  581. HRESULT
  582. SetRawSDToFile(
  583. LPWSTR pszFileName,
  584. SECURITY_INFORMATION secInfo,
  585. PSECURITY_DESCRIPTOR pSD
  586. )
  587. {
  588. HRESULT hr = S_OK;
  589. if (!SetFileSecurity(
  590. pszFileName,
  591. secInfo,
  592. pSD
  593. )
  594. ) {
  595. RRETURN(HRESULT_FROM_WIN32(GetLastError()));
  596. }
  597. else {
  598. RRETURN(S_OK);
  599. }
  600. }
  601. //+---------------------------------------------------------------------------
  602. // Function: GetRawSDFromFileShare - Helper routine.
  603. //
  604. // Synopsis: Gets the security descriptor from the fileshare in bin format.
  605. //
  606. // Arguments: pszFileShareName - Name of fileshare to get sd from.
  607. // ppSD - Return value for the SD.
  608. // pdwLength - Return value for the lenght of the SD.
  609. //
  610. // Returns: S_OK or any appropriate error code.
  611. //
  612. // Modifies: ppSD and pdwLength on success.
  613. //
  614. //----------------------------------------------------------------------------
  615. HRESULT
  616. GetRawSDFromFileShare(
  617. LPWSTR pszFileShareName,
  618. PSECURITY_DESCRIPTOR *ppSD,
  619. PDWORD pdwLength
  620. )
  621. {
  622. HRESULT hr = S_OK;
  623. LPWSTR pszServerName = NULL;
  624. LPWSTR pszShareName = NULL;
  625. DWORD dwLength = 0;
  626. PSECURITY_DESCRIPTOR pSD = NULL;
  627. SHARE_INFO_502 * pShareInfo502 = NULL;
  628. NET_API_STATUS nasStatus = NERR_Success;
  629. *ppSD = NULL;
  630. *pdwLength = 0;
  631. //
  632. // We need to split the name into serverName and shareName
  633. //
  634. hr = GetServerAndResource(
  635. pszFileShareName,
  636. &pszServerName,
  637. &pszShareName
  638. );
  639. BAIL_ON_FAILURE(hr);
  640. //
  641. // Only 502 level call returns the SD Info.
  642. //
  643. nasStatus = NetShareGetInfo(
  644. pszServerName,
  645. pszShareName,
  646. 502,
  647. (LPBYTE *)&pShareInfo502
  648. );
  649. if (nasStatus != NERR_Success) {
  650. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  651. }
  652. //
  653. // If the SD is non NULL process the SD.
  654. //
  655. if (pShareInfo502->shi502_security_descriptor) {
  656. //
  657. // Get the length of the SD, it should not be 0.
  658. //
  659. SetLastError(0);
  660. dwLength = GetSecurityDescriptorLength(
  661. pShareInfo502->shi502_security_descriptor
  662. );
  663. //
  664. // The return length should not be zero.
  665. //
  666. if (dwLength == 0) {
  667. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  668. }
  669. pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength);
  670. if (!pSD) {
  671. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  672. }
  673. memcpy(pSD, pShareInfo502->shi502_security_descriptor, dwLength);
  674. *ppSD = pSD;
  675. *pdwLength = dwLength;
  676. }
  677. else {
  678. //
  679. // The SD was NULL the ret values are set correctly
  680. //
  681. ;
  682. }
  683. error:
  684. if (pszServerName) {
  685. FreeADsStr(pszServerName);
  686. }
  687. if (pszShareName) {
  688. FreeADsStr(pszShareName);
  689. }
  690. if (pShareInfo502) {
  691. NetApiBufferFree(pShareInfo502);
  692. }
  693. RRETURN(hr);
  694. }
  695. //+---------------------------------------------------------------------------
  696. // Function: SetRawSDToFileShare - Helper routine.
  697. //
  698. // Synopsis: Sets the binary SD on the fileshare.
  699. //
  700. // Arguments: pszFileShare - Name of fileshare to set sd on.
  701. // pSD - The SD to set.
  702. //
  703. // Returns: S_OK or any appropriate error code.
  704. //
  705. // Modifies: N/A.
  706. //
  707. //----------------------------------------------------------------------------
  708. HRESULT
  709. SetRawSDToFileShare(
  710. LPWSTR pszFileShare,
  711. PSECURITY_DESCRIPTOR pSD
  712. )
  713. {
  714. HRESULT hr = S_OK;
  715. LPWSTR pszServerName = NULL;
  716. LPWSTR pszShareName = NULL;
  717. SHARE_INFO_502 * pShareInfo502 = NULL;
  718. NET_API_STATUS nasStatus = NERR_Success;
  719. PSECURITY_DESCRIPTOR pTempSD = NULL;
  720. //
  721. // We need to split the name into serverName and shareName
  722. //
  723. hr = GetServerAndResource(
  724. pszFileShare,
  725. &pszServerName,
  726. &pszShareName
  727. );
  728. BAIL_ON_FAILURE(hr);
  729. //
  730. // Ideally we should use 1501 level but that is only on Win2k. So
  731. // we need to read the info, update SD and then set it.
  732. //
  733. nasStatus = NetShareGetInfo(
  734. pszServerName,
  735. pszShareName,
  736. 502,
  737. (LPBYTE *) &pShareInfo502
  738. );
  739. if (nasStatus != NERR_Success) {
  740. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  741. }
  742. //
  743. // Store away the SD so we restore before free.
  744. //
  745. pTempSD = pShareInfo502->shi502_security_descriptor;
  746. pShareInfo502->shi502_security_descriptor = pSD;
  747. nasStatus = NetShareSetInfo(
  748. pszServerName,
  749. pszShareName,
  750. 502,
  751. (LPBYTE) pShareInfo502,
  752. NULL
  753. );
  754. pShareInfo502->shi502_security_descriptor = pTempSD;
  755. if (nasStatus != NERR_Success) {
  756. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  757. }
  758. error:
  759. if (pShareInfo502) {
  760. NetApiBufferFree(pShareInfo502);
  761. }
  762. if (pszServerName) {
  763. FreeADsStr(pszServerName);
  764. }
  765. if (pszShareName) {
  766. FreeADsStr(pszShareName);
  767. }
  768. RRETURN(hr);
  769. }
  770. //+---------------------------------------------------------------------------
  771. // Function: GetRawSDFromRegistry - Helper routine.
  772. //
  773. // Synopsis: Gets the security descriptor from the registry in bin format.
  774. //
  775. // Arguments: pszFileRegKeyName - Name of fileshare to get sd from.
  776. // secInfo - Security mask to use for the operation.
  777. // ppSD - Return value for the SD.
  778. // pdwLength - Return value for the lenght of the SD.
  779. //
  780. // Returns: S_OK or any appropriate error code.
  781. //
  782. // Modifies: ppSD and pdwLength on success.
  783. //
  784. //----------------------------------------------------------------------------
  785. HRESULT
  786. GetRawSDFromRegistry(
  787. LPWSTR pszFileRegKeyName,
  788. SECURITY_INFORMATION secInfo,
  789. PSECURITY_DESCRIPTOR *ppSD,
  790. PDWORD pdwLength
  791. )
  792. {
  793. HRESULT hr;
  794. LPWSTR pszServerName = NULL;
  795. LPWSTR pszKeyName = NULL;
  796. LPWSTR pszSubKey = NULL;
  797. DWORD dwLength = 0;
  798. DWORD dwErr;
  799. PSECURITY_DESCRIPTOR pSD = NULL;
  800. HKEY hKey = NULL;
  801. HKEY hKeyRoot = NULL;
  802. HKEY hKeyMachine = NULL;
  803. *ppSD = NULL;
  804. *pdwLength = 0;
  805. //
  806. // We need to split the name into serverName and shareName
  807. //
  808. hr = GetServerAndResource(
  809. pszFileRegKeyName,
  810. &pszServerName,
  811. &pszKeyName
  812. );
  813. BAIL_ON_FAILURE(hr);
  814. //
  815. // pszKeyName has to have a valid string. We need to process it
  816. // to find out which key set we need to open (such as HKLM).
  817. //
  818. hr = GetKeyRootAndSubKey(pszKeyName, &pszSubKey, &hKeyRoot);
  819. BAIL_ON_FAILURE(hr);
  820. //
  821. // Need to open the hKeyRoot on the appropriate machine.
  822. // If the serverName is NULL it will be local machine.
  823. //
  824. dwErr = RegConnectRegistry(
  825. pszServerName,
  826. hKeyRoot,
  827. &hKeyMachine
  828. );
  829. if (dwErr) {
  830. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  831. }
  832. //
  833. // Open the key and try and read the security descriptor
  834. //
  835. dwErr = RegOpenKeyEx(
  836. hKeyMachine,
  837. pszSubKey,
  838. 0,
  839. KEY_READ,
  840. &hKey
  841. );
  842. if (dwErr) {
  843. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  844. }
  845. dwErr = RegGetKeySecurity(
  846. hKey,
  847. secInfo,
  848. pSD,
  849. &dwLength
  850. );
  851. if (dwLength == 0) {
  852. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  853. }
  854. pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength);
  855. if (!pSD) {
  856. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  857. }
  858. dwErr = RegGetKeySecurity(
  859. hKey,
  860. secInfo,
  861. pSD,
  862. &dwLength
  863. );
  864. if (dwErr) {
  865. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  866. }
  867. *ppSD = pSD;
  868. *pdwLength = dwLength;
  869. error:
  870. if (pszServerName) {
  871. FreeADsStr(pszServerName);
  872. }
  873. if (pszKeyName) {
  874. FreeADsStr(pszKeyName);
  875. }
  876. if (pszSubKey) {
  877. FreeADsStr(pszSubKey);
  878. }
  879. if (hKey) {
  880. RegCloseKey(hKey);
  881. }
  882. if (hKeyMachine) {
  883. RegCloseKey(hKeyMachine);
  884. }
  885. if (FAILED(hr) && pSD) {
  886. FreeADsMem(pSD);
  887. }
  888. RRETURN(hr);
  889. }
  890. //+---------------------------------------------------------------------------
  891. // Function: SetRawSDToRegistry - Helper routine.
  892. //
  893. // Synopsis: Sets the security descriptor to the specified key.
  894. //
  895. // Arguments: pszFileRegKeyName - Name of fileshare to set sd on.
  896. // secInfo - Security mask to use for the operation.
  897. // pSD - SD to set on the reg key.
  898. //
  899. // Returns: S_OK or any appropriate error code.
  900. //
  901. // Modifies: N/A.
  902. //
  903. //----------------------------------------------------------------------------
  904. HRESULT
  905. SetRawSDToRegistry(
  906. LPWSTR pszFileRegKeyName,
  907. SECURITY_INFORMATION secInfo,
  908. PSECURITY_DESCRIPTOR pSD
  909. )
  910. {
  911. HRESULT hr;
  912. LPWSTR pszServerName = NULL;
  913. LPWSTR pszKeyName = NULL;
  914. LPWSTR pszSubKey = NULL;
  915. DWORD dwErr;
  916. HKEY hKey = NULL;
  917. HKEY hKeyRoot = NULL;
  918. HKEY hKeyMachine = NULL;
  919. //
  920. // We need to split the name into serverName and shareName
  921. //
  922. hr = GetServerAndResource(
  923. pszFileRegKeyName,
  924. &pszServerName,
  925. &pszKeyName
  926. );
  927. BAIL_ON_FAILURE(hr);
  928. //
  929. // pszKeyName has to have a valid string. We need to process it
  930. // to find out which key set we need to open (such as HKLM).
  931. //
  932. hr = GetKeyRootAndSubKey(pszKeyName, &pszSubKey, &hKeyRoot);
  933. BAIL_ON_FAILURE(hr);
  934. //
  935. // Need to open the hKeyRoot on the appropriate machine.
  936. // If the serverName is NULL it will be local machine.
  937. //
  938. dwErr = RegConnectRegistry(
  939. pszServerName,
  940. hKeyRoot,
  941. &hKeyMachine
  942. );
  943. if (dwErr) {
  944. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  945. }
  946. //
  947. // Open the key and try and read the security descriptor
  948. //
  949. dwErr = RegOpenKeyEx(
  950. hKeyMachine,
  951. pszSubKey,
  952. 0,
  953. KEY_WRITE,
  954. &hKey
  955. );
  956. if (dwErr) {
  957. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  958. }
  959. dwErr = RegSetKeySecurity(
  960. hKey,
  961. secInfo,
  962. pSD
  963. );
  964. if (dwErr) {
  965. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  966. }
  967. error:
  968. if (pszServerName) {
  969. FreeADsStr(pszServerName);
  970. }
  971. if (pszKeyName) {
  972. FreeADsStr(pszKeyName);
  973. }
  974. if (pszSubKey) {
  975. FreeADsStr(pszSubKey);
  976. }
  977. if (hKey) {
  978. RegCloseKey(hKey);
  979. }
  980. if (hKeyMachine) {
  981. RegCloseKey(hKeyMachine);
  982. }
  983. RRETURN(hr);
  984. }
  985. /****************************************************************************/
  986. //
  987. // CADsSecurityUtility Class.
  988. //
  989. /****************************************************************************/
  990. DEFINE_IDispatch_Implementation(CADsSecurityUtility)
  991. //+---------------------------------------------------------------------------
  992. // Function: CSecurity::CSecurityDescriptor - Constructor.
  993. //
  994. // Synopsis: Standard constructor.
  995. //
  996. // Arguments: N/A.
  997. //
  998. // Returns: N/A.
  999. //
  1000. // Modifies: N/A.
  1001. //
  1002. //----------------------------------------------------------------------------
  1003. CADsSecurityUtility::CADsSecurityUtility():
  1004. _secInfo( DACL_SECURITY_INFORMATION
  1005. | GROUP_SECURITY_INFORMATION
  1006. | OWNER_SECURITY_INFORMATION
  1007. ),
  1008. _pDispMgr(NULL)
  1009. {
  1010. }
  1011. //+---------------------------------------------------------------------------
  1012. // Function: CADsSecurityUtility::~CADsSecurityUtility - Destructor.
  1013. //
  1014. // Synopsis: Standard destructor.
  1015. //
  1016. // Arguments: N/A.
  1017. //
  1018. // Returns: N/A.
  1019. //
  1020. // Modifies: N/A.
  1021. //
  1022. //----------------------------------------------------------------------------
  1023. CADsSecurityUtility::~CADsSecurityUtility()
  1024. {
  1025. //
  1026. // Only the dispmgr needs to be cleaned up.
  1027. //
  1028. delete _pDispMgr;
  1029. }
  1030. //+---------------------------------------------------------------------------
  1031. // Function: CADsSecurityUtility::AllocateADsSecurityUtilityObject -
  1032. // Static helper method.
  1033. //
  1034. // Synopsis: Standard static allocation routine.
  1035. //
  1036. // Arguments: ppADsSecurityUtil - Return ptr.
  1037. //
  1038. // Returns: S_OK on success or appropriate error code on failure.
  1039. //
  1040. // Modifies: *ppADsSecurity.
  1041. //
  1042. //----------------------------------------------------------------------------
  1043. HRESULT
  1044. CADsSecurityUtility::AllocateADsSecurityUtilityObject(
  1045. CADsSecurityUtility **ppADsSecurityUtil
  1046. )
  1047. {
  1048. HRESULT hr = S_OK;
  1049. CADsSecurityUtility FAR * pADsSecurityUtil = NULL;
  1050. CDispatchMgr FAR * pDispMgr = NULL;
  1051. pADsSecurityUtil = new CADsSecurityUtility();
  1052. if (!pADsSecurityUtil) {
  1053. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1054. }
  1055. pDispMgr = new CDispatchMgr;
  1056. if (!pDispMgr) {
  1057. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1058. }
  1059. hr = LoadTypeInfoEntry(
  1060. pDispMgr,
  1061. LIBID_ADs,
  1062. IID_IADsSecurityUtility,
  1063. (IADsSecurityUtility *)pADsSecurityUtil,
  1064. DISPID_REGULAR
  1065. );
  1066. BAIL_ON_FAILURE(hr);
  1067. pADsSecurityUtil->_pDispMgr = pDispMgr;
  1068. *ppADsSecurityUtil = pADsSecurityUtil;
  1069. RRETURN(hr);
  1070. error:
  1071. delete pADsSecurityUtil;
  1072. delete pDispMgr;
  1073. RRETURN_EXP_IF_ERR(hr);
  1074. }
  1075. //+---------------------------------------------------------------------------
  1076. // Function: CADsSecurityUtility::CreateADsSecurityUtility - Static
  1077. // helper method.
  1078. //
  1079. // Synopsis: Standard static class factor helper method.
  1080. //
  1081. // Arguments: riid - IID needed on returned object.
  1082. // ppvObj - Return ptr.
  1083. //
  1084. // Returns: S_OK on success or appropriate error code on failure.
  1085. //
  1086. // Modifies: *ppvObj is suitably modified.
  1087. //
  1088. //----------------------------------------------------------------------------
  1089. HRESULT
  1090. CADsSecurityUtility::CreateADsSecurityUtility(
  1091. REFIID riid,
  1092. void **ppvObj
  1093. )
  1094. {
  1095. CADsSecurityUtility FAR * pADsSecurityUtil = NULL;
  1096. HRESULT hr = S_OK;
  1097. hr = AllocateADsSecurityUtilityObject(&pADsSecurityUtil);
  1098. BAIL_ON_FAILURE(hr);
  1099. hr = pADsSecurityUtil->QueryInterface(riid, ppvObj);
  1100. BAIL_ON_FAILURE(hr);
  1101. pADsSecurityUtil->Release();
  1102. RRETURN(hr);
  1103. error:
  1104. delete pADsSecurityUtil;
  1105. RRETURN_EXP_IF_ERR(hr);
  1106. }
  1107. //+---------------------------------------------------------------------------
  1108. // Function: CADsSecurityUtility::QueryInterface --- IUnknown support.
  1109. //
  1110. // Synopsis: Standard query interface method.
  1111. //
  1112. // Arguments: iid - Interface requested.
  1113. // ppInterface - Return pointer to interface requested.
  1114. //
  1115. // Returns: S_OK on success. Error code otherwise.
  1116. //
  1117. // Modifies: *ppInterface to return interface pointer.
  1118. //
  1119. //----------------------------------------------------------------------------
  1120. STDMETHODIMP
  1121. CADsSecurityUtility::QueryInterface(
  1122. REFIID iid,
  1123. LPVOID *ppInterface
  1124. )
  1125. {
  1126. HRESULT hr = S_OK;
  1127. if (!ppInterface) {
  1128. RRETURN(E_INVALIDARG);
  1129. }
  1130. if (IsEqualIID(iid, IID_IUnknown)) {
  1131. *ppInterface = (IADsSecurityUtility *) this;
  1132. }
  1133. else if (IsEqualIID(iid, IID_IDispatch)) {
  1134. *ppInterface = (IADsSecurityUtility *) this;
  1135. }
  1136. else if (IsEqualIID(iid, IID_IADsSecurityUtility)) {
  1137. *ppInterface = (IADsSecurityUtility *) this;
  1138. }
  1139. else if (IsEqualIID(iid, IID_ISupportErrorInfo)) {
  1140. *ppInterface = (ISupportErrorInfo *) this;
  1141. }
  1142. else {
  1143. RRETURN(E_NOINTERFACE);
  1144. }
  1145. AddRef();
  1146. RRETURN(S_OK);
  1147. }
  1148. //+---------------------------------------------------------------------------
  1149. // Function: CADsSecurityUtility::InterfaceSupportserrorInfo
  1150. // ISupportErrorInfo support.
  1151. //
  1152. // Synopsis: N/A.
  1153. //
  1154. // Arguments: riid - Interface being tested..
  1155. //
  1156. // Returns: S_OK or S_FALSE on failure.
  1157. //
  1158. // Modifies: N/A.
  1159. //
  1160. //----------------------------------------------------------------------------
  1161. STDMETHODIMP
  1162. CADsSecurityUtility::InterfaceSupportsErrorInfo(THIS_ REFIID riid)
  1163. {
  1164. if (IsEqualIID(riid, IID_IADsSecurityUtility)) {
  1165. return S_OK;
  1166. } else {
  1167. return S_FALSE;
  1168. }
  1169. }
  1170. //+---------------------------------------------------------------------------
  1171. // Function: CADsSecurityUtility::GetSecurityDescriptor -
  1172. // IADsSecurityUtility support.
  1173. //
  1174. // Synopsis: Gets the security descriptor from the named object.
  1175. //
  1176. // Arguments: varPath - Path of object to get SD from.
  1177. // lPathFormat - Specifies type of object path.
  1178. // Only ADS_PATH_FILE, ADS_PATH_FILESHARE
  1179. // and ADS_PATH_REGISTRY are supported.
  1180. // lOutFormat - Specifies output SD format.
  1181. // pVariant - Return value for SD.
  1182. //
  1183. // Returns: S_OK or any appropriate error code.
  1184. //
  1185. // Modifies: pVariant is update appropriately.
  1186. //
  1187. //----------------------------------------------------------------------------
  1188. STDMETHODIMP
  1189. CADsSecurityUtility::GetSecurityDescriptor(
  1190. IN VARIANT varPath,
  1191. IN long lPathFormat,
  1192. IN OPTIONAL long lOutFormat,
  1193. OUT VARIANT *pVariant
  1194. )
  1195. {
  1196. HRESULT hr = S_OK;
  1197. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  1198. DWORD dwLength = 0;
  1199. VARIANT *pvPath = NULL;
  1200. //
  1201. // Make sure the params are correct.
  1202. //
  1203. if (!pVariant) {
  1204. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1205. }
  1206. VariantInit(pVariant);
  1207. if (lPathFormat < ADS_PATH_FILE
  1208. || lPathFormat > ADS_PATH_REGISTRY
  1209. ) {
  1210. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1211. }
  1212. //
  1213. // Make sure we handle byRef params correctly.
  1214. //
  1215. pvPath = &varPath;
  1216. if (V_VT(pvPath) == (VT_BYREF|VT_VARIANT)) {
  1217. pvPath = V_VARIANTREF(&varPath);
  1218. }
  1219. //
  1220. // For the path to be valid for now, it has to be a string.
  1221. //
  1222. if (pvPath->vt != VT_BSTR) {
  1223. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1224. }
  1225. if (pvPath->bstrVal == NULL) {
  1226. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1227. }
  1228. if (lOutFormat < ADS_SD_FORMAT_IID
  1229. || lOutFormat > ADS_SD_FORMAT_HEXSTRING
  1230. ) {
  1231. BAIL_ON_FAILURE(hr);
  1232. }
  1233. //
  1234. // Time to get the raw sd from the source.
  1235. //
  1236. switch (lPathFormat) {
  1237. case ADS_PATH_FILE:
  1238. hr = GetRawSDFromFile(
  1239. pvPath->bstrVal,
  1240. _secInfo,
  1241. &pSecurityDescriptor,
  1242. &dwLength
  1243. );
  1244. break;
  1245. case ADS_PATH_FILESHARE:
  1246. hr = GetRawSDFromFileShare(
  1247. pvPath->bstrVal,
  1248. &pSecurityDescriptor,
  1249. &dwLength
  1250. );
  1251. break;
  1252. case ADS_PATH_REGISTRY:
  1253. hr = GetRawSDFromRegistry(
  1254. pvPath->bstrVal,
  1255. _secInfo,
  1256. &pSecurityDescriptor,
  1257. &dwLength
  1258. );
  1259. break;
  1260. default:
  1261. hr = E_INVALIDARG;
  1262. break;
  1263. } // end of case to read sd.
  1264. BAIL_ON_FAILURE(hr);
  1265. //
  1266. // Now convert the sd to the required format.
  1267. //
  1268. switch (lOutFormat) {
  1269. case ADS_SD_FORMAT_IID:
  1270. hr = BinarySDToSecurityDescriptor(
  1271. pSecurityDescriptor,
  1272. pVariant,
  1273. NULL,
  1274. NULL,
  1275. NULL,
  1276. 0
  1277. );
  1278. break;
  1279. case ADS_SD_FORMAT_RAW:
  1280. hr = ConvertRawSDToBinary(
  1281. pSecurityDescriptor,
  1282. dwLength,
  1283. pVariant
  1284. );
  1285. break;
  1286. case ADS_SD_FORMAT_HEXSTRING:
  1287. hr = ConvertRawSDToHexString(
  1288. pSecurityDescriptor,
  1289. dwLength,
  1290. pVariant
  1291. );
  1292. break;
  1293. default:
  1294. hr = E_INVALIDARG;
  1295. } // end of case for output format.
  1296. error:
  1297. if (pSecurityDescriptor) {
  1298. FreeADsMem(pSecurityDescriptor);
  1299. }
  1300. RRETURN(hr);
  1301. }
  1302. //+---------------------------------------------------------------------------
  1303. // Function: CADsSecurityUtility::SetSecurityDescriptor -
  1304. // IADsSecurityUtility support.
  1305. //
  1306. // Synopsis: Sets the security descriptor from the named object.
  1307. //
  1308. // Arguments: varPath - Path of object to set SD on.
  1309. // lPathFormat - Format of path.
  1310. // varData - Variant with SD to set.
  1311. // lDataFormat - Format of the SD data.
  1312. //
  1313. // Returns: S_OK or any appropriate error code.
  1314. //
  1315. // Modifies: N/A.
  1316. //
  1317. //----------------------------------------------------------------------------
  1318. STDMETHODIMP
  1319. CADsSecurityUtility::SetSecurityDescriptor(
  1320. IN VARIANT varPath,
  1321. IN long lPathFormat,
  1322. IN VARIANT varData,
  1323. IN long lDataFormat
  1324. )
  1325. {
  1326. HRESULT hr = E_INVALIDARG;
  1327. VARIANT *pvPath = NULL;
  1328. VARIANT *pvData = NULL;
  1329. PSECURITY_DESCRIPTOR pSD = NULL;
  1330. DWORD dwLength = 0;
  1331. if ((lPathFormat < ADS_PATH_FILE)
  1332. || (lPathFormat > ADS_PATH_REGISTRY)
  1333. || (lDataFormat < ADS_SD_FORMAT_IID)
  1334. || (lDataFormat > ADS_SD_FORMAT_HEXSTRING)
  1335. ) {
  1336. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1337. }
  1338. //
  1339. // Make sure we handle byRef params correctly.
  1340. //
  1341. pvPath = &varPath;
  1342. if (V_VT(pvPath) == (VT_BYREF | VT_VARIANT)) {
  1343. pvPath = V_VARIANTREF(&varPath);
  1344. }
  1345. pvData = &varData;
  1346. if (V_VT(pvData) == (VT_BYREF | VT_VARIANT)) {
  1347. pvData = V_VARIANTREF(&varData);
  1348. }
  1349. //
  1350. // Find out what format the SD is in and convert to raw binary
  1351. // format as that is what we need to set.
  1352. //
  1353. switch (lDataFormat) {
  1354. case ADS_SD_FORMAT_IID:
  1355. hr = SecurityDescriptorToBinarySD(
  1356. *pvData,
  1357. &pSD,
  1358. &dwLength,
  1359. NULL,
  1360. NULL,
  1361. NULL,
  1362. 0
  1363. );
  1364. break;
  1365. case ADS_SD_FORMAT_HEXSTRING:
  1366. if (V_VT(pvData) == VT_BSTR) {
  1367. hr = ConvertHexSDToRawSD(
  1368. pvData,
  1369. &pSD,
  1370. &dwLength
  1371. );
  1372. }
  1373. break;
  1374. case ADS_SD_FORMAT_RAW:
  1375. if (V_VT(pvData) == (VT_UI1 | VT_ARRAY)) {
  1376. hr = ConvertBinarySDToRawSD(
  1377. pvData,
  1378. &pSD,
  1379. &dwLength
  1380. );
  1381. }
  1382. default:
  1383. hr = E_INVALIDARG;
  1384. break;
  1385. } // end switch type of input data.
  1386. //
  1387. // This will catch conversion failures as well as bad params.
  1388. //
  1389. BAIL_ON_FAILURE(hr);
  1390. //
  1391. // For now the path has to be a string.
  1392. //
  1393. if (pvPath->vt != VT_BSTR) {
  1394. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1395. }
  1396. switch (lPathFormat) {
  1397. case ADS_PATH_FILE:
  1398. hr = SetRawSDToFile(
  1399. pvPath->bstrVal,
  1400. _secInfo,
  1401. pSD
  1402. );
  1403. break;
  1404. case ADS_PATH_FILESHARE:
  1405. hr = SetRawSDToFileShare(
  1406. pvPath->bstrVal,
  1407. pSD
  1408. );
  1409. break;
  1410. case ADS_PATH_REGISTRY:
  1411. hr = SetRawSDToRegistry(
  1412. pvPath->bstrVal,
  1413. _secInfo,
  1414. pSD
  1415. );
  1416. break;
  1417. default:
  1418. hr = E_INVALIDARG;
  1419. break;
  1420. }
  1421. BAIL_ON_FAILURE(hr);
  1422. error:
  1423. if (pSD) {
  1424. FreeADsMem(pSD);
  1425. }
  1426. RRETURN(hr);
  1427. }
  1428. //+---------------------------------------------------------------------------
  1429. // Function: CADsSecurityUtility::ConvertSecurityDescriptor -
  1430. // IADsSecurityUtility method.
  1431. //
  1432. // Synopsis: Converts the input SD to the appropriate format requested.
  1433. //
  1434. // Arguments: varData - Input SD to convert.
  1435. // lDataFormat - Input SD format.
  1436. // loutFormat - Format of output SD.
  1437. // pvResult - Return value.
  1438. //
  1439. // Returns: S_OK or any appropriate error code.
  1440. //
  1441. // Modifies: pvResult with appropriate value.
  1442. //
  1443. //----------------------------------------------------------------------------
  1444. STDMETHODIMP
  1445. CADsSecurityUtility::ConvertSecurityDescriptor(
  1446. IN VARIANT varData,
  1447. IN long lDataFormat,
  1448. IN long lOutFormat,
  1449. OUT VARIANT *pvResult
  1450. )
  1451. {
  1452. HRESULT hr;
  1453. PSECURITY_DESCRIPTOR pSD = NULL;
  1454. DWORD dwLenSD;
  1455. VARIANT *pVarData = &varData;
  1456. if (!pvResult) {
  1457. BAIL_ON_FAILURE(hr= E_INVALIDARG);
  1458. }
  1459. if (V_VT(pVarData) == (VT_BYREF | VT_VARIANT)) {
  1460. pVarData = V_VARIANTREF(&varData);
  1461. }
  1462. //
  1463. // We will convert to binary format and then to
  1464. // the requested format.
  1465. //
  1466. switch (lDataFormat) {
  1467. case ADS_SD_FORMAT_IID:
  1468. hr = SecurityDescriptorToBinarySD(
  1469. *pVarData,
  1470. &pSD,
  1471. &dwLenSD,
  1472. NULL,
  1473. NULL,
  1474. NULL,
  1475. 0
  1476. );
  1477. break;
  1478. case ADS_SD_FORMAT_RAW :
  1479. hr = ConvertBinarySDToRawSD(
  1480. pVarData,
  1481. &pSD,
  1482. &dwLenSD
  1483. );
  1484. break;
  1485. case ADS_SD_FORMAT_HEXSTRING:
  1486. hr = ConvertHexSDToRawSD(
  1487. pVarData,
  1488. &pSD,
  1489. &dwLenSD
  1490. );
  1491. break;
  1492. default:
  1493. hr = E_INVALIDARG;
  1494. break;
  1495. }
  1496. BAIL_ON_FAILURE(hr);
  1497. //
  1498. // Convert to the requested format.
  1499. //
  1500. switch (lOutFormat) {
  1501. case ADS_SD_FORMAT_IID:
  1502. hr = BinarySDToSecurityDescriptor(
  1503. pSD,
  1504. pvResult,
  1505. NULL,
  1506. NULL,
  1507. NULL,
  1508. 0
  1509. );
  1510. break;
  1511. case ADS_SD_FORMAT_RAW:
  1512. hr = ConvertRawSDToBinary(
  1513. pSD,
  1514. dwLenSD,
  1515. pvResult
  1516. );
  1517. break;
  1518. case ADS_SD_FORMAT_HEXSTRING:
  1519. hr = ConvertRawSDToHexString(
  1520. pSD,
  1521. dwLenSD,
  1522. pvResult
  1523. );
  1524. break;
  1525. default:
  1526. hr = E_INVALIDARG;
  1527. break;
  1528. }
  1529. error:
  1530. if (pSD) {
  1531. FreeADsMem(pSD);
  1532. }
  1533. RRETURN(hr);
  1534. }
  1535. STDMETHODIMP
  1536. CADsSecurityUtility::put_SecurityMask(
  1537. long lSecurityMask
  1538. )
  1539. {
  1540. _secInfo = (SECURITY_INFORMATION) lSecurityMask;
  1541. RRETURN(S_OK);
  1542. }
  1543. STDMETHODIMP
  1544. CADsSecurityUtility::get_SecurityMask(
  1545. long *plSecurityMask
  1546. )
  1547. {
  1548. if (!plSecurityMask) {
  1549. RRETURN(E_INVALIDARG);
  1550. }
  1551. *plSecurityMask = (long) _secInfo;
  1552. RRETURN(S_OK);
  1553. }