2005-04-23 05:41:42 +04:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2004-04-18 18:21:17 +04:00
/* ***** BEGIN LICENSE BLOCK *****
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
1999-12-04 04:13:44 +03:00
*
2004-04-18 18:21:17 +04:00
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
1999-12-04 04:13:44 +03:00
*
2004-04-18 18:21:17 +04:00
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
1999-12-04 04:13:44 +03:00
*
2004-04-18 18:21:17 +04:00
* The Original Code is Mozilla Communicator client code , released
* March 31 , 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation .
* Portions created by the Initial Developer are Copyright ( C ) 1998 - 1999
* the Initial Developer . All Rights Reserved .
1999-12-04 04:13:44 +03:00
*
2003-09-29 22:15:52 +04:00
* Contributor ( s ) :
2004-04-18 18:21:17 +04:00
* Doug Turner < dougt @ netscape . com >
2004-06-02 12:19:42 +04:00
* Dean Tessman < dean_tessman @ hotmail . com >
2004-06-17 20:37:25 +04:00
* Brodie Thiesfield < brofield @ jellycan . com >
2006-03-22 07:26:30 +03:00
* Jungshik Shin < jshin @ i18nl10n . com >
2004-04-18 18:21:17 +04:00
*
* Alternatively , the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later ( the " GPL " ) ,
* or the GNU Lesser General Public License Version 2.1 or later ( the " LGPL " ) ,
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above . If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL , and not to allow others to
* use your version of this file under the terms of the MPL , indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL . If you do not delete
* the provisions above , a recipient may use your version of this file under
* the terms of any one of the MPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * */
1999-12-04 04:13:44 +03:00
# include "nsCOMPtr.h"
2000-06-03 13:46:12 +04:00
# include "nsMemory.h"
1999-12-04 04:13:44 +03:00
2003-06-19 03:19:11 +04:00
# include "nsLocalFile.h"
2005-04-23 05:39:51 +04:00
# include "nsIDirectoryEnumerator.h"
2002-10-06 04:29:46 +04:00
# include "nsNativeCharsetUtils.h"
2006-03-22 07:26:30 +03:00
# include "nsWinAPIs.h"
1999-12-04 04:13:44 +03:00
# include "nsISimpleEnumerator.h"
# include "nsIComponentManager.h"
# include "prtypes.h"
# include "prio.h"
2006-03-22 07:26:30 +03:00
# include "private/pprio.h" // To get PR_ImportFile
2005-02-25 12:00:45 +03:00
# include "prprf.h"
2006-03-22 07:26:30 +03:00
# include "prmem.h"
2006-04-15 02:59:21 +04:00
# include "nsHashKeys.h"
1999-12-04 04:13:44 +03:00
2001-06-22 02:02:47 +04:00
# include "nsXPIDLString.h"
2001-11-01 12:09:57 +03:00
# include "nsReadableUtils.h"
2001-06-22 02:02:47 +04:00
1999-12-04 04:13:44 +03:00
# include <direct.h>
# include <windows.h>
# include "shellapi.h"
# include "shlguid.h"
2000-02-22 00:51:47 +03:00
# include <io.h>
# include <stdio.h>
# include <stdlib.h>
2000-04-26 07:57:34 +04:00
# include <mbstring.h>
1999-12-04 04:13:44 +03:00
2001-01-30 08:02:48 +03:00
# include "nsXPIDLString.h"
2000-02-17 19:08:53 +03:00
# include "prproces.h"
2001-08-17 06:03:34 +04:00
# include "nsITimelineService.h"
2000-02-17 19:08:53 +03:00
2002-01-08 05:20:13 +03:00
# include "nsAutoLock.h"
2004-06-02 12:19:42 +04:00
# include "SpecialSystemDirectory.h"
2002-01-08 05:20:13 +03:00
2003-03-12 11:35:57 +03:00
// _mbsstr isn't declared in w32api headers but it's there in the libs
# ifdef __MINGW32__
extern " C " {
unsigned char * _mbsstr ( const unsigned char * str ,
const unsigned char * substr ) ;
2004-05-13 08:08:34 +04:00
}
2003-03-12 11:35:57 +03:00
# endif
2002-01-08 05:20:13 +03:00
2004-04-29 12:16:50 +04:00
class nsDriveEnumerator : public nsISimpleEnumerator
{
public :
nsDriveEnumerator ( ) ;
virtual ~ nsDriveEnumerator ( ) ;
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
nsresult Init ( ) ;
private :
/* mDrives and mLetter share data
* Init sets them .
* HasMoreElements reads mLetter .
* GetNext advances mLetter .
*/
nsCString mDrives ;
const char * mLetter ;
} ;
2002-04-27 09:33:09 +04:00
//----------------------------------------------------------------------------
// short cut resolver
//----------------------------------------------------------------------------
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2002-01-08 05:20:13 +03:00
class ShortcutResolver
{
public :
ShortcutResolver ( ) ;
2004-02-11 09:19:03 +03:00
// nonvirtual since we're not subclassed
~ ShortcutResolver ( ) ;
2002-01-08 05:20:13 +03:00
nsresult Init ( ) ;
2006-03-22 07:26:30 +03:00
nsresult Resolve ( const WCHAR * in , WCHAR * out ) ;
2002-01-08 05:20:13 +03:00
private :
PRLock * mLock ;
2003-09-29 22:15:52 +04:00
IPersistFile * mPersistFile ;
2006-03-22 07:26:30 +03:00
// Win 95 and 98 don't have IShellLinkW
union
{
IShellLinkW * W ;
IShellLinkA * A ;
} mShellLink ;
2002-01-08 05:20:13 +03:00
} ;
ShortcutResolver : : ShortcutResolver ( )
{
mLock = nsnull ;
mPersistFile = nsnull ;
2006-03-22 07:26:30 +03:00
mShellLink . W = nsnull ;
2002-01-08 05:20:13 +03:00
}
ShortcutResolver : : ~ ShortcutResolver ( )
{
if ( mLock )
PR_DestroyLock ( mLock ) ;
2003-09-29 22:15:52 +04:00
// Release the pointer to the IPersistFile interface.
2002-01-08 05:20:13 +03:00
if ( mPersistFile )
2003-09-29 22:15:52 +04:00
mPersistFile - > Release ( ) ;
// Release the pointer to the IShellLink interface.
2006-03-22 07:26:30 +03:00
if ( NS_UseUnicode ( ) )
{
if ( mShellLink . W )
mShellLink . W - > Release ( ) ;
}
else
{
if ( mShellLink . A )
mShellLink . A - > Release ( ) ;
}
2002-01-08 05:20:13 +03:00
CoUninitialize ( ) ;
}
nsresult
ShortcutResolver : : Init ( )
{
CoInitialize ( NULL ) ; // FIX: we should probably move somewhere higher up during startup
mLock = PR_NewLock ( ) ;
if ( ! mLock )
return NS_ERROR_FAILURE ;
2006-03-22 07:26:30 +03:00
HRESULT hres ;
if ( NS_UseUnicode ( ) )
{
hres = CoCreateInstance ( CLSID_ShellLink ,
NULL ,
CLSCTX_INPROC_SERVER ,
IID_IShellLinkW ,
( void * * ) & ( mShellLink . W ) ) ;
if ( SUCCEEDED ( hres ) )
{
// Get a pointer to the IPersistFile interface.
hres = mShellLink . W - > QueryInterface ( IID_IPersistFile ,
( void * * ) & mPersistFile ) ;
}
}
else
2002-01-08 05:20:13 +03:00
{
2006-03-22 07:26:30 +03:00
hres = CoCreateInstance ( CLSID_ShellLink ,
NULL ,
CLSCTX_INPROC_SERVER ,
IID_IShellLinkA ,
( void * * ) & ( mShellLink . A ) ) ;
if ( SUCCEEDED ( hres ) )
{
// Get a pointer to the IPersistFile interface.
hres = mShellLink . A - > QueryInterface ( IID_IPersistFile ,
( void * * ) & mPersistFile ) ;
}
2002-01-08 05:20:13 +03:00
}
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
if ( mPersistFile = = nsnull | | mShellLink . W = = nsnull )
2002-01-08 05:20:13 +03:00
return NS_ERROR_FAILURE ;
return NS_OK ;
}
// |out| must be an allocated buffer of size MAX_PATH
2003-09-29 22:15:52 +04:00
nsresult
2006-03-22 07:26:30 +03:00
ShortcutResolver : : Resolve ( const WCHAR * in , WCHAR * out )
2002-01-08 05:20:13 +03:00
{
nsAutoLock lock ( mLock ) ;
2003-09-29 22:15:52 +04:00
2002-01-08 05:20:13 +03:00
// see if we can Load the path.
2003-09-29 22:15:52 +04:00
HRESULT hres = mPersistFile - > Load ( in , STGM_READ ) ;
if ( FAILED ( hres ) )
2002-01-08 05:20:13 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
// Resolve the link.
2006-03-22 07:26:30 +03:00
hres = mShellLink . W - > Resolve ( nsnull , SLR_NO_UI ) ;
2003-09-29 22:15:52 +04:00
if ( FAILED ( hres ) )
2002-01-08 05:20:13 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
// Get the path to the link target.
2006-03-22 07:26:30 +03:00
if ( NS_UseUnicode ( ) )
hres = mShellLink . W - > GetPath ( out , MAX_PATH , NULL , SLGP_UNCPRIORITY ) ;
else {
char tmp [ MAX_PATH ] ;
hres = mShellLink . A - > GetPath ( tmp , MAX_PATH , NULL , SLGP_UNCPRIORITY ) ;
if ( SUCCEEDED ( hres ) )
NS_ConvertAtoW ( tmp , MAX_PATH , out ) ;
}
2003-09-29 22:15:52 +04:00
if ( FAILED ( hres ) )
2002-01-08 05:20:13 +03:00
return NS_ERROR_FAILURE ;
return NS_OK ;
}
static ShortcutResolver * gResolver = nsnull ;
2002-04-27 09:33:09 +04:00
static nsresult NS_CreateShortcutResolver ( )
2002-01-08 05:20:13 +03:00
{
gResolver = new ShortcutResolver ( ) ;
if ( ! gResolver )
return NS_ERROR_OUT_OF_MEMORY ;
return gResolver - > Init ( ) ;
}
2002-04-27 09:33:09 +04:00
static void NS_DestroyShortcutResolver ( )
2002-01-08 05:20:13 +03:00
{
delete gResolver ;
gResolver = nsnull ;
}
2005-01-31 00:33:47 +03:00
# endif
2002-01-08 05:20:13 +03:00
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// static helper functions
//-----------------------------------------------------------------------------
2003-09-29 22:15:52 +04:00
// certainly not all the error that can be
1999-12-04 04:13:44 +03:00
// encountered, but many of them common ones
static nsresult ConvertWinError ( DWORD winErr )
{
nsresult rv ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
switch ( winErr )
{
case ERROR_FILE_NOT_FOUND :
case ERROR_PATH_NOT_FOUND :
case ERROR_INVALID_DRIVE :
rv = NS_ERROR_FILE_NOT_FOUND ;
break ;
case ERROR_ACCESS_DENIED :
case ERROR_NOT_SAME_DEVICE :
rv = NS_ERROR_FILE_ACCESS_DENIED ;
break ;
case ERROR_NOT_ENOUGH_MEMORY :
case ERROR_INVALID_BLOCK :
case ERROR_INVALID_HANDLE :
case ERROR_ARENA_TRASHED :
rv = NS_ERROR_OUT_OF_MEMORY ;
break ;
case ERROR_CURRENT_DIRECTORY :
rv = NS_ERROR_FILE_DIR_NOT_EMPTY ;
break ;
case ERROR_WRITE_PROTECT :
rv = NS_ERROR_FILE_READ_ONLY ;
break ;
case ERROR_HANDLE_DISK_FULL :
rv = NS_ERROR_FILE_TOO_BIG ;
break ;
2000-06-24 05:50:53 +04:00
case ERROR_FILE_EXISTS :
case ERROR_ALREADY_EXISTS :
case ERROR_CANNOT_MAKE :
rv = NS_ERROR_FILE_ALREADY_EXISTS ;
break ;
2005-03-02 21:16:37 +03:00
case ERROR_FILENAME_EXCED_RANGE :
rv = NS_ERROR_FILE_NAME_TOO_LONG ;
break ;
1999-12-04 04:13:44 +03:00
case 0 :
rv = NS_OK ;
2005-03-02 21:16:37 +03:00
break ;
2003-09-29 22:15:52 +04:00
default :
1999-12-04 04:13:44 +03:00
rv = NS_ERROR_FAILURE ;
2005-03-02 21:16:37 +03:00
break ;
1999-12-04 04:13:44 +03:00
}
return rv ;
}
2004-06-17 20:37:25 +04:00
// definition of INVALID_SET_FILE_POINTER from VC.NET header files
// it doesn't appear to be defined by VC6
# ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
# endif
// same goes for INVALID_FILE_ATTRIBUTES
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
// as suggested in the MSDN documentation on SetFilePointer
static __int64
MyFileSeek64 ( HANDLE aHandle , __int64 aDistance , DWORD aMoveMethod )
1999-12-08 02:31:25 +03:00
{
2004-06-17 20:37:25 +04:00
LARGE_INTEGER li ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
li . QuadPart = aDistance ;
li . LowPart = SetFilePointer ( aHandle , li . LowPart , & li . HighPart , aMoveMethod ) ;
if ( li . LowPart = = INVALID_SET_FILE_POINTER & & GetLastError ( ) ! = NO_ERROR )
{
li . QuadPart = - 1 ;
}
1999-12-08 02:31:25 +03:00
2004-06-17 20:37:25 +04:00
return li . QuadPart ;
1999-12-08 02:31:25 +03:00
}
2003-08-25 22:28:10 +04:00
static PRBool
2006-03-22 07:26:30 +03:00
IsShortcutPath ( const nsAString & path )
2004-06-17 20:37:25 +04:00
{
// Under Windows, the shortcuts are just files with a ".lnk" extension.
// Note also that we don't resolve links in the middle of paths.
// i.e. "c:\foo.lnk\bar.txt" is invalid.
2006-03-22 07:26:30 +03:00
NS_ABORT_IF_FALSE ( ! path . IsEmpty ( ) , " don't pass an empty string " ) ;
PRInt32 len = path . Length ( ) ;
return ( StringTail ( path , 4 ) . LowerCaseEqualsASCII ( " .lnk " ) ) ;
}
2006-03-26 19:34:40 +04:00
//-----------------------------------------------------------------------------
// We need the following three definitions to make |OpenFile| convert a file
// handle to an NSPR file descriptor correctly when |O_APPEND| flag is
// specified. It is defined in a private header of NSPR (primpl.h) we can't
// include. As a temporary workaround until we decide how to extend
// |PR_ImportFile|, we define it here. Currently, |_PR_HAVE_PEEK_BUFFER|
// and |PR_STRICT_ADDR_LEN| are not defined for the 'w95'-dependent portion
// of NSPR so that fields of |PRFilePrivate| #ifdef'd by them are not copied.
// Similarly, |_MDFileDesc| is taken from nsprpub/pr/include/md/_win95.h.
// In an unlikely case we switch to 'NT'-dependent NSPR AND this temporary
// workaround last beyond the switch, |PRFilePrivate| and |_MDFileDesc|
// need to be changed to match the definitions for WinNT.
//-----------------------------------------------------------------------------
typedef enum {
_PR_TRI_TRUE = 1 ,
_PR_TRI_FALSE = 0 ,
_PR_TRI_UNKNOWN = - 1
} _PRTriStateBool ;
struct _MDFileDesc {
PROsfd osfd ;
} ;
struct PRFilePrivate {
PRInt32 state ;
PRBool nonblocking ;
_PRTriStateBool inheritable ;
PRFileDesc * next ;
PRIntn lockCount ; /* 0: not locked
* - 1 : a native lockfile call is in progress
* > 0 : # times the file is locked */
PRBool appendMode ;
_MDFileDesc md ;
} ;
2006-03-22 07:26:30 +03:00
//-----------------------------------------------------------------------------
// Six static methods defined below (OpenFile, FileTimeToPRTime, GetFileInfo,
// OpenDir, CloseDir, ReadDir) should go away once the corresponding
2006-03-26 19:34:40 +04:00
// UTF-16 APIs are implemented on all the supported platforms (or at least
2006-03-22 07:26:30 +03:00
// Windows 9x/ME) in NSPR. Currently, they're only implemented on
// Windows NT4 or later. (bug 330665)
//-----------------------------------------------------------------------------
2006-03-26 19:34:40 +04:00
// copied from nsprpub/pr/src/{io/prfile.c | md/windows/w95io.c} :
// PR_Open and _PR_MD_OPEN
2006-03-22 07:26:30 +03:00
static nsresult
OpenFile ( const nsAFlatString & name , PRIntn osflags , PRIntn mode ,
PRFileDesc * * fd )
{
// XXX : 'mode' is not translated !!!
PRInt32 access = 0 ;
PRInt32 flags = 0 ;
PRInt32 flag6 = 0 ;
if ( osflags & PR_SYNC ) flag6 = FILE_FLAG_WRITE_THROUGH ;
if ( osflags & PR_RDONLY | | osflags & PR_RDWR )
access | = GENERIC_READ ;
if ( osflags & PR_WRONLY | | osflags & PR_RDWR )
access | = GENERIC_WRITE ;
if ( osflags & PR_CREATE_FILE & & osflags & PR_EXCL )
flags = CREATE_NEW ;
else if ( osflags & PR_CREATE_FILE ) {
if ( osflags & PR_TRUNCATE )
flags = CREATE_ALWAYS ;
else
flags = OPEN_ALWAYS ;
} else {
if ( osflags & PR_TRUNCATE )
flags = TRUNCATE_EXISTING ;
else
flags = OPEN_EXISTING ;
}
HANDLE file = nsWinAPIs : : mCreateFile ( name . get ( ) , access ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
NULL , flags , flag6 , NULL ) ;
if ( file = = INVALID_HANDLE_VALUE ) {
* fd = nsnull ;
return ConvertWinError ( GetLastError ( ) ) ;
}
* fd = PR_ImportFile ( ( PROsfd ) file ) ;
2006-03-26 19:34:40 +04:00
if ( * fd ) {
// On Windows, _PR_HAVE_O_APPEND is not defined so that we have to
// add it manually. (see |PR_Open| in nsprpub/pr/src/io/prfile.c)
( * fd ) - > secret - > appendMode = ( PR_APPEND & osflags ) ? PR_TRUE : PR_FALSE ;
2006-03-22 07:26:30 +03:00
return NS_OK ;
2006-03-26 19:34:40 +04:00
}
2006-03-22 07:26:30 +03:00
nsresult rv = NS_ErrorAccordingToNSPR ( ) ;
CloseHandle ( file ) ;
return rv ;
}
2006-03-26 19:34:40 +04:00
// copied from nsprpub/pr/src/{io/prfile.c | md/windows/w95io.c} :
// PR_FileTimeToPRTime and _PR_FileTimeToPRTime
2006-03-22 07:26:30 +03:00
static
void FileTimeToPRTime ( const FILETIME * filetime , PRTime * prtm )
{
# ifdef __GNUC__
const PRTime _pr_filetime_offset = 116444736000000000LL ;
# else
const PRTime _pr_filetime_offset = 116444736000000000 i64 ;
# endif
PR_ASSERT ( sizeof ( FILETIME ) = = sizeof ( PRTime ) ) ;
: : CopyMemory ( prtm , filetime , sizeof ( PRTime ) ) ;
# ifdef __GNUC__
* prtm = ( * prtm - _pr_filetime_offset ) / 10LL ;
# else
* prtm = ( * prtm - _pr_filetime_offset ) / 10 i64 ;
# endif
}
2006-03-26 19:34:40 +04:00
// copied from nsprpub/pr/src/{io/prfile.c | md/windows/w95io.c} with some
// changes : PR_GetFileInfo64, _PR_MD_GETFILEINFO64
2006-03-22 07:26:30 +03:00
static nsresult
GetFileInfo ( const nsAFlatString & name , PRFileInfo64 * info )
{
WIN32_FILE_ATTRIBUTE_DATA fileData ;
if ( name . IsEmpty ( ) | | name . FindCharInSet ( L " ?* " ) ! = kNotFound )
return NS_ERROR_INVALID_ARG ;
// GetFileAttributesExW/A were confirmed to work correctly
// with a filename ending with a slash and a root directory except on Win95
// without MS IE 4 or later (see |mGetFileAttributesEx| in nsWinAPIs.cpp.)
// Therefore, we don't need to add a fallback as done in
// _PR_MD_GETFILEINFO64 (w95io.c)
if ( ! nsWinAPIs : : mGetFileAttributesEx ( name . get ( ) , GetFileExInfoStandard ,
& fileData ) )
return ConvertWinError ( GetLastError ( ) ) ;
if ( fileData . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
info - > type = PR_FILE_DIRECTORY ;
} else {
info - > type = PR_FILE_FILE ;
}
info - > size = fileData . nFileSizeHigh ;
info - > size = ( info - > size < < 32 ) + fileData . nFileSizeLow ;
FileTimeToPRTime ( & fileData . ftLastWriteTime , & info - > modifyTime ) ;
if ( 0 = = fileData . ftCreationTime . dwLowDateTime & &
0 = = fileData . ftCreationTime . dwHighDateTime ) {
info - > creationTime = info - > modifyTime ;
} else {
FileTimeToPRTime ( & fileData . ftCreationTime , & info - > creationTime ) ;
}
return NS_OK ;
}
struct nsDir
{
HANDLE handle ;
union
{
WIN32_FIND_DATAW dataW ;
WIN32_FIND_DATAA dataA ;
} entry ;
PRBool firstEntry ;
} ;
static nsresult
OpenDir ( const nsAFlatString & name , nsDir * * dir )
{
NS_ENSURE_ARG_POINTER ( dir ) ;
* dir = nsnull ;
if ( name . Length ( ) + 3 > = MAX_PATH )
return NS_ERROR_FILE_NAME_TOO_LONG ;
nsDir * d = PR_NEW ( nsDir ) ;
if ( ! d )
return NS_ERROR_OUT_OF_MEMORY ;
nsAutoString filename ( name ) ;
//If 'name' ends in a slash or backslash, do not append
//another backslash.
if ( filename . Last ( ) = = L ' / ' | | filename . Last ( ) = = L ' \\ ' )
filename . AppendASCII ( " * " ) ;
else
filename . AppendASCII ( " \\ * " ) ;
filename . ReplaceChar ( L ' / ' , L ' \\ ' ) ;
if ( NS_UseUnicode ( ) )
d - > handle = : : FindFirstFileW ( filename . get ( ) , & ( d - > entry . dataW ) ) ;
else
{
nsCAutoString filenameA ;
NS_CopyUnicodeToNative ( filename , filenameA ) ;
d - > handle = : : FindFirstFileA ( filenameA . get ( ) , & ( d - > entry . dataA ) ) ;
}
if ( d - > handle = = INVALID_HANDLE_VALUE )
{
PR_Free ( d ) ;
return ConvertWinError ( GetLastError ( ) ) ;
}
d - > firstEntry = PR_TRUE ;
* dir = d ;
return NS_OK ;
}
static nsresult
ReadDir ( nsDir * dir , PRDirFlags flags , nsString & name )
{
name . Truncate ( ) ;
NS_ENSURE_ARG ( dir ) ;
while ( 1 ) {
BOOL rv ;
if ( dir - > firstEntry )
{
dir - > firstEntry = PR_FALSE ;
rv = 1 ;
} else
if ( NS_UseUnicode ( ) )
rv = : : FindNextFileW ( dir - > handle , & ( dir - > entry . dataW ) ) ;
else
rv = : : FindNextFileA ( dir - > handle , & ( dir - > entry . dataA ) ) ;
if ( rv = = 0 )
break ;
const PRUnichar * fileName ;
nsString tmp ;
if ( NS_UseUnicode ( ) )
fileName = ( dir ) - > entry . dataW . cFileName ;
else
{
NS_CopyNativeToUnicode ( nsDependentCString ( ( dir ) - >
entry . dataA . cFileName ) ,
tmp ) ;
fileName = tmp . get ( ) ;
}
if ( ( flags & PR_SKIP_DOT ) & &
( fileName [ 0 ] = = L ' . ' ) & & ( fileName [ 1 ] = = L ' \0 ' ) )
continue ;
if ( ( flags & PR_SKIP_DOT_DOT ) & &
( fileName [ 0 ] = = L ' . ' ) & & ( fileName [ 1 ] = = L ' . ' ) & &
( fileName [ 2 ] = = L ' \0 ' ) )
continue ;
// Perhaps, we can just get away with using entry.dataW.dwFileAttributes
// because dwFileAttributes is the first field of both WIN32_FIND_DATAW
// and WIN32_FIND_DATAA, but let's be on the safe side here.
DWORD attrib = NS_UseUnicode ( ) ? dir - > entry . dataW . dwFileAttributes :
dir - > entry . dataA . dwFileAttributes ;
if ( ( flags & PR_SKIP_HIDDEN ) & & ( attrib & FILE_ATTRIBUTE_HIDDEN ) )
continue ;
if ( fileName = = tmp . get ( ) )
name = tmp ;
else
name = fileName ;
return NS_OK ;
}
DWORD err = GetLastError ( ) ;
return err = = ERROR_NO_MORE_FILES ? NS_OK : ConvertWinError ( err ) ;
}
static nsresult
CloseDir ( nsDir * d )
{
NS_ENSURE_ARG ( d ) ;
BOOL isOk = FindClose ( d - > handle ) ;
PR_DELETE ( d ) ;
return isOk ? NS_OK : ConvertWinError ( GetLastError ( ) ) ;
2002-11-27 00:37:58 +03:00
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsDirEnumerator
//-----------------------------------------------------------------------------
2005-04-23 05:39:51 +04:00
class nsDirEnumerator : public nsISimpleEnumerator ,
public nsIDirectoryEnumerator
1999-12-04 04:13:44 +03:00
{
public :
NS_DECL_ISUPPORTS
2003-09-29 22:15:52 +04:00
nsDirEnumerator ( ) : mDir ( nsnull )
1999-12-04 04:13:44 +03:00
{
}
2003-09-29 22:15:52 +04:00
nsresult Init ( nsILocalFile * parent )
1999-12-04 04:13:44 +03:00
{
2006-03-22 07:26:30 +03:00
nsAutoString filepath ;
parent - > GetTarget ( filepath ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( filepath . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2006-03-22 07:26:30 +03:00
parent - > GetPath ( filepath ) ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( filepath . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
return NS_ERROR_UNEXPECTED ;
1999-12-04 04:13:44 +03:00
}
2006-03-22 07:26:30 +03:00
nsresult rv = OpenDir ( filepath , & mDir ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
mParent = parent ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHOD HasMoreElements ( PRBool * result )
1999-12-04 04:13:44 +03:00
{
nsresult rv ;
2003-09-29 22:15:52 +04:00
if ( mNext = = nsnull & & mDir )
1999-12-04 04:13:44 +03:00
{
2006-03-22 07:26:30 +03:00
nsString name ;
rv = ReadDir ( mDir , PR_SKIP_BOTH , name ) ;
if ( NS_FAILED ( rv ) )
return rv ;
if ( name . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
// end of dir entries
2006-03-22 07:26:30 +03:00
if ( NS_FAILED ( CloseDir ( mDir ) ) )
1999-12-04 04:13:44 +03:00
return NS_ERROR_FAILURE ;
2006-03-22 07:26:30 +03:00
1999-12-04 04:13:44 +03:00
mDir = nsnull ;
* result = PR_FALSE ;
return NS_OK ;
}
1999-12-22 04:56:45 +03:00
nsCOMPtr < nsIFile > file ;
2000-02-11 07:50:23 +03:00
rv = mParent - > Clone ( getter_AddRefs ( file ) ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
2000-02-11 07:50:23 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
rv = file - > Append ( name ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
2000-01-25 00:28:28 +03:00
// make sure the thing exists. If it does, try the next one.
PRBool exists ;
2002-04-27 09:33:09 +04:00
rv = file - > Exists ( & exists ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) | | ! exists )
2000-01-25 00:28:28 +03:00
{
2003-09-29 22:15:52 +04:00
return HasMoreElements ( result ) ;
2000-01-25 00:28:28 +03:00
}
2003-09-29 22:15:52 +04:00
1999-12-22 04:56:45 +03:00
mNext = do_QueryInterface ( file ) ;
1999-12-04 04:13:44 +03:00
}
* result = mNext ! = nsnull ;
2005-04-23 05:39:51 +04:00
if ( ! * result )
Close ( ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHOD GetNext ( nsISupports * * result )
1999-12-04 04:13:44 +03:00
{
nsresult rv ;
PRBool hasMore ;
rv = HasMoreElements ( & hasMore ) ;
if ( NS_FAILED ( rv ) ) return rv ;
* result = mNext ; // might return nsnull
NS_IF_ADDREF ( * result ) ;
2002-07-18 09:09:10 +04:00
2001-10-07 14:58:39 +04:00
mNext = nsnull ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2005-04-23 05:39:51 +04:00
NS_IMETHOD GetNextFile ( nsIFile * * result )
{
* result = nsnull ;
PRBool hasMore = PR_FALSE ;
nsresult rv = HasMoreElements ( & hasMore ) ;
if ( NS_FAILED ( rv ) | | ! hasMore )
return rv ;
* result = mNext ;
NS_IF_ADDREF ( * result ) ;
mNext = nsnull ;
return NS_OK ;
}
NS_IMETHOD Close ( )
1999-12-04 04:13:44 +03:00
{
2003-09-29 22:15:52 +04:00
if ( mDir )
1999-12-04 04:13:44 +03:00
{
2006-03-22 07:26:30 +03:00
nsresult rv = CloseDir ( mDir ) ;
NS_ASSERTION ( NS_SUCCEEDED ( rv ) , " close failed " ) ;
if ( NS_FAILED ( rv ) )
2005-04-23 05:39:51 +04:00
return NS_ERROR_FAILURE ;
mDir = nsnull ;
1999-12-04 04:13:44 +03:00
}
2005-04-23 05:39:51 +04:00
return NS_OK ;
}
// dtor can be non-virtual since there are no subclasses, but must be
// public to use the class on the stack.
~ nsDirEnumerator ( )
{
Close ( ) ;
1999-12-04 04:13:44 +03:00
}
protected :
2006-03-22 07:26:30 +03:00
nsDir * mDir ;
1999-12-04 04:13:44 +03:00
nsCOMPtr < nsILocalFile > mParent ;
nsCOMPtr < nsILocalFile > mNext ;
} ;
2005-04-23 05:39:51 +04:00
NS_IMPL_ISUPPORTS2 ( nsDirEnumerator , nsISimpleEnumerator , nsIDirectoryEnumerator )
1999-12-04 04:13:44 +03:00
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile <public>
//-----------------------------------------------------------------------------
1999-12-04 04:13:44 +03:00
nsLocalFile : : nsLocalFile ( )
2005-09-14 02:08:52 +04:00
: mDirty ( PR_TRUE )
, mFollowSymlinks ( PR_FALSE )
1999-12-04 04:13:44 +03:00
{
}
NS_METHOD
2000-01-25 00:28:28 +03:00
nsLocalFile : : nsLocalFileConstructor ( nsISupports * outer , const nsIID & aIID , void * * aInstancePtr )
1999-12-04 04:13:44 +03:00
{
NS_ENSURE_ARG_POINTER ( aInstancePtr ) ;
2000-01-25 00:28:28 +03:00
NS_ENSURE_NO_AGGREGATION ( outer ) ;
1999-12-04 04:13:44 +03:00
nsLocalFile * inst = new nsLocalFile ( ) ;
if ( inst = = NULL )
return NS_ERROR_OUT_OF_MEMORY ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
nsresult rv = inst - > QueryInterface ( aIID , aInstancePtr ) ;
if ( NS_FAILED ( rv ) )
{
delete inst ;
return rv ;
}
return NS_OK ;
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile::nsISupports
//-----------------------------------------------------------------------------
2005-11-18 23:12:46 +03:00
NS_IMPL_THREADSAFE_ISUPPORTS4 ( nsLocalFile ,
nsILocalFile ,
nsIFile ,
nsILocalFileWin ,
nsIHashable )
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile <private>
//-----------------------------------------------------------------------------
2003-07-19 02:14:16 +04:00
nsLocalFile : : nsLocalFile ( const nsLocalFile & other )
2005-09-14 02:08:52 +04:00
: mDirty ( PR_TRUE )
2003-07-19 02:14:16 +04:00
, mFollowSymlinks ( other . mFollowSymlinks )
, mWorkingPath ( other . mWorkingPath )
{
}
2004-06-17 20:37:25 +04:00
// Resolve the shortcut file from mWorkingPath and write the path
// it points to into mResolvedPath.
2003-09-29 22:15:52 +04:00
nsresult
2004-06-17 20:37:25 +04:00
nsLocalFile : : ResolveShortcut ( )
1999-12-04 04:13:44 +03:00
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2004-06-17 20:37:25 +04:00
// we can't do anything without the resolver
if ( ! gResolver )
return NS_ERROR_FAILURE ;
2001-04-13 03:56:28 +04:00
2004-06-17 20:37:25 +04:00
mResolvedPath . SetLength ( MAX_PATH ) ;
2006-03-22 07:26:30 +03:00
if ( mResolvedPath . Length ( ) ! = MAX_PATH )
return NS_ERROR_OUT_OF_MEMORY ;
PRUnichar * resolvedPath = mResolvedPath . BeginWriting ( ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// resolve this shortcut
2006-03-22 07:26:30 +03:00
nsresult rv = gResolver - > Resolve ( mWorkingPath . get ( ) , resolvedPath ) ;
1999-12-08 02:31:25 +03:00
2006-03-22 07:26:30 +03:00
size_t len = NS_FAILED ( rv ) ? 0 : wcslen ( resolvedPath ) ;
2004-06-17 20:37:25 +04:00
mResolvedPath . SetLength ( len ) ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return rv ;
2005-01-31 00:33:47 +03:00
# else
return NS_OK ;
# endif
1999-12-04 04:13:44 +03:00
}
2004-06-17 20:37:25 +04:00
// Resolve any shortcuts and stat the resolved path. After a successful return
// the path is guaranteed valid and the members of mFileInfo64 can be used.
1999-12-04 04:13:44 +03:00
nsresult
2004-06-17 20:37:25 +04:00
nsLocalFile : : ResolveAndStat ( )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
// if we aren't dirty then we are already done
if ( ! mDirty )
2000-01-25 00:28:28 +03:00
return NS_OK ;
2000-03-08 05:53:04 +03:00
2004-06-17 20:37:25 +04:00
// we can't resolve/stat anything that isn't a valid NSPR addressable path
if ( mWorkingPath . IsEmpty ( ) )
return NS_ERROR_FILE_INVALID_PATH ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// this is usually correct
mResolvedPath . Assign ( mWorkingPath ) ;
2003-09-29 22:15:52 +04:00
2004-06-25 21:27:24 +04:00
// slutty hack designed to work around bug 134796 until it is fixed
2006-03-22 07:26:30 +03:00
nsAutoString nsprPath ( mWorkingPath . get ( ) ) ;
if ( mWorkingPath . Length ( ) = = 2 & & mWorkingPath . CharAt ( 1 ) = = L ' : ' )
nsprPath . AppendASCII ( " \\ " ) ;
2004-06-25 21:27:24 +04:00
2004-06-17 20:37:25 +04:00
// first we will see if the working path exists. If it doesn't then
// there is nothing more that can be done
2006-03-22 07:26:30 +03:00
if ( NS_FAILED ( GetFileInfo ( nsprPath , & mFileInfo64 ) ) )
2004-06-17 20:37:25 +04:00
return NS_ERROR_FILE_NOT_FOUND ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// if this isn't a shortcut file or we aren't following symlinks then we're done
if ( ! mFollowSymlinks
| | mFileInfo64 . type ! = PR_FILE_FILE
2006-03-22 07:26:30 +03:00
| | ! IsShortcutPath ( mWorkingPath ) )
2004-06-17 20:37:25 +04:00
{
mDirty = PR_FALSE ;
return NS_OK ;
2000-01-25 00:28:28 +03:00
}
2004-06-17 20:37:25 +04:00
// we need to resolve this shortcut to what it points to, this will
// set mResolvedPath. Even if it fails we need to have the resolved
// path equal to working path for those functions that always use
// the resolved path.
nsresult rv = ResolveShortcut ( ) ;
if ( NS_FAILED ( rv ) )
{
mResolvedPath . Assign ( mWorkingPath ) ;
return rv ;
}
2000-01-25 00:28:28 +03:00
2004-06-17 20:37:25 +04:00
// get the details of the resolved path
2006-03-22 07:26:30 +03:00
if ( NS_FAILED ( GetFileInfo ( mResolvedPath , & mFileInfo64 ) ) )
2004-06-17 20:37:25 +04:00
return NS_ERROR_FILE_NOT_FOUND ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
mDirty = PR_FALSE ;
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile::nsIFile,nsILocalFile
//-----------------------------------------------------------------------------
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-22 04:56:45 +03:00
nsLocalFile : : Clone ( nsIFile * * file )
1999-12-04 04:13:44 +03:00
{
2002-02-06 23:40:40 +03:00
// Just copy-construct ourselves
2003-07-19 02:14:16 +04:00
* file = new nsLocalFile ( * this ) ;
if ( ! * file )
return NS_ERROR_OUT_OF_MEMORY ;
1999-12-04 04:13:44 +03:00
2002-02-06 23:40:40 +03:00
NS_ADDREF ( * file ) ;
2003-07-19 02:14:16 +04:00
2002-02-06 23:40:40 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : InitWithFile ( nsILocalFile * aFile )
{
NS_ENSURE_ARG ( aFile ) ;
nsAutoString path ;
aFile - > GetPath ( path ) ;
if ( path . IsEmpty ( ) )
return NS_ERROR_INVALID_ARG ;
return InitWithPath ( path ) ;
}
NS_IMETHODIMP
nsLocalFile : : InitWithPath ( const nsAString & filePath )
1999-12-04 04:13:44 +03:00
{
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAString : : const_iterator begin , end ;
2002-04-27 09:33:09 +04:00
filePath . BeginReading ( begin ) ;
filePath . EndReading ( end ) ;
// input string must not be empty
if ( begin = = end )
return NS_ERROR_FAILURE ;
2006-03-22 07:26:30 +03:00
PRUnichar firstChar = * begin ;
PRUnichar secondChar = * ( + + begin ) ;
2002-04-27 09:33:09 +04:00
1999-12-04 04:13:44 +03:00
// just do a sanity check. if it has any forward slashes, it is not a Native path
// on windows. Also, it must have a colon at after the first char.
2002-04-27 09:33:09 +04:00
2006-03-22 07:26:30 +03:00
PRUnichar * path = nsnull ;
2002-04-27 09:33:09 +04:00
PRInt32 pathLen = 0 ;
2006-03-22 07:26:30 +03:00
if ( ( ( secondChar = = L ' : ' ) & & ! FindCharInReadable ( L ' / ' , begin , end ) ) | | // normal path
2005-01-31 00:33:47 +03:00
# ifdef WINCE
2006-03-22 07:26:30 +03:00
( ( firstChar = = L ' \\ ' ) ) // wince absolute path or network path
2005-01-31 00:33:47 +03:00
# else
2006-03-22 07:26:30 +03:00
( ( firstChar = = L ' \\ ' ) & & ( secondChar = = L ' \\ ' ) ) // network path
2005-01-31 00:33:47 +03:00
# endif
)
1999-12-04 04:13:44 +03:00
{
// This is a native path
2006-03-22 07:26:30 +03:00
path = ToNewUnicode ( filePath ) ;
2002-04-27 09:33:09 +04:00
pathLen = filePath . Length ( ) ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
2005-01-31 00:33:47 +03:00
if ( path = = nsnull ) {
1999-12-04 04:13:44 +03:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2005-01-31 00:33:47 +03:00
}
1999-12-04 04:13:44 +03:00
2006-03-22 07:26:30 +03:00
// kill any trailing '\'
2002-04-27 09:33:09 +04:00
PRInt32 len = pathLen - 1 ;
2006-03-22 07:26:30 +03:00
if ( path [ len ] = = L ' \\ ' )
2002-04-27 09:33:09 +04:00
{
2006-03-22 07:26:30 +03:00
path [ len ] = L ' \0 ' ;
2002-04-27 09:33:09 +04:00
pathLen = len ;
}
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
mWorkingPath . Adopt ( path , pathLen ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
2006-03-22 07:26:30 +03:00
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-01-25 00:28:28 +03:00
nsLocalFile : : OpenNSPRFileDesc ( PRInt32 flags , PRInt32 mode , PRFileDesc * * _retval )
1999-12-22 04:56:45 +03:00
{
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-22 04:56:45 +03:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
2003-09-29 22:15:52 +04:00
return rv ;
2006-03-22 07:26:30 +03:00
return OpenFile ( mResolvedPath , flags , mode , _retval ) ;
2000-01-25 00:28:28 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-01-25 00:28:28 +03:00
nsLocalFile : : OpenANSIFileDesc ( const char * mode , FILE * * _retval )
{
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
2000-01-25 00:28:28 +03:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
2003-09-29 22:15:52 +04:00
return rv ;
2006-03-22 07:26:30 +03:00
* _retval = nsWinAPIs : : mFopen ( mResolvedPath . get ( ) ,
NS_ConvertASCIItoUTF16 ( mode ) . get ( ) ) ;
1999-12-22 04:56:45 +03:00
if ( * _retval )
return NS_OK ;
return NS_ERROR_FAILURE ;
}
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : Create ( PRUint32 type , PRUint32 attributes )
2003-09-29 22:15:52 +04:00
{
1999-12-04 04:13:44 +03:00
if ( type ! = NORMAL_FILE_TYPE & & type ! = DIRECTORY_TYPE )
return NS_ERROR_FILE_UNKNOWN_TYPE ;
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
2003-09-29 22:15:52 +04:00
return rv ;
2003-05-15 01:56:49 +04:00
// create directories to target
//
// A given local file can be either one of these forms:
//
// - normal: X:\some\path\on\this\drive
// ^--- start here
//
// - UNC path: \\machine\volume\some\path\on\this\drive
// ^--- start here
//
// Skip the first 'X:\' for the first form, and skip the first full
// '\\machine\volume\' segment for the second form.
2006-03-22 07:26:30 +03:00
PRUnichar * path = mResolvedPath . BeginWriting ( ) ;
2005-01-31 00:33:47 +03:00
2006-03-22 07:26:30 +03:00
if ( path [ 0 ] = = L ' \\ ' & & path [ 1 ] = = L ' \\ ' )
2003-05-15 01:56:49 +04:00
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
+ + path ;
# else
2003-05-15 01:56:49 +04:00
// dealing with a UNC path here; skip past '\\machine\'
2006-03-22 07:26:30 +03:00
path = wcschr ( path + 2 , L ' \\ ' ) ;
2003-05-15 01:56:49 +04:00
if ( ! path )
return NS_ERROR_FILE_INVALID_PATH ;
+ + path ;
2005-01-31 00:33:47 +03:00
# endif
2003-05-15 01:56:49 +04:00
}
// search for first slash after the drive (or volume) name
2006-03-22 07:26:30 +03:00
PRUnichar * slash = wcschr ( path , L ' \\ ' ) ;
1999-12-04 04:13:44 +03:00
2002-01-08 05:20:13 +03:00
if ( slash )
1999-12-04 04:13:44 +03:00
{
2002-01-08 05:20:13 +03:00
// skip the first '\\'
1999-12-04 04:13:44 +03:00
+ + slash ;
2006-03-22 07:26:30 +03:00
slash = wcschr ( slash , L ' \\ ' ) ;
2003-09-29 22:15:52 +04:00
2002-01-08 05:20:13 +03:00
while ( slash )
{
2006-03-22 07:26:30 +03:00
* slash = L ' \0 ' ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
if ( ! nsWinAPIs : : mCreateDirectory ( mResolvedPath . get ( ) , NULL ) ) {
2002-04-27 09:33:09 +04:00
rv = ConvertWinError ( GetLastError ( ) ) ;
2003-05-15 01:56:49 +04:00
// perhaps the base path already exists, or perhaps we don't have
// permissions to create the directory. NOTE: access denied could
// occur on a parent directory even though it exists.
if ( rv ! = NS_ERROR_FILE_ALREADY_EXISTS & &
rv ! = NS_ERROR_FILE_ACCESS_DENIED )
return rv ;
2002-04-27 09:33:09 +04:00
}
2006-03-22 07:26:30 +03:00
* slash = L ' \\ ' ;
2002-04-27 09:33:09 +04:00
+ + slash ;
2006-03-22 07:26:30 +03:00
slash = wcschr ( slash , L ' \\ ' ) ;
2002-01-08 05:20:13 +03:00
}
1999-12-04 04:13:44 +03:00
}
if ( type = = NORMAL_FILE_TYPE )
{
2006-03-22 07:26:30 +03:00
PRFileDesc * file ;
OpenFile ( mResolvedPath ,
PR_RDONLY | PR_CREATE_FILE | PR_APPEND | PR_EXCL , attributes ,
& file ) ;
2000-06-24 05:50:53 +04:00
if ( ! file ) return NS_ERROR_FILE_ALREADY_EXISTS ;
PR_Close ( file ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
if ( type = = DIRECTORY_TYPE )
{
2006-03-22 07:26:30 +03:00
if ( ! nsWinAPIs : : mCreateDirectory ( mResolvedPath . get ( ) , NULL ) )
2000-06-24 05:50:53 +04:00
return ConvertWinError ( GetLastError ( ) ) ;
2003-09-29 22:15:52 +04:00
else
2000-06-24 05:50:53 +04:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
return NS_ERROR_FILE_UNKNOWN_TYPE ;
}
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : Append ( const nsAString & node )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
// append this path, multiple components are not permitted
2006-03-22 07:26:30 +03:00
return AppendInternal ( PromiseFlatString ( node ) , PR_FALSE ) ;
2000-05-05 09:47:32 +04:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : AppendRelativePath ( const nsAString & node )
2000-05-05 09:47:32 +04:00
{
2004-06-17 20:37:25 +04:00
// append this path, multiple components are permitted
2006-03-22 07:26:30 +03:00
return AppendInternal ( PromiseFlatString ( node ) , PR_TRUE ) ;
2004-06-17 20:37:25 +04:00
}
2006-03-22 07:26:30 +03:00
2004-06-17 20:37:25 +04:00
nsresult
2006-03-22 07:26:30 +03:00
nsLocalFile : : AppendInternal ( const nsAFlatString & node , PRBool multipleComponents )
2004-06-17 20:37:25 +04:00
{
if ( node . IsEmpty ( ) )
return NS_OK ;
// check the relative path for validity
2006-03-22 07:26:30 +03:00
if ( node . First ( ) = = L ' \\ ' // can't start with an '\'
2006-03-29 21:14:07 +04:00
| | node . FindChar ( L ' / ' ) ! = kNotFound // can't contain /
2006-03-22 07:26:30 +03:00
| | node . EqualsASCII ( " .. " ) ) // can't be ..
2000-01-25 00:28:28 +03:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2004-06-17 20:37:25 +04:00
2005-01-31 00:33:47 +03:00
# ifndef WINCE // who cares?
2004-06-17 20:37:25 +04:00
if ( multipleComponents )
{
2006-03-22 07:26:30 +03:00
// can't contain .. as a path component. Ensure that the valid components
// "foo..foo", "..foo", and "foo.." are not falsely detected,
// but the invalid paths "..\", "foo\..", "foo\..\foo",
// "..\foo", etc are.
NS_NAMED_LITERAL_STRING ( doubleDot , " \\ .. " ) ;
nsAString : : const_iterator start , end , offset ;
node . BeginReading ( start ) ;
node . EndReading ( end ) ;
offset = end ;
while ( FindInReadable ( doubleDot , start , offset ) )
2004-06-17 20:37:25 +04:00
{
2006-03-22 07:26:30 +03:00
if ( offset = = end | | * offset = = L ' \\ ' )
2004-06-17 20:37:25 +04:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2006-03-22 07:26:30 +03:00
start = offset ;
offset = end ;
2004-06-17 20:37:25 +04:00
}
2006-03-22 07:26:30 +03:00
// catches the remaining cases of prefixes
if ( StringBeginsWith ( node , NS_LITERAL_STRING ( " .. \\ " ) ) )
2004-06-17 20:37:25 +04:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
1999-12-04 04:13:44 +03:00
}
2006-03-22 07:26:30 +03:00
// single components can't contain '\'
else if ( node . FindChar ( L ' \\ ' ) ! = kNotFound )
2004-06-17 20:37:25 +04:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2005-01-31 00:33:47 +03:00
# endif
2004-06-17 20:37:25 +04:00
2000-01-25 00:28:28 +03:00
MakeDirty ( ) ;
2004-06-17 20:37:25 +04:00
2006-03-22 07:26:30 +03:00
mWorkingPath . Append ( NS_LITERAL_STRING ( " \\ " ) + node ) ;
2004-06-17 20:37:25 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2006-03-22 07:26:30 +03:00
# define TOUPPER(u) (((u) >= L'a' && (u) <= L'z') ? \
( u ) - ( L ' a ' - L ' A ' ) : ( u ) )
1999-12-04 04:13:44 +03:00
NS_IMETHODIMP
nsLocalFile : : Normalize ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2004-07-29 19:08:25 +04:00
// XXX See bug 187957 comment 18 for possible problems with this implementation.
if ( mWorkingPath . IsEmpty ( ) )
return NS_OK ;
2006-03-22 07:26:30 +03:00
nsAutoString path ( mWorkingPath ) ;
2004-07-29 19:08:25 +04:00
// find the index of the root backslash for the path. Everything before
// this is considered fully normalized and cannot be ascended beyond
// using ".." For a local drive this is the first slash (e.g. "c:\").
// For a UNC path it is the slash following the share name
// (e.g. "\\server\share\").
PRInt32 rootIdx = 2 ; // default to local drive
2006-03-22 07:26:30 +03:00
if ( path . First ( ) = = L ' \\ ' ) // if a share then calculate the rootIdx
2004-07-29 19:08:25 +04:00
{
2006-03-22 07:26:30 +03:00
rootIdx = path . FindChar ( L ' \\ ' , 2 ) ; // skip \\ in front of the server
2004-07-29 19:08:25 +04:00
if ( rootIdx = = kNotFound )
return NS_OK ; // already normalized
2006-03-22 07:26:30 +03:00
rootIdx = path . FindChar ( L ' \\ ' , rootIdx + 1 ) ;
2004-07-29 19:08:25 +04:00
if ( rootIdx = = kNotFound )
return NS_OK ; // already normalized
}
2006-03-22 07:26:30 +03:00
else if ( path . CharAt ( rootIdx ) ! = L ' \\ ' )
2004-07-29 19:08:25 +04:00
{
// The path has been specified relative to the current working directory
// for that drive. To normalize it, the current working directory for
// that drive needs to be inserted before the supplied relative path
// which will provide an absolute path (and the rootIdx will still be 2).
2006-03-22 07:26:30 +03:00
WCHAR cwd [ MAX_PATH ] ;
WCHAR * pcwd = cwd ;
int drive = TOUPPER ( path . First ( ) ) - ' A ' + 1 ;
if ( ! nsWinAPIs : : mGetDCwd ( drive , pcwd , MAX_PATH ) )
pcwd = nsWinAPIs : : mGetDCwd ( drive , 0 , 0 ) ;
2004-07-29 19:08:25 +04:00
if ( ! pcwd )
return NS_ERROR_OUT_OF_MEMORY ;
2006-03-22 07:26:30 +03:00
nsAutoString currentDir ( pcwd ) ;
2004-07-29 19:08:25 +04:00
if ( pcwd ! = cwd )
free ( pcwd ) ;
if ( currentDir . Last ( ) = = ' \\ ' )
path . Replace ( 0 , 2 , currentDir ) ;
else
path . Replace ( 0 , 2 , currentDir + NS_LITERAL_STRING ( " \\ " ) ) ;
}
NS_POSTCONDITION ( 0 < rootIdx & & rootIdx < ( PRInt32 ) path . Length ( ) , " rootIdx is invalid " ) ;
NS_POSTCONDITION ( path . CharAt ( rootIdx ) = = ' \\ ' , " rootIdx is invalid " ) ;
// if there is nothing following the root path then it is already normalized
if ( rootIdx + 1 = = ( PRInt32 ) path . Length ( ) )
return NS_OK ;
// assign the root
const PRUnichar * pathBuffer = path . get ( ) ; // simplify access to the buffer
2006-03-22 07:26:30 +03:00
mWorkingPath . SetCapacity ( path . Length ( ) ) ; // it won't ever grow longer
mWorkingPath . Assign ( pathBuffer , rootIdx ) ;
2004-07-29 19:08:25 +04:00
// Normalize the path components. The actions taken are:
//
// "\\" condense to single backslash
// "." remove from path
// ".." up a directory
// "..." remove from path (any number of dots > 2)
//
// The last form is something that Windows 95 and 98 supported and
// is a shortcut for changing up multiple directories. Windows XP
// and ilk ignore it in a path, as is done here.
PRInt32 len , begin , end = rootIdx ;
while ( end < ( PRInt32 ) path . Length ( ) )
{
// find the current segment (text between the backslashes) to
// be examined, this will set the following variables:
// begin == index of first char in segment
// end == index 1 char after last char in segment
// len == length of segment
begin = end + 1 ;
end = path . FindChar ( ' \\ ' , begin ) ;
if ( end = = kNotFound )
end = path . Length ( ) ;
len = end - begin ;
// ignore double backslashes
if ( len = = 0 )
continue ;
// len != 0, and interesting paths always begin with a dot
if ( pathBuffer [ begin ] = = ' . ' )
{
// ignore single dots
if ( len = = 1 )
continue ;
// handle multiple dots
2006-03-22 07:26:30 +03:00
if ( len > = 2 & & pathBuffer [ begin + 1 ] = = L ' . ' )
2004-07-29 19:08:25 +04:00
{
// back up a path component on double dot
if ( len = = 2 )
{
2006-03-22 07:26:30 +03:00
PRInt32 prev = mWorkingPath . RFindChar ( ' \\ ' ) ;
2004-07-29 19:08:25 +04:00
if ( prev > = rootIdx )
2006-03-22 07:26:30 +03:00
mWorkingPath . Truncate ( prev ) ;
2004-07-29 19:08:25 +04:00
continue ;
}
// length is > 2 and the first two characters are dots.
// if the rest of the string is dots, then ignore it.
int idx = len - 1 ;
for ( ; idx > = 2 ; - - idx )
{
2006-03-22 07:26:30 +03:00
if ( pathBuffer [ begin + idx ] ! = L ' . ' )
2004-07-29 19:08:25 +04:00
break ;
}
// this is true if the loop above didn't break
// and all characters in this segment are dots.
if ( idx < 2 )
continue ;
}
}
// add the current component to the path, including the preceding backslash
2006-03-22 07:26:30 +03:00
mWorkingPath . Append ( pathBuffer + begin - 1 , len + 1 ) ;
2004-07-29 19:08:25 +04:00
}
2005-02-12 01:11:45 +03:00
// kill trailing dots and spaces.
2006-03-22 07:26:30 +03:00
PRInt32 filePathLen = mWorkingPath . Length ( ) - 1 ;
while ( filePathLen > 0 & & ( mWorkingPath [ filePathLen ] = = L ' ' | |
mWorkingPath [ filePathLen ] = = L ' . ' ) )
2005-02-12 01:11:45 +03:00
{
2006-03-22 07:26:30 +03:00
mWorkingPath . Truncate ( filePathLen - - ) ;
2005-02-12 01:11:45 +03:00
}
2004-07-29 19:08:25 +04:00
MakeDirty ( ) ;
2005-01-31 00:33:47 +03:00
# else // WINCE
// WINCE FIX
# endif
1999-12-08 02:31:25 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : GetLeafName ( nsAString & aLeafName )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
aLeafName . Truncate ( ) ;
1999-12-04 04:13:44 +03:00
2006-03-22 07:26:30 +03:00
if ( mWorkingPath . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2006-03-22 07:26:30 +03:00
PRInt32 offset = mWorkingPath . RFindChar ( L ' \\ ' ) ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
// if the working path is just a node without any lashes.
2006-03-22 07:26:30 +03:00
if ( offset = = kNotFound )
aLeafName = mWorkingPath ;
1999-12-04 04:13:44 +03:00
else
2006-03-22 07:26:30 +03:00
aLeafName = Substring ( mWorkingPath , offset + 1 ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : SetLeafName ( const nsAString & aLeafName )
2000-01-25 00:28:28 +03:00
{
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
if ( mWorkingPath . IsEmpty ( ) )
2000-01-25 00:28:28 +03:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2000-04-26 07:57:34 +04:00
// cannot use nsCString::RFindChar() due to 0x5c problem
2006-03-22 07:26:30 +03:00
PRInt32 offset = mWorkingPath . RFindChar ( L ' \\ ' ) ;
2000-01-25 00:28:28 +03:00
if ( offset )
{
mWorkingPath . Truncate ( offset + 1 ) ;
}
mWorkingPath . Append ( aLeafName ) ;
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : GetPath ( nsAString & _retval )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
_retval = mWorkingPath ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : GetCanonicalPath ( nsAString & aResult )
{
EnsureShortPath ( ) ;
aResult . Assign ( mShortWorkingPath ) ;
return NS_OK ;
}
2005-02-25 12:00:45 +03:00
typedef struct {
WORD wLanguage ;
WORD wCodePage ;
} LANGANDCODEPAGE ;
NS_IMETHODIMP
nsLocalFile : : GetVersionInfoField ( const char * aField , nsAString & _retval )
{
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
rv = NS_ERROR_FAILURE ;
// Cast away const-ness here because WinAPI functions don't understand it,
// the path is used for [in] parameters only however so it's safe.
2006-03-22 07:26:30 +03:00
WCHAR * path = NS_CONST_CAST ( WCHAR * , mFollowSymlinks ? mResolvedPath . get ( )
: mWorkingPath . get ( ) ) ;
2005-02-25 12:00:45 +03:00
// Per http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/versioninformation/versioninformationreference/versioninformationfunctions/getfileversioninfosize.asp
// if the "short" version of this file name is > 125 characters,
// GetFileVersionInfoSize will not work (for Win9x compatibility)
2006-03-22 07:26:30 +03:00
WCHAR shortPath [ 126 ] ;
nsWinAPIs : : mGetShortPathName ( path , shortPath , sizeof ( shortPath ) ) ;
2005-02-25 12:00:45 +03:00
DWORD dummy ;
2006-03-22 07:26:30 +03:00
DWORD size = nsWinAPIs : : mGetFileVersionInfoSize ( shortPath , & dummy ) ;
2005-02-25 12:00:45 +03:00
if ( ! size )
return rv ;
void * ver = calloc ( size , 1 ) ;
if ( ! ver )
return NS_ERROR_OUT_OF_MEMORY ;
2006-03-22 07:26:30 +03:00
if ( nsWinAPIs : : mGetFileVersionInfo ( path , 0 , size , ver ) )
2005-02-25 12:00:45 +03:00
{
LANGANDCODEPAGE * translate = nsnull ;
UINT pageCount ;
2006-09-15 05:52:09 +04:00
BOOL queryResult = : : VerQueryValue ( ver , " \\ VarFileInfo \\ Translation " ,
2005-02-25 12:00:45 +03:00
( void * * ) & translate , & pageCount ) ;
if ( queryResult & & translate )
{
for ( PRInt32 i = 0 ; i < 2 ; + + i )
{
2006-09-15 05:52:09 +04:00
// XXX : need to make sure that we can get away with
// 'VerQueryValueA' here.
char subBlock [ MAX_PATH ] ;
PR_snprintf ( subBlock , sizeof ( subBlock ) ,
" \\ StringFileInfo \\ %04x%04x \\ %s " ,
( i = = 0 ? translate [ 0 ] . wLanguage
: : : GetUserDefaultLangID ( ) ) ,
translate [ 0 ] . wCodePage , aField ) ;
2005-02-25 12:00:45 +03:00
LPVOID value = nsnull ;
UINT size ;
2006-09-15 05:52:09 +04:00
queryResult = : : VerQueryValueA ( ver , subBlock , & value , & size ) ;
2005-02-25 12:00:45 +03:00
if ( queryResult & & value )
{
2006-09-15 05:52:09 +04:00
NS_ASSERTION ( nsCRT : : IsAscii ( ( const char * ) value ) ,
" Version string has non-ASCII characters " ) ;
CopyASCIItoUTF16 ( nsDependentCString ( ( const char * ) value ) ,
_retval ) ;
2005-02-25 12:00:45 +03:00
if ( ! _retval . IsEmpty ( ) )
{
rv = NS_OK ;
break ;
}
}
}
}
}
free ( ver ) ;
return rv ;
}
2006-03-22 07:26:30 +03:00
1999-12-04 04:13:44 +03:00
nsresult
2006-03-22 07:26:30 +03:00
nsLocalFile : : CopySingleFile ( nsIFile * sourceFile , nsIFile * destParent ,
const nsAString & newName ,
2004-06-17 20:37:25 +04:00
PRBool followSymlinks , PRBool move )
1999-12-04 04:13:44 +03:00
{
nsresult rv ;
2006-03-22 07:26:30 +03:00
nsAutoString filePath ;
1999-12-04 04:13:44 +03:00
// get the path that we are going to copy to.
// Since windows does not know how to auto
2004-06-17 20:37:25 +04:00
// resolve shortcuts, we must work with the
1999-12-04 04:13:44 +03:00
// target.
2006-03-22 07:26:30 +03:00
nsAutoString destPath ;
destParent - > GetTarget ( destPath ) ;
1999-12-04 04:13:44 +03:00
2006-03-22 07:26:30 +03:00
destPath . AppendASCII ( " \\ " ) ;
1999-12-04 04:13:44 +03:00
2002-04-27 09:33:09 +04:00
if ( newName . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2006-03-22 07:26:30 +03:00
nsAutoString aFileName ;
sourceFile - > GetLeafName ( aFileName ) ;
1999-12-04 04:13:44 +03:00
destPath . Append ( aFileName ) ;
}
else
{
destPath . Append ( newName ) ;
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
if ( followSymlinks )
{
2006-03-22 07:26:30 +03:00
rv = sourceFile - > GetTarget ( filePath ) ;
2002-04-27 09:33:09 +04:00
if ( filePath . IsEmpty ( ) )
2006-03-22 07:26:30 +03:00
rv = sourceFile - > GetPath ( filePath ) ;
1999-12-04 04:13:44 +03:00
}
else
{
2006-03-22 07:26:30 +03:00
rv = sourceFile - > GetPath ( filePath ) ;
1999-12-04 04:13:44 +03:00
}
if ( NS_FAILED ( rv ) )
return rv ;
int copyOK ;
if ( ! move )
2006-03-22 07:26:30 +03:00
copyOK = nsWinAPIs : : mCopyFile ( filePath . get ( ) , destPath . get ( ) , PR_TRUE ) ;
2003-09-29 22:15:52 +04:00
else
2002-11-13 17:04:51 +03:00
{
2003-09-29 22:15:52 +04:00
// What we have to do is check to see if the destPath exists. If it
// does, we have to move it out of the say so that MoveFile will
// succeed. However, we don't want to just remove it since MoveFile
2002-11-13 17:04:51 +03:00
// can fail leaving us without a file.
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString backup ;
2002-11-13 17:04:51 +03:00
PRFileInfo64 fileInfo64 ;
2006-03-22 07:26:30 +03:00
if ( NS_SUCCEEDED ( GetFileInfo ( destPath , & fileInfo64 ) ) )
2002-11-13 17:04:51 +03:00
{
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
// the file exists. Check to make sure it is not a directory,
// then move it out of the way.
if ( fileInfo64 . type = = PR_FILE_FILE )
{
backup . Append ( destPath ) ;
2006-03-22 07:26:30 +03:00
backup . Append ( L " .moztmp " ) ;
2002-11-13 17:04:51 +03:00
// remove any existing backup file that we may already have.
2003-09-29 22:15:52 +04:00
// maybe we should be doing some kind of unique naming here,
2002-11-13 17:04:51 +03:00
// but why bother.
2006-03-22 07:26:30 +03:00
nsWinAPIs : : mRemove ( backup . get ( ) ) ;
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
// move destination file to backup file
2006-03-22 07:26:30 +03:00
copyOK = nsWinAPIs : : mMoveFile ( destPath . get ( ) , backup . get ( ) ) ;
2002-11-13 17:04:51 +03:00
if ( ! copyOK )
{
// I guess we can't do the backup copy, so return.
rv = ConvertWinError ( GetLastError ( ) ) ;
return rv ;
}
}
}
// move source file to destination file
2006-03-22 07:26:30 +03:00
copyOK = nsWinAPIs : : mMoveFile ( filePath . get ( ) , destPath . get ( ) ) ;
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
if ( ! backup . IsEmpty ( ) )
{
2003-09-29 22:15:52 +04:00
if ( copyOK )
2002-11-13 17:04:51 +03:00
{
// remove the backup copy.
2006-03-22 07:26:30 +03:00
nsWinAPIs : : mRemove ( backup . get ( ) ) ;
2002-11-13 17:04:51 +03:00
}
else
{
// restore backup
2006-03-22 07:26:30 +03:00
int backupOk = nsWinAPIs : : mMoveFile ( backup . get ( ) ,
destPath . get ( ) ) ;
2002-11-13 17:04:51 +03:00
NS_ASSERTION ( backupOk , " move backup failed " ) ;
}
}
2003-09-29 22:15:52 +04:00
}
1999-12-04 04:13:44 +03:00
if ( ! copyOK ) // CopyFile and MoveFile returns non-zero if succeeds (backward if you ask me).
rv = ConvertWinError ( GetLastError ( ) ) ;
return rv ;
}
nsresult
2006-03-22 07:26:30 +03:00
nsLocalFile : : CopyMove ( nsIFile * aParentDir , const nsAString & newName , PRBool followSymlinks , PRBool move )
1999-12-04 04:13:44 +03:00
{
2000-03-24 08:47:39 +03:00
nsCOMPtr < nsIFile > newParentDir = aParentDir ;
1999-12-04 04:13:44 +03:00
// check to see if this exists, otherwise return an error.
// we will check this by resolving. If the user wants us
// to follow links, then we are talking about the target,
// hence we can use the |followSymlinks| parameter.
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2000-03-24 08:47:39 +03:00
if ( ! newParentDir )
{
// no parent was specified. We must rename.
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( newName . IsEmpty ( ) )
2000-03-24 08:47:39 +03:00
return NS_ERROR_INVALID_ARG ;
rv = GetParent ( getter_AddRefs ( newParentDir ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
}
if ( ! newParentDir )
return NS_ERROR_FILE_DESTINATION_NOT_DIR ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
// make sure it exists and is a directory. Create it if not there.
PRBool exists ;
newParentDir - > Exists ( & exists ) ;
2002-11-13 17:04:51 +03:00
if ( ! exists )
1999-12-04 04:13:44 +03:00
{
rv = newParentDir - > Create ( DIRECTORY_TYPE , 0644 ) ; // TODO, what permissions should we use
if ( NS_FAILED ( rv ) )
return rv ;
}
else
{
PRBool isDir ;
newParentDir - > IsDirectory ( & isDir ) ;
if ( isDir = = PR_FALSE )
{
if ( followSymlinks )
{
PRBool isLink ;
newParentDir - > IsSymlink ( & isLink ) ;
if ( isLink )
{
2006-03-22 07:26:30 +03:00
nsAutoString target ;
newParentDir - > GetTarget ( target ) ;
1999-12-04 04:13:44 +03:00
2000-01-25 00:28:28 +03:00
nsCOMPtr < nsILocalFile > realDest = new nsLocalFile ( ) ;
if ( realDest = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
1999-12-04 04:13:44 +03:00
2006-03-22 07:26:30 +03:00
rv = realDest - > InitWithPath ( target ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return CopyMove ( realDest , newName , followSymlinks , move ) ;
}
}
else
2003-09-29 22:15:52 +04:00
{
1999-12-04 04:13:44 +03:00
return NS_ERROR_FILE_DESTINATION_NOT_DIR ;
}
2000-03-24 08:47:39 +03:00
}
1999-12-04 04:13:44 +03:00
}
2005-04-27 08:38:21 +04:00
// Try different ways to move/copy files/directories
PRBool done = PR_FALSE ;
1999-12-04 04:13:44 +03:00
PRBool isDir ;
IsDirectory ( & isDir ) ;
1999-12-08 05:07:38 +03:00
PRBool isSymlink ;
IsSymlink ( & isSymlink ) ;
2005-04-27 08:38:21 +04:00
// Try to move the file or directory, or try to copy a single file (or non-followed symlink)
if ( move | | ! isDir | | ( isSymlink & & ! followSymlinks ) )
1999-12-04 04:13:44 +03:00
{
2005-04-27 08:38:21 +04:00
// Copy/Move single file, or move a directory
1999-12-04 04:13:44 +03:00
rv = CopySingleFile ( this , newParentDir , newName , followSymlinks , move ) ;
2005-04-27 08:38:21 +04:00
done = NS_SUCCEEDED ( rv ) ;
// If we are moving a directory and that fails, fallback on directory
// enumeration. See bug 231300 for details.
if ( ! done & & ! ( move & & isDir ) )
return rv ;
1999-12-04 04:13:44 +03:00
}
2005-04-27 08:38:21 +04:00
// Not able to copy or move directly, so enumerate it
if ( ! done )
1999-12-04 04:13:44 +03:00
{
// create a new target destination in the new parentDir;
1999-12-22 04:56:45 +03:00
nsCOMPtr < nsIFile > target ;
rv = newParentDir - > Clone ( getter_AddRefs ( target ) ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString allocatedNewName ;
2002-04-27 09:33:09 +04:00
if ( newName . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
1999-12-08 02:31:25 +03:00
PRBool isLink ;
IsSymlink ( & isLink ) ;
if ( isLink )
{
2006-03-22 07:26:30 +03:00
nsAutoString temp ;
GetTarget ( temp ) ;
PRInt32 offset = temp . RFindChar ( L ' \\ ' ) ;
if ( offset = = kNotFound )
allocatedNewName = temp ;
else
allocatedNewName = Substring ( temp , offset + 1 ) ;
1999-12-08 02:31:25 +03:00
}
else
{
2006-03-22 07:26:30 +03:00
GetLeafName ( allocatedNewName ) ; // this should be the leaf name of the
1999-12-08 02:31:25 +03:00
}
1999-12-04 04:13:44 +03:00
}
else
{
2002-04-27 09:33:09 +04:00
allocatedNewName = newName ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
rv = target - > Append ( allocatedNewName ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2002-04-27 09:33:09 +04:00
allocatedNewName . Truncate ( ) ;
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
// check if the destination directory already exists
target - > Exists ( & exists ) ;
if ( ! exists )
{
// if the destination directory cannot be created, return an error
rv = target - > Create ( DIRECTORY_TYPE , 0644 ) ; // TODO, what permissions should we use
if ( NS_FAILED ( rv ) )
return rv ;
}
else
{
// check if the destination directory is writable and empty
PRBool isWritable ;
target - > IsWritable ( & isWritable ) ;
if ( ! isWritable )
return NS_ERROR_FILE_ACCESS_DENIED ;
nsCOMPtr < nsISimpleEnumerator > targetIterator ;
rv = target - > GetDirectoryEntries ( getter_AddRefs ( targetIterator ) ) ;
PRBool more ;
targetIterator - > HasMoreElements ( & more ) ;
// return error if target directory is not empty
if ( more )
return NS_ERROR_FILE_DIR_NOT_EMPTY ;
}
1999-12-04 04:13:44 +03:00
2003-08-25 22:28:10 +04:00
nsDirEnumerator dirEnum ;
rv = dirEnum . Init ( this ) ;
2002-06-04 22:47:37 +04:00
if ( NS_FAILED ( rv ) ) {
2006-02-23 12:36:43 +03:00
NS_WARNING ( " dirEnum initialization failed " ) ;
2002-06-04 22:47:37 +04:00
return rv ;
}
1999-12-04 04:13:44 +03:00
PRBool more ;
2003-08-25 22:28:10 +04:00
while ( NS_SUCCEEDED ( dirEnum . HasMoreElements ( & more ) ) & & more )
1999-12-04 04:13:44 +03:00
{
nsCOMPtr < nsISupports > item ;
nsCOMPtr < nsIFile > file ;
2003-08-25 22:28:10 +04:00
dirEnum . GetNext ( getter_AddRefs ( item ) ) ;
1999-12-04 04:13:44 +03:00
file = do_QueryInterface ( item ) ;
2002-07-18 09:09:10 +04:00
if ( file )
2003-09-29 22:15:52 +04:00
{
2002-07-18 09:09:10 +04:00
PRBool isDir , isLink ;
2003-09-29 22:15:52 +04:00
2002-07-18 09:09:10 +04:00
file - > IsDirectory ( & isDir ) ;
file - > IsSymlink ( & isLink ) ;
2003-09-29 22:15:52 +04:00
2002-07-18 09:09:10 +04:00
if ( move )
{
if ( followSymlinks )
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
rv = file - > MoveTo ( target , EmptyString ( ) ) ;
2002-07-18 09:09:10 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
1999-12-04 04:13:44 +03:00
else
2003-09-29 22:15:52 +04:00
{
2002-07-18 09:09:10 +04:00
if ( followSymlinks )
2006-03-22 07:26:30 +03:00
rv = file - > CopyToFollowingLinks ( target , EmptyString ( ) ) ;
2002-07-18 09:09:10 +04:00
else
2006-03-22 07:26:30 +03:00
rv = file - > CopyTo ( target , EmptyString ( ) ) ;
2002-07-18 09:09:10 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
1999-12-04 04:13:44 +03:00
}
}
2002-04-25 22:56:04 +04:00
// we've finished moving all the children of this directory
// in the new directory. so now delete the directory
// note, we don't need to do a recursive delete.
// MoveTo() is recursive. At this point,
2003-09-29 22:15:52 +04:00
// we've already moved the children of the current folder
2002-04-25 22:56:04 +04:00
// to the new location. nothing should be left in the folder.
if ( move )
2002-06-04 22:47:37 +04:00
{
2002-04-25 22:56:04 +04:00
rv = Remove ( PR_FALSE /* recursive */ ) ;
2002-06-04 22:47:37 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
// If we moved, we want to adjust this.
if ( move )
{
1999-12-22 04:56:45 +03:00
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString newParentPath ;
newParentDir - > GetPath ( newParentPath ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( newParentPath . IsEmpty ( ) )
1999-12-22 04:56:45 +03:00
return NS_ERROR_FAILURE ;
2002-04-27 09:33:09 +04:00
if ( newName . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2006-03-22 07:26:30 +03:00
nsAutoString aFileName ;
GetLeafName ( aFileName ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
InitWithPath ( newParentPath ) ;
Append ( aFileName ) ;
1999-12-04 04:13:44 +03:00
}
else
{
2006-03-22 07:26:30 +03:00
InitWithPath ( newParentPath ) ;
Append ( newName ) ;
1999-12-04 04:13:44 +03:00
}
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : CopyTo ( nsIFile * newParentDir , const nsAString & newName )
1999-12-04 04:13:44 +03:00
{
return CopyMove ( newParentDir , newName , PR_FALSE , PR_FALSE ) ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : CopyToFollowingLinks ( nsIFile * newParentDir , const nsAString & newName )
1999-12-04 04:13:44 +03:00
{
2006-03-24 10:30:22 +03:00
return CopyMove ( newParentDir , newName , PR_TRUE , PR_FALSE ) ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : MoveTo ( nsIFile * newParentDir , const nsAString & newName )
1999-12-04 04:13:44 +03:00
{
return CopyMove ( newParentDir , newName , PR_FALSE , PR_TRUE ) ;
}
2006-03-22 07:26:30 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-22 07:11:13 +03:00
nsLocalFile : : Load ( PRLibrary * * _retval )
1999-12-22 06:01:08 +03:00
{
PRBool isFile ;
nsresult rv = IsFile ( & isFile ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
1999-12-22 06:01:08 +03:00
if ( ! isFile )
return NS_ERROR_FILE_IS_DIRECTORY ;
2006-03-22 07:26:30 +03:00
NS_TIMELINE_START_TIMER ( " PR_LoadLibraryWithFlags " ) ;
PRLibSpec libSpec ;
libSpec . value . pathname_u = mResolvedPath . get ( ) ;
libSpec . type = PR_LibSpec_PathnameU ;
* _retval = PR_LoadLibraryWithFlags ( libSpec , 0 ) ;
NS_TIMELINE_STOP_TIMER ( " PR_LoadLibraryWithFlags " ) ;
NS_TIMELINE_MARK_TIMER1 ( " PR_LoadLibraryWithFlags " ,
NS_ConvertUTF16toUTF8 ( mResolvedPath ) . get ( ) ) ;
2001-11-17 23:23:48 +03:00
1999-12-22 06:01:08 +03:00
if ( * _retval )
return NS_OK ;
return NS_ERROR_NULL_POINTER ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-07-24 22:38:25 +04:00
nsLocalFile : : Remove ( PRBool recursive )
1999-12-04 04:13:44 +03:00
{
2003-08-25 22:28:10 +04:00
// NOTE:
//
// if the working path points to a shortcut, then we will only
// delete the shortcut itself. even if the shortcut points to
// a directory, we will not recurse into that directory or
// delete that directory itself. likewise, if the shortcut
// points to a normal file, we will not delete the real file.
// this is done to be consistent with the other platforms that
// behave this way. we do this even if the followLinks attribute
// is set to true. this helps protect against misuse that could
// lead to security bugs (e.g., bug 210588).
//
2004-06-17 20:37:25 +04:00
// Since shortcut files are no longer permitted to be used as unix-like
// symlinks interspersed in the path (e.g. "c:/file.lnk/foo/bar.txt")
// this processing is a lot simpler. Even if the shortcut file is
// pointing to a directory, only the mWorkingPath value is used and so
// only the shortcut file will be deleted.
2003-08-25 22:28:10 +04:00
2004-06-17 20:37:25 +04:00
PRBool isDir , isLink ;
nsresult rv ;
isDir = PR_FALSE ;
rv = IsSymlink ( & isLink ) ;
if ( NS_FAILED ( rv ) )
return rv ;
// only check to see if we have a directory if it isn't a link
if ( ! isLink )
2003-08-25 22:28:10 +04:00
{
rv = IsDirectory ( & isDir ) ;
if ( NS_FAILED ( rv ) )
return rv ;
}
1999-12-04 04:13:44 +03:00
if ( isDir )
{
if ( recursive )
{
2003-08-25 22:28:10 +04:00
nsDirEnumerator dirEnum ;
rv = dirEnum . Init ( this ) ;
if ( NS_FAILED ( rv ) )
return rv ;
1999-12-04 04:13:44 +03:00
PRBool more ;
2003-08-25 22:28:10 +04:00
while ( NS_SUCCEEDED ( dirEnum . HasMoreElements ( & more ) ) & & more )
1999-12-04 04:13:44 +03:00
{
nsCOMPtr < nsISupports > item ;
2003-08-25 22:28:10 +04:00
dirEnum . GetNext ( getter_AddRefs ( item ) ) ;
nsCOMPtr < nsIFile > file = do_QueryInterface ( item ) ;
2002-07-18 09:09:10 +04:00
if ( file )
file - > Remove ( recursive ) ;
1999-12-04 04:13:44 +03:00
}
}
2006-03-22 07:26:30 +03:00
rv = nsWinAPIs : : mRmdir ( mWorkingPath . get ( ) ) ;
1999-12-04 04:13:44 +03:00
}
else
{
2006-03-22 07:26:30 +03:00
rv = nsWinAPIs : : mRemove ( mWorkingPath . get ( ) ) ;
1999-12-04 04:13:44 +03:00
}
2003-08-25 22:28:10 +04:00
// fixup error code if necessary...
2004-04-13 23:30:51 +04:00
if ( rv = = ( nsresult ) - 1 )
2003-08-25 22:28:10 +04:00
rv = NSRESULT_FOR_ERRNO ( ) ;
1999-12-04 04:13:44 +03:00
2000-01-25 00:28:28 +03:00
MakeDirty ( ) ;
2002-01-26 03:38:37 +03:00
return rv ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : GetLastModifiedTime ( PRInt64 * aLastModifiedTime )
1999-12-04 04:13:44 +03:00
{
2001-11-26 11:05:05 +03:00
NS_ENSURE_ARG ( aLastModifiedTime ) ;
2004-06-17 20:37:25 +04:00
// get the modified time of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as GetLastModifiedTimeOfLink)
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2000-05-09 23:11:14 +04:00
// microseconds -> milliseconds
2004-06-17 20:37:25 +04:00
PRInt64 usecPerMsec ;
LL_I2L ( usecPerMsec , PR_USEC_PER_MSEC ) ;
LL_DIV ( * aLastModifiedTime , mFileInfo64 . modifyTime , usecPerMsec ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : GetLastModifiedTimeOfLink ( PRInt64 * aLastModifiedTime )
1999-12-04 04:13:44 +03:00
{
2001-11-26 11:05:05 +03:00
NS_ENSURE_ARG ( aLastModifiedTime ) ;
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
PRFileInfo64 info ;
2006-03-22 07:26:30 +03:00
nsresult rv = GetFileInfo ( mWorkingPath , & info ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2000-05-09 23:11:14 +04:00
// microseconds -> milliseconds
2004-06-17 20:37:25 +04:00
PRInt64 usecPerMsec ;
LL_I2L ( usecPerMsec , PR_USEC_PER_MSEC ) ;
LL_DIV ( * aLastModifiedTime , info . modifyTime , usecPerMsec ) ;
2000-02-22 00:51:47 +03:00
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : SetLastModifiedTime ( PRInt64 aLastModifiedTime )
2000-02-22 00:51:47 +03:00
{
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
// set the modified time of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as SetLastModifiedTimeOfLink)
rv = SetModDate ( aLastModifiedTime , mResolvedPath . get ( ) ) ;
if ( NS_SUCCEEDED ( rv ) )
MakeDirty ( ) ;
return rv ;
1999-12-04 04:13:44 +03:00
}
2000-02-22 00:51:47 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : SetLastModifiedTimeOfLink ( PRInt64 aLastModifiedTime )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = SetModDate ( aLastModifiedTime , mWorkingPath . get ( ) ) ;
if ( NS_SUCCEEDED ( rv ) )
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
return rv ;
}
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult
2006-03-22 07:26:30 +03:00
nsLocalFile : : SetModDate ( PRInt64 aLastModifiedTime , const PRUnichar * filePath )
{
HANDLE file = nsWinAPIs : : mCreateFile ( filePath , // pointer to name of the file
GENERIC_WRITE , // access (write) mode
0 , // share mode
NULL , // pointer to security attributes
OPEN_EXISTING , // how to create
0 , // file attributes
NULL ) ;
2005-01-31 00:33:47 +03:00
2004-06-17 20:37:25 +04:00
if ( file = = INVALID_HANDLE_VALUE )
1999-12-04 04:13:44 +03:00
{
2000-03-22 04:37:52 +03:00
return ConvertWinError ( GetLastError ( ) ) ;
1999-12-04 04:13:44 +03:00
}
2000-03-28 07:39:02 +04:00
FILETIME lft , ft ;
SYSTEMTIME st ;
PRExplodedTime pret ;
2003-09-29 22:15:52 +04:00
2000-05-09 23:11:14 +04:00
// PR_ExplodeTime expects usecs...
2001-11-26 11:05:05 +03:00
PR_ExplodeTime ( aLastModifiedTime * PR_USEC_PER_MSEC , PR_LocalTimeParameters , & pret ) ;
2003-09-29 22:15:52 +04:00
st . wYear = pret . tm_year ;
2000-03-28 07:39:02 +04:00
st . wMonth = pret . tm_month + 1 ; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
2003-09-29 22:15:52 +04:00
st . wDayOfWeek = pret . tm_wday ;
st . wDay = pret . tm_mday ;
2000-03-28 07:39:02 +04:00
st . wHour = pret . tm_hour ;
2003-09-29 22:15:52 +04:00
st . wMinute = pret . tm_min ;
2000-03-28 07:39:02 +04:00
st . wSecond = pret . tm_sec ;
st . wMilliseconds = pret . tm_usec / 1000 ;
2004-06-17 20:37:25 +04:00
nsresult rv = NS_OK ;
2006-04-11 03:43:12 +04:00
// if at least one of these fails...
2006-04-10 22:29:41 +04:00
if ( ! ( SystemTimeToFileTime ( & st , & lft ) ! = 0 & &
LocalFileTimeToFileTime ( & lft , & ft ) ! = 0 & &
SetFileTime ( file , NULL , & ft , & ft ) ! = 0 ) )
1999-12-04 04:13:44 +03:00
{
2006-04-10 22:29:41 +04:00
rv = ConvertWinError ( GetLastError ( ) ) ;
1999-12-04 04:13:44 +03:00
}
2000-03-28 07:39:02 +04:00
2004-06-17 20:37:25 +04:00
CloseHandle ( file ) ;
2000-03-22 04:37:52 +03:00
return rv ;
2000-02-22 00:51:47 +03:00
}
2000-03-28 07:39:02 +04:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetPermissions ( PRUint32 * aPermissions )
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( aPermissions ) ;
// get the permissions of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as GetPermissionsOfLink)
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
PRBool isWritable , isExecutable ;
IsWritable ( & isWritable ) ;
IsExecutable ( & isExecutable ) ;
* aPermissions = PR_IRUSR | PR_IRGRP | PR_IROTH ; // all read
if ( isWritable )
* aPermissions | = PR_IWUSR | PR_IWGRP | PR_IWOTH ; // all write
if ( isExecutable )
* aPermissions | = PR_IXUSR | PR_IXGRP | PR_IXOTH ; // all execute
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2004-06-17 20:37:25 +04:00
nsLocalFile : : GetPermissionsOfLink ( PRUint32 * aPermissions )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( aPermissions ) ;
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link. It is not
// possible for a link file to be executable.
2006-03-22 07:26:30 +03:00
DWORD word = nsWinAPIs : : mGetFileAttributes ( mWorkingPath . get ( ) ) ;
2004-06-17 20:37:25 +04:00
if ( word = = INVALID_FILE_ATTRIBUTES )
return NS_ERROR_FILE_INVALID_PATH ;
PRBool isWritable = ! ( word & FILE_ATTRIBUTE_READONLY ) ;
* aPermissions = PR_IRUSR | PR_IRGRP | PR_IROTH ; // all read
if ( isWritable )
* aPermissions | = PR_IWUSR | PR_IWGRP | PR_IWOTH ; // all write
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : SetPermissions ( PRUint32 aPermissions )
{
2004-06-17 20:37:25 +04:00
// set the permissions of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as SetPermissionsOfLink)
nsresult rv = ResolveAndStat ( ) ;
2000-02-22 00:51:47 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// windows only knows about the following permissions
int mode = 0 ;
if ( aPermissions & ( PR_IRUSR | PR_IRGRP | PR_IROTH ) ) // any read
mode | = _S_IREAD ;
if ( aPermissions & ( PR_IWUSR | PR_IWGRP | PR_IWOTH ) ) // any write
mode | = _S_IWRITE ;
2006-03-22 07:26:30 +03:00
if ( nsWinAPIs : : mChmod ( mResolvedPath . get ( ) , mode ) = = - 1 )
2000-02-22 00:51:47 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
2000-02-22 00:51:47 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : SetPermissionsOfLink ( PRUint32 aPermissions )
{
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// windows only knows about the following permissions
int mode = 0 ;
if ( aPermissions & ( PR_IRUSR | PR_IRGRP | PR_IROTH ) ) // any read
mode | = _S_IREAD ;
if ( aPermissions & ( PR_IWUSR | PR_IWGRP | PR_IWOTH ) ) // any write
mode | = _S_IWRITE ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
if ( nsWinAPIs : : mChmod ( mWorkingPath . get ( ) , mode ) = = - 1 )
2000-02-22 00:51:47 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
2000-02-22 00:51:47 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetFileSize ( PRInt64 * aFileSize )
{
NS_ENSURE_ARG ( aFileSize ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2000-02-22 00:51:47 +03:00
* aFileSize = mFileInfo64 . size ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2004-06-17 20:37:25 +04:00
nsLocalFile : : GetFileSizeOfLink ( PRInt64 * aFileSize )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( aFileSize ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
PRFileInfo64 info ;
2006-03-22 07:26:30 +03:00
if ( NS_FAILED ( GetFileInfo ( mWorkingPath , & info ) ) )
2004-06-17 20:37:25 +04:00
return NS_ERROR_FILE_INVALID_PATH ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
* aFileSize = info . size ;
return NS_OK ;
}
NS_IMETHODIMP
nsLocalFile : : SetFileSize ( PRInt64 aFileSize )
{
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
HANDLE hFile = nsWinAPIs : : mCreateFile ( mResolvedPath . get ( ) , // pointer to name of the file
GENERIC_WRITE , // access (write) mode
FILE_SHARE_READ , // share mode
NULL , // pointer to security attributes
OPEN_EXISTING , // how to create
FILE_ATTRIBUTE_NORMAL , // file attributes
NULL ) ;
1999-12-04 04:13:44 +03:00
if ( hFile = = INVALID_HANDLE_VALUE )
2000-01-25 00:28:28 +03:00
{
2004-06-17 20:37:25 +04:00
return ConvertWinError ( GetLastError ( ) ) ;
2000-01-25 00:28:28 +03:00
}
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// seek the file pointer to the new, desired end of file
// and then truncate the file at that position
rv = NS_ERROR_FAILURE ;
aFileSize = MyFileSeek64 ( hFile , aFileSize , FILE_BEGIN ) ;
if ( aFileSize ! = - 1 & & SetEndOfFile ( hFile ) )
{
MakeDirty ( ) ;
rv = NS_OK ;
}
1999-12-04 04:13:44 +03:00
CloseHandle ( hFile ) ;
2004-06-17 20:37:25 +04:00
return rv ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetDiskSpaceAvailable ( PRInt64 * aDiskSpaceAvailable )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
1999-12-04 04:13:44 +03:00
NS_ENSURE_ARG ( aDiskSpaceAvailable ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
ResolveAndStat ( ) ;
2006-03-22 07:26:30 +03:00
ULARGE_INTEGER liFreeBytesAvailableToCaller , liTotalNumberOfBytes ;
if ( nsWinAPIs : : mGetDiskFreeSpaceEx ( mResolvedPath . get ( ) ,
& liFreeBytesAvailableToCaller ,
& liTotalNumberOfBytes ,
NULL ) )
1999-12-04 04:13:44 +03:00
{
2006-03-22 07:26:30 +03:00
* aDiskSpaceAvailable = liFreeBytesAvailableToCaller . QuadPart ;
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2004-06-17 20:37:25 +04:00
// use the old method of getting available disk space
2006-03-22 07:26:30 +03:00
WCHAR aDrive [ _MAX_DRIVE + 2 ] ;
_wsplitpath ( mResolvedPath . get ( ) , aDrive , NULL , NULL , NULL ) ;
wcscat ( aDrive , L " \\ " ) ;
2004-06-17 20:37:25 +04:00
DWORD dwSecPerClus , dwBytesPerSec , dwFreeClus , dwTotalClus ;
2005-01-31 00:33:47 +03:00
2006-03-22 07:26:30 +03:00
if ( nsWinAPIs : : mGetDiskFreeSpace ( aDrive , & dwSecPerClus , & dwBytesPerSec ,
& dwFreeClus , & dwTotalClus ) )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
__int64 bytes = dwFreeClus ;
bytes * = dwSecPerClus ;
bytes * = dwBytesPerSec ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
* aDiskSpaceAvailable = bytes ;
return NS_OK ;
2002-02-07 17:46:10 +03:00
}
2006-03-22 07:26:30 +03:00
2005-01-31 00:33:47 +03:00
# endif
// WINCE FIX
* aDiskSpaceAvailable = 0 ;
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetParent ( nsIFile * * aParent )
{
NS_ENSURE_ARG_POINTER ( aParent ) ;
2006-03-22 07:26:30 +03:00
nsAutoString parentPath ( mWorkingPath ) ;
1999-12-04 04:13:44 +03:00
2006-03-22 07:26:30 +03:00
PRInt32 offset = parentPath . RFindChar ( PRUnichar ( ' \\ ' ) ) ;
2004-05-20 21:46:35 +04:00
// adding this offset check that was removed in bug 241708 fixes mail
// directories that aren't relative to/underneath the profile dir.
// e.g., on a different drive. Before you remove them, please make
// sure local mail directories that aren't underneath the profile dir work.
2006-03-22 07:26:30 +03:00
if ( offset = = kNotFound )
2004-05-20 21:46:35 +04:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2006-03-22 07:26:30 +03:00
if ( offset = = 1 & & parentPath [ 0 ] = = L ' \\ ' ) {
2005-06-29 21:25:24 +04:00
* aParent = nsnull ;
2004-04-29 12:16:50 +04:00
return NS_OK ;
}
if ( offset > 0 )
parentPath . Truncate ( offset ) ;
else
2004-06-17 04:13:25 +04:00
parentPath . AssignLiteral ( " \\ \\ . " ) ;
1999-12-04 04:13:44 +03:00
2000-01-25 00:28:28 +03:00
nsCOMPtr < nsILocalFile > localFile ;
2006-03-22 07:26:30 +03:00
nsresult rv = NS_NewLocalFile ( parentPath , mFollowSymlinks , getter_AddRefs ( localFile ) ) ;
2003-09-29 22:15:52 +04:00
2000-01-25 00:28:28 +03:00
if ( NS_SUCCEEDED ( rv ) & & localFile )
{
2002-04-27 09:33:09 +04:00
return CallQueryInterface ( localFile , aParent ) ;
2000-01-25 00:28:28 +03:00
}
return rv ;
1999-12-04 04:13:44 +03:00
}
2000-01-25 00:28:28 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : Exists ( PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
2004-06-17 20:37:25 +04:00
* _retval = PR_FALSE ;
2000-01-25 00:28:28 +03:00
2000-04-25 06:39:42 +04:00
MakeDirty ( ) ;
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
* _retval = NS_SUCCEEDED ( rv ) ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2004-07-30 03:25:32 +04:00
nsLocalFile : : IsWritable ( PRBool * aIsWritable )
1999-12-04 04:13:44 +03:00
{
2004-07-30 03:25:32 +04:00
//TODO: extend to support NTFS file permissions
// The read-only attribute on a FAT directory only means that it can't
// be deleted. It is still possible to modify the contents of the directory.
nsresult rv = IsDirectory ( aIsWritable ) ;
if ( NS_FAILED ( rv ) )
return rv ;
if ( * aIsWritable )
return NS_OK ;
// writable if the file doesn't have the readonly attribute
rv = HasFileAttribute ( FILE_ATTRIBUTE_READONLY , aIsWritable ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
2003-09-29 22:15:52 +04:00
return rv ;
2004-07-30 03:25:32 +04:00
* aIsWritable = ! * aIsWritable ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsReadable ( PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
* _retval = PR_FALSE ;
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
* _retval = PR_TRUE ;
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsExecutable ( PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
* _retval = PR_FALSE ;
2004-06-17 20:37:25 +04:00
nsresult rv ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
// only files can be executables
PRBool isFile ;
rv = IsFile ( & isFile ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2004-06-17 20:37:25 +04:00
if ( ! isFile )
return NS_OK ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
//TODO: shouldn't we be checking mFollowSymlinks here?
1999-12-04 04:13:44 +03:00
PRBool symLink ;
rv = IsSymlink ( & symLink ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString path ;
1999-12-04 04:13:44 +03:00
if ( symLink )
2006-03-22 07:26:30 +03:00
GetTarget ( path ) ;
1999-12-04 04:13:44 +03:00
else
2006-03-22 07:26:30 +03:00
GetPath ( path ) ;
1999-12-04 04:13:44 +03:00
2005-02-12 02:13:38 +03:00
// kill trailing dots and spaces.
PRInt32 filePathLen = path . Length ( ) - 1 ;
2006-03-22 07:26:30 +03:00
while ( filePathLen > 0 & & ( path [ filePathLen ] = = L ' ' | | path [ filePathLen ] = = L ' . ' ) )
2005-02-12 02:13:38 +03:00
{
path . Truncate ( filePathLen - - ) ;
}
2001-05-23 10:03:59 +04:00
// Get extension.
2006-03-22 07:26:30 +03:00
PRInt32 dotIdx = path . RFindChar ( PRUnichar ( ' . ' ) ) ;
if ( dotIdx ! = kNotFound ) {
2001-05-23 10:03:59 +04:00
// Convert extension to lower case.
2006-03-22 07:26:30 +03:00
PRUnichar * p = path . BeginWriting ( ) ;
for ( p + = dotIdx + 1 ; * p ; p + + )
* p + = ( * p > = L ' A ' & & * p < = L ' Z ' ) ? ' a ' - ' A ' : 0 ;
2005-01-31 00:33:47 +03:00
2001-05-23 10:03:59 +04:00
// Search for any of the set of executable extensions.
2004-05-11 07:36:01 +04:00
const char * const executableExts [ ] = {
2006-03-22 07:26:30 +03:00
" ad " ,
" adp " ,
" asp " ,
" bas " ,
" bat " ,
" chm " ,
" cmd " ,
" com " ,
" cpl " ,
" crt " ,
" exe " ,
" hlp " ,
" hta " ,
" inf " ,
" ins " ,
" isp " ,
" js " ,
" jse " ,
" lnk " ,
" mdb " ,
" mde " ,
" msc " ,
" msi " ,
" msp " ,
" mst " ,
" pcd " ,
" pif " ,
" reg " ,
" scr " ,
" sct " ,
" shb " ,
" shs " ,
" url " ,
" vb " ,
" vbe " ,
" vbs " ,
" vsd " ,
" vss " ,
" vst " ,
" vsw " ,
" ws " ,
" wsc " ,
" wsf " ,
" wsh " ,
2004-05-11 07:36:01 +04:00
0 } ;
2001-05-23 10:03:59 +04:00
for ( int i = 0 ; executableExts [ i ] ; i + + ) {
2006-03-22 07:26:30 +03:00
if ( Substring ( path , dotIdx + 1 ) . EqualsASCII ( executableExts [ i ] ) ) {
2001-05-23 10:03:59 +04:00
// Found a match. Set result and quit.
* _retval = PR_TRUE ;
break ;
}
}
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsDirectory ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( _retval ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2000-02-22 00:51:47 +03:00
* _retval = ( mFileInfo64 . type = = PR_FILE_DIRECTORY ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsFile ( PRBool * _retval )
{
2000-02-22 00:51:47 +03:00
NS_ENSURE_ARG ( _retval ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
2000-02-22 00:51:47 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
* _retval = ( mFileInfo64 . type = = PR_FILE_FILE ) ;
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsHidden ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
return HasFileAttribute ( FILE_ATTRIBUTE_HIDDEN , _retval ) ;
}
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
nsresult
nsLocalFile : : HasFileAttribute ( DWORD fileAttrib , PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2002-11-27 00:37:58 +03:00
2004-06-17 20:37:25 +04:00
// get the file attributes for the correct item depending on following symlinks
2006-03-22 07:26:30 +03:00
const PRUnichar * filePath = mFollowSymlinks ?
mResolvedPath . get ( ) : mWorkingPath . get ( ) ;
DWORD word = nsWinAPIs : : mGetFileAttributes ( filePath ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
* _retval = ( ( word & fileAttrib ) ! = 0 ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsSymlink ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( _retval ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
// unless it is a valid shortcut path it's not a symlink
2006-03-22 07:26:30 +03:00
if ( ! IsShortcutPath ( mWorkingPath ) )
2004-06-17 20:37:25 +04:00
{
2003-08-25 22:28:10 +04:00
* _retval = PR_FALSE ;
2004-06-17 20:37:25 +04:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2004-06-17 20:37:25 +04:00
// we need to know if this is a file or directory
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
// it's only a shortcut if it is a file
* _retval = ( mFileInfo64 . type = = PR_FILE_FILE ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsSpecial ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
return HasFileAttribute ( FILE_ATTRIBUTE_SYSTEM , _retval ) ;
1999-12-04 04:13:44 +03:00
}
NS_IMETHODIMP
nsLocalFile : : Equals ( nsIFile * inFile , PRBool * _retval )
{
NS_ENSURE_ARG ( inFile ) ;
NS_ENSURE_ARG ( _retval ) ;
2006-01-10 23:33:54 +03:00
EnsureShortPath ( ) ;
2003-09-29 22:15:52 +04:00
2006-01-10 23:33:54 +03:00
nsCOMPtr < nsILocalFileWin > lf ( do_QueryInterface ( inFile ) ) ;
if ( ! lf ) {
* _retval = PR_FALSE ;
return NS_OK ;
}
2005-07-23 18:00:07 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString inFilePath ;
lf - > GetCanonicalPath ( inFilePath ) ;
2005-07-23 18:00:07 +04:00
2006-03-22 07:26:30 +03:00
// Ok : Win9x
* _retval = _wcsicmp ( mShortWorkingPath . get ( ) , inFilePath . get ( ) ) = = 0 ;
2005-07-23 18:00:07 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2006-03-22 07:26:30 +03:00
1999-12-04 04:13:44 +03:00
NS_IMETHODIMP
2000-01-29 02:53:59 +03:00
nsLocalFile : : Contains ( nsIFile * inFile , PRBool recur , PRBool * _retval )
1999-12-04 04:13:44 +03:00
{
2000-01-29 02:53:59 +03:00
* _retval = PR_FALSE ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString myFilePath ;
if ( NS_FAILED ( GetTarget ( myFilePath ) ) )
GetPath ( myFilePath ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
PRUint32 myFilePathLen = myFilePath . Length ( ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString inFilePath ;
if ( NS_FAILED ( inFile - > GetTarget ( inFilePath ) ) )
inFile - > GetPath ( inFilePath ) ;
2000-01-29 03:00:21 +03:00
2006-03-22 07:26:30 +03:00
// make sure that the |inFile|'s path has a trailing separator.
if ( inFilePath . Length ( ) > = myFilePathLen & & inFilePath [ myFilePathLen ] = = L ' \\ ' )
1999-12-08 02:31:25 +03:00
{
2006-03-22 07:26:30 +03:00
if ( _wcsnicmp ( myFilePath . get ( ) , inFilePath . get ( ) , myFilePathLen ) = = 0 )
1999-12-08 02:31:25 +03:00
{
2000-01-25 00:28:28 +03:00
* _retval = PR_TRUE ;
1999-12-08 02:31:25 +03:00
}
}
2000-01-25 00:28:28 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : GetTarget ( nsAString & _retval )
2003-09-29 22:15:52 +04:00
{
2002-04-27 09:33:09 +04:00
_retval . Truncate ( ) ;
2003-09-29 22:15:52 +04:00
# if STRICT_FAKE_SYMLINKS
1999-12-04 04:13:44 +03:00
PRBool symLink ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
nsresult rv = IsSymlink ( & symLink ) ;
if ( NS_FAILED ( rv ) )
return rv ;
if ( ! symLink )
{
return NS_ERROR_FILE_INVALID_PATH ;
}
1999-12-08 02:31:25 +03:00
# endif
2004-06-17 20:37:25 +04:00
ResolveAndStat ( ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
_retval = mResolvedPath ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2000-07-13 03:31:31 +04:00
/* attribute PRBool followLinks; */
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-07-13 03:31:31 +04:00
nsLocalFile : : GetFollowLinks ( PRBool * aFollowLinks )
{
* aFollowLinks = mFollowSymlinks ;
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-07-13 03:31:31 +04:00
nsLocalFile : : SetFollowLinks ( PRBool aFollowLinks )
{
MakeDirty ( ) ;
mFollowSymlinks = aFollowLinks ;
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
NS_IMETHODIMP
nsLocalFile : : GetDirectoryEntries ( nsISimpleEnumerator * * entries )
{
nsresult rv ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
* entries = nsnull ;
2004-05-23 02:15:22 +04:00
if ( mWorkingPath . EqualsLiteral ( " \\ \\ . " ) ) {
2004-04-29 12:16:50 +04:00
nsDriveEnumerator * drives = new nsDriveEnumerator ;
if ( ! drives )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( drives ) ;
rv = drives - > Init ( ) ;
if ( NS_FAILED ( rv ) ) {
NS_RELEASE ( drives ) ;
return rv ;
}
* entries = drives ;
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
PRBool isDir ;
rv = IsDirectory ( & isDir ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
if ( ! isDir )
return NS_ERROR_FILE_NOT_DIRECTORY ;
nsDirEnumerator * dirEnum = new nsDirEnumerator ( ) ;
if ( dirEnum = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( dirEnum ) ;
rv = dirEnum - > Init ( this ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
{
NS_RELEASE ( dirEnum ) ;
return rv ;
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
* entries = dirEnum ;
return NS_OK ;
}
2000-07-17 19:03:05 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : GetPersistentDescriptor ( nsACString & aPersistentDescriptor )
2000-07-17 19:03:05 +04:00
{
2006-03-22 07:26:30 +03:00
CopyUTF16toUTF8 ( mWorkingPath , aPersistentDescriptor ) ;
return NS_OK ;
}
2000-07-17 19:03:05 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : SetPersistentDescriptor ( const nsACString & aPersistentDescriptor )
2000-07-17 19:03:05 +04:00
{
2006-03-22 07:26:30 +03:00
if ( IsUTF8 ( aPersistentDescriptor ) )
return InitWithPath ( NS_ConvertUTF8toUTF16 ( aPersistentDescriptor ) ) ;
else
return InitWithNativePath ( aPersistentDescriptor ) ;
}
2000-07-17 19:03:05 +04:00
2001-01-30 08:02:48 +03:00
NS_IMETHODIMP
nsLocalFile : : Reveal ( )
{
2004-06-02 12:19:42 +04:00
// make sure mResolvedPath is set
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
2004-06-02 12:19:42 +04:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
return rv ;
2002-02-20 08:41:34 +03:00
2004-06-02 12:19:42 +04:00
// use the full path to explorer for security
nsCOMPtr < nsILocalFile > winDir ;
rv = GetSpecialSystemDirectory ( Win_WindowsDirectory , getter_AddRefs ( winDir ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2006-03-22 07:26:30 +03:00
nsAutoString explorerPath ;
rv = winDir - > GetPath ( explorerPath ) ;
2004-06-02 12:19:42 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2006-03-22 07:26:30 +03:00
explorerPath . Append ( L " \\ explorer.exe " ) ;
2004-06-02 12:19:42 +04:00
// Always open a new window for files because Win2K doesn't appear to select
// the file if a window showing that folder was already open. If the resolved
// path is a directory then instead of opening the parent and selecting it,
// we open the directory itself.
2006-03-22 07:26:30 +03:00
nsAutoString explorerParams ;
2004-06-02 12:19:42 +04:00
if ( mFileInfo64 . type ! = PR_FILE_DIRECTORY ) // valid because we ResolveAndStat above
2006-03-22 07:26:30 +03:00
explorerParams . Append ( L " /n,/select, " ) ;
explorerParams . Append ( L ' \" ' ) ;
2004-06-02 12:19:42 +04:00
explorerParams . Append ( mResolvedPath ) ;
2006-03-22 07:26:30 +03:00
explorerParams . Append ( L ' \" ' ) ;
2004-06-02 12:19:42 +04:00
2006-03-22 07:26:30 +03:00
if ( nsWinAPIs : : mShellExecute ( NULL , L " open " , explorerPath . get ( ) ,
explorerParams . get ( ) ,
NULL , SW_SHOWNORMAL ) < = ( HINSTANCE ) 32 )
2004-06-02 12:19:42 +04:00
return NS_ERROR_FAILURE ;
2006-06-24 01:38:38 +04:00
2002-02-20 08:41:34 +03:00
return NS_OK ;
2001-01-30 08:02:48 +03:00
}
NS_IMETHODIMP
nsLocalFile : : Launch ( )
{
2006-03-22 07:26:30 +03:00
const nsString & path = mWorkingPath ;
2001-01-30 08:02:48 +03:00
2003-09-29 22:15:52 +04:00
// use the app registry name to launch a shell execute....
2006-03-22 07:26:30 +03:00
LONG r = ( LONG ) nsWinAPIs : : mShellExecute ( NULL , NULL , path . get ( ) ,
NULL , NULL , SW_SHOWNORMAL ) ;
2003-09-29 22:15:52 +04:00
// if the file has no association, we launch windows' "what do you want to do" dialog
if ( r = = SE_ERR_NOASSOC ) {
2006-03-22 07:26:30 +03:00
nsAutoString shellArg ;
shellArg . Assign ( NS_LITERAL_STRING ( " shell32.dll,OpenAs_RunDLL " ) + path ) ;
r = ( LONG ) nsWinAPIs : : mShellExecute ( NULL , NULL , L " RUNDLL32.EXE " ,
shellArg . get ( ) ,
NULL , SW_SHOWNORMAL ) ;
2003-09-27 18:37:16 +04:00
}
2003-09-29 22:15:52 +04:00
if ( r < 32 ) {
switch ( r ) {
case 0 :
case SE_ERR_OOM :
return NS_ERROR_OUT_OF_MEMORY ;
case ERROR_FILE_NOT_FOUND :
return NS_ERROR_FILE_NOT_FOUND ;
case ERROR_PATH_NOT_FOUND :
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
case ERROR_BAD_FORMAT :
return NS_ERROR_FILE_CORRUPTED ;
case SE_ERR_ACCESSDENIED :
return NS_ERROR_FILE_ACCESS_DENIED ;
case SE_ERR_ASSOCINCOMPLETE :
case SE_ERR_NOASSOC :
return NS_ERROR_UNEXPECTED ;
case SE_ERR_DDEBUSY :
case SE_ERR_DDEFAIL :
case SE_ERR_DDETIMEOUT :
return NS_ERROR_NOT_AVAILABLE ;
case SE_ERR_DLLNOTFOUND :
return NS_ERROR_FAILURE ;
case SE_ERR_SHARE :
return NS_ERROR_FILE_IS_LOCKED ;
default :
return NS_ERROR_FILE_EXECUTION_FAILED ;
}
}
return NS_OK ;
2001-01-30 08:02:48 +03:00
}
1999-12-04 04:13:44 +03:00
2006-03-22 07:26:30 +03:00
2003-09-29 22:15:52 +04:00
nsresult
2006-03-22 07:26:30 +03:00
NS_NewLocalFile ( const nsAString & path , PRBool followLinks , nsILocalFile * * result )
2000-01-25 00:28:28 +03:00
{
nsLocalFile * file = new nsLocalFile ( ) ;
if ( file = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( file ) ;
2000-07-13 03:31:31 +04:00
file - > SetFollowLinks ( followLinks ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( ! path . IsEmpty ( ) ) {
2006-03-22 07:26:30 +03:00
nsresult rv = file - > InitWithPath ( path ) ;
2000-07-17 19:03:05 +04:00
if ( NS_FAILED ( rv ) ) {
NS_RELEASE ( file ) ;
return rv ;
}
2000-01-25 00:28:28 +03:00
}
2003-09-29 22:15:52 +04:00
2000-01-25 00:28:28 +03:00
* result = file ;
return NS_OK ;
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
2006-03-22 07:26:30 +03:00
// Native (lossy) interface
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : InitWithNativePath ( const nsACString & filePath )
{
nsAutoString tmp ;
nsresult rv = NS_CopyNativeToUnicode ( filePath , tmp ) ;
if ( NS_SUCCEEDED ( rv ) )
return InitWithPath ( tmp ) ;
2002-04-27 09:33:09 +04:00
2006-03-22 07:26:30 +03:00
return rv ;
}
NS_IMETHODIMP
nsLocalFile : : AppendNative ( const nsACString & node )
2002-02-01 00:55:01 +03:00
{
2006-03-22 07:26:30 +03:00
nsAutoString tmp ;
nsresult rv = NS_CopyNativeToUnicode ( node , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
return Append ( tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : AppendRelativeNativePath ( const nsACString & node )
2002-02-01 00:55:01 +03:00
{
2006-03-22 07:26:30 +03:00
nsAutoString tmp ;
nsresult rv = NS_CopyNativeToUnicode ( node , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
return AppendRelativePath ( tmp ) ;
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : GetNativeLeafName ( nsACString & aLeafName )
2002-02-01 00:55:01 +03:00
{
2006-03-22 07:26:30 +03:00
//NS_WARNING("This API is lossy. Use GetLeafName !");
nsAutoString tmp ;
nsresult rv = GetLeafName ( tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
rv = NS_CopyUnicodeToNative ( tmp , aLeafName ) ;
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : SetNativeLeafName ( const nsACString & aLeafName )
2002-02-01 00:55:01 +03:00
{
2006-03-22 07:26:30 +03:00
nsAutoString tmp ;
nsresult rv = NS_CopyNativeToUnicode ( aLeafName , tmp ) ;
2002-10-06 04:29:46 +04:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
return SetLeafName ( tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : GetNativePath ( nsACString & _retval )
2002-02-01 00:55:01 +03:00
{
2006-03-22 07:26:30 +03:00
//NS_WARNING("This API is lossy. Use GetPath !");
nsAutoString tmp ;
nsresult rv = GetPath ( tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
rv = NS_CopyUnicodeToNative ( tmp , _retval ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : GetNativeCanonicalPath ( nsACString & aResult )
2002-02-01 00:55:01 +03:00
{
2006-03-22 07:26:30 +03:00
NS_WARNING ( " This method is lossy. Use GetCanoincailPath ! " ) ;
EnsureShortPath ( ) ;
NS_CopyUnicodeToNative ( mShortWorkingPath , aResult ) ;
return NS_OK ;
2002-02-01 00:55:01 +03:00
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : CopyToNative ( nsIFile * newParentDir , const nsACString & newName )
2002-02-01 00:55:01 +03:00
{
2002-05-08 03:07:19 +04:00
if ( newName . IsEmpty ( ) )
2006-03-22 07:26:30 +03:00
return CopyTo ( newParentDir , EmptyString ( ) ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString tmp ;
nsresult rv = NS_CopyNativeToUnicode ( newName , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
return CopyTo ( newParentDir , tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : CopyToFollowingLinksNative ( nsIFile * newParentDir , const nsACString & newName )
2002-02-01 00:55:01 +03:00
{
2002-05-08 03:07:19 +04:00
if ( newName . IsEmpty ( ) )
2006-03-22 07:26:30 +03:00
return CopyToFollowingLinks ( newParentDir , EmptyString ( ) ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString tmp ;
nsresult rv = NS_CopyNativeToUnicode ( newName , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
return CopyToFollowingLinks ( newParentDir , tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : MoveToNative ( nsIFile * newParentDir , const nsACString & newName )
2002-02-01 00:55:01 +03:00
{
2002-05-08 03:07:19 +04:00
if ( newName . IsEmpty ( ) )
2006-03-22 07:26:30 +03:00
return MoveTo ( newParentDir , EmptyString ( ) ) ;
2003-09-29 22:15:52 +04:00
2006-03-22 07:26:30 +03:00
nsAutoString tmp ;
nsresult rv = NS_CopyNativeToUnicode ( newName , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
return MoveTo ( newParentDir , tmp ) ;
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
NS_IMETHODIMP
nsLocalFile : : GetNativeTarget ( nsACString & _retval )
2002-02-01 00:55:01 +03:00
{
2006-03-22 07:26:30 +03:00
NS_WARNING ( " This API is lossy. Use GetTarget ! " ) ;
nsAutoString tmp ;
nsresult rv = GetTarget ( tmp ) ;
2002-10-06 04:29:46 +04:00
if ( NS_SUCCEEDED ( rv ) )
2006-03-22 07:26:30 +03:00
rv = NS_CopyUnicodeToNative ( tmp , _retval ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2006-03-22 07:26:30 +03:00
nsresult
NS_NewNativeLocalFile ( const nsACString & path , PRBool followLinks , nsILocalFile * * result )
2005-11-18 17:18:49 +03:00
{
2006-03-22 07:26:30 +03:00
nsAutoString buf ;
nsresult rv = NS_CopyNativeToUnicode ( path , buf ) ;
if ( NS_FAILED ( rv ) ) {
* result = nsnull ;
return rv ;
2005-11-18 17:18:49 +03:00
}
2006-03-22 07:26:30 +03:00
return NS_NewLocalFile ( buf , followLinks , result ) ;
2005-11-18 17:18:49 +03:00
}
2006-01-10 23:33:54 +03:00
void
nsLocalFile : : EnsureShortPath ( )
{
if ( ! mShortWorkingPath . IsEmpty ( ) )
return ;
2006-03-22 07:26:30 +03:00
WCHAR thisshort [ MAX_PATH ] ;
DWORD thisr = nsWinAPIs : :
mGetShortPathName ( mWorkingPath . get ( ) , thisshort ,
sizeof ( thisshort ) ) ;
2006-01-10 23:33:54 +03:00
if ( thisr < sizeof ( thisshort ) )
mShortWorkingPath . Assign ( thisshort ) ;
else
mShortWorkingPath . Assign ( mWorkingPath ) ;
}
2006-03-22 07:26:30 +03:00
// nsIHashable
2005-11-18 17:18:49 +03:00
2006-01-10 23:33:54 +03:00
NS_IMETHODIMP
2006-03-22 07:26:30 +03:00
nsLocalFile : : Equals ( nsIHashable * aOther , PRBool * aResult )
2006-01-10 23:33:54 +03:00
{
2006-03-22 07:26:30 +03:00
nsCOMPtr < nsIFile > otherfile ( do_QueryInterface ( aOther ) ) ;
if ( ! otherfile ) {
* aResult = PR_FALSE ;
return NS_OK ;
}
return Equals ( otherfile , aResult ) ;
2006-01-10 23:33:54 +03:00
}
NS_IMETHODIMP
nsLocalFile : : GetHashCode ( PRUint32 * aResult )
{
// In order for short and long path names to hash to the same value we
// always hash on the short pathname.
EnsureShortPath ( ) ;
2005-11-18 17:18:49 +03:00
2006-01-10 23:33:54 +03:00
* aResult = HashString ( mShortWorkingPath ) ;
2005-11-18 17:18:49 +03:00
return NS_OK ;
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile <static members>
//-----------------------------------------------------------------------------
2000-01-25 00:28:28 +03:00
2002-04-27 09:33:09 +04:00
void
nsLocalFile : : GlobalInit ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2002-04-27 09:33:09 +04:00
nsresult rv = NS_CreateShortcutResolver ( ) ;
NS_ASSERTION ( NS_SUCCEEDED ( rv ) , " Shortcut resolver could not be created " ) ;
2005-01-31 00:33:47 +03:00
# endif
2002-04-27 09:33:09 +04:00
}
void
nsLocalFile : : GlobalShutdown ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2002-04-27 09:33:09 +04:00
NS_DestroyShortcutResolver ( ) ;
2005-01-31 00:33:47 +03:00
# endif
2002-04-27 09:33:09 +04:00
}
2004-04-29 12:16:50 +04:00
2004-05-13 08:08:34 +04:00
NS_IMPL_ISUPPORTS1 ( nsDriveEnumerator , nsISimpleEnumerator )
2004-04-29 12:16:50 +04:00
nsDriveEnumerator : : nsDriveEnumerator ( )
: mLetter ( 0 )
{
}
nsDriveEnumerator : : ~ nsDriveEnumerator ( )
{
}
nsresult nsDriveEnumerator : : Init ( )
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
return NS_OK ;
# else
2004-04-29 12:16:50 +04:00
/* If the length passed to GetLogicalDriveStrings is smaller
* than the length of the string it would return , it returns
* the length required for the string . */
DWORD length = GetLogicalDriveStrings ( 0 , 0 ) ;
/* The string is null terminated */
2006-06-22 23:07:30 +04:00
if ( ! EnsureStringLength ( mDrives , length + 1 ) )
return NS_ERROR_OUT_OF_MEMORY ;
2004-04-29 12:16:50 +04:00
if ( ! GetLogicalDriveStrings ( length , mDrives . BeginWriting ( ) ) )
return NS_ERROR_FAILURE ;
mLetter = mDrives . get ( ) ;
return NS_OK ;
2005-01-31 00:33:47 +03:00
# endif
2004-04-29 12:16:50 +04:00
}
NS_IMETHODIMP nsDriveEnumerator : : HasMoreElements ( PRBool * aHasMore )
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
* aHasMore = FALSE ;
# else
2004-04-29 12:16:50 +04:00
* aHasMore = * mLetter ! = ' \0 ' ;
2005-01-31 00:33:47 +03:00
# endif
2004-04-29 12:16:50 +04:00
return NS_OK ;
}
NS_IMETHODIMP nsDriveEnumerator : : GetNext ( nsISupports * * aNext )
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
nsILocalFile * file ;
2006-03-22 07:26:30 +03:00
nsresult rv = NS_NewLocalFile ( NS_LITERAL_STRING ( " \\ " ) , PR_FALSE , & file ) ;
2005-01-31 00:33:47 +03:00
* aNext = file ;
# else
2004-04-29 12:16:50 +04:00
/* GetLogicalDrives stored in mLetter is a concatenation
* of null terminated strings , followed by a null terminator . */
if ( ! * mLetter ) {
* aNext = nsnull ;
return NS_OK ;
}
2006-03-22 07:26:30 +03:00
NS_ConvertASCIItoUTF16 drive ( mLetter ) ;
mLetter + = drive . Length ( ) + 1 ;
2004-04-29 12:16:50 +04:00
nsILocalFile * file ;
nsresult rv =
2006-03-22 07:26:30 +03:00
NS_NewLocalFile ( drive , PR_FALSE , & file ) ;
2004-04-29 12:16:50 +04:00
* aNext = file ;
2005-01-31 00:33:47 +03:00
# endif
2004-04-29 12:16:50 +04:00
return rv ;
}
2006-03-22 07:26:30 +03:00