Author: ion
Date: Tue Dec 20 19:09:13 2011
New Revision: 54713

URL: http://svn.reactos.org/svn/reactos?rev=54713&view=rev
Log:
[KERNEL32] Part 2 of the Path patch: rewrite SearchPathW to use the 
RtlDosSearchPath_UStr function implemented last week. No (visible) regressions 
seen... let's see what Testbot says.

Modified:
    trunk/reactos/dll/win32/kernel32/client/path.c

Modified: trunk/reactos/dll/win32/kernel32/client/path.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/path.c?rev=54713&r1=54712&r2=54713&view=diff
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/path.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/path.c [iso-8859-1] Tue Dec 20 
19:09:13 2011
@@ -1285,206 +1285,161 @@
     return PathSize;
 }
 
-/***********************************************************************
- *           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] == '\\'));
-}
-
-/**
- * @name GetDllLoadPath
- *
- * Internal function to compute the load path to use for a given dll.
- *
- * @remarks Returned pointer must be freed by caller.
- */
-
-LPWSTR
-GetDllLoadPath(LPCWSTR lpModule)
-{
-       ULONG Pos = 0, Length = 4, Tmp;
-       PWCHAR EnvironmentBufferW = NULL;
-       LPCWSTR lpModuleEnd = NULL;
-       UNICODE_STRING ModuleName;
-       DWORD LastError = GetLastError(); /* GetEnvironmentVariable changes 
LastError */
-
-    // FIXME: This function is used only by SearchPathW, and is deprecated and 
will be deleted ASAP.
-
-       if (lpModule != NULL && wcslen(lpModule) > 2 && lpModule[1] == ':')
-       {
-               lpModuleEnd = lpModule + wcslen(lpModule);
-       }
-       else
-       {
-               ModuleName = NtCurrentPeb()->ProcessParameters->ImagePathName;
-               lpModule = ModuleName.Buffer;
-               lpModuleEnd = lpModule + (ModuleName.Length / sizeof(WCHAR));
-       }
-
-       if (lpModule != NULL)
-       {
-               while (lpModuleEnd > lpModule && *lpModuleEnd != L'/' &&
-                      *lpModuleEnd != L'\\' && *lpModuleEnd != L':')
-               {
-                       --lpModuleEnd;
-               }
-               Length = (lpModuleEnd - lpModule) + 1;
-       }
-
-       Length += GetCurrentDirectoryW(0, NULL);
-       Length += GetDllDirectoryW(0, NULL);
-       Length += GetSystemDirectoryW(NULL, 0);
-       Length += GetWindowsDirectoryW(NULL, 0);
-       Length += GetEnvironmentVariableW(L"PATH", NULL, 0);
-
-       EnvironmentBufferW = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                                            (Length + 1) * sizeof(WCHAR));
-       if (EnvironmentBufferW == NULL)
-       {
-           return NULL;
-       }
-
-       if (lpModule)
-       {
-               RtlCopyMemory(EnvironmentBufferW, lpModule,
-                             (lpModuleEnd - lpModule) * sizeof(WCHAR));
-               Pos += lpModuleEnd - lpModule;
-               EnvironmentBufferW[Pos++] = L';';
-       }
-
-    Tmp = GetCurrentDirectoryW(Length, EnvironmentBufferW + Pos);
-       if(Tmp > 0 && Tmp < Length - Pos)
-       {
-           Pos += Tmp;
-           if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
-       }
-
-       Tmp = GetDllDirectoryW(Length - Pos, EnvironmentBufferW + Pos);
-       if(Tmp > 0 && Tmp < Length - Pos)
-       {
-           Pos += Tmp;
-           if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
-       }
-
-       Tmp = GetSystemDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
-       if(Tmp > 0 && Tmp < Length - Pos)
-       {
-           Pos += Tmp;
-           if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
-       }
-
-       Tmp = GetWindowsDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
-       if(Tmp > 0 && Tmp < Length - Pos)
-       {
-           Pos += Tmp;
-           if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
-       }
-
-       Tmp = GetEnvironmentVariableW(L"PATH", EnvironmentBufferW + Pos, Length 
- Pos);
-
-       /* Make sure buffer is null terminated */
-    EnvironmentBufferW[Pos++] = UNICODE_NULL;
-
-
-       SetLastError(LastError);
-       return EnvironmentBufferW;
-}
-
 /*
  * @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);
+SearchPathW(IN LPCWSTR lpPath,
+            IN LPCWSTR lpFileName,
+            IN LPCWSTR lpExtension,
+            IN DWORD nBufferLength,
+            IN LPWSTR lpBuffer,
+            OUT LPWSTR *lpFilePart)
+{
+    UNICODE_STRING FileNameString, ExtensionString, PathString, CallerBuffer;
+    ULONG Flags, LengthNeeded, FilePartSize;
+    NTSTATUS Status;
+    DWORD Result = 0;
+
+    /* Default flags for RtlDosSearchPath_Ustr */
+    Flags = 6;
+
+    /* Clear file part in case we fail */
+    if (lpFilePart) *lpFilePart = NULL;
+
+    /* Initialize path buffer for free later */
+    PathString.Buffer = NULL;
+
+    /* Convert filename to a unicode string and eliminate trailing spaces */
+    RtlInitUnicodeString(&FileNameString, lpFileName);
+    while ((FileNameString.Length >= sizeof(WCHAR)) &&
+           (FileNameString.Buffer[(FileNameString.Length / sizeof(WCHAR)) - 1] 
== L' '))
+    {
+        FileNameString.Length -= sizeof(WCHAR);
+    }
+
+    /* Was it all just spaces? */
+    if (!FileNameString.Length)
+    {
+        /* Fail out */
+        BaseSetLastNTError(STATUS_INVALID_PARAMETER);
+        goto Quickie;
+    }
+
+    /* Convert extension to a unicode string */
+    RtlInitUnicodeString(&ExtensionString, lpExtension);
+
+    /* Check if the user sent a path */
+    if (lpPath)
+    {
+        /* Convert it to a unicode string too */
+        Status = RtlInitUnicodeStringEx(&PathString, lpPath);
+        if (NT_ERROR(Status))
+        {
+            /* Fail if it was too long */
+            BaseSetLastNTError(Status);
+            goto Quickie;
+        }
+    }
+    else
+    {
+        /* A path wasn't sent, so compute it ourselves */
+        PathString.Buffer = BaseComputeProcessSearchPath();
+        if (!PathString.Buffer)
+        {
+            /* Fail if we couldn't compute it */
+            BaseSetLastNTError(STATUS_NO_MEMORY);
+            goto Quickie;
+        }
+
+        /* See how big the computed path is */
+        LengthNeeded = lstrlenW(PathString.Buffer);
+        if (LengthNeeded > UNICODE_STRING_MAX_CHARS)
+        {
+            /* Fail if it's too long */
+            BaseSetLastNTError(STATUS_NAME_TOO_LONG);
+            goto Quickie;
+        }
+
+        /* Set the path size now that we have it */
+        PathString.MaximumLength = PathString.Length = LengthNeeded * 
sizeof(WCHAR);
+
+        /* Request SxS isolation from RtlDosSearchPath_Ustr */
+        Flags |= 1;
+    }
+
+    /* Create the string that describes the output buffer from the caller */
+    CallerBuffer.Length = 0;
+    CallerBuffer.Buffer = lpBuffer;
+    
+    /* How much space does the caller have? */
+    if (nBufferLength <= UNICODE_STRING_MAX_CHARS)
+    {
+        /* Add it into the string */
+        CallerBuffer.MaximumLength = nBufferLength * sizeof(WCHAR);
+    }
+    else
+    {
+        /* Caller wants too much, limit it to the maximum length of a string */
+        CallerBuffer.MaximumLength = UNICODE_STRING_MAX_BYTES;
+    }
+
+    /* Call Rtl to do the work */
+    Status = RtlDosSearchPath_Ustr(Flags,
+                                   &PathString,
+                                   &FileNameString,
+                                   &ExtensionString,
+                                   &CallerBuffer,
+                                   NULL,
+                                   NULL,
+                                   &FilePartSize,
+                                   &LengthNeeded);
+    if (NT_ERROR(Status))
+    {
+        /* Check for unusual status codes */
+        if ((Status != STATUS_NO_SUCH_FILE) && (Status != 
STATUS_BUFFER_TOO_SMALL))
+        {
+            /* Print them out since maybe an app needs fixing */
+            DbgPrint("%s on file %wZ failed; NTSTATUS = %08lx\n",
+                     __FUNCTION__,
+                     &FileNameString,
+                     Status);
+            DbgPrint("    Path = %wZ\n", &PathString);
+        }
+        
+        /* Check if the failure was due to a small buffer */
+        if (Status == STATUS_BUFFER_TOO_SMALL)
+        {
+            /* Check if the length was actually too big for Rtl to work with */
+            Result = LengthNeeded / sizeof(WCHAR);
+            if (Result > 0xFFFFFFFF) BaseSetLastNTError(STATUS_NAME_TOO_LONG);
         }
         else
         {
-            SetLastError(ERROR_OUTOFMEMORY);
-            return 0;
-        }
-    }
-
-    if (!ret) SetLastError(ERROR_FILE_NOT_FOUND);
-
-    return ret;
+            /* Some other error, set the error code */
+            BaseSetLastNTError(Status);
+        }
+    }
+    else
+    {
+        /* It worked! Write the file part now */
+        if (lpFilePart) *lpFilePart = &lpBuffer[FilePartSize];
+        
+        /* Convert the final result length */
+        Result = CallerBuffer.Length / sizeof(WCHAR);
+    }
+
+Quickie:
+    /* Check if there was a dynamic path stirng to free */
+    if ((PathString.Buffer != lpPath) && (PathString.Buffer))
+    {
+        /* And free it */
+        RtlFreeHeap(RtlGetProcessHeap(), 0, PathString.Buffer);
+    }
+
+    /* Return the final result lenght */
+    return Result;
 }
 
 /*


Reply via email to