[ros-diffs] [ion] 54309: [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 s...

ion at svn.reactos.org ion at svn.reactos.org
Sun Nov 6 02:00:57 UTC 2011


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/CMakeLists.txt?rev=54309&r1=54308&r2=54309&view=diff
==============================================================================
--- 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/file/dir.c?rev=54309&r1=54308&r2=54309&view=diff
==============================================================================
--- 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/path.c?rev=54309&view=auto
==============================================================================
--- 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 at 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/kernel32.rbuild?rev=54309&r1=54308&r2=54309&view=diff
==============================================================================
--- 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>




More information about the Ros-diffs mailing list