diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2023-03-26 23:01:46 +0200 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2023-03-27 19:51:09 +0200 |
| commit | 5a4e7caa54bab9da2061b0003bb546aa0da6ea1b (patch) | |
| tree | f4c315905d4021939d8d8aea8d4b9062dde32ab0 | |
| parent | 6aa6866d80de123e53b864383d5457ec6e7844d1 (diff) | |
Windows: use SHGetFolderPathW() for application data folder (#710)
See GitHub issue #710: "Fl_Preferences not stored on Windows 10"
Summary: don't use the undocumented registry key "Shell Folders",
use function SHGetFolderPathW() instead although this function is
meanwhile deprecated (but available since Windows XP).
Note: tested with 32-bit build running on Windows XP (works).
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx | 84 |
1 files changed, 27 insertions, 57 deletions
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx index 3a335868c..681e519bf 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx @@ -1,7 +1,7 @@ // // Definition of Windows system driver for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2022 by Bill Spitzak and others. +// Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -39,6 +39,7 @@ #include <direct.h> #include <io.h> #include <fcntl.h> +#include <shlobj.h> // function pointer for the UuidCreate Function // RPC_STATUS RPC_ENTRY UuidCreate(UUID __RPC_FAR *Uuid); @@ -845,72 +846,41 @@ void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer) char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_Preferences::Root root, const char *vendor, const char *application) { -# define FLPREFS_RESOURCE "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" -# define FLPREFS_RESOURCEW L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" static char *filename = 0L; - // make enough room for a UTF16 pathname - if (!filename) filename = (char*)::malloc(2*FL_PATH_MAX); - filename[0] = 0; - filename[1] = 0; - size_t appDataLen = strlen(vendor) + strlen(application) + 8; - DWORD nn; - LONG err; - HKEY key; - - switch (root&Fl_Preferences::ROOT_MASK) { - case Fl_Preferences::SYSTEM: - err = RegOpenKeyW( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCEW, &key ); - if (err == ERROR_SUCCESS) { - nn = (DWORD) (FL_PATH_MAX - appDataLen); - err = RegQueryValueExW( key, L"Common AppData", 0L, 0L, - (BYTE*)filename, &nn ); - if ( err != ERROR_SUCCESS ) { - filename[0] = 0; - filename[1] = 0; - } - RegCloseKey(key); - } - break; - case Fl_Preferences::USER: - err = RegOpenKeyW( HKEY_CURRENT_USER, FLPREFS_RESOURCEW, &key ); - if (err == ERROR_SUCCESS) { - nn = (DWORD) (FL_PATH_MAX - appDataLen); - err = RegQueryValueExW( key, L"AppData", 0L,0L, - (BYTE*)filename, &nn ); - if ( err != ERROR_SUCCESS ) { - filename[0] = 0; - filename[1] = 0; - } - RegCloseKey(key); - } - break; - } - if (!filename[1] && !filename[0]) { - // Don't write data into some arbitrary directory! Just return NULL. - //strcpy(filename, "C:\\FLTK"); + // make enough room for a UTF-16 pathname + if (!filename) filename = (char*)::malloc(2 * FL_PATH_MAX); + HRESULT res; + + // https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw + + int appdata = CSIDL_APPDATA; // assume user preferences + if ((root & Fl_Preferences::ROOT_MASK) == Fl_Preferences::SYSTEM) + appdata = CSIDL_COMMON_APPDATA; // use system preferences + + res = SHGetFolderPathW(NULL, // hwnd: Reserved! + appdata, // csidl: User or common Application Data (Roaming) + NULL, // hToken (unused) + SHGFP_TYPE_CURRENT, // dwFlags: use current, potentially redirected path + (LPWSTR)filename); // out: filename in Windows wide string encoding + if (res != S_OK) { + // don't write data into some arbitrary directory! Just return NULL. return 0L; - } else { -#if 0 - wchar_t *b = (wchar_t*)_wcsdup((wchar_t *)filename); -#else - // cygwin does not come with _wcsdup. Use malloc + wcscpy. - // For implementation of wcsdup functionality See - // - http://linenum.info/p/glibc/2.7/wcsmbs/wcsdup.c - wchar_t *b = (wchar_t *)malloc((wcslen((wchar_t *)filename) + 1) * sizeof(wchar_t)); - wcscpy(b, (wchar_t *) filename); -#endif - // filename[fl_unicode2utf(b, wcslen((wchar_t*)b), filename)] = 0; - unsigned len = fl_utf8fromwc(filename, (FL_PATH_MAX-1), b, (unsigned) wcslen(b)); - filename[len] = 0; - free(b); } + // convert the path from Windows wide character (UTF-16) to UTF-8 + // FIXME: can this be simplified? Don't allocate/copy/move/free more than necessary! + char *buf = NULL; + wchar_to_utf8((wchar_t *)filename, buf); // allocates buf for conversion + strcpy(filename, buf); + free(buf); + // Make sure that the parameters are not NULL if ( (vendor==0L) || (vendor[0]==0) ) vendor = "unknown"; if ( (application==0L) || (application[0]==0) ) application = "unknown"; + // append vendor, application, and ".prefs", and convert '\' to '/' snprintf(filename + strlen(filename), FL_PATH_MAX - strlen(filename), "/%s/%s.prefs", vendor, application); for (char *s = filename; *s; s++) if (*s == '\\') *s = '/'; |
