Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: SHGetSpecialFolderPath works differently in different projects - same compiler



Permlink Replies: 6 - Last Post: Jun 5, 2014 6:30 PM Last Post By: Colin Maharaj
Colin Maharaj

Posts: 23
Registered: 3/19/09
SHGetSpecialFolderPath works differently in different projects - same compiler
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 5, 2014 3:28 PM
What will cause this to happen,
in one project this compiles fine.

In another project (both BCB XE4 Pro),
it creates this error (on SHGetSpecialFolderPath)


[bcc32 Error] myApp_utils.cpp(37): E2034 Cannot convert 'wchar_t[260]' to 'char *'
Full parser context
myApp_utils.cpp(27): parsing: char GetProgFilesDrive()

//---------------------------------------------------------------------------

#pragma hdrstop

#include <vcl.h>

#include <ctype.h>
#include <shlobj.h>

#include <string.h>

#include <shellapi.h>
#include <registry.hpp>
#include <regstr.h>

#include <FileCtrl.hpp>

#include <fcntl.h>
#include "myApp_utils.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------


char GetProgFilesDrive()
{
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize = sizeof(osv);
GetVersionEx(&osv);
wchar_t pft[MAX_PATH];
char pf[MAX_PATH];
AnsiString A="";

if (osv.dwMajorVersion <= 5)
{
SHGetSpecialFolderPath(0,pft,CSIDL_PROGRAM_FILES,FALSE);
A = pft;
strcpy(pf, A.c_str());

}

if (osv.dwMajorVersion >= 6)
{
GUID FOLDERID_Desktop2 = StringToGUID("{905e63b6-c1bf-494e-b29c-65b732d3d21a}");
PWSTR lpStr;
SHGetKnownFolderPath(FOLDERID_Desktop2, 0, NULL, &lpStr);
A = WideCharToString(lpStr);
CoTaskMemFree(lpStr);
strcpy(pf, A.c_str());
}
char c = pf[0];
return c;
}

Colin Maharaj

Posts: 23
Registered: 3/19/09
Re: SHGetSpecialFolderPath works differently in different projects - same compiler
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 5, 2014 3:34 PM   in response to: Colin Maharaj in response to: Colin Maharaj
Couple more things,
1) The app where it crashes is a service not a 'normal' app
2) The shlobj header has this,

SHSTDAPI_(BOOL) SHGetSpecialFolderPathA(__reserved HWND hwnd, __out_ecount(MAX_PATH) LPSTR pszPath, __in int csidl, __in BOOL fCreate);
__success(return != 0)
SHSTDAPI_(BOOL) SHGetSpecialFolderPathW(__reserved HWND hwnd, __out_ecount(MAX_PATH) LPWSTR pszPath, __in int csidl, __in BOOL fCreate);
#ifdef UNICODE
#define SHGetSpecialFolderPath SHGetSpecialFolderPathW
#else
#define SHGetSpecialFolderPath SHGetSpecialFolderPathA
#endif // !UNICODE

So clearly, this appears to be a service that does not support Unicode by default
but how do I turn on Unicode??? All this talk about unicode being everywhere and
I get these errors? (or maybe I am completely duped here)

On 05/06/2014 06:28 PM, Colin Maharaj wrote:

What will cause this to happen,
in one project this compiles fine.

In another project (both BCB XE4 Pro),
it creates this error (on SHGetSpecialFolderPath)


[bcc32 Error] myApp_utils.cpp(37): E2034 Cannot convert 'wchar_t[260]' to 'char *'
Full parser context
myApp_utils.cpp(27): parsing: char GetProgFilesDrive()

//---------------------------------------------------------------------------

#pragma hdrstop

#include <vcl.h>

#include <ctype.h>
#include <shlobj.h>

#include <string.h>

#include <shellapi.h>
#include <registry.hpp>
#include <regstr.h>

#include <FileCtrl.hpp>

