GetSpecialFolder

  MESSAGE GetSpecialFolder({&CSIDL_SYSTEM}) VIEW-AS ALERT-BOX.

will return "c:\windows\system" or "c:\winnt\system32" or whatever is valid on your PC.
There are different implementations of this function. This page shows one by Stuart Morris and one by Jan Verley.

Using SHGetSpecialFolderLocation

by Stuart Morris, stuart@IBS-PUBLIC-SERVICES.co.uk

PROCEDURE SHGetPathFromIDListA EXTERNAL "shell32.dll":U :
  DEFINE INPUT  PARAMETER pidl    AS  LONG.
  DEFINE OUTPUT PARAMETER pszPath AS  CHARACTER.
  DEFINE RETURN PARAMETER iResult AS  LONG.
END PROCEDURE.       
 
PROCEDURE SHGetSpecialFolderLocation EXTERNAL "shell32.dll":U :
  DEFINE INPUT  PARAMETER hwndOwner AS  LONG.
  DEFINE INPUT  PARAMETER nFolder   AS  LONG.
  DEFINE OUTPUT PARAMETER pidl      AS  LONG.
  DEFINE RETURN PARAMETER iResult   AS  LONG.
END PROCEDURE.
 
PROCEDURE CoTaskMemFree EXTERNAL "ole32.dll":U :
  DEFINE INPUT PARAMETER lpPidl AS LONG.
END PROCEDURE.
 
FUNCTION GetSpecialFolder RETURNS CHARACTER (INPUT iCSIDL AS INT):
/*-----------------------------------------------------------
  Purpose:      
  Notes:  
-------------------------------------------------------------*/
  DEFINE VARIABLE iResult AS INTEGER  NO-UNDO.
  DEFINE VARIABLE cPath   AS CHARACTER NO-UNDO.
  DEFINE VARIABLE pidl    AS INTEGER  NO-UNDO.
 
  RUN SHGetSpecialFolderLocation (INPUT  0,
                                  INPUT  iCSIDL,
                                  OUTPUT pidl,
                                  OUTPUT iResult
                                 ).
 
  IF iResult = 0 THEN DO:    
     cPath = FILL(' ', {&MAX_PATH}).
     RUN SHGetPathFromIDListA(INPUT  pidl,
                              OUTPUT cPath,
                              OUTPUT iResult
                             ).
 
     RUN CoTaskMemFree(INPUT pidl).
 
     IF iResult GT 0 THEN
        RETURN TRIM(cPath) + '\':U.
  END.
 
  RETURN "".   /* Function return value. */
 
END FUNCTION.

Using SHGetFolderPathA

by Jan Verley, jverle@softcell.be

Jan made a similar function, using SHGetFolderPathA in shfolder.dll. SHGetFolderPathA is more programmer-friendly because it simply returns the path as a string, not as as pidl. SHGetFolderPathA is a wrapper to lower-level procedures, it selects the appropriate procedures matching the current Windows version. Another interesting aspect is that this procedure lets you impersonate any user to get his/her personal folders. The downside is that SHGetFolderPathA doesn't support every defined CSIDL.
Info (for Visual Basic programmers) about this on: http:www.mvps.org/vbnet/code/shell/csidl.htm and on http:developer.earthweb.com/journal/techworkshop/020400_vbwin2k.html
Be careful: shfolder.dll may not be available on your target machine. It is a freely redistributable dll and ships with Win2000 and NT4 service pack 4 and later, IE5, Win98 Second Edition and probably ships with other MS products as well.

PROCEDURE SHGetFolderPathA EXTERNAL "shfolder.dll":U :
   DEFINE INPUT  PARAMETER hwndOwner   AS LONG.
   DEFINE INPUT  PARAMETER nFolder     AS LONG.
   DEFINE INPUT  PARAMETER hToken      AS LONG.
   DEFINE INPUT  PARAMETER dwFlags     AS LONG.
   DEFINE OUTPUT PARAMETER pszPath     AS CHARACTER.
   DEFINE RETURN PARAMETER hResult     AS LONG.
END PROCEDURE.
 
