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.

420 lines
11 KiB

  1. // PermPage.cxx : Implementation ACL Editor classes
  2. // jonn 7/10/97 copied from \nt\private\admin\snapin\filemgmt\permpage.cpp
  3. #include "headers.hxx"
  4. #pragma hdrstop
  5. #include "acl.hxx"
  6. #include "resource.h" // IDS_SHAREPERM_*
  7. #include <atlbase.h>
  8. CComModule _Module;
  9. #include <atlcom.h>
  10. #include <atlimpl.cpp>
  11. #include <sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor
  12. // need IID_ISecurityInformation
  13. #define INITGUID
  14. #include <initguid.h>
  15. #include <aclui.h>
  16. //
  17. // I define my own implementation of ISecurityInformation
  18. //
  19. class CSecurityInformation : public ISecurityInformation, public CComObjectRoot
  20. {
  21. DECLARE_NOT_AGGREGATABLE(CSecurityInformation)
  22. BEGIN_COM_MAP(CSecurityInformation)
  23. COM_INTERFACE_ENTRY(ISecurityInformation)
  24. END_COM_MAP()
  25. // *** ISecurityInformation methods ***
  26. STDMETHOD(GetObjectInformation) (PSI_OBJECT_INFO pObjectInfo ) = 0;
  27. STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation,
  28. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  29. BOOL fDefault ) = 0;
  30. STDMETHOD(SetSecurity) (SECURITY_INFORMATION SecurityInformation,
  31. PSECURITY_DESCRIPTOR pSecurityDescriptor ) = 0;
  32. STDMETHOD(GetAccessRights) (const GUID* pguidObjectType,
  33. DWORD dwFlags,
  34. PSI_ACCESS *ppAccess,
  35. ULONG *pcAccesses,
  36. ULONG *piDefaultAccess );
  37. STDMETHOD(MapGeneric) (const GUID *pguidObjectType,
  38. UCHAR *pAceFlags,
  39. ACCESS_MASK *pMask);
  40. STDMETHOD(GetInheritTypes) (PSI_INHERIT_TYPE *ppInheritTypes,
  41. ULONG *pcInheritTypes );
  42. STDMETHOD(PropertySheetPageCallback)(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage );
  43. protected:
  44. HRESULT NewDefaultDescriptor(
  45. PSECURITY_DESCRIPTOR* ppsd,
  46. SECURITY_INFORMATION RequestedInformation
  47. );
  48. HRESULT MakeSelfRelativeCopy(
  49. PSECURITY_DESCRIPTOR psdOriginal,
  50. PSECURITY_DESCRIPTOR* ppsdNew );
  51. };
  52. class CShareSecurityInformation : public CSecurityInformation
  53. {
  54. private:
  55. LPWSTR m_strMachineName;
  56. LPWSTR m_strShareName;
  57. WCHAR m_szTitle[200];
  58. public:
  59. CShareSecurityInformation()
  60. {
  61. LoadString( g_hInstance, IDS_PERMPAGE_TITLE, m_szTitle, ARRAYLEN(m_szTitle) );
  62. }
  63. void SetMachineName( LPWSTR pszMachineName )
  64. {
  65. m_strMachineName = pszMachineName;
  66. }
  67. void SetShareName( LPWSTR pszShareName )
  68. {
  69. m_strShareName = pszShareName;
  70. }
  71. // note: these should be LPCTSTR but are left this way for convenience
  72. LPWSTR QueryMachineName()
  73. {
  74. return m_strMachineName;
  75. }
  76. LPWSTR QueryShareName()
  77. {
  78. return m_strShareName;
  79. }
  80. // *** ISecurityInformation methods ***
  81. STDMETHOD(GetObjectInformation) (PSI_OBJECT_INFO pObjectInfo );
  82. };
  83. class CSMBSecurityInformation : public CShareSecurityInformation
  84. {
  85. STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation,
  86. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  87. BOOL fDefault );
  88. STDMETHOD(SetSecurity) (SECURITY_INFORMATION SecurityInformation,
  89. PSECURITY_DESCRIPTOR pSecurityDescriptor );
  90. public:
  91. PSECURITY_DESCRIPTOR m_pInitialDescriptor;
  92. PSECURITY_DESCRIPTOR* m_ppCurrentDescriptor;
  93. CSMBSecurityInformation();
  94. ~CSMBSecurityInformation();
  95. };
  96. // ISecurityInformation interface implementation
  97. SI_ACCESS siShareAccesses[] =
  98. {
  99. { &GUID_NULL,
  100. FILE_ALL_ACCESS,
  101. MAKEINTRESOURCE(IDS_SHAREPERM_ALL),
  102. SI_ACCESS_GENERAL },
  103. { &GUID_NULL,
  104. FILE_GENERIC_READ | FILE_EXECUTE | FILE_GENERIC_WRITE | DELETE,
  105. MAKEINTRESOURCE(IDS_SHAREPERM_MODIFY),
  106. SI_ACCESS_GENERAL },
  107. { &GUID_NULL,
  108. FILE_GENERIC_READ | FILE_EXECUTE,
  109. MAKEINTRESOURCE(IDS_SHAREPERM_READ),
  110. SI_ACCESS_GENERAL }
  111. };
  112. #define iShareDefAccess 2 // FILE_GEN_READ
  113. #ifndef ARRAYSIZE
  114. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  115. #endif
  116. STDMETHODIMP CSecurityInformation::GetAccessRights (
  117. const GUID* pguidObjectType,
  118. DWORD dwFlags,
  119. PSI_ACCESS *ppAccess,
  120. ULONG *pcAccesses,
  121. ULONG *piDefaultAccess )
  122. {
  123. appAssert(ppAccess != NULL);
  124. appAssert(pcAccesses != NULL);
  125. appAssert(piDefaultAccess != NULL);
  126. *ppAccess = siShareAccesses;
  127. *pcAccesses = ARRAYSIZE(siShareAccesses);
  128. *piDefaultAccess = iShareDefAccess;
  129. return S_OK;
  130. }
  131. // This is consistent with the NETUI code
  132. GENERIC_MAPPING ShareMap =
  133. {
  134. FILE_GENERIC_READ,
  135. FILE_GENERIC_WRITE,
  136. FILE_GENERIC_EXECUTE,
  137. FILE_ALL_ACCESS
  138. };
  139. STDMETHODIMP CSecurityInformation::MapGeneric (
  140. const GUID *pguidObjectType,
  141. UCHAR *pAceFlags,
  142. ACCESS_MASK *pMask)
  143. {
  144. appAssert(pMask != NULL);
  145. MapGenericMask(pMask, &ShareMap);
  146. return S_OK;
  147. }
  148. STDMETHODIMP CSecurityInformation::GetInheritTypes (
  149. PSI_INHERIT_TYPE *ppInheritTypes,
  150. ULONG *pcInheritTypes )
  151. {
  152. appAssert(FALSE);
  153. return E_NOTIMPL;
  154. }
  155. STDMETHODIMP CSecurityInformation::PropertySheetPageCallback(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage )
  156. {
  157. return S_OK;
  158. }
  159. /*
  160. JeffreyS 1/24/97:
  161. If you don't set the SI_RESET flag in
  162. ISecurityInformation::GetObjectInformation, then fDefault should never be TRUE
  163. so you can ignore it. Returning E_NOTIMPL in this case is OK too.
  164. If you want the user to be able to reset the ACL to some default state
  165. (defined by you) then turn on SI_RESET and return your default ACL
  166. when fDefault is TRUE. This happens if/when the user pushes a button
  167. that is only visible when SI_RESET is on.
  168. */
  169. STDMETHODIMP CShareSecurityInformation::GetObjectInformation (
  170. PSI_OBJECT_INFO pObjectInfo )
  171. {
  172. appAssert(pObjectInfo != NULL &&
  173. !IsBadWritePtr(pObjectInfo, sizeof(*pObjectInfo)));
  174. pObjectInfo->dwFlags = SI_EDIT_ALL | SI_NO_ACL_PROTECT | SI_PAGE_TITLE;
  175. pObjectInfo->hInstance = g_hInstance;
  176. pObjectInfo->pszServerName = QueryMachineName();
  177. pObjectInfo->pszObjectName = QueryShareName();
  178. // page title added JonN 3/8/99 per 115196
  179. pObjectInfo->pszPageTitle = m_szTitle;
  180. return S_OK;
  181. }
  182. //
  183. // caller must free using LocalFree()
  184. //
  185. // jeffreys 10/11/2000: Replaced all of the old ACL goop with a
  186. // call to ConvertStringSecurityDescriptorToSecurityDescriptor.
  187. //
  188. const WCHAR c_szDefaultShareSD[] = L"O:BAG:BAD:(A;;GA;;;WD)";
  189. HRESULT CSecurityInformation::NewDefaultDescriptor(
  190. PSECURITY_DESCRIPTOR* ppsd,
  191. SECURITY_INFORMATION RequestedInformation
  192. )
  193. {
  194. HRESULT hr = S_OK;
  195. *ppsd = NULL;
  196. if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
  197. c_szDefaultShareSD,
  198. SDDL_REVISION_1,
  199. ppsd,
  200. NULL))
  201. {
  202. DWORD err = GetLastError();
  203. hr = HRESULT_FROM_WIN32(err);
  204. }
  205. return hr;
  206. }
  207. HRESULT CSecurityInformation::MakeSelfRelativeCopy(
  208. PSECURITY_DESCRIPTOR psdOriginal,
  209. PSECURITY_DESCRIPTOR* ppsdNew )
  210. {
  211. appAssert( NULL != psdOriginal );
  212. // we have to find out whether the original is already self-relative
  213. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  214. DWORD dwRevision = 0;
  215. if ( !::GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) )
  216. {
  217. appAssert( FALSE );
  218. DWORD err = ::GetLastError();
  219. return HRESULT_FROM_WIN32( err );
  220. }
  221. DWORD cb = ::GetSecurityDescriptorLength( psdOriginal ) + 20;
  222. PSECURITY_DESCRIPTOR psdSelfRelativeCopy = reinterpret_cast<PSECURITY_DESCRIPTOR>(
  223. ::LocalAlloc(LMEM_ZEROINIT, cb) );
  224. if (NULL == psdSelfRelativeCopy)
  225. {
  226. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  227. }
  228. if ( sdc & SE_SELF_RELATIVE )
  229. // the original is in self-relative format, just byte-copy it
  230. {
  231. ::memcpy( psdSelfRelativeCopy, psdOriginal, cb - 20 );
  232. }
  233. else if ( !::MakeSelfRelativeSD( psdOriginal, psdSelfRelativeCopy, &cb ) )
  234. // the original is in absolute format, convert-copy it
  235. {
  236. appAssert( FALSE );
  237. if( NULL != ::LocalFree( psdSelfRelativeCopy ) )
  238. {
  239. appAssert(FALSE);
  240. }
  241. DWORD err = ::GetLastError();
  242. return HRESULT_FROM_WIN32( err );
  243. }
  244. *ppsdNew = psdSelfRelativeCopy;
  245. return S_OK;
  246. }
  247. CSMBSecurityInformation::CSMBSecurityInformation()
  248. : CShareSecurityInformation()
  249. , m_pInitialDescriptor( NULL )
  250. , m_ppCurrentDescriptor( NULL )
  251. {
  252. }
  253. CSMBSecurityInformation::~CSMBSecurityInformation()
  254. {
  255. }
  256. STDMETHODIMP CSMBSecurityInformation::GetSecurity (
  257. SECURITY_INFORMATION RequestedInformation,
  258. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  259. BOOL fDefault )
  260. {
  261. appAssert( NULL != m_ppCurrentDescriptor );
  262. // NOTE: we allow NULL == ppSecurityDescriptor, see SetSecurity
  263. if (0 == RequestedInformation )
  264. {
  265. appAssert(FALSE);
  266. return E_INVALIDARG;
  267. }
  268. if (fDefault)
  269. return E_NOTIMPL;
  270. if ( NULL == ppSecurityDescriptor )
  271. return S_OK;
  272. *ppSecurityDescriptor = NULL;
  273. HRESULT hr = S_OK;
  274. if (NULL != *m_ppCurrentDescriptor)
  275. {
  276. hr = MakeSelfRelativeCopy(
  277. *m_ppCurrentDescriptor,
  278. ppSecurityDescriptor );
  279. appAssert( SUCCEEDED(hr) && NULL != *ppSecurityDescriptor );
  280. }
  281. else if (NULL != m_pInitialDescriptor)
  282. {
  283. hr = MakeSelfRelativeCopy(
  284. m_pInitialDescriptor,
  285. ppSecurityDescriptor );
  286. appAssert( SUCCEEDED(hr) && NULL != *ppSecurityDescriptor );
  287. }
  288. else
  289. {
  290. hr = NewDefaultDescriptor(
  291. ppSecurityDescriptor,
  292. RequestedInformation );
  293. appAssert( SUCCEEDED(hr) && NULL != *ppSecurityDescriptor );
  294. }
  295. return hr;
  296. }
  297. STDMETHODIMP CSMBSecurityInformation::SetSecurity (
  298. SECURITY_INFORMATION SecurityInformation,
  299. PSECURITY_DESCRIPTOR pSecurityDescriptor )
  300. {
  301. appAssert( NULL != m_ppCurrentDescriptor );
  302. if (NULL != *m_ppCurrentDescriptor)
  303. {
  304. ::LocalFree(*m_ppCurrentDescriptor);
  305. *m_ppCurrentDescriptor = NULL;
  306. }
  307. HRESULT hr = MakeSelfRelativeCopy(
  308. pSecurityDescriptor,
  309. m_ppCurrentDescriptor );
  310. appAssert( SUCCEEDED(hr) && NULL != *m_ppCurrentDescriptor );
  311. return hr;
  312. }
  313. HMODULE g_hlibACLUI = NULL;
  314. typedef BOOL (*EDIT_SECURITY_PROC) ( HWND, LPSECURITYINFO );
  315. EDIT_SECURITY_PROC g_pfnEditSecurityProc;
  316. LONG
  317. EditShareAcl(
  318. IN HWND hwndParent,
  319. IN LPWSTR pszServerName,
  320. IN TCHAR * pszShareName,
  321. IN PSECURITY_DESCRIPTOR pSecDesc,
  322. OUT BOOL* pfSecDescModified,
  323. OUT PSECURITY_DESCRIPTOR* ppSecDesc
  324. )
  325. {
  326. appAssert( ppSecDesc != NULL );
  327. *ppSecDesc = NULL;
  328. if (NULL == g_hlibACLUI)
  329. {
  330. g_hlibACLUI = ::LoadLibrary(L"ACLUI.DLL");
  331. if (NULL == g_hlibACLUI)
  332. {
  333. appAssert(FALSE); // ACLUI.DLL isn't installed?
  334. return 0;
  335. }
  336. }
  337. if (NULL == g_pfnEditSecurityProc)
  338. {
  339. g_pfnEditSecurityProc = reinterpret_cast<EDIT_SECURITY_PROC>(
  340. ::GetProcAddress(g_hlibACLUI,"EditSecurity") );
  341. if (NULL == g_pfnEditSecurityProc)
  342. {
  343. appAssert(FALSE); // ACLUI.DLL is invalid?
  344. return 0;
  345. }
  346. }
  347. CComObject<CSMBSecurityInformation>* psecinfo = NULL;
  348. HRESULT hRes = CComObject<CSMBSecurityInformation>::CreateInstance(&psecinfo);
  349. if ( FAILED(hRes) )
  350. return 0;
  351. psecinfo->AddRef();
  352. psecinfo->SetMachineName( pszServerName );
  353. psecinfo->SetShareName( pszShareName );
  354. psecinfo->m_pInitialDescriptor = pSecDesc;
  355. psecinfo->m_ppCurrentDescriptor = ppSecDesc;
  356. (g_pfnEditSecurityProc)(hwndParent,psecinfo);
  357. if (NULL != pfSecDescModified)
  358. *pfSecDescModified = (NULL != *ppSecDesc);
  359. psecinfo->Release();
  360. return 0;
  361. }