Solved

Usage of FirstFileW

Posted on 2010-08-23
24
404 Views
Last Modified: 2012-05-10
Looks like this is a very basic query but pardon my ignorance. I have the following case where I find FindFirstFileW returning an invalid handle error

std::wstring fname;
fname = L"c:\be?a\*";

FindFirstFileW(fname.c_str(), ....);

I understand that this API supports wild characters but does it support wild chars in the middle?

0
Comment
Question by:trinitrotoluene
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
  • 3
  • +2
24 Comments
 
LVL 42

Expert Comment

by:sedgwick
ID: 33508319
you put '?' character in the middle of the fname which is illegal.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33508332
FindFirstFileW - uses wide chars.
0
 
LVL 12

Author Comment

by:trinitrotoluene
ID: 33508354
so the issue may not be the '?" in the middle??
0
Free Backup Tool for VMware and Hyper-V

Restore full virtual machine or individual guest files from 19 common file systems directly from the backup file. Schedule VM backups with PowerShell scripts. Set desired time, lean back and let the script to notify you via email upon completion.  

 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33508370
Nope - that should be ok.  (It is OK if you open a cmd window and perform a dir with a pattern containing a ? in the middle).
I'm not an expert on the stl but I think the c_str is the narrow char string, not the wchar that the 'W' version of the FindFirstFile is expecting
0
 
LVL 12

Author Comment

by:trinitrotoluene
ID: 33508375
Andy: i use c_str() to convert the wstring to an LPCWSTR
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 33508385
what is the error number returned?
use GetLastError(errNumberReturned) to get the error description
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33508391
OK, if the c_str does return wchars then taht bit isn't the problem



fname = L"c:\be?a\*";

should that not be:
fname = L"c:\\be?a\\*";
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33508677
Just done a quick console app:
this fails
int _tmain(int argc, _TCHAR* argv[])
{
    WIN32_FIND_DATAW x;
    HANDLE hFind = FindFirstFileW(L"c:\a?d*", &x);
if (hFind == INVALID_HANDLE_VALUE)
  {
    printf ("Invalid File Handle. GetLastError reports %d\n",
            GetLastError ());
    return (0);
  }
  else
  {
    printf ("The first file found is %s\n",
            x.cFileName);
    FindClose(hFind);
    return (1);
  }
}



but this works (note the double backslash)

int _tmain(int argc, _TCHAR* argv[])
{
    WIN32_FIND_DATAW x;
    HANDLE hFind = FindFirstFileW(L"c:\\a?d*", &x);
if (hFind == INVALID_HANDLE_VALUE)
  {
    printf ("Invalid File Handle. GetLastError reports %d\n",
            GetLastError ());
    return (0);
  }
  else
  {
    printf ("The first file found is %s\n",
            x.cFileName);
    FindClose(hFind);
    return (1);
  }
}


0
 
LVL 40

Expert Comment

by:evilrix
ID: 33508721
It could just be nothing matches the pattern "c:\be?a\*"

Have you checked this?

"If the function fails or fails to locate files from the search string in the lpFileName parameter, the return value is INVALID_HANDLE_VALUE"
http://msdn.microsoft.com/en-us/library/aa364418(VS.85).aspx
0
 
LVL 12

Author Comment

by:trinitrotoluene
ID: 33516680
folks thanks for the suggestions.

Will try it out and let you know. The file definitely exists so I guess its something to do with my searchstring
0
 
LVL 40

Expert Comment

by:evilrix
ID: 33516713
>> The file definitely exists so I guess its something to do with my searchstring

The file may exist but (as you elude) the glob pattern may not match it. A quick call to GetLastError() will confirm this (or not).
http://msdn.microsoft.com/en-us/library/ms679360(v=VS.85).aspx
0
 
LVL 12

Author Comment

by:trinitrotoluene
ID: 33518041
andy:

the // works but doesn't return the first file in the directory rather it returns the directory name.

for eg.
have a directory as c:\dir3 and try the below

HANDLE hFind = FindFirstFileW(L"c:\\d?r3*", &x);

you will get dir3 as the filename. Is this expected behaviour. I was expecting the first file in the directory?
0
 
LVL 33

Expert Comment

by:pgnatyuk
ID: 33518176
Why as a file name? The function return names of the files and subdirectories.
http://msdn.microsoft.com/en-us/library/aa364418(VS.85).aspx

When you have the name you can check with GetFileAttributes if this is a directory: FILE_ATTRIBUTE_DIRECTORY.

Here is an example with FindFirstFile and GetFileAttribute:
http://msdn.microsoft.com/en-us/library/aa365522(v=VS.85).aspx
 
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33518273
OK, I've done a further change

int _tmain(int argc, _TCHAR* argv[])
{
    std::wstring s = L"c:\\a?t*";
  WIN32_FIND_DATAW x;
   HANDLE hFind = FindFirstFileW(s.c_str(), &x);
if (hFind == INVALID_HANDLE_VALUE)
  {
   wprintf (L"Invalid File Handle. GetLastError reports %d\n",
            GetLastError ());
   return (0);
 }
  else
  {
   wprintf (L"The first file found is %s\n",
            x.cFileName);
   FindClose(hFind);
   return (1);
 }    return 0;
}

