Great description of the nuance between Systems Hungarian and Apps Hungarian.
One further nuance is that return types of APIs also affect the naming of the APIs in Apps Hungarian. Boolean return values are typically called f for flag. An API that returns a boolean would be called FApiFunction - the capital F (camel case is used) at the beginning of the API name indicates that the API returns a boolean. If you write code that stores the return value in a variable that doesn't begin with an 'f' then any code reader would see the mismatch.
FTA, one problem is that the API returns a ULONG where 0 is failure and non-zero is success.
But the developer thought that the API returned an NTSTATUS error code, where 0 (== STATUS_SUCCESS) is success and non-zero is failure. This is the opposite of the documented return value for the API in question.
In Apps Hungarian, the naming of the API would be obvious that it didn't return an NTSTATUS variable vs a ULONG. Systems Hungarian lost that tidbit somewhere. So developers must be more diligent about knowing the return values of various APIS (but assuming NTSTATUS usually works, expect in this case).
But Apps Hungarian rarely names variables with native type prefixes. Variables are more than just the native underlying type (ULONG, int). Variables have a purpose. The return type of strlen or Win32 equivalent is an int or for more modern-designed APIs, an unsigned int (since string lengths can't be negative). In Systems Hungarian, you'd name the variable ulen. But in Apps Hungarian, strlen returns an int representing the count of characters. Apps Hungarian uses 'ch' for character and 'c' to denote a count. So the variable used to store the return value from strlen would be cch. (And in Apps Hungarian, you'd actually alias strlen to CchStrlen so you'd know just looking at the API that it returns a 'cch', count of characters, and you'd need a CCH type to store the return value).
bytes are bytes, and in Apps Hungarian, it'd be 'b' type. So 'cb' would be a count of bytes.
I'm not sure you could place utf characters 'atop' of 'ch', more alongside/as well.
Win32 had support for wide-characters (UCS-2, I believe) which mapped to WCHAR/'wch'. They also support, in the windows.h headers, for compiling code to support both single-byte characters and wide characters using one code base via macros/typedefs with the TCHAR type et al. This resulted in code that used 'tch' as the underlying character type.
So code that only wanted 16-bit Unicode would have variables like 'wch' and 'cwch'. Code that supported both single and wide characters would have 'tch' and 'ctch'.
UTF support in Win32 appeared after I stopped Win32 programming. Looking up a few Win32 UTF-related programming docs, MS seems to have shoved UTF-8 support under the old Win32 Ansi-character/single byte string APIs. I'd probably create some Utf-type related APIs that called down to the Win32-related APIs. But it would also depend on the UTF-8 API design (strlen doesn't map 1-1 to UTF chars anymore) - parsing UTF-8 characters/code points is different than single-byte character set. I'd guess there'd be 'uch' for a UTF-8 character, probably a 'ucp' for a UTF-8 character point, etc.
[edit]
You wouldn't just repurpose single-byte string code with 'cch' for UTF-8 since the semantics aren't the same (not even if you include double-byte character sets like Japanese), one UTF-8 character can be one or more bytes which typical one/double-character set string code doesn't deal with.
as a reference, the reference to 'ppszOutStr' that a previous poster mentioned wouldn't be typical Apps Hungarian.
'sz' is a null-terminated string, so naming a variable 'szOutStr' is redundant since 'sz' automatically tells you it's a string. 'szOut' would be fine.
The 'pp' at the front tells you it's a pointer to a pointer.
You typically only use a 'psz' to refer to a string (I usually used 'sz' since most of the time, you're dealing with allocated memory and that means I had a pointer alread).
But if you want to reallocate the string memory , you'd have to take the address of the pointer (&psz) which meant you'd have a pointer to a pointer to a string: 'ppsz = &psz;'
When dealing with a 'ppsz', you'd know that you couldn't pass 'ppsz' directly to a function that handled 'psz' variables, you'd need to dereference ppsz (*ppsz) to get a 'psz' to pass to those functions. Useful when dealing with liberal C compilers, not as useful with stricter C++ compilers.
MSDN Library seems to have totally nuked any pre-2005-ish URLs and their search engine is just bad as well (archive.org seems to have gotten tons of 302s/301s when crawling for this article). So you'll have to make do with a copy of the MSDN Library article at purdue.edu.
For all the people who say to me “yOu DoNt NeEd RuSt”, you can have your tyre fire languages where you need to build SOCIAL ABSTRACTIONS on top of the language because your type system literally came from the 1970s.
… I don’t know, I kind of like my compiler catching issues like these rather than having to do it by eye and hoping for the best
One further nuance is that return types of APIs also affect the naming of the APIs in Apps Hungarian. Boolean return values are typically called f for flag. An API that returns a boolean would be called FApiFunction - the capital F (camel case is used) at the beginning of the API name indicates that the API returns a boolean. If you write code that stores the return value in a variable that doesn't begin with an 'f' then any code reader would see the mismatch.
FTA, one problem is that the API returns a ULONG where 0 is failure and non-zero is success.
But the developer thought that the API returned an NTSTATUS error code, where 0 (== STATUS_SUCCESS) is success and non-zero is failure. This is the opposite of the documented return value for the API in question.
In Apps Hungarian, the naming of the API would be obvious that it didn't return an NTSTATUS variable vs a ULONG. Systems Hungarian lost that tidbit somewhere. So developers must be more diligent about knowing the return values of various APIS (but assuming NTSTATUS usually works, expect in this case).
But Apps Hungarian rarely names variables with native type prefixes. Variables are more than just the native underlying type (ULONG, int). Variables have a purpose. The return type of strlen or Win32 equivalent is an int or for more modern-designed APIs, an unsigned int (since string lengths can't be negative). In Systems Hungarian, you'd name the variable ulen. But in Apps Hungarian, strlen returns an int representing the count of characters. Apps Hungarian uses 'ch' for character and 'c' to denote a count. So the variable used to store the return value from strlen would be cch. (And in Apps Hungarian, you'd actually alias strlen to CchStrlen so you'd know just looking at the API that it returns a 'cch', count of characters, and you'd need a CCH type to store the return value).