VirtualBox

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

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

VBoxNetDHCP: G/c -line.

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