[APPWIZ] Update French translation
[reactos.git] / dll / ntdll / rtl / libsupp.c
index 22c6811..d29ccaf 100644 (file)
 
 SIZE_T RtlpAllocDeallocQueryBufferSize = PAGE_SIZE;
 PTEB LdrpTopLevelDllBeingLoadedTeb = NULL;
+PVOID MmHighestUserAddress = (PVOID)MI_HIGHEST_USER_ADDRESS;
 
 /* FUNCTIONS ***************************************************************/
 
-#ifndef _M_AMD64
-// FIXME: Why "Not implemented"???
-/*
- * @implemented
- */
-ULONG
-NTAPI
-RtlWalkFrameChain(OUT PVOID *Callers,
-                  IN ULONG Count,
-                  IN ULONG Flags)
-{
-    /* Not implemented for user-mode */
-    return 0;
-}
-#endif
-
 BOOLEAN
 NTAPI
 RtlpCheckForActiveDebugger(VOID)
@@ -65,7 +50,7 @@ RtlpClearInDbgPrint(VOID)
 
 KPROCESSOR_MODE
 NTAPI
-RtlpGetMode()
+RtlpGetMode(VOID)
 {
    return UserMode;
 }
@@ -127,6 +112,15 @@ RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
     return RtlEnterCriticalSection(&Lock->CriticalSection);
 }
 
+BOOLEAN
+NTAPI
+RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
+{
+    UNREFERENCED_PARAMETER(Exclusive);
+
+    return RtlTryEnterCriticalSection(&Lock->CriticalSection);
+}
+
 NTSTATUS
 NTAPI
 RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
@@ -224,6 +218,118 @@ RtlpCaptureStackLimits(IN ULONG_PTR Ebp,
     return TRUE;
 }
 
+#ifndef _M_AMD64
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+RtlWalkFrameChain(OUT PVOID *Callers,
+                  IN ULONG Count,
+                  IN ULONG Flags)
+{
+    ULONG_PTR Stack, NewStack, StackBegin, StackEnd = 0;
+    ULONG Eip;
+    BOOLEAN Result, StopSearch = FALSE;
+    ULONG i = 0;
+
+    /* Get current EBP */
+#if defined(_M_IX86)
+#if defined __GNUC__
+    __asm__("mov %%ebp, %0" : "=r" (Stack) : );
+#elif defined(_MSC_VER)
+    __asm mov Stack, ebp
+#endif
+#elif defined(_M_MIPS)
+        __asm__("move $sp, %0" : "=r" (Stack) : );
+#elif defined(_M_PPC)
+    __asm__("mr %0,1" : "=r" (Stack) : );
+#elif defined(_M_ARM)
+#if defined __GNUC__
+    __asm__("mov sp, %0" : "=r"(Stack) : );
+#elif defined(_MSC_VER)
+    // FIXME: Hack. Probably won't work if this ever actually manages to run someday.
+    Stack = (ULONG_PTR)&Stack;
+#endif
+#else
+#error Unknown architecture
+#endif
+
+    /* Set it as the stack begin limit as well */
+    StackBegin = (ULONG_PTR)Stack;
+
+    /* Check if we're called for non-logging mode */
+    if (!Flags)
+    {
+        /* Get the actual safe limits */
+        Result = RtlpCaptureStackLimits((ULONG_PTR)Stack,
+                                        &StackBegin,
+                                        &StackEnd);
+        if (!Result) return 0;
+    }
+
+    /* Use a SEH block for maximum protection */
+    _SEH2_TRY
+    {
+        /* Loop the frames */
+        for (i = 0; i < Count; i++)
+        {
+            /*
+             * Leave if we're past the stack,
+             * if we're before the stack,
+             * or if we've reached ourselves.
+             */
+            if ((Stack >= StackEnd) ||
+                (!i ? (Stack < StackBegin) : (Stack <= StackBegin)) ||
+                ((StackEnd - Stack) < (2 * sizeof(ULONG_PTR))))
+            {
+                /* We're done or hit a bad address */
+                break;
+            }
+
+            /* Get new stack and EIP */
+            NewStack = *(PULONG_PTR)Stack;
+            Eip = *(PULONG_PTR)(Stack + sizeof(ULONG_PTR));
+
+            /* Check if the new pointer is above the oldone and past the end */
+            if (!((Stack < NewStack) && (NewStack < StackEnd)))
+            {
+                /* Stop searching after this entry */
+                StopSearch = TRUE;
+            }
+
+            /* Also make sure that the EIP isn't a stack address */
+            if ((StackBegin < Eip) && (Eip < StackEnd)) break;
+
+            /* FIXME: Check that EIP is inside a loaded module */
+
+            /* Save this frame */
+            Callers[i] = (PVOID)Eip;
+
+            /* Check if we should continue */
+            if (StopSearch)
+            {
+                /* Return the next index */
+                i++;
+                break;
+            }
+
+            /* Move to the next stack */
+            Stack = NewStack;
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* No index */
+        i = 0;
+    }
+    _SEH2_END;
+
+    /* Return frames parsed */
+    return i;
+}
+#endif
+
 #ifdef _AMD64_
 VOID
 NTAPI
@@ -288,8 +394,8 @@ BOOLEAN
 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
 {
    RtlInitializeHandleTable(0xCFFF,
-                           sizeof(RTL_ATOM_HANDLE),
-                           &AtomTable->RtlHandleTable);
+                            sizeof(RTL_ATOM_HANDLE),
+                            &AtomTable->RtlHandleTable);
 
    return TRUE;
 }
@@ -536,6 +642,133 @@ RtlPcToFileHeader(IN PVOID PcValue,
     return ImageBase;
 }
 
+NTSTATUS get_buffer(LPWSTR *buffer, SIZE_T needed, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer)
+{
+    WCHAR *p;
+
+    if (CallerBuffer && CallerBuffer->MaximumLength > needed)
+    {
+        p = CallerBuffer->Buffer;
+        CallerBuffer->Length = needed - sizeof(WCHAR);
+    }
+    else
+    {
+        if (!bAllocateBuffer)
+            return STATUS_BUFFER_TOO_SMALL;
+
+        if (CallerBuffer)
+            CallerBuffer->Buffer[0] = 0;
+
+        p = RtlAllocateHeap(RtlGetProcessHeap(), 0, needed );
+        if (!p)
+            return STATUS_NO_MEMORY;
+    }
+    *buffer = p;
+
+    return STATUS_SUCCESS;
+}
+
+/* NOTE: Remove this one once our actctx support becomes better */
+NTSTATUS find_actctx_dll( PUNICODE_STRING pnameW, LPWSTR *fullname, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer)
+{
+    static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
+    static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
+
+    ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
+    ACTCTX_SECTION_KEYED_DATA data;
+    NTSTATUS status;
+    SIZE_T needed, size = 1024;
+    WCHAR *p;
+
+    data.cbSize = sizeof(data);
+    status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
+                                                    ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
+                                                    pnameW, &data );
+    if (status != STATUS_SUCCESS)
+    {
+        //DPRINT1("RtlFindActivationContextSectionString returned 0x%x for %wZ\n", status, pnameW);
+        return status;
+    }
+
+    for (;;)
+    {
+        if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
+        {
+            status = STATUS_NO_MEMORY;
+            goto done;
+        }
+        status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
+                                                       AssemblyDetailedInformationInActivationContext,
+                                                       info, size, &needed );
+        if (status == STATUS_SUCCESS) break;
+        if (status != STATUS_BUFFER_TOO_SMALL) goto done;
+        RtlFreeHeap( RtlGetProcessHeap(), 0, info );
+        size = needed;
+    }
+
+    DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath);
+    DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName);
+    if (!info->lpAssemblyManifestPath /*|| !info->lpAssemblyDirectoryName*/)
+    {
+        status = STATUS_SXS_KEY_NOT_FOUND;
+        goto done;
+    }    
+
+    if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' )))
+    {
+        DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
+
+        p++;
+        if (!info->lpAssemblyDirectoryName || _wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW ))
+        {
+            /* manifest name does not match directory name, so it's not a global
+             * windows/winsxs manifest; use the manifest directory name instead */
+            dirlen = p - info->lpAssemblyManifestPath;
+            needed = (dirlen + 1) * sizeof(WCHAR) + pnameW->Length;
+
+            status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer);
+            if (!NT_SUCCESS(status))
+                goto done;
+
+            p = *fullname;
+
+            memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
+            p += dirlen;
+            memcpy( p, pnameW->Buffer, pnameW->Length);
+            p += (pnameW->Length / sizeof(WCHAR));
+            *p = L'\0';
+
+            goto done;
+        }
+    }
+
+    needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) +
+              sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + pnameW->Length + 2*sizeof(WCHAR));
+
+    status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer);
+    if (!NT_SUCCESS(status))
+        goto done;
+
+    p = *fullname;
+
+    wcscpy( p, SharedUserData->NtSystemRoot );
+    p += wcslen(p);
+    memcpy( p, winsxsW, sizeof(winsxsW) );
+    p += sizeof(winsxsW) / sizeof(WCHAR);
+    memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
+    p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
+    *p++ = L'\\';
+    memcpy( p, pnameW->Buffer, pnameW->Length);
+    p += (pnameW->Length / sizeof(WCHAR));
+    *p = L'\0';
+
+done:
+    RtlFreeHeap( RtlGetProcessHeap(), 0, info );
+    RtlReleaseActivationContext( data.hActCtx );
+    DPRINT("%S\n", fullname);
+    return status;
+}
+
 /*
  * @unimplemented
  */
