/* * NTDLL directory functions * * Copyright 1993 Erik Bos * Copyright 2003 Eric Pouech * Copyright 1996, 2004 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include "wine/port.h" #include #include #ifdef HAVE_DIRENT_H # include #endif #include #include #include #include #include #include #include #ifdef HAVE_MNTENT_H #include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_SYSCALL_H # include #endif #ifdef HAVE_SYS_ATTR_H #include #endif #ifdef MAJOR_IN_MKDEV # include #elif defined(MAJOR_IN_SYSMACROS) # include #endif #ifdef HAVE_SYS_VNODE_H # ifdef HAVE_STDINT_H # include /* needed for kfreebsd */ # endif /* Work around a conflict with Solaris' system list defined in sys/list.h. */ #define list SYSLIST #define list_next SYSLIST_NEXT #define list_prev SYSLIST_PREV #define list_head SYSLIST_HEAD #define list_tail SYSLIST_TAIL #define list_move_tail SYSLIST_MOVE_TAIL #define list_remove SYSLIST_REMOVE #include #undef list #undef list_next #undef list_prev #undef list_head #undef list_tail #undef list_move_tail #undef list_remove #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_LINUX_IOCTL_H #include #endif #ifdef HAVE_LINUX_MAJOR_H # include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #include #ifdef HAVE_UNISTD_H # include #endif #include "ntstatus.h" #define WIN32_NO_STATUS #define NONAMELESSUNION #include "windef.h" #include "winnt.h" #include "winternl.h" #include "ddk/wdm.h" #include "ntdll_misc.h" #include "wine/server.h" #include "wine/list.h" #include "wine/debug.h" #include "wine/exception.h" #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1') #define IS_SEPARATOR(ch) ((ch) == '\\' || (ch) == '/') static BOOL show_dot_files; static RTL_CRITICAL_SECTION dir_section; static RTL_CRITICAL_SECTION_DEBUG critsect_debug = { 0, 0, &dir_section, { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 0, 0, { (DWORD_PTR)(__FILE__ ": dir_section") } }; static RTL_CRITICAL_SECTION dir_section = { &critsect_debug, -1, 0, 0, 0, 0 }; /*********************************************************************** * DIR_get_drives_info * * Retrieve device/inode number for all the drives. Helper for find_drive_root. */ unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ) { static struct drive_info cache[MAX_DOS_DRIVES]; static time_t last_update; static unsigned int nb_drives; unsigned int ret; time_t now = time(NULL); RtlEnterCriticalSection( &dir_section ); if (now != last_update) { char *buffer, *p; struct stat st; unsigned int i; if ((buffer = RtlAllocateHeap( GetProcessHeap(), 0, strlen(config_dir) + sizeof("/dosdevices/a:") ))) { strcpy( buffer, config_dir ); strcat( buffer, "/dosdevices/a:" ); p = buffer + strlen(buffer) - 2; for (i = nb_drives = 0; i < MAX_DOS_DRIVES; i++) { *p = 'a' + i; if (!stat( buffer, &st )) { cache[i].dev = st.st_dev; cache[i].ino = st.st_ino; nb_drives++; } else { cache[i].dev = 0; cache[i].ino = 0; } } RtlFreeHeap( GetProcessHeap(), 0, buffer ); } last_update = now; } memcpy( info, cache, sizeof(cache) ); ret = nb_drives; RtlLeaveCriticalSection( &dir_section ); return ret; } /*********************************************************************** * init_directories */ void init_directories(void) { static const WCHAR WineW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e',0}; static const WCHAR ShowDotFilesW[] = {'S','h','o','w','D','o','t','F','i','l','e','s',0}; char tmp[80]; HANDLE root, hkey; DWORD dummy; OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; RtlOpenCurrentUser( KEY_ALL_ACCESS, &root ); attr.Length = sizeof(attr); attr.RootDirectory = root; attr.ObjectName = &nameW; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; RtlInitUnicodeString( &nameW, WineW ); /* @@ Wine registry key: HKCU\Software\Wine */ if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) { RtlInitUnicodeString( &nameW, ShowDotFilesW ); if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy )) { WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data; show_dot_files = IS_OPTION_TRUE( str[0] ); } NtClose( hkey ); } NtClose( root ); unix_funcs->set_show_dot_files( show_dot_files ); } /****************************************************************************** * NtQueryDirectoryFile [NTDLL.@] * ZwQueryDirectoryFile [NTDLL.@] */ NTSTATUS WINAPI DECLSPEC_HOTPATCH NtQueryDirectoryFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc_routine, PVOID apc_context, PIO_STATUS_BLOCK io, PVOID buffer, ULONG length, FILE_INFORMATION_CLASS info_class, BOOLEAN single_entry, PUNICODE_STRING mask, BOOLEAN restart_scan ) { return unix_funcs->NtQueryDirectoryFile( handle, event, apc_routine, apc_context, io, buffer, length, info_class, single_entry, mask, restart_scan ); } /****************************************************************************** * wine_nt_to_unix_file_name (NTDLL.@) Not a Windows API * * Convert a file name from NT namespace to Unix namespace. * * If disposition is not FILE_OPEN or FILE_OVERWRITE, the last path * element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is * returned, but the unix name is still filled in properly. */ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret, UINT disposition, BOOLEAN check_case ) { return unix_funcs->nt_to_unix_file_name( nameW, unix_name_ret, disposition, check_case ); } /****************************************************************** * RtlWow64EnableFsRedirection (NTDLL.@) */ NTSTATUS WINAPI RtlWow64EnableFsRedirection( BOOLEAN enable ) { if (!is_wow64) return STATUS_NOT_IMPLEMENTED; ntdll_get_thread_data()->wow64_redir = enable; return STATUS_SUCCESS; } /****************************************************************** * RtlWow64EnableFsRedirectionEx (NTDLL.@) */ NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx( ULONG disable, ULONG *old_value ) { if (!is_wow64) return STATUS_NOT_IMPLEMENTED; __TRY { *old_value = !ntdll_get_thread_data()->wow64_redir; } __EXCEPT_PAGE_FAULT { return STATUS_ACCESS_VIOLATION; } __ENDTRY ntdll_get_thread_data()->wow64_redir = !disable; return STATUS_SUCCESS; } /****************************************************************** * RtlDoesFileExists_U (NTDLL.@) */ BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name) { UNICODE_STRING nt_name; FILE_BASIC_INFORMATION basic_info; OBJECT_ATTRIBUTES attr; BOOLEAN ret; if (!RtlDosPathNameToNtPathName_U( file_name, &nt_name, NULL, NULL )) return FALSE; attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &nt_name; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; ret = NtQueryAttributesFile(&attr, &basic_info) == STATUS_SUCCESS; RtlFreeUnicodeString( &nt_name ); return ret; }