Re: KERNEL: [1/2] fixed FindFirstFileExW; support for dosdevices (NUL, LPT[1-9], COM[1-9]...) (Edited)
Konstantin Petrov wrote:
(Patch Edited) There were the problem while I advert to dosdevices through WINE. I made the test (Windows vs Wine), which shows that in Windows there are available dosdevices-files (such as NUL, COM1, COM2,.., LPT1, ..), and in Wine aren't. The characteristic property of these files is that I can advert to them only directly. In other cases they are invisible.
patch for FinFrstFileExW
changelog file.c: fixed FindFirstFileExW for correct work with dosdevices. HI Konstantin,
a couple of comments on your patch
------------------------------------------------------------------------
Fix dosdevice finding (by argentum(a)etersoft.ru)
Index: dlls/kernel/file.c =================================================================== RCS file: /home/wine/wine/dlls/kernel/file.c,v retrieving revision 1.51 diff -u -p -u -r1.51 file.c --- dlls/kernel/file.c 3 Apr 2006 19:46:58 -0000 1.51 +++ dlls/kernel/file.c 5 Apr 2006 05:43:28 -0000 @@ -1552,7 +1553,9 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK io; NTSTATUS status; + ULONG dos_device;
+ TRACE("%s %d %p %d %p %lx\n", debugstr_w(filename), level, data, search_op, filter, flags);
if ((search_op != FindExSearchNameMatch && search_op != FindExSearchLimitToDirectories) @@ -1575,8 +1578,74 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR
if (!mask || !*mask) { - SetLastError( ERROR_FILE_NOT_FOUND ); - goto error; + if(!mask && (dos_device = RtlIsDosDeviceName_U( filename ))) + { + WIN32_FIND_DATAW *d = data; //create file's attribute structure + + + /*LOWORD(dos_device) - quantity of symbols in the DOS device name (NUL, LPT1,...) + filename + HIWORD(dos_device) - points to the Dos device name's beginning */ + if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info)))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + goto error; + } + + info->mask.Length = LOWORD(dos_device); /* in bytes, not in WCHAR; as USHORT Length */ + info->mask.MaximumLength = nt_name.Length + sizeof(WCHAR); + info->mask.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, info->mask.MaximumLength); + memcpy( info->mask.Buffer, filename + HIWORD(dos_device)/sizeof(WCHAR), info->mask.Length); + info->mask.Buffer[info->mask.Length/sizeof(WCHAR)] = 0; /* with '/' */ + + nt_name.Length = 4*sizeof(WCHAR) + HIWORD(dos_device); + nt_name.MaximumLength = nt_name.Length + sizeof(WCHAR); /* + '0' at the end */ + nt_name.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, nt_name.MaximumLength); + nt_name.Buffer[0] = '\\'; /* convert to NT' style path */ + nt_name.Buffer[1] = nt_name.Buffer[2] = '?'; + nt_name.Buffer[3] = '\\'; + memcpy( (void *)(nt_name.Buffer + 4), filename, HIWORD(dos_device)); + nt_name.Buffer[nt_name.Length/sizeof(WCHAR)] = 0; /* with '/' */ + + /* check if pftLastAccessTimeath is the root of the drive */ + info->is_root = FALSE; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &nt_name; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + /* check if nt_name is existing directory */ + status = NtOpenFile( &info->handle, GENERIC_READ, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); + + if (status != STATUS_SUCCESS) + { + RtlFreeUnicodeString( &info->mask ); + SetLastError( RtlNtStatusToDosError(status) ); + goto error; + } + + RtlInitializeCriticalSection( &info->cs ); + info->path = nt_name; + info->magic = FIND_FIRST_MAGIC; + info->data_pos = 0; + info->data_len = 0; + info->search_op = search_op; + + memset(d, 0, sizeof(*d)); + d->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE; + memcpy( d->cFileName, filename + HIWORD(dos_device)/sizeof(WCHAR), LOWORD(dos_device)); + + return (HANDLE)info; + } + else + { + SetLastError( ERROR_FILE_NOT_FOUND ); + goto error; + } }
most of the code here is rather close to the rest of the function, so you should try to factorize the two paths into a single one
if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info)))) @@ -1612,6 +1681,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
+ /* check if nt_name is existing directory */ status = NtOpenFile( &info->handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); @@ -1819,6 +1889,14 @@ HANDLE WINAPI FindFirstFileExA( LPCSTR l FILE_name_WtoA( dataW.cFileName, -1, dataA->cFileName, sizeof(dataA->cFileName) ); FILE_name_WtoA( dataW.cAlternateFileName, -1, dataA->cAlternateFileName, sizeof(dataA->cAlternateFileName) ); +/****************************************************** +* * +* In Windows fields dataA->dwReserved0 = 0x003D4830 * +* and dataA->dwReserved1 = 0x000000CC * +* But here these fields are not initialized and used * +* * +******************************************************/
there's no need for this comment, unless you document what those fields are in real windows
+ return handle; }
-- Eric Pouech
participants (1)
-
Eric Pouech