Discussion:
StringCchPrintf is broken
(too old to reply)
Norman Diamond
2006-10-20 05:01:19 UTC
Permalink
StringCchPrintf is broken, verified with the debugger in Visual Studio 2005
on Windows XP Pro, target running on a Windows Mobile 5 Pocket PC.

All machines, Windows versions, and Visual Studio 2005 are the same language
version, Japanese. The Windows Mobile 5 Pocket PC SDK is US-English.

char devnm[50]; // ANSI because gethostname doesn't handle Unicode
char *mdlnm = "Pocket PC"; // ANSI for no reason at the moment
gethostname(devnm, sizeof devnm);
#ifdef _UNICODE
StringCchPrintf(szTraceInfo, ARRAYSIZE(szTraceInfo),
_T("device type \"%S\", hostname \"%S\""), mdlnm, devnm);
#else
StringCchPrintf(szTraceInfo, ARRAYSIZE(szTraceInfo),
_T("device type \"%s\", hostname \"%s\""), mdlnm, devnm);
#endif
// breakpoint on the next line of code
...

The Unicode version of StringCchPrintf was executed, as expected in
Windows CE.

mdlnm was a constant this time as shown:
Pocket PC

devnm was an ANSI string 15 bytes long including the NUL terminator:
ソフト開発iPaq

The result:
device type "Pocket PC", hostname ""

StringCchPrintf really can't handle conversion between ANSI and Unicode, so
maybe that's why MSDN doesn't say it can. (Except that StringCchPrintf
managed to handle one conversion, where a string only used a small subset of
all the characters that exist in the default and current code page.)
Norman Diamond
2006-10-20 05:21:11 UTC
Permalink
I forgot to mention:
_TCHAR szTraceInfo[200];
It's long enough.
Post by Norman Diamond
StringCchPrintf is broken, verified with the debugger in Visual Studio
2005 on Windows XP Pro, target running on a Windows Mobile 5 Pocket PC.
All machines, Windows versions, and Visual Studio 2005 are the same
language version, Japanese. The Windows Mobile 5 Pocket PC SDK is
US-English.
char devnm[50]; // ANSI because gethostname doesn't handle Unicode
char *mdlnm = "Pocket PC"; // ANSI for no reason at the moment
gethostname(devnm, sizeof devnm);
#ifdef _UNICODE
StringCchPrintf(szTraceInfo, ARRAYSIZE(szTraceInfo),
_T("device type \"%S\", hostname \"%S\""), mdlnm, devnm);
#else
StringCchPrintf(szTraceInfo, ARRAYSIZE(szTraceInfo),
_T("device type \"%s\", hostname \"%s\""), mdlnm, devnm);
#endif
// breakpoint on the next line of code
...
The Unicode version of StringCchPrintf was executed, as expected in
Windows CE.
Pocket PC
ソフト開発iPaq
device type "Pocket PC", hostname ""
StringCchPrintf really can't handle conversion between ANSI and Unicode,
so maybe that's why MSDN doesn't say it can. (Except that StringCchPrintf
managed to handle one conversion, where a string only used a small subset
of all the characters that exist in the default and current code page.)
unknown
2006-10-22 22:14:05 UTC
Permalink
Yes, UNICODE is defined, and must be, when building WinCE applications.

