United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4787931 : System property "user.home" does not correspond to "USERPROFILE" (win)

Details
Type:
Bug
Submit Date:
2002-12-03
Status:
Resolved
Updated Date:
2014-03-04
Project Name:
JDK
Resolved Date:
2013-05-07
Component:
core-libs
OS:
windows_vista,windows_nt,windows_xp,windows_7,windows
Sub-Component:
java.lang
CPU:
x86,generic
Priority:
P4
Resolution:
Duplicate
Affected Versions:
1.3.0,1.4.1,1.4.2,6u5,6u24,7,7u1
Fixed Versions:

Related Reports
Backport:
Duplicate:
Relates:
Relates:
Relates:

Sub Tasks

Description
Name: nt126004			Date: 12/03/2002


FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]

ADDITIONAL OPERATING SYSTEMS :
All Windows


A DESCRIPTION OF THE PROBLEM :
The Java runtime looks (as far as I can see) at the
Registrykey
"[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersio
n\Explorer\Shell Folders\Desktop]"
and strips the last directory of this value.
As this is a derived value from a Registry-key whose
purpose is *NOT* to point at the users home directory, this
behaviour is likely to fail.
We have seen some cases, where the mentioned registry entry
changed during a windows session or after a restart. So a
Java-program's behaviour depends on when the user has
started a programm (before or after the change to the
registry, which the user probably does not know about).
After all, its really difficult to track down the reason
for a java-programs malfunction, because the mentioned
registry entry is not easy to find, and the Environment-
variable "USERPROFILE" - which should be the source
of "user.home" (this is my opinion) - does not
influence "user.home" at all.





STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.change the above windows registry value to an other value
(e.g. "c:\MyDesktopFolder")
2.run PropertyTest.java
3.type "set USERPROFILE" inside windows cmd-line (shell)

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected Result:
PropertyTest returns what Windows thinks is the User Home
directory, which should be the same value as "set
USERPROFILE" returns, e.g. "C:\Dokumente und Einstellungen\TestUser1".

Actual Result:
PropertyTest returns "C:", whereas "set USERPROFILE" still
returns "C:\Dokumente und Einstellungen\TestUser1" !


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/* precondition:
alter "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shel
l Folders\Desktop" prior to running this test */

public class PropertyTest{
  public static void main(String[] args) {
    System.out.println(System.getProperty("user.home"));
  }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
No simple workaround for us, since it depends on how our
customer deploys our application to his employees.

Reading the Environment-variable "USERPROFILE" on
Application startup is not that simple because of other
java-bugs (Exec for batch-files...).

If a customer has a problem (most often, our Application
won't start at some time (hopefully not during a
presentation to the management ;-(, because the "user.home"
is different, and the license-information file can not be
found anymore), we can tell him to manually edit the
registry, which is so awful and unprofessional for
a "professional application plattform" like java should be
one.
(Review ID: 178403) 
======================================================================

                                    

Comments
WORK AROUND

J2SE 1.5 will have a working System.getenv(String), so users can simply
do a System.getenv("USERPROFILE") directly.

###@###.### 2004-03-19
                                     
2004-03-19
EVALUATION

Will investigate fix for Tiger; problem has existed since 1.3.

###@###.### 2002-12-09

It is not at all obvious to me what the correct value for java.home should be.
When I log in to my Windows machine using ssh, I see

HOME=C:HOMEDRIVE=d:
HOMEPATH=\martin
USERPROFILE=C:\WINNT/Profiles/martin

Three different values, and the directory C:\WINNT/Profiles/martin doesn't
even exist!

When I log in the traditional way on the console, I get

HOME=C:HOMEDRIVE=C:
HOMEPATH=USERPROFILE=C:\Documents and Settings\martin

which is a little more consistent, and the latter directory
actually exists.

Given that HOME is what is used on Unix, and given that this
variable exists on Windows, I would favor this algorithm:

if HOME is defined, and names an actual directory, use that.
if HOMEDRIVE and HOMEPATH are defined, and name an actual directory, use that.
if USERPROFILE is defined, and names an actual directory, use that.
else use the root directory of the drive where the windows system directory
is located (typically C:\).

But I am not a real windows user, and I am not familiar with the
culture enough to know what most users would expected.

An argument for HOME is that this variable appears to be used by
"Command Prompt" for its initial directory.

###@###.### 2004-03-19

       The registry approach used by the JDK is definitely wrong. The
suggestion in the evaluation is also problematic because
HOME/HOMEDRIVE/HOMEPATH don't exist in older Windows platforms, and
there are many bugs documented in MSDN that these variables are not set
properly by Microsoft in various situations.

	To determine the user profile correctly on Windows, there are really
two ways to do it:

1. Use %USERPROFILE% environment

	This variable is normally set to the actual user profile location by
Microsoft. The advantages is that it works on various Windows platforms
with various types of user profile settings:

http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/xpusrdat.mspx

	However, older Windows (e.g. Windows 95/98) is more or less a single
user system, so settings up user profile is not required for end users.
In these OSes, %USERPROFILE% would not be set by Windows, but Windows
itself would default the profile location internally to Windows
directory.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/shlwapi/registry/shreggetpath.asp

	Thus, the correct algorithm in this case would be:

	if %USERPROFILE% is present	{
	   Set "user.home" to value of %USERPROFILE%
	} else  {
	   Set "user.home" to Windows directory
	}

	This scheme works in general, and it basically mirrors the internal
algorithm used by Windows. There is still a catch - because the value is
set in environment variables, if the user happens to change the user
profile location on-the-fly through Windows Control Panel, %USERPROFILE%
will reflect the new value only in new processes;  
%USERPROFILE% in all the running processes will still have the old
value. Users could also override USERPROFILE in the shell which may
cause unintentional side effect.


2. Use SHGetFolderLocation or SHGetFolderPath APIs

	These APIs are actually the recommended way from Microsoft to determine
special folders in user profile on Windows:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_new/fastuserswitching.asp

	These APIs generally return the special folder location under the user
profile:

	C:\Documents and Settings\<username>\<special-folder>

	You could determine the user profile by looking up the parent directory
of the returned path. Thus, the algorithm would be something like

	if shfolder.dll is present	{
	   SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, pszPath)
	} else if shell32.dll is present	{
	   SHGetSpecialFolderPath(NULL, pszPath, CSIDL_APPDATA, TRUE);
	}
	Set "user.home" to parent directory of pszPath 	   


