VirtualBox

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

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

*: RTFILE becomes a pointer, RTFileOpen++ expands it's flags paramter from uint32_t to uint64_t.

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

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