Il fonctionne comme prévu.
L'expansion retardée développe les variables au moment de l'exécution, et non au moment de l'analyse, de sorte qu'elle interprète votre ligne ENDLOCAL & SET S1=!S2!
comme
endlocal
Mais à la partie de SET S1=!S2!
l'expansion retardée est désactivée, de sorte qu'elle ne peut plus être étendue.
Dans votre cas, vous pourriez utiliser ENDLOCAL & SET S1=%S2%
Comme le point d'exclamation est S2 est "sûr", car l'exp. retardée est désactivée au moment de l'exécution.
Mais un retour toujours sécurisé est un peu plus compliqué.
Nous en avons discuté à Dostips : Retourner N'IMPORTE QUELLE chaîne au-delà de la limite ENDLOCAL