Author: ion
Date: Sun Nov 6 02:00:56 2011
New Revision: 54309
URL:
http://svn.reactos.org/svn/reactos?rev=54309&view=rev
Log:
[KERNEL32]: Move path-related APIs away from dir.c, and into path.c instead.
[KERNEL32]: Fix SetDllDirectoryW:
- Fail if ";" is in path
- Use RtlCreateUnicodeString instead of manual string management -- if the allocation
fails, do not free the current base directory string! Older API would always free the
current directory string, even if setting up the new one failed.
- Don't assume lpPathName is filled out, it can be NULL, and this means the DLL
directory should be cleared.
[KERNEL32]: Fix SetDllDirectoryA as above, additionally use RtlInitAnsiStringEx to protect
against overflow, and use Basep8BitStringToUnicodeString, to add support for OEM paths
instead of assuming ANSI.
[KERNEL32]: GetDllDirectoryW: correctly NULL-terminate and check lengths
[KERNEL32]: GetDllDirectoryA: same as above, plus use BasepUnicodeString* APIs to
correctly support OEM paths instead of assuming ANSI.
[KERNEL32]: NeedCurrentDirectoryForExePath(A/W): call internal
BasepIsCurDirAllowedForPlainExeNames instead of converting from A->W, this isn't
needed.
[KERNEL32]: GetFullPathNameW just calls RtlGetFullPathName_U, no extra checks/etc are
needed.
Next steps are GetFullPathNameA, GetShort/LongPathNameA, GetShort/LongPathNameW, hoping to
bring the wine test failures closer to zero.
Added:
trunk/reactos/dll/win32/kernel32/client/path.c (with props)
Modified:
trunk/reactos/dll/win32/kernel32/CMakeLists.txt
trunk/reactos/dll/win32/kernel32/client/file/dir.c
trunk/reactos/dll/win32/kernel32/kernel32.rbuild
Modified: trunk/reactos/dll/win32/kernel32/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/CMakeLi…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/CMakeLists.txt [iso-8859-1] Sun Nov 6 02:00:56 2011
@@ -20,6 +20,7 @@
client/heapmem.c
client/job.c
client/loader.c
+ client/path.c
client/perfcnt.c
client/power.c
client/proc.c
Modified: trunk/reactos/dll/win32/kernel32/client/file/dir.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/file/dir.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/file/dir.c [iso-8859-1] Sun Nov 6 02:00:56
2011
@@ -19,8 +19,6 @@
#define NDEBUG
#include <debug.h>
DEBUG_CHANNEL(kernel32file);
-
-UNICODE_STRING BaseDllDirectory = {0, 0, NULL};
/* FUNCTIONS *****************************************************************/
@@ -578,799 +576,4 @@
return TRUE;
}
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-GetFullPathNameA (
- LPCSTR lpFileName,
- DWORD nBufferLength,
- LPSTR lpBuffer,
- LPSTR *lpFilePart
- )
-{
- WCHAR BufferW[MAX_PATH];
- PWCHAR FileNameW;
- DWORD ret;
- LPWSTR FilePartW = NULL;
-
- TRACE("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
- "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
-
- if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
- return 0;
-
- ret = GetFullPathNameW(FileNameW, MAX_PATH, BufferW, &FilePartW);
-
- if (!ret)
- return 0;
-
- if (ret > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- return 0;
- }
-
- ret = FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
-
- if (ret < nBufferLength && lpFilePart)
- {
- /* if the path closed with '\', FilePart is NULL */
- if (!FilePartW)
- *lpFilePart=NULL;
- else
- *lpFilePart = (FilePartW - BufferW) + lpBuffer;
- }
-
- TRACE("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n",
- lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart);
-
- return ret;
-}
-
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-GetFullPathNameW (
- LPCWSTR lpFileName,
- DWORD nBufferLength,
- LPWSTR lpBuffer,
- LPWSTR *lpFilePart
- )
-{
- ULONG Length;
-
- TRACE("GetFullPathNameW(lpFileName %S, nBufferLength %d, lpBuffer %p, "
- "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
-
- Length = RtlGetFullPathName_U ((LPWSTR)lpFileName,
- nBufferLength * sizeof(WCHAR),
- lpBuffer,
- lpFilePart);
-
- TRACE("GetFullPathNameW ret: lpBuffer %S lpFilePart %S Length %ld\n",
- lpBuffer, (lpFilePart == NULL) ? L"NULL" : *lpFilePart, Length /
sizeof(WCHAR));
-
- if (!lpFileName)
- {
-#if (WINVER >= _WIN32_WINNT_WIN7)
- SetLastError(ERROR_INVALID_PARAMETER);
-#endif
- return 0;
- }
-
- return Length/sizeof(WCHAR);
-}
-
-
-/*
- * NOTE: Copied from Wine.
- * @implemented
- */
-DWORD
-WINAPI
-GetShortPathNameA (
- LPCSTR longpath,
- LPSTR shortpath,
- DWORD shortlen
- )
-{
- PWCHAR LongPathW;
- WCHAR ShortPathW[MAX_PATH];
- DWORD ret;
-
- if (!longpath)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- if (!(LongPathW = FilenameA2W(longpath, FALSE)))
- return 0;
-
- ret = GetShortPathNameW(LongPathW, ShortPathW, MAX_PATH);
-
- if (!ret)
- return 0;
-
- if (ret > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- return 0;
- }
-
- return FilenameW2A_FitOrFail(shortpath, shortlen, ShortPathW, ret+1);
-}
-
-
-/*
- * NOTE: Copied from Wine.
- * @implemented
- */
-DWORD
-WINAPI
-GetShortPathNameW (
- LPCWSTR longpath,
- LPWSTR shortpath,
- DWORD shortlen
- )
-{
- WCHAR tmpshortpath[MAX_PATH];
- LPCWSTR p;
- DWORD sp = 0, lp = 0;
- DWORD tmplen;
- WIN32_FIND_DATAW wfd;
- HANDLE goit;
- UNICODE_STRING ustr;
- WCHAR ustr_buf[8+1+3+1];
-
- TRACE("GetShortPathNameW: %S\n",longpath);
-
- if (!longpath)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
- if (!longpath[0])
- {
- SetLastError(ERROR_BAD_PATHNAME);
- return 0;
- }
-
- /* check for drive letter */
- if (longpath[0] != '/' && longpath[1] == ':' )
- {
- tmpshortpath[0] = longpath[0];
- tmpshortpath[1] = ':';
- sp = lp = 2;
- }
-
- ustr.Buffer = ustr_buf;
- ustr.Length = 0;
- ustr.MaximumLength = sizeof(ustr_buf);
-
- while (longpath[lp])
- {
- /* check for path delimiters and reproduce them */
- if (longpath[lp] == '\\' || longpath[lp] == '/')
- {
- if (!sp || tmpshortpath[sp-1] != '\\')
- {
- /* strip double "\\" */
- tmpshortpath[sp] = '\\';
- sp++;
- }
- tmpshortpath[sp] = 0; /* terminate string */
- lp++;
- continue;
- }
-
- for (p = longpath + lp; *p && *p != '/' && *p !=
'\\'; p++);
- tmplen = p - (longpath + lp);
- lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
- /* Check, if the current element is a valid dos name */
- if (tmplen <= 8+1+3)
- {
- BOOLEAN spaces;
- memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
- ustr_buf[tmplen] = '\0';
- ustr.Length = (USHORT)tmplen * sizeof(WCHAR);
- if (RtlIsNameLegalDOS8Dot3(&ustr, NULL, &spaces) && !spaces)
- {
- sp += tmplen;
- lp += tmplen;
- continue;
- }
- }
-
- /* Check if the file exists and use the existing short file name */
- goit = FindFirstFileW(tmpshortpath, &wfd);
- if (goit == INVALID_HANDLE_VALUE) goto notfound;
- FindClose(goit);
- lstrcpyW(tmpshortpath + sp, wfd.cAlternateFileName);
- sp += lstrlenW(tmpshortpath + sp);
- lp += tmplen;
- }
- tmpshortpath[sp] = 0;
-
- tmplen = lstrlenW(tmpshortpath) + 1;
- if (tmplen <= shortlen)
- {
- lstrcpyW(shortpath, tmpshortpath);
- tmplen--; /* length without 0 */
- }
-
- return tmplen;
-
- notfound:
- SetLastError ( ERROR_FILE_NOT_FOUND );
- return 0;
-}
-
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-SearchPathA (
- LPCSTR lpPath,
- LPCSTR lpFileName,
- LPCSTR lpExtension,
- DWORD nBufferLength,
- LPSTR lpBuffer,
- LPSTR *lpFilePart
- )
-{
- UNICODE_STRING PathU = { 0, 0, NULL };
- UNICODE_STRING FileNameU = { 0, 0, NULL };
- UNICODE_STRING ExtensionU = { 0, 0, NULL };
- UNICODE_STRING BufferU = { 0, 0, NULL };
- ANSI_STRING Path;
- ANSI_STRING FileName;
- ANSI_STRING Extension;
- ANSI_STRING Buffer;
- PWCHAR FilePartW;
- DWORD RetValue = 0;
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (!lpFileName)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- RtlInitAnsiString (&Path,
- (LPSTR)lpPath);
- RtlInitAnsiString (&FileName,
- (LPSTR)lpFileName);
- RtlInitAnsiString (&Extension,
- (LPSTR)lpExtension);
-
- /* convert ansi (or oem) strings to unicode */
- if (bIsFileApiAnsi)
- {
- Status = RtlAnsiStringToUnicodeString (&PathU,
- &Path,
- TRUE);
- if (!NT_SUCCESS(Status))
- goto Cleanup;
-
- Status = RtlAnsiStringToUnicodeString (&FileNameU,
- &FileName,
- TRUE);
- if (!NT_SUCCESS(Status))
- goto Cleanup;
-
- Status = RtlAnsiStringToUnicodeString (&ExtensionU,
- &Extension,
- TRUE);
- if (!NT_SUCCESS(Status))
- goto Cleanup;
- }
- else
- {
- Status = RtlOemStringToUnicodeString (&PathU,
- &Path,
- TRUE);
- if (!NT_SUCCESS(Status))
- goto Cleanup;
- Status = RtlOemStringToUnicodeString (&FileNameU,
- &FileName,
- TRUE);
- if (!NT_SUCCESS(Status))
- goto Cleanup;
-
- Status = RtlOemStringToUnicodeString (&ExtensionU,
- &Extension,
- TRUE);
- if (!NT_SUCCESS(Status))
- goto Cleanup;
- }
-
- BufferU.MaximumLength = min(nBufferLength * sizeof(WCHAR), USHRT_MAX);
- BufferU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
- 0,
- BufferU.MaximumLength);
- if (BufferU.Buffer == NULL)
- {
- Status = STATUS_NO_MEMORY;
- goto Cleanup;
- }
-
- Buffer.MaximumLength = min(nBufferLength, USHRT_MAX);
- Buffer.Buffer = lpBuffer;
-
- RetValue = SearchPathW (NULL == lpPath ? NULL : PathU.Buffer,
- NULL == lpFileName ? NULL : FileNameU.Buffer,
- NULL == lpExtension ? NULL : ExtensionU.Buffer,
- nBufferLength,
- BufferU.Buffer,
- &FilePartW);
-
- if (0 != RetValue)
- {
- BufferU.Length = wcslen(BufferU.Buffer) * sizeof(WCHAR);
- /* convert ansi (or oem) string to unicode */
- if (bIsFileApiAnsi)
- Status = RtlUnicodeStringToAnsiString(&Buffer,
- &BufferU,
- FALSE);
- else
- Status = RtlUnicodeStringToOemString(&Buffer,
- &BufferU,
- FALSE);
-
- if (NT_SUCCESS(Status) && Buffer.Buffer)
- {
- /* nul-terminate ascii string */
- Buffer.Buffer[BufferU.Length / sizeof(WCHAR)] = '\0';
-
- if (NULL != lpFilePart && BufferU.Length != 0)
- {
- *lpFilePart = strrchr (lpBuffer, '\\') + 1;
- }
- }
- }
-
-Cleanup:
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- PathU.Buffer);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- FileNameU.Buffer);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- ExtensionU.Buffer);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- BufferU.Buffer);
-
- if (!NT_SUCCESS(Status))
- {
- BaseSetLastNTError(Status);
- return 0;
- }
-
- return RetValue;
-}
-
-
-/***********************************************************************
- * ContainsPath (Wine name: contains_pathW)
- *
- * Check if the file name contains a path; helper for SearchPathW.
- * A relative path is not considered a path unless it starts with ./ or ../
- */
-static
-BOOL
-ContainsPath(LPCWSTR name)
-{
- if (RtlDetermineDosPathNameType_U(name) != RtlPathTypeRelative) return TRUE;
- if (name[0] != '.') return FALSE;
- if (name[1] == '/' || name[1] == '\\' || name[1] == '\0')
return TRUE;
- return (name[1] == '.' && (name[2] == '/' || name[2] ==
'\\'));
-}
-
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-SearchPathW(LPCWSTR lpPath,
- LPCWSTR lpFileName,
- LPCWSTR lpExtension,
- DWORD nBufferLength,
- LPWSTR lpBuffer,
- LPWSTR *lpFilePart)
-{
- DWORD ret = 0;
-
- if (!lpFileName || !lpFileName[0])
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- /* If the name contains an explicit path, ignore the path */
- if (ContainsPath(lpFileName))
- {
- /* try first without extension */
- if (RtlDoesFileExists_U(lpFileName))
- return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
-
- if (lpExtension)
- {
- LPCWSTR p = wcsrchr(lpFileName, '.');
- if (p && !strchr((const char *)p, '/') && !wcschr( p,
'\\' ))
- lpExtension = NULL; /* Ignore the specified extension */
- }
-
- /* Allocate a buffer for the file name and extension */
- if (lpExtension)
- {
- LPWSTR tmp;
- DWORD len = wcslen(lpFileName) + wcslen(lpExtension);
-
- if (!(tmp = RtlAllocateHeap(RtlGetProcessHeap(), 0, (len + 1) *
sizeof(WCHAR))))
- {
- SetLastError(ERROR_OUTOFMEMORY);
- return 0;
- }
- wcscpy(tmp, lpFileName);
- wcscat(tmp, lpExtension);
- if (RtlDoesFileExists_U(tmp))
- ret = GetFullPathNameW(tmp, nBufferLength, lpBuffer, lpFilePart);
- RtlFreeHeap(RtlGetProcessHeap(), 0, tmp);
- }
- }
- else if (lpPath && lpPath[0]) /* search in the specified path */
- {
- ret = RtlDosSearchPath_U(lpPath,
- lpFileName,
- lpExtension,
- nBufferLength * sizeof(WCHAR),
- lpBuffer,
- lpFilePart) / sizeof(WCHAR);
- }
- else /* search in the default path */
- {
- WCHAR *DllPath = GetDllLoadPath(NULL);
-
- if (DllPath)
- {
- ret = RtlDosSearchPath_U(DllPath,
- lpFileName,
- lpExtension,
- nBufferLength * sizeof(WCHAR),
- lpBuffer,
- lpFilePart) / sizeof(WCHAR);
- RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath);
- }
- else
- {
- SetLastError(ERROR_OUTOFMEMORY);
- return 0;
- }
- }
-
- if (!ret) SetLastError(ERROR_FILE_NOT_FOUND);
-
- return ret;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-SetDllDirectoryW(
- LPCWSTR lpPathName
- )
-{
- UNICODE_STRING PathName;
-
- RtlInitUnicodeString(&PathName, lpPathName);
-
- RtlEnterCriticalSection(&BaseDllDirectoryLock);
- if(PathName.Length > 0)
- {
- if(PathName.Length + sizeof(WCHAR) <= BaseDllDirectory.MaximumLength)
- {
- RtlCopyUnicodeString(&BaseDllDirectory, &PathName);
- }
- else
- {
- RtlFreeUnicodeString(&BaseDllDirectory);
- if(!(BaseDllDirectory.Buffer = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- PathName.Length +
sizeof(WCHAR))))
- {
- RtlLeaveCriticalSection(&BaseDllDirectoryLock);
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
- BaseDllDirectory.Length = 0;
- BaseDllDirectory.MaximumLength = PathName.Length + sizeof(WCHAR);
-
- RtlCopyUnicodeString(&BaseDllDirectory, &PathName);
- }
- }
- else
- {
- RtlFreeUnicodeString(&BaseDllDirectory);
- }
- RtlLeaveCriticalSection(&BaseDllDirectoryLock);
-
- return TRUE;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-SetDllDirectoryA(
- LPCSTR lpPathName /* can be NULL */
- )
-{
- PWCHAR PathNameW=NULL;
-
- if(lpPathName)
- {
- if (!(PathNameW = FilenameA2W(lpPathName, FALSE)))
- return FALSE;
- }
-
- return SetDllDirectoryW(PathNameW);
-}
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-GetDllDirectoryW(
- DWORD nBufferLength,
- LPWSTR lpBuffer
- )
-{
- DWORD Ret;
-
- RtlEnterCriticalSection(&BaseDllDirectoryLock);
- if(nBufferLength > 0)
- {
- Ret = BaseDllDirectory.Length / sizeof(WCHAR);
- if(Ret > nBufferLength - 1)
- {
- Ret = nBufferLength - 1;
- }
-
- if(Ret > 0)
- {
- RtlCopyMemory(lpBuffer, BaseDllDirectory.Buffer, Ret * sizeof(WCHAR));
- }
- lpBuffer[Ret] = L'\0';
- }
- else
- {
- /* include termination character, even if the string is empty! */
- Ret = (BaseDllDirectory.Length / sizeof(WCHAR)) + 1;
- }
- RtlLeaveCriticalSection(&BaseDllDirectoryLock);
-
- return Ret;
-}
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-GetDllDirectoryA(
- DWORD nBufferLength,
- LPSTR lpBuffer
- )
-{
- WCHAR BufferW[MAX_PATH];
- DWORD ret;
-
- ret = GetDllDirectoryW(MAX_PATH, BufferW);
-
- if (!ret)
- return 0;
-
- if (ret > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- return 0;
- }
-
- return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-NeedCurrentDirectoryForExePathW(LPCWSTR ExeName)
-{
- static const WCHAR env_name[] =
{'N','o','D','e','f','a','u','l','t',
-
'C','u','r','r','e','n','t',
-
'D','i','r','e','c','t','o','r','y',
-
'I','n','E','x','e','P','a','t','h',0};
- WCHAR env_val;
-
- /* MSDN mentions some 'registry location'. We do not use registry. */
- FIXME("(%s): partial stub\n", debugstr_w(ExeName));
-
- if (wcschr(ExeName, L'\\'))
- return TRUE;
-
- /* Check the existence of the variable, not value */
- if (!GetEnvironmentVariableW( env_name, &env_val, 1 ))
- return TRUE;
-
- return FALSE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-NeedCurrentDirectoryForExePathA(LPCSTR ExeName)
-{
- WCHAR *ExeNameW;
-
- if (!(ExeNameW = FilenameA2W(ExeName, FALSE)))
- return TRUE;
-
- return NeedCurrentDirectoryForExePathW(ExeNameW);
-}
-
-
-
-
-
-/***********************************************************************
- * @implemented
- *
- * GetLongPathNameW (KERNEL32.@)
- *
- * NOTES
- * observed (Win2000):
- * shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
- * shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
- */
-DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen )
-{
-#define MAX_PATHNAME_LEN 1024
-
- WCHAR tmplongpath[MAX_PATHNAME_LEN];
- LPCWSTR p;
- DWORD sp = 0, lp = 0;
- DWORD tmplen;
- BOOL unixabsolute;
- WIN32_FIND_DATAW wfd;
- HANDLE goit;
-
- if (!shortpath)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
- if (!shortpath[0])
- {
- SetLastError(ERROR_PATH_NOT_FOUND);
- return 0;
- }
-
- TRACE("GetLongPathNameW(%s,%p,%ld)\n", shortpath, longpath, longlen);
-
- if (shortpath[0] == '\\' && shortpath[1] == '\\')
- {
- WARN("ERR: UNC pathname %s\n", shortpath);
- lstrcpynW( longpath, shortpath, longlen );
- return wcslen(longpath);
- }
- unixabsolute = (shortpath[0] == '/');
- /* check for drive letter */
- if (!unixabsolute && shortpath[1] == ':' )
- {
- tmplongpath[0] = shortpath[0];
- tmplongpath[1] = ':';
- lp = sp = 2;
- }
-
- while (shortpath[sp])
- {
- /* check for path delimiters and reproduce them */
- if (shortpath[sp] == '\\' || shortpath[sp] == '/')
- {
- if (!lp || tmplongpath[lp-1] != '\\')
- {
- /* strip double "\\" */
- tmplongpath[lp++] = '\\';
- }
- tmplongpath[lp] = 0; /* terminate string */
- sp++;
- continue;
- }
-
- p = shortpath + sp;
- if (sp == 0 && p[0] == '.' && (p[1] == '/' ||
p[1] == '\\'))
- {
- tmplongpath[lp++] = *p++;
- tmplongpath[lp++] = *p++;
- }
- for (; *p && *p != '/' && *p != '\\'; p++);
- tmplen = p - (shortpath + sp);
- lstrcpynW(tmplongpath + lp, shortpath + sp, tmplen + 1);
- /* Check if the file exists and use the existing file name */
- goit = FindFirstFileW(tmplongpath, &wfd);
- if (goit == INVALID_HANDLE_VALUE)
- {
- TRACE("not found %s!\n", tmplongpath);
- SetLastError ( ERROR_FILE_NOT_FOUND );
- return 0;
- }
- FindClose(goit);
- wcscpy(tmplongpath + lp, wfd.cFileName);
- lp += wcslen(tmplongpath + lp);
- sp += tmplen;
- }
- tmplen = wcslen(shortpath) - 1;
- if ((shortpath[tmplen] == '/' || shortpath[tmplen] == '\\')
&&
- (tmplongpath[lp - 1] != '/' && tmplongpath[lp - 1] !=
'\\'))
- tmplongpath[lp++] = shortpath[tmplen];
- tmplongpath[lp] = 0;
-
- tmplen = wcslen(tmplongpath) + 1;
- if (tmplen <= longlen)
- {
- wcscpy(longpath, tmplongpath);
- TRACE("returning %s\n", longpath);
- tmplen--; /* length without 0 */
- }
-
- return tmplen;
-}
-
-
-
-/***********************************************************************
- * GetLongPathNameA (KERNEL32.@)
- */
-DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen )
-{
- WCHAR *shortpathW;
- WCHAR longpathW[MAX_PATH];
- DWORD ret;
-
- TRACE("GetLongPathNameA %s, %i\n",shortpath,longlen );
-
- if (!(shortpathW = FilenameA2W( shortpath, FALSE )))
- return 0;
-
- ret = GetLongPathNameW(shortpathW, longpathW, MAX_PATH);
-
- if (!ret) return 0;
- if (ret > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- return 0;
- }
-
- return FilenameW2A_FitOrFail(longpath, longlen, longpathW, ret+1 );
-}
-
/* EOF */
Added: trunk/reactos/dll/win32/kernel32/client/path.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/path.c (added)
+++ trunk/reactos/dll/win32/kernel32/client/path.c [iso-8859-1] Sun Nov 6 02:00:56 2011
@@ -1,0 +1,817 @@
+/*
+ * PROJECT: ReactOS Win32 Base API
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: dll/win32/kernel32/client/path.c
+ * PURPOSE: Handles path APIs
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <k32.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+UNICODE_STRING BaseDllDirectory;
+UNICODE_STRING NoDefaultCurrentDirectoryInExePath =
RTL_CONSTANT_STRING(L"NoDefaultCurrentDirectoryInExePath");
+
+/* FUNCTIONS ******************************************************************/
+
+BOOL
+WINAPI
+BasepIsCurDirAllowedForPlainExeNames(VOID)
+{
+ NTSTATUS Status;
+ UNICODE_STRING EmptyString;
+
+ RtlInitEmptyUnicodeString(&EmptyString, NULL, 0);
+ Status = RtlQueryEnvironmentVariable_U(0,
+ &NoDefaultCurrentDirectoryInExePath,
+ &EmptyString);
+ return NT_SUCCESS(Status);
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetDllDirectoryW(IN LPCWSTR lpPathName)
+{
+ UNICODE_STRING OldDirectory, DllDirectory;
+
+ if (lpPathName)
+ {
+ if (wcschr(lpPathName, ';'))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (!RtlCreateUnicodeString(&DllDirectory, lpPathName))
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&DllDirectory, 0);
+ }
+
+ RtlEnterCriticalSection(&BaseDllDirectoryLock);
+
+ OldDirectory = BaseDllDirectory;
+ BaseDllDirectory = DllDirectory;
+
+ RtlLeaveCriticalSection(&BaseDllDirectoryLock);
+
+ RtlFreeUnicodeString(&OldDirectory);
+ return 1;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetDllDirectoryA(IN LPCSTR lpPathName)
+{
+ ANSI_STRING AnsiDllDirectory;
+ UNICODE_STRING OldDirectory, DllDirectory;
+ NTSTATUS Status;
+
+ if (lpPathName)
+ {
+ if (strchr(lpPathName, ';'))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ Status = RtlInitAnsiStringEx(&AnsiDllDirectory, lpPathName);
+ if (NT_SUCCESS(Status))
+ {
+ Status = Basep8BitStringToUnicodeString(&DllDirectory,
+ &AnsiDllDirectory,
+ TRUE);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ return 0;
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&DllDirectory, 0);
+ }
+
+ RtlEnterCriticalSection(&BaseDllDirectoryLock);
+
+ OldDirectory = BaseDllDirectory;
+ BaseDllDirectory = DllDirectory;
+
+ RtlLeaveCriticalSection(&BaseDllDirectoryLock);
+
+ RtlFreeUnicodeString(&OldDirectory);
+ return 1;
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetDllDirectoryW(IN DWORD nBufferLength,
+ OUT LPWSTR lpBuffer)
+{
+ ULONG Length;
+
+ RtlEnterCriticalSection(&BaseDllDirectoryLock);
+
+ if ((nBufferLength * sizeof(WCHAR)) > BaseDllDirectory.Length)
+ {
+ RtlCopyMemory(lpBuffer, BaseDllDirectory.Buffer, BaseDllDirectory.Length);
+ Length = BaseDllDirectory.Length / sizeof(WCHAR);
+ lpBuffer[Length] = UNICODE_NULL;
+ }
+ else
+ {
+ Length = (BaseDllDirectory.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+ if (lpBuffer) *lpBuffer = UNICODE_NULL;
+ }
+
+ RtlLeaveCriticalSection(&BaseDllDirectoryLock);
+ return Length;
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetDllDirectoryA(IN DWORD nBufferLength,
+ OUT LPSTR lpBuffer)
+{
+ NTSTATUS Status;
+ ANSI_STRING AnsiDllDirectory;
+ ULONG Length;
+
+ RtlInitEmptyAnsiString(&AnsiDllDirectory, lpBuffer, 0);
+
+ RtlEnterCriticalSection(&BaseDllDirectoryLock);
+
+ Length = BasepUnicodeStringTo8BitSize(&BaseDllDirectory);
+ if (Length > nBufferLength)
+ {
+ Status = STATUS_SUCCESS;
+ if (lpBuffer) *lpBuffer = ANSI_NULL;
+ }
+ else
+ {
+ --Length;
+ Status = BasepUnicodeStringTo8BitString(&AnsiDllDirectory,
+ &BaseDllDirectory,
+ FALSE);
+ }
+
+ RtlLeaveCriticalSection(&BaseDllDirectoryLock);
+
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ Length = 0;
+ if (lpBuffer) *lpBuffer = ANSI_NULL;
+ }
+
+ return Length;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+NeedCurrentDirectoryForExePathW(IN LPCWSTR ExeName)
+{
+ if (wcschr(ExeName, '\\')) return TRUE;
+
+ return BasepIsCurDirAllowedForPlainExeNames();
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+NeedCurrentDirectoryForExePathA(IN LPCSTR ExeName)
+{
+ if (strchr(ExeName, '\\')) return TRUE;
+
+ return BasepIsCurDirAllowedForPlainExeNames();
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetFullPathNameA (
+ LPCSTR lpFileName,
+ DWORD nBufferLength,
+ LPSTR lpBuffer,
+ LPSTR *lpFilePart
+ )
+{
+ WCHAR BufferW[MAX_PATH];
+ PWCHAR FileNameW;
+ DWORD ret;
+ LPWSTR FilePartW = NULL;
+
+ DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
+ "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
+
+ if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+ return 0;
+
+ ret = GetFullPathNameW(FileNameW, MAX_PATH, BufferW, &FilePartW);
+
+ if (!ret)
+ return 0;
+
+ if (ret > MAX_PATH)
+ {
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return 0;
+ }
+
+ ret = FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
+
+ if (ret < nBufferLength && lpFilePart)
+ {
+ /* if the path closed with '\', FilePart is NULL */
+ if (!FilePartW)
+ *lpFilePart=NULL;
+ else
+ *lpFilePart = (FilePartW - BufferW) + lpBuffer;
+ }
+
+ DPRINT("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n",
+ lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart);
+
+ return ret;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetFullPathNameW(IN LPCWSTR lpFileName,
+ IN DWORD nBufferLength,
+ IN LPWSTR lpBuffer,
+ OUT LPWSTR *lpFilePart)
+{
+ return RtlGetFullPathName_U((LPWSTR)lpFileName,
+ nBufferLength * sizeof(WCHAR),
+ lpBuffer,
+ lpFilePart) / sizeof(WCHAR);
+}
+
+
+/*
+ * NOTE: Copied from Wine.
+ * @implemented
+ */
+DWORD
+WINAPI
+GetShortPathNameA (
+ LPCSTR longpath,
+ LPSTR shortpath,
+ DWORD shortlen
+ )
+{
+ PWCHAR LongPathW;
+ WCHAR ShortPathW[MAX_PATH];
+ DWORD ret;
+
+ if (!longpath)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ if (!(LongPathW = FilenameA2W(longpath, FALSE)))
+ return 0;
+
+ ret = GetShortPathNameW(LongPathW, ShortPathW, MAX_PATH);
+
+ if (!ret)
+ return 0;
+
+ if (ret > MAX_PATH)
+ {
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return 0;
+ }
+
+ return FilenameW2A_FitOrFail(shortpath, shortlen, ShortPathW, ret+1);
+}
+
+
+/*
+ * NOTE: Copied from Wine.
+ * @implemented
+ */
+DWORD
+WINAPI
+GetShortPathNameW (
+ LPCWSTR longpath,
+ LPWSTR shortpath,
+ DWORD shortlen
+ )
+{
+ WCHAR tmpshortpath[MAX_PATH];
+ LPCWSTR p;
+ DWORD sp = 0, lp = 0;
+ DWORD tmplen;
+ WIN32_FIND_DATAW wfd;
+ HANDLE goit;
+ UNICODE_STRING ustr;
+ WCHAR ustr_buf[8+1+3+1];
+
+ DPRINT("GetShortPathNameW: %S\n",longpath);
+
+ if (!longpath)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ if (!longpath[0])
+ {
+ SetLastError(ERROR_BAD_PATHNAME);
+ return 0;
+ }
+
+ /* check for drive letter */
+ if (longpath[0] != '/' && longpath[1] == ':' )
+ {
+ tmpshortpath[0] = longpath[0];
+ tmpshortpath[1] = ':';
+ sp = lp = 2;
+ }
+
+ ustr.Buffer = ustr_buf;
+ ustr.Length = 0;
+ ustr.MaximumLength = sizeof(ustr_buf);
+
+ while (longpath[lp])
+ {
+ /* check for path delimiters and reproduce them */
+ if (longpath[lp] == '\\' || longpath[lp] == '/')
+ {
+ if (!sp || tmpshortpath[sp-1] != '\\')
+ {
+ /* strip double "\\" */
+ tmpshortpath[sp] = '\\';
+ sp++;
+ }
+ tmpshortpath[sp] = 0; /* terminate string */
+ lp++;
+ continue;
+ }
+
+ for (p = longpath + lp; *p && *p != '/' && *p !=
'\\'; p++);
+ tmplen = p - (longpath + lp);
+ lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
+ /* Check, if the current element is a valid dos name */
+ if (tmplen <= 8+1+3)
+ {
+ BOOLEAN spaces;
+ memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
+ ustr_buf[tmplen] = '\0';
+ ustr.Length = (USHORT)tmplen * sizeof(WCHAR);
+ if (RtlIsNameLegalDOS8Dot3(&ustr, NULL, &spaces) && !spaces)
+ {
+ sp += tmplen;
+ lp += tmplen;
+ continue;
+ }
+ }
+
+ /* Check if the file exists and use the existing short file name */
+ goit = FindFirstFileW(tmpshortpath, &wfd);
+ if (goit == INVALID_HANDLE_VALUE) goto notfound;
+ FindClose(goit);
+ lstrcpyW(tmpshortpath + sp, wfd.cAlternateFileName);
+ sp += lstrlenW(tmpshortpath + sp);
+ lp += tmplen;
+ }
+ tmpshortpath[sp] = 0;
+
+ tmplen = lstrlenW(tmpshortpath) + 1;
+ if (tmplen <= shortlen)
+ {
+ lstrcpyW(shortpath, tmpshortpath);
+ tmplen--; /* length without 0 */
+ }
+
+ return tmplen;
+
+ notfound:
+ SetLastError ( ERROR_FILE_NOT_FOUND );
+ return 0;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+SearchPathA (
+ LPCSTR lpPath,
+ LPCSTR lpFileName,
+ LPCSTR lpExtension,
+ DWORD nBufferLength,
+ LPSTR lpBuffer,
+ LPSTR *lpFilePart
+ )
+{
+ UNICODE_STRING PathU = { 0, 0, NULL };
+ UNICODE_STRING FileNameU = { 0, 0, NULL };
+ UNICODE_STRING ExtensionU = { 0, 0, NULL };
+ UNICODE_STRING BufferU = { 0, 0, NULL };
+ ANSI_STRING Path;
+ ANSI_STRING FileName;
+ ANSI_STRING Extension;
+ ANSI_STRING Buffer;
+ PWCHAR FilePartW;
+ DWORD RetValue = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (!lpFileName)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ RtlInitAnsiString (&Path,
+ (LPSTR)lpPath);
+ RtlInitAnsiString (&FileName,
+ (LPSTR)lpFileName);
+ RtlInitAnsiString (&Extension,
+ (LPSTR)lpExtension);
+
+ /* convert ansi (or oem) strings to unicode */
+ if (bIsFileApiAnsi)
+ {
+ Status = RtlAnsiStringToUnicodeString (&PathU,
+ &Path,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
+
+ Status = RtlAnsiStringToUnicodeString (&FileNameU,
+ &FileName,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
+
+ Status = RtlAnsiStringToUnicodeString (&ExtensionU,
+ &Extension,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
+ }
+ else
+ {
+ Status = RtlOemStringToUnicodeString (&PathU,
+ &Path,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
+ Status = RtlOemStringToUnicodeString (&FileNameU,
+ &FileName,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
+
+ Status = RtlOemStringToUnicodeString (&ExtensionU,
+ &Extension,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
+ }
+
+ BufferU.MaximumLength = min(nBufferLength * sizeof(WCHAR), USHRT_MAX);
+ BufferU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
+ 0,
+ BufferU.MaximumLength);
+ if (BufferU.Buffer == NULL)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ Buffer.MaximumLength = min(nBufferLength, USHRT_MAX);
+ Buffer.Buffer = lpBuffer;
+
+ RetValue = SearchPathW (NULL == lpPath ? NULL : PathU.Buffer,
+ NULL == lpFileName ? NULL : FileNameU.Buffer,
+ NULL == lpExtension ? NULL : ExtensionU.Buffer,
+ nBufferLength,
+ BufferU.Buffer,
+ &FilePartW);
+
+ if (0 != RetValue)
+ {
+ BufferU.Length = wcslen(BufferU.Buffer) * sizeof(WCHAR);
+ /* convert ansi (or oem) string to unicode */
+ if (bIsFileApiAnsi)
+ Status = RtlUnicodeStringToAnsiString(&Buffer,
+ &BufferU,
+ FALSE);
+ else
+ Status = RtlUnicodeStringToOemString(&Buffer,
+ &BufferU,
+ FALSE);
+
+ if (NT_SUCCESS(Status) && Buffer.Buffer)
+ {
+ /* nul-terminate ascii string */
+ Buffer.Buffer[BufferU.Length / sizeof(WCHAR)] = '\0';
+
+ if (NULL != lpFilePart && BufferU.Length != 0)
+ {
+ *lpFilePart = strrchr (lpBuffer, '\\') + 1;
+ }
+ }
+ }
+
+Cleanup:
+ RtlFreeHeap (RtlGetProcessHeap (),
+ 0,
+ PathU.Buffer);
+ RtlFreeHeap (RtlGetProcessHeap (),
+ 0,
+ FileNameU.Buffer);
+ RtlFreeHeap (RtlGetProcessHeap (),
+ 0,
+ ExtensionU.Buffer);
+ RtlFreeHeap (RtlGetProcessHeap (),
+ 0,
+ BufferU.Buffer);
+
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ return 0;
+ }
+
+ return RetValue;
+}
+
+
+/***********************************************************************
+ * ContainsPath (Wine name: contains_pathW)
+ *
+ * Check if the file name contains a path; helper for SearchPathW.
+ * A relative path is not considered a path unless it starts with ./ or ../
+ */
+static
+BOOL
+ContainsPath(LPCWSTR name)
+{
+ if (RtlDetermineDosPathNameType_U(name) != RtlPathTypeRelative) return TRUE;
+ if (name[0] != '.') return FALSE;
+ if (name[1] == '/' || name[1] == '\\' || name[1] == '\0')
return TRUE;
+ return (name[1] == '.' && (name[2] == '/' || name[2] ==
'\\'));
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+SearchPathW(LPCWSTR lpPath,
+ LPCWSTR lpFileName,
+ LPCWSTR lpExtension,
+ DWORD nBufferLength,
+ LPWSTR lpBuffer,
+ LPWSTR *lpFilePart)
+{
+ DWORD ret = 0;
+
+ if (!lpFileName || !lpFileName[0])
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ /* If the name contains an explicit path, ignore the path */
+ if (ContainsPath(lpFileName))
+ {
+ /* try first without extension */
+ if (RtlDoesFileExists_U(lpFileName))
+ return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
+
+ if (lpExtension)
+ {
+ LPCWSTR p = wcsrchr(lpFileName, '.');
+ if (p && !strchr((const char *)p, '/') && !wcschr( p,
'\\' ))
+ lpExtension = NULL; /* Ignore the specified extension */
+ }
+
+ /* Allocate a buffer for the file name and extension */
+ if (lpExtension)
+ {
+ LPWSTR tmp;
+ DWORD len = wcslen(lpFileName) + wcslen(lpExtension);
+
+ if (!(tmp = RtlAllocateHeap(RtlGetProcessHeap(), 0, (len + 1) *
sizeof(WCHAR))))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
+ }
+ wcscpy(tmp, lpFileName);
+ wcscat(tmp, lpExtension);
+ if (RtlDoesFileExists_U(tmp))
+ ret = GetFullPathNameW(tmp, nBufferLength, lpBuffer, lpFilePart);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, tmp);
+ }
+ }
+ else if (lpPath && lpPath[0]) /* search in the specified path */
+ {
+ ret = RtlDosSearchPath_U(lpPath,
+ lpFileName,
+ lpExtension,
+ nBufferLength * sizeof(WCHAR),
+ lpBuffer,
+ lpFilePart) / sizeof(WCHAR);
+ }
+ else /* search in the default path */
+ {
+ WCHAR *DllPath = GetDllLoadPath(NULL);
+
+ if (DllPath)
+ {
+ ret = RtlDosSearchPath_U(DllPath,
+ lpFileName,
+ lpExtension,
+ nBufferLength * sizeof(WCHAR),
+ lpBuffer,
+ lpFilePart) / sizeof(WCHAR);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath);
+ }
+ else
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
+ }
+ }
+
+ if (!ret) SetLastError(ERROR_FILE_NOT_FOUND);
+
+ return ret;
+}
+
+/***********************************************************************
+ * @implemented
+ *
+ * GetLongPathNameW (KERNEL32.@)
+ *
+ * NOTES
+ * observed (Win2000):
+ * shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
+ * shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
+ */
+DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen )
+{
+#define MAX_PATHNAME_LEN 1024
+
+ WCHAR tmplongpath[MAX_PATHNAME_LEN];
+ LPCWSTR p;
+ DWORD sp = 0, lp = 0;
+ DWORD tmplen;
+ BOOL unixabsolute;
+ WIN32_FIND_DATAW wfd;
+ HANDLE goit;
+
+ if (!shortpath)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ if (!shortpath[0])
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return 0;
+ }
+
+ DPRINT("GetLongPathNameW(%s,%p,%ld)\n", shortpath, longpath, longlen);
+
+ if (shortpath[0] == '\\' && shortpath[1] == '\\')
+ {
+ DPRINT1("ERR: UNC pathname %s\n", shortpath);
+ lstrcpynW( longpath, shortpath, longlen );
+ return wcslen(longpath);
+ }
+ unixabsolute = (shortpath[0] == '/');
+ /* check for drive letter */
+ if (!unixabsolute && shortpath[1] == ':' )
+ {
+ tmplongpath[0] = shortpath[0];
+ tmplongpath[1] = ':';
+ lp = sp = 2;
+ }
+
+ while (shortpath[sp])
+ {
+ /* check for path delimiters and reproduce them */
+ if (shortpath[sp] == '\\' || shortpath[sp] == '/')
+ {
+ if (!lp || tmplongpath[lp-1] != '\\')
+ {
+ /* strip double "\\" */
+ tmplongpath[lp++] = '\\';
+ }
+ tmplongpath[lp] = 0; /* terminate string */
+ sp++;
+ continue;
+ }
+
+ p = shortpath + sp;
+ if (sp == 0 && p[0] == '.' && (p[1] == '/' ||
p[1] == '\\'))
+ {
+ tmplongpath[lp++] = *p++;
+ tmplongpath[lp++] = *p++;
+ }
+ for (; *p && *p != '/' && *p != '\\'; p++);
+ tmplen = p - (shortpath + sp);
+ lstrcpynW(tmplongpath + lp, shortpath + sp, tmplen + 1);
+ /* Check if the file exists and use the existing file name */
+ goit = FindFirstFileW(tmplongpath, &wfd);
+ if (goit == INVALID_HANDLE_VALUE)
+ {
+ DPRINT("not found %s!\n", tmplongpath);
+ SetLastError ( ERROR_FILE_NOT_FOUND );
+ return 0;
+ }
+ FindClose(goit);
+ wcscpy(tmplongpath + lp, wfd.cFileName);
+ lp += wcslen(tmplongpath + lp);
+ sp += tmplen;
+ }
+ tmplen = wcslen(shortpath) - 1;
+ if ((shortpath[tmplen] == '/' || shortpath[tmplen] == '\\')
&&
+ (tmplongpath[lp - 1] != '/' && tmplongpath[lp - 1] !=
'\\'))
+ tmplongpath[lp++] = shortpath[tmplen];
+ tmplongpath[lp] = 0;
+
+ tmplen = wcslen(tmplongpath) + 1;
+ if (tmplen <= longlen)
+ {
+ wcscpy(longpath, tmplongpath);
+ DPRINT("returning %s\n", longpath);
+ tmplen--; /* length without 0 */
+ }
+
+ return tmplen;
+}
+
+
+
+/***********************************************************************
+ * GetLongPathNameA (KERNEL32.@)
+ */
+DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen )
+{
+ WCHAR *shortpathW;
+ WCHAR longpathW[MAX_PATH];
+ DWORD ret;
+
+ DPRINT("GetLongPathNameA %s, %i\n",shortpath,longlen );
+
+ if (!(shortpathW = FilenameA2W( shortpath, FALSE )))
+ return 0;
+
+ ret = GetLongPathNameW(shortpathW, longpathW, MAX_PATH);
+
+ if (!ret) return 0;
+ if (ret > MAX_PATH)
+ {
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return 0;
+ }
+
+ return FilenameW2A_FitOrFail(longpath, longlen, longpathW, ret+1 );
+}
+
+/* EOF */
Propchange: trunk/reactos/dll/win32/kernel32/client/path.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/dll/win32/kernel32/kernel32.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/kernel3…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/kernel32.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/kernel32.rbuild [iso-8859-1] Sun Nov 6 02:00:56
2011
@@ -37,6 +37,7 @@
<file>heapmem.c</file>
<file>job.c</file>
<file>loader.c</file>
+ <file>path.c</file>
<file>perfcnt.c</file>
<file>power.c</file>
<file>proc.c</file>