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.

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