VirtualBox

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

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

VBoxNetDHCP: exposed fetchAndUpdateDnsInfo() used in listener(not commited yet) and in initialization. Note: scoped out flush and update configuration amnager's cache will be used for auto-syncronization between updates and requests processing in later commits.

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