2828
2929import com .sun .jna .Library ;
3030import com .sun .jna .Native ;
31- import com .sun .jna .platform .win32 .Kernel32Util ;
32- import com .sun .jna .platform .win32 .Shell32 ;
3331import com .sun .jna .platform .win32 .Shell32Util ;
3432import com .sun .jna .platform .win32 .ShlObj ;
35- import com .sun .jna .platform .win32 .WinDef ;
36- import com .sun .jna .platform .win32 .WinError ;
37- import com .sun .jna .platform .win32 .WinNT .HRESULT ;
3833
3934import processing .app .Base ;
4035import processing .app .Messages ;
4136import processing .app .Preferences ;
42- import processing .app .platform .DefaultPlatform ;
4337import processing .app .platform .WindowsRegistry .REGISTRY_ROOT_KEY ;
38+
4439import processing .core .PApplet ;
4540
4641
@@ -260,11 +255,29 @@ protected void checkPath() {
260255
261256 // looking for Documents and Settings/blah/Application Data/Processing
262257 public File getSettingsFolder () throws Exception {
263- String appData = getAppDataPath ();
264- if (appData != null ) {
265- return new File (appData , APP_NAME );
258+ String appDataRoaming = getAppDataPath ();
259+ if (appDataRoaming != null ) {
260+ File settingsFolder = new File (appDataRoaming , APP_NAME );
261+ if (settingsFolder .exists () || settingsFolder .mkdirs ()) {
262+ return settingsFolder ;
263+ }
264+ }
265+
266+ String appDataLocal = getLocalAppDataPath ();
267+ if (appDataLocal != null ) {
268+ File settingsFolder = new File (appDataLocal , APP_NAME );
269+ if (settingsFolder .exists () || settingsFolder .mkdirs ()) {
270+ return settingsFolder ;
271+ }
272+ }
273+
274+ if (appDataRoaming == null && appDataLocal == null ) {
275+ throw new IOException ("Could not get the AppData folder" );
266276 }
267- throw new IOException ("Could not get the Application Data folder" );
277+
278+ // https://github.com/processing/processing/issues/3838
279+ throw new IOException ("Please fix permissions for either " +
280+ appDataRoaming + " or " + appDataLocal );
268281 }
269282
270283
@@ -279,31 +292,21 @@ public File getSettingsFolder() throws Exception {
279292
280293 http://blogs.msdn.com/b/patricka/archive/2010/03/18/where-should-i-store-my-data-and-configuration-files-if-i-target-multiple-os-versions.aspx
281294 */
295+
296+
297+ /** Get the Users\name\AppData\Roaming path to write settings files. */
282298 static private String getAppDataPath () throws Exception {
283299 return Shell32Util .getSpecialFolderPath (ShlObj .CSIDL_APPDATA , true );
300+ }
284301
285- /*
286- // this will be contain the path if SHGetFolderPath is successful
287- char[] pszPath = new char[WinDef.MAX_PATH];
288- HRESULT hResult =
289- Shell32.INSTANCE.SHGetFolderPath(null, ShlObj.CSIDL_APPDATA,
290- null, ShlObj.SHGFP_TYPE_CURRENT,
291- pszPath);
292-
293- if (!hResult.equals(WinError.S_OK)) {
294- //System.err.println(Kernel32Util.formatMessageFromHR(hResult));
295- //throw new Exception("Problem city, population: your computer.");
296- throw new Exception(Kernel32Util.formatMessageFromHR(hResult));
297- }
298302
299- String appDataPath = new String(pszPath);
300- int len = appDataPath.indexOf("\0");
301- return appDataPath.substring(0, len);
302- */
303+ /** Get the Users\name\AppData\Local path as a settings fallback. */
304+ static private String getLocalAppDataPath () throws Exception {
305+ return Shell32Util .getSpecialFolderPath (ShlObj .CSIDL_LOCAL_APPDATA , true );
303306 }
304307
305308
306- // looking for Documents and Settings/blah/ My Documents/ Processing
309+ /** Get the Documents and Settings\name\ My Documents\ Processing folder. */
307310 public File getDefaultSketchbookFolder () throws Exception {
308311 String documentsPath = getDocumentsPath ();
309312 if (documentsPath != null ) {
@@ -313,6 +316,12 @@ public File getDefaultSketchbookFolder() throws Exception {
313316 }
314317
315318
319+ static private String getDocumentsPath () throws Exception {
320+ return Shell32Util .getSpecialFolderPath (ShlObj .CSIDL_MYDOCUMENTS , true );
321+ }
322+
323+
324+ /*
316325 static private String getDocumentsPath() throws Exception {
317326 // heh, this is a little too cheeky
318327 //new JFileChooser().getFileSystemView().getDefaultDirectory().toString();
@@ -351,6 +360,7 @@ static private String getDocumentsPath() throws Exception {
351360 int len = personalPath.indexOf("\0");
352361 return personalPath.substring(0, len);
353362 }
363+ */
354364
355365
356366// @Override
@@ -503,6 +513,8 @@ public void openFolder(File file) throws Exception {
503513 static WinLibC clib ;
504514
505515
516+ // moved to a getter so that we could handle errors in a single location
517+ // and at a time when it was useful/possible (rather than a static block)
506518 static WinLibC getLibC () {
507519 if (clib == null ) {
508520 try {
0 commit comments