KERNEL: [1/2] fixed FindFirstFileExW; support for dosdevices (NUL, LPT[1-9], COM[1-9]...) (Edited)

Eric Pouech eric.pouech at wanadoo.fr
Mon Apr 24 13:57:18 CDT 2006


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 at 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




More information about the wine-devel mailing list