39
39
#include "structmember.h" // PyMemberDef
40
40
41
41
42
- #define WINDOWS_LEAN_AND_MEAN
43
42
#include "windows.h"
44
43
#include <crtdbg.h>
45
44
#include "winreparse.h"
46
45
46
+ #include "pycore_runtime.h" // _Py_ID
47
+
47
48
#if defined(MS_WIN32 ) && !defined(MS_WIN64 )
48
49
#define HANDLE_TO_PYNUM (handle ) \
49
50
PyLong_FromUnsignedLong((unsigned long) handle)
@@ -781,12 +782,162 @@ gethandle(PyObject* obj, const char* name)
781
782
return ret ;
782
783
}
783
784
785
+ static PyObject *
786
+ sortenvironmentkey (PyObject * module , PyObject * item )
787
+ {
788
+ PyObject * result = NULL ;
789
+ PyObject * locale = PyUnicode_FromWideChar (LOCALE_NAME_INVARIANT , -1 );
790
+ if (locale ) {
791
+ result = _winapi_LCMapStringEx_impl (NULL , locale , LCMAP_UPPERCASE , item );
792
+ Py_DECREF (locale );
793
+ }
794
+ return result ;
795
+ }
796
+
797
+ static PyMethodDef sortenvironmentkey_def = {
798
+ "sortenvironmentkey" , _PyCFunction_CAST (sortenvironmentkey ), METH_O , "" ,
799
+ };
800
+
801
+ static int
802
+ sort_environment_keys (PyObject * keys )
803
+ {
804
+ PyObject * keyfunc = PyCFunction_New (& sortenvironmentkey_def , NULL );
805
+ if (keyfunc == NULL ) {
806
+ return -1 ;
807
+ }
808
+ PyObject * kwnames = Py_BuildValue ("(s)" , "key" );
809
+ if (kwnames == NULL ) {
810
+ Py_DECREF (keyfunc );
811
+ return -1 ;
812
+ }
813
+ PyObject * args [] = { keys , keyfunc };
814
+ PyObject * ret = PyObject_VectorcallMethod (& _Py_ID (sort ), args , 1 , kwnames );
815
+ Py_DECREF (keyfunc );
816
+ Py_DECREF (kwnames );
817
+ if (ret == NULL ) {
818
+ return -1 ;
819
+ }
820
+ Py_DECREF (ret );
821
+
822
+ return 0 ;
823
+ }
824
+
825
+ static int
826
+ compare_string_ordinal (PyObject * str1 , PyObject * str2 , int * result )
827
+ {
828
+ wchar_t * s1 = PyUnicode_AsWideCharString (str1 , NULL );
829
+ if (s1 == NULL ) {
830
+ return -1 ;
831
+ }
832
+ wchar_t * s2 = PyUnicode_AsWideCharString (str2 , NULL );
833
+ if (s2 == NULL ) {
834
+ PyMem_Free (s1 );
835
+ return -1 ;
836
+ }
837
+ * result = CompareStringOrdinal (s1 , -1 , s2 , -1 , TRUE);
838
+ PyMem_Free (s1 );
839
+ PyMem_Free (s2 );
840
+ return 0 ;
841
+ }
842
+
843
+ static PyObject *
844
+ dedup_environment_keys (PyObject * keys )
845
+ {
846
+ PyObject * result = PyList_New (0 );
847
+ if (result == NULL ) {
848
+ return NULL ;
849
+ }
850
+
851
+ // Iterate over the pre-ordered keys, check whether the current key is equal
852
+ // to the next key (ignoring case), if different, insert the current value
853
+ // into the result list. If they are equal, do nothing because we always
854
+ // want to keep the last inserted one.
855
+ for (Py_ssize_t i = 0 ; i < PyList_GET_SIZE (keys ); i ++ ) {
856
+ PyObject * key = PyList_GET_ITEM (keys , i );
857
+
858
+ // The last key will always be kept.
859
+ if (i + 1 == PyList_GET_SIZE (keys )) {
860
+ if (PyList_Append (result , key ) < 0 ) {
861
+ Py_DECREF (result );
862
+ return NULL ;
863
+ }
864
+ continue ;
865
+ }
866
+
867
+ PyObject * next_key = PyList_GET_ITEM (keys , i + 1 );
868
+ int compare_result ;
869
+ if (compare_string_ordinal (key , next_key , & compare_result ) < 0 ) {
870
+ Py_DECREF (result );
871
+ return NULL ;
872
+ }
873
+ if (compare_result == CSTR_EQUAL ) {
874
+ continue ;
875
+ }
876
+ if (PyList_Append (result , key ) < 0 ) {
877
+ Py_DECREF (result );
878
+ return NULL ;
879
+ }
880
+ }
881
+
882
+ return result ;
883
+ }
884
+
885
+ static PyObject *
886
+ normalize_environment (PyObject * environment )
887
+ {
888
+ PyObject * keys = PyMapping_Keys (environment );
889
+ if (keys == NULL ) {
890
+ return NULL ;
891
+ }
892
+
893
+ if (sort_environment_keys (keys ) < 0 ) {
894
+ Py_DECREF (keys );
895
+ return NULL ;
896
+ }
897
+
898
+ PyObject * normalized_keys = dedup_environment_keys (keys );
899
+ Py_DECREF (keys );
900
+ if (normalized_keys == NULL ) {
901
+ return NULL ;
902
+ }
903
+
904
+ PyObject * result = PyDict_New ();
905
+ if (result == NULL ) {
906
+ Py_DECREF (normalized_keys );
907
+ return NULL ;
908
+ }
909
+
910
+ for (int i = 0 ; i < PyList_GET_SIZE (normalized_keys ); i ++ ) {
911
+ PyObject * key = PyList_GET_ITEM (normalized_keys , i );
912
+ PyObject * value = PyObject_GetItem (environment , key );
913
+ if (value == NULL ) {
914
+ Py_DECREF (normalized_keys );
915
+ Py_DECREF (result );
916
+ return NULL ;
917
+ }
918
+
919
+ int ret = PyObject_SetItem (result , key , value );
920
+ Py_DECREF (value );
921
+ if (ret < 0 ) {
922
+ Py_DECREF (normalized_keys );
923
+ Py_DECREF (result );
924
+ return NULL ;
925
+ }
926
+ }
927
+
928
+ Py_DECREF (normalized_keys );
929
+
930
+ return result ;
931
+ }
932
+
784
933
static wchar_t *
785
934
getenvironment (PyObject * environment )
786
935
{
787
936
Py_ssize_t i , envsize , totalsize ;
788
937
wchar_t * buffer = NULL , * p , * end ;
789
- PyObject * keys , * values ;
938
+ PyObject * normalized_environment = NULL ;
939
+ PyObject * keys = NULL ;
940
+ PyObject * values = NULL ;
790
941
791
942
/* convert environment dictionary to windows environment string */
792
943
if (! PyMapping_Check (environment )) {
@@ -795,11 +946,16 @@ getenvironment(PyObject* environment)
795
946
return NULL ;
796
947
}
797
948
798
- keys = PyMapping_Keys (environment );
799
- if (! keys ) {
949
+ normalized_environment = normalize_environment (environment );
950
+ if (normalize_environment == NULL ) {
800
951
return NULL ;
801
952
}
802
- values = PyMapping_Values (environment );
953
+
954
+ keys = PyMapping_Keys (normalized_environment );
955
+ if (!keys ) {
956
+ goto error ;
957
+ }
958
+ values = PyMapping_Values (normalized_environment );
803
959
if (!values ) {
804
960
goto error ;
805
961
}
@@ -891,6 +1047,7 @@ getenvironment(PyObject* environment)
891
1047
892
1048
cleanup :
893
1049
error :
1050
+ Py_XDECREF (normalized_environment );
894
1051
Py_XDECREF (keys );
895
1052
Py_XDECREF (values );
896
1053
return buffer ;
0 commit comments