2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/dhcpcapi/dhcpcapi.c
5 * PURPOSE: Client API for DHCP
6 * COPYRIGHT: Copyright 2005 Art Yerkes <ayerkes@speakeasy.net>
15 static WCHAR ServiceName
[] = L
"DHCP";
17 SERVICE_STATUS_HANDLE ServiceStatusHandle
= 0;
18 SERVICE_STATUS ServiceStatus
;
19 HANDLE hStopEvent
= NULL
;
21 static HANDLE PipeHandle
= INVALID_HANDLE_VALUE
;
24 DhcpCApiInitialize(LPDWORD Version
)
28 /* Wait for the pipe to be available */
29 if (!WaitNamedPipeW(DHCP_PIPE_NAME
, NMPWAIT_USE_DEFAULT_WAIT
))
31 /* No good, we failed */
32 return GetLastError();
35 /* It's available, let's try to open it */
36 PipeHandle
= CreateFileW(DHCP_PIPE_NAME
,
37 GENERIC_READ
| GENERIC_WRITE
,
38 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
44 /* Check if we succeeded in opening the pipe */
45 if (PipeHandle
== INVALID_HANDLE_VALUE
)
48 return GetLastError();
51 /* Change the pipe into message mode */
52 PipeMode
= PIPE_READMODE_MESSAGE
;
53 if (!SetNamedPipeHandleState(PipeHandle
, &PipeMode
, NULL
, NULL
))
55 /* Mode change failed */
56 CloseHandle(PipeHandle
);
57 PipeHandle
= INVALID_HANDLE_VALUE
;
58 return GetLastError();
62 /* We're good to go */
71 CloseHandle(PipeHandle
);
72 PipeHandle
= INVALID_HANDLE_VALUE
;
76 DhcpQueryHWInfo(DWORD AdapterIndex
,
82 COMM_DHCP_REPLY Reply
;
86 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
88 Req
.Type
= DhcpReqQueryHWInfo
;
89 Req
.AdapterIndex
= AdapterIndex
;
91 Result
= TransactNamedPipe(PipeHandle
,
93 &Reply
, sizeof(Reply
),
97 /* Pipe transaction failed */
101 if (Reply
.Reply
== 0)
104 *MediaType
= Reply
.QueryHWInfo
.MediaType
;
105 *Mtu
= Reply
.QueryHWInfo
.Mtu
;
106 *Speed
= Reply
.QueryHWInfo
.Speed
;
111 DhcpLeaseIpAddress(DWORD AdapterIndex
)
114 COMM_DHCP_REPLY Reply
;
118 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
120 Req
.Type
= DhcpReqLeaseIpAddress
;
121 Req
.AdapterIndex
= AdapterIndex
;
123 Result
= TransactNamedPipe(PipeHandle
,
125 &Reply
, sizeof(Reply
),
129 /* Pipe transaction failed */
137 DhcpReleaseIpAddressLease(DWORD AdapterIndex
)
140 COMM_DHCP_REPLY Reply
;
144 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
146 Req
.Type
= DhcpReqReleaseIpAddress
;
147 Req
.AdapterIndex
= AdapterIndex
;
149 Result
= TransactNamedPipe(PipeHandle
,
151 &Reply
, sizeof(Reply
),
155 /* Pipe transaction failed */
163 DhcpRenewIpAddressLease(DWORD AdapterIndex
)
166 COMM_DHCP_REPLY Reply
;
170 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
172 Req
.Type
= DhcpReqRenewIpAddress
;
173 Req
.AdapterIndex
= AdapterIndex
;
175 Result
= TransactNamedPipe(PipeHandle
,
177 &Reply
, sizeof(Reply
),
181 /* Pipe transaction failed */
189 DhcpStaticRefreshParams(DWORD AdapterIndex
,
194 COMM_DHCP_REPLY Reply
;
198 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
200 Req
.Type
= DhcpReqStaticRefreshParams
;
201 Req
.AdapterIndex
= AdapterIndex
;
202 Req
.Body
.StaticRefreshParams
.IPAddress
= Address
;
203 Req
.Body
.StaticRefreshParams
.Netmask
= Netmask
;
205 Result
= TransactNamedPipe(PipeHandle
,
207 &Reply
, sizeof(Reply
),
211 /* Pipe transaction failed */
219 * Set new TCP/IP parameters and notify DHCP client service of this
221 * \param[in] ServerName
222 * NULL for local machine
224 * \param[in] AdapterName
225 * IPHLPAPI name of adapter to change
227 * \param[in] NewIpAddress
228 * TRUE if IP address changes
230 * \param[in] IpAddress
231 * New IP address (network byte order)
233 * \param[in] SubnetMask
234 * New subnet mask (network byte order)
236 * \param[in] DhcpAction
241 * \return non-zero on success
243 * \remarks Undocumented by Microsoft
246 DhcpNotifyConfigChange(LPWSTR ServerName
,
254 DPRINT1("DHCPCSVC: DhcpNotifyConfigChange not implemented yet\n");
259 * Get DHCP info for an adapter
261 * \param[in] AdapterIndex
262 * Index of the adapter (iphlpapi-style) for which info is
265 * \param[out] DhcpEnabled
266 * Returns whether DHCP is enabled for the adapter
268 * \param[out] DhcpServer
269 * Returns DHCP server IP address (255.255.255.255 if no
270 * server reached yet), in network byte order
272 * \param[out] LeaseObtained
273 * Returns time at which the lease was obtained
275 * \param[out] LeaseExpires
276 * Returns time at which the lease will expire
278 * \return non-zero on success
280 * \remarks This is a ReactOS-only routine
283 DhcpRosGetAdapterInfo(DWORD AdapterIndex
,
286 time_t* LeaseObtained
,
287 time_t* LeaseExpires
)
290 COMM_DHCP_REPLY Reply
;
294 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
296 Req
.Type
= DhcpReqGetAdapterInfo
;
297 Req
.AdapterIndex
= AdapterIndex
;
299 Result
= TransactNamedPipe(PipeHandle
,
301 &Reply
, sizeof(Reply
),
304 if (Result
&& Reply
.Reply
!= 0)
305 *DhcpEnabled
= Reply
.GetAdapterInfo
.DhcpEnabled
;
307 *DhcpEnabled
= FALSE
;
311 *DhcpServer
= Reply
.GetAdapterInfo
.DhcpServer
;
312 *LeaseObtained
= Reply
.GetAdapterInfo
.LeaseObtained
;
313 *LeaseExpires
= Reply
.GetAdapterInfo
.LeaseExpires
;
317 *DhcpServer
= INADDR_NONE
;
327 UpdateServiceStatus(DWORD dwState
)
329 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
330 ServiceStatus
.dwCurrentState
= dwState
;
332 if (dwState
== SERVICE_RUNNING
)
333 ServiceStatus
.dwControlsAccepted
= SERVICE_ACCEPT_SHUTDOWN
| SERVICE_ACCEPT_STOP
;
335 ServiceStatus
.dwControlsAccepted
= 0;
337 ServiceStatus
.dwWin32ExitCode
= 0;
338 ServiceStatus
.dwServiceSpecificExitCode
= 0;
339 ServiceStatus
.dwCheckPoint
= 0;
341 if (dwState
== SERVICE_START_PENDING
||
342 dwState
== SERVICE_STOP_PENDING
)
343 ServiceStatus
.dwWaitHint
= 1000;
345 ServiceStatus
.dwWaitHint
= 0;
347 SetServiceStatus(ServiceStatusHandle
,
352 ServiceControlHandler(DWORD dwControl
,
359 case SERVICE_CONTROL_STOP
:
360 case SERVICE_CONTROL_SHUTDOWN
:
361 UpdateServiceStatus(SERVICE_STOP_PENDING
);
362 if (hStopEvent
!= NULL
)
363 SetEvent(hStopEvent
);
364 return ERROR_SUCCESS
;
366 case SERVICE_CONTROL_INTERROGATE
:
367 SetServiceStatus(ServiceStatusHandle
,
369 return ERROR_SUCCESS
;
372 return ERROR_CALL_NOT_IMPLEMENTED
;
377 ServiceMain(DWORD argc
, LPWSTR
* argv
)
379 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
380 ServiceControlHandler
,
382 if (!ServiceStatusHandle
)
384 DPRINT1("DHCPCSVC: Unable to register service control handler (%lx)\n", GetLastError());
388 UpdateServiceStatus(SERVICE_START_PENDING
);
390 /* Create the stop event */
391 hStopEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
392 if (hStopEvent
== NULL
)
394 UpdateServiceStatus(SERVICE_STOPPED
);
398 UpdateServiceStatus(SERVICE_START_PENDING
);
402 DPRINT1("DHCPCSVC: init_client() failed!\n");
403 UpdateServiceStatus(SERVICE_STOPPED
);
407 DH_DbgPrint(MID_TRACE
,("DHCP Service Started\n"));
409 UpdateServiceStatus(SERVICE_RUNNING
);
411 DH_DbgPrint(MID_TRACE
,("Going into dispatch()\n"));
412 DH_DbgPrint(MID_TRACE
,("DHCPCSVC: DHCP service is starting up\n"));
414 dispatch(hStopEvent
);
416 DH_DbgPrint(MID_TRACE
,("DHCPCSVC: DHCP service is shutting down\n"));
419 UpdateServiceStatus(SERVICE_STOPPED
);
423 DllMain(HINSTANCE hinstDLL
,
429 case DLL_PROCESS_ATTACH
:
430 DisableThreadLibraryCalls(hinstDLL
);
433 case DLL_PROCESS_DETACH
: