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)
KPROCESSOR_MODE
NTAPI
-RtlpGetMode()
+RtlpGetMode(VOID)
{
return UserMode;
}
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)
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
RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
RtlInitializeHandleTable(0xCFFF,
- sizeof(RTL_ATOM_HANDLE),
- &AtomTable->RtlHandleTable);
+ sizeof(RTL_ATOM_HANDLE),
+ &AtomTable->RtlHandleTable);
return TRUE;
}
root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
+ if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
resdirptr = root;
if (!level--) goto done;
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
*/
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;
}
/*
NTAPI
RtlComputeImportTableHash(IN HANDLE FileHandle,
OUT PCHAR Hash,
- IN ULONG ImporTTableHashSize)
+ IN ULONG ImportTableHashSize)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
return STATUS_SUCCESS;
}
+/* FIXME: code duplication with kernel32/client/time.c */
+ULONG
+NTAPI
+RtlGetTickCount(VOID)
+{
+ ULARGE_INTEGER TickCount;
+
+#ifdef _WIN64
+ TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount);
+#else
+ while (TRUE)
+ {
+ TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
+ TickCount.LowPart = SharedUserData->TickCount.LowPart;
+
+ if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time)
+ break;
+
+ YieldProcessor();
+ }
+#endif
+
+ return (ULONG)((UInt32x32To64(TickCount.LowPart,
+ SharedUserData->TickCountMultiplier) >> 24) +
+ UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF,
+ SharedUserData->TickCountMultiplier));
+}
+
/* EOF */