Skip to content

Commit ebdc6c7

Browse files
committed
Changed windows platform code to JNA for Issue 410.
1 parent 4f06e64 commit ebdc6c7

File tree

1 file changed

+94
-14
lines changed

1 file changed

+94
-14
lines changed

app/src/processing/app/windows/Platform.java

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@
2424

2525
import java.io.File;
2626
import java.io.UnsupportedEncodingException;
27+
import java.util.HashMap;
28+
import java.util.Map;
2729

2830
import com.sun.jna.Library;
2931
import com.sun.jna.Native;
32+
import com.sun.jna.NativeMapped;
33+
import com.sun.jna.PointerType;
34+
import com.sun.jna.win32.W32APIFunctionMapper;
35+
import com.sun.jna.win32.W32APITypeMapper;
3036

3137
import processing.app.Base;
3238
import processing.app.Preferences;
@@ -182,19 +188,34 @@ public File getSettingsFolder() throws Exception {
182188
// Value Type: REG_SZ
183189
// Value Data: path
184190

185-
String keyPath =
186-
"Software\\Microsoft\\Windows\\CurrentVersion" +
187-
"\\Explorer\\Shell Folders";
188-
String appDataPath =
189-
Registry.getStringValue(REGISTRY_ROOT_KEY.CURRENT_USER, keyPath, "AppData");
191+
//String keyPath =
192+
// "Software\\Microsoft\\Windows\\CurrentVersion" +
193+
// "\\Explorer\\Shell Folders";
194+
//String appDataPath =
195+
// Registry.getStringValue(REGISTRY_ROOT_KEY.CURRENT_USER, keyPath, "AppData");
196+
197+
// Fix for Issue 410
198+
// Java 1.6 doesn't provide a good workaround (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6519127)
199+
// Using JNA and SHGetFolderPath instead.
200+
201+
char[] pszPath = new char[Shell32.MAX_PATH]; // this will be contain the path if SHGetFolderPath is successful
202+
int hResult = Shell32.INSTANCE.SHGetFolderPath(null, Shell32.CSIDL_APPDATA, null, Shell32.SHGFP_TYPE_CURRENT, pszPath);
203+
204+
if (Shell32.S_OK != hResult){
205+
throw new Exception("Problem city, population your computer");
206+
}
190207

191-
File dataFolder = new File(appDataPath, "Processing");
192-
return dataFolder;
208+
String appDataPath = new String(pszPath);
209+
int len = appDataPath.indexOf("\0");
210+
appDataPath = appDataPath.substring(0, len);
211+
212+
// DEBUG
213+
//throw new Exception("win: " + appDataPath);
214+
return new File(appDataPath, "Processing");
193215
}
194216

195217

196218
// looking for Documents and Settings/blah/My Documents/Processing
197-
// (though using a reg key since it's different on other platforms)
198219
public File getDefaultSketchbookFolder() throws Exception {
199220

200221
// http://support.microsoft.com/?kbid=221837&sd=RMVP
@@ -211,12 +232,28 @@ public File getDefaultSketchbookFolder() throws Exception {
211232
// in some instances, this may be overridden by a policy, in which case check:
212233
// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
213234

214-
String keyPath =
215-
"Software\\Microsoft\\Windows\\CurrentVersion" +
216-
"\\Explorer\\Shell Folders";
217-
String personalPath =
218-
Registry.getStringValue(REGISTRY_ROOT_KEY.CURRENT_USER, keyPath, "Personal");
235+
//String keyPath =
236+
// "Software\\Microsoft\\Windows\\CurrentVersion" +
237+
// "\\Explorer\\Shell Folders";
238+
//String personalPath =
239+
// Registry.getStringValue(REGISTRY_ROOT_KEY.CURRENT_USER, keyPath, "Personal");
240+
241+
// "The "Shell Folders" key exists solely to permit four programs written
242+
// in 1994 to continue running on the RTM version of Windows 95." -- Raymond Chen, MSDN
243+
244+
char[] pszPath = new char[Shell32.MAX_PATH]; // this will be contain the path if SHGetFolderPath is successful
245+
int hResult = Shell32.INSTANCE.SHGetFolderPath(null, Shell32.CSIDL_PERSONAL, null, Shell32.SHGFP_TYPE_CURRENT, pszPath);
246+
247+
if (Shell32.S_OK != hResult){
248+
throw new Exception("Problem city, population your computer");
249+
}
219250

251+
String personalPath = new String(pszPath);
252+
int len = personalPath.indexOf("\0");
253+
personalPath = personalPath.substring(0, len);
254+
255+
// DEBUG
256+
//throw new Exception("win: " + personalPath);
220257
return new File(personalPath, "Processing");
221258
}
222259

@@ -285,7 +322,7 @@ public interface WinLibC extends Library {
285322
public int _putenv(String name);
286323
}
287324

288-
325+
289326
public void setenv(String variable, String value) {
290327
//WinLibC clib = WinLibC.INSTANCE;
291328
clib._putenv(variable + "=" + value);
@@ -303,4 +340,47 @@ public int unsetenv(String variable) {
303340
//return 0;
304341
return clib._putenv(variable + "=");
305342
}
343+
344+
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
345+
346+
// JNA code for using SHGetFolderPath to fix Issue 410
347+
// Based on answer provided by McDowell at
348+
// http://stackoverflow.com/questions/585534/
349+
// what-is-the-best-way-to-find-the-users-home-directory-in-java/586917#586917
350+
351+
private static Map<String, Object> OPTIONS = new HashMap<String, Object>();
352+
353+
static{
354+
OPTIONS.put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
355+
OPTIONS.put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
356+
}
357+
358+
static class HANDLE extends PointerType implements NativeMapped{}
359+
360+
static class HWND extends HANDLE {}
361+
362+
public interface Shell32 extends Library{
363+
364+
public static final int MAX_PATH = 260;
365+
public static final int SHGFP_TYPE_CURRENT = 0;
366+
public static final int SHGFP_TYPE_DEFAULT = 1;
367+
public static final int S_OK = 0;
368+
369+
// KNOWNFOLDERIDs are preferred to CSDIL values
370+
// but Windows XP only supports CSDIL so thats what we have to use
371+
public static final int CSIDL_APPDATA = 0x001c; // "Application Data"
372+
public static final int CSIDL_PERSONAL = 0x0005; // "My Documents"
373+
374+
static Shell32 INSTANCE = (Shell32) Native.loadLibrary("shell32", Shell32.class, OPTIONS);
375+
376+
/**
377+
* see http://msdn.microsoft.com/en-us/library/bb762181(VS.85).aspx
378+
*
379+
* HRESULT SHGetFolderPath( HWND hwndOwner, int nFolder, HANDLE hToken,
380+
* DWORD dwFlags, LPTSTR pszPath);
381+
*/
382+
public int SHGetFolderPath(HWND hwndOwner, int nFolder, HANDLE hToken,
383+
int dwFlags, char[] pszPath);
384+
}
385+
306386
}

0 commit comments

Comments
 (0)