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
;
20 static HANDLE PipeHandle
= INVALID_HANDLE_VALUE
;
23 DhcpCApiInitialize(LPDWORD Version
)
27 /* Wait for the pipe to be available */
28 if (!WaitNamedPipeW(DHCP_PIPE_NAME
, NMPWAIT_USE_DEFAULT_WAIT
))
30 /* No good, we failed */
31 return GetLastError();
34 /* It's available, let's try to open it */
35 PipeHandle
= CreateFileW(DHCP_PIPE_NAME
,
36 GENERIC_READ
| GENERIC_WRITE
,
37 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
43 /* Check if we succeeded in opening the pipe */
44 if (PipeHandle
== INVALID_HANDLE_VALUE
)
47 return GetLastError();
50 /* Change the pipe into message mode */
51 PipeMode
= PIPE_READMODE_MESSAGE
;
52 if (!SetNamedPipeHandleState(PipeHandle
, &PipeMode
, NULL
, NULL
))
54 /* Mode change failed */
55 CloseHandle(PipeHandle
);
56 PipeHandle
= INVALID_HANDLE_VALUE
;
57 return GetLastError();
61 /* We're good to go */
70 CloseHandle(PipeHandle
);
71 PipeHandle
= INVALID_HANDLE_VALUE
;
75 DhcpQueryHWInfo(DWORD AdapterIndex
,
81 COMM_DHCP_REPLY Reply
;
85 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
87 Req
.Type
= DhcpReqQueryHWInfo
;
88 Req
.AdapterIndex
= AdapterIndex
;
90 Result
= TransactNamedPipe(PipeHandle
,
92 &Reply
, sizeof(Reply
),
96 /* Pipe transaction failed */
100 if (Reply
.Reply
== 0)
103 *MediaType
= Reply
.QueryHWInfo
.MediaType
;
104 *Mtu
= Reply
.QueryHWInfo
.Mtu
;
105 *Speed
= Reply
.QueryHWInfo
.Speed
;
110 DhcpLeaseIpAddress(DWORD AdapterIndex
)
113 COMM_DHCP_REPLY Reply
;
117 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
119 Req
.Type
= DhcpReqLeaseIpAddress
;
120 Req
.AdapterIndex
= AdapterIndex
;
122 Result
= TransactNamedPipe(PipeHandle
,
124 &Reply
, sizeof(Reply
),
128 /* Pipe transaction failed */
136 DhcpReleaseIpAddressLease(DWORD AdapterIndex
)
139 COMM_DHCP_REPLY Reply
;
143 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
145 Req
.Type
= DhcpReqReleaseIpAddress
;
146 Req
.AdapterIndex
= AdapterIndex
;
148 Result
= TransactNamedPipe(PipeHandle
,
150 &Reply
, sizeof(Reply
),
154 /* Pipe transaction failed */
162 DhcpRenewIpAddressLease(DWORD AdapterIndex
)
165 COMM_DHCP_REPLY Reply
;
169 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
171 Req
.Type
= DhcpReqRenewIpAddress
;
172 Req
.AdapterIndex
= AdapterIndex
;
174 Result
= TransactNamedPipe(PipeHandle
,
176 &Reply
, sizeof(Reply
),
180 /* Pipe transaction failed */
188 DhcpStaticRefreshParams(DWORD AdapterIndex
,
193 COMM_DHCP_REPLY Reply
;
197 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
199 Req
.Type
= DhcpReqStaticRefreshParams
;
200 Req
.AdapterIndex
= AdapterIndex
;
201 Req
.Body
.StaticRefreshParams
.IPAddress
= Address
;
202 Req
.Body
.StaticRefreshParams
.Netmask
= Netmask
;
204 Result
= TransactNamedPipe(PipeHandle
,
206 &Reply
, sizeof(Reply
),
210 /* Pipe transaction failed */
218 * Set new TCP/IP parameters and notify DHCP client service of this
220 * \param[in] ServerName
221 * NULL for local machine
223 * \param[in] AdapterName
224 * IPHLPAPI name of adapter to change
226 * \param[in] NewIpAddress
227 * TRUE if IP address changes
229 * \param[in] IpAddress
230 * New IP address (network byte order)
232 * \param[in] SubnetMask
233 * New subnet mask (network byte order)
235 * \param[in] DhcpAction
240 * \return non-zero on success
242 * \remarks Undocumented by Microsoft
245 DhcpNotifyConfigChange(LPWSTR ServerName
,
253 DPRINT1("DHCPCSVC: DhcpNotifyConfigChange not implemented yet\n");
258 * Get DHCP info for an adapter
260 * \param[in] AdapterIndex
261 * Index of the adapter (iphlpapi-style) for which info is
264 * \param[out] DhcpEnabled
265 * Returns whether DHCP is enabled for the adapter
267 * \param[out] DhcpServer
268 * Returns DHCP server IP address (255.255.255.255 if no
269 * server reached yet), in network byte order
271 * \param[out] LeaseObtained
272 * Returns time at which the lease was obtained
274 * \param[out] LeaseExpires
275 * Returns time at which the lease will expire
277 * \return non-zero on success
279 * \remarks This is a ReactOS-only routine
282 DhcpRosGetAdapterInfo(DWORD AdapterIndex
,
285 time_t* LeaseObtained
,
286 time_t* LeaseExpires
)
289 COMM_DHCP_REPLY Reply
;
293 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
295 Req
.Type
= DhcpReqGetAdapterInfo
;
296 Req
.AdapterIndex
= AdapterIndex
;
298 Result
= TransactNamedPipe(PipeHandle
,
300 &Reply
, sizeof(Reply
),
303 if (Result
&& Reply
.Reply
!= 0)
304 *DhcpEnabled
= Reply
.GetAdapterInfo
.DhcpEnabled
;
306 *DhcpEnabled
= FALSE
;
310 *DhcpServer
= Reply
.GetAdapterInfo
.DhcpServer
;
311 *LeaseObtained
= Reply
.GetAdapterInfo
.LeaseObtained
;
312 *LeaseExpires
= Reply
.GetAdapterInfo
.LeaseExpires
;
316 *DhcpServer
= INADDR_NONE
;
326 UpdateServiceStatus(DWORD dwState
)
328 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
329 ServiceStatus
.dwCurrentState
= dwState
;
331 ServiceStatus
.dwControlsAccepted
= 0;
333 ServiceStatus
.dwWin32ExitCode
= 0;
334 ServiceStatus
.dwServiceSpecificExitCode
= 0;
335 ServiceStatus
.dwCheckPoint
= 0;
337 if (dwState
== SERVICE_START_PENDING
||
338 dwState
== SERVICE_STOP_PENDING
||
339 dwState
== SERVICE_PAUSE_PENDING
||
340 dwState
== SERVICE_CONTINUE_PENDING
)
341 ServiceStatus
.dwWaitHint
= 10000;
343 ServiceStatus
.dwWaitHint
= 0;
345 SetServiceStatus(ServiceStatusHandle
,
350 ServiceControlHandler(DWORD dwControl
,
357 case SERVICE_CONTROL_STOP
:
358 UpdateServiceStatus(SERVICE_STOP_PENDING
);
359 UpdateServiceStatus(SERVICE_STOPPED
);
360 return ERROR_SUCCESS
;
362 case SERVICE_CONTROL_PAUSE
:
363 UpdateServiceStatus(SERVICE_PAUSED
);
364 return ERROR_SUCCESS
;
366 case SERVICE_CONTROL_CONTINUE
:
367 UpdateServiceStatus(SERVICE_START_PENDING
);
368 UpdateServiceStatus(SERVICE_RUNNING
);
369 return ERROR_SUCCESS
;
371 case SERVICE_CONTROL_INTERROGATE
:
372 SetServiceStatus(ServiceStatusHandle
,
374 return ERROR_SUCCESS
;
376 case SERVICE_CONTROL_SHUTDOWN
:
377 UpdateServiceStatus(SERVICE_STOP_PENDING
);
378 UpdateServiceStatus(SERVICE_STOPPED
);
379 return ERROR_SUCCESS
;
382 return ERROR_CALL_NOT_IMPLEMENTED
;
387 ServiceMain(DWORD argc
, LPWSTR
* argv
)
389 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
390 ServiceControlHandler
,
392 if (!ServiceStatusHandle
)
394 DPRINT1("DHCPCSVC: Unable to register service control handler (%lx)\n", GetLastError());
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"));
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
: