]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Driver.c
CommitLineData
8a67d61d 1/** @file\r
2\r
3Copyright (c) 2005 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Tcp4Driver.c\r
15\r
16Abstract:\r
17\r
18\r
19**/\r
20\r
21#include "Tcp4Main.h"\r
22\r
23\r
24UINT16 mTcp4RandomPort;\r
25extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;\r
26\r
27TCP4_HEARTBEAT_TIMER mTcp4Timer = {\r
28 NULL,\r
29 0\r
30};\r
31\r
32EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {\r
33 Tcp4GetModeData,\r
34 Tcp4Configure,\r
35 Tcp4Routes,\r
36 Tcp4Connect,\r
37 Tcp4Accept,\r
38 Tcp4Transmit,\r
39 Tcp4Receive,\r
40 Tcp4Close,\r
41 Tcp4Cancel,\r
42 Tcp4Poll\r
43};\r
44\r
45SOCK_INIT_DATA mTcp4DefaultSockData = {\r
46 SOCK_STREAM,\r
47 0,\r
48 NULL,\r
49 TCP_BACKLOG,\r
50 TCP_SND_BUF_SIZE,\r
51 TCP_RCV_BUF_SIZE,\r
52 &mTcp4ProtocolTemplate,\r
53 Tcp4Dispatcher,\r
54 NULL,\r
55};\r
56\r
57EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {\r
58 Tcp4DriverBindingSupported,\r
59 Tcp4DriverBindingStart,\r
60 Tcp4DriverBindingStop,\r
61 0xa,\r
62 NULL,\r
63 NULL\r
64};\r
65\r
66EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {\r
67 Tcp4ServiceBindingCreateChild,\r
68 Tcp4ServiceBindingDestroyChild\r
69};\r
70\r
71\r
72/**\r
73 Create and start the heartbeat timer for TCP driver.\r
74\r
75 None.\r
76\r
77 @retval EFI_SUCCESS The timer is successfully created and started.\r
78 @retval other The timer is not created.\r
79\r
80**/\r
81STATIC\r
82EFI_STATUS\r
83Tcp4CreateTimer (\r
84 VOID\r
85 )\r
86{\r
87 EFI_STATUS Status;\r
88\r
89 Status = EFI_SUCCESS;\r
90\r
91 if (mTcp4Timer.RefCnt == 0) {\r
92\r
93 Status = gBS->CreateEvent (\r
94 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
95 NET_TPL_TIMER,\r
96 TcpTicking,\r
97 NULL,\r
98 &mTcp4Timer.TimerEvent\r
99 );\r
100 if (!EFI_ERROR (Status)) {\r
101\r
102 Status = gBS->SetTimer (\r
103 mTcp4Timer.TimerEvent,\r
104 TimerPeriodic,\r
105 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)\r
106 );\r
107 }\r
108 }\r
109\r
110 if (!EFI_ERROR (Status)) {\r
111\r
112 mTcp4Timer.RefCnt++;\r
113 }\r
114\r
115 return Status;\r
116}\r
117\r
118\r
119/**\r
120 Stop and destroy the heartbeat timer for TCP driver.\r
121\r
122 None.\r
123\r
124 @return None.\r
125\r
126**/\r
127STATIC\r
128VOID\r
129Tcp4DestroyTimer (\r
130 VOID\r
131 )\r
132{\r
133 ASSERT (mTcp4Timer.RefCnt > 0);\r
134\r
135 mTcp4Timer.RefCnt--;\r
136\r
137 if (mTcp4Timer.RefCnt > 0) {\r
138 return;\r
139 }\r
140\r
141 gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);\r
142 gBS->CloseEvent (mTcp4Timer.TimerEvent);\r
143 mTcp4Timer.TimerEvent = NULL;\r
144}\r
145\r
146//@MT: EFI_DRIVER_ENTRY_POINT (Tcp4DriverEntryPoint)\r
147\r
148EFI_STATUS\r
149EFIAPI\r
150Tcp4DriverEntryPoint (\r
151 IN EFI_HANDLE ImageHandle,\r
152 IN EFI_SYSTEM_TABLE *SystemTable\r
153 )\r
154/*++\r
155\r
156Routine Description:\r
157\r
158 The entry point for Tcp4 driver. used to install\r
159 Tcp4 driver on the ImageHandle.\r
160\r
161Arguments:\r
162\r
163 ImageHandle - The firmware allocated handle for this\r
164 driver image.\r
165 SystemTable - Pointer to the EFI system table.\r
166\r
167Returns:\r
168\r
169 EFI_SUCCESS - Driver loaded.\r
170 other - Driver not loaded.\r
171\r
172--*/\r
173{\r
174 EFI_STATUS Status;\r
175 UINT32 Seed;\r
176\r
177 //\r
178 // Install the TCP4 Driver Binding Protocol\r
179 //\r
180 Status = NetLibInstallAllDriverProtocols (\r
181 ImageHandle,\r
182 SystemTable,\r
183 &mTcp4DriverBinding,\r
184 ImageHandle,\r
185 &gTcp4ComponentName,\r
186 NULL,\r
187 NULL\r
188 );\r
189\r
190 //\r
191 // Initialize ISS and random port.\r
192 //\r
193 Seed = NetRandomInitSeed ();\r
194 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;\r
195 mTcp4RandomPort = TCP4_PORT_KNOWN +\r
196 (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN);\r
197\r
198 return Status;\r
199}\r
200\r
201\r
202/**\r
203 Test to see if this driver supports ControllerHandle.\r
204\r
205 @param This Protocol instance pointer.\r
206 @param ControllerHandle Handle of device to test.\r
207 @param RemainingDevicePath Optional parameter use to pick a specific child\r
208 device to start.\r
209\r
210 @retval EFI_SUCCESS This driver supports this device.\r
211 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
212 @retval other This driver does not support this device.\r
213\r
214**/\r
215EFI_STATUS\r
216EFIAPI\r
217Tcp4DriverBindingSupported (\r
218 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
219 IN EFI_HANDLE ControllerHandle,\r
220 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
221 )\r
222{\r
223 EFI_STATUS Status;\r
224\r
225 //\r
226 // Test for the Tcp4ServiceBinding Protocol\r
227 //\r
228 Status = gBS->OpenProtocol (\r
229 ControllerHandle,\r
230 &gEfiTcp4ServiceBindingProtocolGuid,\r
231 NULL,\r
232 This->DriverBindingHandle,\r
233 ControllerHandle,\r
234 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
235 );\r
236 if (!EFI_ERROR (Status)) {\r
237 return EFI_ALREADY_STARTED;\r
238 }\r
239\r
240 //\r
241 // Test for the Ip4 Protocol\r
242 //\r
243 Status = gBS->OpenProtocol (\r
244 ControllerHandle,\r
245 &gEfiIp4ServiceBindingProtocolGuid,\r
246 NULL,\r
247 This->DriverBindingHandle,\r
248 ControllerHandle,\r
249 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
250 );\r
251\r
252 return Status;\r
253}\r
254\r
255\r
256/**\r
257 Start this driver on ControllerHandle.\r
258\r
259 @param This Protocol instance pointer.\r
260 @param ControllerHandle Handle of device to bind driver to.\r
261 @param RemainingDevicePath Optional parameter use to pick a specific child\r
262 device to start.\r
263\r
264 @retval EFI_SUCCESS The driver is added to ControllerHandle.\r
265 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the\r
266 driver.\r
267 @retval other The driver cannot be added to ControllerHandle.\r
268\r
269**/\r
270EFI_STATUS\r
271EFIAPI\r
272Tcp4DriverBindingStart (\r
273 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
274 IN EFI_HANDLE ControllerHandle,\r
275 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
276 )\r
277{\r
278 EFI_STATUS Status;\r
279 TCP4_SERVICE_DATA *TcpServiceData;\r
280 IP_IO_OPEN_DATA OpenData;\r
281\r
282 TcpServiceData = NetAllocateZeroPool (sizeof (TCP4_SERVICE_DATA));\r
283\r
284 if (NULL == TcpServiceData) {\r
285 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Have no enough"\r
286 " resource to create a Tcp Servcie Data!\n"));\r
287\r
288 return EFI_OUT_OF_RESOURCES;\r
289 }\r
290\r
291 //\r
292 // Create a new IP IO to Consume it\r
293 //\r
294 TcpServiceData->IpIo = IpIoCreate (This->DriverBindingHandle, ControllerHandle);\r
295 if (NULL == TcpServiceData->IpIo) {\r
296\r
297 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Have no enough"\r
298 " resource to create an Ip Io!\n"));\r
299\r
300 Status = EFI_OUT_OF_RESOURCES;\r
301 goto ReleaseServiceData;\r
302 }\r
303\r
304 //\r
305 // Configure and start IpIo.\r
306 //\r
307 NetZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));\r
308\r
309 OpenData.IpConfigData = mIpIoDefaultIpConfigData;\r
310 OpenData.IpConfigData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
311\r
312 OpenData.PktRcvdNotify = Tcp4RxCallback;\r
313 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);\r
314\r
315 if (EFI_ERROR (Status)) {\r
316 goto ReleaseServiceData;\r
317 }\r
318\r
319 //\r
320 // Create the timer event used by TCP driver\r
321 //\r
322 Status = Tcp4CreateTimer ();\r
323 if (EFI_ERROR (Status)) {\r
324\r
325 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Create TcpTimer"\r
326 " Event failed with %r\n", Status));\r
327\r
328 goto ReleaseIpIo;\r
329 }\r
330\r
331 //\r
332 // Install the Tcp4ServiceBinding Protocol on the\r
333 // controller handle\r
334 //\r
335 TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;\r
336\r
337 Status = gBS->InstallMultipleProtocolInterfaces (\r
338 &ControllerHandle,\r
339 &gEfiTcp4ServiceBindingProtocolGuid,\r
340 &TcpServiceData->Tcp4ServiceBinding,\r
341 NULL\r
342 );\r
343 if (EFI_ERROR (Status)) {\r
344\r
345 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Install Tcp4 Service Binding"\r
346 " Protocol failed for %r\n", Status));\r
347\r
348 goto ReleaseTimer;\r
349 }\r
350\r
351 //\r
352 // Initialize member in TcpServiceData\r
353 //\r
354 TcpServiceData->ControllerHandle = ControllerHandle;\r
355 TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;\r
356 TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;\r
357\r
358 TcpSetVariableData (TcpServiceData);\r
359\r
360 return EFI_SUCCESS;\r
361\r
362ReleaseTimer:\r
363\r
364 Tcp4DestroyTimer ();\r
365\r
366ReleaseIpIo:\r
367\r
368 IpIoDestroy (TcpServiceData->IpIo);\r
369\r
370ReleaseServiceData:\r
371\r
372 NetFreePool (TcpServiceData);\r
373\r
374 return Status;\r
375}\r
376\r
377\r
378/**\r
379 Stop this driver on ControllerHandle.\r
380\r
381 @param This Protocol instance pointer.\r
382 @param ControllerHandle Handle of device to stop driver on.\r
383 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
384 of children is zero stop the entire bus driver.\r
385 @param ChildHandleBuffer List of Child Handles to Stop.\r
386\r
387 @retval EFI_SUCCESS This driver is removed from ControllerHandle.\r
388 @retval other This driver is not removed from ControllerHandle.\r
389\r
390**/\r
391EFI_STATUS\r
392EFIAPI\r
393Tcp4DriverBindingStop (\r
394 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
395 IN EFI_HANDLE ControllerHandle,\r
396 IN UINTN NumberOfChildren,\r
397 IN EFI_HANDLE *ChildHandleBuffer\r
398 )\r
399{\r
400 EFI_STATUS Status;\r
401 EFI_HANDLE NicHandle;\r
402 EFI_SERVICE_BINDING_PROTOCOL *Tcp4ServiceBinding;\r
403 TCP4_SERVICE_DATA *TcpServiceData;\r
404 TCP_CB *TcpPcb;\r
405 SOCKET *Sock;\r
406 TCP4_PROTO_DATA *TcpProto;\r
407 NET_LIST_ENTRY *Entry;\r
408 NET_LIST_ENTRY *NextEntry;\r
409\r
410 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.\r
411 //\r
412 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);\r
413 if (NicHandle == NULL) {\r
414 return EFI_SUCCESS;\r
415 }\r
416\r
417 //\r
418 // Retrieve the TCP driver Data Structure\r
419 //\r
420 Status = gBS->OpenProtocol (\r
421 NicHandle,\r
422 &gEfiTcp4ServiceBindingProtocolGuid,\r
423 (VOID **) &Tcp4ServiceBinding,\r
424 This->DriverBindingHandle,\r
425 ControllerHandle,\r
426 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
427 );\r
428 if (EFI_ERROR (Status)) {\r
429\r
430 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Locate Tcp4 Service "\r
431 " Binding Protocol failed with %r\n", Status));\r
432\r
433 return Status;\r
434 }\r
435\r
436 TcpServiceData = TCP4_FROM_THIS (Tcp4ServiceBinding);\r
437\r
438 //\r
439 // Kill TCP driver\r
440 //\r
441 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mTcpRunQue) {\r
442 TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
443\r
444 //\r
445 // Try to destroy this child\r
446 //\r
447 Sock = TcpPcb->Sk;\r
448 TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
449\r
450 if (TcpProto->TcpService == TcpServiceData) {\r
451 Status = SockDestroyChild (Sock);\r
452\r
453 if (EFI_ERROR (Status)) {\r
454\r
455 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Destroy Tcp "\r
456 "instance failed with %r\n", Status));\r
457 return Status;\r
458 }\r
459 }\r
460 }\r
461\r
462 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mTcpListenQue) {\r
463 TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
464\r
465 //\r
466 // Try to destroy this child\r
467 //\r
468 Sock = TcpPcb->Sk;\r
469 TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
470\r
471 if (TcpProto->TcpService == TcpServiceData) {\r
472 Status = SockDestroyChild (TcpPcb->Sk);\r
473 if (EFI_ERROR (Status)) {\r
474\r
475 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Destroy Tcp "\r
476 "instance failed with %r\n", Status));\r
477 return Status;\r
478 }\r
479 }\r
480 }\r
481\r
482 //\r
483 // Uninstall TCP servicebinding protocol\r
484 //\r
485 Status = gBS->UninstallMultipleProtocolInterfaces (\r
486 NicHandle,\r
487 &gEfiTcp4ServiceBindingProtocolGuid,\r
488 Tcp4ServiceBinding,\r
489 NULL\r
490 );\r
491 if (EFI_ERROR (Status)) {\r
492\r
493 TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Uninstall TCP service "\r
494 "binding protocol failed with %r\n", Status));\r
495 return Status;\r
496 }\r
497\r
498 //\r
499 // Destroy the IpIO consumed by TCP driver\r
500 //\r
501 Status = IpIoDestroy (TcpServiceData->IpIo);\r
502\r
503 //\r
504 // Destroy the heartbeat timer.\r
505 //\r
506 Tcp4DestroyTimer ();\r
507\r
508 //\r
509 // Clear the variable.\r
510 //\r
511 TcpClearVariableData (TcpServiceData);\r
512\r
513 //\r
514 // Release the TCP service data\r
515 //\r
516 NetFreePool (TcpServiceData);\r
517\r
518 return Status;\r
519}\r
520\r
521\r
522/**\r
523 Creates a child handle with a set of TCP4 services.\r
524\r
525 @param This Protocol instance pointer.\r
526 @param ChildHandle Pointer to the handle of the child to create. If\r
527 it is NULL, then a new handle is created. If it is\r
528 not NULL, then the I/O services are added to the\r
529 existing child handle.\r
530\r
531 @retval EFI_SUCCESS The child handle is created.\r
532 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
533 @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the\r
534 child.\r
535\r
536**/\r
537EFI_STATUS\r
538EFIAPI\r
539Tcp4ServiceBindingCreateChild (\r
540 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
541 IN EFI_HANDLE *ChildHandle\r
542 )\r
543{\r
544 SOCKET *Sock;\r
545 TCP4_SERVICE_DATA *TcpServiceData;\r
546 TCP4_PROTO_DATA TcpProto;\r
547 EFI_STATUS Status;\r
548 VOID *Ip4;\r
549 EFI_TPL OldTpl;\r
550\r
551 if (NULL == This || NULL == ChildHandle) {\r
552 return EFI_INVALID_PARAMETER;\r
553 }\r
554\r
555 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
556 TcpServiceData = TCP4_FROM_THIS (This);\r
557 TcpProto.TcpService = TcpServiceData;\r
558 TcpProto.TcpPcb = NULL;\r
559\r
560 //\r
561 // Create a tcp instance with defualt Tcp default\r
562 // sock init data and TcpProto\r
563 //\r
564 mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;\r
565\r
566 Sock = SockCreateChild (&mTcp4DefaultSockData, &TcpProto, sizeof (TCP4_PROTO_DATA));\r
567 if (NULL == Sock) {\r
568 TCP4_DEBUG_ERROR (("Tcp4DriverBindingCreateChild: "\r
569 "No resource to create a Tcp Child\n"));\r
570\r
571 Status = EFI_OUT_OF_RESOURCES;\r
572 goto ON_EXIT;\r
573 }\r
574\r
575 *ChildHandle = Sock->SockHandle;\r
576\r
577 //\r
578 // Open the default Ip4 protocol of IP_IO BY_DRIVER.\r
579 //\r
580 Status = gBS->OpenProtocol (\r
581 TcpServiceData->IpIo->ChildHandle,\r
582 &gEfiIp4ProtocolGuid,\r
583 (VOID **) &Ip4,\r
584 TcpServiceData->DriverBindingHandle,\r
585 Sock->SockHandle,\r
586 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
587 );\r
588 if (EFI_ERROR (Status)) {\r
589 SockDestroyChild (Sock);\r
590 }\r
591\r
592ON_EXIT:\r
593 NET_RESTORE_TPL (OldTpl);\r
594 return Status;\r
595}\r
596\r
597\r
598/**\r
599 Destroys a child handle with a set of UDP4 services.\r
600\r
601 @param This Protocol instance pointer.\r
602 @param ChildHandle Handle of the child to be destroyed.\r
603\r
604 @retval EFI_SUCCESS The TCP4 services are removed from the child\r
605 handle.\r
606 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
607 @retval other The child handle is not destroyed.\r
608\r
609**/\r
610EFI_STATUS\r
611EFIAPI\r
612Tcp4ServiceBindingDestroyChild (\r
613 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
614 IN EFI_HANDLE ChildHandle\r
615 )\r
616{\r
617 EFI_STATUS Status;\r
618 EFI_TCP4_PROTOCOL *Tcp4;\r
619 SOCKET *Sock;\r
620 TCP4_PROTO_DATA *TcpProtoData;\r
621 TCP4_SERVICE_DATA *TcpServiceData;\r
622 EFI_TPL OldTpl;\r
623\r
624 if (NULL == This || NULL == ChildHandle) {\r
625 return EFI_INVALID_PARAMETER;\r
626 }\r
627\r
628 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
629\r
630 //\r
631 // retrieve the Tcp4 protocol from ChildHandle\r
632 //\r
633 Status = gBS->OpenProtocol (\r
634 ChildHandle,\r
635 &gEfiTcp4ProtocolGuid,\r
636 (VOID **) &Tcp4,\r
637 mTcp4DriverBinding.DriverBindingHandle,\r
638 ChildHandle,\r
639 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
640 );\r
641 if (EFI_ERROR (Status)) {\r
642 Status = EFI_UNSUPPORTED;\r
643 goto ON_EXIT;\r
644 }\r
645\r
646 //\r
647 // destroy this sock and related Tcp protocol control\r
648 // block\r
649 //\r
650 Sock = SOCK_FROM_THIS (Tcp4);\r
651 TcpProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
652 TcpServiceData = TcpProtoData->TcpService;\r
653\r
654 Status = SockDestroyChild (Sock);\r
655\r
656 //\r
657 // Close the Ip4 protocol.\r
658 //\r
659 gBS->CloseProtocol (\r
660 TcpServiceData->IpIo->ChildHandle,\r
661 &gEfiIp4ProtocolGuid,\r
662 TcpServiceData->DriverBindingHandle,\r
663 ChildHandle\r
664 );\r
665\r
666ON_EXIT:\r
667 NET_RESTORE_TPL (OldTpl);\r
668 return Status;\r
669}\r