The issue is not which index location of the parameter (first or last) the table name is located, the issue is that the params array is not repopulated after is reDIMmed.
Also
Dim params(cmd.Parameters.Length - 2)
should still just be
Dim params(cmd.Parameters.Length - 1)
. The new params array is only one item shorter (the table name) than the original params array. The issue now is that this new params array is empty and has not been populated. The crucial missing steps are to copy the proper, non-table, elements from the passed on Parameters to the new, one less element, params array. Without that step, an empty array is used in the ExecQuery2 method and produces the failure/error message.