Discussion:
GetFileAttributesA fails for multibyte strings?!
(too old to reply)
Steve W.
2005-02-16 20:12:48 UTC
Permalink
I'm hoping that someone has seen this before - or has some idea of what I'm talking about...

I've come accross a situation in which I am walking the list items in the standard File Dialog's list control.
The filenames of each file is retrieved as a multibyte string, and then fed to ::GetFileAttributesA(full_path),
which is always returning INVALID_FILE_ATTRIBUTES for filenames that are actually in non-Western characters.

This algorithm works for any western based language. But when fed a multibyte string, both on my machine set to
have non-unicode programs run as Japanese software, and on our OEM's true Japanese boxes, ::GetFileAtttributes()
return INVALID_FILE_ATTRIBUTES (DWORD -1).

The entire 250,000+ line application isn't about to be turned into UNICODE any day soon.

I'm at a bit of a loss. I need to be able to determine the attributes of each file.

Changing our code so that calls ::GetFileAttributesW(widename) means that we suddenly must use Microsoft Layer for
Unicode support in order to run on pre 2000 boxes. This is... an unfortunate requirement. Also, what happens
under 98 where the filenames are not in UNICDE in the list control? They're actually in Ascii - yet the OS seems to
allow for Kanji based filenames.

Any thoughts? Ideas of what I might look into?

---

Related: Any ideas of where I could look to create my own custom File Open / Save As control / dialog? Subclassing
the common dialog from Microsoft is coming up against more and more of these "grey" areas that are giving me
sleepless nights. Does anyone know of a good example or library that shows exactly how to browse the filesystem
without the common dialogs? I would need to be able to browse everywhere, display icons, etc., much like the
standard dialog does. I'd just like to have complete access to all of the inner workings of such a dialog / interface.

Thanks for any advice you may have.
Severian
2005-02-17 01:04:18 UTC
Permalink
On Wed, 16 Feb 2005 15:12:48 -0500, "Steve W."
Post by Steve W.
I'm hoping that someone has seen this before - or has some idea of what I'm talking about...
I've come accross a situation in which I am walking the list items in the standard File Dialog's list control.
The filenames of each file is retrieved as a multibyte string, and then fed to ::GetFileAttributesA(full_path),
which is always returning INVALID_FILE_ATTRIBUTES for filenames that are actually in non-Western characters.
This algorithm works for any western based language. But when fed a multibyte string, both on my machine set to
have non-unicode programs run as Japanese software, and on our OEM's true Japanese boxes, ::GetFileAtttributes()
return INVALID_FILE_ATTRIBUTES (DWORD -1).
The entire 250,000+ line application isn't about to be turned into UNICODE any day soon.
I'm at a bit of a loss. I need to be able to determine the attributes of each file.
Changing our code so that calls ::GetFileAttributesW(widename) means that we suddenly must use Microsoft Layer for
Unicode support in order to run on pre 2000 boxes. This is... an unfortunate requirement. Also, what happens
under 98 where the filenames are not in UNICDE in the list control? They're actually in Ascii - yet the OS seems to
allow for Kanji based filenames.
Any thoughts? Ideas of what I might look into?
I've localized my non-Unicode application to Japanese, and haven't had
any problem with GetFileAttributes(). I usually retrieve my file names
using _findfirsti64(), etc.

As a test: if a file is selected and opened, does GetFileAttributes()
work properly? If so, that would indicate to me some kind of character
conversion problem reading from the File Dialog's list box. If you're
developing on 2000 or XP, the actual list box contents are in Unicode
and being converted into MBCS in your buffer. Have you verified that
the bytes returned actually contain the Kanji characters you expect?

Also be sure _MBCS is defined for all projects in your solution.
(VC7.1(2003): Project, Configuration Properties, General, Character
Set.) In VC6, ISTR that it required a specific /D_MBCS for each
project (and module).

