Leaked source code of windows server 2003
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.

453 lines
10 KiB

  1. /*************************************************************************
  2. *
  3. * dirwalk.c
  4. *
  5. * Walk a tree setting ACL's on an NT system.
  6. *
  7. * Copyright Microsoft, 1998
  8. *
  9. *
  10. *
  11. *************************************************************************/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <process.h>
  18. #include <winsta.h>
  19. #include <syslib.h>
  20. #include "security.h"
  21. #if DBG
  22. ULONG
  23. DbgPrint(
  24. PCH Format,
  25. ...
  26. );
  27. #define DBGPRINT(x) DbgPrint x
  28. #if DBGTRACE
  29. #define TRACE0(x) DbgPrint x
  30. #define TRACE1(x) DbgPrint x
  31. #else
  32. #define TRACE0(x)
  33. #define TRACE1(x)
  34. #endif
  35. #else
  36. #define DBGPRINT(x)
  37. #define TRACE0(x)
  38. #define TRACE1(x)
  39. #endif
  40. // Global variables
  41. PWCHAR gpAvoidDir = NULL;
  42. CRITICAL_SECTION SyslibCritSect;
  43. typedef BOOLEAN (CALLBACK* NODEPROC)( PWCHAR, PWIN32_FIND_DATAW, DWORD, DWORD );
  44. BOOLEAN
  45. EnumerateDirectory(
  46. PWCHAR pRoot,
  47. DWORD Level,
  48. NODEPROC pProc
  49. );
  50. BOOLEAN
  51. NodeEnumProc(
  52. PWCHAR pParent,
  53. PWIN32_FIND_DATA p,
  54. DWORD Level,
  55. DWORD Index
  56. );
  57. PWCHAR
  58. AddWildCard(
  59. PWCHAR pRoot
  60. );
  61. PWCHAR
  62. AddBackSlash(
  63. PWCHAR pRoot
  64. );
  65. FILE_RESULT
  66. xxxProcessFile(
  67. PWCHAR pParent,
  68. PWIN32_FIND_DATAW p,
  69. DWORD Level,
  70. DWORD Index
  71. );
  72. /*****************************************************************************
  73. *
  74. * CtxGetSyslibCritSect
  75. *
  76. * Returns the library global critical section pointer.
  77. * Critical section will be initialised if necessary
  78. *
  79. * ENTRY:
  80. * VOID - Caller must ensure that only one threads a times calls this
  81. * function. The function will not itself guarantie mutual exclusion.
  82. * EXIT:
  83. * Pointer to critical section. NULL if failure.
  84. *
  85. ****************************************************************************/
  86. PCRITICAL_SECTION
  87. CtxGetSyslibCritSect(void)
  88. {
  89. static BOOLEAN fInitialized = FALSE;
  90. NTSTATUS Status;
  91. if( !fInitialized ){
  92. Status = RtlInitializeCriticalSection(&SyslibCritSect);
  93. if (NT_SUCCESS(Status)) {
  94. fInitialized = TRUE;
  95. }else{
  96. return NULL;
  97. }
  98. }
  99. return(&SyslibCritSect);
  100. }
  101. /*****************************************************************************
  102. *
  103. * SetFileTree
  104. *
  105. * Walk the given tree calling the processing function for each node.
  106. *
  107. * ENTRY:
  108. * pRoot (input)
  109. * Full WIN32 path to directory to walk
  110. *
  111. * pVoidDir (input)
  112. *
  113. * EXIT:
  114. * STATUS_SUCCESS - no error
  115. *
  116. ****************************************************************************/
  117. BOOLEAN
  118. SetFileTree(
  119. PWCHAR pRoot,
  120. PWCHAR pAvoidDir
  121. )
  122. {
  123. BOOLEAN rc;
  124. PWCHAR pRootNew;
  125. static BOOLEAN fInitialized = FALSE;
  126. PRTL_CRITICAL_SECTION pLock = CtxGetSyslibCritSect();
  127. // if critical section could not be created, do nothing.
  128. if (pLock == NULL) {
  129. return FALSE;
  130. }
  131. DBGPRINT(( "entering SetFileTree(pRoot=%ws,pAvoidDir=%ws)\n", pRoot, pAvoidDir ));
  132. EnterCriticalSection(pLock);
  133. // If this is the console make sure the user hasn't changed
  134. if ((NtCurrentPeb()->SessionId == 0) && fInitialized) {
  135. CheckUserSid();
  136. } else if ( !fInitialized ) {
  137. fInitialized = TRUE;
  138. if ( !InitSecurity() ) {
  139. DBGPRINT(( "problem initializing security; we're outta here.\n" ));
  140. LeaveCriticalSection(pLock);
  141. return( 1 ); // (non-zero for error...)// Should be return FALSE!?
  142. }
  143. }
  144. LeaveCriticalSection(pLock);
  145. gpAvoidDir = pAvoidDir;
  146. // be sure to apply security to root directory
  147. pRootNew = AddBackSlash(pRoot);
  148. if(pRootNew) {
  149. DBGPRINT(( "processing file %ws\n", pRootNew ));
  150. xxxProcessFile(pRootNew, NULL, 0, 0);
  151. LocalFree(pRootNew);
  152. }
  153. rc = EnumerateDirectory( pRoot, 0, NodeEnumProc );
  154. DBGPRINT(( "leaving SetFileTree()\n" ));
  155. return( rc );
  156. }
  157. /*****************************************************************************
  158. *
  159. * EnumerateDirectory
  160. *
  161. * Walk the given directory calling the processing function for each file.
  162. *
  163. * ENTRY:
  164. * pRoot (input)
  165. * Full WIN32 path to directory to walk
  166. *
  167. * Level (input)
  168. * Level we are in a given tree. Useful for formating output
  169. *
  170. * pProc (input)
  171. * Procedure to call for each non-directory file
  172. *
  173. * EXIT:
  174. * STATUS_SUCCESS - no error
  175. *
  176. ****************************************************************************/
  177. BOOLEAN
  178. EnumerateDirectory(
  179. PWCHAR pRoot,
  180. DWORD Level,
  181. NODEPROC pProc
  182. )
  183. {
  184. BOOL rc;
  185. DWORD Result;
  186. HANDLE hf;
  187. DWORD Index;
  188. WIN32_FIND_DATA Data;
  189. PWCHAR pRootNew;
  190. DBGPRINT(( "entering EnumerateDirectory(pRoot=%ws,Level=%ld,pProc=NodeEnumProc)\n",pRoot,Level ));
  191. if( pRoot == NULL ) {
  192. DBGPRINT(( "leaving EnumerateDirectory(), return=FALSE\n" ));
  193. return( FALSE );
  194. }
  195. // Make sure it is not one we want to avoid
  196. if( gpAvoidDir ) {
  197. DWORD Len = wcslen( gpAvoidDir );
  198. if( _wcsnicmp( pRoot, gpAvoidDir, Len ) == 0 ) {
  199. DBGPRINT(( "leaving EnumerateDirectory(), return=FALSE\n" ));
  200. return( FALSE );
  201. }
  202. }
  203. pRootNew = AddWildCard( pRoot );
  204. if( pRootNew == NULL ) {
  205. DBGPRINT(( "leaving EnumerateDirectory(), return=FALSE\n" ));
  206. return( FALSE );
  207. }
  208. Index = 0;
  209. DBGPRINT(("FindFirstFileW: %ws\n",pRootNew));
  210. hf = FindFirstFileW(
  211. pRootNew,
  212. &Data
  213. );
  214. if( hf == INVALID_HANDLE_VALUE ) {
  215. DBGPRINT(("EnumerateDirectory: Error %d opening root %ws\n",GetLastError(),pRootNew));
  216. LocalFree( pRootNew );
  217. DBGPRINT(( "leaving EnumerateDirectory(), return=FALSE\n" ));
  218. return(FALSE);
  219. }
  220. while( 1 ) {
  221. // pass the parent without the wildcard added
  222. pProc( pRoot, &Data, Level, Index );
  223. rc = FindNextFile(
  224. hf,
  225. &Data
  226. );
  227. if( !rc ) {
  228. Result = GetLastError();
  229. if( Result == ERROR_NO_MORE_FILES ) {
  230. FindClose( hf );
  231. LocalFree( pRootNew );
  232. DBGPRINT(( "leaving EnumerateDirectory(), return=TRUE\n" ));
  233. return( TRUE );
  234. }
  235. else {
  236. DBGPRINT(("EnumerateDirectory: Error %d, Index 0x%x\n",Result,Index));
  237. FindClose( hf );
  238. LocalFree( pRootNew );
  239. DBGPRINT(( "leaving EnumerateDirectory(), return=FALSE\n" ));
  240. return( FALSE );
  241. }
  242. }
  243. Index++;
  244. }
  245. // UNREACHABLE.
  246. }
  247. /*****************************************************************************
  248. *
  249. * NodeEnumProc
  250. *
  251. * Process the enumerated file
  252. *
  253. * ENTRY:
  254. * Param1 (input/output)
  255. * Comments
  256. *
  257. * EXIT:
  258. * STATUS_SUCCESS - no error
  259. *
  260. ****************************************************************************/
  261. BOOLEAN
  262. NodeEnumProc(
  263. PWCHAR pParent,
  264. PWIN32_FIND_DATAW p,
  265. DWORD Level,
  266. DWORD Index
  267. )
  268. {
  269. BOOLEAN rc;
  270. PWCHAR pParentNew;
  271. DWORD ParentCount, ChildCount;
  272. //
  273. // We must append the directory to our parent path to get the
  274. // new full path.
  275. //
  276. ParentCount = wcslen( pParent );
  277. ChildCount = wcslen( p->cFileName );
  278. pParentNew = LocalAlloc( LMEM_FIXED, (ParentCount + ChildCount + 2)*sizeof(WCHAR) );
  279. if( pParentNew == NULL ) return( FALSE );
  280. wcscpy( pParentNew, pParent );
  281. wcscat( pParentNew, L"\\" );
  282. wcscat( pParentNew, p->cFileName );
  283. if( p->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
  284. // Skip "." and ".."
  285. if( wcscmp( L".", p->cFileName ) == 0 ) {
  286. LocalFree( pParentNew );
  287. return( TRUE );
  288. }
  289. if( wcscmp( L"..", p->cFileName ) == 0 ) {
  290. LocalFree( pParentNew );
  291. return( TRUE );
  292. }
  293. TRACE0(("%ws:\n",pParentNew));
  294. xxxProcessFile( pParentNew, p, Level, Index );
  295. // For directories, we recurse
  296. rc = EnumerateDirectory( pParentNew, Level+1, NodeEnumProc );
  297. LocalFree( pParentNew );
  298. return( rc );
  299. }
  300. TRACE0(("%ws\n",pParentNew));
  301. xxxProcessFile( pParentNew, p, Level, Index );
  302. LocalFree( pParentNew );
  303. return( TRUE );
  304. }
  305. /*****************************************************************************
  306. *
  307. * AddWildCard
  308. *
  309. * Add the wild card search specifier
  310. *
  311. * ENTRY:
  312. * Param1 (input/output)
  313. * Comments
  314. *
  315. * EXIT:
  316. * STATUS_SUCCESS - no error
  317. *
  318. ****************************************************************************/
  319. PWCHAR
  320. AddWildCard(
  321. PWCHAR pRoot
  322. )
  323. {
  324. DWORD Count;
  325. PWCHAR pNew;
  326. PWCHAR WildCard = L"\\*";
  327. Count = wcslen( pRoot );
  328. pNew = LocalAlloc( LMEM_FIXED, (Count + wcslen(WildCard) + 1)*sizeof(WCHAR) );
  329. if( pNew == NULL ) {
  330. return( NULL );
  331. }
  332. wcscpy( pNew, pRoot );
  333. wcscat( pNew, WildCard );
  334. return( pNew );
  335. }
  336. /*****************************************************************************
  337. *
  338. * AddBackSlash
  339. *
  340. * Add the backslash character to path
  341. *
  342. * ENTRY:
  343. * Param1 (input/output)
  344. * Comments
  345. *
  346. * EXIT:
  347. * STATUS_SUCCESS - no error
  348. *
  349. ****************************************************************************/
  350. PWCHAR
  351. AddBackSlash(
  352. PWCHAR pRoot
  353. )
  354. {
  355. DWORD Count;
  356. PWCHAR pNew;
  357. PWCHAR BackSlash = L"\\";
  358. Count = wcslen( pRoot );
  359. pNew = LocalAlloc( LMEM_FIXED, (Count + wcslen(BackSlash) + 1)*sizeof(WCHAR) );
  360. if( pNew == NULL ) {
  361. return( NULL );
  362. }
  363. wcscpy( pNew, pRoot );
  364. // only add backslash if string doesn't already have it
  365. if(*(pRoot+Count-1) != L'\\')
  366. wcscat( pNew, BackSlash );
  367. return( pNew );
  368. }