1) Remove buffer overflow when the number of Driver Binding Protocols increases in...
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Core / Dxe / Hand / locate.c
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   locate.c\r
15 \r
16 Abstract:\r
17 \r
18   Locate handle functions    \r
19 \r
20 Revision History\r
21 \r
22 --*/\r
23 \r
24 #include <DxeMain.h>\r
25 \r
26 //\r
27 // ProtocolRequest - Last LocateHandle request ID\r
28 //\r
29 UINTN mEfiLocateHandleRequest = 0;\r
30 \r
31 //\r
32 // Internal prototypes\r
33 //\r
34 \r
35 typedef struct {\r
36   EFI_GUID        *Protocol;\r
37   VOID            *SearchKey;\r
38   LIST_ENTRY      *Position;\r
39   PROTOCOL_ENTRY  *ProtEntry;\r
40 } LOCATE_POSITION;\r
41 \r
42 typedef \r
43 IHANDLE *\r
44 (* CORE_GET_NEXT) (\r
45   IN OUT LOCATE_POSITION    *Position,\r
46   OUT VOID                  **Interface\r
47   );\r
48 \r
49 STATIC\r
50 IHANDLE *\r
51 CoreGetNextLocateAllHandles (\r
52   IN OUT LOCATE_POSITION    *Position,\r
53   OUT VOID                  **Interface\r
54   );\r
55 \r
56 STATIC\r
57 IHANDLE *\r
58 CoreGetNextLocateByRegisterNotify (\r
59   IN OUT LOCATE_POSITION    *Position,\r
60   OUT VOID                  **Interface\r
61   );\r
62 \r
63 STATIC\r
64 IHANDLE *\r
65 CoreGetNextLocateByProtocol (\r
66   IN OUT LOCATE_POSITION    *Position,\r
67   OUT VOID                  **Interface\r
68   );\r
69 \r
70 //\r
71 //\r
72 //\r
73 \r
74 \r
75 \r
76  \r
77 EFI_STATUS\r
78 EFIAPI\r
79 CoreLocateHandle (\r
80   IN EFI_LOCATE_SEARCH_TYPE   SearchType,\r
81   IN EFI_GUID                 *Protocol   OPTIONAL,\r
82   IN VOID                     *SearchKey  OPTIONAL,\r
83   IN OUT UINTN                *BufferSize,\r
84   OUT EFI_HANDLE              *Buffer\r
85   )\r
86 /*++\r
87 \r
88 Routine Description:\r
89 \r
90   Locates the requested handle(s) and returns them in Buffer.\r
91 \r
92 Arguments:\r
93 \r
94   SearchType  - The type of search to perform to locate the handles\r
95 \r
96   Protocol    - The protocol to search for\r
97   \r
98   SearchKey   - Dependant on SearchType\r
99 \r
100   BufferSize  - On input the size of Buffer.  On output the \r
101                 size of data returned.  \r
102 \r
103   Buffer      - The buffer to return the results in\r
104 \r
105 \r
106 Returns:\r
107 \r
108   EFI_BUFFER_TOO_SMALL      - Buffer too small, required buffer size is returned in BufferSize.\r
109 \r
110   EFI_INVALID_PARAMETER     - Invalid parameter\r
111   \r
112   EFI_SUCCESS               - Successfully found the requested handle(s) and returns them in Buffer.\r
113   \r
114 --*/\r
115 {\r
116   EFI_STATUS          Status;\r
117   LOCATE_POSITION     Position;\r
118   PROTOCOL_NOTIFY     *ProtNotify;\r
119   CORE_GET_NEXT       GetNext;\r
120   UINTN               ResultSize;\r
121   IHANDLE             *Handle;\r
122   IHANDLE             **ResultBuffer;\r
123   VOID                *Interface;\r
124  \r
125   if (BufferSize == NULL) {\r
126     Status = EFI_INVALID_PARAMETER;\r
127   }\r
128   \r
129   if ((*BufferSize > 0) && (Buffer == NULL)) {\r
130     return EFI_INVALID_PARAMETER;\r
131   }\r
132   \r
133   GetNext = NULL;\r
134   //\r
135   // Set initial position\r
136   //\r
137 \r
138   Position.Protocol  = Protocol;\r
139   Position.SearchKey = SearchKey;\r
140   Position.Position  = &gHandleList;\r
141 \r
142   ResultSize = 0;\r
143   ResultBuffer = (IHANDLE **) Buffer;\r
144   Status = EFI_SUCCESS;\r
145 \r
146   //\r
147   // Lock the protocol database\r
148   //\r
149   \r
150   CoreAcquireProtocolLock ();\r
151 \r
152   //\r
153   // Get the search function based on type\r
154   //\r
155   switch (SearchType) {\r
156   case AllHandles:      \r
157     GetNext = CoreGetNextLocateAllHandles;       \r
158     break;\r
159 \r
160   case ByRegisterNotify:    \r
161     //\r
162     // Must have SearchKey for locate ByRegisterNotify\r
163     //\r
164     if (SearchKey == NULL) {\r
165       Status = EFI_INVALID_PARAMETER;\r
166       break;\r
167     }\r
168     GetNext = CoreGetNextLocateByRegisterNotify;   \r
169     break;\r
170 \r
171   case ByProtocol:      \r
172     GetNext = CoreGetNextLocateByProtocol;\r
173     if (Protocol == NULL) {\r
174       Status = EFI_INVALID_PARAMETER;\r
175       break;\r
176     }\r
177     //\r
178     // Look up the protocol entry and set the head pointer\r
179     //\r
180     Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
181     if (Position.ProtEntry == NULL) {\r
182       Status = EFI_NOT_FOUND;\r
183       break;\r
184     }\r
185     Position.Position = &Position.ProtEntry->Protocols;\r
186     break;\r
187 \r
188   default:\r
189     Status = EFI_INVALID_PARAMETER;\r
190     break;\r
191   }\r
192 \r
193   if (EFI_ERROR(Status)) {\r
194     CoreReleaseProtocolLock ();\r
195     return Status;\r
196   }\r
197 \r
198   //\r
199   // Enumerate out the matching handles\r
200   //\r
201   mEfiLocateHandleRequest += 1;\r
202   for (; ;) {\r
203     //\r
204     // Get the next handle.  If no more handles, stop\r
205     //\r
206     Handle = GetNext (&Position, &Interface);\r
207     if (NULL == Handle) {\r
208       break;\r
209     }\r
210 \r
211     //\r
212     // Increase the resulting buffer size, and if this handle\r
213     // fits return it\r
214     //\r
215     ResultSize += sizeof(Handle);\r
216     if (ResultSize <= *BufferSize) {\r
217         *ResultBuffer = Handle;\r
218         ResultBuffer += 1;\r
219     }\r
220   }\r
221 \r
222   //\r
223   // If the result is a zero length buffer, then there were no\r
224   // matching handles\r
225   //\r
226   if (ResultSize == 0) {\r
227     Status = EFI_NOT_FOUND;\r
228   } else {\r
229     //\r
230     // Return the resulting buffer size.  If it's larger than what\r
231     // was passed, then set the error code\r
232     //\r
233     if (ResultSize > *BufferSize) {\r
234       Status = EFI_BUFFER_TOO_SMALL;\r
235     } \r
236     \r
237     *BufferSize = ResultSize;\r
238 \r
239     if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {\r
240       //\r
241       // If this is a search by register notify and a handle was\r
242       // returned, update the register notification position\r
243       // \r
244       ProtNotify = SearchKey;\r
245       ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
246     }\r
247   }\r
248 \r
249   CoreReleaseProtocolLock ();\r
250   return Status;\r
251 }\r
252 \r
253 \r
254 STATIC\r
255 IHANDLE *\r
256 CoreGetNextLocateAllHandles (\r
257   IN OUT LOCATE_POSITION    *Position,\r
258   OUT VOID                  **Interface\r
259   )\r
260 /*++\r
261 \r
262 Routine Description:\r
263 \r
264   Routine to get the next Handle, when you are searching for all handles.\r
265 \r
266 Arguments:\r
267 \r
268   Position  - Information about which Handle to seach for.\r
269 \r
270   Interface - Return the interface structure for the matching protocol.\r
271   \r
272 Returns:\r
273   IHANDLE - An IHANDLE is returned if the next Position is not the end of the\r
274             list. A NULL_HANDLE is returned if it's the end of the list.\r
275   \r
276 --*/\r
277 {\r
278   IHANDLE     *Handle;\r
279 \r
280   //\r
281   // Next handle\r
282   //\r
283   Position->Position = Position->Position->ForwardLink;\r
284 \r
285   //\r
286   // If not at the end of the list, get the handle\r
287   //\r
288   Handle      = NULL_HANDLE;\r
289   *Interface  = NULL;\r
290   if (Position->Position != &gHandleList) {\r
291     Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
292   }\r
293 \r
294   return Handle;\r
295 }\r
296 \r
297 \r
298 STATIC\r
299 IHANDLE *\r
300 CoreGetNextLocateByRegisterNotify (\r
301   IN OUT LOCATE_POSITION    *Position,\r
302   OUT VOID                  **Interface\r
303   )\r
304 /*++\r
305 \r
306 Routine Description:\r
307 \r
308   Routine to get the next Handle, when you are searching for register protocol \r
309   notifies.\r
310 \r
311 Arguments:\r
312 \r
313   Position  - Information about which Handle to seach for.\r
314 \r
315   Interface - Return the interface structure for the matching protocol.\r
316   \r
317 Returns:\r
318   IHANDLE - An IHANDLE is returned if the next Position is not the end of the\r
319             list. A NULL_HANDLE is returned if it's the end of the list.\r
320   \r
321 --*/\r
322 {\r
323   IHANDLE             *Handle;\r
324   PROTOCOL_NOTIFY     *ProtNotify;\r
325   PROTOCOL_INTERFACE  *Prot;\r
326   LIST_ENTRY          *Link;    \r
327 \r
328   Handle      = NULL_HANDLE;\r
329   *Interface  = NULL;\r
330   ProtNotify = Position->SearchKey;\r
331 \r
332   //\r
333   // If this is the first request, get the next handle\r
334   //\r
335   if (ProtNotify != NULL) {\r
336     ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
337     Position->SearchKey = NULL;\r
338 \r
339     //\r
340     // If not at the end of the list, get the next handle\r
341     //\r
342     Link = ProtNotify->Position->ForwardLink;\r
343     if (Link != &ProtNotify->Protocol->Protocols) {\r
344       Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
345       Handle = (IHANDLE *) Prot->Handle;\r
346       *Interface = Prot->Interface;\r
347     }  \r
348   }\r
349 \r
350   return Handle;\r
351 }\r
352 \r
353 \r
354 STATIC\r
355 IHANDLE *\r
356 CoreGetNextLocateByProtocol (\r
357   IN OUT LOCATE_POSITION    *Position,\r
358   OUT VOID                  **Interface\r
359   )\r
360 /*++\r
361 \r
362 Routine Description:\r
363 \r
364   Routine to get the next Handle, when you are searching for a given protocol.\r
365 \r
366 Arguments:\r
367 \r
368   Position  - Information about which Handle to seach for.\r
369 \r
370   Interface - Return the interface structure for the matching protocol.\r
371   \r
372 Returns:\r
373   IHANDLE - An IHANDLE is returned if the next Position is not the end of the\r
374             list. A NULL_HANDLE is returned if it's the end of the list.\r
375   \r
376 --*/\r
377 {\r
378   IHANDLE             *Handle;\r
379   LIST_ENTRY          *Link;\r
380   PROTOCOL_INTERFACE  *Prot;\r
381  \r
382   Handle      = NULL_HANDLE;\r
383   *Interface  = NULL;\r
384   for (; ;) {\r
385     //\r
386     // Next entry\r
387     //\r
388     Link = Position->Position->ForwardLink;\r
389     Position->Position = Link;\r
390 \r
391     //\r
392     // If not at the end, return the handle\r
393     //\r
394     if (Link == &Position->ProtEntry->Protocols) {\r
395       Handle = NULL_HANDLE;\r
396       break;\r
397     }\r
398 \r
399     //\r
400     // Get the handle\r
401     //\r
402     Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
403     Handle = (IHANDLE *) Prot->Handle;\r
404     *Interface = Prot->Interface;\r
405 \r
406     //\r
407     // If this handle has not been returned this request, then \r
408     // return it now\r
409     //\r
410     if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
411       Handle->LocateRequest = mEfiLocateHandleRequest;\r
412       break;\r
413     }\r
414   }\r
415 \r
416   return Handle;\r
417 }\r
418 \r
419 \r
420 \r
421 EFI_STATUS\r
422 EFIAPI\r
423 CoreLocateDevicePath (\r
424   IN EFI_GUID                       *Protocol,\r
425   IN OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath,\r
426   OUT EFI_HANDLE                    *Device\r
427   )\r
428 /*++\r
429 \r
430 Routine Description:\r
431 \r
432   Locates the handle to a device on the device path that best matches the specified protocol.\r
433 \r
434 Arguments:\r
435 \r
436   Protocol    - The protocol to search for.\r
437   DevicePath  - On input, a pointer to a pointer to the device path. On output, the device\r
438                   path pointer is modified to point to the remaining part of the devicepath.\r
439   Device      - A pointer to the returned device handle.              \r
440 \r
441 Returns:\r
442 \r
443   EFI_SUCCESS           - The resulting handle was returned.\r
444   EFI_NOT_FOUND         - No handles matched the search.\r
445   EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
446 \r
447 --*/\r
448 {\r
449   INTN                        SourceSize;\r
450   INTN                        Size;\r
451   INTN                        BestMatch;\r
452   UINTN                       HandleCount;\r
453   UINTN                       Index;\r
454   EFI_STATUS                  Status;\r
455   EFI_HANDLE                  *Handles;\r
456   EFI_HANDLE                  Handle;\r
457   EFI_DEVICE_PATH_PROTOCOL    *SourcePath;\r
458   EFI_DEVICE_PATH_PROTOCOL    *TmpDevicePath;\r
459   \r
460   if (Protocol == NULL) {\r
461     return EFI_INVALID_PARAMETER;\r
462   }\r
463   \r
464   if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
465     return EFI_INVALID_PARAMETER;\r
466   }\r
467   \r
468   if (Device == NULL) {\r
469     return  EFI_INVALID_PARAMETER;\r
470   }\r
471   \r
472   *Device = NULL_HANDLE;\r
473   SourcePath = *DevicePath;\r
474   SourceSize = CoreDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
475   \r
476   //\r
477   // The source path can only have 1 instance\r
478   //\r
479   if (CoreIsDevicePathMultiInstance (SourcePath)) {\r
480     DEBUG((EFI_D_ERROR, "LocateDevicePath: Device path has too many instances\n"));\r
481     return EFI_INVALID_PARAMETER;\r
482   }\r
483 \r
484   //\r
485   // Get a list of all handles that support the requested protocol\r
486   //\r
487   Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
488   if (EFI_ERROR (Status) || HandleCount == 0) {\r
489     return EFI_NOT_FOUND;\r
490   }\r
491 \r
492   BestMatch = -1;\r
493   for(Index = 0; Index < HandleCount; Index += 1) {\r
494     Handle = Handles[Index];\r
495     Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
496     if (EFI_ERROR (Status)) {\r
497       //\r
498       // If this handle doesn't support device path, then skip it\r
499       //\r
500       continue;\r
501     }\r
502 \r
503     //\r
504     // Check if DevicePath is first part of SourcePath\r
505     //\r
506     Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
507     if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {\r
508       //\r
509       // If the size is equal to the best match, then we\r
510       // have a duplice device path for 2 different device\r
511       // handles\r
512       //\r
513       ASSERT (Size != BestMatch);\r
514       \r
515       //\r
516       // We've got a match, see if it's the best match so far\r
517       //\r
518       if (Size > BestMatch) {\r
519         BestMatch = Size;\r
520         *Device = Handle;\r
521       }\r
522     }\r
523   }\r
524 \r
525   CoreFreePool (Handles);\r
526    \r
527   //\r
528   // If there wasn't any match, then no parts of the device path was found.  \r
529   // Which is strange since there is likely a "root level" device path in the system.\r
530   //\r
531   if (BestMatch == -1) {\r
532     return EFI_NOT_FOUND;\r
533   }\r
534 \r
535   //\r
536   // Return the remaining part of the device path\r
537   //\r
538   *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
539   return EFI_SUCCESS;\r
540 }\r
541 \r
542 \r
543  \r
544 EFI_STATUS\r
545 EFIAPI\r
546 CoreLocateProtocol (\r
547   IN  EFI_GUID  *Protocol,\r
548   IN  VOID      *Registration OPTIONAL,\r
549   OUT VOID      **Interface\r
550   )\r
551 /*++\r
552 \r
553 Routine Description:\r
554 \r
555   Return the first Protocol Interface that matches the Protocol GUID. If\r
556   Registration is pasased in return a Protocol Instance that was just add\r
557   to the system. If Retistration is NULL return the first Protocol Interface\r
558   you find.\r
559 \r
560 Arguments:\r
561 \r
562   Protocol     - The protocol to search for\r
563   \r
564   Registration - Optional Registration Key returned from RegisterProtocolNotify() \r
565 \r
566   Interface    - Return the Protocol interface (instance).\r
567 \r
568 Returns:\r
569 \r
570   EFI_SUCCESS - If a valid Interface is returned\r
571   \r
572   EFI_INVALID_PARAMETER       - Invalid parameter\r
573   \r
574   EFI_NOT_FOUND               - Protocol interface not found\r
575 \r
576 --*/\r
577 {\r
578   EFI_STATUS              Status;\r
579   LOCATE_POSITION         Position;\r
580   PROTOCOL_NOTIFY         *ProtNotify;\r
581   IHANDLE                 *Handle;\r
582 \r
583   if (Interface == NULL) {\r
584     return EFI_INVALID_PARAMETER;\r
585   }\r
586   \r
587   if (Protocol == NULL) {\r
588     return EFI_NOT_FOUND;\r
589   }\r
590   \r
591   *Interface = NULL;\r
592   Status = EFI_SUCCESS;\r
593 \r
594   //\r
595   // Set initial position\r
596   //\r
597   Position.Protocol  = Protocol;\r
598   Position.SearchKey = Registration;\r
599   Position.Position  = &gHandleList;\r
600   \r
601   //\r
602   // Lock the protocol database\r
603   //\r
604   CoreAcquireProtocolLock ();\r
605 \r
606   mEfiLocateHandleRequest += 1;\r
607 \r
608   if (NULL == Registration) {\r
609     //\r
610     // Look up the protocol entry and set the head pointer\r
611     //\r
612     Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
613     if (Position.ProtEntry == NULL) {\r
614       Status = EFI_NOT_FOUND;\r
615       goto Done;\r
616     }\r
617     Position.Position = &Position.ProtEntry->Protocols;\r
618 \r
619     Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
620   } else {\r
621     Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);   \r
622   }\r
623 \r
624   if (NULL == Handle) {\r
625     Status = EFI_NOT_FOUND;\r
626   } else if (NULL != Registration) {\r
627     //\r
628     // If this is a search by register notify and a handle was\r
629     // returned, update the register notification position\r
630     // \r
631     ProtNotify = Registration;\r
632     ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
633   }\r
634 \r
635 Done:\r
636   CoreReleaseProtocolLock ();\r
637   return Status;\r
638 }\r
639 \r
640 \r
641  \r
642 EFI_STATUS\r
643 EFIAPI\r
644 CoreLocateHandleBuffer (\r
645   IN EFI_LOCATE_SEARCH_TYPE       SearchType,\r
646   IN EFI_GUID                     *Protocol OPTIONAL,\r
647   IN VOID                         *SearchKey OPTIONAL,\r
648   IN OUT UINTN                    *NumberHandles,\r
649   OUT EFI_HANDLE                  **Buffer\r
650   )\r
651 /*++\r
652 \r
653 Routine Description:\r
654 \r
655   Function returns an array of handles that support the requested protocol \r
656   in a buffer allocated from pool. This is a version of CoreLocateHandle()\r
657   that allocates a buffer for the caller.\r
658 \r
659 Arguments:\r
660 \r
661   SearchType           - Specifies which handle(s) are to be returned.\r
662   Protocol             - Provides the protocol to search by.   \r
663                          This parameter is only valid for SearchType ByProtocol.\r
664   SearchKey            - Supplies the search key depending on the SearchType.\r
665   NumberHandles      - The number of handles returned in Buffer.\r
666   Buffer               - A pointer to the buffer to return the requested array of \r
667                          handles that support Protocol.\r
668 \r
669 Returns:\r
670   \r
671   EFI_SUCCESS          - The result array of handles was returned.\r
672   EFI_NOT_FOUND        - No handles match the search. \r
673   EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.\r
674   EFI_INVALID_PARAMETER   - Invalid parameter\r
675 \r
676 --*/\r
677 {\r
678   EFI_STATUS          Status;\r
679   UINTN               BufferSize;\r
680 \r
681   if (NumberHandles == NULL) {\r
682     return EFI_INVALID_PARAMETER;\r
683   }\r
684 \r
685   if (Buffer == NULL) {\r
686     return EFI_INVALID_PARAMETER;\r
687   }\r
688 \r
689   BufferSize = 0;\r
690   *NumberHandles = 0;\r
691   *Buffer = NULL;\r
692   Status = CoreLocateHandle (\r
693              SearchType,\r
694              Protocol,\r
695              SearchKey,\r
696              &BufferSize,\r
697              *Buffer\r
698              );\r
699   //\r
700   // LocateHandleBuffer() returns incorrect status code if SearchType is\r
701   // invalid.\r
702   //\r
703   // Add code to correctly handle expected errors from CoreLocateHandle().\r
704   //\r
705   if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
706     if (Status != EFI_INVALID_PARAMETER) {\r
707       Status = EFI_NOT_FOUND;\r
708     }\r
709     return Status;\r
710   }\r
711 \r
712   *Buffer = CoreAllocateBootServicesPool (BufferSize);\r
713   if (*Buffer == NULL) {\r
714     return EFI_OUT_OF_RESOURCES;\r
715   }\r
716 \r
717   Status = CoreLocateHandle (\r
718              SearchType,\r
719              Protocol,\r
720              SearchKey,\r
721              &BufferSize,\r
722              *Buffer\r
723              );\r
724 \r
725   *NumberHandles = BufferSize/sizeof(EFI_HANDLE);\r
726   if (EFI_ERROR(Status)) {\r
727     *NumberHandles = 0;\r
728   }\r
729 \r
730   return Status;\r
731 }\r
732 \r
733 \r