@@ -8,9 +8,11 @@ open FSharp.Compiler.AbstractIL.Internal
88open FSharp.Compiler .AbstractIL .Internal .Bytes
99open FSharp.Compiler .AbstractIL .Diagnostics
1010open FSharp.Compiler .AbstractIL .Internal .Library
11+ open FSharp.Compiler .AbstractIL .Internal .NativeRes
1112#if FX_ NO_ CORHOST_ SIGNER
1213open FSharp.Compiler .AbstractIL .Internal .StrongNameSign
1314#endif
15+
1416open System
1517open System.IO
1618open System.Text
@@ -37,8 +39,6 @@ let check _action (hresult) =
3739 System.Runtime.InteropServices.Marshal.ThrowExceptionForHR hresult
3840 //printf "action = %s, hresult = 0x%nx \n" action hresult
3941
40- type PEFileType = X86 | X64
41-
4242let MAX_PATH = 260
4343
4444let E_FAIL = 0x80004005
@@ -570,207 +570,24 @@ type ResFormatNode(tid: int32, nid: int32, lid: int32, dataOffset: int32, pbLink
570570
571571 ! size
572572
573- let linkNativeResourcesViaCVTres ( unlinkedResources : byte [] list ) ( ulLinkedResourceBaseRVA : int32 ) ( fileType : PEFileType ) ( outputFilePath : string ) =
574- let nPEFileType = match fileType with X86 -> 0 | X64 -> 2
575- let mutable tempResFiles : string list = []
576- let mutable objBytes : byte [] = [||]
577-
578- let unlinkedResources = unlinkedResources |> List.filter ( fun arr -> arr.Length > 0 )
579- if isNil unlinkedResources then // bail if there's nothing to link
580- objBytes
581- else
582- // Part 1: Write unlinked resources to an object file for linking
583- // check if the first dword is 0x0
584- let firstDWord = bytesToDWord( unlinkedResources.[ 0 ].[ 0 ], unlinkedResources.[ 0 ].[ 1 ], unlinkedResources.[ 0 ].[ 2 ], unlinkedResources.[ 0 ].[ 3 ])
585- if firstDWord = 0 then
586- // build the command line invocation string for cvtres.exe
587- let corSystemDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
588- // We'll use the current dir and a random file name rather than System.IO.Path.GetTempFileName
589- // to try and prevent the command line invocation string from being > MAX_PATH
590-
591- let outputFilePaths =
592- if outputFilePath = " " then
593- [ FileSystem.GetTempPathShim() ]
594- else
595- [ FileSystem.GetTempPathShim() ; ( outputFilePath + " \\ " ) ]
596-
597- // Get a unique random file
598- let rec GetUniqueRandomFileName path =
599- let tfn = path + System.IO.Path.GetRandomFileName()
600- if FileSystem.SafeExists tfn then
601- GetUniqueRandomFileName path
602- else
603- tfn
604-
605-
606- let machine = if 2 = nPEFileType then " X64" else " X86"
607- let cmdLineArgsPreamble = sprintf " /NOLOGO /READONLY /MACHINE:%s " machine
608-
609- let cvtres = corSystemDir + " cvtres.exe "
610-
611- let createCvtresArgs path =
612- let tempObjFileName = GetUniqueRandomFileName path
613- let mutable cmdLineArgs = sprintf " %s \" /Out:%s \" " cmdLineArgsPreamble tempObjFileName
614- let mutable resFiles : string list = []
615-
616- for _ ulr in unlinkedResources do
617- let tempResFileName = GetUniqueRandomFileName path
618- resFiles <- tempResFileName :: resFiles
619- cmdLineArgs <- cmdLineArgs + " \" " + tempResFileName + " \" "
620- let trf = resFiles
621- let cmd = cmdLineArgs
622- cmd, tempObjFileName, trf
623-
624- let cmdLineArgs , tempObjFileName , tempResFileNames =
625- let attempts =
626- outputFilePaths |>
627- List.map ( fun path -> createCvtresArgs path) |>
628- List.filter ( fun (( argstring : string ), ( _t : string ), ( _f : string list )) -> ( cvtres.Length + argstring.Length) < MAX_ PATH)
629- let invoc , tmp , files =
630- match attempts with
631- | [] -> createCvtresArgs " .\\ " // hope for the best...
632- | ( i, t, f) :: _ rest -> i, t, f // use the first one, since they're listed in order of precedence
633- tempResFiles <- files
634- ( invoc, tmp, files)
635-
636- let cvtresInvocation = cvtres + cmdLineArgs
637-
638- try
639- let mutable iFiles = 0
640-
641- for ulr in unlinkedResources do
642- // REVIEW: What can go wrong here? What happens when the various file calls fail
643- // dump the unlinked resource bytes into the temp file
644- System.IO.File.WriteAllBytes( tempResFileNames.[ iFiles], ulr)
645- iFiles <- iFiles + 1
646-
647- // call cvtres.exe using the full cmd line string we've generated
648-
649- // check to see if the generated string is too long - if it is, fail with E_FAIL
650- if cvtresInvocation.Length >= MAX_ PATH then
651- System.Runtime.InteropServices.Marshal.ThrowExceptionForHR( E_ FAIL)
652-
653- // REVIEW: We really shouldn't be calling out to cvtres
654- let mutable psi = System.Diagnostics.ProcessStartInfo cvtres
655- psi.Arguments <- cmdLineArgs
656- psi.CreateNoWindow <- true ; // REVIEW: For some reason, this still creates a window unless WindowStyle is set to hidden
657- psi.WindowStyle <- System.Diagnostics.ProcessWindowStyle.Hidden
658- let p = System.Diagnostics.Process.Start psi
659-
660- // Wait for the process to finish
661- p.WaitForExit()
662-
663- check " Process.Start" p.ExitCode // TODO: really need to check against 0
664-
665- // Conversion was successful, so read the object file
666- objBytes <- FileSystem.ReadAllBytesShim tempObjFileName
667- //Array.Copy(objBytes, pbUnlinkedResource, pbUnlinkedResource.Length)
668- FileSystem.FileDelete tempObjFileName
669- finally
670- // clean up the temp files
671- List.iter ( fun tempResFileName -> FileSystem.FileDelete tempResFileName) tempResFiles
672-
673- // Part 2: Read the COFF file held in pbUnlinkedResource, spit it out into pResBuffer and apply the COFF fixups
674- // pResBuffer will become the .rsrc section of the PE file
675- if ( objBytes = Unchecked.defaultof< byte[]>) then
676- System.Runtime.InteropServices.Marshal.ThrowExceptionForHR( E_ FAIL)
677-
678- let hMod = bytesToIFH objBytes 0
679-
680- if hMod.SizeOfOptionalHeader <> 0 s then
681- System.Runtime.InteropServices.Marshal.ThrowExceptionForHR( E_ FAIL)
682-
683- let rsrc01Name = 0x313024637273722e L // ".rsrc$01"
684- let rsrc02Name = 0x323024637273722e L // ".rsrc$02"
685- let nullHdr = Unchecked.defaultof< IMAGE_ SECTION_ HEADER>
686- let mutable rsrc01 = nullHdr
687- let mutable rsrc02 = nullHdr
688-
689- for i = 0 to int hMod.NumberOfSections do
690- let pSection = bytesToISH objBytes ( IMAGE_ FILE_ HEADER.Width + ( IMAGE_ SECTION_ HEADER.Width * i))
691- if pSection.Name = rsrc01Name then
692- rsrc01 <- pSection
693- else if pSection.Name = rsrc02Name then
694- rsrc02 <- pSection
695-
696- if ( nullHdr = rsrc01) || ( nullHdr = rsrc02) then
697- // One of the rsrc sections wasn't found
698- System.Runtime.InteropServices.Marshal.ThrowExceptionForHR( E_ FAIL)
699-
700- let size = rsrc01.SizeOfRawData + rsrc02.SizeOfRawData
701-
702- let pResBuffer = Bytes.zeroCreate size
703-
704- // Copy over the raw data
705- Bytes.blit objBytes rsrc01.PointerToRawData pResBuffer 0 rsrc01.SizeOfRawData
706-
707- // map all the relocs in .rsrc$01 using the reloc and symbol tables in the COFF object
708- let symbolTableHead = hMod.PointerToSymbolTable
709- let IMAGE_SYM_CLASS_STATIC = 0x3 uy
710- let IMAGE_SYM_TYPE_NULL = 0x0 s
711-
712- let GetSymbolEntry ( buffer : byte []) ( idx : int ) =
713- bytesToIS buffer ( symbolTableHead + ( idx * IMAGE_ SYMBOL.Width) )
714-
715- for iReloc = 0 to int ( rsrc01.NumberOfRelocations - 1 s) do
716- let pReloc = bytesToIR objBytes ( rsrc01.PointerToRelocations + ( iReloc * IMAGE_ RELOCATION.Width))
717- let IdxSymbol = pReloc.SymbolTableIndex
718- let pSymbolEntry = GetSymbolEntry objBytes IdxSymbol
719-
720- // Ensure the symbol entry is valid for a resource
721- if (( pSymbolEntry.StorageClass <> IMAGE_ SYM_ CLASS_ STATIC) ||
722- ( pSymbolEntry.Type <> IMAGE_ SYM_ TYPE_ NULL) ||
723- ( pSymbolEntry.SectionNumber <> 3 s)) then
724- System.Runtime.InteropServices.Marshal.ThrowExceptionForHR( E_ FAIL)
725-
726- // Ensure that RVA is a valid address inside rsrc02
727- if pSymbolEntry.Value >= rsrc02.SizeOfRawData then
728- // pSymbolEntry.Value is too big
729- System.Runtime.InteropServices.Marshal.ThrowExceptionForHR( E_ FAIL)
730-
731- // store the value
732- let vBuff , vSize = dwToBytes ( ulLinkedResourceBaseRVA + rsrc01.SizeOfRawData + pSymbolEntry.Value)
733- //Bytes.blit objBytes rsrc02.PointerToRawData pResBuffer pReloc.VirtualAddress rsrc02.SizeOfRawData
734- Bytes.blit vBuff 0 pResBuffer pReloc.VirtualAddress vSize
735- // Copy $02 (resource raw into pResBuffer
736- Bytes.blit objBytes rsrc02.PointerToRawData pResBuffer rsrc01.SizeOfRawData rsrc02.SizeOfRawData
737-
738- // return the buffer
739- pResBuffer
740-
741- let linkNativeResourcesManaged ( unlinkedResources : byte [] list ) ( ulLinkedResourceBaseRVA : int32 ) ( fileType : PEFileType ) ( outputFilePath : string ) =
742- ignore fileType
743- ignore outputFilePath
744-
573+ let linkNativeResources ( unlinkedResources : byte [] list ) ( ulLinkedResourceBaseRVA : int32 ) =
745574 let resources =
746575 unlinkedResources
747576 |> Seq.map ( fun s -> new MemoryStream( s))
748577 |> Seq.map ( fun s ->
749- let res = CVTres. CvtResFile.ReadResFile s
578+ let res = CvtResFile.ReadResFile s
750579 s.Dispose()
751580 res)
752581 |> Seq.collect id
753582 // See MakeWin32ResourceList https://github.com/dotnet/roslyn/blob/f40b89234db51da1e1153c14af184e618504be41/src/Compilers/Core/Portable/Compilation/Compilation.cs
754583 |> Seq.map ( fun r ->
755- WriteNativeRes. Win32Resource( data = r.data, codePage = 0 u, languageId = uint32 r.LanguageId,
584+ Win32Resource( data = r.data, codePage = 0 u, languageId = uint32 r.LanguageId,
756585 id = int ( int16 r.pstringName.Ordinal), name = r.pstringName.theString,
757586 typeId = int ( int16 r.pstringType.Ordinal), typeName = r.pstringType.theString))
758587 let bb = new System.Reflection.Metadata.BlobBuilder()
759- WriteNativeRes. NativeResourceWriter.SerializeWin32Resources( bb, resources, ulLinkedResourceBaseRVA)
588+ NativeResourceWriter.SerializeWin32Resources( bb, resources, ulLinkedResourceBaseRVA)
760589 bb.ToArray()
761590
762- let linkNativeResources ( unlinkedResources : byte [] list ) ( ulLinkedResourceBaseRVA : int32 ) ( fileType : PEFileType ) ( outputFilePath : string ) =
763- #if ENABLE_ MONO_ SUPPORT
764- if IL.runningOnMono then
765- linkNativeResourcesManaged unlinkedResources ulLinkedResourceBaseRVA fileType outputFilePath
766- else
767- #endif
768- #if ! FX_ NO_ LINKEDRESOURCES
769- linkNativeResourcesViaCVTres unlinkedResources ulLinkedResourceBaseRVA fileType outputFilePath
770- #else
771- linkNativeResourcesManaged unlinkedResources ulLinkedResourceBaseRVA fileType outputFilePath
772- #endif
773-
774591let unlinkResource ( ulLinkedResourceBaseRVA : int32 ) ( pbLinkedResource : byte []) =
775592 let mutable nResNodes = 0
776593
0 commit comments