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 DhcpRequestParams(DWORD Flags
,
262 LPDHCPCAPI_CLASSID ClassId
,
263 DHCPCAPI_PARAMS_ARRAY SendParams
,
264 DHCPCAPI_PARAMS_ARRAY RecdParams
,
274 * Get DHCP info for an adapter
276 * \param[in] AdapterIndex
277 * Index of the adapter (iphlpapi-style) for which info is
280 * \param[out] DhcpEnabled
281 * Returns whether DHCP is enabled for the adapter
283 * \param[out] DhcpServer
284 * Returns DHCP server IP address (255.255.255.255 if no
285 * server reached yet), in network byte order
287 * \param[out] LeaseObtained
288 * Returns time at which the lease was obtained
290 * \param[out] LeaseExpires
291 * Returns time at which the lease will expire
293 * \return non-zero on success
295 * \remarks This is a ReactOS-only routine
298 DhcpRosGetAdapterInfo(DWORD AdapterIndex
,
301 time_t* LeaseObtained
,
302 time_t* LeaseExpires
)
305 COMM_DHCP_REPLY Reply
;
309 ASSERT(PipeHandle
!= INVALID_HANDLE_VALUE
);
311 Req
.Type
= DhcpReqGetAdapterInfo
;
312 Req
.AdapterIndex
= AdapterIndex
;
314 Result
= TransactNamedPipe(PipeHandle
,
316 &Reply
, sizeof(Reply
),
319 if (Result
&& Reply
.Reply
!= 0)
320 *DhcpEnabled
= Reply
.GetAdapterInfo
.DhcpEnabled
;
322 *DhcpEnabled
= FALSE
;
326 *DhcpServer
= Reply
.GetAdapterInfo
.DhcpServer
;
327 *LeaseObtained
= Reply
.GetAdapterInfo
.LeaseObtained
;
328 *LeaseExpires
= Reply
.GetAdapterInfo
.LeaseExpires
;
332 *DhcpServer
= INADDR_NONE
;
342 UpdateServiceStatus(DWORD dwState
)
344 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
345 ServiceStatus
.dwCurrentState
= dwState
;
347 if (dwState
== SERVICE_RUNNING
)
348 ServiceStatus
.dwControlsAccepted
= SERVICE_ACCEPT_SHUTDOWN
| SERVICE_ACCEPT_STOP
;
350 ServiceStatus
.dwControlsAccepted
= 0;
352 ServiceStatus
.dwWin32ExitCode
= 0;
353 ServiceStatus
.dwServiceSpecificExitCode
= 0;
354 ServiceStatus
.dwCheckPoint
= 0;
356 if (dwState
== SERVICE_START_PENDING
||
357 dwState
== SERVICE_STOP_PENDING
)
358 ServiceStatus
.dwWaitHint
= 1000;
360 ServiceStatus
.dwWaitHint
= 0;
362 SetServiceStatus(ServiceStatusHandle
,
367 ServiceControlHandler(DWORD dwControl
,
374 case SERVICE_CONTROL_STOP
:
375 case SERVICE_CONTROL_SHUTDOWN
:
376 UpdateServiceStatus(SERVICE_STOP_PENDING
);
377 if (hStopEvent
!= NULL
)
378 SetEvent(hStopEvent
);
379 return ERROR_SUCCESS
;
381 case SERVICE_CONTROL_INTERROGATE
:
382 SetServiceStatus(ServiceStatusHandle
,
384 return ERROR_SUCCESS
;
387 return ERROR_CALL_NOT_IMPLEMENTED
;
392 ServiceMain(DWORD argc
, LPWSTR
* argv
)
394 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
395 ServiceControlHandler
,
397 if (!ServiceStatusHandle
)
399 DPRINT1("DHCPCSVC: Unable to register service control handler (%lx)\n", GetLastError());
403 UpdateServiceStatus(SERVICE_START_PENDING
);
405 /* Create the stop event */
406 hStopEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
407 if (hStopEvent
== NULL
)
409 UpdateServiceStatus(SERVICE_STOPPED
);
413 UpdateServiceStatus(SERVICE_START_PENDING
);
417 DPRINT1("DHCPCSVC: init_client() failed!\n");
418 UpdateServiceStatus(SERVICE_STOPPED
);
422 DH_DbgPrint(MID_TRACE
,("DHCP Service Started\n"));
424 UpdateServiceStatus(SERVICE_RUNNING
);
426 DH_DbgPrint(MID_TRACE
,("Going into dispatch()\n"));
427 DH_DbgPrint(MID_TRACE
,("DHCPCSVC: DHCP service is starting up\n"));
429 dispatch(hStopEvent
);
431 DH_DbgPrint(MID_TRACE
,("DHCPCSVC: DHCP service is shutting down\n"));
434 UpdateServiceStatus(SERVICE_STOPPED
);
438 DllMain(HINSTANCE hinstDLL
,
444 case DLL_PROCESS_ATTACH
:
445 DisableThreadLibraryCalls(hinstDLL
);
448 case DLL_PROCESS_DETACH
: