Merge branch 'master' into openal

This commit is contained in:
Christoph Oelckers 2015-04-25 09:13:11 +02:00
commit 54c2a14145
4 changed files with 54 additions and 17 deletions

View File

@ -22,6 +22,8 @@
#if defined(_WIN32) #if defined(_WIN32)
#include "i_system.h"
typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *); typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *);
//=========================================================================== //===========================================================================
@ -73,18 +75,7 @@ bool UseKnownFolders()
bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create, FString &path) bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create, FString &path)
{ {
static GKFP SHGetKnownFolderPath = NULL; static TOptWin32Proc<GKFP> SHGetKnownFolderPath("shell32.dll", "SHGetKnownFolderPath");
static bool tested = false;
if (!tested)
{
tested = true;
HMODULE shell32 = GetModuleHandle("shell32.dll");
if (shell32 != NULL)
{
SHGetKnownFolderPath = (GKFP)GetProcAddress(shell32, "SHGetKnownFolderPath");
}
}
char pathstr[MAX_PATH]; char pathstr[MAX_PATH];
@ -92,6 +83,13 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
// new to Vista, hence the reason we support both. // new to Vista, hence the reason we support both.
if (SHGetKnownFolderPath == NULL) if (SHGetKnownFolderPath == NULL)
{ {
static TOptWin32Proc<HRESULT(*)(HWND, int, HANDLE, DWORD, LPTSTR)>
SHGetFolderPathA("shell32.dll", "SHGetFolderPathA");
// NT4 doesn't even have this function.
if (SHGetFolderPathA == NULL)
return false;
if (shell_folder < 0) if (shell_folder < 0)
{ // Not supported by SHGetFolderPath { // Not supported by SHGetFolderPath
return false; return false;
@ -100,7 +98,7 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
{ {
shell_folder |= CSIDL_FLAG_CREATE; shell_folder |= CSIDL_FLAG_CREATE;
} }
if (FAILED(SHGetFolderPathA(NULL, shell_folder, NULL, 0, pathstr))) if (FAILED(SHGetFolderPathA.Call(NULL, shell_folder, NULL, 0, pathstr)))
{ {
return false; return false;
} }
@ -110,7 +108,7 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
else else
{ {
PWSTR wpath; PWSTR wpath;
if (FAILED(SHGetKnownFolderPath(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath))) if (FAILED(SHGetKnownFolderPath.Call(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath)))
{ {
return false; return false;
} }

View File

@ -1600,13 +1600,20 @@ unsigned int I_MakeRNGSeed()
FString I_GetLongPathName(FString shortpath) FString I_GetLongPathName(FString shortpath)
{ {
DWORD buffsize = GetLongPathName(shortpath.GetChars(), NULL, 0); static TOptWin32Proc<DWORD (WINAPI*)(LPCTSTR, LPTSTR, DWORD)>
GetLongPathName("kernel32.dll", "GetLongPathNameA", NULL);
// Doesn't exist on NT4
if (GetLongPathName == NULL)
return shortpath;
DWORD buffsize = GetLongPathName.Call(shortpath.GetChars(), NULL, 0);
if (buffsize == 0) if (buffsize == 0)
{ // nothing to change (it doesn't exist, maybe?) { // nothing to change (it doesn't exist, maybe?)
return shortpath; return shortpath;
} }
TCHAR *buff = new TCHAR[buffsize]; TCHAR *buff = new TCHAR[buffsize];
DWORD buffsize2 = GetLongPathName(shortpath.GetChars(), buff, buffsize); DWORD buffsize2 = GetLongPathName.Call(shortpath.GetChars(), buff, buffsize);
if (buffsize2 >= buffsize) if (buffsize2 >= buffsize)
{ // Failure! Just return the short path { // Failure! Just return the short path
delete[] buff; delete[] buff;

View File

@ -51,6 +51,35 @@ typedef enum {
extern os_t OSPlatform; extern os_t OSPlatform;
// Helper template so that we can access newer Win32 functions with a single static
// variable declaration. If this were C++11 it could be totally transparent.
template<typename Proto>
class TOptWin32Proc
{
static Proto GetOptionalWin32Proc(const char* module, const char* function, const char* alt)
{
HMODULE hmodule = GetModuleHandle(module);
if (hmodule == NULL)
return NULL;
Proto ret = (Proto)GetProcAddress(hmodule, function);
if(ret != NULL || alt == NULL)
return ret;
// Lookup alternate function name (ex. ProcW -> ProcA)
return (Proto)GetProcAddress(hmodule, alt);
}
public:
const Proto Call;
TOptWin32Proc(const char* module, const char* function, const char* alt=NULL)
: Call(GetOptionalWin32Proc(module, function, alt)) {}
// Wrapper object can be tested against NULL, but not directly called.
operator const void*() const { return Call; }
};
// Called by DoomMain. // Called by DoomMain.
void I_Init (void); void I_Init (void);

View File

@ -414,7 +414,10 @@ void Win32Video::DumpAdapters()
HMONITOR hm = D3D->GetAdapterMonitor(i); HMONITOR hm = D3D->GetAdapterMonitor(i);
MONITORINFOEX mi; MONITORINFOEX mi;
mi.cbSize = sizeof(mi); mi.cbSize = sizeof(mi);
if (GetMonitorInfo(hm, &mi))
TOptWin32Proc<BOOL(WINAPI*)(HMONITOR, LPMONITORINFO)> GetMonitorInfo("user32.dll", "GetMonitorInfoW");
assert(GetMonitorInfo != NULL); // Missing in NT4, but so is D3D
if (GetMonitorInfo.Call(hm, &mi))
{ {
mysnprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s", mysnprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s",
mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.right - mi.rcMonitor.left,