(svn r7460) -Fix (r7337): [win32] If the underlying OS didn't have support for SHGetFolderPath the
authorDarkvater
Sat, 09 Dec 2006 23:55:56 +0000
changeset 5304 50daae4d7d38
parent 5303 5a3fa9dfe40b
child 5305 e07957fe871e
(svn r7460) -Fix (r7337): [win32] If the underlying OS didn't have support for SHGetFolderPath the
application failed to run. Now test if the function exists and if not try a different
approach using our own OTTDSHGetFolderPath wrapper.
win32.c
win32.h
--- a/win32.c	Sat Dec 09 20:14:26 2006 +0000
+++ b/win32.c	Sat Dec 09 23:55:56 2006 +0000
@@ -14,6 +14,7 @@
 #include <wininet.h>
 #include <io.h>
 #include <fcntl.h>
+#include <shlobj.h> // SHGetFolderPath
 #include "variables.h"
 #include "win32.h"
 #include "fios.h" // opendir/readdir/closedir
@@ -1092,3 +1093,52 @@
 	static char utf8_buf[512];
 	return convert_from_fs(name, utf8_buf, lengthof(utf8_buf));
 }
+
+/** Our very own SHGetFolderPath function for support of windows operating
+ * systems that don't have this function (eg Win9x, etc.). We try using the
+ * native function, and if that doesn't exist we will try a more crude approach
+ * of environment variables and hope for the best */
+HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath)
+{
+	static HRESULT (WINAPI *SHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR) = NULL;
+	static bool first_time = true;
+
+	/* We only try to load the library one time; if it fails, it fails */
+	if (first_time) {
+#if defined(UNICODE)
+# define W(x) x "W"
+#else
+# define W(x) x "A"
+#endif
+		if (!LoadLibraryList((Function*)&SHGetFolderPath, "SHFolder.dll\0" W("SHGetFolderPath") "\0\0")) {
+			DEBUG(misc, 0) ("Unable to load " W("SHGetFolderPath") "from SHFolder.dll");
+		}
+#undef W
+		first_time = false;
+	}
+
+	if (SHGetFolderPath != NULL) return SHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath);
+
+	/* SHGetFolderPath doesn't exist, try a more conservative approach,
+	 * eg environment variables. This is only included for legacy modes
+	 * MSDN says: that 'pszPath' is a "Pointer to a null-terminated string of
+	 * length MAX_PATH which will receive the path" so let's assume that
+	 * Windows 95 with Internet Explorer 5.0, Windows 98 with Internet Explorer 5.0,
+	 * Windows 98 Second Edition (SE), Windows NT 4.0 with Internet Explorer 5.0,
+	 * Windows NT 4.0 with Service Pack 4 (SP4) */
+	{
+		DWORD ret;
+		switch (csidl) {
+			case CSIDL_FONTS: /* Get the system font path, eg %WINDIR%\Fonts */
+				ret = GetEnvironmentVariable(_T("WINDIR"), pszPath, MAX_PATH * sizeof(TCHAR));
+				if (ret == 0) break;
+				_tcsncat(pszPath, _T("\\Fonts"), MAX_PATH * sizeof(TCHAR));
+
+				return (HRESULT)0;
+				break;
+			/* XXX - other types to go here when needed... */
+		}
+	}
+
+	return E_INVALIDARG;
+}
--- a/win32.h	Sat Dec 09 20:14:26 2006 +0000
+++ b/win32.h	Sat Dec 09 23:55:56 2006 +0000
@@ -3,6 +3,7 @@
 #ifndef WIN32_H
 #define WIN32_H
 
+#include <windows.h>
 bool MyShowCursor(bool show);
 
 typedef void (*Function)(int);
@@ -23,6 +24,14 @@
 # define WIDE_TO_MB_BUFFER(str, buffer, buflen) (str)
 #endif
 
+/* Override SHGetFolderPath with our custom implementation */
+#if defined(SHGetFolderPath)
+#undef SHGetFolderPath
+#endif
+#define SHGetFolderPath OTTDSHGetFolderPath
+
+HRESULT OTTDSHGetFolderPath(HWND, int, HANDLE, DWORD, LPTSTR);
+
 #if defined(__MINGW32__)
 #define SHGFP_TYPE_CURRENT 0
 #endif /* __MINGW32__ */