There are no directories and only one file that matches the pattern - the file is found and the name printed out to the console.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33518301
Just one 'minor' point.  I hope you are looping through ALL the files returned to check, they are NOT sorted the way they are with a dir command.
0
 
LVL 12

Author Comment

by:trinitrotoluene
ID: 33518405
AndyA

I understand what you are trying to tell me. Its not an issue with string conversions. I guess i didn't explain my scenario properly

I have the following directory structure

C:\Dir3
  In Dir3 I could be having several files/folders

I get a string pattern from another module  "C:\Di?3*" and I am expected to find the C:\Dir3 and also list out all the files and folders inside Dir3.
What happens is that FindFirstFileW(L"C:\Di?3*", ...) returns Dir3 and not the files/folders within C:\Dir3.

Now doing a FindNextFileW() is inconsequential and it just bumps out.

I hope you understand the situation now. All I want you folks to confirm is that the Win API is working correctly and I might need to add special logic of my own to handle this weird case
0
 
LVL 33

Expert Comment

by:pgnatyuk
ID: 33518442
From my point of view Win32 API works properly. Actually, it does not matter - I need my app to work properly. For your case, I think, it should be L"C:\Di?3*\*.*".
0
 
LVL 12

Author Comment

by:trinitrotoluene
ID: 33518475
pgnatyuk: thats not the expression I get from the other module. I cannot assume its a directory and add \*.* at the end.

all I get from the other module is C:\Di?r* or maybe C:\D?or or maybe C:\Dir* and I am supposed to handle all the cases
0
 
LVL 44

Accepted Solution

by:
AndyAinscow earned 500 total points
ID: 33518478
Now I understand.
You need to find the directory.  THEN you do a new FindFile using the directory as th base search string eg.
FindFileW(L"C:\\Dir3\*.*"...
Also you need to do that for each directory - recursive function
0
 
LVL 33

Expert Comment

by:pgnatyuk
ID: 33519247
>>pgnatyuk: thats not the expression I get from the other module. I cannot assume its a directory and add \*.* at the end.

You don't need to assume. You may check the names you get from the FindFirstFile are directories or files with GetFileAttribute.

Maybe you can formulate the task?
Seems like you already understand FindFirstFile function.
0
 
LVL 12

Author Comment

by:trinitrotoluene
ID: 33528145
Thats right Andy!

What happens is that FindFirstFileW(L"C:\Di?3*", ...) returns Dir3 and not the file/folders within C:\Dir3 as would have been the case if i had used FindFirstFileW(L"C:\\Dir3", ...) so in this case I would have had to determine  whether its a file/directory and then proceed further
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33528423
From the help files - Retrieving and  Changing File Attributes


#include <windows.h>
#include <stdio.h>

void main()
{
   WIN32_FIND_DATA FileData; 
   HANDLE hSearch; 
   DWORD dwAttrs;   
   TCHAR szDirPath[] = TEXT("c:\\TextRO\\"); 
   TCHAR szNewPath[MAX_PATH];   
 
   BOOL fFinished = FALSE; 
 
// Create a new directory. 
 
   if (!CreateDirectory(szDirPath, NULL)) 
   { 
      printf("Could not create new directory.\n"); 
      return;
   } 
 
// Start searching for text files in the current directory. 
 
   hSearch = FindFirstFile(TEXT("*.txt"), &FileData); 
   if (hSearch == INVALID_HANDLE_VALUE) 
   { 
      printf("No text files found.\n"); 
      return;
   } 
 
// Copy each .TXT file to the new directory 
// and change it to read only, if not already. 
 
   while (!fFinished) 
   { 
      lstrcpy(szNewPath, szDirPath); 
      lstrcat(szNewPath, FileData.cFileName); 
      if (CopyFile(FileData.cFileName, szNewPath, FALSE))
      { 
         dwAttrs = GetFileAttributes(FileData.cFileName); 
         if (dwAttrs==INVALID_FILE_ATTRIBUTES) return; 

         if (!(dwAttrs & FILE_ATTRIBUTE_READONLY)) 
         { 
            SetFileAttributes(szNewPath, 
                dwAttrs | FILE_ATTRIBUTE_READONLY); 
         } 
      } 
      else 
      { 
         printf("Could not copy file.\n"); 
         return;
      } 
 
      if (!FindNextFile(hSearch, &FileData)) 
      {
         if (GetLastError() == ERROR_NO_MORE_FILES) 
         { 
            printf("Copied all text files.\n"); 
            fFinished = TRUE; 
         } 
         else 
         { 
            printf("Could not find next file.\n"); 
            return;
         } 
      }
   } 
 
// Close the search handle. 
 
   FindClose(hSearch);
}

Open in new window

0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 33528426
One of the possible attributes is: FILE_ATTRIBUTE_DIRECTORY


0
 
LVL 12

Author Closing Comment

by:trinitrotoluene
ID: 33643183
Helped in stimulating my grey cells. Sorry about the long delay. Got mired in work
0

Featured Post

More Than Just A Video Library

Train for your certification. Learn the latest DevOps tools. Grow your skillset to do better work.

At Linux Academy, we release new training modules every week so you'll always be up to date on the latest tech.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

627 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question