	The nice thing about using these APIs is that they could provide the
user profile location programmatically without suffering the drawback of
environment variable scheme in general. 

	This scheme also works in most cases. The catch is that these APIs are
from shfolder.dll and shell32.dll, and these DLLs only present if
Internet Explorer 4 or later is installed. Although IE is almost
pre-installed with every Windows OS, Windows 95 and Windows NT4 are the
exception. Loading shfolder.dll and shell32.dll would also have minor
footprint impact because additional Windows libraries are now required
to run the Java apps.



	In general, the end result of using #1 and #2 would be pretty much the
same, and it is simply a matter of choice. In plugin, we used #1 for
determine the "user.home" settings for simplicity, and we used #2 to
determine special folder location. Since JRE only cares about user
profile location for "user.home", I would suggest #1, so it will be
consistent with plugin. #1 was also suggested by many customers in early
releases of plugin to workaround this particular "user.home" in the JRE,
so this fix should be well-received by customers. The only potential
issue for customers is backward compatibility of "user.home", but we
should fix it anyway because it is really a bug.

###@###.###

I have done some more investigation.  The windows system I was using
(Win 2003 Server 64-bit) has both the concept of a "User Profile" and
a "Home Folder" (which I think is the same as the "Home Directory"),
as can be seen from per-user properties in the menu tree
Administrative Tools ->
Computer Management ->
Local Users & Groups ->
Users

If the Home Folder is unset, it defaults to the User Profile, which
in turn defaults to %SYSTEMDRIVE%Documents and Settings\%USERNAME%.

Windows (at least in the interactive session) will initialize
%HOMEDRIVE% and %HOMEPATH% to point to the Home Folder, and will
set HOME=%HOMEDRIVE%%HOMEPATH%.

Intuitively, it seems clear we should set user.home to the same value
as the Windows Home Folder, at least on modern Windows systems.
Which means we should use %USERPROFILE% only as a fallback.

There is a programmatic API to access the home directory.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netusergetinfo.asp

NetUserGetInfo returns in its USER_INFO_1 structure, the member
LPWSTR usri1_home_dir;
which seems to be exactly what we want.

My current recommendation is:
Check if HOMEDRIVE and HOMEPATH are defined, and name a directory.
If not, use the NetUserGetInfo API to extract a valid home directory.
If that doesn't work, try %USERPROFILE%.
If that doesn't work, try the root directory of %SYSTEMDRIVE%

This seems to be consistent with "Command Prompt".

###@###.### 2004-03-23
                                     
2004-03-23
Do we need the backport,
    http://cr.openjdk.java.net/~uta/openjdk-webrevs/JDK-6519127/webrev.03/
?

Fixed in JDK 8.
                                     
2013-05-07
Duplicate for JDK-6519127
                                     
2013-05-07



Hardware and Software, Engineered to Work Together