@@ -642,6 +642,133 @@ RtlPcToFileHeader(IN PVOID PcValue,
642
642
return ImageBase ;
643
643
}
644
644
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
+
645
772
/*
646
773
* @unimplemented
647
774
*/
@@ -658,7 +785,101 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
658
785
IN PSIZE_T FileNameSize ,
659
786
IN PSIZE_T RequiredLength )
660
787
{
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 ;
662
883
}
663
884
664
885
/*
0 commit comments