VirtualBox

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

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

VBoxNetDHCP.cpp: adds listener for host DNS change event.

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