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.

694 lines
17 KiB

  1. // AclPage.cpp : Implementation of ISecurityInformation and IDataObject
  2. #include "stdafx.h"
  3. #include "AclPage.h"
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static char THIS_FILE[] = __FILE__;
  8. #endif
  9. //////////////////////////////////////////////////////
  10. // class CPermEntry
  11. CPermEntry::CPermEntry()
  12. : m_dwAccessMask(0),
  13. m_pSid(NULL),
  14. m_bWellKnownSid(FALSE)
  15. {
  16. }
  17. CPermEntry::~CPermEntry()
  18. {
  19. if (m_pSid)
  20. if (m_bWellKnownSid)
  21. FreeSid(m_pSid);
  22. else
  23. LocalFree((HLOCAL)m_pSid);
  24. }
  25. HRESULT
  26. CPermEntry::Initialize(
  27. IN LPCTSTR lpszSystem,
  28. IN LPCTSTR lpszAccount,
  29. IN DWORD dwAccessMask
  30. )
  31. {
  32. m_cstrSystem = lpszSystem;
  33. m_cstrAccount = lpszAccount;
  34. m_dwAccessMask = dwAccessMask;
  35. return GetAccountSID(m_cstrSystem, m_cstrAccount, &m_pSid, &m_bWellKnownSid);
  36. }
  37. UINT
  38. CPermEntry::GetLengthSid()
  39. {
  40. return (m_pSid ? ::GetLengthSid(m_pSid) : 0);
  41. }
  42. HRESULT
  43. CPermEntry::AddAccessAllowedAce(OUT PACL pACL)
  44. {
  45. if ( !::AddAccessAllowedAce(pACL, ACL_REVISION, m_dwAccessMask, m_pSid) )
  46. return HRESULT_FROM_WIN32(GetLastError());
  47. return S_OK;
  48. }
  49. // NOTE: caller needs to call LocalFree() on the returned SD
  50. HRESULT
  51. BuildSecurityDescriptor(
  52. IN CPermEntry *pPermEntry, // an array of CPermEntry
  53. IN UINT cEntries, // number of entries in the array
  54. OUT PSECURITY_DESCRIPTOR *ppSelfRelativeSD // return a security descriptor in self-relative form
  55. )
  56. {
  57. if (!pPermEntry || !cEntries || !ppSelfRelativeSD)
  58. return E_INVALIDARG;
  59. if (*ppSelfRelativeSD)
  60. {
  61. LocalFree((HLOCAL)*ppSelfRelativeSD);
  62. *ppSelfRelativeSD = NULL;
  63. }
  64. HRESULT hr = S_OK;
  65. PSECURITY_DESCRIPTOR pAbsoluteSD = NULL;
  66. PACL pACL = NULL;
  67. do { // false loop
  68. UINT i = 0;
  69. CPermEntry *pEntry = NULL;
  70. DWORD cbACL = sizeof(ACL);
  71. // Initialize a new ACL
  72. for (pEntry=pPermEntry, i=0; i<cEntries; pEntry++, i++)
  73. cbACL += sizeof(ACCESS_ALLOWED_ACE) + pEntry->GetLengthSid() - sizeof(DWORD);
  74. if ( !(pACL = (PACL)LocalAlloc(LPTR, cbACL)) ||
  75. !InitializeAcl(pACL, cbACL, ACL_REVISION))
  76. {
  77. hr = HRESULT_FROM_WIN32(GetLastError());
  78. break;
  79. }
  80. // Add Ace
  81. for (pEntry=pPermEntry, i=0; SUCCEEDED(hr) && i<cEntries; pEntry++, i++)
  82. hr = pEntry->AddAccessAllowedAce(pACL);
  83. if (FAILED(hr))
  84. break;
  85. // Note: this is a new object, set Dacl only.
  86. // Initialize a new security descriptor in absolute form and add the new ACL to it
  87. if ( !(pAbsoluteSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH)) ||
  88. !InitializeSecurityDescriptor(pAbsoluteSD, SECURITY_DESCRIPTOR_REVISION) ||
  89. !SetSecurityDescriptorDacl(pAbsoluteSD, TRUE, pACL, FALSE) )
  90. {
  91. hr = HRESULT_FROM_WIN32(GetLastError());
  92. break;
  93. }
  94. // transform into a self-relative form
  95. DWORD dwSDSize = 0;
  96. MakeSelfRelativeSD(pAbsoluteSD, *ppSelfRelativeSD, &dwSDSize);
  97. if ( !(*ppSelfRelativeSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSDSize)) ||
  98. !MakeSelfRelativeSD(pAbsoluteSD, *ppSelfRelativeSD, &dwSDSize) )
  99. {
  100. hr = HRESULT_FROM_WIN32(GetLastError());
  101. break;
  102. }
  103. } while (0);
  104. if (FAILED(hr))
  105. {
  106. if (*ppSelfRelativeSD)
  107. {
  108. LocalFree((HLOCAL)*ppSelfRelativeSD);
  109. *ppSelfRelativeSD = NULL;
  110. }
  111. }
  112. if (pACL)
  113. LocalFree((HLOCAL)pACL);
  114. if (pAbsoluteSD)
  115. LocalFree((HLOCAL)pAbsoluteSD);
  116. return hr;
  117. }
  118. #define MAX_DOMAIN_NAME_LENGTH 1024
  119. // NOTE: caller needs to call FreeSid()/LocalFree() on the returned SID
  120. // NOTE: this function only handles limited well-known SIDs.
  121. HRESULT
  122. GetAccountSID(
  123. IN LPCTSTR lpszSystem, // system where the account belongs to
  124. IN LPCTSTR lpszAccount, // account
  125. OUT PSID *ppSid, // return SID of the account
  126. OUT BOOL *pbWellKnownSID // return a BOOL, caller needs to call FreeSid() on a well-known SID
  127. )
  128. {
  129. if (!lpszAccount || !*lpszAccount || !ppSid || !pbWellKnownSID)
  130. return E_INVALIDARG;
  131. ASSERT(!*ppSid); // prevent memory leak
  132. *ppSid = NULL;
  133. SID_IDENTIFIER_AUTHORITY SidIdentifierNTAuthority = SECURITY_NT_AUTHORITY;
  134. SID_IDENTIFIER_AUTHORITY SidIdentifierWORLDAuthority = SECURITY_WORLD_SID_AUTHORITY;
  135. PSID_IDENTIFIER_AUTHORITY pSidIdentifierAuthority = NULL;
  136. DWORD dwRet = ERROR_SUCCESS;
  137. BYTE Count = 0;
  138. DWORD dwRID[8];
  139. ZeroMemory(dwRID, sizeof(dwRID));
  140. *pbWellKnownSID = TRUE;
  141. CString cstrAccount = lpszAccount;
  142. cstrAccount.MakeLower();
  143. if ( ACCOUNT_ADMINISTRATORS == cstrAccount ) {
  144. // Administrators group
  145. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  146. Count = 2;
  147. dwRID[0] = SECURITY_BUILTIN_DOMAIN_RID;
  148. dwRID[1] = DOMAIN_ALIAS_RID_ADMINS;
  149. } else if ( ACCOUNT_EVERYONE == cstrAccount ) {
  150. // Everyone
  151. pSidIdentifierAuthority = &SidIdentifierWORLDAuthority;
  152. Count = 1;
  153. dwRID[0] = SECURITY_WORLD_RID;
  154. } else if ( ACCOUNT_SYSTEM == cstrAccount ) {
  155. // SYSTEM
  156. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  157. Count = 1;
  158. dwRID[0] = SECURITY_LOCAL_SYSTEM_RID;
  159. } else if ( ACCOUNT_INTERACTIVE == cstrAccount ) {
  160. // INTERACTIVE
  161. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  162. Count = 1;
  163. dwRID[0] = SECURITY_INTERACTIVE_RID;
  164. } else {
  165. *pbWellKnownSID = FALSE;
  166. }
  167. if (*pbWellKnownSID) {
  168. if ( !AllocateAndInitializeSid(pSidIdentifierAuthority, Count,
  169. dwRID[0], dwRID[1], dwRID[2], dwRID[3],
  170. dwRID[4], dwRID[5], dwRID[6], dwRID[7], ppSid) )
  171. {
  172. dwRet = GetLastError();
  173. }
  174. } else {
  175. // get regular account sid
  176. DWORD dwSidSize = 0;
  177. TCHAR refDomain[MAX_DOMAIN_NAME_LENGTH];
  178. DWORD refDomainSize = MAX_DOMAIN_NAME_LENGTH;
  179. SID_NAME_USE snu;
  180. LookupAccountName (lpszSystem, lpszAccount, *ppSid, &dwSidSize,
  181. refDomain, &refDomainSize, &snu);
  182. dwRet = GetLastError();
  183. if (ERROR_INSUFFICIENT_BUFFER == dwRet)
  184. {
  185. dwRet = ERROR_SUCCESS;
  186. if ( !(*ppSid = (PSID)LocalAlloc(LPTR, dwSidSize)) )
  187. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  188. else
  189. {
  190. refDomainSize = MAX_DOMAIN_NAME_LENGTH;
  191. if (!LookupAccountName (lpszSystem, lpszAccount, *ppSid, &dwSidSize,
  192. refDomain, &refDomainSize, &snu))
  193. dwRet = GetLastError();
  194. }
  195. }
  196. }
  197. if (ERROR_SUCCESS != dwRet)
  198. {
  199. if (*ppSid)
  200. {
  201. if (*pbWellKnownSID)
  202. FreeSid(*ppSid);
  203. else
  204. LocalFree((HLOCAL)*ppSid);
  205. *ppSid = NULL;
  206. }
  207. }
  208. return HRESULT_FROM_WIN32(dwRet);
  209. }
  210. ///////////////////////////////////////////////////////
  211. // class CShareSecurityInformation
  212. CShareSecurityInformation::CShareSecurityInformation(PSECURITY_DESCRIPTOR pSelfRelativeSD)
  213. : m_cRef(1), m_pDefaultDescriptor(pSelfRelativeSD)
  214. {
  215. m_bDefaultSD = !pSelfRelativeSD;
  216. }
  217. CShareSecurityInformation::~CShareSecurityInformation()
  218. {
  219. TRACE(_T("CShareSecurityInformation::~CShareSecurityInformation m_cRef=%d\n"), m_cRef);
  220. if (m_bDefaultSD && m_pDefaultDescriptor)
  221. LocalFree((HLOCAL)m_pDefaultDescriptor);
  222. }
  223. void
  224. CShareSecurityInformation::Initialize(
  225. IN LPCTSTR lpszComputerName,
  226. IN LPCTSTR lpszShareName,
  227. IN LPCTSTR lpszPageTitle
  228. )
  229. {
  230. m_cstrComputerName = lpszComputerName;
  231. m_cstrShareName = lpszShareName;
  232. m_cstrPageTitle = lpszPageTitle;
  233. }
  234. ////////////////////////////////
  235. // IUnknown methods
  236. ////////////////////////////////
  237. STDMETHODIMP
  238. CShareSecurityInformation::QueryInterface(REFIID riid, LPVOID *ppv)
  239. {
  240. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation))
  241. {
  242. *ppv = this;
  243. m_cRef++;
  244. return S_OK;
  245. } else
  246. {
  247. *ppv = NULL;
  248. return E_NOINTERFACE;
  249. }
  250. }
  251. STDMETHODIMP_(ULONG)
  252. CShareSecurityInformation::AddRef()
  253. {
  254. return ++m_cRef;
  255. }
  256. STDMETHODIMP_(ULONG)
  257. CShareSecurityInformation::Release()
  258. {
  259. if (--m_cRef == 0)
  260. {
  261. delete this;
  262. return 0;
  263. }
  264. return m_cRef;
  265. }
  266. ////////////////////////////////
  267. // ISecurityInformation methods
  268. ////////////////////////////////
  269. STDMETHODIMP
  270. CShareSecurityInformation::GetObjectInformation (
  271. PSI_OBJECT_INFO pObjectInfo
  272. )
  273. {
  274. ASSERT(pObjectInfo);
  275. ASSERT(!IsBadWritePtr(pObjectInfo, sizeof(*pObjectInfo)));
  276. pObjectInfo->dwFlags = SI_EDIT_ALL | SI_NO_ACL_PROTECT | SI_PAGE_TITLE | SI_RESET;
  277. pObjectInfo->hInstance = AfxGetResourceHandle();
  278. pObjectInfo->pszServerName = const_cast<LPTSTR>(static_cast<LPCTSTR>(m_cstrComputerName));
  279. pObjectInfo->pszObjectName = const_cast<LPTSTR>(static_cast<LPCTSTR>(m_cstrShareName));
  280. pObjectInfo->pszPageTitle = const_cast<LPTSTR>(static_cast<LPCTSTR>(m_cstrPageTitle));
  281. return S_OK;
  282. }
  283. STDMETHODIMP
  284. CShareSecurityInformation::GetSecurity (
  285. SECURITY_INFORMATION RequestedInformation,
  286. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  287. BOOL fDefault
  288. )
  289. {
  290. ASSERT(DACL_SECURITY_INFORMATION == RequestedInformation);
  291. ASSERT(ppSecurityDescriptor);
  292. TRACE(_T("GetSecurity RequestedInformation=%d fDefault=%d\n"), RequestedInformation, fDefault);
  293. *ppSecurityDescriptor = NULL;
  294. if (NULL == m_pDefaultDescriptor)
  295. {
  296. HRESULT hr = GetDefaultSD(&m_pDefaultDescriptor);
  297. if (FAILED(hr))
  298. return hr;
  299. }
  300. // We have to pass back a LocalAlloc'ed copy of the SD
  301. return MakeSelfRelativeCopy(m_pDefaultDescriptor, ppSecurityDescriptor);
  302. }
  303. STDMETHODIMP
  304. CShareSecurityInformation::SetSecurity (
  305. SECURITY_INFORMATION SecurityInformation,
  306. PSECURITY_DESCRIPTOR pSecurityDescriptor
  307. )
  308. {
  309. ASSERT(DACL_SECURITY_INFORMATION == SecurityInformation);
  310. TRACE(_T("SetSecurity SecurityInformation=%d\n"), SecurityInformation);
  311. PSECURITY_DESCRIPTOR pNewSD = NULL;
  312. HRESULT hr = MakeSelfRelativeCopy(pSecurityDescriptor, &pNewSD);
  313. if (SUCCEEDED(hr))
  314. ((CShrwizApp *)AfxGetApp())->SetSecurity(pNewSD);
  315. return hr;
  316. }
  317. SI_ACCESS siShareAccesses[] =
  318. {
  319. { &GUID_NULL,
  320. FILE_ALL_ACCESS,
  321. MAKEINTRESOURCE(IDS_SHAREPERM_ALL),
  322. SI_ACCESS_GENERAL },
  323. { &GUID_NULL,
  324. FILE_GENERIC_READ | FILE_EXECUTE | FILE_GENERIC_WRITE | DELETE,
  325. MAKEINTRESOURCE(IDS_SHAREPERM_CHANGE),
  326. SI_ACCESS_GENERAL },
  327. { &GUID_NULL,
  328. FILE_GENERIC_READ | FILE_EXECUTE,
  329. MAKEINTRESOURCE(IDS_SHAREPERM_READ),
  330. SI_ACCESS_GENERAL }
  331. };
  332. #define iShareDefAccess 2 // index of value in array siShareAccesses
  333. #ifndef ARRAYSIZE
  334. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  335. #endif
  336. STDMETHODIMP
  337. CShareSecurityInformation::GetAccessRights(
  338. const GUID *pguidObjectType,
  339. DWORD dwFlags,
  340. PSI_ACCESS *ppAccess,
  341. ULONG *pcAccesses,
  342. ULONG *piDefaultAccess
  343. )
  344. {
  345. ASSERT(ppAccess);
  346. ASSERT(pcAccesses);
  347. ASSERT(piDefaultAccess);
  348. *ppAccess = siShareAccesses;
  349. *pcAccesses = ARRAYSIZE(siShareAccesses);
  350. *piDefaultAccess = iShareDefAccess;
  351. return S_OK;
  352. }
  353. // This is consistent with the NETUI code
  354. GENERIC_MAPPING ShareMap =
  355. {
  356. FILE_GENERIC_READ,
  357. FILE_GENERIC_WRITE,
  358. FILE_GENERIC_EXECUTE,
  359. FILE_ALL_ACCESS
  360. };
  361. STDMETHODIMP
  362. CShareSecurityInformation::MapGeneric(
  363. const GUID *pguidObjectType,
  364. UCHAR *pAceFlags,
  365. ACCESS_MASK *pMask
  366. )
  367. {
  368. ASSERT(pMask);
  369. MapGenericMask(pMask, &ShareMap);
  370. return S_OK;
  371. }
  372. STDMETHODIMP
  373. CShareSecurityInformation::GetInheritTypes (
  374. PSI_INHERIT_TYPE *ppInheritTypes,
  375. ULONG *pcInheritTypes
  376. )
  377. {
  378. return E_NOTIMPL;
  379. }
  380. STDMETHODIMP
  381. CShareSecurityInformation::PropertySheetPageCallback(
  382. HWND hwnd,
  383. UINT uMsg,
  384. SI_PAGE_TYPE uPage
  385. )
  386. {
  387. return S_OK;
  388. }
  389. HRESULT
  390. CShareSecurityInformation::GetDefaultSD(
  391. OUT PSECURITY_DESCRIPTOR *ppsd
  392. )
  393. {
  394. CPermEntry permEntry;
  395. HRESULT hr = permEntry.Initialize(NULL, ACCOUNT_EVERYONE, SHARE_PERM_READ_ONLY);
  396. if (SUCCEEDED(hr))
  397. hr = BuildSecurityDescriptor(&permEntry, 1, ppsd);
  398. return hr;
  399. }
  400. HRESULT
  401. CShareSecurityInformation::MakeSelfRelativeCopy(
  402. IN PSECURITY_DESCRIPTOR psdOriginal,
  403. OUT PSECURITY_DESCRIPTOR *ppsdNew
  404. )
  405. {
  406. ASSERT(psdOriginal);
  407. ASSERT(ppsdNew);
  408. *ppsdNew = NULL;
  409. DWORD dwErr = 0;
  410. PSECURITY_DESCRIPTOR psdSelfRelative = NULL;
  411. do { // false loop
  412. DWORD cbSD = ::GetSecurityDescriptorLength(psdOriginal);
  413. if ( !(psdSelfRelative = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, cbSD)) )
  414. {
  415. dwErr = ::GetLastError();
  416. break;
  417. }
  418. // we have to find out whether the original is already self-relative
  419. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  420. DWORD dwRevision = 0;
  421. if ( !::GetSecurityDescriptorControl(psdOriginal, &sdc, &dwRevision) )
  422. {
  423. dwErr = ::GetLastError();
  424. break;
  425. }
  426. if (sdc & SE_SELF_RELATIVE)
  427. {
  428. ::memcpy(psdSelfRelative, psdOriginal, cbSD);
  429. } else if ( !::MakeSelfRelativeSD(psdOriginal, psdSelfRelative, &cbSD) )
  430. {
  431. dwErr = ::GetLastError();
  432. break;
  433. }
  434. *ppsdNew = psdSelfRelative;
  435. } while (FALSE);
  436. if (dwErr && psdSelfRelative)
  437. LocalFree((HLOCAL)psdSelfRelative);
  438. return (dwErr ? HRESULT_FROM_WIN32(dwErr) : S_OK);
  439. }
  440. ///////////////////////////////////////////////////////
  441. // class CFileSecurityDataObject
  442. CFileSecurityDataObject::CFileSecurityDataObject()
  443. : m_cRef(1)
  444. {
  445. }
  446. CFileSecurityDataObject::~CFileSecurityDataObject()
  447. {
  448. TRACE(_T("CFileSecurityDataObject::~CFileSecurityDataObject m_cRef=%d\n"), m_cRef);
  449. }
  450. void
  451. CFileSecurityDataObject::Initialize(
  452. IN LPCTSTR lpszComputerName,
  453. IN LPCTSTR lpszFolder
  454. )
  455. {
  456. m_cstrComputerName = lpszComputerName;
  457. m_cstrFolder = lpszFolder;
  458. GetFullPath(lpszComputerName, lpszFolder, m_cstrPath);
  459. m_cfIDList = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_SHELLIDLIST);
  460. }
  461. ////////////////////////////////
  462. // IUnknown methods
  463. ////////////////////////////////
  464. STDMETHODIMP
  465. CFileSecurityDataObject::QueryInterface(REFIID riid, LPVOID *ppv)
  466. {
  467. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDataObject))
  468. {
  469. *ppv = this;
  470. m_cRef++;
  471. return S_OK;
  472. } else
  473. {
  474. *ppv = NULL;
  475. return E_NOINTERFACE;
  476. }
  477. }
  478. STDMETHODIMP_(ULONG)
  479. CFileSecurityDataObject::AddRef()
  480. {
  481. return ++m_cRef;
  482. }
  483. STDMETHODIMP_(ULONG)
  484. CFileSecurityDataObject::Release()
  485. {
  486. if (--m_cRef == 0)
  487. {
  488. delete this;
  489. return 0;
  490. }
  491. return m_cRef;
  492. }
  493. STDMETHODIMP
  494. CFileSecurityDataObject::GetData(
  495. FORMATETC __RPC_FAR * pFormatEtcIn,
  496. STGMEDIUM __RPC_FAR * pMedium
  497. )
  498. {
  499. ASSERT(pFormatEtcIn);
  500. ASSERT(pMedium);
  501. if (m_cfIDList != pFormatEtcIn->cfFormat)
  502. return DV_E_FORMATETC;
  503. LPITEMIDLIST pidl = NULL;
  504. LPITEMIDLIST pidlR = NULL;
  505. HRESULT hr = GetFolderPIDList(&pidl);
  506. if (SUCCEEDED(hr))
  507. {
  508. pidlR = ILClone(ILFindLastID(pidl)); // relative IDList
  509. ILRemoveLastID(pidl); // folder IDList
  510. int cidl = 1;
  511. UINT offset = sizeof(CIDA) + sizeof(UINT)*cidl;
  512. UINT cbFolder = ILGetSize(pidl);
  513. UINT cbRelative = ILGetSize(pidlR);
  514. UINT cbTotal = offset + cbFolder + cbRelative;
  515. HGLOBAL hGlobal = ::GlobalAlloc (GPTR, cbTotal);
  516. if ( hGlobal )
  517. {
  518. LPIDA pida = (LPIDA)hGlobal;
  519. pida->cidl = cidl;
  520. pida->aoffset[0] = offset;
  521. MoveMemory(((LPBYTE)hGlobal+offset), pidl, cbFolder);
  522. offset += cbFolder;
  523. pida->aoffset[1] = offset;
  524. MoveMemory(((LPBYTE)hGlobal+offset), pidlR, cbRelative);
  525. pMedium->hGlobal = hGlobal;
  526. } else
  527. {
  528. hr = E_OUTOFMEMORY;
  529. }
  530. if (pidl)
  531. ILFree(pidl);
  532. if (pidlR)
  533. ILFree(pidlR);
  534. }
  535. return hr;
  536. }
  537. HRESULT
  538. CFileSecurityDataObject::GetFolderPIDList(
  539. OUT LPITEMIDLIST *ppidl
  540. )
  541. {
  542. ASSERT(!m_cstrPath.IsEmpty());
  543. ASSERT(ppidl);
  544. ASSERT(!*ppidl); // prevent memory leak
  545. *ppidl = ILCreateFromPath(m_cstrPath);
  546. return ((*ppidl) ? S_OK : E_FAIL);
  547. }
  548. ///////////////////////////////////////////////
  549. // File security
  550. // Security Shell extension CLSID - {1F2E5C40-9550-11CE-99D2-00AA006E086C}
  551. const CLSID CLSID_ShellExtSecurity =
  552. {0x1F2E5C40, 0x9550, 0x11CE, {0x99, 0xD2, 0x0, 0xAA, 0x0, 0x6E, 0x08, 0x6C}};
  553. BOOL CALLBACK
  554. AddPageProc(HPROPSHEETPAGE hPage, LPARAM lParam)
  555. {
  556. // pass out the created page handle
  557. *((HPROPSHEETPAGE *)lParam) = hPage;
  558. return TRUE;
  559. }
  560. HRESULT
  561. CreateFileSecurityPropPage(
  562. HPROPSHEETPAGE *phOutPage,
  563. LPDATAOBJECT pDataObject
  564. )
  565. {
  566. ASSERT(phOutPage);
  567. ASSERT(pDataObject);
  568. IShellExtInit *piShellExtInit = NULL;
  569. HRESULT hr = CoCreateInstance(CLSID_ShellExtSecurity,
  570. NULL,
  571. CLSCTX_INPROC_SERVER,
  572. IID_IShellExtInit,
  573. (void **)&piShellExtInit);
  574. if (SUCCEEDED(hr))
  575. {
  576. hr = piShellExtInit->Initialize(NULL, pDataObject, 0);
  577. if (SUCCEEDED(hr))
  578. {
  579. IShellPropSheetExt *piSPSE = NULL;
  580. hr = piShellExtInit->QueryInterface(IID_IShellPropSheetExt, (void **)&piSPSE);
  581. if (SUCCEEDED(hr))
  582. {
  583. hr = piSPSE->AddPages(AddPageProc, (LPARAM)phOutPage);
  584. piSPSE->Release();
  585. }
  586. }
  587. piShellExtInit->Release();
  588. }
  589. return hr;
  590. }