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.

300 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. setperm.cpp
  5. Abstract:
  6. IIS Security Wizard helper file
  7. Author:
  8. Sergei Antonov (sergeia)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. 7/12/99 created
  13. --*/
  14. //
  15. // Include Files
  16. //
  17. #include "stdafx.h"
  18. #include "comprop.h"
  19. #include <aclapi.h>
  20. #include <ntseapi.h>
  21. #include <shlwapi.h>
  22. static HRESULT
  23. SetSecurityDeep(
  24. LPTSTR *ppszBuffer,
  25. UINT * pcchBuffer,
  26. DWORD dwAttributes,
  27. SECURITY_INFORMATION si,
  28. PACL pDacl,
  29. PACL pSacl
  30. );
  31. static BOOL
  32. PathIsDotOrDotDot(LPCTSTR pszPath)
  33. {
  34. if (TEXT('.') == *pszPath++)
  35. {
  36. if (TEXT('\0') == *pszPath || (TEXT('.') == *pszPath && TEXT('\0') == *(pszPath + 1)))
  37. return TRUE;
  38. }
  39. return FALSE;
  40. }
  41. HRESULT
  42. CPWSummary::SetPermToChildren(
  43. IN CString& FileName,
  44. IN SECURITY_INFORMATION si,
  45. IN PACL pDacl,
  46. IN PACL pSacl
  47. )
  48. {
  49. HRESULT hr = S_OK;
  50. LPTSTR pszBuffer = NULL;
  51. UINT cchBuffer = 0, cchFolder;
  52. HANDLE hFind;
  53. WIN32_FIND_DATA fd;
  54. pszBuffer = (LPTSTR)LocalAlloc(LMEM_FIXED, 2 * MAX_PATH * sizeof(TCHAR));
  55. if (pszBuffer == NULL)
  56. return E_OUTOFMEMORY;
  57. cchBuffer = (UINT)LocalSize(pszBuffer) / sizeof(TCHAR);
  58. lstrcpy(pszBuffer, FileName);
  59. cchFolder = lstrlen(pszBuffer);
  60. // Append a backslash if it's not there already
  61. if (pszBuffer[cchFolder-1] != TEXT('\\'))
  62. {
  63. pszBuffer[cchFolder] = TEXT('\\');
  64. cchFolder++;
  65. }
  66. // Append the '*' wildcard
  67. pszBuffer[cchFolder] = TEXT('*');
  68. pszBuffer[cchFolder+1] = TEXT('\0');
  69. if (INVALID_HANDLE_VALUE != (hFind = FindFirstFile(pszBuffer, &fd)))
  70. {
  71. do
  72. {
  73. if (PathIsDotOrDotDot(fd.cFileName))
  74. continue;
  75. //
  76. // Build full path name and recurse
  77. //
  78. lstrcpyn(pszBuffer + cchFolder, fd.cFileName, cchBuffer - cchFolder);
  79. if (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
  80. {
  81. hr = SetSecurityDeep(&pszBuffer,
  82. &cchBuffer,
  83. fd.dwFileAttributes,
  84. si,
  85. pDacl,
  86. pSacl);
  87. }
  88. else
  89. {
  90. hr = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
  91. pszBuffer,
  92. SE_FILE_OBJECT,
  93. si,
  94. NULL,
  95. NULL,
  96. pDacl,
  97. pSacl));
  98. }
  99. }
  100. while (S_OK == hr && FindNextFile(hFind, &fd));
  101. FindClose(hFind);
  102. }
  103. if (pszBuffer != NULL)
  104. LocalFree(pszBuffer);
  105. return hr;
  106. }
  107. static HRESULT
  108. SetSecurityDeep(
  109. LPTSTR *ppszBuffer,
  110. UINT * pcchBuffer,
  111. DWORD dwAttributes,
  112. SECURITY_INFORMATION si,
  113. PACL pDacl,
  114. PACL pSacl
  115. )
  116. {
  117. HRESULT hr = S_OK;
  118. DWORD dwErr = NOERROR;
  119. LPTSTR pszBuffer;
  120. BOOL bWriteDone = FALSE;
  121. pszBuffer = *ppszBuffer;
  122. //
  123. // Recursively apply the new SD to subfolders
  124. //
  125. if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
  126. {
  127. HANDLE hFind;
  128. WIN32_FIND_DATA fd;
  129. UINT cchFolder;
  130. UINT cchSizeRequired;
  131. cchFolder = lstrlen(pszBuffer);
  132. //
  133. // If the buffer is getting tight, realloc
  134. //
  135. cchSizeRequired = cchFolder + 1 + sizeof(fd.cFileName) / sizeof(TCHAR); // 1 for backslash
  136. if (cchSizeRequired > *pcchBuffer)
  137. {
  138. cchSizeRequired += MAX_PATH; // so we don't realloc as often
  139. pszBuffer = (LPTSTR)LocalReAlloc(*ppszBuffer, cchSizeRequired * sizeof(TCHAR), LMEM_MOVEABLE);
  140. if (pszBuffer)
  141. {
  142. *ppszBuffer = pszBuffer;
  143. *pcchBuffer = cchSizeRequired;
  144. }
  145. else
  146. {
  147. // fd.cFileName typically has some empty space, so we
  148. // may be able to continue
  149. pszBuffer = *ppszBuffer;
  150. if (*pcchBuffer < cchFolder + 3) // backslash, '*', and NULL
  151. return E_OUTOFMEMORY;
  152. }
  153. }
  154. // Append a backslash if it's not there already
  155. if (pszBuffer[cchFolder-1] != TEXT('\\'))
  156. {
  157. pszBuffer[cchFolder] = TEXT('\\');
  158. cchFolder++;
  159. }
  160. // Append the '*' wildcard
  161. pszBuffer[cchFolder] = TEXT('*');
  162. pszBuffer[cchFolder+1] = TEXT('\0');
  163. //
  164. // Enumerate the folder contents
  165. //
  166. hFind = FindFirstFile(pszBuffer, &fd);
  167. if (INVALID_HANDLE_VALUE == hFind)
  168. {
  169. dwErr = GetLastError();
  170. if (ERROR_ACCESS_DENIED == dwErr)
  171. {
  172. // Remove the '*' wildcard
  173. pszBuffer[cchFolder-1] = TEXT('\0');
  174. if (si & DACL_SECURITY_INFORMATION)
  175. {
  176. //
  177. // The user may be granting themselves access, so call
  178. // WriteObjectSecurity and retry FindFirstFile.
  179. //
  180. // Don't blindly call WriteObjectSecurity before FindFirstFile
  181. // since it's possible the user has access now but is removing
  182. // their own access.
  183. //
  184. bWriteDone = TRUE;
  185. hr = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
  186. pszBuffer,
  187. SE_FILE_OBJECT,
  188. si,
  189. NULL,
  190. NULL,
  191. pDacl,
  192. pSacl));
  193. if (SUCCEEDED(hr))
  194. {
  195. // Retry FindFirstFile
  196. pszBuffer[cchFolder-1] = TEXT('\\');
  197. hFind = FindFirstFile(pszBuffer, &fd);
  198. }
  199. }
  200. }
  201. }
  202. if (hFind != INVALID_HANDLE_VALUE)
  203. {
  204. do
  205. {
  206. if (PathIsDotOrDotDot(fd.cFileName))
  207. continue;
  208. //
  209. // Build full path name and recurse
  210. //
  211. lstrcpyn(pszBuffer + cchFolder, fd.cFileName, *pcchBuffer - cchFolder);
  212. hr = SetSecurityDeep(ppszBuffer,
  213. pcchBuffer,
  214. fd.dwFileAttributes,
  215. si,
  216. pDacl,
  217. pSacl);
  218. // In case the buffer was reallocated
  219. pszBuffer = *ppszBuffer;
  220. }
  221. while (S_OK == hr && FindNextFile(hFind, &fd));
  222. FindClose(hFind);
  223. }
  224. else if (NOERROR != dwErr)
  225. {
  226. hr = S_FALSE; // abort
  227. }
  228. // Truncate the path back to the original length (sans backslash)
  229. pszBuffer[cchFolder-1] = TEXT('\0');
  230. }
  231. //
  232. // Finally, write out the new security descriptor
  233. //
  234. if (!bWriteDone)
  235. {
  236. hr = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
  237. pszBuffer,
  238. SE_FILE_OBJECT,
  239. si,
  240. NULL,
  241. NULL,
  242. pDacl,
  243. pSacl));
  244. }
  245. if (SUCCEEDED(hr))
  246. {
  247. //
  248. // Notify the shell if we change permissions on a folder (48220)
  249. //
  250. if ( (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
  251. && (si & DACL_SECURITY_INFORMATION)
  252. )
  253. {
  254. SHChangeNotify(
  255. SHCNE_UPDATEDIR,
  256. SHCNF_PATH | SHCNF_FLUSH | SHCNF_FLUSHNOWAIT,
  257. pszBuffer,
  258. NULL);
  259. }
  260. }
  261. else
  262. {
  263. hr = S_FALSE; // abort
  264. }
  265. return hr;
  266. }