+#include <Protocol/ShellDynamicCommand.h>\r
+\r
+/**\r
+ function to insert string items into a list in the correct alphabetical place\r
+\r
+ the resultant list is a double NULL terminated list of NULL terminated strings.\r
+\r
+ upon successful return the memory must be caller freed (unless passed back in \r
+ via a loop where it will get reallocated).\r
+\r
+ @param[in,out] DestList double pointer to the list. may be NULL.\r
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.\r
+ @param[in] Item the item to insert.\r
+\r
+ @retval EFI_SUCCESS the operation was successful.\r
+**/\r
+EFI_STATUS\r
+LexicalInsertIntoList(\r
+ IN OUT CHAR16 **DestList, \r
+ IN OUT UINTN *DestSize,\r
+ IN CONST CHAR16 *Item\r
+ )\r
+{\r
+ CHAR16 *NewList;\r
+ INTN LexicalMatchValue;\r
+ CHAR16 *LexicalSpot;\r
+ UINTN SizeOfAddedNameInBytes;\r
+\r
+ //\r
+ // If there are none, then just return with success\r
+ //\r
+ if (Item == NULL || *Item == CHAR_NULL || StrLen(Item)==0) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ NewList = *DestList;\r
+\r
+ SizeOfAddedNameInBytes = StrSize(Item);\r
+ NewList = ReallocatePool(*DestSize, (*DestSize) + SizeOfAddedNameInBytes, NewList);\r
+ (*DestSize) = (*DestSize) + SizeOfAddedNameInBytes;\r
+\r
+ //\r
+ // Find the correct spot in the list\r
+ //\r
+ for (LexicalSpot = NewList\r
+ ; LexicalSpot != NULL && LexicalSpot < NewList + (*DestSize)\r
+ ; LexicalSpot += StrLen(LexicalSpot) + 1\r
+ ) {\r
+ //\r
+ // Get Lexical Comparison Value between PrevCommand and Command list entry\r
+ //\r
+ LexicalMatchValue = gUnicodeCollation->StriColl (\r
+ gUnicodeCollation,\r
+ (CHAR16 *)LexicalSpot,\r
+ (CHAR16 *)Item\r
+ );\r
+ //\r
+ // The new item goes before this one.\r
+ //\r
+ if (LexicalMatchValue > 0 || StrLen(LexicalSpot) == 0) {\r
+ if (StrLen(LexicalSpot) != 0) {\r
+ //\r
+ // Move this and all other items out of the way\r
+ //\r
+ CopyMem(\r
+ LexicalSpot + (SizeOfAddedNameInBytes/sizeof(CHAR16)),\r
+ LexicalSpot,\r
+ (*DestSize) - SizeOfAddedNameInBytes - ((LexicalSpot - NewList) * sizeof(CHAR16))\r
+ );\r
+ }\r
+\r
+ //\r
+ // Stick this one in place\r
+ //\r
+ StrCpyS(LexicalSpot, SizeOfAddedNameInBytes/sizeof(CHAR16), Item);\r
+ break;\r
+ }\r
+ }\r
+\r
+ *DestList = NewList;\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ function to add each command name from the linked list to the string list.\r
+\r
+ the resultant list is a double NULL terminated list of NULL terminated strings.\r
+\r
+ @param[in,out] DestList double pointer to the list. may be NULL.\r
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.\r
+ @param[in] SourceList the double linked list of commands.\r
+\r
+ @retval EFI_SUCCESS the operation was successful.\r
+**/\r
+EFI_STATUS\r
+CopyListOfCommandNames(\r
+ IN OUT CHAR16 **DestList, \r
+ IN OUT UINTN *DestSize,\r
+ IN CONST COMMAND_LIST *SourceList\r
+ )\r
+{\r
+ CONST COMMAND_LIST *Node;\r
+\r
+ for ( Node = (COMMAND_LIST*)GetFirstNode(&SourceList->Link)\r
+ ; SourceList != NULL && !IsListEmpty(&SourceList->Link) && !IsNull(&SourceList->Link, &Node->Link)\r
+ ; Node = (COMMAND_LIST*)GetNextNode(&SourceList->Link, &Node->Link)\r
+ ) {\r
+ LexicalInsertIntoList(DestList, DestSize, Node->CommandString);\r
+ }\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ function to add each dynamic command name to the string list.\r
+\r
+ the resultant list is a double NULL terminated list of NULL terminated strings.\r
+\r
+ @param[in,out] DestList double pointer to the list. may be NULL.\r
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.\r
+\r
+ @retval EFI_SUCCESS the operation was successful.\r
+ @return an error from HandleProtocol\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+CopyListOfCommandNamesWithDynamic(\r
+ IN OUT CHAR16** DestList, \r
+ IN OUT UINTN *DestSize\r
+ )\r
+{\r
+ EFI_HANDLE *CommandHandleList;\r
+ CONST EFI_HANDLE *NextCommand;\r
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;\r
+ EFI_STATUS Status;\r
+\r
+ CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);\r
+\r
+ //\r
+ // If there are none, then just return with success\r
+ //\r
+ if (CommandHandleList == NULL) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Append those to the list.\r
+ //\r
+ for (NextCommand = CommandHandleList ; *NextCommand != NULL && !EFI_ERROR(Status) ; NextCommand++) {\r
+ Status = gBS->HandleProtocol(\r
+ *NextCommand,\r
+ &gEfiShellDynamicCommandProtocolGuid,\r
+ (VOID **)&DynamicCommand\r
+ );\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ Status = LexicalInsertIntoList(DestList, DestSize, DynamicCommand->CommandName);\r
+ }\r
+\r
+ SHELL_FREE_NON_NULL(CommandHandleList);\r
+ return (Status);\r
+}\r
+\r