-
Notifications
You must be signed in to change notification settings - Fork 23
/
InProcStart.cpp
135 lines (112 loc) · 3.52 KB
/
InProcStart.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "ist.h"
#include <process.h>
#include "resource.h"
#include "startVM.h"
//#import "DolphinSmalltalk.tlb" no_namespace raw_interfaces_only
#include "DolphinSmalltalk_i.h"
//#include "VMExcept.h"
#ifndef TO_GO
#include "..\Launcher\ImageFileMapping.h"
#endif
/////////////////////////////////////////////////////////////////////
struct VMEntryArgs
{
HINSTANCE hInstance;
LPVOID imageData;
DWORD imageSize;
LPCWSTR fileName;
IStream* piMarshalledOuter;
CLSCTX clsctx;
};
static VMEntryArgs argBlock;
// Disable warning about combination of SEH and destructors
#pragma warning(disable:4509)
int __stdcall StartVM(HMODULE hModule,
LPVOID imageData, DWORD imageSize, LPCWSTR fileName,
IUnknown* punkOuter, CLSCTX clsctx)
{
IDolphinStart* piDolphin = NULL;
HRESULT hr = CreateVM(CLSCTX_INPROC_SERVER, NULL, NULL, __uuidof(IDolphinStart), reinterpret_cast<void**>(&piDolphin));
if (FAILED(hr))
return hr;
#ifndef TO_GO
ImageFileMapping imageFile;
if (imageData == NULL)
{
int ret = imageFile.Open(fileName);
if (ret < 0)
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
if (imageFile.GetType() != ImageFileMapping::ISTIMAGE)
return E_FAIL;
imageData = imageFile.GetRawData();
imageSize = imageFile.GetRawSize();
}
// Perform a version check to verify that the embedded image matches the loaded VM
ImageHeader* pHeader = &(reinterpret_cast<ISTImageHeader*>(imageData)->header);
VS_FIXEDFILEINFO vi;
hr = piDolphin->GetVersionInfo(&vi);
if (FAILED(hr))
return hr;
if (pHeader->versionMS != vi.dwProductVersionMS)
return ErrorVMVersionMismatch(pHeader, &vi);
#else
// A ToGo image is bound with its VM, and must therefore be of the correct version
#endif
hr = piDolphin->Initialise(hModule, fileName, imageData, imageSize, /*IsDevSys*/0);
if (FAILED(hr))
return hr;
hr = piDolphin->Run(punkOuter);
piDolphin->Release();
return hr;
}
static HRESULT VMStart(VMEntryArgs* pArgs)
{
IUnknown* punkOuter;
if (pArgs->piMarshalledOuter)
{
HRESULT hr = ::CoGetInterfaceAndReleaseStream(pArgs->piMarshalledOuter, IID_IUnknown, reinterpret_cast<void**>(&punkOuter));
if (FAILED(hr))
return ReportError(IDP_FAILEDTOUNMARSHALOUTER);
}
else
punkOuter = NULL;
return StartVM(pArgs->hInstance,
pArgs->imageData, pArgs->imageSize, pArgs->fileName,
punkOuter, pArgs->clsctx);
}
// Dolphin thread main routine - only exits when SE_VMEXIT exception is thrown (in the normal case)
static UINT __stdcall DolphinMain(void* pArgs)
{
#ifdef _DEBUG
trace(L"%#x: DolphinMain\n", GetCurrentThreadId());
#endif
::CoInitialize(NULL);
HRESULT hr = VMStart(reinterpret_cast<VMEntryArgs*>(pArgs));
::CoUninitialize();
return DecodeHRESULT(hr);
}
// Spawn off the main Dolphin thread and return its handle
// Note the caller must make sure that the two strings don't go out of scope
HRESULT __stdcall VMEntry(HINSTANCE hInstance,
LPVOID imageData, UINT imageSize, LPCWSTR fileName, IUnknown* punkOuter, CLSCTX ctx,
HANDLE& hThread)
{
argBlock.hInstance = hInstance;
argBlock.imageData = imageData;
argBlock.imageSize = imageSize;
argBlock.fileName = fileName;
argBlock.clsctx = ctx;
UINT dwThreadId;
if (punkOuter)
{
HRESULT hr = ::CoMarshalInterThreadInterfaceInStream(IID_IUnknown, punkOuter, &argBlock.piMarshalledOuter);
if (FAILED(hr))
return ReportError(IDP_FAILEDTOMARSHALOUTER);
}
else
argBlock.piMarshalledOuter = NULL;
hThread = (HANDLE)_beginthreadex(NULL, 0, &DolphinMain, &argBlock, 0, &dwThreadId);
if (hThread == (HANDLE)-1)
return ReportError(IDP_FAILTOSTARTTHREAD);
return S_OK;
}