Option Explicit

'-----------------------------------------------------
' プロセス関連、メモリ関連
'-----------------------------------------------------

#If Win64 Then
    
    Private Declare PtrSafe Function CloseHandle Lib "kernel32" _
        (ByVal hObject As Long) As Long

    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (Destination As Any, _
         Source As Any, _
         ByVal Length As Long)

#Else
    
    Private Declare Function CloseHandle Lib "kernel32" _
        (ByVal hObject As Long) As Long

    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (Destination As Any, _
         Source As Any, _
         ByVal Length As Long)

#End If


'--------------------------------------------------------
' マップドメモリ
'--------------------------------------------------------

Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Long
End Type

#If Win64 Then

    ' ファイルマップの生成  注:hFile ⇒ LongLong
    Private Declare PtrSafe Function CreateFileMapping _
        Lib "kernel32" Alias "CreateFileMappingA" _
        (ByVal hFile As LongLong, _
         ByRef lpFileMappigAttributes As SECURITY_ATTRIBUTES, _
         ByVal flProtect As Long, _
         ByVal dwMaximumSizeHigh As Long, _
         ByVal dwMaximumSizeLow As Long, _
         ByVal lpName As String _
         ) As Long
    
    
    
    ' ファイルマップのオープン
    Public Declare PtrSafe Function OpenFileMapping _
        Lib "kernel32" Alias "OpenFileMappingA" _
         (ByVal dwDesiredAccess As Long, _
         ByVal bInheritHandle As Long, _
         ByVal lpName As String _
         ) As Long
    
    
    ' 指定された範囲のデータを書き込む
    Private Declare PtrSafe Function FlushViewOfFile Lib "kernel32" _
        (ByRef lpBaseAddress As Any, _
         ByVal dwNumberOfBytesToFlush As Long _
         ) As Long
    
    ' 呼び出し側プロセスのアドレス空間にファイルのビューをマップ
    Private Declare PtrSafe Function MapViewOfFile Lib "kernel32" ( _
        ByVal hFileMappingObject As Long, _
        ByVal dwDesiredAccess As Long, _
        ByVal dwFileOffsetHigh As Long, _
        ByVal dwFileOffsetLow As Long, _
        ByVal dwNumberOfBytesToMap As Long) As Long
    
    Private Declare PtrSafe Function UnmapViewOfFile Lib "kernel32" ( _
        lpBaseAddress As Long) As Long

#Else

    ' ファイルマップの生成
    Private Declare Function CreateFileMapping _
        Lib "kernel32" Alias "CreateFileMappingA" _
        (ByVal hFile As Long, _
         ByRef lpFileMappigAttributes As SECURITY_ATTRIBUTES, _
         ByVal flProtect As Long, _
         ByVal dwMaximumSizeHigh As Long, _
         ByVal dwMaximumSizeLow As Long, _
         ByVal lpName As String _
         ) As Long
    
    
    
    ' ファイルマップのオープン
    Public Declare Function OpenFileMapping _
        Lib "kernel32" Alias "OpenFileMappingA" _
         (ByVal dwDesiredAccess As Long, _
         ByVal bInheritHandle As Long, _
         ByVal lpName As String _
         ) As Long
    
    
    ' 指定された範囲のデータを書き込む
    Private Declare Function FlushViewOfFile Lib "kernel32" _
        (ByRef lpBaseAddress As Any, _
         ByVal dwNumberOfBytesToFlush As Long _
         ) As Long
    
    ' 呼び出し側プロセスのアドレス空間にファイルのビューをマップ
    Private Declare Function MapViewOfFile Lib "kernel32" ( _
        ByVal hFileMappingObject As Long, _
        ByVal dwDesiredAccess As Long, _
        ByVal dwFileOffsetHigh As Long, _
        ByVal dwFileOffsetLow As Long, _
        ByVal dwNumberOfBytesToMap As Long) As Long
    
    Private Declare Function UnmapViewOfFile Lib "kernel32" ( _
        lpBaseAddress As Long) As Long


#End If

Private Const PAGE_READWRITE = 4
'
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SECTION_QUERY = &H1
Private Const SECTION_MAP_WRITE = &H2
Private Const SECTION_MAP_READ = &H4
Private Const SECTION_MAP_EXECUTE = &H8
Private Const SECTION_EXTEND_SIZE = &H10
Private Const SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or _
                                   SECTION_MAP_WRITE Or SECTION_MAP_READ Or _
                                   SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE
Private Const SEC_COMMIT = &H8000000
Private Const FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS
'

'/////////////////////////////////////////////////////////////////

Public Function CallExe(ExeName As String, ParamArray Arg()) As String
'
' Exeファイルコール
'
    Const MapName = "MAP_EXE-CALL"
    Const MapSize = "4096"
    
    
    Dim objWs As New WshShell
    
    Dim hFileMap As Long

    Dim Param As String         'EXE   へのパラメータ
    Dim ShellParam As String    'Shell へのパラメータ

    Dim f As String             'ファイルパス

    Dim pId As Long             'プロセスID
    Dim i As Integer
    
    Dim rc As Long
    

    MakeFileMap MapName, hFileMap, MapSize 'ファイルマップ作成

    f = ExeName
    If InStr(1, f, " ") Then f = """" & f & """"  'EXEファイルのパス−半角スペースがあった場合

    Param = " -user_map_name " & MapName & " " & MapSize & " -user_args"

    For i = 0 To UBound(Arg)
        If InStr(1, Arg(i), " ") Then Arg(i) = """" & Arg(i) & """" '半角スペースがあった場合
        Param = Param & " " & Arg(i)
    Next i

    ShellParam = f & Param
    rc = objWs.Run(ShellParam, vbHide, True)    '起動−完了まで待つ

    If rc = 0 Then  'OK?
        CallExe = GetStrDataFromShared(MapName, MapSize)  '戻り値
    End If
    
    CloseHandle hFileMap                'ファイルマップ開放

    Set objWs = Nothing
    
End Function

Private Function GetStrDataFromShared(MapName As String, DtLen As Long) As String
'
' データを共有メモリ(マップドファイル)から読込む
'
    Dim lpFileMap As Long
    Dim hFileMap As Long
    Dim Dt() As Byte
    Dim tmp As String
    Dim p As Long

    tmp = String(DtLen, Chr(0))
    hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, MapName)
    lpFileMap = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0&, 0&, 0&)
    If lpFileMap <> 0 Then
        CopyMemory ByVal tmp, ByVal lpFileMap, DtLen
        p = InStr(tmp, Chr(0))
        If p = 0 Then p = DtLen
        GetStrDataFromShared = Left(tmp, MyMin(p - 1, DtLen))
    Else
        GetStrDataFromShared = ""
    End If

    GoTo MyEnd

MyErr:

MyEnd:
    UnmapViewOfFile lpFileMap
    CloseHandle hFileMap

End Function


Public Function MyMin(Dt1, Dt2) '小さい方を返す
    If Dt1 < Dt2 Then
        MyMin = Dt1
    Else
        MyMin = Dt2
    End If
End Function


'/////////////////////////////////////////////
'
' ファイルマップを作成
'
' 引数  :
'    strFileMapName - ファイルマップ名
'    hFileMap       - ファイルマップハンドル
'    Size           - ファイルマップサイズ
'
' 戻り値: True:成功  False:失敗
'
Public Function MakeFileMap(ByVal strFileMapName As String, _
                            ByRef hFileMap As Long, _
                            Size As Long) As Long
                            
    Dim SecurityAttribute As SECURITY_ATTRIBUTES
    Dim ret As Long
    Dim DummyBuffer As String
    Dim lpFileMap As Long

    DummyBuffer = String(Size, Chr(0))
    
    hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, strFileMapName)
    If (hFileMap = 0) Then ' 新規ファイルマップ生成

        SecurityAttribute.bInheritHandle = 0&               ' ハンドル継承無し
        SecurityAttribute.lpSecurityDescriptor = 0&         ' セキュリティをセット無し
        SecurityAttribute.nLength = Len(SecurityAttribute)  ' 構造体のサイズ
        
        hFileMap = CreateFileMapping(-1&, _
                                     SecurityAttribute, _
                                     PAGE_READWRITE Or SEC_COMMIT, _
                                     0&, _
                                     Size, _
                                     strFileMapName)
        If (hFileMap = 0) Then Exit Function    ' 失敗!
        
        lpFileMap = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0&, 0&, 0&)
        If lpFileMap = 0 Then Exit Function

        CopyMemory ByVal lpFileMap, DummyBuffer, Size 'データを初期化
        ret = FlushViewOfFile(ByVal lpFileMap, Size)
        
        MakeFileMap = lpFileMap
    
    End If
    
End Function