#include <fcntl.h>
#include "myApp_utils.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------


char GetProgFilesDrive()
{
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize = sizeof(osv);
GetVersionEx(&osv);
wchar_t pft[MAX_PATH];
char pf[MAX_PATH];
AnsiString A="";

if (osv.dwMajorVersion <= 5)
{
SHGetSpecialFolderPath(0,pft,CSIDL_PROGRAM_FILES,FALSE);
A = pft;
strcpy(pf, A.c_str());

}

if (osv.dwMajorVersion >= 6)
{
GUID FOLDERID_Desktop2 = StringToGUID("{905e63b6-c1bf-494e-b29c-65b732d3d21a}");
PWSTR lpStr;
SHGetKnownFolderPath(FOLDERID_Desktop2, 0, NULL, &lpStr);
A = WideCharToString(lpStr);
CoTaskMemFree(lpStr);
strcpy(pf, A.c_str());
}
char c = pf[0];
return c;
}

Colin Maharaj

Posts: 23
Registered: 3/19/09
Re: SHGetSpecialFolderPath works differently in different projects - same compiler
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 5, 2014 3:41 PM   in response to: Colin Maharaj in response to: Colin Maharaj
So guess what I tried to do.....?
define UNICODE (right?) bleep
In the define window, and I get this.......

Defining UNICODE and/or _UNICODE here may result in
link errors caused by a mismatch in the application's
entry point prototype. Setting the _TCHAR mapping
option below to "wchar_t" will ensure linking with the
appropriate version when the entry point is declared as
_tWinMain or _tmain (the default).
Do you want enable the "_TCHAR Mapping" option
instead?
[Yes] [ No ]

On 05/06/2014 06:34 PM, Colin Maharaj wrote:

Couple more things,
1) The app where it crashes is a service not a 'normal' app
2) The shlobj header has this,

SHSTDAPI_(BOOL) SHGetSpecialFolderPathA(__reserved HWND hwnd, __out_ecount(MAX_PATH) LPSTR pszPath, __in int csidl, __in BOOL fCreate);
__success(return != 0)
SHSTDAPI_(BOOL) SHGetSpecialFolderPathW(__reserved HWND hwnd, __out_ecount(MAX_PATH) LPWSTR pszPath, __in int csidl, __in BOOL fCreate);
#ifdef UNICODE
#define SHGetSpecialFolderPath SHGetSpecialFolderPathW
#else
#define SHGetSpecialFolderPath SHGetSpecialFolderPathA
#endif // !UNICODE

So clearly, this appears to be a service that does not support Unicode by default
but how do I turn on Unicode??? All this talk about unicode being everywhere and
I get these errors? (or maybe I am completely duped here)

On 05/06/2014 06:28 PM, Colin Maharaj wrote:

What will cause this to happen,
in one project this compiles fine.

In another project (both BCB XE4 Pro),
it creates this error (on SHGetSpecialFolderPath)


[bcc32 Error] myApp_utils.cpp(37): E2034 Cannot convert 'wchar_t[260]' to 'char *'
Full parser context
myApp_utils.cpp(27): parsing: char GetProgFilesDrive()

//---------------------------------------------------------------------------

#pragma hdrstop

#include <vcl.h>

#include <ctype.h>
#include <shlobj.h>

#include <string.h>

#include <shellapi.h>
#include <registry.hpp>
#include <regstr.h>

#include <FileCtrl.hpp>

#include <fcntl.h>
#include "myApp_utils.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------


