Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

When does GETENV("TEMP") return Long file names? 1

Status
Not open for further replies.

wgcs

Programmer
Mar 31, 2002
2,056
EC
I just discovered our code has places using the temp path in a Long File Name -- Unsafe way, and it never gave us problems before because the GETENV("TEMP") always returned the Short file name version of the path in the past.

Can someone who runs on WinXP and/or Win2k NTFS with this temp path on the NTFS drive with spaces in the path tell me if those circumstances cause this to return the Long version of the path?

And, on NTFS, is there a "short" version of the path that is guaranteed to not have spaces?

(this function gets the SFN given the LFN, and works on Win2k running on Fat32:

Code:
FUNCTION lfn2sfn
PARAMETERS lcInputString
   *FROM: Q192827 
   * Converts a Win32 long file name to its short file name equivalent
   *
   * passed: long file name, must already exist for this to work
   *
   * returns: fully qualified short file name, or empty string
   * if error is encountered
   *

   DECLARE INTEGER GetShortPathName IN Kernel32 STRING @lpszLongPath, ;
      STRING @lpszShortPath, INTEGER cchBuffer
   DECLARE INTEGER GetLastError IN Win32api

   #DEFINE MAX_PATH 255

   * buffer to receive converted file name
   lcOutputString = SPACE(MAX_PATH)

   * length of receiving buffer
   llcbOutputString = LEN(lcOutputString)

   * if successful, llretval will contain the length of the
   * output string
   llretval = GetShortPathName(@lcInputString, @lcOutputString,;
      llcbOutputString)
   IF llretval = 0
   * uncomment for error code
   * wait window "Error occurred, code is: " + ltrim(str(GetLastError()))
      RETURN ""
   ENDIF

   * truncate it at the length the return value indicates
   lcOutputString = LEFT(lcOutputString, llretval)

RETURN lcOutputString
 
You could always surround it with quotes:
STORE '"' + getenv("temp") + '"' TO cTempPath

But, using your function did give me the short file name.
For example:
?lfn2sfn('c:\program files')

returns c:\progra~1


-Dave S.-
[cheers]
Even more Fox stuff at:
 
The other way to solve the problem is to use name expressions:
Code:
cTempPath = getenv("temp")
COPY TO (cTempPath)

But there is some code using a common function to get the unique file name in the temp path, which already adds the quotes, and other code that uses the name expression, and other code that (has the bug) just uses macro replacement.

I'm converting all the code to use name expressions, but I want to know which of our customers that have the old version will have problems....
 
So, Dave, Does GETENV('TEMP') return a long file name for you? or does it return the short version?

I guess you did answer my other question, that the short version Does work on Win2k/NTFS (at least, Lfn2Sfn works... can you use files in that short path?)

(I'm on W2k Fat32 and it always returns the short version to VFP)
 
GETENV('TEMP') returns the short file name.
Keep in mind that GETENV() is going to return whatever the environment setting is.
Go to a command prompt and type SET.
As you probably know, any of those items can be returned with GETENV(). They will be returned as they are displayed using SET.
Now for a puzzler, go to your system properties.
(Hold down the windows key and press the Pause/Break key)
Click on the 'Advanced' tab, then 'Environment Variables.
At least on my system, TEMP has a long file name.
(%USERPROFILE%\Local Settings\Temp).
But by the time it is set in the environment, it is short.
(TEMP=C:\DOCUME~1\dsummers.000\LOCALS~1\Temp)
However, the USERPROFILE variable is
(USERPROFILE=C:\Documents and Settings\dsummers.000).


-Dave S.-
[cheers]
Even more Fox stuff at:
 
That's exactly what I found: Because the Advanced tab shows the long file path, and NTFS isn't groundd in the FAT limitation of 8.3, I thought that was possibly our customers cause of the crash when the "TEMP" path has a space in it.

Thanks for confirming that Win2k+NTFS still understands the short path, and that GETENV("TEMP") still returns the short path.

Now, Anyone have WinXP+NTFS that could test?
 
wgcs,

Tested. Works as expected with WinXP (home and prof).

Slighthaze = NULL
craig1442@mchsi.com
"Whom computers would destroy, they must first drive mad." - Anon​
 
Thanks.. Is that "works as Expected" mean always returns the short path, or always returns the long path (with spaces in it)?
 
always returns the short path...when i say always, i guess i mean on the computers i tried it on...maybe there is some kind of setting that can effect it.

Slighthaze = NULL
craig1442@mchsi.com
"Whom computers would destroy, they must first drive mad." - Anon​
 
let me start by saying that I'm not a Foxpro programming. I'm trying to use the lfn2sfn to get the short file name of a file. I have a varible name that is passed to the function. How to I read the return?

* lcProgramWebDLL is dynamic
* lcProgramWebDLL = "'"c:\Documents and Settings\jte\process\myDll.dll"'"

?lfn2sfn(lcProgramWebDLL)

Within the lfn2sfn function, the short name is generated but I don't know how to read it the value once it returns. The lcProgramWebDLL is stil the long name outside the
lfn2sfn function.

Thanks in advance.
 
Not hard:

Code:
lcProgramWebDLL = 'c:\Documents and Settings\jte\process\myDll.dll'

lcShortName = lfn2sfn(lcProgramWebDLL)

?lcShortName
 
Thanks for the help. Now my lfn2sfn isn't getting the correct llretval when running the GetShortPathName. I'm getting a "0" error. Does anyone know what this error is? I have tried using GetShortPathName from Kernel32 and Win32API. Otherwise, my code is identical to the code above. I'm running XP locally. Could that be a problem?

Thanks in advance.
 
If you uncomment the "wait window ..." command by just deleteing the leading "*", what shows up in the Window?

Rick
 
If I step through the code, I get "Error occurred, code is: 0". If there are no breakpoints in the code, I get "Error occurred, code is: 123
 
I'm not sure what this means, but you may want to use the code in "HOWTO: Use the Win32 API FormatMessage Function with Visual FoxPro" to print out a meaningful description rather than a number.

Note: I found that 123 is defined as ERROR_INVALID_NAME, I might guess that you aren't giving it a valid file/directory name (or that it's hidden, system or not accessable by the current user). It's probably best if you check it's existance with FILE() and/or Directory() before you try and get the SFN.

Rick
 
In fact playing with the code in "HOWTO: Use the Win32 API FormatMessage Function with Visual FoxPro" gives the following for 123:
Code:
---------------------------
ERROR
---------------------------
System error has occurred.
System Error code: 123
System Error message: The filename, directory name, or volume label syntax is incorrect.

---------------------------
OK   
---------------------------
Maybe you can show us what you are really checking on?

Rick
 
I'm not sure what you are asking for. Is this it?

lcProgramWebDLL = 'c:\Documents and Settings\jte\process\myDll.dll'

lcShortName = lfn2sfn(lcProgramWebDLL)

?lcShortName

In lfn2sfn,

* if successful, llretval will contain the length of the
* output string
llretval = GetShortPathName(@lcInputString, @lcOutputString,;
llcbOutputString)
IF llretval = 0
* uncomment for error code
lnError = GetLastError()
wait window "Error occurred, code is: " + ltrim(str(lnError()))
RETURN ""

 
And since I went through the process, here's the "new" version of lfn2sfn():
Code:
FUNCTION lfn2sfn
PARAMETERS lcInputString
   *FROM: Q192827 
   * Converts a Win32 long file name to its short file name equivalent
   *
   * passed: long file name, must already exist for this to work
   *
   * returns: fully qualified short file name, or empty string
   * if error is encountered
   *

   DECLARE INTEGER GetShortPathName IN Kernel32 STRING @lpszLongPath, ;
      STRING @lpszShortPath, INTEGER cchBuffer
   DECLARE INTEGER GetLastError IN Win32api
	*!* Declare function to return text message from system error code.
   DECLARE INTEGER FormatMessage IN kernel32.DLL ;
	INTEGER dwFlags, ;
	STRING @lpSource, ;
	INTEGER dwMessageId, ;
	INTEGER dwLanguageId, ;
	STRING @lpBuffer, ;
	INTEGER nSize, ;
	INTEGER Arguments

   #DEFINE MAX_PATH 255
   *!* #DEFINES from HOME()+"FOXPRO.h"
   #DEFINE MB_ICONINFORMATION      64      && Information message
   #DEFINE MB_OK                   0       && OK button only

   #DEFINE CR			CHR(13) && Carriage Return
   #DEFINE ERROR_SUCCESS           0		&& Success error code from WINERROR.H
   #DEFINE FORMAT_MESSAGE_FROM_SYSTEM   0x00001000 && Value for FormatMessage API. From WINBASE.H

   * buffer to receive converted file name
   lcOutputString = SPACE(MAX_PATH)

   * length of receiving buffer
   llcbOutputString = LEN(lcOutputString)

   * if successful, llretval will contain the length of the
   * output string
   llretval = GetShortPathName(@lcInputString, @lcOutputString,;
      llcbOutputString)
   IF llretval = 0
   * uncomment for error code
   * wait window "Error occurred, code is: " + ltrim(str(GetLastError()))
      lpBuffer  = SPACE(128)
      lnError = GetLastError()
      =FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, ;
         'WINERROR.H', lnError, 0, @lpBuffer, 128 , 0)
      =MESSAGEBOX("System error has occurred." + CR + ;
          "System Error code: " + ALLTRIM(STR(lnError)) + CR + ;
          "System Error message: "+ALLT(lpBuffer),MB_ICONINFORMATION+MB_OK,"ERROR")
      RETURN ""
   ENDIF

   * truncate it at the length the return value indicates
   lcOutputString = LEFT(lcOutputString, llretval)

RETURN lcOutputString
Rick
 
lsugirl, In this line of your code:
lcProgramWebDLL = 'c:\Documents and Settings\jte\process\myDll.dll'

is that what you really are executing? if so, does "mydll.dll" really exist at that location?

( ie: what is displayed when you execute in VFP:

WAIT WINDOW TRAN( FILE( 'c:\Documents and Settings\jte\process\myDll.dll' ))
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top