SHGetFolderPath()
返回 an HRESULT
,其中 0 是S_OK
,但您的代码期望它返回一个BOOL
like SHGetSpecialFolderPath()
do ,其中 0 是FALSE
。因此,您需要在代码中修复该错误,因为它当前将成功视为失败。
话虽如此,您正在LPSTR
从您的函数中返回 a 。那是一个char*
. 但是你正在使用TCHAR
你的缓冲区。 TCHAR
映射到char
或者wchar_t
取决于是否UNICODE
定义。因此,您需要决定是要char*
无条件返回 a ,还是要返回 a TCHAR*
,或两者兼而有之。它有很大的不同,例如:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPSTR desktop_directory()
{
static char path[MAX_PATH+1];
if (SHGetSpecialFolderPathA(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return "ERROR";
}
相对:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPTSTR desktop_directory()
{
static TCHAR path[MAX_PATH+1];
if (SHGetSpecialFolderPath(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return TEXT("ERROR");
}
相对:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPSTR desktop_directory_ansi()
{
static char path[MAX_PATH+1];
if (SHGetSpecialFolderPathA(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return "ERROR";
}
export LPWSTR desktop_directory_unicode()
{
static wchar_t path[MAX_PATH+1];
if (SHGetSpecialFolderPathW(HWND_DESKTOP, path, CSIDL_DESKTOP, FALSE))
return path;
else
return L"ERROR";
}
更新:大多数 Win32 API 函数不支持 UTF-8,因此如果您希望函数返回 UTF-8 字符串,则必须调用函数的 Unicode 风格,然后使用WideCharToMultiByte()
将输出转换为 UTF-8 . 但是你有一个问题 - 谁分配和释放 UTF-8 缓冲区?有几种不同的方法来处理它:
使用线程安全的静态缓冲区(但要注意这个问题)。如果您不需要担心多个线程访问该函数,则删除说明__declspec(thread)
符:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
__declspec(thread) char desktop_dir_buffer[((MAX_PATH*4)+1];
export LPCSTR desktop_directory()
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return NULL;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int buflen = WideCharToMultiByte(CP_UTF8, 0, path, lstrlenW(path), desktop_dir_buffer, MAX_PATH*4, NULL, NULL);
if (buflen <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
desktop_dir_buffer[buflen] = 0;
return desktop_dir_buffer;
}
让 DLL 使用自己的内存管理器动态分配缓冲区并将其返回给调用者,然后要求调用者在使用完缓冲区后将缓冲区传递回 DLL,以便可以使用 DLL 的内存管理器释放它:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPCSTR desktop_directory()
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return NULL;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int pathlen = lstrlenW(path);
int buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, NULL, 0, NULL, NULL);
if (buflen <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
char *buffer = new char[buflen+1];
buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, buffer, buflen, NULL, NULL);
if (buflen <= 0)
{
delete[] buffer;
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
buffer[buflen] = 0;
return buffer;
}
export void free_buffer(LPVOID buffer)
{
delete[] (char*) buffer;
}
让 DLL 使用 Win32 API 内存管理器动态分配缓冲区并将其返回给调用者,然后调用者可以使用相同的 Win32 API 内存管理器释放它,而无需将其传递回 DLL 以释放它:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
export LPCSTR desktop_directory()
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return NULL;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int pathlen = lstrlenW(path);
int buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, NULL, 0, NULL, NULL);
if (buflen <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
char *buffer = (char*) LocalAlloc(LMEM_FIXED, buflen+1);
if (!buffer)
{
MessageBoxW(NULL, L"ERROR in LocalAlloc", L"TEST", MB_OK);
return NULL;
}
buflen = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, buffer, buflen, NULL, NULL);
if (buflen <= 0)
{
LocalFree(buffer);
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return NULL;
}
buffer[buflen] = 0;
return buffer; // caller can use LocalFree() to free it
}
让调用者传入它自己的缓冲区,DLL 只是填充它。这样,调用者可以决定分配和释放它的最佳方式:
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#define CSIDL_MYMUSIC 0x000D
#define CSIDL_MYVIDEO 0x000E
#include "dll.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
// the caller can set buffer=NULL and buflen=0 to calculate the needed buffer size
export int desktop_directory(LPSTR buffer, int buflen)
{
wchar_t path[MAX_PATH+1] = {0};
if (SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, path) != S_OK)
{
MessageBoxW(NULL, L"ERROR in SHGetFolderPathW", L"TEST", MB_OK);
return -1;
}
MessageBoxW(NULL, path, L"TEST", MB_OK);
int pathlen = lstrlenW(path);
int len = WideCharToMultiByte(CP_UTF8, 0, path, pathlen, buffer, buflen, NULL, NULL);
if (len <= 0)
{
MessageBoxW(NULL, L"ERROR in WideCharToMultiByte", L"TEST", MB_OK);
return -1;
}
if (!buffer)
++len;
else if (len < buflen)
buffer[len] = 0;
return len;
}