That doesn't mean StringCchPrintf is broken. There are two functions, and
StringCchPrintf is not one of them. Since UNICODE is defined,
StringCchPrintf resolves to StringCchPrintfW. The ASCII version, which you
have to use explicitly for char type, is StringCchPrintfA. See safestr.h
for more info.
--
Michael Salamone [eMVP]
Entrek Software, Inc.
www.entrek.com
Post by Norman Diamond
_TCHAR szTraceInfo[200];
It's long enough.
Post by Norman Diamond
StringCchPrintf is broken, verified with the debugger in Visual Studio
2005 on Windows XP Pro, target running on a Windows Mobile 5 Pocket PC.
All machines, Windows versions, and Visual Studio 2005 are the same
language version, Japanese. The Windows Mobile 5 Pocket PC SDK is
US-English.
char devnm[50]; // ANSI because gethostname doesn't handle Unicode
char *mdlnm = "Pocket PC"; // ANSI for no reason at the moment
gethostname(devnm, sizeof devnm);
#ifdef _UNICODE
StringCchPrintf(szTraceInfo, ARRAYSIZE(szTraceInfo),
_T("device type \"%S\", hostname \"%S\""), mdlnm, devnm);
#else
StringCchPrintf(szTraceInfo, ARRAYSIZE(szTraceInfo),
_T("device type \"%s\", hostname \"%s\""), mdlnm, devnm);
#endif
// breakpoint on the next line of code
...
The Unicode version of StringCchPrintf was executed, as expected in
Windows CE.
Pocket PC
ソフト開発iPaq
device type "Pocket PC", hostname ""
StringCchPrintf really can't handle conversion between ANSI and Unicode,
so maybe that's why MSDN doesn't say it can. (Except that
StringCchPrintf
managed to handle one conversion, where a string only used a small subset
of all the characters that exist in the default and current code page.)
Tim Roberts
2006-10-24 05:37:05 UTC
Permalink
Post by unknown
Yes, UNICODE is defined, and must be, when building WinCE applications.
That doesn't mean StringCchPrintf is broken. There are two functions, and
StringCchPrintf is not one of them. Since UNICODE is defined,
StringCchPrintf resolves to StringCchPrintfW. The ASCII version, which you
have to use explicitly for char type, is StringCchPrintfA. See safestr.h
for more info.
Although your assessment is fundamentally correct, it doesn't have anything
to do with his complaint. His complaint was that the %S (uppercase)
descriptor to StringCchPrintfW, which should accept a multibyte string,
does not work if there are true multibyte characters in the string. Only
single-byte ASCII works.

Windows CE doesn't have StringCchPrintfA.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
unknown
2006-10-24 12:58:49 UTC
Permalink
Maybe not - the problem wasn't well-stated (though the source is the doc,
right - so not making excuses here!).

But still, it is a solution. I've not called StringCchPrintfA - but I do
see that it is exported from COREDLL. It is guarded (as most things are) by
a SYSGEN tag, so it may or may not be available in your config.
--
Michael Salamone [eMVP]
Entrek Software, Inc.
www.entrek.com
Post by Tim Roberts
Post by unknown
Yes, UNICODE is defined, and must be, when building WinCE applications.
That doesn't mean StringCchPrintf is broken. There are two functions, and
StringCchPrintf is not one of them. Since UNICODE is defined,
StringCchPrintf resolves to StringCchPrintfW. The ASCII version, which you
have to use explicitly for char type, is StringCchPrintfA. See safestr.h
for more info.
Although your assessment is fundamentally correct, it doesn't have anything
to do with his complaint. His complaint was that the %S (uppercase)
descriptor to StringCchPrintfW, which should accept a multibyte string,
does not work if there are true multibyte characters in the string. Only
single-byte ASCII works.
Windows CE doesn't have StringCchPrintfA.
--
Providenza & Boekelheide, Inc.
Norman Diamond
2006-11-06 01:19:55 UTC
Permalink
I think the problem was stated well enough. Although I wrote code to
contend with either Unicode or ANSI environments, the ANSI version was
irrelevant in this case exactly as stated. Perhaps I should have commented
it out.

The problem exactly as stated is that StringCchPrintf[W] broke as soon as
the %S format specifier hit a string that really uses the machine's code
page. The Pocket PC is running Windows Mobile 5 Japanese (as stated) and
the compiler and everything except the Pocket PC SDK are Japanese.