char GetProgFilesDrive()
{
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize = sizeof(osv);
GetVersionEx(&osv);
wchar_t pft[MAX_PATH];
char pf[MAX_PATH];
AnsiString A="";

if (osv.dwMajorVersion <= 5)
{
SHGetSpecialFolderPath(0,pft,CSIDL_PROGRAM_FILES,FALSE);
A = pft;
strcpy(pf, A.c_str());

}

if (osv.dwMajorVersion >= 6)
{
GUID FOLDERID_Desktop2 = StringToGUID("{905e63b6-c1bf-494e-b29c-65b732d3d21a}");
PWSTR lpStr;
SHGetKnownFolderPath(FOLDERID_Desktop2, 0, NULL, &lpStr);
A = WideCharToString(lpStr);
CoTaskMemFree(lpStr);
strcpy(pf, A.c_str());
}
char c = pf[0];
return c;
}

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SHGetSpecialFolderPath works differently in different projects -same compiler
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 5, 2014 4:25 PM   in response to: Colin Maharaj in response to: Colin Maharaj
Colin wrote:

So guess what I tried to do.....?
define UNICODE (right?) bleep
In the define window, and I get this.......
Defining UNICODE and/or _UNICODE here may result in
link errors caused by a mismatch in the application's
entry point prototype.

That is correct. Unicode has a global effect on the entire project as a
whole, touching many different aspects of it (different defines for use in
source files, different library files being linked to, etc). So simply adding
UNICODE and _UNICODE to the defines list is not enough.

Setting the _TCHAR mapping option below to "wchar_t"
will ensure linking with the appropriate version when the
entry point is declared as _tWinMain or _tmain (the default).

Exactly. There are different .obj files linked to for the RTL's startup
code depending on whether Unicode is being used or not. Setting the TCHAR
option will tell the project what to do, including managing the UNICODE/_UNICODE
defines for you.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SHGetSpecialFolderPath works differently in different projects -same compiler
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 5, 2014 4:21 PM   in response to: Colin Maharaj in response to: Colin Maharaj
Colin wrote:

1) The app where it crashes is a service not a 'normal' app

Are you referring to the compiler error? Or are you experiencing an actual
crash at run-time?

2) The shlobj header has this,
<snip>
So clearly, this appears to be a service that does not support Unicode
by default but how do I turn on Unicode???

Go into the Project Options and set the 'TCHAR maps to' option to 'wchar_t'.
Or simply stop calling the generic SHGetSpecialFolderPath() function and
call either SHGetSpecialFolderPathA() or SHGetSpecialFolderPathW() directly
instead.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SHGetSpecialFolderPath works differently in different projects - samecompiler
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 5, 2014 4:08 PM   in response to: Colin Maharaj in response to: Colin Maharaj
Colin wrote:

What will cause this to happen

You are compiling one project for Ansi and the other project for Unicode.

Like most Win32 API functions that deal with string data, SHGetSpecialFolderPath()
operates on TCHAR data and has separate Ansi and Unicode versions available
- SHGetSpecialFolderPathA() and SHGetSpecialFolderPathW(), respectively.
You are calling the generic version of the function, which is implemented
as a macro that maps to either the Ansi or Unicode version depending on whether
UNICODE is defined during the precompiler stage.

in one project this compiles fine.

That project is compiled for Unicode. In the Project Options, the 'TCHAR'
maps to' option is set to 'wchar_t'. This is the default for new projects.

In another project (both BCB XE4 Pro),
it creates this error (on SHGetSpecialFolderPath)
[bcc32 Error] myApp_utils.cpp(37): E2034 Cannot convert 'wchar_t[260]'
to 'char *'

That project is compiled for Ansi. In the Project Options, the 'TCHAR' maps
to' option is set to 'char'. This is the default if you migrated a pre-2009
project into XE4.

To make the code compile in both projects (assuming you do not want to change
the 'TCHAR maps to' project option), you need to use TCHAR instead of wchar_t
for your path array:

TCHAR pft[MAX_PATH];


Or else change the code to not use the generic version of the function anymore,
use one of the others explicitly instead:

char pft[MAX_PATH];
SHGetSpecialFolderPathA(0, pft, CSIDL_PROGRAM_FILES, FALSE);


