HiiRemovePackageList (
  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,
  IN EFI_HII_HANDLE                     Handle
  )
{
  EFI_STATUS                          Status;
  HII_DATABASE_PRIVATE_DATA           *Private;
  LIST_ENTRY                          *Link;
  HII_DATABASE_RECORD                 *Node;
  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageList;
  HII_HANDLE                          *HiiHandle;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (!IsHiiHandleValid (Handle)) {
    return EFI_NOT_FOUND;
  }

  EfiAcquireLock (&mHiiDatabaseLock);

  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

  //
  // Get the packagelist to be removed.
  //
  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
    if (Node->Handle == Handle) {
      PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);
      ASSERT (PackageList != NULL);

      //
      // Call registered functions with REMOVE_PACK before removing packages
      // then remove them.
      //
      Status = RemoveGuidPackages (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }
      Status = RemoveFormPackages (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }
      Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }
      Status = RemoveStringPackages (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }
      Status = RemoveFontPackages (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }
      Status = RemoveImagePackages (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }
      Status = RemoveSimpleFontPackages (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }
      Status = RemoveDevicePathPackage (Private, Handle, PackageList);
      if (EFI_ERROR (Status)) {
        EfiReleaseLock (&mHiiDatabaseLock);
        return Status;
      }

      //
      // Free resources of the package list
      //
      RemoveEntryList (&Node->DatabaseEntry);

      HiiHandle = (HII_HANDLE *) Handle;
      RemoveEntryList (&HiiHandle->Handle);
      Private->HiiHandleCount--;
      ASSERT (Private->HiiHandleCount >= 0);

      HiiHandle->Signature = 0;
      FreePool (HiiHandle);
      FreePool (Node->PackageList);
      FreePool (Node);

      //
      // Check whether need to get the Database info.
      // Only after ReadyToBoot, need to do the export.
      //
      if (gExportAfterReadyToBoot) {
        HiiGetDatabaseInfo (This);
      }
      EfiReleaseLock (&mHiiDatabaseLock);

      //
      // Notes:
      // HiiGetDatabaseInfo () will get the contents of HII data base,
      // belong to the atomic behavior of Hii Database update.
      // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
      // we can not think it belong to the atomic behavior of Hii Database update.
      // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
      //

      //
      // Check whether need to get the configuration setting info from HII drivers.
      // When after ReadyToBoot and need to do the export for form package remove.
      //
      if (gExportAfterReadyToBoot && gExportConfigResp) {
        HiiGetConfigRespInfo (This);
      }
      return EFI_SUCCESS;
    }
  }

  EfiReleaseLock (&mHiiDatabaseLock);
  return EFI_NOT_FOUND;
}