VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/VBoxNetNAT.cpp@ 38636

Last change on this file since 38636 was 38636, checked in by vboxsync, 13 years ago

*,IPRT: Redid the ring-3 init to always convert the arguments to UTF-8.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.4 KB
Line 
1/* $Id: VBoxNetNAT.cpp 38636 2011-09-05 13:49:45Z vboxsync $ */
2/** @file
3 * VBoxNetNAT - NAT Service for connecting to IntNet.
4 */
5
6/*
7 * Copyright (C) 2009 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @page pg_net_nat VBoxNetNAT
19 *
20 * Write a few words...
21 *
22 */
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include <iprt/net.h>
28#include <iprt/initterm.h>
29#include <iprt/alloca.h>
30#include <iprt/err.h>
31#include <iprt/time.h>
32#include <iprt/timer.h>
33#include <iprt/thread.h>
34#include <iprt/stream.h>
35#include <iprt/path.h>
36#include <iprt/param.h>
37#include <iprt/pipe.h>
38#include <iprt/getopt.h>
39#include <iprt/string.h>
40#include <iprt/mem.h>
41#include <iprt/message.h>
42#include <iprt/req.h>
43#include <iprt/file.h>
44#include <iprt/semaphore.h>
45#define LOG_GROUP LOG_GROUP_NAT_SERVICE
46#include <VBox/log.h>
47
48#include <VBox/sup.h>
49#include <VBox/intnet.h>
50#include <VBox/intnetinline.h>
51#include <VBox/vmm/pdmnetinline.h>
52#include <VBox/vmm/vmm.h>
53#include <VBox/version.h>
54
55#include <vector>
56#include <string>
57
58#include "../NetLib/VBoxNetLib.h"
59#include "../NetLib/VBoxNetBaseService.h"
60#include <libslirp.h>
61
62#ifdef RT_OS_WINDOWS /* WinMain */
63# include <Windows.h>
64# include <stdlib.h>
65#else
66# include <errno.h>
67#endif
68
69
70
71/*******************************************************************************
72* Structures and Typedefs *
73*******************************************************************************/
74
75class VBoxNetNAT : public VBoxNetBaseService
76{
77public:
78 VBoxNetNAT();
79 virtual ~VBoxNetNAT();
80 void usage(void);
81 void run(void);
82 void init(void);
83
84public:
85 PNATState m_pNATState;
86 RTNETADDRIPV4 m_Ipv4Netmask;
87 bool m_fPassDomain;
88 RTTHREAD m_ThrNAT;
89 RTTHREAD m_ThrSndNAT;
90 RTTHREAD m_ThrUrgSndNAT;
91#ifdef RT_OS_WINDOWS
92 HANDLE m_hWakeupEvent;
93#else
94 RTPIPE m_hPipeWrite;
95 RTPIPE m_hPipeRead;
96#endif
97 /** Queue for NAT-thread-external events. */
98 /** event to wakeup the guest receive thread */
99 RTSEMEVENT m_EventSend;
100 /** event to wakeup the guest urgent receive thread */
101 RTSEMEVENT m_EventUrgSend;
102
103 PRTREQQUEUE m_pReqQueue;
104 PRTREQQUEUE m_pSendQueue;
105 PRTREQQUEUE m_pUrgSendQueue;
106 volatile uint32_t cUrgPkt;
107 volatile uint32_t cPkt;
108 bool fIsRunning;
109};
110
111
112
113/*******************************************************************************
114* Global Variables *
115*******************************************************************************/
116/** Pointer to the NAT server. */
117class VBoxNetNAT *g_pNAT;
118static DECLCALLBACK(int) AsyncIoThread(RTTHREAD pThread, void *pvUser);
119static DECLCALLBACK(int) natSndThread(RTTHREAD pThread, void *pvUser);
120static DECLCALLBACK(int) natUrgSndThread(RTTHREAD pThread, void *pvUser);
121static void SendWorker(struct mbuf *m, size_t cb);
122static void IntNetSendWorker(bool urg, void *pvFrame, size_t cbFrame, struct mbuf *m);
123
124
125static void natNotifyNATThread(void)
126{
127 int rc;
128#ifndef RT_OS_WINDOWS
129 /* kick select() */
130 size_t cbIgnored;
131 rc = RTPipeWrite(g_pNAT->m_hPipeWrite, "", 1, &cbIgnored);
132#else
133 /* kick WSAWaitForMultipleEvents */
134 rc = WSASetEvent(g_pNAT->hWakeupEvent);
135#endif
136 AssertRC(rc);
137}
138
139VBoxNetNAT::VBoxNetNAT()
140{
141#if defined(RT_OS_WINDOWS)
142 /*@todo check if we can remove this*/
143 VBoxNetBaseService();
144#endif
145 m_enmTrunkType = kIntNetTrunkType_WhateverNone;
146 m_TrunkName = "";
147 m_MacAddress.au8[0] = 0x08;
148 m_MacAddress.au8[1] = 0x00;
149 m_MacAddress.au8[2] = 0x27;
150 m_MacAddress.au8[3] = 0x40;
151 m_MacAddress.au8[4] = 0x41;
152 m_MacAddress.au8[5] = 0x42;
153 m_Ipv4Address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 1)));
154 m_Ipv4Netmask.u = 0xffff0000;
155 cPkt = 0;
156 cUrgPkt = 0;
157}
158
159VBoxNetNAT::~VBoxNetNAT() { }
160void VBoxNetNAT::init()
161{
162 int rc;
163
164 /*
165 * Initialize slirp.
166 */
167 rc = slirp_init(&m_pNATState, m_Ipv4Address.u, m_Ipv4Netmask.u, m_fPassDomain, false, 0, this);
168 AssertReleaseRC(rc);
169
170 slirp_set_ethaddr_and_activate_port_forwarding(m_pNATState, &m_MacAddress.au8[0], INADDR_ANY);
171#ifndef RT_OS_WINDOWS
172 /*
173 * Create the control pipe.
174 */
175 rc = RTPipeCreate(&m_hPipeRead, &m_hPipeWrite, 0 /*fFlags*/);
176 AssertReleaseRC(rc);
177#else
178 m_hWakeupEvent = CreateEvent(NULL, FALSE, FALSE, NULL); /* auto-reset event */
179 AssertReleaseRC(m_hWakeupEvent != NULL);
180 slirp_register_external_event(m_pNATState, m_hWakeupEvent, VBOX_WAKEUP_EVENT_INDEX);
181#endif
182 rc = RTReqCreateQueue(&m_pReqQueue);
183 AssertReleaseRC(rc);
184
185 rc = RTReqCreateQueue(&m_pSendQueue);
186 AssertReleaseRC(rc);
187
188 rc = RTReqCreateQueue(&m_pUrgSendQueue);
189 AssertReleaseRC(rc);
190
191 rc = RTThreadCreate(&m_ThrNAT, AsyncIoThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "NAT");
192 rc = RTThreadCreate(&m_ThrSndNAT, natSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "SndNAT");
193 rc = RTThreadCreate(&m_ThrUrgSndNAT, natUrgSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "UrgSndNAT");
194 rc = RTSemEventCreate(&m_EventSend);
195 rc = RTSemEventCreate(&m_EventUrgSend);
196 AssertReleaseRC(rc);
197}
198
199/* Mandatory functions */
200void VBoxNetNAT::run()
201{
202
203 /*
204 * The loop.
205 */
206 fIsRunning = true;
207 PINTNETRINGBUF pRingBuf = &m_pIfBuf->Recv;
208 //RTThreadSetType(RTThreadSelf(), RTTHREADTYPE_IO);
209 for (;;)
210 {
211 /*
212 * Wait for a packet to become available.
213 */
214 INTNETIFWAITREQ WaitReq;
215 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
216 WaitReq.Hdr.cbReq = sizeof(WaitReq);
217 WaitReq.pSession = m_pSession;
218 WaitReq.hIf = m_hIf;
219 WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */ /** @todo fix interruptability in SrvIntNet! */
220#if 1
221 RTReqProcess(m_pSendQueue, 0);
222 RTReqProcess(m_pUrgSendQueue, 0);
223#endif
224 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
225 if (RT_FAILURE(rc))
226 {
227 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
228 continue;
229 LogRel(("VBoxNetNAT: VMMR0_DO_INTNET_IF_WAIT returned %Rrc\n", rc));
230 return;
231 }
232
233 /*
234 * Process the receive buffer.
235 */
236 PCINTNETHDR pHdr;
237 while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
238 {
239 uint16_t const u16Type = pHdr->u16Type;
240 if (RT_LIKELY( u16Type == INTNETHDR_TYPE_FRAME
241 || u16Type == INTNETHDR_TYPE_GSO))
242 {
243 size_t cbFrame = pHdr->cbFrame;
244 size_t cbIgnored;
245 void *pvSlirpFrame;
246 struct mbuf *m;
247 if (u16Type == INTNETHDR_TYPE_FRAME)
248 {
249 m = slirp_ext_m_get(g_pNAT->m_pNATState, cbFrame, &pvSlirpFrame, &cbIgnored);
250 if (!m)
251 {
252 LogRel(("NAT: Can't allocate send buffer cbFrame=%u\n", cbFrame));
253 break;
254 }
255 memcpy(pvSlirpFrame, IntNetHdrGetFramePtr(pHdr, m_pIfBuf), cbFrame);
256 IntNetRingSkipFrame(&m_pIfBuf->Recv);
257
258 /* don't wait, we may have to wakeup the NAT thread first */
259 rc = RTReqCallEx(m_pReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
260 (PFNRT)SendWorker, 2, m, cbFrame);
261 AssertReleaseRC(rc);
262 }
263 else
264 {
265 /** @todo pass these unmodified. */
266 PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m_pIfBuf);
267 if (!PDMNetGsoIsValid(pGso, cbFrame, cbFrame - sizeof(*pGso)))
268 {
269 IntNetRingSkipFrame(&m_pIfBuf->Recv);
270 STAM_REL_COUNTER_INC(&m_pIfBuf->cStatBadFrames);
271 continue;
272 }
273
274 uint8_t abHdrScratch[256];
275 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame - sizeof(*pGso));
276 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
277 {
278 uint32_t cbSegFrame;
279 void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)(pGso + 1), cbFrame, abHdrScratch,
280 iSeg, cSegs, &cbSegFrame);
281 m = slirp_ext_m_get(g_pNAT->m_pNATState, cbFrame, &pvSlirpFrame, &cbIgnored);
282 if (!m)
283 {
284 LogRel(("NAT: Can't allocate send buffer cbSegFrame=%u seg=%u/%u\n", cbSegFrame, iSeg, cSegs));
285 break;
286 }
287 memcpy(pvSlirpFrame, pvSegFrame, cbFrame);
288
289 rc = RTReqCallEx(m_pReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
290 (PFNRT)SendWorker, 2, m, cbSegFrame);
291 AssertReleaseRC(rc);
292 }
293 IntNetRingSkipFrame(&m_pIfBuf->Recv);
294 }
295
296#ifndef RT_OS_WINDOWS
297 /* kick select() */
298 size_t cbIgnored;
299 rc = RTPipeWrite(m_hPipeWrite, "", 1, &cbIgnored);
300 AssertRC(rc);
301#else
302 /* kick WSAWaitForMultipleEvents */
303 rc = WSASetEvent(m_hWakeupEvent);
304 AssertRelease(rc == TRUE);
305#endif
306 }
307 else if (u16Type == INTNETHDR_TYPE_PADDING)
308 IntNetRingSkipFrame(&m_pIfBuf->Recv);
309 else
310 {
311 IntNetRingSkipFrame(&m_pIfBuf->Recv);
312 STAM_REL_COUNTER_INC(&m_pIfBuf->cStatBadFrames);
313 }
314 }
315
316 }
317 fIsRunning = false;
318}
319
320void VBoxNetNAT::usage()
321{
322}
323
324/**
325 * Entry point.
326 */
327extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
328{
329 Log2(("NAT: main\n"));
330 g_pNAT = new VBoxNetNAT();
331 Log2(("NAT: parsing command line\n"));
332 int rc = g_pNAT->parseArgs(argc - 1, argv + 1);
333 if (!rc)
334 {
335 Log2(("NAT: initialization\n"));
336 g_pNAT->init();
337 Log2(("NAT: try go online\n"));
338 g_pNAT->tryGoOnline();
339 Log2(("NAT: main loop\n"));
340 g_pNAT->run();
341 }
342 delete g_pNAT;
343 return 0;
344}
345
346/** slirp's hooks */
347extern "C" int slirp_can_output(void * pvUser)
348{
349 return 1;
350}
351
352extern "C" void slirp_urg_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
353{
354 int rc = RTReqCallEx(g_pNAT->m_pUrgSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
355 (PFNRT)IntNetSendWorker, 4, (uintptr_t)1, (uintptr_t)pu8Buf, (uintptr_t)cb, (uintptr_t)m);
356 ASMAtomicIncU32(&g_pNAT->cUrgPkt);
357 RTSemEventSignal(g_pNAT->m_EventUrgSend);
358 AssertReleaseRC(rc);
359}
360extern "C" void slirp_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
361{
362 AssertRelease(g_pNAT == pvUser);
363 int rc = RTReqCallEx(g_pNAT->m_pSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
364 (PFNRT)IntNetSendWorker, 4, (uintptr_t)0, (uintptr_t)pu8Buf, (uintptr_t)cb, (uintptr_t)m);
365 ASMAtomicIncU32(&g_pNAT->cPkt);
366 RTSemEventSignal(g_pNAT->m_EventSend);
367 AssertReleaseRC(rc);
368}
369
370extern "C" void slirp_output_pending(void *pvUser)
371{
372 AssertMsgFailed(("Unimplemented"));
373}
374
375/**
376 * Worker function for drvNATSend().
377 * @thread "NAT" thread.
378 */
379static void SendWorker(struct mbuf *m, size_t cb)
380{
381 slirp_input(g_pNAT->m_pNATState, m, cb);
382}
383
384static void IntNetSendWorker(bool urg, void *pvFrame, size_t cbFrame, struct mbuf *m)
385{
386 Log2(("VBoxNetNAT: going to send some bytes ... \n"));
387 VBoxNetNAT *pThis = g_pNAT;
388 INTNETIFSENDREQ SendReq;
389 int rc;
390
391 if (!urg)
392 {
393 while (ASMAtomicReadU32(&g_pNAT->cUrgPkt) != 0
394 || ASMAtomicReadU32(&g_pNAT->cPkt) == 0)
395 rc = RTSemEventWait(g_pNAT->m_EventSend, RT_INDEFINITE_WAIT);
396 }
397 else
398 {
399 while (ASMAtomicReadU32(&g_pNAT->cUrgPkt) == 0)
400 rc = RTSemEventWait(g_pNAT->m_EventUrgSend, RT_INDEFINITE_WAIT);
401 }
402 rc = IntNetRingWriteFrame(&pThis->m_pIfBuf->Send, pvFrame, cbFrame);
403 if (RT_FAILURE(rc))
404 {
405 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
406 SendReq.Hdr.cbReq = sizeof(SendReq);
407 SendReq.pSession = pThis->m_pSession;
408 SendReq.hIf = pThis->m_hIf;
409 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
410
411 rc = IntNetRingWriteFrame(&pThis->m_pIfBuf->Send, pvFrame, cbFrame);
412
413 }
414 if (RT_SUCCESS(rc))
415 {
416 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
417 SendReq.Hdr.cbReq = sizeof(SendReq);
418 SendReq.pSession = pThis->m_pSession;
419 SendReq.hIf = pThis->m_hIf;
420 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
421 }
422 if (RT_FAILURE(rc))
423 Log2(("VBoxNetNAT: Failed to send packet; rc=%Rrc\n", rc));
424
425 if (!urg)
426 {
427 ASMAtomicDecU32(&g_pNAT->cPkt);
428 }
429 else {
430 if (ASMAtomicDecU32(&g_pNAT->cUrgPkt) == 0)
431 RTSemEventSignal(g_pNAT->m_EventSend);
432 }
433 natNotifyNATThread();
434 slirp_ext_m_free(pThis->m_pNATState, m, (uint8_t *)pvFrame);
435}
436
437static DECLCALLBACK(int) AsyncIoThread(RTTHREAD pThread, void *pvUser)
438{
439 VBoxNetNAT *pThis = (VBoxNetNAT *)pvUser;
440 int nFDs = -1;
441#ifdef RT_OS_WINDOWS
442 HANDLE *pahEvents = slirp_get_events(pThis->m_pNATState);
443#else /* RT_OS_WINDOWS */
444 unsigned int cPollNegRet = 0;
445#endif /* !RT_OS_WINDOWS */
446
447 LogFlow(("drvNATAsyncIoThread: pThis=%p\n", pThis));
448
449 /*
450 * Polling loop.
451 */
452 for(;;)
453 {
454 /*
455 * To prevent concurrent execution of sending/receiving threads
456 */
457#ifndef RT_OS_WINDOWS
458 nFDs = slirp_get_nsock(pThis->m_pNATState);
459 /* allocation for all sockets + Management pipe */
460 struct pollfd *polls = (struct pollfd *)RTMemAlloc((1 + nFDs) * sizeof(struct pollfd) + sizeof(uint32_t));
461 if (polls == NULL)
462 return VERR_NO_MEMORY;
463
464 /* don't pass the management pipe */
465 slirp_select_fill(pThis->m_pNATState, &nFDs, &polls[1]);
466 unsigned int cMsTimeout = slirp_get_timeout_ms(pThis->m_pNATState);
467
468 polls[0].fd = RTPipeToNative(pThis->m_hPipeRead);
469 /* POLLRDBAND usually doesn't used on Linux but seems used on Solaris */
470 polls[0].events = POLLRDNORM|POLLPRI|POLLRDBAND;
471 polls[0].revents = 0;
472
473 int cChangedFDs = poll(polls, nFDs + 1, cMsTimeout);
474 if (cChangedFDs < 0)
475 {
476 if (errno == EINTR)
477 {
478 Log2(("NAT: signal was caught while sleep on poll\n"));
479 /* No error, just process all outstanding requests but don't wait */
480 cChangedFDs = 0;
481 }
482 else if (cPollNegRet++ > 128)
483 {
484 LogRel(("NAT:Poll returns (%s) suppressed %d\n", strerror(errno), cPollNegRet));
485 cPollNegRet = 0;
486 }
487 }
488
489 if (cChangedFDs >= 0)
490 {
491 slirp_select_poll(pThis->m_pNATState, &polls[1], nFDs);
492 if (polls[0].revents & (POLLRDNORM|POLLPRI|POLLRDBAND))
493 {
494 /* drain the pipe
495 *
496 * Note!
497 * drvNATSend decoupled so we don't know how many times
498 * device's thread sends before we've entered multiplex,
499 * so to avoid false alarm drain pipe here to the very end
500 *
501 * @todo: Probably we should counter drvNATSend to count how
502 * deep pipe has been filed before drain.
503 *
504 */
505 /** @todo XXX: Make it reading exactly we need to drain the
506 * pipe. */
507 char ch;
508 size_t cbRead;
509 RTPipeRead(pThis->m_hPipeRead, &ch, 1, &cbRead);
510 }
511 }
512 /* process _all_ outstanding requests but don't wait */
513 RTReqProcess(pThis->m_pReqQueue, 0);
514 RTMemFree(polls);
515
516#else /* RT_OS_WINDOWS */
517 nFDs = -1;
518 slirp_select_fill(pThis->m_pNATState, &nFDs);
519 DWORD dwEvent = WSAWaitForMultipleEvents(nFDs, pahEvents, FALSE,
520 slirp_get_timeout_ms(pThis->m_pNATState),
521 FALSE);
522 if ( (dwEvent < WSA_WAIT_EVENT_0 || dwEvent > WSA_WAIT_EVENT_0 + nFDs - 1)
523 && dwEvent != WSA_WAIT_TIMEOUT)
524 {
525 int error = WSAGetLastError();
526 LogRel(("NAT: WSAWaitForMultipleEvents returned %d (error %d)\n", dwEvent, error));
527 RTAssertReleasePanic();
528 }
529
530 if (dwEvent == WSA_WAIT_TIMEOUT)
531 {
532 /* only check for slow/fast timers */
533 slirp_select_poll(pThis->m_pNATState, /* fTimeout=*/true, /*fIcmp=*/false);
534 continue;
535 }
536
537 /* poll the sockets in any case */
538 slirp_select_poll(pThis->m_pNATState, /* fTimeout=*/false, /* fIcmp=*/(dwEvent == WSA_WAIT_EVENT_0));
539 /* process _all_ outstanding requests but don't wait */
540 RTReqProcess(pThis->m_pReqQueue, 0);
541#endif /* RT_OS_WINDOWS */
542 }
543
544 return VINF_SUCCESS;
545}
546
547static DECLCALLBACK(int) natSndThread(RTTHREAD pThread, void *pvUser)
548{
549 while (g_pNAT->fIsRunning)
550 RTReqProcess(g_pNAT->m_pSendQueue, 0);
551 return VINF_SUCCESS;
552}
553static DECLCALLBACK(int) natUrgSndThread(RTTHREAD pThread, void *pvUser)
554{
555 while (g_pNAT->fIsRunning)
556 RTReqProcess(g_pNAT->m_pUrgSendQueue, 0);
557 return VINF_SUCCESS;
558}
559
560#ifndef VBOX_WITH_HARDENING
561
562int main(int argc, char **argv, char **envp)
563{
564 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
565 if (RT_FAILURE(rc))
566 return RTMsgInitFailure(rc);
567
568 return TrustedMain(argc, argv, envp);
569}
570
571# if defined(RT_OS_WINDOWS)
572
573static LRESULT CALLBACK WindowProc(HWND hwnd,
574 UINT uMsg,
575 WPARAM wParam,
576 LPARAM lParam
577)
578{
579 if(uMsg == WM_DESTROY)
580 {
581 PostQuitMessage(0);
582 return 0;
583 }
584 return DefWindowProc (hwnd, uMsg, wParam, lParam);
585}
586
587static LPCSTR g_WndClassName = "VBoxNetNatClass";
588
589static DWORD WINAPI MsgThreadProc(__in LPVOID lpParameter)
590{
591 HWND hwnd = 0;
592 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);
593 bool bExit = false;
594
595 /* Register the Window Class. */
596 WNDCLASS wc;
597 wc.style = 0;
598 wc.lpfnWndProc = WindowProc;
599 wc.cbClsExtra = 0;
600 wc.cbWndExtra = sizeof(void *);
601 wc.hInstance = hInstance;
602 wc.hIcon = NULL;
603 wc.hCursor = NULL;
604 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
605 wc.lpszMenuName = NULL;
606 wc.lpszClassName = g_WndClassName;
607
608 ATOM atomWindowClass = RegisterClass(&wc);
609
610 if (atomWindowClass != 0)
611 {
612 /* Create the window. */
613 hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
614 g_WndClassName, g_WndClassName,
615 WS_POPUPWINDOW,
616 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
617
618 if (hwnd)
619 {
620 SetWindowPos(hwnd, HWND_TOPMOST, -200, -200, 0, 0,
621 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
622
623 MSG msg;
624 while (GetMessage(&msg, NULL, 0, 0))
625 {
626 TranslateMessage(&msg);
627 DispatchMessage(&msg);
628 }
629
630 DestroyWindow (hwnd);
631
632 bExit = true;
633 }
634
635 UnregisterClass (g_WndClassName, hInstance);
636 }
637
638 if(bExit)
639 {
640 /* no need any accuracy here, in anyway the DHCP server usually gets terminated with TerminateProcess */
641 exit(0);
642 }
643
644 return 0;
645}
646
647
648
649/** (We don't want a console usually.) */
650int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
651{
652#if 0
653 NOREF(hInstance); NOREF(hPrevInstance); NOREF(lpCmdLine); NOREF(nCmdShow);
654
655 HANDLE hThread = CreateThread(
656 NULL, /*__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, */
657 0, /*__in SIZE_T dwStackSize, */
658 MsgThreadProc, /*__in LPTHREAD_START_ROUTINE lpStartAddress,*/
659 NULL, /*__in_opt LPVOID lpParameter,*/
660 0, /*__in DWORD dwCreationFlags,*/
661 NULL /*__out_opt LPDWORD lpThreadId*/
662 );
663
664 if(hThread != NULL)
665 CloseHandle(hThread);
666
667#endif
668 return main(__argc, __argv, environ);
669}
670# endif /* RT_OS_WINDOWS */
671
672#endif /* !VBOX_WITH_HARDENING */
673
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette