VirtualBox

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

最後變更 在這個檔案從39410是 39410,由 vboxsync 提交於 13 年 前

NAT/service: some delayed fixes.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 21.7 KB
 
1/* $Id: VBoxNetNAT.cpp 39410 2011-11-24 15:30:16Z 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.alldomusa.eu.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, 2)));
154 m_Ipv4Netmask.u = RT_H2N_U32_C(0xffffff);
155 cPkt = 0;
156 cUrgPkt = 0;
157}
158
159VBoxNetNAT::~VBoxNetNAT() { }
160void VBoxNetNAT::init()
161{
162 int rc;
163#if 0
164 using namespace com;
165 HRESULT hrc = com::Initialize();
166 if (FAILED(hrc))
167 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM!");
168#endif
169
170 /*
171 * Initialize slirp.
172 */
173 rc = slirp_init(&m_pNATState, RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 0))), m_Ipv4Netmask.u, m_fPassDomain, false, 0x40, 100, this);
174 AssertReleaseRC(rc);
175
176 slirp_set_ethaddr_and_activate_port_forwarding(m_pNATState, &m_MacAddress.au8[0], INADDR_ANY);
177#ifndef RT_OS_WINDOWS
178 /*
179 * Create the control pipe.
180 */
181 rc = RTPipeCreate(&m_hPipeRead, &m_hPipeWrite, 0 /*fFlags*/);
182 AssertReleaseRC(rc);
183#else
184 m_hWakeupEvent = CreateEvent(NULL, FALSE, FALSE, NULL); /* auto-reset event */
185 AssertReleaseRC(m_hWakeupEvent != NULL);
186 slirp_register_external_event(m_pNATState, m_hWakeupEvent, VBOX_WAKEUP_EVENT_INDEX);
187#endif
188 rc = RTReqCreateQueue(&m_pReqQueue);
189 AssertReleaseRC(rc);
190
191 rc = RTReqCreateQueue(&m_pSendQueue);
192 AssertReleaseRC(rc);
193
194 rc = RTReqCreateQueue(&m_pUrgSendQueue);
195 AssertReleaseRC(rc);
196
197 rc = RTThreadCreate(&m_ThrNAT, AsyncIoThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "NAT");
198 rc = RTThreadCreate(&m_ThrSndNAT, natSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "SndNAT");
199 rc = RTThreadCreate(&m_ThrUrgSndNAT, natUrgSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "UrgSndNAT");
200 rc = RTSemEventCreate(&m_EventSend);
201 rc = RTSemEventCreate(&m_EventUrgSend);
202 AssertReleaseRC(rc);
203}
204
205/* Mandatory functions */
206void VBoxNetNAT::run()
207{
208
209 /*
210 * The loop.
211 */
212 fIsRunning = true;
213 PINTNETRINGBUF pRingBuf = &m_pIfBuf->Recv;
214 //RTThreadSetType(RTThreadSelf(), RTTHREADTYPE_IO);
215 for (;;)
216 {
217 /*
218 * Wait for a packet to become available.
219 */
220 INTNETIFWAITREQ WaitReq;
221 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
222 WaitReq.Hdr.cbReq = sizeof(WaitReq);
223 WaitReq.pSession = m_pSession;
224 WaitReq.hIf = m_hIf;
225 WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */ /** @todo fix interruptability in SrvIntNet! */
226#if 1
227 RTReqProcess(m_pSendQueue, 0);
228 RTReqProcess(m_pUrgSendQueue, 0);
229#endif
230 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
231 if (RT_FAILURE(rc))
232 {
233 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
234 continue;
235 LogRel(("VBoxNetNAT: VMMR0_DO_INTNET_IF_WAIT returned %Rrc\n", rc));
236 return;
237 }
238
239 /*
240 * Process the receive buffer.
241 */
242 PCINTNETHDR pHdr;
243 while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
244 {
245 uint16_t const u16Type = pHdr->u16Type;
246 size_t cbFrame = pHdr->cbFrame;
247 size_t cbIgnored;
248 void *pvSlirpFrame;
249 struct mbuf *m;
250 switch (u16Type)
251 {
252 case INTNETHDR_TYPE_FRAME:
253 m = slirp_ext_m_get(g_pNAT->m_pNATState, cbFrame, &pvSlirpFrame, &cbIgnored);
254 if (!m)
255 {
256 LogRel(("NAT: Can't allocate send buffer cbFrame=%u\n", cbFrame));
257 break;
258 }
259 memcpy(pvSlirpFrame, IntNetHdrGetFramePtr(pHdr, m_pIfBuf), cbFrame);
260 IntNetRingSkipFrame(&m_pIfBuf->Recv);
261
262 /* don't wait, we may have to wakeup the NAT thread first */
263 rc = RTReqCallEx(m_pReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
264 (PFNRT)SendWorker, 2, m, cbFrame);
265 AssertReleaseRC(rc);
266 break;
267 case INTNETHDR_TYPE_GSO:
268 {
269 /** @todo pass these unmodified. */
270 PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m_pIfBuf);
271 if (!PDMNetGsoIsValid(pGso, cbFrame, cbFrame - sizeof(*pGso)))
272 {
273 IntNetRingSkipFrame(&m_pIfBuf->Recv);
274 STAM_REL_COUNTER_INC(&m_pIfBuf->cStatBadFrames);
275 continue;
276 }
277
278 uint8_t abHdrScratch[256];
279 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame - sizeof(*pGso));
280 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
281 {
282 uint32_t cbSegFrame;
283 void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)(pGso + 1), cbFrame, abHdrScratch,
284 iSeg, cSegs, &cbSegFrame);
285 m = slirp_ext_m_get(g_pNAT->m_pNATState, cbFrame, &pvSlirpFrame, &cbIgnored);
286 if (!m)
287 {
288 LogRel(("NAT: Can't allocate send buffer cbSegFrame=%u seg=%u/%u\n",
289 cbSegFrame, iSeg, cSegs));
290 break;
291 }
292 memcpy(pvSlirpFrame, pvSegFrame, cbFrame);
293
294 rc = RTReqCallEx(m_pReqQueue, NULL /*ppReq*/, 0 /*cMillies*/,
295 RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
296 (PFNRT)SendWorker, 2, m, cbSegFrame);
297 AssertReleaseRC(rc);
298 }
299 IntNetRingSkipFrame(&m_pIfBuf->Recv);
300 }
301 break;
302 case INTNETHDR_TYPE_PADDING:
303 IntNetRingSkipFrame(&m_pIfBuf->Recv);
304 break;
305 default:
306 IntNetRingSkipFrame(&m_pIfBuf->Recv);
307 STAM_REL_COUNTER_INC(&m_pIfBuf->cStatBadFrames);
308 break;
309 }
310
311#ifndef RT_OS_WINDOWS
312 /* kick select() */
313 rc = RTPipeWrite(m_hPipeWrite, "", 1, &cbIgnored);
314 AssertRC(rc);
315#else
316 /* kick WSAWaitForMultipleEvents */
317 rc = WSASetEvent(m_hWakeupEvent);
318 AssertRelease(rc == TRUE);
319#endif
320 }
321 natNotifyNATThread();
322
323 }
324 fIsRunning = false;
325}
326
327void VBoxNetNAT::usage()
328{
329}
330
331/**
332 * Entry point.
333 */
334extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
335{
336 Log2(("NAT: main\n"));
337 g_pNAT = new VBoxNetNAT();
338 Log2(("NAT: parsing command line\n"));
339 int rc = g_pNAT->parseArgs(argc - 1, argv + 1);
340 if (!rc)
341 {
342 Log2(("NAT: initialization\n"));
343 g_pNAT->init();
344 Log2(("NAT: try go online\n"));
345 g_pNAT->tryGoOnline();
346 Log2(("NAT: main loop\n"));
347 g_pNAT->run();
348 }
349 delete g_pNAT;
350 return 0;
351}
352
353/** slirp's hooks */
354extern "C" int slirp_can_output(void * pvUser)
355{
356 return 1;
357}
358
359extern "C" void slirp_urg_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
360{
361 int rc = RTReqCallEx(g_pNAT->m_pUrgSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
362 (PFNRT)IntNetSendWorker, 4, (uintptr_t)1, (uintptr_t)pu8Buf, (uintptr_t)cb, (uintptr_t)m);
363 ASMAtomicIncU32(&g_pNAT->cUrgPkt);
364 RTSemEventSignal(g_pNAT->m_EventUrgSend);
365 AssertReleaseRC(rc);
366}
367extern "C" void slirp_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
368{
369 AssertRelease(g_pNAT == pvUser);
370 int rc = RTReqCallEx(g_pNAT->m_pSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
371 (PFNRT)IntNetSendWorker, 4, (uintptr_t)0, (uintptr_t)pu8Buf, (uintptr_t)cb, (uintptr_t)m);
372 ASMAtomicIncU32(&g_pNAT->cPkt);
373 RTSemEventSignal(g_pNAT->m_EventSend);
374 AssertReleaseRC(rc);
375}
376
377extern "C" void slirp_output_pending(void *pvUser)
378{
379 AssertMsgFailed(("Unimplemented"));
380}
381
382/**
383 * Worker function for drvNATSend().
384 * @thread "NAT" thread.
385 */
386static void SendWorker(struct mbuf *m, size_t cb)
387{
388 slirp_input(g_pNAT->m_pNATState, m, cb);
389}
390
391static void IntNetSendWorker(bool urg, void *pvFrame, size_t cbFrame, struct mbuf *m)
392{
393 Log2(("VBoxNetNAT: going to send some bytes ... \n"));
394 VBoxNetNAT *pThis = g_pNAT;
395 INTNETIFSENDREQ SendReq;
396 int rc;
397
398 if (!urg)
399 {
400 while (ASMAtomicReadU32(&g_pNAT->cUrgPkt) != 0
401 || ASMAtomicReadU32(&g_pNAT->cPkt) == 0)
402 rc = RTSemEventWait(g_pNAT->m_EventSend, RT_INDEFINITE_WAIT);
403 }
404 else
405 {
406 while (ASMAtomicReadU32(&g_pNAT->cUrgPkt) == 0)
407 rc = RTSemEventWait(g_pNAT->m_EventUrgSend, RT_INDEFINITE_WAIT);
408 }
409 rc = IntNetRingWriteFrame(&pThis->m_pIfBuf->Send, pvFrame, cbFrame);
410 if (RT_FAILURE(rc))
411 {
412 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
413 SendReq.Hdr.cbReq = sizeof(SendReq);
414 SendReq.pSession = pThis->m_pSession;
415 SendReq.hIf = pThis->m_hIf;
416 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
417
418 rc = IntNetRingWriteFrame(&pThis->m_pIfBuf->Send, pvFrame, cbFrame);
419
420 }
421 if (RT_SUCCESS(rc))
422 {
423 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
424 SendReq.Hdr.cbReq = sizeof(SendReq);
425 SendReq.pSession = pThis->m_pSession;
426 SendReq.hIf = pThis->m_hIf;
427 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
428 }
429 if (RT_FAILURE(rc))
430 Log2(("VBoxNetNAT: Failed to send packet; rc=%Rrc\n", rc));
431
432 if (!urg)
433 {
434 ASMAtomicDecU32(&g_pNAT->cPkt);
435 }
436 else {
437 if (ASMAtomicDecU32(&g_pNAT->cUrgPkt) == 0)
438 RTSemEventSignal(g_pNAT->m_EventSend);
439 }
440 natNotifyNATThread();
441 slirp_ext_m_free(pThis->m_pNATState, m, (uint8_t *)pvFrame);
442}
443
444static DECLCALLBACK(int) AsyncIoThread(RTTHREAD pThread, void *pvUser)
445{
446 VBoxNetNAT *pThis = (VBoxNetNAT *)pvUser;
447 int nFDs = -1;
448#ifdef RT_OS_WINDOWS
449 HANDLE *pahEvents = slirp_get_events(pThis->m_pNATState);
450#else /* RT_OS_WINDOWS */
451 unsigned int cPollNegRet = 0;
452#endif /* !RT_OS_WINDOWS */
453
454 LogFlow(("drvNATAsyncIoThread: pThis=%p\n", pThis));
455
456 /*
457 * Polling loop.
458 */
459 for(;;)
460 {
461 /*
462 * To prevent concurrent execution of sending/receiving threads
463 */
464#ifndef RT_OS_WINDOWS
465 nFDs = slirp_get_nsock(pThis->m_pNATState);
466 /* allocation for all sockets + Management pipe */
467 struct pollfd *polls = (struct pollfd *)RTMemAlloc((1 + nFDs) * sizeof(struct pollfd) + sizeof(uint32_t));
468 if (polls == NULL)
469 return VERR_NO_MEMORY;
470
471 /* don't pass the management pipe */
472 slirp_select_fill(pThis->m_pNATState, &nFDs, &polls[1]);
473 unsigned int cMsTimeout = slirp_get_timeout_ms(pThis->m_pNATState);
474
475 polls[0].fd = RTPipeToNative(pThis->m_hPipeRead);
476 /* POLLRDBAND usually doesn't used on Linux but seems used on Solaris */
477 polls[0].events = POLLRDNORM|POLLPRI|POLLRDBAND;
478 polls[0].revents = 0;
479
480 int cChangedFDs = poll(polls, nFDs + 1, cMsTimeout);
481 if (cChangedFDs < 0)
482 {
483 if (errno == EINTR)
484 {
485 Log2(("NAT: signal was caught while sleep on poll\n"));
486 /* No error, just process all outstanding requests but don't wait */
487 cChangedFDs = 0;
488 }
489 else if (cPollNegRet++ > 128)
490 {
491 LogRel(("NAT:Poll returns (%s) suppressed %d\n", strerror(errno), cPollNegRet));
492 cPollNegRet = 0;
493 }
494 }
495
496 if (cChangedFDs >= 0)
497 {
498 slirp_select_poll(pThis->m_pNATState, &polls[1], nFDs);
499 if (polls[0].revents & (POLLRDNORM|POLLPRI|POLLRDBAND))
500 {
501 /* drain the pipe
502 *
503 * Note!
504 * drvNATSend decoupled so we don't know how many times
505 * device's thread sends before we've entered multiplex,
506 * so to avoid false alarm drain pipe here to the very end
507 *
508 * @todo: Probably we should counter drvNATSend to count how
509 * deep pipe has been filed before drain.
510 *
511 */
512 /** @todo XXX: Make it reading exactly we need to drain the
513 * pipe. */
514 char ch;
515 size_t cbRead;
516 RTPipeRead(pThis->m_hPipeRead, &ch, 1, &cbRead);
517 }
518 }
519 /* process _all_ outstanding requests but don't wait */
520 RTReqProcess(pThis->m_pReqQueue, 0);
521 RTMemFree(polls);
522
523#else /* RT_OS_WINDOWS */
524 nFDs = -1;
525 slirp_select_fill(pThis->m_pNATState, &nFDs);
526 DWORD dwEvent = WSAWaitForMultipleEvents(nFDs, pahEvents, FALSE,
527 slirp_get_timeout_ms(pThis->m_pNATState),
528 FALSE);
529 if ( (dwEvent < WSA_WAIT_EVENT_0 || dwEvent > WSA_WAIT_EVENT_0 + nFDs - 1)
530 && dwEvent != WSA_WAIT_TIMEOUT)
531 {
532 int error = WSAGetLastError();
533 LogRel(("NAT: WSAWaitForMultipleEvents returned %d (error %d)\n", dwEvent, error));
534 RTAssertReleasePanic();
535 }
536
537 if (dwEvent == WSA_WAIT_TIMEOUT)
538 {
539 /* only check for slow/fast timers */
540 slirp_select_poll(pThis->m_pNATState, /* fTimeout=*/true, /*fIcmp=*/false);
541 continue;
542 }
543
544 /* poll the sockets in any case */
545 slirp_select_poll(pThis->m_pNATState, /* fTimeout=*/false, /* fIcmp=*/(dwEvent == WSA_WAIT_EVENT_0));
546 /* process _all_ outstanding requests but don't wait */
547 RTReqProcess(pThis->m_pReqQueue, 0);
548#endif /* RT_OS_WINDOWS */
549 }
550
551 return VINF_SUCCESS;
552}
553
554static DECLCALLBACK(int) natSndThread(RTTHREAD pThread, void *pvUser)
555{
556 while (g_pNAT->fIsRunning)
557 RTReqProcess(g_pNAT->m_pSendQueue, 0);
558 return VINF_SUCCESS;
559}
560static DECLCALLBACK(int) natUrgSndThread(RTTHREAD pThread, void *pvUser)
561{
562 while (g_pNAT->fIsRunning)
563 RTReqProcess(g_pNAT->m_pUrgSendQueue, 0);
564 return VINF_SUCCESS;
565}
566
567#ifndef VBOX_WITH_HARDENING
568
569int main(int argc, char **argv, char **envp)
570{
571 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
572 if (RT_FAILURE(rc))
573 return RTMsgInitFailure(rc);
574
575 return TrustedMain(argc, argv, envp);
576}
577
578# if defined(RT_OS_WINDOWS)
579
580static LRESULT CALLBACK WindowProc(HWND hwnd,
581 UINT uMsg,
582 WPARAM wParam,
583 LPARAM lParam
584)
585{
586 if(uMsg == WM_DESTROY)
587 {
588 PostQuitMessage(0);
589 return 0;
590 }
591 return DefWindowProc (hwnd, uMsg, wParam, lParam);
592}
593
594static LPCSTR g_WndClassName = "VBoxNetNatClass";
595
596static DWORD WINAPI MsgThreadProc(__in LPVOID lpParameter)
597{
598 HWND hwnd = 0;
599 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);
600 bool bExit = false;
601
602 /* Register the Window Class. */
603 WNDCLASS wc;
604 wc.style = 0;
605 wc.lpfnWndProc = WindowProc;
606 wc.cbClsExtra = 0;
607 wc.cbWndExtra = sizeof(void *);
608 wc.hInstance = hInstance;
609 wc.hIcon = NULL;
610 wc.hCursor = NULL;
611 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
612 wc.lpszMenuName = NULL;
613 wc.lpszClassName = g_WndClassName;
614
615 ATOM atomWindowClass = RegisterClass(&wc);
616
617 if (atomWindowClass != 0)
618 {
619 /* Create the window. */
620 hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
621 g_WndClassName, g_WndClassName,
622 WS_POPUPWINDOW,
623 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
624
625 if (hwnd)
626 {
627 SetWindowPos(hwnd, HWND_TOPMOST, -200, -200, 0, 0,
628 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
629
630 MSG msg;
631 while (GetMessage(&msg, NULL, 0, 0))
632 {
633 TranslateMessage(&msg);
634 DispatchMessage(&msg);
635 }
636
637 DestroyWindow (hwnd);
638
639 bExit = true;
640 }
641
642 UnregisterClass (g_WndClassName, hInstance);
643 }
644
645 if(bExit)
646 {
647 /* no need any accuracy here, in anyway the DHCP server usually gets terminated with TerminateProcess */
648 exit(0);
649 }
650
651 return 0;
652}
653
654
655
656/** (We don't want a console usually.) */
657int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
658{
659#if 0
660 NOREF(hInstance); NOREF(hPrevInstance); NOREF(lpCmdLine); NOREF(nCmdShow);
661
662 HANDLE hThread = CreateThread(
663 NULL, /*__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, */
664 0, /*__in SIZE_T dwStackSize, */
665 MsgThreadProc, /*__in LPTHREAD_START_ROUTINE lpStartAddress,*/
666 NULL, /*__in_opt LPVOID lpParameter,*/
667 0, /*__in DWORD dwCreationFlags,*/
668 NULL /*__out_opt LPDWORD lpThreadId*/
669 );
670
671 if(hThread != NULL)
672 CloseHandle(hThread);
673
674#endif
675 return main(__argc, __argv, environ);
676}
677# endif /* RT_OS_WINDOWS */
678
679#endif /* !VBOX_WITH_HARDENING */
680
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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