VirtualBox

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

Last change on this file since 28371 was 28371, checked in by vboxsync, 15 years ago

NetworkServices: branding and cosmetical fixes

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

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