VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp@ 51582

Last change on this file since 51582 was 50587, checked in by vboxsync, 11 years ago

NetworkServices/DHCP: use Utf8Str

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1/* $Id: VBoxNetDHCP.cpp 50587 2014-02-25 16:37:29Z vboxsync $ */
2/** @file
3 * VBoxNetDHCP - DHCP Service for connecting to IntNet.
4 */
5
6/*
7 * Copyright (C) 2009-2011 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_dhcp VBoxNetDHCP
19 *
20 * Write a few words...
21 *
22 */
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include <VBox/com/com.h>
28#include <VBox/com/listeners.h>
29#include <VBox/com/string.h>
30#include <VBox/com/Guid.h>
31#include <VBox/com/array.h>
32#include <VBox/com/ErrorInfo.h>
33#include <VBox/com/errorprint.h>
34#include <VBox/com/EventQueue.h>
35#include <VBox/com/VirtualBox.h>
36
37#include <iprt/alloca.h>
38#include <iprt/buildconfig.h>
39#include <iprt/err.h>
40#include <iprt/net.h> /* must come before getopt */
41#include <iprt/getopt.h>
42#include <iprt/initterm.h>
43#include <iprt/message.h>
44#include <iprt/param.h>
45#include <iprt/path.h>
46#include <iprt/stream.h>
47#include <iprt/time.h>
48#include <iprt/string.h>
49
50#include <VBox/sup.h>
51#include <VBox/intnet.h>
52#include <VBox/intnetinline.h>
53#include <VBox/vmm/vmm.h>
54#include <VBox/version.h>
55
56
57#include "../NetLib/VBoxNetLib.h"
58#include "../NetLib/shared_ptr.h"
59
60#include <vector>
61#include <list>
62#include <string>
63#include <map>
64
65#include "../NetLib/VBoxNetBaseService.h"
66#include "../NetLib/utils.h"
67
68#ifdef RT_OS_WINDOWS /* WinMain */
69# include <Windows.h>
70# include <stdlib.h>
71# ifdef INET_ADDRSTRLEN
72/* On Windows INET_ADDRSTRLEN defined as 22 Ws2ipdef.h, because it include port number */
73# undef INET_ADDRSTRLEN
74# endif
75# define INET_ADDRSTRLEN 16
76#else
77# include <netinet/in.h>
78#endif
79
80
81#include "Config.h"
82/*******************************************************************************
83* Structures and Typedefs *
84*******************************************************************************/
85/**
86 * DHCP server instance.
87 */
88class VBoxNetDhcp: public VBoxNetBaseService, public NATNetworkEventAdapter
89{
90public:
91 VBoxNetDhcp();
92 virtual ~VBoxNetDhcp();
93
94 int init();
95 void usage(void) { /* XXX: document options */ };
96 int parseOpt(int rc, const RTGETOPTUNION& getOptVal);
97 int processFrame(void *, size_t) {return VERR_IGNORED; };
98 int processGSO(PCPDMNETWORKGSO, size_t) {return VERR_IGNORED; };
99 int processUDP(void *, size_t);
100
101protected:
102 bool handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb);
103
104 void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
105 static const char *debugDhcpName(uint8_t uMsgType);
106
107private:
108 int initNoMain();
109 int initWithMain();
110 HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent);
111 int fetchAndUpdateDnsInfo();
112
113protected:
114 /** @name The DHCP server specific configuration data members.
115 * @{ */
116 /*
117 * XXX: what was the plan? SQL3 or plain text file?
118 * How it will coexists with managment from VBoxManagement, who should manage db
119 * in that case (VBoxManage, VBoxSVC ???)
120 */
121 std::string m_LeaseDBName;
122
123 /** @} */
124
125 /* corresponding dhcp server description in Main */
126 ComPtr<IDHCPServer> m_DhcpServer;
127
128 ComPtr<INATNetwork> m_NATNetwork;
129
130 /** Listener for Host DNS changes */
131 ComPtr<NATNetworkListenerImpl> m_vboxListener;
132 /*
133 * We will ignore cmd line parameters IFF there will be some DHCP specific arguments
134 * otherwise all paramters will come from Main.
135 */
136 bool m_fIgnoreCmdLineParameters;
137
138 /*
139 * -b -n 10.0.1.2 -m 255.255.255.0 -> to the list processing in
140 */
141 typedef struct
142 {
143 char Key;
144 std::string strValue;
145 } CMDLNPRM;
146 std::list<CMDLNPRM> CmdParameterll;
147 typedef std::list<CMDLNPRM>::iterator CmdParameterIterator;
148
149 /** @name Debug stuff
150 * @{ */
151 int32_t m_cVerbosity;
152 uint8_t m_uCurMsgType;
153 size_t m_cbCurMsg;
154 PCRTNETBOOTP m_pCurMsg;
155 VBOXNETUDPHDRS m_CurHdrs;
156 /** @} */
157};
158
159
160static inline int configGetBoundryAddress(const ComDhcpServerPtr& dhcp, bool fUpperBoundry, RTNETADDRIPV4& boundryAddress)
161{
162 boundryAddress.u = INADDR_ANY;
163
164 HRESULT hrc;
165 com::Bstr strAddress;
166 if (fUpperBoundry)
167 hrc = dhcp->COMGETTER(UpperIP)(strAddress.asOutParam());
168 else
169 hrc = dhcp->COMGETTER(LowerIP)(strAddress.asOutParam());
170 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
171
172 return RTNetStrToIPv4Addr(com::Utf8Str(strAddress).c_str(), &boundryAddress);
173}
174
175/*******************************************************************************
176* Global Variables *
177*******************************************************************************/
178/** Pointer to the DHCP server. */
179static VBoxNetDhcp *g_pDhcp;
180
181/* DHCP server specific options */
182static RTGETOPTDEF g_aOptionDefs[] =
183{
184 { "--lease-db", 'D', RTGETOPT_REQ_STRING },
185 { "--begin-config", 'b', RTGETOPT_REQ_NOTHING },
186 { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR },
187 { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR },
188 { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR },
189};
190
191/**
192 * Construct a DHCP server with a default configuration.
193 */
194VBoxNetDhcp::VBoxNetDhcp():VBoxNetBaseService("VBoxNetDhcp", "VBoxNetDhcp")
195{
196 /* m_enmTrunkType = kIntNetTrunkType_WhateverNone; */
197 RTMAC mac;
198 mac.au8[0] = 0x08;
199 mac.au8[1] = 0x00;
200 mac.au8[2] = 0x27;
201 mac.au8[3] = 0x40;
202 mac.au8[4] = 0x41;
203 mac.au8[5] = 0x42;
204 setMacAddress(mac);
205
206 RTNETADDRIPV4 address;
207 address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 5)));
208 setIpv4Address(address);
209
210 setSendBufSize(8 * _1K);
211 setRecvBufSize(50 * _1K);
212
213 m_uCurMsgType = UINT8_MAX;
214 m_cbCurMsg = 0;
215 m_pCurMsg = NULL;
216 memset(&m_CurHdrs, '\0', sizeof(m_CurHdrs));
217
218 m_fIgnoreCmdLineParameters = true;
219
220 for(unsigned int i = 0; i < RT_ELEMENTS(g_aOptionDefs); ++i)
221 addCommandLineOption(&g_aOptionDefs[i]);
222}
223
224
225/**
226 * Destruct a DHCP server.
227 */
228VBoxNetDhcp::~VBoxNetDhcp()
229{
230}
231
232
233
234
235/**
236 * Parse the DHCP specific arguments.
237 *
238 * This callback caled for each paramenter so
239 * ....
240 * we nee post analisys of the parameters, at least
241 * for -b, -g, -l, -u, -m
242 */
243int VBoxNetDhcp::parseOpt(int rc, const RTGETOPTUNION& Val)
244{
245 CMDLNPRM prm;
246
247 /* Ok, we've entered here, thus we can't ignore cmd line parameters anymore */
248 m_fIgnoreCmdLineParameters = false;
249
250 prm.Key = rc;
251
252 switch (rc)
253 {
254 case 'l':
255 case 'u':
256 case 'g':
257 {
258 char buf[17];
259 RTStrPrintf(buf, 17, "%RTnaipv4", Val.IPv4Addr.u);
260 prm.strValue = buf;
261 CmdParameterll.push_back(prm);
262 }
263 break;
264
265 case 'b': // ignore
266 case 'D': // ignore
267 break;
268
269 default:
270 rc = RTGetOptPrintError(rc, &Val);
271 RTPrintf("Use --help for more information.\n");
272 return rc;
273 }
274
275 return VINF_SUCCESS;
276}
277
278int VBoxNetDhcp::init()
279{
280 int rc = this->VBoxNetBaseService::init();
281 AssertRCReturn(rc, rc);
282
283 NetworkManager *netManager = NetworkManager::getNetworkManager();
284
285 netManager->setOurAddress(getIpv4Address());
286 netManager->setOurNetmask(getIpv4Netmask());
287 netManager->setOurMac(getMacAddress());
288 netManager->setService(this);
289
290 if (isMainNeeded())
291 rc = initWithMain();
292 else
293 rc = initNoMain();
294
295 AssertRCReturn(rc, rc);
296
297 return VINF_SUCCESS;
298}
299
300
301int VBoxNetDhcp::processUDP(void *pv, size_t cbPv)
302{
303 PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
304 m_pCurMsg = pDhcpMsg;
305 m_cbCurMsg = cbPv;
306
307 uint8_t uMsgType;
308 if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cbPv, &uMsgType))
309 {
310 m_uCurMsgType = uMsgType;
311 {
312 /* To avoid fight with event processing thread */
313 VBoxNetALock(this);
314 handleDhcpMsg(uMsgType, pDhcpMsg, cbPv);
315 }
316 m_uCurMsgType = UINT8_MAX;
317 }
318 else
319 debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */
320
321 m_pCurMsg = NULL;
322 m_cbCurMsg = 0;
323
324 return VINF_SUCCESS;
325}
326
327
328/**
329 * Handles a DHCP message.
330 *
331 * @returns true if handled, false if not.
332 * @param uMsgType The message type.
333 * @param pDhcpMsg The DHCP message.
334 * @param cb The size of the DHCP message.
335 */
336bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb)
337{
338 if (pDhcpMsg->bp_op == RTNETBOOTP_OP_REQUEST)
339 {
340 NetworkManager *networkManager = NetworkManager::getNetworkManager();
341
342 switch (uMsgType)
343 {
344 case RTNET_DHCP_MT_DISCOVER:
345 return networkManager->handleDhcpReqDiscover(pDhcpMsg, cb);
346
347 case RTNET_DHCP_MT_REQUEST:
348 return networkManager->handleDhcpReqRequest(pDhcpMsg, cb);
349
350 case RTNET_DHCP_MT_DECLINE:
351 return networkManager->handleDhcpReqDecline(pDhcpMsg, cb);
352
353 case RTNET_DHCP_MT_RELEASE:
354 return networkManager->handleDhcpReqRelease(pDhcpMsg, cb);
355
356 case RTNET_DHCP_MT_INFORM:
357 debugPrint(0, true, "Should we handle this?");
358 break;
359
360 default:
361 debugPrint(0, true, "Unexpected.");
362 break;
363 }
364 }
365 return false;
366}
367
368/**
369 * Print debug message depending on the m_cVerbosity level.
370 *
371 * @param iMinLevel The minimum m_cVerbosity level for this message.
372 * @param fMsg Whether to dump parts for the current DHCP message.
373 * @param pszFmt The message format string.
374 * @param va Optional arguments.
375 */
376void VBoxNetDhcp::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
377{
378 if (iMinLevel <= m_cVerbosity)
379 {
380 va_list vaCopy; /* This dude is *very* special, thus the copy. */
381 va_copy(vaCopy, va);
382 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy);
383 va_end(vaCopy);
384
385 if ( fMsg
386 && m_cVerbosity >= 2
387 && m_pCurMsg)
388 {
389 /* XXX: export this to debugPrinfDhcpMsg or variant and other method export
390 * to base class
391 */
392 const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";
393 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d xid=%#x\n",
394 pszMsg,
395 &m_pCurMsg->bp_chaddr,
396 m_pCurMsg->bp_ciaddr.au8[0], m_pCurMsg->bp_ciaddr.au8[1], m_pCurMsg->bp_ciaddr.au8[2], m_pCurMsg->bp_ciaddr.au8[3],
397 m_pCurMsg->bp_yiaddr.au8[0], m_pCurMsg->bp_yiaddr.au8[1], m_pCurMsg->bp_yiaddr.au8[2], m_pCurMsg->bp_yiaddr.au8[3],
398 m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3],
399 m_pCurMsg->bp_xid);
400 }
401 }
402}
403
404
405/**
406 * Gets the name of given DHCP message type.
407 *
408 * @returns Readonly name.
409 * @param uMsgType The message number.
410 */
411/* static */ const char *VBoxNetDhcp::debugDhcpName(uint8_t uMsgType)
412{
413 switch (uMsgType)
414 {
415 case 0: return "MT_00";
416 case RTNET_DHCP_MT_DISCOVER: return "DISCOVER";
417 case RTNET_DHCP_MT_OFFER: return "OFFER";
418 case RTNET_DHCP_MT_REQUEST: return "REQUEST";
419 case RTNET_DHCP_MT_DECLINE: return "DECLINE";
420 case RTNET_DHCP_MT_ACK: return "ACK";
421 case RTNET_DHCP_MT_NAC: return "NAC";
422 case RTNET_DHCP_MT_RELEASE: return "RELEASE";
423 case RTNET_DHCP_MT_INFORM: return "INFORM";
424 case 9: return "MT_09";
425 case 10: return "MT_0a";
426 case 11: return "MT_0b";
427 case 12: return "MT_0c";
428 case 13: return "MT_0d";
429 case 14: return "MT_0e";
430 case 15: return "MT_0f";
431 case 16: return "MT_10";
432 case 17: return "MT_11";
433 case 18: return "MT_12";
434 case 19: return "MT_13";
435 case UINT8_MAX: return "MT_ff";
436 default: return "UNKNOWN";
437 }
438}
439
440
441int VBoxNetDhcp::initNoMain()
442{
443 CmdParameterIterator it;
444
445 RTNETADDRIPV4 address = getIpv4Address();
446 RTNETADDRIPV4 netmask = getIpv4Netmask();
447 RTNETADDRIPV4 networkId;
448 networkId.u = address.u & netmask.u;
449
450 RTNETADDRIPV4 UpperAddress;
451 RTNETADDRIPV4 LowerAddress = networkId;
452 UpperAddress.u = RT_H2N_U32(RT_N2H_U32(LowerAddress.u) | RT_N2H_U32(netmask.u));
453
454 for (it = CmdParameterll.begin(); it != CmdParameterll.end(); ++it)
455 {
456 switch(it->Key)
457 {
458 case 'l':
459 RTNetStrToIPv4Addr(it->strValue.c_str(), &LowerAddress);
460 break;
461
462 case 'u':
463 RTNetStrToIPv4Addr(it->strValue.c_str(), &UpperAddress);
464 break;
465 case 'b':
466 break;
467
468 }
469 }
470
471 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
472 AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
473 confManager->addNetwork(unconst(g_RootConfig),
474 networkId,
475 netmask,
476 LowerAddress,
477 UpperAddress);
478
479 return VINF_SUCCESS;
480}
481
482
483int VBoxNetDhcp::initWithMain()
484{
485 /* ok, here we should initiate instance of dhcp server
486 * and listener for Dhcp configuration events
487 */
488 AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);
489 std::string networkName = getNetwork();
490
491 int rc = findDhcpServer(virtualbox, networkName, m_DhcpServer);
492 AssertRCReturn(rc, rc);
493
494 rc = findNatNetwork(virtualbox, networkName, m_NATNetwork);
495 AssertRCReturn(rc, rc);
496
497 BOOL fNeedDhcpServer = isDhcpRequired(m_NATNetwork);
498 if (!fNeedDhcpServer)
499 return VERR_CANCELLED;
500
501 RTNETADDRIPV4 gateway;
502 com::Bstr strGateway;
503 HRESULT hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());
504 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
505 RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway);
506
507 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
508 AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
509 confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway);
510
511 rc = fetchAndUpdateDnsInfo();
512 AssertMsgRCReturn(rc, ("Wasn't able to fetch Dns info"), rc);
513
514 ComEventTypeArray aVBoxEvents;
515 aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
516 rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
517 AssertRCReturn(rc, rc);
518
519 RTNETADDRIPV4 LowerAddress;
520 rc = configGetBoundryAddress(m_DhcpServer, false, LowerAddress);
521 AssertMsgRCReturn(rc, ("can't get lower boundrary adderss'"),rc);
522
523 RTNETADDRIPV4 UpperAddress;
524 rc = configGetBoundryAddress(m_DhcpServer, true, UpperAddress);
525 AssertMsgRCReturn(rc, ("can't get upper boundrary adderss'"),rc);
526
527 RTNETADDRIPV4 address = getIpv4Address();
528 RTNETADDRIPV4 netmask = getIpv4Netmask();
529 RTNETADDRIPV4 networkId = networkid(address, netmask);
530 std::string name = std::string("default");
531
532 confManager->addNetwork(unconst(g_RootConfig),
533 networkId,
534 netmask,
535 LowerAddress,
536 UpperAddress);
537
538 com::Bstr bstr;
539 hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
540 com::Utf8StrFmt strXmlLeaseFile("%ls%c%s.leases",
541 bstr.raw(), RTPATH_DELIMITER, networkName.c_str());
542 confManager->loadFromFile(strXmlLeaseFile);
543
544 return VINF_SUCCESS;
545}
546
547
548int VBoxNetDhcp::fetchAndUpdateDnsInfo()
549{
550 ComHostPtr host;
551 if (SUCCEEDED(virtualbox->COMGETTER(Host)(host.asOutParam())))
552 {
553 AddressToOffsetMapping mapIp4Addr2Off;
554 int rc = localMappings(m_NATNetwork, mapIp4Addr2Off);
555 /* XXX: here could be several cases: 1. COM error, 2. not found (empty) 3. ? */
556 AssertMsgRCReturn(rc, ("Can't fetch local mappings"), rc);
557
558 RTNETADDRIPV4 address = getIpv4Address();
559 RTNETADDRIPV4 netmask = getIpv4Netmask();
560
561 AddressList nameservers;
562 rc = hostDnsServers(host, networkid(address, netmask), mapIp4Addr2Off, nameservers);
563 AssertMsgRCReturn(rc, ("Debug me!!!"), rc);
564 /* XXX: Search strings */
565
566 std::string domain;
567 rc = hostDnsDomain(host, domain);
568 AssertMsgRCReturn(rc, ("Debug me!!"), rc);
569
570 {
571 VBoxNetALock(this);
572 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
573 confManager->flushAddressList(RTNET_DHCP_OPT_DNS);
574
575 for (AddressList::iterator it = nameservers.begin(); it != nameservers.end(); ++it)
576 confManager->addToAddressList(RTNET_DHCP_OPT_DNS, *it);
577
578 confManager->setString(RTNET_DHCP_OPT_DOMAIN_NAME, domain);
579 }
580 }
581
582 return VINF_SUCCESS;
583}
584
585
586HRESULT VBoxNetDhcp::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
587{
588 switch(aEventType)
589 {
590 case VBoxEventType_OnHostNameResolutionConfigurationChange:
591 fetchAndUpdateDnsInfo();
592 break;
593 }
594
595 return S_OK;
596}
597
598/**
599 * Entry point.
600 */
601extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv)
602{
603 /*
604 * Instantiate the DHCP server and hand it the options.
605 */
606
607 VBoxNetDhcp *pDhcp = new VBoxNetDhcp();
608 if (!pDhcp)
609 {
610 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: new VBoxNetDhcp failed!\n");
611 return 1;
612 }
613 int rc = pDhcp->parseArgs(argc - 1, argv + 1);
614 if (rc)
615 return rc;
616
617 pDhcp->init();
618
619 /*
620 * Try connect the server to the network.
621 */
622 rc = pDhcp->tryGoOnline();
623 if (RT_FAILURE(rc))
624 {
625 delete pDhcp;
626 return 1;
627 }
628
629 /*
630 * Process requests.
631 */
632 g_pDhcp = pDhcp;
633 rc = pDhcp->run();
634 g_pDhcp = NULL;
635 delete pDhcp;
636
637 return 0;
638}
639
640
641#ifndef VBOX_WITH_HARDENING
642
643int main(int argc, char **argv)
644{
645 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
646 if (RT_FAILURE(rc))
647 return RTMsgInitFailure(rc);
648
649 return TrustedMain(argc, argv);
650}
651
652# ifdef RT_OS_WINDOWS
653
654static LRESULT CALLBACK WindowProc(HWND hwnd,
655 UINT uMsg,
656 WPARAM wParam,
657 LPARAM lParam
658)
659{
660 if(uMsg == WM_DESTROY)
661 {
662 PostQuitMessage(0);
663 return 0;
664 }
665 return DefWindowProc (hwnd, uMsg, wParam, lParam);
666}
667
668static LPCWSTR g_WndClassName = L"VBoxNetDHCPClass";
669
670static DWORD WINAPI MsgThreadProc(__in LPVOID lpParameter)
671{
672 HWND hwnd = 0;
673 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);
674 bool bExit = false;
675
676 /* Register the Window Class. */
677 WNDCLASS wc;
678 wc.style = 0;
679 wc.lpfnWndProc = WindowProc;
680 wc.cbClsExtra = 0;
681 wc.cbWndExtra = sizeof(void *);
682 wc.hInstance = hInstance;
683 wc.hIcon = NULL;
684 wc.hCursor = NULL;
685 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
686 wc.lpszMenuName = NULL;
687 wc.lpszClassName = g_WndClassName;
688
689 ATOM atomWindowClass = RegisterClass(&wc);
690
691 if (atomWindowClass != 0)
692 {
693 /* Create the window. */
694 hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
695 g_WndClassName, g_WndClassName,
696 WS_POPUPWINDOW,
697 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
698
699 if (hwnd)
700 {
701 SetWindowPos(hwnd, HWND_TOPMOST, -200, -200, 0, 0,
702 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
703
704 MSG msg;
705 while (GetMessage(&msg, NULL, 0, 0))
706 {
707 TranslateMessage(&msg);
708 DispatchMessage(&msg);
709 }
710
711 DestroyWindow (hwnd);
712
713 bExit = true;
714 }
715
716 UnregisterClass (g_WndClassName, hInstance);
717 }
718
719 if(bExit)
720 {
721 /* no need any accuracy here, in anyway the DHCP server usually gets terminated with TerminateProcess */
722 exit(0);
723 }
724
725 return 0;
726}
727
728
729/** (We don't want a console usually.) */
730int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
731{
732 NOREF(hInstance); NOREF(hPrevInstance); NOREF(lpCmdLine); NOREF(nCmdShow);
733
734 HANDLE hThread = CreateThread(
735 NULL, /*__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, */
736 0, /*__in SIZE_T dwStackSize, */
737 MsgThreadProc, /*__in LPTHREAD_START_ROUTINE lpStartAddress,*/
738 NULL, /*__in_opt LPVOID lpParameter,*/
739 0, /*__in DWORD dwCreationFlags,*/
740 NULL /*__out_opt LPDWORD lpThreadId*/
741 );
742
743 if(hThread != NULL)
744 CloseHandle(hThread);
745
746 return main(__argc, __argv);
747}
748# endif /* RT_OS_WINDOWS */
749
750#endif /* !VBOX_WITH_HARDENING */
751
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