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.

564 lines
16 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. pin.c
  5. Abstract:
  6. Author:
  7. Chuck Lenzmeier (chuckl)
  8. Revision History:
  9. --*/
  10. #define UNICODE
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <g:\nt\private\ntos\rdr2\csc\inc\cscapi.h>
  18. #if 1
  19. DWORD DebugLevel = 1;
  20. #define dprintf(_lvl_,_x_) if ((_lvl_) <= DebugLevel) printf _x_
  21. #define DEBUG(_x_) _x_
  22. #else
  23. #define dprintf(_lvl_,_x_)
  24. #define DEBUG(_x_)
  25. #endif
  26. typedef enum {
  27. OP_PIN = 1,
  28. OP_UNPIN,
  29. OP_DELETE,
  30. OP_QUERY,
  31. OP_READ,
  32. OP_QUERY_SPARSE,
  33. OP_QUERY_FULL,
  34. OP_QUERY_FREE,
  35. OP_QUERY_NOT_IN_DB,
  36. OP_QUERY_SYSTEM,
  37. OP_QUERY_NOT_SYSTEM
  38. } OPERATION;
  39. OPERATION Operation;
  40. BOOL Recurse = TRUE;
  41. BOOL TotalsOnly = FALSE;
  42. BOOL SkipSymbols = TRUE;
  43. BOOL SkipPagefile = TRUE;
  44. #define PAGE_SIZE 4096
  45. //
  46. // Common header for container entries (directories and keys).
  47. //
  48. typedef struct _CONTAINER_ENTRY {
  49. LIST_ENTRY SiblingListEntry;
  50. LIST_ENTRY ContainerList;
  51. struct _CONTAINER_ENTRY *Parent;
  52. } CONTAINER_ENTRY, *PCONTAINER_ENTRY;
  53. //
  54. // Macros for manipulating containers and objects.
  55. //
  56. #define InitializeContainer(_container,_parent) { \
  57. InitializeListHead(&(_container)->ContainerList); \
  58. (_container)->Parent = (PCONTAINER_ENTRY)(_parent); \
  59. }
  60. #define InsertContainer(_container,_subcontainer) { \
  61. dprintf( 3, ("inserting subcontainer %x on container %x, list head at %x = %x,%x\n",\
  62. _subcontainer, _container, &_container->ContainerList, \
  63. _container->ContainerList.Flink, _container->ContainerList.Blink) ); \
  64. InsertTailList(&(_container)->ContainerList,&(_subcontainer)->SiblingListEntry); \
  65. dprintf( 3, ("inserted subcontainer %x on container %x, list head at %x = %x,%x\n", \
  66. _subcontainer, _container, &_container->ContainerList, \
  67. _container->ContainerList.Flink, _container->ContainerList.Blink) ); \
  68. }
  69. #define RemoveContainer(_container) RemoveEntryList(&(_container)->SiblingListEntry)
  70. #define GetFirstContainer(_container) \
  71. ((_container)->ContainerList.Flink != &(_container)->ContainerList ? \
  72. CONTAINING_RECORD( (_container)->ContainerList.Flink, \
  73. CONTAINER_ENTRY, \
  74. SiblingListEntry ) : NULL)
  75. #define GetNextContainer(_container) \
  76. ((_container)->SiblingListEntry.Flink != &(_container)->Parent->ContainerList ? \
  77. CONTAINING_RECORD( (_container)->SiblingListEntry.Flink, \
  78. CONTAINER_ENTRY, \
  79. SiblingListEntry ) : NULL)
  80. #define GetParent(_container) (_container)->Parent
  81. //
  82. // Structures for entries in the watch tree.
  83. //
  84. typedef struct _DIRECTORY_ENTRY {
  85. CONTAINER_ENTRY ;
  86. WCHAR Name[1];
  87. } DIRECTORY_ENTRY, *PDIRECTORY_ENTRY;
  88. VOID
  89. OpenAndReadFile (
  90. PWCH File
  91. )
  92. {
  93. HANDLE fileHandle;
  94. DWORD fileSize;
  95. HANDLE mappingHandle;
  96. PUCHAR mappedBase;
  97. DWORD i;
  98. PUCHAR p;
  99. DWORD j;
  100. fileHandle = CreateFile(
  101. File,
  102. GENERIC_READ,
  103. 0,
  104. NULL,
  105. OPEN_EXISTING,
  106. 0,
  107. NULL
  108. );
  109. if ( fileHandle == INVALID_HANDLE_VALUE ) {
  110. printf( "Couldn't open %ws: %d\n", File, GetLastError() );
  111. return;
  112. }
  113. fileSize = SetFilePointer( fileHandle, 0, NULL, FILE_END );
  114. if ( fileSize == 0xFFFFFFFF ) {
  115. printf( "SetFilePointer(END) failed with %d\n", GetLastError() );
  116. } else if ( fileSize != 0 ) {
  117. mappingHandle = CreateFileMapping(
  118. fileHandle,
  119. NULL,
  120. PAGE_READONLY,
  121. 0,
  122. fileSize,
  123. NULL
  124. );
  125. if ( mappingHandle == NULL ) {
  126. printf( "Couldn't create mapping %ws: %d\n", File, GetLastError() );
  127. } else {
  128. mappedBase = MapViewOfFile( mappingHandle, FILE_MAP_READ, 0, 0, fileSize );
  129. if ( mappedBase == NULL ) {
  130. printf( "Couldn't map view %ws: %d\n", File, GetLastError() );
  131. } else {
  132. //printf( "OpenAndReadFile: fileSize = %x, mappedBase = %x\n", fileSize, mappedBase );
  133. j = 0;
  134. for ( i = 0, p = mappedBase;
  135. i < fileSize;
  136. i += PAGE_SIZE, p += PAGE_SIZE ) {
  137. j += *p;
  138. }
  139. UnmapViewOfFile( mappedBase );
  140. }
  141. }
  142. CloseHandle( mappingHandle );
  143. }
  144. CloseHandle( fileHandle );
  145. return;
  146. }
  147. DWORD
  148. OperateOnFile (
  149. PWCH Directory,
  150. PWCH File
  151. )
  152. {
  153. DWORD pathLength;
  154. DWORD status;
  155. DWORD pinCount;
  156. DWORD hintFlags;
  157. BOOL inDatabase;
  158. BOOL printThis;
  159. DWORD count = 0;
  160. pathLength = wcslen( Directory );
  161. if ( File != NULL ) {
  162. wcscat( Directory, L"\\" );
  163. wcscat( Directory, File );
  164. }
  165. inDatabase = CSCQueryFileStatusW( Directory, &status, &pinCount, &hintFlags );
  166. if ( Operation == OP_PIN ) {
  167. if ( !inDatabase || (pinCount == 0) ) {
  168. inDatabase = CSCPinFileW( Directory, hintFlags, &status, &pinCount, &hintFlags );
  169. if ( !TotalsOnly ) printf( "%ws : PINNED : pin count %d, hint flags %x, status %x\n", Directory, pinCount, hintFlags, status );
  170. count = 1;
  171. } else if ( (status & FLAG_CSC_COPY_STATUS_SPARSE) != 0 ) {
  172. printf( "%ws : SPARSE : pin count %d, hint flags %x, status %x\n", Directory, pinCount, hintFlags, status );
  173. }
  174. } else if ( Operation == OP_UNPIN ) {
  175. if ( inDatabase && (pinCount != 0) ) {
  176. inDatabase = CSCUnpinFileW( Directory, hintFlags, &status, &pinCount, &hintFlags );
  177. if ( !TotalsOnly ) printf( "%ws : UNPINNED : pin count %d, hintFlags %x, status %x\n", Directory, pinCount, hintFlags, status );
  178. count = 1;
  179. }
  180. } else if ( Operation == OP_DELETE ) {
  181. if ( inDatabase ) {
  182. inDatabase = CSCDeleteW( Directory );
  183. if ( inDatabase ) {
  184. if ( !TotalsOnly ) printf( "%ws : DELETED\n", Directory );
  185. } else {
  186. printf( "%ws : DELETE FAILED\n", Directory );
  187. }
  188. count = 1;
  189. }
  190. } else if ( Operation == OP_READ ) {
  191. if ( inDatabase &&
  192. ((hintFlags & FLAG_CSC_HINT_PIN_SYSTEM) != 0) &&
  193. ((status & FLAG_CSC_COPY_STATUS_SPARSE) != 0) ) {
  194. if ( !TotalsOnly ) printf( "%ws : READING\n", Directory );
  195. OpenAndReadFile( Directory );
  196. count = 1;
  197. }
  198. } else {
  199. if ( inDatabase ) {
  200. printThis = FALSE;
  201. if ( Operation == OP_QUERY ) {
  202. printThis = TRUE;
  203. } else {
  204. if ( (Operation == OP_QUERY_FREE) &&
  205. ((hintFlags & FLAG_CSC_HINT_PIN_SYSTEM) == 0) ) {
  206. printThis = TRUE;
  207. }
  208. if ( (Operation == OP_QUERY_SPARSE) &&
  209. ((status & FLAG_CSC_COPY_STATUS_SPARSE) != 0) ) {
  210. printThis = TRUE;
  211. }
  212. if ( (Operation == OP_QUERY_FULL) &&
  213. ((status & FLAG_CSC_COPY_STATUS_SPARSE) == 0) ) {
  214. printThis = TRUE;
  215. }
  216. if ( (Operation == OP_QUERY_SYSTEM) &&
  217. ((hintFlags & FLAG_CSC_HINT_PIN_SYSTEM) != 0) ) {
  218. printThis = TRUE;
  219. }
  220. if ( (Operation == OP_QUERY_NOT_SYSTEM) &&
  221. ((hintFlags & FLAG_CSC_HINT_PIN_SYSTEM) == 0) ) {
  222. printThis = TRUE;
  223. }
  224. }
  225. if ( printThis ) {
  226. if ( !TotalsOnly ) printf( "%ws : pin count %d, hint flags %x, status %x\n", Directory, pinCount, hintFlags, status );
  227. count = 1;
  228. }
  229. } else if ( (Operation == OP_QUERY) || (Operation == OP_QUERY_NOT_IN_DB) ) {
  230. if ( !TotalsOnly ) printf( "%ws : not in database\n", Directory );
  231. count = 1;
  232. }
  233. }
  234. Directory[pathLength] = 0;
  235. return count;
  236. }
  237. VOID
  238. WalkDirectory (
  239. IN PWCH Directory
  240. )
  241. /*++
  242. Routine Description:
  243. Arguments:
  244. Return Value:
  245. DWORD - Win32 status of the operation.
  246. --*/
  247. {
  248. DIRECTORY_ENTRY rootDirectory;
  249. PDIRECTORY_ENTRY currentDirectory;
  250. PDIRECTORY_ENTRY newDirectory;
  251. WIN32_FIND_DATA fileData;
  252. HANDLE findHandle;
  253. DWORD attributes;
  254. DWORD error;
  255. BOOL ok;
  256. WCHAR currentPath[MAX_PATH + 1];
  257. DWORD count = 0;
  258. //
  259. // Get the address of the root directory entry.
  260. //
  261. currentDirectory = &rootDirectory;
  262. InitializeContainer( currentDirectory, NULL );
  263. wcscpy( currentPath, Directory );
  264. if ( currentPath[wcslen(currentPath)-1] == '\\' ) {
  265. currentPath[wcslen(currentPath)-1] = 0;
  266. }
  267. attributes = GetFileAttributes( currentPath );
  268. if ( attributes == 0xffffffff ) {
  269. printf( "Error querying %ws: %d\n", currentPath, GetLastError() );
  270. return;
  271. }
  272. if ( (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
  273. //
  274. // The input name represents a file, not a directory. Process the file.
  275. //
  276. dprintf( 2, (" found file %ws\n", currentPath) );
  277. count += OperateOnFile( currentPath, NULL );
  278. } else {
  279. do {
  280. //
  281. // Look for files/directories in the current directory.
  282. //
  283. wcscat( currentPath, L"\\*" );
  284. dprintf( 2, ("FindFirst for %ws\n", currentPath) );
  285. findHandle = FindFirstFile( currentPath, &fileData );
  286. currentPath[wcslen(currentPath) - 2] = 0;
  287. if ( findHandle != INVALID_HANDLE_VALUE ) {
  288. do {
  289. if ( (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
  290. //
  291. // The entry returned is for a file. Process the file.
  292. //
  293. if ( !SkipPagefile || (_wcsicmp(fileData.cFileName,L"pagefile.sys") != 0) ) {
  294. dprintf( 2, (" found file %ws\\%ws\n", currentPath, fileData.cFileName) );
  295. count += OperateOnFile( currentPath, fileData.cFileName );
  296. }
  297. } else if (Recurse &&
  298. (wcscmp(fileData.cFileName,L".") != 0) &&
  299. (wcscmp(fileData.cFileName,L"..") != 0) &&
  300. (!SkipSymbols || (_wcsicmp(fileData.cFileName,L"symbols") != 0))) {
  301. //
  302. // The entry returned is for a directory. Add it to the tree.
  303. //
  304. dprintf( 2, (" found directory %ws\\%ws\n", currentPath, fileData.cFileName) );
  305. newDirectory = malloc( sizeof(DIRECTORY_ENTRY) - sizeof(WCHAR) +
  306. ((wcslen(fileData.cFileName) + 1) * sizeof(WCHAR)) );
  307. if ( newDirectory == NULL ) {
  308. FindClose( findHandle );
  309. printf( "Out of memory\n" );
  310. return;
  311. }
  312. InitializeContainer( newDirectory, currentDirectory );
  313. wcscpy( newDirectory->Name, fileData.cFileName );
  314. InsertContainer( currentDirectory, newDirectory );
  315. }
  316. //
  317. // Find another entry in the directory.
  318. //
  319. ok = FindNextFile( findHandle, &fileData );
  320. } while ( ok );
  321. //
  322. // All entries found. Close the find handle.
  323. //
  324. FindClose( findHandle );
  325. } // findHandle != INVALID_HANDLE_VALUE
  326. //
  327. // If the current directory has subdirectories, recurse into the
  328. // first one.
  329. //
  330. newDirectory = (PDIRECTORY_ENTRY)GetFirstContainer( currentDirectory );
  331. dprintf( 3, ("done with directory %ws; first child %ws\n", currentPath, newDirectory == NULL ? L"(none)" : newDirectory->Name ));
  332. if ( newDirectory != NULL ) {
  333. currentDirectory = newDirectory;
  334. wcscat( currentPath, L"\\" );
  335. wcscat( currentPath, currentDirectory->Name );
  336. } else {
  337. //
  338. // The directory has no subdirectories. Walk back up the
  339. // tree looking for a sibling directory to process.
  340. //
  341. while ( TRUE ) {
  342. //
  343. // If the current directory is the root directory, we're done.
  344. //
  345. if ( currentDirectory == &rootDirectory ) {
  346. currentDirectory = NULL;
  347. break;
  348. }
  349. //
  350. // Strip the name of the current directory off of the path.
  351. //
  352. *wcsrchr(currentPath, L'\\') = 0;
  353. //
  354. // If the parent directory has more subdirectories,
  355. // recurse into the next one. Otherwise, move up
  356. // to the parent directory and try again.
  357. //
  358. newDirectory = (PDIRECTORY_ENTRY)GetNextContainer( currentDirectory );
  359. if ( newDirectory != NULL ) {
  360. currentDirectory = newDirectory;
  361. wcscat( currentPath, L"\\" );
  362. wcscat( currentPath, currentDirectory->Name );
  363. break;
  364. } else {
  365. currentDirectory = (PDIRECTORY_ENTRY)GetParent( currentDirectory );
  366. }
  367. }
  368. }
  369. } while ( currentDirectory != NULL );
  370. }
  371. if ( count != 0 ) {
  372. printf( "%d files%s\n", count, TotalsOnly ? "" : " listed" );
  373. }
  374. return;
  375. } // WalkDirectory
  376. int
  377. __cdecl
  378. wmain (
  379. int argc,
  380. PWCH argv[]
  381. )
  382. {
  383. int c = --argc;
  384. PWCH *v = &argv[1];
  385. PWCH a;
  386. while ( c != 0 ) {
  387. a = *v;
  388. if ( *a != '-' ) {
  389. break;
  390. }
  391. a++;
  392. while ( *a != 0 ) {
  393. if ( tolower(*a) == 'd' ) {
  394. Recurse = FALSE;
  395. } else if ( tolower(*a) == 't' ) {
  396. TotalsOnly = TRUE;
  397. } else {
  398. goto usage;
  399. }
  400. a++;
  401. }
  402. c--;
  403. v++;
  404. }
  405. if ( c < 2 ) {
  406. goto usage;
  407. }
  408. if ( _wcsicmp(v[1],L"pin") == 0 ) {
  409. Operation = OP_PIN;
  410. } else if ( _wcsicmp(v[1],L"unpin") == 0 ) {
  411. Operation = OP_UNPIN;
  412. } else if ( _wcsicmp(v[1],L"delete") == 0 ) {
  413. Operation = OP_DELETE;
  414. } else if ( _wcsicmp(v[1],L"query") == 0 ) {
  415. Operation = OP_QUERY;
  416. } else if ( _wcsicmp(v[1],L"sparse") == 0 ) {
  417. Operation = OP_QUERY_SPARSE;
  418. } else if ( _wcsicmp(v[1],L"full") == 0 ) {
  419. Operation = OP_QUERY_FULL;
  420. } else if ( _wcsicmp(v[1],L"free") == 0 ) {
  421. Operation = OP_QUERY_FREE;
  422. } else if ( _wcsicmp(v[1],L"read") == 0 ) {
  423. Operation = OP_READ;
  424. } else if ( _wcsicmp(v[1],L"nid") == 0 ) {
  425. Operation = OP_QUERY_NOT_IN_DB;
  426. } else if ( _wcsicmp(v[1],L"sys") == 0 ) {
  427. Operation = OP_QUERY_SYSTEM;
  428. } else if ( _wcsicmp(v[1],L"nosys") == 0 ) {
  429. Operation = OP_QUERY_NOT_SYSTEM;
  430. } else {
  431. goto usage;
  432. }
  433. WalkDirectory( v[0] );
  434. return 0;
  435. usage:
  436. printf( "usage: %ws [-d] [-t] <directory> <pin|unpin|delete|query|sparse|full|free|read|nid|sys|nosys>\n", argv[0] );
  437. return 1;
  438. }