1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6/**********************************************************************
7svcworker.cpp -- logic for the runtime implementation of the native
8image service.
9
10Overview: the runtime implementation is accessed via a local COM
11server implemented in ngen.exe. That server is simply a stub that
12loads the most recent runtime and calls into the actual implementation
13in this file. There are three entrypoints in mscorwks.dll that
14are called by the local service in ngen.exe:
15
16NGenWorkerRegisterServer -- called to register ngen.exe as the current
17 COM server for CLSID_CorSvcWorker
18NGenWorkerUnregisterServer -- unregister ngen.exe as the current COM
19 server for CLSID_CorSvcWorker
20NGenWorkerEmbedding() -- called when COM invoked the COM server with
21 the "-Embedding" flag. Implements the logic for registering the class
22 factory for CLSID_CorSvcWorker and controlling the lifetime of the
23 COM server.
24**********************************************************************/
25
26#include "common.h"
27
28
29#ifdef FEATURE_APPX
30#include "AppXUtil.h"
31#endif
32
33ILocalServerLifetime *g_pLocalServerLifetime = NULL;
34
35SvcLogger::SvcLogger()
36 : pss(NULL),
37 pCorSvcLogger(NULL)
38{
39}
40
41inline void SvcLogger::CheckInit()
42{
43 if(pss == NULL)
44 {
45 StackSString* psstemp = new StackSString();
46 StackSString* pssOrig = InterlockedCompareExchangeT(&pss, psstemp, NULL);
47 if(pssOrig)
48 delete psstemp;
49 }
50}
51
52SvcLogger::~SvcLogger()
53{
54 if (pCorSvcLogger)
55 {
56// pCorSvcLogger->Release();
57 pCorSvcLogger = NULL;
58 }
59 if (pss)
60 delete pss;
61}
62
63void SvcLogger::ReleaseLogger()
64{
65 if (pCorSvcLogger)
66 {
67 pCorSvcLogger->Release();
68 pCorSvcLogger = NULL;
69 }
70}
71
72void SvcLogger::Printf(const CHAR *format, ...)
73{
74 StackSString s;
75
76 va_list args;
77 va_start(args, format);
78 s.VPrintf(format, args);
79 va_end(args);
80
81 if (pCorSvcLogger)
82 {
83 LogHelper(s);
84 }
85 else
86 {
87 wprintf( W("%s"), s.GetUnicode() );
88 }
89}
90
91void SvcLogger::SvcPrintf(const CHAR *format, ...)
92{
93 StackSString s;
94
95 va_list args;
96 va_start(args, format);
97 s.VPrintf(format, args);
98 va_end(args);
99
100 LogHelper(s);
101}
102
103void SvcLogger::Printf(const WCHAR *format, ...)
104{
105 StackSString s;
106
107 va_list args;
108 va_start(args, format);
109 s.VPrintf(format, args);
110 va_end(args);
111
112 if (pCorSvcLogger)
113 {
114 LogHelper(s);
115 }
116 else
117 {
118 wprintf( W("%s"), s.GetUnicode() );
119 }
120}
121
122void SvcLogger::Printf(CorSvcLogLevel logLevel, const WCHAR *format, ...)
123{
124 StackSString s;
125
126 va_list args;
127 va_start(args, format);
128 s.VPrintf(format, args);
129 va_end(args);
130
131 if (pCorSvcLogger)
132 {
133 LogHelper(s, logLevel);
134 }
135 else
136 {
137 wprintf( W("%s"), s.GetUnicode());
138 }
139}
140
141void SvcLogger::SvcPrintf(const WCHAR *format, ...)
142{
143 StackSString s;
144
145 va_list args;
146 va_start(args, format);
147 s.VPrintf(format, args);
148 va_end(args);
149
150 LogHelper(s);
151}
152
153void SvcLogger::Log(const WCHAR *message, CorSvcLogLevel logLevel)
154{
155 LogHelper(StackSString(message), logLevel);
156}
157
158void SvcLogger::LogHelper(SString s, CorSvcLogLevel logLevel)
159{
160 CheckInit();
161 pss->Append(s);
162
163 // Does s contain a newline?
164 SString::Iterator i = pss->Begin();
165 if (pss->FindASCII(i, "\n"))
166 {
167 if (pCorSvcLogger)
168 {
169 BSTRHolder bstrHolder(::SysAllocString(pss->GetUnicode()));
170 // Can't use the IfFailThrow macro here because in checked
171 // builds that macros will try to log an error message
172 // that will recursively return to this method.
173 HRESULT hr = pCorSvcLogger->Log(logLevel, bstrHolder);
174 if (FAILED(hr))
175 ThrowHR(hr);
176 }
177 pss->Clear();
178 }
179}
180
181void SvcLogger::SetSvcLogger(ICorSvcLogger *pCorSvcLoggerArg)
182{
183 ReleaseLogger();
184 this->pCorSvcLogger = pCorSvcLoggerArg;
185 if (pCorSvcLoggerArg)
186 {
187 pCorSvcLogger->AddRef();
188 }
189}
190
191BOOL SvcLogger::HasSvcLogger()
192{
193 return (this->pCorSvcLogger != NULL);
194}
195
196ICorSvcLogger* SvcLogger::GetSvcLogger()
197{
198 return pCorSvcLogger;
199}
200
201
202namespace
203{
204 SvcLogger *g_SvcLogger = NULL;
205}
206
207// As NGen is currently single-threaded, this function is intentionally not thread safe.
208// If necessary, change it into an interlocked function.
209SvcLogger *GetSvcLogger()
210{
211 if (g_SvcLogger == NULL)
212 {
213 g_SvcLogger = new SvcLogger();
214 }
215 return g_SvcLogger;
216}
217
218BOOL HasSvcLogger()
219{
220 if (g_SvcLogger != NULL)
221 {
222 return g_SvcLogger->HasSvcLogger();
223 }
224 return FALSE;
225}
226
227#ifdef CROSSGEN_COMPILE
228void SetSvcLogger(ICorSvcLogger *pCorSvcLogger)
229{
230 GetSvcLogger()->SetSvcLogger(pCorSvcLogger);
231}
232#endif
233
234