ntdll / kernel32: #47
Eric Pouech
pouech-eric at wanadoo.fr
Wed Feb 4 14:55:40 CST 2004
Moved directory browsing to ntdll
- Added NtQueryDirectoryFile
- Implemented FindFile{First|Next} on top of NtQueryDirectoryFile
-------------- next part --------------
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel46/file.c dlls/kernel/file.c
--- dlls/kernel46/file.c 2004-01-23 22:35:52.000000000 +0100
+++ dlls/kernel/file.c 2004-01-23 22:37:39.000000000 +0100
@@ -42,8 +42,12 @@
#include "wine/unicode.h"
#include "wine/debug.h"
+#include "wine/exception.h"
+#include "excpt.h"
#include "async.h"
+#include "../files/smb.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(file);
HANDLE dos_handles[DOS_TABLE_SIZE];
@@ -556,3 +560,395 @@
SetLastError(ERROR_UNABLE_TO_MOVE_REPLACEMENT);
return FALSE;
}
+
+/**************************************************************************
+ * Operations on file search *
+ **************************************************************************/
+
+/* Info structure for FindFirstFile handle */
+typedef struct
+{
+ CRITICAL_SECTION cs;
+ union
+ {
+ void* nt_data;
+ SMB_DIR* smb_dir;
+ } u;
+ BOOL is_smb;
+ PFILE_BOTH_DIR_INFORMATION dir_info;
+} FIND_FIRST_INFO;
+
+
+static WINE_EXCEPTION_FILTER(page_fault)
+{
+ if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
+ return EXCEPTION_EXECUTE_HANDLER;
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+/***********************************************************************
+ * DOSFS_FindNextEx
+ */
+static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAW *entry )
+{
+ /* FIXME UINT flags = DRIVE_GetFlags( info->drive ); */
+
+ while (info->dir_info)
+ {
+ /* FIXME: should we let the following code here, or shall we move it
+ * to ntdll
+ */
+#if 0
+ /* Don't return '.' and '..' in the root of the drive */
+ if (drive_root && (long_name[0] == '.') &&
+ (!long_name[1] || ((long_name[1] == '.') && !long_name[2])))
+ continue;
+#endif
+ /* We have a matching entry; fill the result and return */
+ entry->dwFileAttributes = info->dir_info->FileAttributes;
+ /* FIXME: take endianness into account */
+ memcpy(&entry->ftCreationTime , &info->dir_info->CreationTime, sizeof(FILETIME));
+ memcpy(&entry->ftLastAccessTime, &info->dir_info->LastAccessTime, sizeof(FILETIME));
+ memcpy(&entry->ftLastWriteTime , &info->dir_info->LastWriteTime, sizeof(FILETIME));
+ entry->nFileSizeHigh = (DWORD)(info->dir_info->EndOfFile.QuadPart >> 32);
+ entry->nFileSizeLow = (DWORD)(info->dir_info->EndOfFile.QuadPart & 0xffffffff);
+
+ memcpy(entry->cFileName, info->dir_info->FileName,
+ info->dir_info->FileNameLength);
+ entry->cFileName[info->dir_info->FileNameLength / sizeof(WCHAR)] = 0;
+ memcpy(entry->cAlternateFileName, info->dir_info->ShortName, info->dir_info->ShortNameLength + sizeof(WCHAR));
+ entry->cAlternateFileName[info->dir_info->ShortNameLength / sizeof(WCHAR)] = 0;
+
+ /* FIXME */
+ /* if (!(flags & DRIVE_CASE_PRESERVING)) strlwrW( entry->cFileName ); */
+ TRACE("returning %s (%s) %02lx %ld\n",
+ debugstr_w(entry->cFileName), debugstr_w(entry->cAlternateFileName),
+ entry->dwFileAttributes, entry->nFileSizeLow );
+ info->dir_info = (info->dir_info->NextEntryOffset) ?
+ (PFILE_BOTH_DIR_INFORMATION)((char*)info->dir_info +
+ info->dir_info->NextEntryOffset) : NULL;
+ return 1;
+ }
+ return 0; /* End of directory */
+}
+
+/*************************************************************************
+ * FindFirstFileExW (KERNEL32.@)
+ */
+HANDLE WINAPI FindFirstFileExW(
+ LPCWSTR lpFileName,
+ FINDEX_INFO_LEVELS fInfoLevelId,
+ LPVOID lpFindFileData,
+ FINDEX_SEARCH_OPS fSearchOp,
+ LPVOID lpSearchFilter,
+ DWORD dwAdditionalFlags)
+{
+ FIND_FIRST_INFO *info;
+
+ if (!lpFileName)
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if ((fSearchOp != FindExSearchNameMatch) || (dwAdditionalFlags != 0))
+ {
+ FIXME("options not implemented 0x%08x 0x%08lx\n", fSearchOp, dwAdditionalFlags );
+ return INVALID_HANDLE_VALUE;
+ }
+
+ switch (fInfoLevelId)
+ {
+ case FindExInfoStandard:
+ {
+ WIN32_FIND_DATAW * data = (WIN32_FIND_DATAW *) lpFindFileData;
+
+ data->dwReserved0 = data->dwReserved1 = 0x0;
+ if (lpFileName[0] == '\\' && lpFileName[1] == '\\')
+ {
+ ERR("UNC path name\n");
+ if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(FIND_FIRST_INFO)))) break;
+ info->u.smb_dir = SMB_FindFirst(lpFileName);
+ if(!info->u.smb_dir)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ break;
+ }
+ info->is_smb = TRUE;
+ RtlInitializeCriticalSection( &info->cs );
+ }
+ else
+ {
+ UNICODE_STRING uname, umask;
+ OBJECT_ATTRIBUTES oa;
+ HANDLE h;
+ IO_STATUS_BLOCK iosb;
+ LPCWSTR pw;
+ ULONG data_size;
+ WCHAR tmp[MAX_PATH], fn[MAX_PATH];
+
+ TRACE("[%s]\n", debugstr_w(lpFileName));
+ oa.Length = sizeof(oa);
+ oa.RootDirectory = NULL;
+ oa.ObjectName = &uname;
+ oa.Attributes = 0;
+ oa.SecurityDescriptor = NULL;
+ oa.SecurityQualityOfService = NULL;
+
+ if (lpFileName[0] && lpFileName[1] == ':')
+ {
+ /* FIXME: this cannot be tested unless we have a full path ? */
+ /* don't allow root directories */
+ if (!lpFileName[2] ||
+ ((lpFileName[2] == '/' || lpFileName[2] == '\\') && !lpFileName[3]))
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return INVALID_HANDLE_VALUE;
+ }
+ }
+ for (pw = lpFileName + strlenW(lpFileName) - 2; pw >= lpFileName; pw--)
+ if (*pw == '/' || *pw == '\\') break;
+ if (pw > lpFileName)
+ {
+ memcpy(tmp, lpFileName, (pw - lpFileName + 1) * sizeof(WCHAR));
+ tmp[pw - lpFileName + 1] = '\0';
+ strcpyW(fn, pw + 1);
+ }
+ else if (pw == lpFileName)
+ {
+ tmp[0] = '/'; tmp[1] = '\0';
+ strcpyW(fn, pw + 1);
+ }
+ else
+ {
+ tmp[0] = '.'; tmp[1] = '\0';
+ strcpyW(fn, lpFileName);
+ }
+ RtlInitUnicodeString(&uname, tmp);
+ switch (fn[strlenW(fn) - 1])
+ {
+ case '/':
+ case '\\':
+ fn[strlenW(fn) - 1] = '\0';
+ }
+ RtlInitUnicodeString(&umask, fn);
+ NtCreateFile(&h, GENERIC_READ /* | FILE_LIST_DIRECTORY */, &oa, &iosb,
+ NULL, 0, FILE_SHARE_READ, FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_ALERT|FILE_DIRECTORY_FILE|FILE_OPEN_FOR_BACKUP_INTENT,
+ NULL, 0);
+ if (iosb.u.Status)
+ {
+ SetLastError( RtlNtStatusToDosError(iosb.u.Status) );
+ break;
+ }
+ if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(FIND_FIRST_INFO))))
+ {
+ CloseHandle(h);
+ break;
+ }
+ RtlInitializeCriticalSection( &info->cs );
+
+ /* FIXME: don't do it that way: use a static buf, and if it's too small allocate a bigger one */
+ NtQueryDirectoryFile(h, NULL, NULL, NULL, &iosb,
+ NULL, 0, FileBothDirectoryInformation,
+ FALSE, &umask, TRUE);
+ if (iosb.u.Status != STATUS_BUFFER_TOO_SMALL)
+ {
+ CloseHandle(h);
+ SetLastError( RtlNtStatusToDosError(iosb.u.Status) );
+ break;
+ }
+ data_size = iosb.Information;
+ info->u.nt_data = HeapAlloc(GetProcessHeap(), 0, data_size);
+
+ NtQueryDirectoryFile(h, NULL, NULL, NULL, &iosb,
+ info->u.nt_data, data_size,
+ FileBothDirectoryInformation,
+ FALSE, &umask, TRUE);
+ CloseHandle(h);
+ if (iosb.u.Status)
+ {
+ SetLastError( RtlNtStatusToDosError(iosb.u.Status) );
+ break;
+ }
+ info->is_smb = FALSE;
+ info->dir_info = (PFILE_BOTH_DIR_INFORMATION)info->u.nt_data;
+ }
+ if (!FindNextFileW( (HANDLE) info, data ))
+ {
+ FindClose( (HANDLE) info );
+ SetLastError( ERROR_FILE_NOT_FOUND );
+ break;
+ }
+ return (HANDLE)info;
+ }
+ break;
+ default:
+ FIXME("fInfoLevelId 0x%08x not implemented\n", fInfoLevelId );
+ }
+ return INVALID_HANDLE_VALUE;
+}
+
+/*************************************************************************
+ * FindFirstFileA (KERNEL32.@)
+ */
+HANDLE WINAPI FindFirstFileA(
+ LPCSTR lpFileName,
+ WIN32_FIND_DATAA *lpFindData )
+{
+ return FindFirstFileExA(lpFileName, FindExInfoStandard, lpFindData,
+ FindExSearchNameMatch, NULL, 0);
+}
+
+/*************************************************************************
+ * FindFirstFileExA (KERNEL32.@)
+ */
+HANDLE WINAPI FindFirstFileExA(
+ LPCSTR lpFileName,
+ FINDEX_INFO_LEVELS fInfoLevelId,
+ LPVOID lpFindFileData,
+ FINDEX_SEARCH_OPS fSearchOp,
+ LPVOID lpSearchFilter,
+ DWORD dwAdditionalFlags)
+{
+ HANDLE handle;
+ WIN32_FIND_DATAA *dataA;
+ WIN32_FIND_DATAW dataW;
+ UNICODE_STRING pathW;
+
+ if (!lpFileName)
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!RtlCreateUnicodeStringFromAsciiz(&pathW, lpFileName))
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ handle = FindFirstFileExW(pathW.Buffer, fInfoLevelId, &dataW, fSearchOp, lpSearchFilter, dwAdditionalFlags);
+ RtlFreeUnicodeString(&pathW);
+ if (handle == INVALID_HANDLE_VALUE) return handle;
+
+ dataA = (WIN32_FIND_DATAA *) lpFindFileData;
+ dataA->dwFileAttributes = dataW.dwFileAttributes;
+ dataA->ftCreationTime = dataW.ftCreationTime;
+ dataA->ftLastAccessTime = dataW.ftLastAccessTime;
+ dataA->ftLastWriteTime = dataW.ftLastWriteTime;
+ dataA->nFileSizeHigh = dataW.nFileSizeHigh;
+ dataA->nFileSizeLow = dataW.nFileSizeLow;
+ WideCharToMultiByte( CP_ACP, 0, dataW.cFileName, -1,
+ dataA->cFileName, sizeof(dataA->cFileName), NULL, NULL );
+ WideCharToMultiByte( CP_ACP, 0, dataW.cAlternateFileName, -1,
+ dataA->cAlternateFileName, sizeof(dataA->cAlternateFileName), NULL, NULL );
+ return handle;
+}
+
+/*************************************************************************
+ * FindFirstFileW (KERNEL32.@)
+ */
+HANDLE WINAPI FindFirstFileW( LPCWSTR lpFileName, WIN32_FIND_DATAW *lpFindData )
+{
+ return FindFirstFileExW(lpFileName, FindExInfoStandard, lpFindData,
+ FindExSearchNameMatch, NULL, 0);
+}
+
+/*************************************************************************
+ * FindNextFileW (KERNEL32.@)
+ */
+BOOL WINAPI FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *data )
+{
+ FIND_FIRST_INFO *info;
+ BOOL ret = FALSE;
+ DWORD gle = ERROR_NO_MORE_FILES;
+
+ TRACE("(%p, %p)\n", handle, data);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return ret;
+ }
+ info = (FIND_FIRST_INFO*) handle;
+ RtlEnterCriticalSection( &info->cs );
+ if (info->is_smb)
+ {
+ ret = SMB_FindNext( info->u.smb_dir, data );
+ if(!ret)
+ {
+ SMB_CloseDir( info->u.smb_dir );
+ }
+ goto done;
+ }
+ else if (!info->u.nt_data)
+ {
+ goto done;
+ }
+ else if (!DOSFS_FindNextEx( info, data ))
+ {
+ HeapFree(GetProcessHeap(), 0, info->u.nt_data ); info->u.nt_data = NULL;
+ goto done;
+ }
+ TRACE("=> %s %s\n", debugstr_w(data->cFileName), debugstr_w(data->cAlternateFileName));
+ ret = TRUE;
+done:
+ RtlLeaveCriticalSection( &info->cs );
+ if( !ret ) SetLastError( gle );
+ return ret;
+}
+
+
+/*************************************************************************
+ * FindNextFileA (KERNEL32.@)
+ */
+BOOL WINAPI FindNextFileA( HANDLE handle, WIN32_FIND_DATAA *data )
+{
+ WIN32_FIND_DATAW dataW;
+ if (!FindNextFileW( handle, &dataW )) return FALSE;
+ data->dwFileAttributes = dataW.dwFileAttributes;
+ data->ftCreationTime = dataW.ftCreationTime;
+ data->ftLastAccessTime = dataW.ftLastAccessTime;
+ data->ftLastWriteTime = dataW.ftLastWriteTime;
+ data->nFileSizeHigh = dataW.nFileSizeHigh;
+ data->nFileSizeLow = dataW.nFileSizeLow;
+ WideCharToMultiByte( CP_ACP, 0, dataW.cFileName, -1,
+ data->cFileName, sizeof(data->cFileName), NULL, NULL );
+ WideCharToMultiByte( CP_ACP, 0, dataW.cAlternateFileName, -1,
+ data->cAlternateFileName,
+ sizeof(data->cAlternateFileName), NULL, NULL );
+ return TRUE;
+}
+
+/*************************************************************************
+ * FindClose (KERNEL32.@)
+ */
+BOOL WINAPI FindClose( HANDLE handle )
+{
+ FIND_FIRST_INFO *info = (FIND_FIRST_INFO*) handle;
+
+ if (handle == INVALID_HANDLE_VALUE) goto error;
+
+ __TRY
+ {
+ RtlEnterCriticalSection( &info->cs );
+ if (info && info->u.nt_data)
+ HeapFree(GetProcessHeap(), 0, info->u.nt_data );
+ }
+ __EXCEPT(page_fault)
+ {
+ WARN("Illegal handle %p\n", handle);
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+ __ENDTRY
+ if (!info) goto error;
+ RtlLeaveCriticalSection( &info->cs );
+ RtlDeleteCriticalSection( &info->cs );
+ HeapFree(GetProcessHeap(), 0, info);
+ return TRUE;
+
+ error:
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+}
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll46/dos_fs.c dlls/ntdll/dos_fs.c
--- dlls/ntdll46/dos_fs.c 2004-02-01 17:06:09.000000000 +0100
+++ dlls/ntdll/dos_fs.c 2004-02-01 17:06:21.000000000 +0100
@@ -60,6 +60,48 @@
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
/***********************************************************************
+ * get_show_dir_symlinks_option
+ */
+static BOOL get_show_dir_symlinks_option(void)
+{
+ static const WCHAR WineW[] = {'M','a','c','h','i','n','e','\\',
+ 'S','o','f','t','w','a','r','e','\\',
+ 'W','i','n','e','\\','W','i','n','e','\\',
+ 'C','o','n','f','i','g','\\','W','i','n','e',0};
+ static const WCHAR ShowDirSymlinksW[] = {'S','h','o','w','D','i','r','S','y','m','l','i','n','k','s',0};
+ static int show_dir_symlinks = -1;
+
+ if (show_dir_symlinks == -1)
+ {
+ char tmp[80];
+ HKEY hkey;
+ DWORD dummy;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &nameW, WineW );
+
+ if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ))
+ {
+ RtlInitUnicodeString( &nameW, ShowDirSymlinksW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ show_dir_symlinks = IS_OPTION_TRUE( str[0] );
+ }
+ NtClose( hkey );
+ }
+ }
+ return show_dir_symlinks;
+}
+
+/***********************************************************************
* DOSFS_ValidDOSName
*
* Return 1 if Unix file 'name' is also a valid MS-DOS name
@@ -202,6 +244,29 @@
}
/***********************************************************************
+ * DOSFS_ToDosDTAFormat
+ *
+ * Convert a file name from FCB to DTA format (name.ext, null-terminated)
+ * converting to upper-case in the process.
+ * File name can be terminated by '\0', '\\' or '/'.
+ * 'buffer' must be at least 13 characters long.
+ */
+static void DOSFS_ToDosDTAFormat(LPCWSTR name, LPWSTR dst)
+{
+ LPWSTR p;
+
+ memcpy(dst, name, 8 * sizeof(WCHAR));
+ p = dst + 8;
+ while ((p > dst) && (p[-1] == ' ')) p--;
+ *p++ = '.';
+ memcpy(p, name + 8, 3 * sizeof(WCHAR));
+ p += 3;
+ while (p[-1] == ' ') p--;
+ if (p[-1] == '.') p--;
+ *p = '\0';
+}
+
+/***********************************************************************
* DOSFS_Hash
*
* Transform a Unix file name into a hashed DOS name. If the name is a valid
@@ -841,3 +906,220 @@
}
return status == STATUS_SUCCESS;
}
+
+/******************************************************************
+ * match_filename
+ *
+ * Helper for NtQueryDirectoryFile
+ */
+static BOOL match_filename(LPCWSTR mask, LPCWSTR name, BOOL case_sensitive)
+{
+ LPCWSTR lastjoker = NULL;
+ LPCWSTR next_to_retry = NULL;
+ static const WCHAR asterisk_dot_asterisk[] = {'*','.','*',0};
+
+ TRACE("(%s, %s, %x)\n", debugstr_w(mask), debugstr_w(name), case_sensitive);
+
+ if (!strcmpW( mask, asterisk_dot_asterisk )) return TRUE;
+ while (*name && *mask)
+ {
+ if (*mask == '*')
+ {
+ while (*++mask == '*'); /* Skip consecutive '*' */
+ lastjoker = mask;
+ if (!*mask) return TRUE; /* end of mask is all '*', so match */
+
+ /* skip to the next match after the joker(s) */
+ if (case_sensitive) while (*name && (*name != *mask)) name++;
+ else while (*name && (toupperW(*name) != toupperW(*mask))) name++;
+
+ if (!*name) break;
+ next_to_retry = name;
+ }
+ else if (*mask == '?')
+ {
+ mask++;
+ name++;
+ }
+ else
+ {
+ int mismatch = 0;
+ if (case_sensitive)
+ {
+ if (*mask != *name) mismatch = 1;
+ }
+ else
+ {
+ if (toupperW(*mask) != toupperW(*name)) mismatch = 1;
+ }
+ if (!mismatch)
+ {
+ mask++;
+ name++;
+ if (*mask == '\0')
+ {
+ if (*name == '\0') return TRUE;
+ if (lastjoker) mask = lastjoker;
+ }
+ }
+ else /* mismatch ! */
+ {
+ if (lastjoker) /* we had an '*', so we can try unlimitedly */
+ {
+ mask = lastjoker;
+
+ /* this scan sequence was a mismatch, so restart
+ * 1 char after the first char we checked last time */
+ next_to_retry++;
+ name = next_to_retry;
+ }
+ else return FALSE; /* bad luck */
+ }
+ }
+ }
+ while ((*mask == '.') || (*mask == '*'))
+ mask++; /* Ignore trailing '.' or '*' in mask */
+ return (!*name && !*mask);
+}
+
+/******************************************************************************
+ * NtQueryDirectoryFile [NTDLL.@]
+ * ZwQueryDirectoryFile [NTDLL.@]
+ */
+NTSTATUS WINAPI NtQueryDirectoryFile(IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass,
+ IN BOOLEAN ReturnSingleEntry,
+ IN PUNICODE_STRING FileName OPTIONAL,
+ IN BOOLEAN RestartScan)
+{
+ TRACE("(%p %p %p %p %p %p 0x%08lx 0x%08x 0x%08x %s 0x%08x\n",
+ FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation,
+ Length, FileInformationClass, ReturnSingleEntry,
+ debugstr_us(FileName),RestartScan);
+
+ if (ReturnSingleEntry || !RestartScan || Event || ApcRoutine)
+ {
+ FIXME("Unsupported yet option\n");
+ return IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
+ }
+ if (FileName && FileName->Buffer[FileName->Length / sizeof(WCHAR)])
+ {
+ FIXME("Unterminated string: NIY\n");
+ return IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
+ }
+
+ IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
+ IoStatusBlock->Information = 0;
+
+ switch (FileInformationClass)
+ {
+ case FileBothDirectoryInformation:
+ {
+ int cd, fd, idx = 0, len;
+ LPCWSTR long_name, short_name;
+ DOS_DIR* dir;
+ PFILE_BOTH_DIR_INFORMATION lfi = NULL,
+ fi = (FILE_BOTH_DIR_INFORMATION*)FileInformation;
+ char name[MAX_PATH];
+ struct stat st;
+ WCHAR shortW[13];
+ BOOL is_link;
+
+ wine_server_handle_to_fd( FileHandle, GENERIC_READ, &fd, NULL, NULL );
+ if (fd == -1) return IoStatusBlock->u.Status = STATUS_INVALID_PARAMETER;
+
+ if ((IoStatusBlock->u.Status = DOSFS_OpenDir(fd, &dir)) != STATUS_SUCCESS)
+ {
+ WARN("Can't open dir\n");
+ wine_server_release_fd(FileHandle, fd);
+ return IoStatusBlock->u.Status;
+ }
+
+ /* FIXME: is there a better way to do lookup a directory content from its fd ??? */
+ if ((cd = open(".", O_RDONLY|O_DIRECTORY)) == -1 || fchdir(fd) == -1)
+ return IoStatusBlock->u.Status = FILE_GetNtStatus();
+
+ while ((IoStatusBlock->u.Status = DOSFS_ReadDir(dir, &long_name, &short_name)) == STATUS_SUCCESS)
+ {
+ if (short_name)
+ DOSFS_ToDosDTAFormat(short_name, shortW);
+ else
+ DOSFS_Hash(long_name, shortW, FALSE);
+ if (FileName && (!match_filename(FileName->Buffer, long_name, FALSE) &&
+ !match_filename(FileName->Buffer, shortW, FALSE)))
+ continue;
+
+ ntdll_wcstoumbs(0, long_name, strlenW(long_name) + 1,
+ name, sizeof(name), NULL, NULL);
+ /* this happens, for example, on broken symlinks */
+ if (lstat(name, &st) == -1) continue;
+ is_link = S_ISLNK(st.st_mode);
+ if (stat(name, &st) == -1) continue;
+ if (S_ISDIR(st.st_mode) && is_link && get_show_dir_symlinks_option())
+ continue;
+
+ len = strlenW(long_name) * sizeof(WCHAR);
+ if (Length >= IoStatusBlock->Information + sizeof(*fi) + len)
+ {
+ fi->NextEntryOffset = sizeof(*fi) + len;
+ fi->FileIndex = idx++;
+
+ RtlSecondsSince1970ToTime( st.st_mtime, &fi->CreationTime );
+ RtlSecondsSince1970ToTime( st.st_mtime, &fi->LastWriteTime );
+ RtlSecondsSince1970ToTime( st.st_atime, &fi->LastAccessTime );
+ RtlSecondsSince1970ToTime( st.st_ctime, &fi->ChangeTime );
+ if (S_ISDIR(st.st_mode))
+ {
+ fi->EndOfFile.QuadPart = fi->AllocationSize.QuadPart = 0;
+ fi->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
+ }
+ else
+ {
+ fi->EndOfFile.QuadPart = st.st_size;
+ fi->AllocationSize.QuadPart = st.st_blksize;
+ fi->AllocationSize.QuadPart *= st.st_blocks;
+ fi->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
+ }
+
+ if (!(st.st_mode & S_IWUSR))
+ fi->FileAttributes |= FILE_ATTRIBUTE_READONLY;
+
+ fi->EaSize = 0; /* FIXME */
+ strcpyW(fi->ShortName, shortW);
+ fi->ShortNameLength = strlenW(fi->ShortName) * sizeof(WCHAR);
+ memcpy(fi->FileName, long_name, len);
+ fi->FileNameLength = len;
+ lfi = fi;
+ fi = (PFILE_BOTH_DIR_INFORMATION)((char*)fi + fi->NextEntryOffset);
+ }
+ IoStatusBlock->Information += sizeof(*fi) + len;
+ }
+ if (IoStatusBlock->u.Status == STATUS_NO_MORE_ENTRIES)
+ {
+ if (Length < IoStatusBlock->Information)
+ IoStatusBlock->u.Status = STATUS_BUFFER_TOO_SMALL;
+ else
+ {
+ if (lfi) lfi->NextEntryOffset = 0;
+ IoStatusBlock->u.Status = STATUS_SUCCESS;
+ }
+ }
+ DOSFS_CloseDir(dir);
+ wine_server_release_fd(FileHandle, fd);
+ fchdir(cd); /* FIXME error handling */
+ close(cd);
+ }
+ TRACE("=> %lu (%ld)\n", IoStatusBlock->u.Status, IoStatusBlock->Information);
+ return IoStatusBlock->u.Status;
+ default:
+ break;
+ }
+
+ return IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
+}
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll46/file.c dlls/ntdll/file.c
--- dlls/ntdll46/file.c 2004-02-01 17:25:50.000000000 +0100
+++ dlls/ntdll/file.c 2004-02-01 18:25:38.000000000 +0100
@@ -1104,29 +1104,6 @@
return status;
}
-/******************************************************************************
- * NtQueryDirectoryFile [NTDLL.@]
- * ZwQueryDirectoryFile [NTDLL.@]
- */
-NTSTATUS WINAPI NtQueryDirectoryFile(
- IN HANDLE FileHandle,
- IN HANDLE Event OPTIONAL,
- IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
- IN PVOID ApcContext OPTIONAL,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- OUT PVOID FileInformation,
- IN ULONG Length,
- IN FILE_INFORMATION_CLASS FileInformationClass,
- IN BOOLEAN ReturnSingleEntry,
- IN PUNICODE_STRING FileName OPTIONAL,
- IN BOOLEAN RestartScan)
-{
- FIXME("(%p %p %p %p %p %p 0x%08lx 0x%08x 0x%08x %p 0x%08x\n",
- FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation,
- Length, FileInformationClass, ReturnSingleEntry,
- debugstr_us(FileName),RestartScan);
- return 0;
-}
/******************************************************************************
* NtQueryVolumeInformationFile [NTDLL.@]
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll46/path.c dlls/ntdll/path.c
--- dlls/ntdll46/path.c 2004-01-23 22:36:16.000000000 +0100
+++ dlls/ntdll/path.c 2004-01-23 22:38:04.000000000 +0100
@@ -469,7 +469,7 @@
reqsize += deplen + sizeof(WCHAR);
goto done;
}
-
+
memmove(buffer + reqsize / sizeof(WCHAR), name + dep, deplen + sizeof(WCHAR));
if (reqsize) memcpy(buffer, ins_str, reqsize);
reqsize += deplen;
diff -u -N -r -x '*~' -x '.#*' -x CVS files46/dos_fs.c files/dos_fs.c
--- files46/dos_fs.c 2004-01-23 22:36:21.000000000 +0100
+++ files/dos_fs.c 2004-01-23 22:38:38.000000000 +0100
@@ -105,30 +105,6 @@
WCHAR names[1];
} DOS_DIR;
-/* Info structure for FindFirstFile handle */
-typedef struct
-{
- char *path; /* unix path */
- LPWSTR long_mask;
- int drive;
- int cur_pos;
- CRITICAL_SECTION cs;
- union
- {
- DOS_DIR *dos_dir;
- SMB_DIR *smb_dir;
- } u;
-} FIND_FIRST_INFO;
-
-
-static WINE_EXCEPTION_FILTER(page_fault)
-{
- if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
- return EXCEPTION_EXECUTE_HANDLER;
- return EXCEPTION_CONTINUE_SEARCH;
-}
-
-
/***********************************************************************
* DOSFS_ValidDOSName
*
@@ -298,97 +274,6 @@
/***********************************************************************
- * DOSFS_MatchLong
- *
- * Check a long file name against a mask.
- *
- * Tests (done in W95 DOS shell - case insensitive):
- * *.txt test1.test.txt *
- * *st1* test1.txt *
- * *.t??????.t* test1.ta.tornado.txt *
- * *tornado* test1.ta.tornado.txt *
- * t*t test1.ta.tornado.txt *
- * ?est* test1.txt *
- * ?est??? test1.txt -
- * *test1.txt* test1.txt *
- * h?l?o*t.dat hellothisisatest.dat *
- */
-static int DOSFS_MatchLong( LPCWSTR mask, LPCWSTR name, int case_sensitive )
-{
- LPCWSTR lastjoker = NULL;
- LPCWSTR next_to_retry = NULL;
- static const WCHAR asterisk_dot_asterisk[] = {'*','.','*',0};
-
- TRACE("(%s, %s, %x)\n", debugstr_w(mask), debugstr_w(name), case_sensitive);
-
- if (!strcmpW( mask, asterisk_dot_asterisk )) return 1;
- while (*name && *mask)
- {
- if (*mask == '*')
- {
- mask++;
- while (*mask == '*') mask++; /* Skip consecutive '*' */
- lastjoker = mask;
- if (!*mask) return 1; /* end of mask is all '*', so match */
-
- /* skip to the next match after the joker(s) */
- if (case_sensitive) while (*name && (*name != *mask)) name++;
- else while (*name && (toupperW(*name) != toupperW(*mask))) name++;
-
- if (!*name) break;
- next_to_retry = name;
- }
- else if (*mask != '?')
- {
- int mismatch = 0;
- if (case_sensitive)
- {
- if (*mask != *name) mismatch = 1;
- }
- else
- {
- if (toupperW(*mask) != toupperW(*name)) mismatch = 1;
- }
- if (!mismatch)
- {
- mask++;
- name++;
- if (*mask == '\0')
- {
- if (*name == '\0')
- return 1;
- if (lastjoker)
- mask = lastjoker;
- }
- }
- else /* mismatch ! */
- {
- if (lastjoker) /* we had an '*', so we can try unlimitedly */
- {
- mask = lastjoker;
-
- /* this scan sequence was a mismatch, so restart
- * 1 char after the first char we checked last time */
- next_to_retry++;
- name = next_to_retry;
- }
- else
- return 0; /* bad luck */
- }
- }
- else /* '?' */
- {
- mask++;
- name++;
- }
- }
- while ((*mask == '.') || (*mask == '*'))
- mask++; /* Ignore trailing '.' or '*' in mask */
- return (!*name && !*mask);
-}
-
-
-/***********************************************************************
* DOSFS_AddDirEntry
*
* Used to construct an array of filenames in DOSFS_OpenDir
@@ -957,389 +842,6 @@
/***********************************************************************
- * get_show_dir_symlinks_option
- */
-static BOOL get_show_dir_symlinks_option(void)
-{
- static const WCHAR WineW[] = {'M','a','c','h','i','n','e','\\',
- 'S','o','f','t','w','a','r','e','\\',
- 'W','i','n','e','\\','W','i','n','e','\\',
- 'C','o','n','f','i','g','\\','W','i','n','e',0};
- static const WCHAR ShowDirSymlinksW[] = {'S','h','o','w','D','i','r','S','y','m','l','i','n','k','s',0};
-
- char tmp[80];
- HKEY hkey;
- DWORD dummy;
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING nameW;
- BOOL ret = FALSE;
-
- attr.Length = sizeof(attr);
- attr.RootDirectory = 0;
- attr.ObjectName = &nameW;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString( &nameW, WineW );
-
- if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ))
- {
- RtlInitUnicodeString( &nameW, ShowDirSymlinksW );
- if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
- {
- WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
- ret = IS_OPTION_TRUE( str[0] );
- }
- NtClose( hkey );
- }
- return ret;
-}
-
-
-/***********************************************************************
- * DOSFS_FindNextEx
- */
-static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAW *entry )
-{
- UINT flags = DRIVE_GetFlags( info->drive );
- char *p, buffer[MAX_PATHNAME_LEN];
- const char *drive_path;
- int drive_root;
- LPCWSTR long_name, short_name;
- BY_HANDLE_FILE_INFORMATION fileinfo;
- BOOL is_symlink;
-
- drive_path = info->path + strlen(DRIVE_GetRoot( info->drive ));
- while ((*drive_path == '/') || (*drive_path == '\\')) drive_path++;
- drive_root = !*drive_path;
-
- lstrcpynA( buffer, info->path, sizeof(buffer) - 1 );
- strcat( buffer, "/" );
- p = buffer + strlen(buffer);
-
- while (DOSFS_ReadDir( info->u.dos_dir, &long_name, &short_name ))
- {
- info->cur_pos++;
-
- /* Don't return '.' and '..' in the root of the drive */
- if (drive_root && (long_name[0] == '.') &&
- (!long_name[1] || ((long_name[1] == '.') && !long_name[2])))
- continue;
-
- /* Check the long mask */
-
- if (info->long_mask && *info->long_mask)
- {
- if (!DOSFS_MatchLong( info->long_mask, long_name,
- flags & DRIVE_CASE_SENSITIVE )) continue;
- }
-
- /* Check the file attributes */
- WideCharToMultiByte(CP_UNIXCP, 0, long_name, -1,
- p, sizeof(buffer) - (int)(p - buffer), NULL, NULL);
- if (!FILE_Stat( buffer, &fileinfo, &is_symlink ))
- {
- WARN("can't stat %s\n", buffer);
- continue;
- }
- if (is_symlink && (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
- {
- static int show_dir_symlinks = -1;
- if (show_dir_symlinks == -1)
- show_dir_symlinks = get_show_dir_symlinks_option();
- if (!show_dir_symlinks) continue;
- }
-
- /* We now have a matching entry; fill the result and return */
-
- entry->dwFileAttributes = fileinfo.dwFileAttributes;
- entry->ftCreationTime = fileinfo.ftCreationTime;
- entry->ftLastAccessTime = fileinfo.ftLastAccessTime;
- entry->ftLastWriteTime = fileinfo.ftLastWriteTime;
- entry->nFileSizeHigh = fileinfo.nFileSizeHigh;
- entry->nFileSizeLow = fileinfo.nFileSizeLow;
-
- if (short_name)
- DOSFS_ToDosDTAFormat( short_name, entry->cAlternateFileName );
- else
- DOSFS_Hash( long_name, entry->cAlternateFileName, FALSE,
- !(flags & DRIVE_CASE_SENSITIVE) );
-
- lstrcpynW( entry->cFileName, long_name, sizeof(entry->cFileName)/sizeof(entry->cFileName[0]) );
- if (!(flags & DRIVE_CASE_PRESERVING)) strlwrW( entry->cFileName );
- TRACE("returning %s (%s) %02lx %ld\n",
- debugstr_w(entry->cFileName), debugstr_w(entry->cAlternateFileName),
- entry->dwFileAttributes, entry->nFileSizeLow );
- return 1;
- }
- return 0; /* End of directory */
-}
-
-/*************************************************************************
- * FindFirstFileExW (KERNEL32.@)
- */
-HANDLE WINAPI FindFirstFileExW(
- LPCWSTR lpFileName,
- FINDEX_INFO_LEVELS fInfoLevelId,
- LPVOID lpFindFileData,
- FINDEX_SEARCH_OPS fSearchOp,
- LPVOID lpSearchFilter,
- DWORD dwAdditionalFlags)
-{
- FIND_FIRST_INFO *info;
-
- if (!lpFileName)
- {
- SetLastError(ERROR_PATH_NOT_FOUND);
- return INVALID_HANDLE_VALUE;
- }
-
- if ((fSearchOp != FindExSearchNameMatch) || (dwAdditionalFlags != 0))
- {
- FIXME("options not implemented 0x%08x 0x%08lx\n", fSearchOp, dwAdditionalFlags );
- return INVALID_HANDLE_VALUE;
- }
-
- switch(fInfoLevelId)
- {
- case FindExInfoStandard:
- {
- WIN32_FIND_DATAW * data = (WIN32_FIND_DATAW *) lpFindFileData;
- char *p;
- INT long_mask_len;
-
- data->dwReserved0 = data->dwReserved1 = 0x0;
- if (lpFileName[0] == '\\' && lpFileName[1] == '\\')
- {
- ERR("UNC path name\n");
- if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(FIND_FIRST_INFO)))) break;
- info->u.smb_dir = SMB_FindFirst(lpFileName);
- if(!info->u.smb_dir)
- {
- HeapFree(GetProcessHeap(), 0, info);
- break;
- }
- info->drive = -1;
- RtlInitializeCriticalSection( &info->cs );
- }
- else
- {
- DOS_FULL_NAME full_name;
-
- if (lpFileName[0] && lpFileName[1] == ':')
- {
- /* don't allow root directories */
- if (!lpFileName[2] ||
- ((lpFileName[2] == '/' || lpFileName[2] == '\\') && !lpFileName[3]))
- {
- SetLastError(ERROR_FILE_NOT_FOUND);
- return INVALID_HANDLE_VALUE;
- }
- }
- if (!DOSFS_GetFullName( lpFileName, FALSE, &full_name )) break;
- if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(FIND_FIRST_INFO)))) break;
- RtlInitializeCriticalSection( &info->cs );
- info->path = HeapAlloc( GetProcessHeap(), 0, strlen(full_name.long_name)+1 );
- strcpy( info->path, full_name.long_name );
-
- p = strrchr( info->path, '/' );
- *p++ = '\0';
- long_mask_len = MultiByteToWideChar(CP_UNIXCP, 0, p, -1, NULL, 0);
- info->long_mask = HeapAlloc( GetProcessHeap(), 0, long_mask_len * sizeof(WCHAR) );
- MultiByteToWideChar(CP_UNIXCP, 0, p, -1, info->long_mask, long_mask_len);
-
- info->drive = full_name.drive;
- info->cur_pos = 0;
-
- info->u.dos_dir = DOSFS_OpenDir( info->path );
- }
- if (!FindNextFileW( (HANDLE) info, data ))
- {
- FindClose( (HANDLE) info );
- SetLastError( ERROR_FILE_NOT_FOUND );
- break;
- }
- return (HANDLE) info;
- }
- break;
- default:
- FIXME("fInfoLevelId 0x%08x not implemented\n", fInfoLevelId );
- }
- return INVALID_HANDLE_VALUE;
-}
-
-/*************************************************************************
- * FindFirstFileA (KERNEL32.@)
- */
-HANDLE WINAPI FindFirstFileA(
- LPCSTR lpFileName,
- WIN32_FIND_DATAA *lpFindData )
-{
- return FindFirstFileExA(lpFileName, FindExInfoStandard, lpFindData,
- FindExSearchNameMatch, NULL, 0);
-}
-
-/*************************************************************************
- * FindFirstFileExA (KERNEL32.@)
- */
-HANDLE WINAPI FindFirstFileExA(
- LPCSTR lpFileName,
- FINDEX_INFO_LEVELS fInfoLevelId,
- LPVOID lpFindFileData,
- FINDEX_SEARCH_OPS fSearchOp,
- LPVOID lpSearchFilter,
- DWORD dwAdditionalFlags)
-{
- HANDLE handle;
- WIN32_FIND_DATAA *dataA;
- WIN32_FIND_DATAW dataW;
- UNICODE_STRING pathW;
-
- if (!lpFileName)
- {
- SetLastError(ERROR_PATH_NOT_FOUND);
- return INVALID_HANDLE_VALUE;
- }
-
- if (!RtlCreateUnicodeStringFromAsciiz(&pathW, lpFileName))
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return INVALID_HANDLE_VALUE;
- }
-
- handle = FindFirstFileExW(pathW.Buffer, fInfoLevelId, &dataW, fSearchOp, lpSearchFilter, dwAdditionalFlags);
- RtlFreeUnicodeString(&pathW);
- if (handle == INVALID_HANDLE_VALUE) return handle;
-
- dataA = (WIN32_FIND_DATAA *) lpFindFileData;
- dataA->dwFileAttributes = dataW.dwFileAttributes;
- dataA->ftCreationTime = dataW.ftCreationTime;
- dataA->ftLastAccessTime = dataW.ftLastAccessTime;
- dataA->ftLastWriteTime = dataW.ftLastWriteTime;
- dataA->nFileSizeHigh = dataW.nFileSizeHigh;
- dataA->nFileSizeLow = dataW.nFileSizeLow;
- WideCharToMultiByte( CP_ACP, 0, dataW.cFileName, -1,
- dataA->cFileName, sizeof(dataA->cFileName), NULL, NULL );
- WideCharToMultiByte( CP_ACP, 0, dataW.cAlternateFileName, -1,
- dataA->cAlternateFileName, sizeof(dataA->cAlternateFileName), NULL, NULL );
- return handle;
-}
-
-/*************************************************************************
- * FindFirstFileW (KERNEL32.@)
- */
-HANDLE WINAPI FindFirstFileW( LPCWSTR lpFileName, WIN32_FIND_DATAW *lpFindData )
-{
- return FindFirstFileExW(lpFileName, FindExInfoStandard, lpFindData,
- FindExSearchNameMatch, NULL, 0);
-}
-
-/*************************************************************************
- * FindNextFileW (KERNEL32.@)
- */
-BOOL WINAPI FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *data )
-{
- FIND_FIRST_INFO *info;
- BOOL ret = FALSE;
- DWORD gle = ERROR_NO_MORE_FILES;
-
- if (handle == INVALID_HANDLE_VALUE)
- {
- SetLastError( ERROR_INVALID_HANDLE );
- return ret;
- }
- info = (FIND_FIRST_INFO*) handle;
- RtlEnterCriticalSection( &info->cs );
- if (info->drive == -1)
- {
- ret = SMB_FindNext( info->u.smb_dir, data );
- if(!ret)
- {
- SMB_CloseDir( info->u.smb_dir );
- HeapFree( GetProcessHeap(), 0, info->path );
- }
- goto done;
- }
- else if (!info->path || !info->u.dos_dir)
- {
- goto done;
- }
- else if (!DOSFS_FindNextEx( info, data ))
- {
- DOSFS_CloseDir( info->u.dos_dir ); info->u.dos_dir = NULL;
- HeapFree( GetProcessHeap(), 0, info->path );
- info->path = NULL;
- HeapFree( GetProcessHeap(), 0, info->long_mask );
- info->long_mask = NULL;
- goto done;
- }
- ret = TRUE;
-done:
- RtlLeaveCriticalSection( &info->cs );
- if( !ret ) SetLastError( gle );
- return ret;
-}
-
-
-/*************************************************************************
- * FindNextFileA (KERNEL32.@)
- */
-BOOL WINAPI FindNextFileA( HANDLE handle, WIN32_FIND_DATAA *data )
-{
- WIN32_FIND_DATAW dataW;
- if (!FindNextFileW( handle, &dataW )) return FALSE;
- data->dwFileAttributes = dataW.dwFileAttributes;
- data->ftCreationTime = dataW.ftCreationTime;
- data->ftLastAccessTime = dataW.ftLastAccessTime;
- data->ftLastWriteTime = dataW.ftLastWriteTime;
- data->nFileSizeHigh = dataW.nFileSizeHigh;
- data->nFileSizeLow = dataW.nFileSizeLow;
- WideCharToMultiByte( CP_ACP, 0, dataW.cFileName, -1,
- data->cFileName, sizeof(data->cFileName), NULL, NULL );
- WideCharToMultiByte( CP_ACP, 0, dataW.cAlternateFileName, -1,
- data->cAlternateFileName,
- sizeof(data->cAlternateFileName), NULL, NULL );
- return TRUE;
-}
-
-/*************************************************************************
- * FindClose (KERNEL32.@)
- */
-BOOL WINAPI FindClose( HANDLE handle )
-{
- FIND_FIRST_INFO *info = (FIND_FIRST_INFO*) handle;
-
- if (handle == INVALID_HANDLE_VALUE) goto error;
-
- __TRY
- {
- RtlEnterCriticalSection( &info->cs );
- if (info)
- {
- if (info->u.dos_dir) DOSFS_CloseDir( info->u.dos_dir );
- if (info->path) HeapFree( GetProcessHeap(), 0, info->path );
- if (info->long_mask) HeapFree( GetProcessHeap(), 0, info->long_mask );
- }
- }
- __EXCEPT(page_fault)
- {
- WARN("Illegal handle %p\n", handle);
- SetLastError( ERROR_INVALID_HANDLE );
- return FALSE;
- }
- __ENDTRY
- if (!info) goto error;
- RtlLeaveCriticalSection( &info->cs );
- RtlDeleteCriticalSection( &info->cs );
- HeapFree(GetProcessHeap(), 0, info);
- return TRUE;
-
- error:
- SetLastError( ERROR_INVALID_HANDLE );
- return FALSE;
-}
-
-/***********************************************************************
* MulDiv (KERNEL32.@)
* RETURNS
* Result of multiplication and division
diff -u -N -r -x '*~' -x '.#*' -x CVS include46/winternl.h include/winternl.h
--- include46/winternl.h 2004-01-21 21:37:39.000000000 +0100
+++ include/winternl.h 2004-01-21 21:48:53.000000000 +0100
@@ -243,6 +243,54 @@
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+typedef struct _FILE_DIRECTORY_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ WCHAR FileName[0];
+} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
+
+typedef struct _FILE_FULL_DIRECTORY_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ WCHAR FileName[0];
+} FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION,
+ FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
+
+typedef struct _FILE_BOTH_DIRECTORY_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CHAR ShortNameLength;
+ WCHAR ShortName[12];
+ WCHAR FileName[0];
+} FILE_BOTH_DIRECTORY_INFORMATION, *PFILE_BOTH_DIRECTORY_INFORMATION,
+ FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
+
typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
@@ -1046,6 +1094,7 @@
NTSTATUS WINAPI NtPulseEvent(HANDLE,PULONG);
NTSTATUS WINAPI NtQueueApcThread(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR);
NTSTATUS WINAPI NtQueryDefaultLocale(BOOLEAN,LCID*);
+NTSTATUS WINAPI NtQueryDirectoryFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
NTSTATUS WINAPI NtQueryInformationFile(HANDLE,PIO_STATUS_BLOCK,PVOID,LONG,FILE_INFORMATION_CLASS);
NTSTATUS WINAPI NtQueryInformationProcess(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
NTSTATUS WINAPI NtQueryInformationThread(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
More information about the wine-patches
mailing list