FUNCTION GetSpecialFolder RETURNS CHARACTER (INPUT iCSIDL AS INT):
/*-----------------------------------------------------------
  Purpose:      
  Notes:  
-------------------------------------------------------------*/
  DEFINE VARIABLE op_dir      AS CHARACTER NO-UNDO.
  DEFINE VARIABLE ReturnValue AS INTEGER   NO-UNDO.
 
  ASSIGN op_dir = FILL (" " ,{&MAX_PATH}).
  RUN SHGetFolderPathA (INPUT  0, 
                        INPUT  iCSIDL, 
                        INPUT  0, 
                        INPUT  0, 
                        OUTPUT op_dir,
                        OUTPUT ReturnValue).
  RETURN TRIM(op_dir).
 
END FUNCTION.

Definitions

Constants used in this example, and a few more. This is a subset from te list in [[winconst]] wikilink.zip.

&GLOBAL-DEFINE CSIDL_ADMINTOOLS 48
&GLOBAL-DEFINE CSIDL_ALTSTARTUP 29
&GLOBAL-DEFINE CSIDL_APPDATA 26
&GLOBAL-DEFINE CSIDL_BITBUCKET 10
&GLOBAL-DEFINE CSIDL_COMMON_ADMINTOOLS 47
&GLOBAL-DEFINE CSIDL_COMMON_ALTSTARTUP 30
&GLOBAL-DEFINE CSIDL_COMMON_DESKTOPDIRECTORY 25
&GLOBAL-DEFINE CSIDL_COMMON_DOCUMENTS 46
&GLOBAL-DEFINE CSIDL_COMMON_FAVORITES 31
&GLOBAL-DEFINE CSIDL_COMMON_PROGRAMS 23
&GLOBAL-DEFINE CSIDL_COMMON_STARTMENU 22
&GLOBAL-DEFINE CSIDL_COMMON_STARTUP 24
&GLOBAL-DEFINE CSIDL_COMMON_TEMPLATES 45
&GLOBAL-DEFINE CSIDL_CONTROLS 3
&GLOBAL-DEFINE CSIDL_COOKIES 33
&GLOBAL-DEFINE CSIDL_DESKTOP 0
&GLOBAL-DEFINE CSIDL_DESKTOPDIRECTORY 16
&GLOBAL-DEFINE CSIDL_DRIVES 17
&GLOBAL-DEFINE CSIDL_FAVORITES 6
&GLOBAL-DEFINE CSIDL_FONTS 20
&GLOBAL-DEFINE CSIDL_HISTORY 34
&GLOBAL-DEFINE CSIDL_INTERNET 1
&GLOBAL-DEFINE CSIDL_INTERNET_CACHE 32
&GLOBAL-DEFINE CSIDL_LOCAL_APPDATA 28
&GLOBAL-DEFINE CSIDL_MYPICTURES 39
&GLOBAL-DEFINE CSIDL_NETHOOD 19
&GLOBAL-DEFINE CSIDL_NETWORK 18
&GLOBAL-DEFINE CSIDL_PERSONAL 5
&GLOBAL-DEFINE CSIDL_PRINTERS 4
&GLOBAL-DEFINE CSIDL_PRINTHOOD 27
&GLOBAL-DEFINE CSIDL_PROFILE 40
&GLOBAL-DEFINE CSIDL_PROGRAMS 2
&GLOBAL-DEFINE CSIDL_PROGRAM_FILES 38
&GLOBAL-DEFINE CSIDL_PROGRAM_FILESX86 42
&GLOBAL-DEFINE CSIDL_PROGRAM_FILES_COMMON 43
&GLOBAL-DEFINE CSIDL_PROGRAM_FILES_COMMONX86 44
&GLOBAL-DEFINE CSIDL_RECENT 8
&GLOBAL-DEFINE CSIDL_SENDTO 9
&GLOBAL-DEFINE CSIDL_STARTMENU 11
&GLOBAL-DEFINE CSIDL_STARTUP 7
&GLOBAL-DEFINE CSIDL_SYSTEM 37
&GLOBAL-DEFINE CSIDL_SYSTEMX86 41
&GLOBAL-DEFINE CSIDL_TEMPLATES 21
&GLOBAL-DEFINE CSIDL_WINDOWS 36
 
&GLOBAL-DEFINE CSIDL_FLAG_CREATE 32768
&GLOBAL-DEFINE CSIDL_FLAG_DONT_VERIFY 16384
&GLOBAL-DEFINE CSIDL_FLAG_MASK 65280
 
&GLOBAL-DEFINE MAX_PATH 260