In a thread about a week before I started this one, someone in Microsoft
asserted that %S works in Windows CE even though MSDN doesn't document it.
%S does not work. Now maybe if StringCchPrintfA exists as you suggested,
and if I change the strings and format specifiers to convert everything else
from Unicode to ANSI, you think it will work? It might. And then I'll have
to call MultiByteToWideChar to convert the result back to the Unicode that
was desired in the first place, since StringCchPrintfW with a %S format
specifier will fall apart.
Post by unknown
Maybe not - the problem wasn't well-stated (though the source is the doc,
right - so not making excuses here!).
But still, it is a solution. I've not called StringCchPrintfA - but I do
see that it is exported from COREDLL. It is guarded (as most things are)
by a SYSGEN tag, so it may or may not be available in your config.
--
Michael Salamone [eMVP]
Entrek Software, Inc.
www.entrek.com
Post by Tim Roberts
Post by unknown
Yes, UNICODE is defined, and must be, when building WinCE applications.
That doesn't mean StringCchPrintf is broken. There are two functions, and
StringCchPrintf is not one of them. Since UNICODE is defined,
StringCchPrintf resolves to StringCchPrintfW. The ASCII version, which you
have to use explicitly for char type, is StringCchPrintfA. See safestr.h
for more info.
Although your assessment is fundamentally correct, it doesn't have anything
to do with his complaint. His complaint was that the %S (uppercase)
descriptor to StringCchPrintfW, which should accept a multibyte string,
does not work if there are true multibyte characters in the string. Only
single-byte ASCII works.
Windows CE doesn't have StringCchPrintfA.
--
Providenza & Boekelheide, Inc.
Tim Roberts
2006-11-08 05:56:25 UTC
Permalink
Post by Norman Diamond
I think the problem was stated well enough. Although I wrote code to
contend with either Unicode or ANSI environments, the ANSI version was
irrelevant in this case exactly as stated. Perhaps I should have commented
it out.
The problem exactly as stated is that StringCchPrintf[W] broke as soon as
the %S format specifier hit a string that really uses the machine's code
page. The Pocket PC is running Windows Mobile 5 Japanese (as stated) and
the compiler and everything except the Pocket PC SDK are Japanese.
More precisely, the %S specifier breaks as soon as it encounteres a
multi-byte character. And, in a begrudging acknowledgement to Michael, I
think the documentation actually supports this behavior. The documentation
for the Windows CE version says that %S accepts "single-byte character
strings". This is very different from the non-CE version, which is spec-ed
to accept "multibyte character strings."

So, to wrap up, I think this is working exactly the way it is supposed to.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Norman Diamond
2006-11-09 00:31:36 UTC
Permalink
Post by Tim Roberts
More precisely, the %S specifier breaks as soon as it encounteres a
multi-byte character.
I still wonder if it breaks as soon as it encounters a single-byte English
character too, i.e. I wonder if ITV was running Windows CE ^_^
Post by Tim Roberts
And, in a begrudging acknowledgement to Michael, I think the documentation
actually supports this behavior.
Yup. The Japanese version of Windows CE 5 can't handle Japanese strings.
How can we ever forget we're dealing with Microsoft here.
Tim Roberts
2006-11-10 04:11:29 UTC
Permalink
Post by Norman Diamond
Post by Tim Roberts
More precisely, the %S specifier breaks as soon as it encounteres a
multi-byte character.
I still wonder if it breaks as soon as it encounters a single-byte English
character too, i.e. I wonder if ITV was running Windows CE ^_^
You yourself said the %S spec did exactly what it was supposed to, as long
as the hostname was just single-byte characters.
Post by Norman Diamond
Post by Tim Roberts
And, in a begrudging acknowledgement to Michael, I think the documentation
actually supports this behavior.
Yup. The Japanese version of Windows CE 5 can't handle Japanese strings.
It can't handle *multibyte* Japanese strings. It does handle Unicode
Japanese strings.
Post by Norman Diamond
How can we ever forget we're dealing with Microsoft here.
Don't forget that you're dealing with Windows CE here, which was designed
for devices of limited size and ability. Unicode code-page conversion
tables are HUGE. Even Windows XP doesn't guarantee those conversions in
kernel mode, because the tables are in paged memory.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Norman Diamond
2006-11-13 00:15:53 UTC
Permalink
Post by Tim Roberts
Post by Norman Diamond
Post by Tim Roberts
More precisely, the %S specifier breaks as soon as it encounteres a
multi-byte character.
I still wonder if it breaks as soon as it encounters a single-byte English
character too, i.e. I wonder if ITV was running Windows CE ^_^
You yourself said the %S spec did exactly what it was supposed to, as long
as the hostname was just single-byte characters.
I did not. I said that the %S spec did exactly what it was supposed to in
one case which I observed, one case in which the string was not a hostname
but which was just single-byte characters. Since my initial posting even
contained the contents of that string, you can observe that the observed
case where %S worked only contained a limited set of single-byte characters,
it didn't even include an English character such as the pound sign.
Post by Tim Roberts
Post by Norman Diamond
Post by Tim Roberts
And, in a begrudging acknowledgement to Michael, I think the
documentation actually supports this behavior.
Yup. The Japanese version of Windows CE 5 can't handle Japanese strings.
It can't handle *multibyte* Japanese strings.
Oh. I suppose you mean maybe it can handle hankaku katakana because those
are single-bytes. For some inexplicable reason I agree that it's
theoretically possible but think I don't have sufficiently powerful hardware
floating point to calculate how small the odds are.
Post by Tim Roberts
It does handle Unicode Japanese strings.
Because it doesn't know what language is involved when the strings are
Unicode.