wchar_t pft[MAX_PATH];
SHGetSpecialFolderPathW(0, pft, CSIDL_PROGRAM_FILES, FALSE);


That being said, the rest of the function can be greatly simplified:

char GetProgFilesDrive()
{
    if (Win32MajorVersion >= 6)
    {
        const GUID My_FOLDERID_ProgramFiles = {0x905e63b6, 0xc1bf, 0x494e, 
{0xb2, 0x9c, 0x65, 0xb7, 0x32, 0xd3, 0xd2, 0x1a};
 
        LPWSTR lpStr;
        if (SHGetKnownFolderPath(My_FOLDERID_ProgramFiles, 0, NULL, &lpStr) 
== S_OK)
        {
            AnsiString A(lpStr);
            CoTaskMemFree(lpStr);
            return A.c_str()[0];
        }
    }
    else
    {
        char pft[MAX_PATH] = {0};
        if (SHGetSpecialFolderPathA(0, pft, CSIDL_PROGRAM_FILES, FALSE))
            return pft[0];
    }
 
    return 0;
}


--
Remy Lebeau (TeamB)
Colin Maharaj

Posts: 23
Registered: 3/19/09
Re: SHGetSpecialFolderPath works differently in different projects - samecompiler
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 5, 2014 6:30 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
OK, got it.
Thanks again.

On 05/06/2014 07:08 PM, Remy Lebeau (TeamB) wrote:

Colin wrote:

What will cause this to happen

You are compiling one project for Ansi and the other project for Unicode.

Like most Win32 API functions that deal with string data, SHGetSpecialFolderPath()
operates on TCHAR data and has separate Ansi and Unicode versions available
- SHGetSpecialFolderPathA() and SHGetSpecialFolderPathW(), respectively.
You are calling the generic version of the function, which is implemented
as a macro that maps to either the Ansi or Unicode version depending on whether
UNICODE is defined during the precompiler stage.

in one project this compiles fine.

That project is compiled for Unicode. In the Project Options, the 'TCHAR'
maps to' option is set to 'wchar_t'. This is the default for new projects.

In another project (both BCB XE4 Pro),
it creates this error (on SHGetSpecialFolderPath)
[bcc32 Error] myApp_utils.cpp(37): E2034 Cannot convert 'wchar_t[260]'
to 'char *'

That project is compiled for Ansi. In the Project Options, the 'TCHAR' maps
to' option is set to 'char'. This is the default if you migrated a pre-2009
project into XE4.

To make the code compile in both projects (assuming you do not want to change
the 'TCHAR maps to' project option), you need to use TCHAR instead of wchar_t
for your path array:

TCHAR pft[MAX_PATH];


Or else change the code to not use the generic version of the function anymore,
use one of the others explicitly instead:

char pft[MAX_PATH];
SHGetSpecialFolderPathA(0, pft, CSIDL_PROGRAM_FILES, FALSE);


wchar_t pft[MAX_PATH];
SHGetSpecialFolderPathW(0, pft, CSIDL_PROGRAM_FILES, FALSE);


That being said, the rest of the function can be greatly simplified:

char GetProgFilesDrive()
{
     if (Win32MajorVersion >= 6)
     {
         const GUID My_FOLDERID_ProgramFiles = {0x905e63b6, 0xc1bf, 0x494e,
{0xb2, 0x9c, 0x65, 0xb7, 0x32, 0xd3, 0xd2, 0x1a};
 
         LPWSTR lpStr;
         if (SHGetKnownFolderPath(My_FOLDERID_ProgramFiles, 0, NULL, &lpStr)
== S_OK)
         {
             AnsiString A(lpStr);
             CoTaskMemFree(lpStr);
             return A.c_str()[0];
         }
     }
     else
     {
         char pft[MAX_PATH] = {0};
         if (SHGetSpecialFolderPathA(0, pft, CSIDL_PROGRAM_FILES, FALSE))
             return pft[0];
     }
 
     return 0;
}


--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02