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.

692 lines
17 KiB

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