Ability to handle Unicode doesn't help a bit when the string came from
gethostname(). Did you forget?
Post by Tim Roberts
Post by Norman Diamond
How can we ever forget we're dealing with Microsoft here.
Don't forget that you're dealing with Windows CE here, which was designed
for devices of limited size and ability.
THIS IS THE JAPANESE VERSION OF WINDOWS CE HERE.

WHO OTHER THAN MICROSOFT COULD SURVIVE IN JAPAN
YEAR AFTER YEAR WITH THIS KIND OF CRAP?
Post by Tim Roberts
Unicode code-page conversion tables are HUGE.
Ooooh. In that case you think that even MultiByteToWideChar won't be able
to handle Japanese. Maybe I haven't done enough testing yet because I
didn't find those failures, but thank you for the warning. Now if you know
how to get Microsoft's crap out of Japan so that working tools will have a
better chance of surviving in Japan, let's get started.
Post by Tim Roberts
Even Windows XP doesn't guarantee those conversions in kernel mode,
because the tables are in paged memory.
Where Windows XP can't do Unicode conversions in kernel mode, it treats
foreign countries the same way it treats Japan, and foreign versions of
Windows XP have the same limit that Japanese versions have.

Next?

Tim Roberts
2006-10-22 01:31:54 UTC
Permalink
Post by Norman Diamond
StringCchPrintf is broken, verified with the debugger in Visual Studio 2005
on Windows XP Pro, target running on a Windows Mobile 5 Pocket PC.
All machines, Windows versions, and Visual Studio 2005 are the same language
version, Japanese. The Windows Mobile 5 Pocket PC SDK is US-English.
...
StringCchPrintf really can't handle conversion between ANSI and Unicode, so
maybe that's why MSDN doesn't say it can. (Except that StringCchPrintf
managed to handle one conversion, where a string only used a small subset of
all the characters that exist in the default and current code page.)
I'm not particularly surprised. Windows CE is VERY strongly oriented
towards Unicode, and does not contain ANSI versions of most of the APIs.
You may have to fall back to converting the devnm string to Unicode using
one of the specific APIs for that before calling StringCchPrintf.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Norman Diamond
2006-11-06 01:23:36 UTC
Permalink
Post by Tim Roberts
Post by Norman Diamond
StringCchPrintf is broken, verified with the debugger in Visual Studio
2005 on Windows XP Pro, target running on a Windows Mobile 5 Pocket PC.
All machines, Windows versions, and Visual Studio 2005 are the same
language version, Japanese. The Windows Mobile 5 Pocket PC SDK is
US-English.
...
StringCchPrintf really can't handle conversion between ANSI and Unicode,
so maybe that's why MSDN doesn't say it can. (Except that StringCchPrintf
managed to handle one conversion, where a string only used a small subset
of all the characters that exist in the default and current code page.)
I'm not particularly surprised. Windows CE is VERY strongly oriented
towards Unicode, and does not contain ANSI versions of most of the APIs.
Yeah, but it still doesn't contain Unicode versions of some APIs such as
gethostname(). My sample code showed exactly the reason why I used the %S
format specifier. I found the breakage in what was expected to be
production code. I will call MultiByteToWideChar instead of using the %S
specifier because I do need the string. Still wondering how anyone thought
that Windows (CE or other) is production code, but meanwhile I'll code
workarounds and I'll still sometimes post reports of such breakage.
Loading...