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.

340 lines
8.3 KiB

  1. // PermPage.cpp : Implementation of data object classes
  2. #include "stdafx.h"
  3. #include "cookie.h"
  4. #include "macros.h"
  5. USE_HANDLE_MACROS("FILEMGMT(PermPage.cpp)")
  6. #include "DynamLnk.h" // DynamicDLL
  7. #include "PermPage.h"
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. /*
  14. * Share General Permissions -- from shareacl.hxx
  15. #define FILE_PERM_GEN_NO_ACCESS (0)
  16. #define FILE_PERM_GEN_READ (GENERIC_READ |\
  17. GENERIC_EXECUTE)
  18. #define FILE_PERM_GEN_MODIFY (GENERIC_READ |\
  19. GENERIC_EXECUTE |\
  20. GENERIC_WRITE |\
  21. DELETE )
  22. #define FILE_PERM_GEN_ALL (GENERIC_ALL)
  23. */
  24. SI_ACCESS siShareAccesses[] =
  25. {
  26. { &GUID_NULL,
  27. FILE_ALL_ACCESS,
  28. MAKEINTRESOURCE(IDS_SHAREPERM_ALL),
  29. SI_ACCESS_GENERAL },
  30. { &GUID_NULL,
  31. FILE_GENERIC_READ | FILE_EXECUTE | FILE_GENERIC_WRITE | DELETE,
  32. MAKEINTRESOURCE(IDS_SHAREPERM_MODIFY),
  33. SI_ACCESS_GENERAL },
  34. { &GUID_NULL,
  35. FILE_GENERIC_READ | FILE_EXECUTE,
  36. MAKEINTRESOURCE(IDS_SHAREPERM_READ),
  37. SI_ACCESS_GENERAL }
  38. };
  39. #define iShareDefAccess 2 // index of value in array siShareAccesses
  40. #ifndef ARRAYSIZE
  41. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  42. #endif
  43. STDMETHODIMP
  44. CSecurityInformation::GetAccessRights(
  45. const GUID * /*pguidObjectType*/,
  46. DWORD /*dwFlags*/,
  47. PSI_ACCESS *ppAccess,
  48. ULONG *pcAccesses,
  49. ULONG *piDefaultAccess
  50. )
  51. {
  52. ASSERT(ppAccess);
  53. ASSERT(pcAccesses);
  54. ASSERT(piDefaultAccess);
  55. *ppAccess = siShareAccesses;
  56. *pcAccesses = ARRAYSIZE(siShareAccesses);
  57. *piDefaultAccess = iShareDefAccess;
  58. return S_OK;
  59. }
  60. // This is consistent with the NETUI code
  61. GENERIC_MAPPING ShareMap =
  62. {
  63. FILE_GENERIC_READ,
  64. FILE_GENERIC_WRITE,
  65. FILE_GENERIC_EXECUTE,
  66. FILE_ALL_ACCESS
  67. };
  68. STDMETHODIMP
  69. CSecurityInformation::MapGeneric(
  70. const GUID * /*pguidObjectType*/,
  71. UCHAR * /*pAceFlags*/,
  72. ACCESS_MASK *pMask
  73. )
  74. {
  75. ASSERT(pMask);
  76. MapGenericMask(pMask, &ShareMap);
  77. return S_OK;
  78. }
  79. STDMETHODIMP
  80. CSecurityInformation::GetInheritTypes (
  81. PSI_INHERIT_TYPE * /*ppInheritTypes*/,
  82. ULONG * /*pcInheritTypes*/
  83. )
  84. {
  85. return E_NOTIMPL;
  86. }
  87. STDMETHODIMP
  88. CSecurityInformation::PropertySheetPageCallback(
  89. HWND /*hwnd*/,
  90. UINT /*uMsg*/,
  91. SI_PAGE_TYPE /*uPage*/
  92. )
  93. {
  94. return S_OK;
  95. }
  96. /*
  97. JeffreyS 1/24/97:
  98. If you don't set the SI_RESET flag in
  99. ISecurityInformation::GetObjectInformation, then fDefault should never be TRUE
  100. so you can ignore it. Returning E_NOTIMPL in this case is OK too.
  101. If you want the user to be able to reset the ACL to some default state
  102. (defined by you) then turn on SI_RESET and return your default ACL
  103. when fDefault is TRUE. This happens if/when the user pushes a button
  104. that is only visible when SI_RESET is on.
  105. */
  106. STDMETHODIMP CShareSecurityInformation::GetObjectInformation (
  107. PSI_OBJECT_INFO pObjectInfo )
  108. {
  109. ASSERT(pObjectInfo != NULL &&
  110. !IsBadWritePtr(pObjectInfo, sizeof(*pObjectInfo)));
  111. pObjectInfo->dwFlags = SI_EDIT_ALL | SI_NO_ACL_PROTECT | SI_PAGE_TITLE;
  112. pObjectInfo->hInstance = g_hInstanceSave;
  113. pObjectInfo->pszServerName = QueryMachineName();
  114. pObjectInfo->pszObjectName = QueryShareName();
  115. pObjectInfo->pszPageTitle = QueryPageTitle();
  116. return S_OK;
  117. }
  118. typedef enum _AcluiApiIndex
  119. {
  120. ACLUI_CREATE_PAGE = 0
  121. };
  122. // not subject to localization
  123. static LPCSTR g_apchFunctionNames[] = {
  124. "CreateSecurityPage",
  125. NULL
  126. };
  127. // not subject to localization
  128. DynamicDLL g_AcluiDLL( _T("ACLUI.DLL"), g_apchFunctionNames );
  129. /*
  130. HPROPSHEETPAGE ACLUIAPI CreateSecurityPage( LPSECURITYINFO psi );
  131. */
  132. typedef HPROPSHEETPAGE (*CREATEPAGE_PROC) (LPSECURITYINFO);
  133. HRESULT
  134. MyCreateShareSecurityPage(
  135. IN LPPROPERTYSHEETCALLBACK pCallBack,
  136. IN CShareSecurityInformation *pSecInfo,
  137. IN LPCTSTR pszMachineName,
  138. IN LPCTSTR pszShareName
  139. )
  140. {
  141. ASSERT( pCallBack );
  142. ASSERT( pSecInfo );
  143. HRESULT hr = S_OK;
  144. if ( !g_AcluiDLL.LoadFunctionPointers() )
  145. return hr; // ignore the load failure
  146. pSecInfo->SetMachineName( pszMachineName );
  147. pSecInfo->SetShareName( pszShareName );
  148. CString csPageTitle;
  149. csPageTitle.LoadString(IDS_SHARE_SECURITY);
  150. pSecInfo->SetPageTitle( csPageTitle );
  151. pSecInfo->AddRef();
  152. HPROPSHEETPAGE hPage = ((CREATEPAGE_PROC)g_AcluiDLL[ACLUI_CREATE_PAGE])(pSecInfo);
  153. if (hPage)
  154. pCallBack->AddPage(hPage);
  155. else
  156. hr = HRESULT_FROM_WIN32(GetLastError());
  157. pSecInfo->Release();
  158. return hr;
  159. }
  160. HRESULT
  161. CSecurityInformation::NewDefaultDescriptor(
  162. OUT PSECURITY_DESCRIPTOR *ppsd,
  163. IN SECURITY_INFORMATION /*RequestedInformation*/
  164. )
  165. {
  166. ASSERT(ppsd);
  167. *ppsd = NULL;
  168. PSID psidWorld = NULL, psidAdmins = NULL;
  169. PACL pAcl = NULL;
  170. SECURITY_DESCRIPTOR sd;
  171. DWORD dwErr = 0;
  172. do { // false loop
  173. // get World SID for "everyone"
  174. SID_IDENTIFIER_AUTHORITY IDAuthorityWorld = SECURITY_WORLD_SID_AUTHORITY;
  175. if ( !::AllocateAndInitializeSid(
  176. &IDAuthorityWorld,
  177. 1,
  178. SECURITY_WORLD_RID,
  179. 0,0,0,0,0,0,0,
  180. &psidWorld ) )
  181. {
  182. dwErr = GetLastError();
  183. break;
  184. }
  185. // get Admins SID
  186. SID_IDENTIFIER_AUTHORITY IDAuthorityNT = SECURITY_NT_AUTHORITY;
  187. if ( !::AllocateAndInitializeSid(
  188. &IDAuthorityNT,
  189. 2,
  190. SECURITY_BUILTIN_DOMAIN_RID,
  191. DOMAIN_ALIAS_RID_ADMINS,
  192. 0,0,0,0,0,0,
  193. &psidAdmins ) )
  194. {
  195. dwErr = GetLastError();
  196. break;
  197. }
  198. // build ACL, and add AccessAllowedAce to it
  199. DWORD cbAcl = sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE) +
  200. ::GetLengthSid(psidWorld) - sizeof (DWORD);
  201. pAcl = reinterpret_cast<ACL *>(LocalAlloc(LPTR, cbAcl));
  202. if ( !pAcl ||
  203. !::InitializeAcl(pAcl, cbAcl, ACL_REVISION2) ||
  204. !::AddAccessAllowedAce(pAcl, ACL_REVISION2, GENERIC_ALL, psidWorld) )
  205. {
  206. dwErr = GetLastError();
  207. break;
  208. }
  209. // add ACL to the security descriptor, and set Owner and Group appropriately
  210. if ( !::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
  211. !::SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE) ||
  212. !::SetSecurityDescriptorOwner(&sd, psidAdmins, FALSE) ||
  213. !::SetSecurityDescriptorGroup(&sd, psidAdmins, FALSE) )
  214. {
  215. dwErr = GetLastError();
  216. break;
  217. }
  218. // convert security descriptor to self-relative format
  219. DWORD cbSD = 0;
  220. ::MakeSelfRelativeSD(&sd, NULL, &cbSD); // this call should fail and set cbSD to the correct size
  221. *ppsd = (PSECURITY_DESCRIPTOR)(LocalAlloc(LPTR, cbSD));
  222. if ( !(*ppsd) || !::MakeSelfRelativeSD(&sd, *ppsd, &cbSD) )
  223. {
  224. dwErr = GetLastError();
  225. break;
  226. }
  227. } while (FALSE); // false loop
  228. // clean up
  229. if (psidWorld)
  230. (void)::FreeSid(psidWorld);
  231. if (psidAdmins)
  232. (void)::FreeSid(psidAdmins);
  233. if (pAcl)
  234. LocalFree(pAcl);
  235. if (dwErr && *ppsd)
  236. {
  237. LocalFree(*ppsd);
  238. *ppsd = NULL;
  239. }
  240. return (dwErr ? HRESULT_FROM_WIN32(dwErr) : S_OK);
  241. }
  242. HRESULT
  243. CSecurityInformation::MakeSelfRelativeCopy(
  244. IN PSECURITY_DESCRIPTOR psdOriginal,
  245. OUT PSECURITY_DESCRIPTOR *ppsdNew
  246. )
  247. {
  248. ASSERT(psdOriginal);
  249. ASSERT(ppsdNew);
  250. *ppsdNew = NULL;
  251. DWORD dwErr = 0;
  252. PSECURITY_DESCRIPTOR psdSelfRelative = NULL;
  253. do { // false loop
  254. DWORD cbSD = ::GetSecurityDescriptorLength(psdOriginal);
  255. psdSelfRelative = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, cbSD);
  256. if ( !psdSelfRelative )
  257. {
  258. dwErr = ::GetLastError();
  259. break;
  260. }
  261. // we have to find out whether the original is already self-relative
  262. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  263. DWORD dwRevision = 0;
  264. if ( !::GetSecurityDescriptorControl(psdOriginal, &sdc, &dwRevision) )
  265. {
  266. dwErr = ::GetLastError();
  267. break;
  268. }
  269. if (sdc & SE_SELF_RELATIVE)
  270. {
  271. ::memcpy(psdSelfRelative, psdOriginal, cbSD);
  272. } else if ( !::MakeSelfRelativeSD(psdOriginal, psdSelfRelative, &cbSD) )
  273. {
  274. dwErr = ::GetLastError();
  275. break;
  276. }
  277. *ppsdNew = psdSelfRelative;
  278. } while (FALSE);
  279. if (dwErr && psdSelfRelative)
  280. LocalFree(psdSelfRelative);
  281. return (dwErr ? HRESULT_FROM_WIN32(dwErr) : S_OK);
  282. }