I had some weird stuff when one of my library projects was not set
this way.
Post by Steve W.
Related: Any ideas of where I could look to create my own custom File Open / Save As control / dialog? Subclassing
the common dialog from Microsoft is coming up against more and more of these "grey" areas that are giving me
sleepless nights. Does anyone know of a good example or library that shows exactly how to browse the filesystem
without the common dialogs? I would need to be able to browse everywhere, display icons, etc., much like the
standard dialog does. I'd just like to have complete access to all of the inner workings of such a dialog / interface.
To make it look like MS, investigate the Shell functions SH... and the
IShell... interfaces. It is not a pretty sight, though.


--
Sev
Krish
2005-02-17 04:28:43 UTC
Permalink
Steve,

We have faced similar problem in our Internationalization project.
We have a component which is using MFC in static build, not compatible
with Unicode and also not compatible with MSLU for Win 9x based
systems.

The problem we have faced was, in Simplified Chinese ME, 98
operating systems, ::GetFileAtribute() failed to check the directory
name, which is in chinese. It will return 0xFFFFFFFF.

To resolve this problem, I have used CFile::GetStatus() static
function. There we faced one problem. CFile::GetStatus() worked fine
for Simplified ME and 98 OS, but failed in some cases.

So I used ::GetFileAttribute() and CFile::GetStatus() function to fix
the problem.

Here the code snippet.


CFileStatus cStatus;
if (GetFileAttributes(csPath) == 0xFFFFFFFF) // Check for availablity
{
// Check with CFile::GetStatus
if ( !(CFile::GetStatus (csPath,cStatus) && cStatus.m_attribute ==
0x10) )
{
// Create the directory
if (!CreateDirectory(csPath, NULL))
{
.......
}
}
}

I don't know whether this idea will fix your exact problem. However
This may be one input for you.

I really don't know the MFC implementation of CFile::GetStatus.

Thanks & Regards,

--
Gopal
Mihai N.
2005-02-17 06:15:20 UTC
Permalink
Post by Steve W.
This algorithm works for any western based language. But when fed a
multibyte string, both on my machine set to
have non-unicode programs run as Japanese software, and on our OEM's true
Japanese boxes, ::GetFileAtttributes()
return INVALID_FILE_ATTRIBUTES (DWORD -1).
Japanese file names on Japanese system (or W2K/XP with system default locales
set to Japanese) should work.
Can you isolate the code with the problem and write some small test case to
illustrate the problem?
This really should not happen, so it is most likely a mistake in the code.
--
Mihai Nita [Microsoft MVP, Windows - SDK]
------------------------------------------
Replace _year_ with _ to get the real email
Steve W.
2005-02-17 18:53:18 UTC
Permalink
Post by Mihai N.
Post by Steve W.
This algorithm works for any western based language. But when fed a
multibyte string, both on my machine set to
have non-unicode programs run as Japanese software, and on our OEM's true
Japanese boxes, ::GetFileAtttributes()
return INVALID_FILE_ATTRIBUTES (DWORD -1).
Japanese file names on Japanese system (or W2K/XP with system default locales
set to Japanese) should work.
Can you isolate the code with the problem and write some small test case to
illustrate the problem?
This really should not happen, so it is most likely a mistake in the code.
Update: The problem is not (at least in my case) ::GetFileAttributesA() - rather I had
implemented some code which extracts the filename of each item in the list view using an
undocumented associated item data with each item. This item data hack works for western languages,
but there seems to be some thing different about Asian languages - at least Japanese - where
the internal filename is not stored at the same offset as used by English or other western languages.

So, I was pulling in what was essentially a garbage filename and ::GetFileAttributesA() was
correct in returning -1.

Continuing Issues: The original reason that we felt that we had to resort to such a hack is due to the
fact that the common dialog interface appears to offer no way to know what the extension of a given item is
if the user has selected the option not to be shown extensions.

So - If anyone out there has a insightful response of how we might obtain the filename+extension for
each item currently displayed in the list view control on the common file dialog in a more
robust, "portable" fassion, I'm all ears.

Again - if there is example code somewhere that I could look at to see how to roll-my-own file dialog
then I'd be very indebteded to you.

Thanks all for the thoughtful responses so far...

Steve Wolf

Loading...