GetProcAddress with SHGetSpecialFolder return right value but the func doesn't work.

Hi,
as stated in the title i've called shell32.dll with LoadLirary and then used GetProcAddress to find the address of "SHGetSpecialFolderDirectoryW" but also if the address of the function is right (i've checked it with some tools + calc) it doesn't work.



shell.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include "Shell32.h"
#include <cstdio>

SHELL32::SHELL32()
{
	SHELL32::MODULE_SHELL32 = LoadLibraryW(TEXT("C:\\Windows\\System32\\Shell32.dll"));
}


bool SHELL32::callSpecialFolder(HWND  rsv, LPTSTR folderBuff, int CSIDL, bool Create)
{

	printf("%x\n", MODULE_SHELL32);
	
	pSHGetSpecialFolderPathW SHGetSpecialFolderPathW = (pSHGetSpecialFolderPathW)GetProcAddress(MODULE_SHELL32, "SHGetSpecialFolderPathW");


	printf("%x\n", SHGetSpecialFolderPathW);

	BOOL stat = 0;

	BOOL err = SHGetSpecialFolderPathW(NULL, folderBuff, CSIDL_LOCAL_APPDATA, stat);
       
        printf("%d\n",err);
	
	

	return err;
	
}





main.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "stdafx.h"
#include <Windows.h>
#include "Shell32.h"


int main()
{
	LPWSTR folderBuff = NULL;

	SHELL32 ShellDll;
	ShellDll.callSpecialFolder(NULL, folderBuff, CSIDL_LOCAL_APPDATA, FALSE);

        printf("%s\n", folderBuff);

	
	return 0;
}



The output of err is 0 and so the output of folderBuff is <null>.
I've also checked the argument and they are right.
Thanks to those who'll help.
Last edited on
Edit: just noticed you're not passing a buffer, as required, for the folderBuff param. Alter line 8 of main.cpp to:

WCHAR folderBuff[MAX_PATH] = {0};

From: SHGetSpecialFolderPath function
https://msdn.microsoft.com/en-us/library/windows/desktop/bb762204%28v=vs.85%29.aspx

pszPath [out]

Type: LPTSTR

A pointer to a null-terminated string that receives the drive and path of the specified folder. This buffer must be at least MAX_PATH characters in size.

Meanwhile...

What does GetLastError() return when SHGetSpecialFolderPath fails?

Andy

PS If you're using the -W version of SHGetSpecialFolderPath I would adjust the signature to use LPWSTR rather than LPTSTR.
Last edited on
Thanks for the answer,
GetLastError() return 5,ERROR_ACCESS_DENIED.
I'm running VC++ as Admin.
Last edited on
Have you fixed your code?

Have you tried it with a different CSIDL?

Andy

This works for me (compiled as a single .cpp file) as a regular user on Windows 8:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "Windows.h"
#include "Shlobj.h"
#include <cstdio>
#pragma comment(lib, "shell32.lib")

typedef BOOL (WINAPI * pSHGetSpecialFolderPathW)(HWND rsv, LPWSTR folderBuff, int CSIDL, BOOL Create);

class SHELL32
{
private:
    HMODULE MODULE_SHELL32;
    pSHGetSpecialFolderPathW SHGetSpecialFolderPathW;
public:
    SHELL32();
    ~SHELL32();
    bool callSpecialFolder(HWND rsv, LPWSTR folderBuff, int CSIDL, bool Create);
};

SHELL32::SHELL32() : MODULE_SHELL32(NULL), SHGetSpecialFolderPathW(NULL)
{
    MODULE_SHELL32 = LoadLibraryW(L"C:\\Windows\\System32\\Shell32.dll");
}

SHELL32::~SHELL32()
{
    if(NULL != MODULE_SHELL32)
        FreeLibrary(MODULE_SHELL32); // to be tidy
}

bool SHELL32::callSpecialFolder(HWND rsv, LPWSTR folderBuff, int CSIDL, bool Create)
{
    printf("%x\n", MODULE_SHELL32);

    pSHGetSpecialFolderPathW SHGetSpecialFolderPathW = (pSHGetSpecialFolderPathW)GetProcAddress(MODULE_SHELL32, "SHGetSpecialFolderPathW");

    printf("%x\n", SHGetSpecialFolderPathW);

    BOOL stat = Create ? TRUE : FALSE;

    BOOL retCode = SHGetSpecialFolderPathW(rsv, folderBuff, CSIDL, stat);
    // was CSIDL_LOCAL_APPDATA rather than 

    printf("%d\n", retCode);

    return (FALSE != retCode);
}

//#include "stdafx.h"
//#include <Windows.h>
//#include "Shell32.h"

int main()
{
    //LPWSTR folderBuff = NULL;
    WCHAR folderBuff[MAX_PATH] = {0};

    SHELL32 ShellDll;
    ShellDll.callSpecialFolder(NULL, folderBuff, CSIDL_LOCAL_APPDATA, FALSE);

    printf("%S\n", folderBuff); // was %s (need %S for Unicode)

    return 0;
}
Last edited on
Hey! Great answer & Thanks for the code!
I just saw that i've not posted the shell32.h header:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pragma once

#include <Windows.h>

#define CSIDL_LOCAL_APPDATA 0x001c

typedef BOOL (_stdcall WINAPI *pSHGetSpecialFolderPathW)(HWND rsv, LPWSTR folderBuff, int CSIDL, BOOL Create);

class SHELL32
{
public:

	SHELL32();

	bool callSpecialFolder(HWND  rsv, LPTSTR folderBuff, int CSIDL, bool Create);

private:

	HMODULE MODULE_SHELL32;
};


In the end it worked! Just one question,why you specify a destructor if calling the class like this SHELL32 ShellDll; (without the new keyword) let the kernel deal with the deallocation of the memory?
Last edited on
Out of interest, why are you defining CSIDL_LOCAL_APPDATA ?? Aren't you using the appropriate WinSDK header?

Andy

PS I always teardown what I setup.
Because my program has very limited memory space in which work so include the entire <ShlObj.h> would have meant include other 4k line of code
Last edited on
By "your program" I assume you mean compiler, yes? (as the size of an include file will have zero impact on the size of the binary you build.)

Andy
Topic archived. No new replies allowed.