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.

223 lines
5.3 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. findfile.c
  5. Abstract:
  6. This module implements IMFindFirst/IMFindNext
  7. Author:
  8. Revision History:
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #define IMIRROR_DIR_ENUM_BUFFER_SIZE 4096
  13. ULONG
  14. IMConvertNT2Win32Error(
  15. IN NTSTATUS Status
  16. )
  17. /*++
  18. Routine Description:
  19. This API sets the "last error value" and the "last error string"
  20. based on the value of Status. For status codes that don't have
  21. a corresponding error string, the string is set to null.
  22. Arguments:
  23. Status - Supplies the status value to store as the last error value.
  24. Return Value:
  25. The corresponding Win32 error code that was stored in the
  26. "last error value" thread variable.
  27. --*/
  28. {
  29. ULONG dwErrorCode;
  30. dwErrorCode = RtlNtStatusToDosError( Status );
  31. SetLastError( dwErrorCode );
  32. return( dwErrorCode );
  33. }
  34. DWORD
  35. IMFindNextFile(
  36. PIMIRROR_THREAD_CONTEXT ThreadContext,
  37. HANDLE DirHandle,
  38. PFILE_FULL_DIR_INFORMATION *lpFindFileData
  39. )
  40. /*++
  41. ThreadContext - instance data for this enumeration
  42. DirHandle - handle of directory to query.
  43. lpFindFileData - On a successful find, this parameter returns information
  44. about the located file.
  45. Return Value:
  46. TRUE - The operation was successful.
  47. FALSE/NULL - The operation failed. Extended error status is available
  48. using GetLastError.
  49. --*/
  50. {
  51. IO_STATUS_BLOCK IoStatusBlock;
  52. NTSTATUS Status;
  53. if (ThreadContext->FindBufferNext != NULL) {
  54. *lpFindFileData = (PFILE_FULL_DIR_INFORMATION) ThreadContext->FindBufferNext;
  55. if ((*lpFindFileData)->NextEntryOffset > 0) {
  56. ThreadContext->FindBufferNext =
  57. (PVOID)(((PCHAR)*lpFindFileData ) + (*lpFindFileData)->NextEntryOffset );
  58. } else {
  59. ThreadContext->FindBufferNext = NULL;
  60. }
  61. return ERROR_SUCCESS;
  62. }
  63. ThreadContext->FindBufferNext = NULL;
  64. Status = NtQueryDirectoryFile(
  65. DirHandle,
  66. NULL,
  67. NULL,
  68. NULL,
  69. &IoStatusBlock,
  70. ThreadContext->FindBufferBase,
  71. ThreadContext->FindBufferLength,
  72. FileFullDirectoryInformation,
  73. FALSE, // return multiple entries
  74. NULL,
  75. FALSE // not a rescan
  76. );
  77. if (NT_SUCCESS( Status )) {
  78. *lpFindFileData = (PFILE_FULL_DIR_INFORMATION) ThreadContext->FindBufferBase;
  79. if ((*lpFindFileData)->NextEntryOffset > 0) {
  80. ThreadContext->FindBufferNext =
  81. (PVOID)(((PCHAR) *lpFindFileData ) + (*lpFindFileData)->NextEntryOffset );
  82. }
  83. return STATUS_SUCCESS;
  84. }
  85. *lpFindFileData = NULL;
  86. if (Status == STATUS_NO_MORE_FILES ||
  87. Status == STATUS_NO_SUCH_FILE ||
  88. Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  89. return STATUS_SUCCESS;
  90. }
  91. return IMConvertNT2Win32Error( Status );
  92. }
  93. DWORD
  94. IMFindFirstFile(
  95. PIMIRROR_THREAD_CONTEXT ThreadContext,
  96. HANDLE DirHandle,
  97. PFILE_FULL_DIR_INFORMATION *lpFindFileData
  98. )
  99. /*++
  100. Routine Description:
  101. This returns all entries in a directory. This allocates a buffer if
  102. needed and sets up the variables in the ThreadContext to track the
  103. enumeration.
  104. Arguments:
  105. ThreadContext - instance data for this enumeration
  106. DirHandle - handle of directory to query.
  107. lpFindFileData - Supplies a pointer to a full dir info structure.
  108. This points into our buffer and should not be freed by the caller.
  109. No call is required to close this, but note that a thread context
  110. can only have a single enumeration going on at any time.
  111. Return Value:
  112. Win32 error. ERROR_SUCCESS is only successful case.
  113. --*/
  114. {
  115. IO_STATUS_BLOCK IoStatusBlock;
  116. NTSTATUS Status;
  117. UNICODE_STRING allFiles;
  118. if (ThreadContext->FindBufferBase == NULL) {
  119. ThreadContext->FindBufferBase = IMirrorAllocMem( IMIRROR_DIR_ENUM_BUFFER_SIZE );
  120. if (ThreadContext->FindBufferBase == NULL) {
  121. return IMConvertNT2Win32Error(STATUS_NO_MEMORY);
  122. }
  123. ThreadContext->FindBufferLength = IMIRROR_DIR_ENUM_BUFFER_SIZE;
  124. }
  125. RtlInitUnicodeString( &allFiles, L"*" );
  126. ThreadContext->FindBufferNext = NULL;
  127. Status = NtQueryDirectoryFile(
  128. DirHandle,
  129. NULL,
  130. NULL,
  131. NULL,
  132. &IoStatusBlock,
  133. ThreadContext->FindBufferBase,
  134. ThreadContext->FindBufferLength,
  135. FileFullDirectoryInformation,
  136. FALSE, // return multiple entries
  137. &allFiles,
  138. TRUE
  139. );
  140. if (NT_SUCCESS( Status )) {
  141. *lpFindFileData = (PFILE_FULL_DIR_INFORMATION) ThreadContext->FindBufferBase;
  142. if ((*lpFindFileData)->NextEntryOffset > 0) {
  143. ThreadContext->FindBufferNext =
  144. (PVOID)(((PCHAR) *lpFindFileData ) + (*lpFindFileData)->NextEntryOffset );
  145. }
  146. } else {
  147. *lpFindFileData = NULL;
  148. }
  149. return IMConvertNT2Win32Error( Status );
  150. }