diff options
author | Mikhail Voytenko <mav@openoffice.org> | 2010-01-28 13:56:00 +0100 |
---|---|---|
committer | Mikhail Voytenko <mav@openoffice.org> | 2010-01-28 13:56:00 +0100 |
commit | 066fd012867ceb64fb05f79b3e82ba353ac6d418 (patch) | |
tree | bd082d741844a2ac7e32e5ae6163856f94a91af3 /sal | |
parent | b370e800215be46aa394c372e983ab6b5f2682d5 (diff) |
#i50885# workaround the CreateDirectoryW problem
Diffstat (limited to 'sal')
-rw-r--r-- | sal/osl/w32/file_dirvol.cxx | 83 | ||||
-rw-r--r-- | sal/osl/w32/file_url.cxx | 146 | ||||
-rw-r--r-- | sal/osl/w32/file_url.h | 3 |
3 files changed, 198 insertions, 34 deletions
diff --git a/sal/osl/w32/file_dirvol.cxx b/sal/osl/w32/file_dirvol.cxx index 2bc011355750..df2919143b18 100644 --- a/sal/osl/w32/file_dirvol.cxx +++ b/sal/osl/w32/file_dirvol.cxx @@ -665,7 +665,26 @@ static DWORD create_dir_with_callback( // user specified callback function. On success // the function returns ERROR_SUCCESS else a Win32 error code. - if (CreateDirectory( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( dir_path ) ), NULL) ) + BOOL bCreated = FALSE; + + if ( rtl_uString_getLength( dir_path ) < MAX_PATH - 12 ) + { + /* this is a normal short URL, ".." are acceptable here */ + bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( dir_path )), NULL ); + } + else + { + /* the long urls can not contain ".." while calling CreateDirectory, no idea why! */ + sal_Unicode pBuf[MAX_LONG_PATH]; + sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( dir_path ) ), + pBuf, + MAX_LONG_PATH, + sal_False ); + + bCreated = CreateDirectoryW( pBuf, NULL ); + } + + if ( bCreated ) { if (aDirectoryCreationCallbackFunc) { @@ -761,15 +780,34 @@ oslFileError SAL_CALL osl_createDirectory(rtl_uString* strPath) if ( osl_File_E_None == error ) { - if ( CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL ) ) - error = osl_File_E_None; -/*@@@ToDo - The else case is a hack because the ucb or the webtop had some - problems with the error code that CreateDirectory returns in - case the path is only a logical drive, should be removed! -*/ + BOOL bCreated = FALSE; + + if ( rtl_uString_getLength( strSysPath ) < MAX_PATH - 12 ) + { + /* this is a normal short URL, ".." are acceptable here */ + bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL ); + } else { + /* the long urls can not contain ".." while calling CreateDirectory, no idea why! */ + sal_Unicode pBuf[MAX_LONG_PATH]; + sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( strSysPath ) ), + pBuf, + MAX_LONG_PATH, + sal_False ); + + bCreated = CreateDirectoryW( pBuf, NULL ); + } + + + if ( !bCreated ) + { + /*@@@ToDo + The following case is a hack because the ucb or the webtop had some + problems with the error code that CreateDirectory returns in + case the path is only a logical drive, should be removed! + */ + const sal_Unicode *pBuffer = rtl_uString_getStr( strSysPath ); sal_Int32 nLen = rtl_uString_getLength( strSysPath ); @@ -1168,7 +1206,6 @@ oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString *strFilePath, oslDirector rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath ); // MT: This costs 600ms startup time on fast v60x! - // if it is necessary in future, the system call GetLongPathName() should be used instead // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) ); pItemImpl->uType = DIRECTORYITEM_FILE; @@ -1748,29 +1785,15 @@ oslFileError SAL_CALL osl_getFileStatus( if ( !pItemImpl->bFullPathNormalized ) { sal_uInt32 nLen = rtl_uString_getLength( pItemImpl->m_pFullPath ); - sal_Unicode* pBuffer = reinterpret_cast<sal_Unicode*>( rtl_allocateMemory( sizeof(sal_Unicode) * ( nLen + 1 ) ) ); - if ( pBuffer ) - { - sal_uInt32 nNewLen = GetLongPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ), + sal_Unicode pBuffer[ MAX_LONG_PATH]; + sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ), pBuffer, - nLen ); - if ( nNewLen > nLen ) - { - rtl_freeMemory( pBuffer ); - pBuffer = reinterpret_cast<sal_Unicode*>( rtl_allocateMemory( sizeof(sal_Unicode*) * ( nNewLen + 1 ) ) ); - if ( pBuffer ) - { - sal_uInt32 nNewestLen = GetLongPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ), - pBuffer, - nNewLen ); - if ( nNewLen == nNewestLen ) - rtl_uString_newFromStr( &pItemImpl->m_pFullPath, reinterpret_cast< const sal_Unicode* >( pBuffer ) ); - } - } - else - rtl_uString_newFromStr( &pItemImpl->m_pFullPath, reinterpret_cast< const sal_Unicode* >( pBuffer ) ); + MAX_LONG_PATH, + sal_True ); - rtl_freeMemory( pBuffer ); + if ( nNewLen ) + { + rtl_uString_newFromStr( &pItemImpl->m_pFullPath, reinterpret_cast< const sal_Unicode* >( pBuffer ) ); pItemImpl->bFullPathNormalized = TRUE; } } diff --git a/sal/osl/w32/file_url.cxx b/sal/osl/w32/file_url.cxx index b666dd2c1e6f..3e40ab0fb28a 100644 --- a/sal/osl/w32/file_url.cxx +++ b/sal/osl/w32/file_url.cxx @@ -402,10 +402,8 @@ DWORD IsValidFilePath(rtl_uString *path, LPCTSTR *lppError, DWORD dwFlags, rtl_u return fValid ? dwPathType : PATHTYPE_ERROR; } -//############################################# //##################################################### -//Undocumented in SHELL32.DLL ordinal 35 -static BOOL PathRemoveFileSpec(LPTSTR lpPath) +static BOOL PathRemoveFileSpec(LPTSTR lpPath, LPTSTR lpFileName ) { BOOL fSuccess = FALSE; // Assume failure LPTSTR lpLastBkSlash = _tcsrchr( lpPath, '\\' ); @@ -419,11 +417,13 @@ static BOOL PathRemoveFileSpec(LPTSTR lpPath) if ( lpLastDelimiter > lpPath && *(lpLastDelimiter - 1) != ':' ) { *lpLastDelimiter = 0; + *lpFileName = 0; fSuccess = TRUE; } } else { + _tcscpy( lpFileName, lpLastDelimiter + 1 ); *(++lpLastDelimiter) = 0; fSuccess = TRUE; } @@ -431,6 +431,146 @@ static BOOL PathRemoveFileSpec(LPTSTR lpPath) return fSuccess; } +//##################################################### +// Undocumented in SHELL32.DLL ordinal 32 +static LPTSTR PathAddBackslash(LPTSTR lpPath, sal_Int32 nBufLen) +{ + LPTSTR lpEndPath = NULL; + + if ( lpPath ) + { + int nLen = _tcslen(lpPath); + + if ( !nLen || lpPath[nLen-1] != '\\' && lpPath[nLen-1] != '/' && nLen < nBufLen - 1 ) + { + lpEndPath = lpPath + nLen; + *lpEndPath++ = '\\'; + *lpEndPath = 0; + } + } + return lpEndPath; +} + +//##################################################### +// Same as GetLongPathName but also 95/NT4 +static DWORD GetCaseCorrectPathNameEx( + LPCTSTR lpszShortPath, // file name + LPTSTR lpszLongPath, // path buffer + DWORD cchBuffer, // size of path buffer + DWORD nSkipLevels, + BOOL bCheckExistence ) +{ + TCHAR szPath[MAX_LONG_PATH]; + TCHAR szFile[MAX_LONG_PATH]; /* MAX_LONG_PATH is used here for the case of invalid long file names */ + BOOL fSuccess; + + cchBuffer = cchBuffer; /* avoid warnings */ + + _tcscpy( szPath, lpszShortPath ); + + fSuccess = PathRemoveFileSpec( szPath, szFile ); + + if ( fSuccess ) + { + int nLen = _tcslen( szPath ); + LPCTSTR lpszFileSpec = lpszShortPath + nLen; + BOOL bSkipThis; + + if ( 0 == _tcscmp( lpszFileSpec, TEXT("..") ) ) + { + bSkipThis = TRUE; + nSkipLevels += 1; + } + else if ( + 0 == _tcscmp( lpszFileSpec, TEXT(".") ) || + 0 == _tcscmp( lpszFileSpec, TEXT("\\") ) || + 0 == _tcscmp( lpszFileSpec, TEXT("/") ) + ) + { + bSkipThis = TRUE; + } + else if ( nSkipLevels ) + { + bSkipThis = TRUE; + nSkipLevels--; + } + else + bSkipThis = FALSE; + + GetCaseCorrectPathNameEx( szPath, szPath, MAX_LONG_PATH, nSkipLevels, bCheckExistence ); + + PathAddBackslash( szPath, ELEMENTS_OF_ARRAY( szPath ) ); + + /* Analyze parent if not only a trailing backslash was cutted but a real file spec */ + if ( !bSkipThis ) + { + if ( bCheckExistence ) + { + WIN32_FIND_DATA aFindFileData; + HANDLE hFind = FindFirstFile( lpszShortPath, &aFindFileData ); + + if ( IsValidHandle(hFind) ) + { + _tcscat( szPath, aFindFileData.cFileName[0] ? aFindFileData.cFileName : aFindFileData.cAlternateFileName ); + + FindClose( hFind ); + } + else + return 0; + } + else + { + /* add the segment name back */ + _tcscat( szPath, szFile ); + } + } + } + else + { + /* File specification can't be removed therefore the short path is either a drive + or a network share. If still levels to skip are left, the path specification + tries to travel below the file system root */ + if ( nSkipLevels ) + return 0; + + _tcsupr( szPath ); + } + + _tcscpy( lpszLongPath, szPath ); + + return _tcslen( lpszLongPath ); +} + +//##################################################### +#define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\" + +DWORD GetCaseCorrectPathName( + LPCTSTR lpszShortPath, // file name + LPTSTR lpszLongPath, // path buffer + DWORD cchBuffer, // size of path buffer + BOOL bCheckExistence +) +{ + /* Special handling for "\\.\" as system root */ + if ( lpszShortPath && 0 == wcscmp( lpszShortPath, WSTR_SYSTEM_ROOT_PATH ) ) + { + if ( cchBuffer >= ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) ) + { + wcscpy( lpszLongPath, WSTR_SYSTEM_ROOT_PATH ); + return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1; + } + else + { + return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1; + } + } + else + { + return GetCaseCorrectPathNameEx( lpszShortPath, lpszLongPath, cchBuffer, 0, bCheckExistence ); + } +} + + //############################################# static sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL ) { diff --git a/sal/osl/w32/file_url.h b/sal/osl/w32/file_url.h index b46708e48722..2b2c79a41eb1 100644 --- a/sal/osl/w32/file_url.h +++ b/sal/osl/w32/file_url.h @@ -77,7 +77,8 @@ DWORD IsValidFilePath ( DWORD GetCaseCorrectPathName ( LPCTSTR lpszShortPath, // file name LPTSTR lpszLongPath, // path buffer - DWORD cchBuffer // size of path buffer + DWORD cchBuffer, // size of path buffer + BOOL bCheckExistence ); oslFileError _osl_getSystemPathFromFileURL ( |