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.

363 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1988-1999 Microsoft Corporation
  3. Module Name:
  4. ffirst.c
  5. Abstract:
  6. Wrappers for file enumeration
  7. --*/
  8. #include "cmd.h"
  9. PHANDLE FFhandles = NULL;
  10. unsigned FFhndlsaved = 0;
  11. extern unsigned DosErr ;
  12. BOOLEAN FindFirstNt( PTCHAR, PWIN32_FIND_DATA, PHANDLE );
  13. BOOLEAN FindNextNt ( PWIN32_FIND_DATA, HANDLE );
  14. BOOLEAN FindFirst(
  15. BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
  16. PTCHAR fspec,
  17. ULONG attr,
  18. PWIN32_FIND_DATA pffBuf,
  19. PHANDLE phandle );
  20. BOOLEAN FindNext (
  21. BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
  22. PWIN32_FIND_DATA pffBuf,
  23. ULONG attr,
  24. HANDLE handle
  25. );
  26. BOOL IsDosAttribMatch( PWIN32_FIND_DATA, ULONG );
  27. BOOL IsNtAttribMatch( PWIN32_FIND_DATA, ULONG );
  28. int findclose( HANDLE );
  29. //
  30. // Under OS/2, we always return entries that are normal, archived or
  31. // read-only (god knows why).
  32. //
  33. // SRCHATTR contains those attribute bits that are used for matching.
  34. //
  35. #define SRCHATTR (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)
  36. /*** IsDosAttribMatch - Simulates the attribute matching from OS/2
  37. *
  38. * Purpose:
  39. * This function determines if the passed in find file buffer has a
  40. * match under the OS/2 find file rules.
  41. *
  42. * Args:
  43. * ffbuf: Buffer returned from FileFirst or Findnext
  44. * attr: Attributes to qualify search
  45. *
  46. * Returns:
  47. * TRUE: if buffer has a attribute match
  48. * FALSE: if not
  49. */
  50. BOOL
  51. IsDosAttribMatch(
  52. IN PWIN32_FIND_DATA pffBuf,
  53. IN ULONG attr
  54. ) {
  55. //
  56. // We emulate the OS/2 behaviour of attribute matching. The semantics
  57. // are evil, so I provide no explanation.
  58. //
  59. pffBuf->dwFileAttributes &= (0x000000FF & ~(FILE_ATTRIBUTE_NORMAL));
  60. if (! ((pffBuf->dwFileAttributes & SRCHATTR) & ~(attr))) {
  61. return TRUE;
  62. } else {
  63. return FALSE;
  64. }
  65. }
  66. BOOL
  67. IsNtAttribMatch(
  68. PWIN32_FIND_DATA pffBuf,
  69. ULONG attr
  70. ) {
  71. UNREFERENCED_PARAMETER( pffBuf );
  72. UNREFERENCED_PARAMETER( attr );
  73. //
  74. // for nt calls always return entry. selection should
  75. // should be based upon callers needs. This is primarily used
  76. // in DIR.
  77. return( TRUE );
  78. }
  79. /*** f_how_many - find how many files are there per fspec with given attr
  80. *
  81. * Args:
  82. * fspec: String pointer to file specification.
  83. * attr: Attributes to qualify search
  84. *
  85. * Returns:
  86. * number of files found or -1 if a file is a directory.
  87. */
  88. int
  89. f_how_many(
  90. PTCHAR fspec,
  91. ULONG attr
  92. ) {
  93. WIN32_FIND_DATA ffBuf;
  94. PWIN32_FIND_DATA pffBuf;
  95. PHANDLE phandle;
  96. HANDLE hnFirst ;
  97. unsigned rc;
  98. int cnt=0;
  99. pffBuf = &ffBuf;
  100. if ( ! ffirst (fspec, attr, pffBuf, &hnFirst )) {
  101. if ( ! ffirst (fspec, FILE_ATTRIBUTE_DIRECTORY, pffBuf, &hnFirst )) {
  102. return (0);
  103. }
  104. else {
  105. findclose(hnFirst);
  106. return (f_RET_DIR);
  107. }
  108. }
  109. do {
  110. cnt++;
  111. } while ( fnext (pffBuf, attr, hnFirst ));
  112. findclose(hnFirst) ;
  113. return (cnt);
  114. }
  115. /*** ffirst - find first file/directory and set up find handles
  116. *
  117. * Purpose:
  118. * This function opens a find first handle. I also returns the first
  119. * qualified file/directory. It simulates the DosFindFirst behavior.
  120. *
  121. * Args:
  122. * fspec: String pointer to file specification.
  123. * attr: Attributes to qualify search
  124. * ffbuf: Buffer to hold inforation on found file/directory
  125. * handle: Find first handle
  126. *
  127. * Returns:
  128. * TRUE: If match found
  129. * FALSE: if not
  130. * DosErr: Contains return code if FALSE function return
  131. */
  132. BOOLEAN
  133. FindFirst(
  134. IN BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
  135. IN PTCHAR fspec,
  136. IN ULONG attr,
  137. IN PWIN32_FIND_DATA pffBuf,
  138. OUT PHANDLE phandle
  139. ) {
  140. BOOLEAN rcode = FALSE;
  141. //
  142. // Loop through looking for a file that matching attributes
  143. //
  144. *phandle = FindFirstFile(fspec, pffBuf);
  145. while (*phandle != (HANDLE) -1) {
  146. if (fctAttribMatch(pffBuf, attr)) {
  147. DosErr = 0;
  148. rcode = TRUE;
  149. break;
  150. }
  151. if (!FindNextFile( *phandle, pffBuf )) {
  152. FindClose( *phandle );
  153. *phandle = (HANDLE)-1;
  154. break;
  155. }
  156. }
  157. //
  158. // If we did find a file (have a handle to prove it) then
  159. // setup a table of saved open find first handles. If we have
  160. // to clean up then these handle can all be closed.
  161. //
  162. if (*phandle != (HANDLE)-1) {
  163. //
  164. // Check if we already created the table. If we have not
  165. // then allocate space for table.
  166. //
  167. if (FFhandles == NULL) {
  168. FFhandles = (PHANDLE)HeapAlloc(GetProcessHeap(), 0, 5 * sizeof(PHANDLE));
  169. } else {
  170. //
  171. // Check if we have space to hold new handle entry
  172. //
  173. if (((FFhndlsaved + 1)* sizeof(PHANDLE)) > HeapSize(GetProcessHeap(), 0, FFhandles)) {
  174. FFhandles = (PHANDLE)HeapReAlloc(GetProcessHeap(), 0, (void*)FFhandles, (FFhndlsaved+1)*sizeof(PHANDLE));
  175. }
  176. }
  177. if (FFhandles != NULL) {
  178. FFhandles[FFhndlsaved++] = *phandle;
  179. }
  180. rcode = TRUE;
  181. }
  182. if (!rcode) {
  183. DosErr = GetLastError();
  184. }
  185. return(rcode);
  186. }
  187. BOOLEAN
  188. FindFirstNt(
  189. IN PTCHAR fspec,
  190. IN PWIN32_FIND_DATA pffBuf,
  191. OUT PHANDLE phandle
  192. )
  193. {
  194. return(FindFirst(IsNtAttribMatch, fspec, 0, pffBuf, phandle));
  195. }
  196. BOOLEAN
  197. ffirst(
  198. PTCHAR fspec,
  199. ULONG attr,
  200. PWIN32_FIND_DATA pffBuf,
  201. PHANDLE phandle
  202. )
  203. {
  204. return(FindFirst(IsDosAttribMatch, fspec, attr, pffBuf, phandle));
  205. }
  206. /*** fnext - find next file/directory
  207. *
  208. * Purpose:
  209. * This function search for the next qualified file or directory.
  210. * ffirst should have been called first and the returned file handle
  211. * should be passed into fnext.
  212. * Args:
  213. * handle: Find first handle
  214. * attr: Attributes to qualify search
  215. * ffbuf: Buffer to hold information on found file/directory
  216. *
  217. * Returns:
  218. * TRUE: If match found
  219. * FALSE: if not
  220. * DosErr: Contains return code if FALSE function return
  221. */
  222. BOOLEAN
  223. FindNextNt (
  224. IN PWIN32_FIND_DATA pffBuf,
  225. IN HANDLE handle
  226. ) {
  227. //
  228. // attributes are ignored for this kind of call
  229. //
  230. return( FindNext( IsNtAttribMatch, pffBuf, 0, handle) );
  231. }
  232. BOOLEAN
  233. fnext (
  234. IN PWIN32_FIND_DATA pffBuf,
  235. IN ULONG attr,
  236. IN HANDLE handle
  237. ) {
  238. return( FindNext( IsDosAttribMatch, pffBuf, attr, handle) );
  239. }
  240. BOOLEAN
  241. FindNext (
  242. IN BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
  243. IN PWIN32_FIND_DATA pffBuf,
  244. IN ULONG attr,
  245. IN HANDLE handle
  246. ) {
  247. //
  248. // Loop through looking for a file that matching attributes
  249. //
  250. while (FindNextFile( handle, pffBuf )) {
  251. if (fctAttribMatch( pffBuf, attr )) {
  252. DosErr = 0;
  253. return(TRUE);
  254. }
  255. }
  256. DosErr = GetLastError();
  257. return(FALSE);
  258. }
  259. int findclose(hn)
  260. HANDLE hn;
  261. {
  262. unsigned cnt;
  263. unsigned cnt2;
  264. DEBUG((CTGRP, COLVL, "findclose: handle %lx",hn)) ;
  265. // Locate handle in table
  266. //
  267. for (cnt = 0; (cnt < FFhndlsaved) && FFhandles[cnt] != hn ; cnt++ ) {
  268. ;
  269. }
  270. //
  271. // Remove handle from table
  272. //
  273. DEBUG((CTGRP, COLVL, "\t found handle in table at %d",cnt)) ;
  274. if (cnt < FFhndlsaved) {
  275. for (cnt2 = cnt; cnt2 < (FFhndlsaved - 1) ; cnt2++) {
  276. FFhandles[cnt2] = FFhandles[cnt2 + 1];
  277. }
  278. FFhndlsaved--;
  279. //
  280. // Shrink memory
  281. //
  282. if (HeapSize(GetProcessHeap(), 0, FFhandles) > 5*sizeof(PHANDLE)) {
  283. FFhandles = (PHANDLE)HeapReAlloc(GetProcessHeap(), 0, (void*)FFhandles,FFhndlsaved*sizeof(PHANDLE));
  284. }
  285. }
  286. //
  287. // Close even if we couldn't find it in table
  288. //
  289. DEBUG((CTGRP, COLVL, "\t closing handle %lx ",hn)) ;
  290. if (FindClose(hn)) /* Close even if we couldn't find it in table */
  291. return(0);
  292. else
  293. DEBUG((CTGRP, COLVL, "\t Error closing handle %lx ",hn)) ;
  294. return(GetLastError());
  295. }