Reputation: 11637
I am having troubles using SHGetKnownFolderPath() function.
I am getting the following error message:
Type error in argument 1 to 'SHGetKnownFolderPath'; expected 'const struct _GUID *' but found 'struct _GUID'.
In the KnowFolders.h
we have the following relevant definitions:
#define DEFINE_KNOWN_FOLDER(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
EXTERN_C const GUID name
...
DEFINE_KNOWN_FOLDER(FOLDERID_ProgramFiles,0x905e63b6,0xc1bf,0x494e,0xb2,0x9c,0x65,0xb7,0x32,0xd3,0xd2,0x1a);
I am using Pelles C compiler .
This is my sample code:
#include <windows.h>
#include <wchar.h>
#include <KnownFolders.h>
#include <shlobj.h>
int wmain(int argc, wchar_t **argv) {
PWSTR path = NULL;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_ProgramFiles, 0, NULL, &path);
if (SUCCEEDED(hr)){
wprintf(L"%ls", path);
}
CoTaskMemFree(path);
return 0;
}
How to fix this error message?
EDIT I have found code examples with SHGetKnownFolderPath(); all of them execute the function without the pointer. For instance:
hr = SHGetKnownFolderPath(FOLDERID_Public, 0, NULL, &pszPath);
if (SUCCEEDED(hr))
{
wprintf(L"FOLDERID_Public: %s\n", pszPath);
CoTaskMemFree(pszPath);
}
Upvotes: 5
Views: 21501
Reputation: 31
It would help to understand that the variable FOLDERID_Documents is actually a GUID structure: it's defined in the GuidDef.h header.
typedef struct {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
byte Data4[ 8 ];
} GUID;
I had problems with this also. I think the confusion arises from the previous use of CSIDLs which were not structures, but simply a number type. It also would help, if MSDN documentation showed an example. So, I'm including one here:
#include <windows.h>
#include <KnownFolders.h>
#include <shlobj.h>
#include <stdio.h>
int main (void)
{
PWSTR path ;
SHGetKnownFolderPath(&FOLDERID_Public, 0, NULL, &path) ;
wprintf(L"%s\nSize of FOLDERID: %d bytes\n", path, sizeof(FOLDERID_Public)) ;
wprintf(L"{%x-%hx-%hx-%x%x%x%x%x%x%x%x}\n", FOLDERID_Public.Data1, FOLDERID_Public.Data2, FOLDERID_Public.Data3, FOLDERID_Public.Data4[0], FOLDERID_Public.Data4[1], FOLDERID_Public.Data4[2], FOLDERID_Public.Data4[3], FOLDERID_Public.Data4[4], FOLDERID_Public.Data4[5], FOLDERID_Public.Data4[6], FOLDERID_Public.Data4[7]) ;
CoTaskMemFree((LPVOID)path) ;
return 0 ;
}
Upvotes: 3
Reputation: 11637
With the help from the comments of Jonathan Potter, I was able to correct the example.
The problem was very subtle. The following code line looks like C, but it is actually C++.
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &path);
The SHGetKnownFolderPath()
function has the following prototype:
STDAPI SHGetKnownFolderPath(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*);
Its first argument is REFKNOWNFOLDERID
.
In the shtypes.h
file we find the following:
#ifdef __cplusplus
#define REFKNOWNFOLDERID const KNOWNFOLDERID &
#else
#define REFKNOWNFOLDERID const KNOWNFOLDERID * /*__MIDL_CONST*/
#endif /* __cplusplus */
This means, that in C++ REFKNOWNFOLDERID
is a reference and in C
it is a pointer. As a consequence, we do not need an ampersand in C++
code for the first parameter.
In Visual C++ C code is often compiled with C++ and the distinction
between the languages is often blurred.
The second issue, the Unresolved external symbol 'FOLDERID_ProgramFiles'. error.
error is fixed by adding #include <initguid.h>
before #include <ShlObj.h>
. The reason is explained in this article.
So the following code compiles on Pelles C.
#include <windows.h>
#include <initguid.h>
#include <KnownFolders.h>
#include <ShlObj.h>
#include <wchar.h>
int wmain(void) {
PWSTR path = NULL;
HRESULT hr = SHGetKnownFolderPath(&FOLDERID_Documents, 0, NULL, &path);
if (SUCCEEDED(hr)) {
wprintf(L"%ls\n", path);
}
CoTaskMemFree(path);
return 0;
}
Upvotes: 17