summaryrefslogtreecommitdiff
path: root/sal
diff options
context:
space:
mode:
authorMikhail Voytenko <mav@openoffice.org>2010-01-28 13:56:00 +0100
committerMikhail Voytenko <mav@openoffice.org>2010-01-28 13:56:00 +0100
commit066fd012867ceb64fb05f79b3e82ba353ac6d418 (patch)
treebd082d741844a2ac7e32e5ae6163856f94a91af3 /sal
parentb370e800215be46aa394c372e983ab6b5f2682d5 (diff)
#i50885# workaround the CreateDirectoryW problem
Diffstat (limited to 'sal')
-rw-r--r--sal/osl/w32/file_dirvol.cxx83
-rw-r--r--sal/osl/w32/file_url.cxx146
-rw-r--r--sal/osl/w32/file_url.h3
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 (