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

Jun 4, 2015 at 6:43pm
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 Jun 4, 2015 at 6:47pm
Jun 4, 2015 at 7:36pm
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 Jun 4, 2015 at 7:43pm
Jun 4, 2015 at 7:49pm
Thanks for the answer,
GetLastError() return 5,ERROR_ACCESS_DENIED.
I'm running VC++ as Admin.
Last edited on Jun 4, 2015 at 7:55pm
Jun 4, 2015 at 8:02pm
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 Jun 4, 2015 at 8:14pm
Jun 4, 2015 at 8:16pm
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 Jun 4, 2015 at 8:21pm
Jun 4, 2015 at 8:27pm
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.
Jun 4, 2015 at 8:33pm
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 Jun 4, 2015 at 8:45pm
Jun 5, 2015 at 4:15am
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.