Skip to content

Commit 7000fe2

Browse files
committed
[NTDLL] Implement RtlDosApplyFileIsolationRedirection_Ustr based on existing wine's code for ldr. .local redirection is not implemented yet.
1 parent 51c6942 commit 7000fe2

File tree

1 file changed

+222
-1
lines changed

1 file changed

+222
-1
lines changed

dll/ntdll/rtl/libsupp.c

Lines changed: 222 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,133 @@ RtlPcToFileHeader(IN PVOID PcValue,
642642
return ImageBase;
643643
}
644644

645+
NTSTATUS get_buffer(LPWSTR *buffer, SIZE_T needed, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer)
646+
{
647+
WCHAR *p;
648+
649+
if (CallerBuffer && CallerBuffer->MaximumLength > needed)
650+
{
651+
p = CallerBuffer->Buffer;
652+
CallerBuffer->Length = needed - sizeof(WCHAR);
653+
}
654+
else
655+
{
656+
if (!bAllocateBuffer)
657+
return STATUS_BUFFER_TOO_SMALL;
658+
659+
if (CallerBuffer)
660+
CallerBuffer->Buffer[0] = 0;
661+
662+
p = RtlAllocateHeap(RtlGetProcessHeap(), 0, needed );
663+
if (!p)
664+
return STATUS_NO_MEMORY;
665+
}
666+
*buffer = p;
667+
668+
return STATUS_SUCCESS;
669+
}
670+
671+
/* NOTE: Remove this one once our actctx support becomes better */
672+
NTSTATUS find_actctx_dll( PUNICODE_STRING pnameW, LPWSTR *fullname, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer)
673+
{
674+
static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
675+
static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
676+
677+
ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
678+
ACTCTX_SECTION_KEYED_DATA data;
679+
NTSTATUS status;
680+
SIZE_T needed, size = 1024;
681+
WCHAR *p;
682+
683+
data.cbSize = sizeof(data);
684+
status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
685+
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
686+
pnameW, &data );
687+
if (status != STATUS_SUCCESS)
688+
{
689+
//DPRINT1("RtlFindActivationContextSectionString returned 0x%x for %wZ\n", status, pnameW);
690+
return status;
691+
}
692+
693+
for (;;)
694+
{
695+
if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
696+
{
697+
status = STATUS_NO_MEMORY;
698+
goto done;
699+
}
700+
status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
701+
AssemblyDetailedInformationInActivationContext,
702+
info, size, &needed );
703+
if (status == STATUS_SUCCESS) break;
704+
if (status != STATUS_BUFFER_TOO_SMALL) goto done;
705+
RtlFreeHeap( RtlGetProcessHeap(), 0, info );
706+
size = needed;
707+
}
708+
709+
DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath);
710+
DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName);
711+
if (!info->lpAssemblyManifestPath /*|| !info->lpAssemblyDirectoryName*/)
712+
{
713+
status = STATUS_SXS_KEY_NOT_FOUND;
714+
goto done;
715+
}
716+
717+
if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' )))
718+
{
719+
DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
720+
721+
p++;
722+
if (!info->lpAssemblyDirectoryName || _wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW ))
723+
{
724+
/* manifest name does not match directory name, so it's not a global
725+
* windows/winsxs manifest; use the manifest directory name instead */
726+
dirlen = p - info->lpAssemblyManifestPath;
727+
needed = (dirlen + 1) * sizeof(WCHAR) + pnameW->Length;
728+
729+
status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer);
730+
if (!NT_SUCCESS(status))
731+
goto done;
732+
733+
p = *fullname;
734+
735+
memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
736+
p += dirlen;
737+
memcpy( p, pnameW->Buffer, pnameW->Length);
738+
p += (pnameW->Length / sizeof(WCHAR));
739+
*p = L'\0';
740+
741+
goto done;
742+
}
743+
}
744+
745+
needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) +
746+
sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + pnameW->Length + 2*sizeof(WCHAR));
747+
748+
status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer);
749+
if (!NT_SUCCESS(status))
750+
goto done;
751+
752+
p = *fullname;
753+
754+
wcscpy( p, SharedUserData->NtSystemRoot );
755+
p += wcslen(p);
756+
memcpy( p, winsxsW, sizeof(winsxsW) );
757+
p += sizeof(winsxsW) / sizeof(WCHAR);
758+
memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
759+
p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
760+
*p++ = L'\\';
761+
memcpy( p, pnameW->Buffer, pnameW->Length);
762+
p += (pnameW->Length / sizeof(WCHAR));
763+
*p = L'\0';
764+
765+
done:
766+
RtlFreeHeap( RtlGetProcessHeap(), 0, info );
767+
RtlReleaseActivationContext( data.hActCtx );
768+
DPRINT("%S\n", fullname);
769+
return status;
770+
}
771+
645772
/*
646773
* @unimplemented
647774
*/
@@ -658,7 +785,101 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
658785
IN PSIZE_T FileNameSize,
659786
IN PSIZE_T RequiredLength)
660787
{
661-
return STATUS_SXS_KEY_NOT_FOUND;
788+
NTSTATUS Status;
789+
LPWSTR fullname;
790+
WCHAR buffer [MAX_PATH];
791+
UNICODE_STRING localStr, localStr2, *pstrParam;
792+
WCHAR *p;
793+
BOOLEAN GotExtension;
794+
WCHAR c;
795+
796+
/* Check for invalid parameters */
797+
if (!OriginalName)
798+
{
799+
return STATUS_INVALID_PARAMETER;
800+
}
801+
802+
if (!DynamicString && !StaticString)
803+
{
804+
return STATUS_INVALID_PARAMETER;
805+
}
806+
807+
if ((DynamicString) && (StaticString) && !(NewName))
808+
{
809+
return STATUS_INVALID_PARAMETER;
810+
}
811+
812+
if (!OriginalName->Buffer || OriginalName->Length == 0)
813+
{
814+
return STATUS_SXS_KEY_NOT_FOUND;
815+
}
816+
817+
if (StaticString && (OriginalName == StaticString || OriginalName->Buffer == StaticString->Buffer))
818+
{
819+
return STATUS_SXS_KEY_NOT_FOUND;
820+
}
821+
822+
pstrParam = OriginalName;
823+
824+
/* Get the file name with an extension */
825+
p = OriginalName->Buffer + OriginalName->Length / sizeof(WCHAR) - 1;
826+
GotExtension = FALSE;
827+
while (p >= OriginalName->Buffer)
828+
{
829+
c = *p--;
830+
if (c == L'.')
831+
{
832+
GotExtension = TRUE;
833+
}
834+
else if (c == L'\\')
835+
{
836+
localStr.Buffer = p + 2;
837+
localStr.Length = OriginalName->Length - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer);
838+
localStr.MaximumLength = OriginalName->MaximumLength - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer);
839+
pstrParam = &localStr;
840+
break;
841+
}
842+
}
843+
844+
if (!GotExtension)
845+
{
846+
if (!Extension)
847+
{
848+
return STATUS_SXS_KEY_NOT_FOUND;
849+
}
850+
851+
if (pstrParam->Length + Extension->Length > sizeof(buffer))
852+
{
853+
//FIXME!
854+
return STATUS_NO_MEMORY;
855+
}
856+
857+
RtlInitEmptyUnicodeString(&localStr2, buffer, sizeof(buffer));
858+
RtlAppendUnicodeStringToString(&localStr2, pstrParam);
859+
RtlAppendUnicodeStringToString(&localStr2, Extension);
860+
pstrParam = &localStr2;
861+
}
862+
863+
/* Use wine's function as long as we use wine's sxs implementation in ntdll */
864+
Status = find_actctx_dll(pstrParam, &fullname, StaticString, DynamicString != NULL);
865+
if (!NT_SUCCESS(Status))
866+
{
867+
return Status;
868+
}
869+
870+
DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname);
871+
872+
if (!StaticString || StaticString->Buffer != fullname)
873+
{
874+
RtlInitUnicodeString(DynamicString, fullname);
875+
*NewName = DynamicString;
876+
}
877+
else
878+
{
879+
*NewName = StaticString;
880+
}
881+
882+
return Status;
662883
}
663884

664885
/*

0 commit comments

Comments
 (0)