@@ -552,7 +785,101 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
                                          IN PSIZE_T FileNameSize,
                                          IN PSIZE_T RequiredLength)
 {
-    return STATUS_SXS_KEY_NOT_FOUND;
+    NTSTATUS Status;
+    LPWSTR fullname;
+    WCHAR buffer [MAX_PATH];
+    UNICODE_STRING localStr, localStr2, *pstrParam;
+    WCHAR *p;
+    BOOLEAN GotExtension;
+    WCHAR c;
+
+    /* Check for invalid parameters */
+    if (!OriginalName)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!DynamicString && !StaticString)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if ((DynamicString) && (StaticString) && !(NewName))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!OriginalName->Buffer || OriginalName->Length == 0)
+    {
+        return STATUS_SXS_KEY_NOT_FOUND;
+    }
+
+    if (StaticString && (OriginalName == StaticString || OriginalName->Buffer == StaticString->Buffer))
+    {
+        return STATUS_SXS_KEY_NOT_FOUND;
+    }
+
+    pstrParam = OriginalName;
+
+    /* Get the file name with an extension */
+    p = OriginalName->Buffer + OriginalName->Length / sizeof(WCHAR) - 1;
+    GotExtension = FALSE;
+    while (p >= OriginalName->Buffer)
+    {
+        c = *p--;
+        if (c == L'.')
+        {
+            GotExtension = TRUE;
+        }
+        else if (c == L'\\')
+        {
+            localStr.Buffer = p + 2;
+            localStr.Length = OriginalName->Length - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer);
+            localStr.MaximumLength = OriginalName->MaximumLength - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer);
+            pstrParam = &localStr;
+            break;
+        }
+    }
+
+    if (!GotExtension)
+    {
+        if (!Extension)
+        {
+            return STATUS_SXS_KEY_NOT_FOUND;
+        }
+
+        if (pstrParam->Length + Extension->Length > sizeof(buffer))
+        {
+            //FIXME!
+            return STATUS_NO_MEMORY;
+        }
+
+        RtlInitEmptyUnicodeString(&localStr2, buffer, sizeof(buffer));
+        RtlAppendUnicodeStringToString(&localStr2, pstrParam);
+        RtlAppendUnicodeStringToString(&localStr2, Extension);
+        pstrParam = &localStr2;
+    }
+
+    /* Use wine's function as long as we use wine's sxs implementation in ntdll */
+    Status = find_actctx_dll(pstrParam, &fullname, StaticString, DynamicString != NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname);
+
+    if (!StaticString || StaticString->Buffer != fullname)
+    {
+        RtlInitUnicodeString(DynamicString, fullname);
+        *NewName = DynamicString;
+    }
+    else
+    {
+        *NewName = StaticString;
+    }
+
+    return Status;
 }
 
 /*
@@ -588,7 +915,7 @@ NTSTATUS
 NTAPI
 RtlComputeImportTableHash(IN HANDLE FileHandle,
                           OUT PCHAR Hash,
-                          IN ULONG ImporTTableHashSize)
+                          IN ULONG ImportTableHashSize)
 {
     UNIMPLEMENTED;
     return STATUS_NOT_IMPLEMENTED;