@@ -1894,6 +1894,113 @@ _winapi_GetFileType_impl(PyObject *module, HANDLE handle)
18941894 return result ;
18951895}
18961896
1897+ /*[clinic input]
1898+ _winapi._mimetypes_read_windows_registry
1899+
1900+ on_type_read: object
1901+
1902+ Optimized function for reading all known MIME types from the registry.
1903+
1904+ *on_type_read* is a callable taking *type* and *ext* arguments, as for
1905+ MimeTypes.add_type.
1906+ [clinic start generated code]*/
1907+
1908+ static PyObject *
1909+ _winapi__mimetypes_read_windows_registry_impl (PyObject * module ,
1910+ PyObject * on_type_read )
1911+ /*[clinic end generated code: output=20829f00bebce55b input=cd357896d6501f68]*/
1912+ {
1913+ #define CCH_EXT 128
1914+ #define CB_TYPE 510
1915+ struct {
1916+ wchar_t ext [CCH_EXT ];
1917+ wchar_t type [CB_TYPE / sizeof (wchar_t ) + 1 ];
1918+ } entries [64 ];
1919+ int entry = 0 ;
1920+ HKEY hkcr = NULL ;
1921+ LRESULT err ;
1922+
1923+ Py_BEGIN_ALLOW_THREADS
1924+ err = RegOpenKeyExW (HKEY_CLASSES_ROOT , NULL , 0 , KEY_READ , & hkcr );
1925+ for (DWORD i = 0 ; err == ERROR_SUCCESS || err == ERROR_MORE_DATA ; ++ i ) {
1926+ LPWSTR ext = entries [entry ].ext ;
1927+ LPWSTR type = entries [entry ].type ;
1928+ DWORD cchExt = CCH_EXT ;
1929+ DWORD cbType = CB_TYPE ;
1930+ HKEY subkey ;
1931+ DWORD regType ;
1932+
1933+ err = RegEnumKeyExW (hkcr , i , ext , & cchExt , NULL , NULL , NULL , NULL );
1934+ if (err != ERROR_SUCCESS || (cchExt && ext [0 ] != L'.' )) {
1935+ continue ;
1936+ }
1937+
1938+ err = RegOpenKeyExW (hkcr , ext , 0 , KEY_READ , & subkey );
1939+ if (err == ERROR_FILE_NOT_FOUND ) {
1940+ err = ERROR_SUCCESS ;
1941+ continue ;
1942+ } else if (err != ERROR_SUCCESS ) {
1943+ continue ;
1944+ }
1945+
1946+ err = RegQueryValueExW (subkey , L"Content Type" , NULL ,
1947+ & regType , (LPBYTE )type , & cbType );
1948+ RegCloseKey (subkey );
1949+ if (err == ERROR_FILE_NOT_FOUND ) {
1950+ err = ERROR_SUCCESS ;
1951+ continue ;
1952+ } else if (err != ERROR_SUCCESS ) {
1953+ continue ;
1954+ } else if (regType != REG_SZ || !cbType ) {
1955+ continue ;
1956+ }
1957+ type [cbType / sizeof (wchar_t )] = L'\0' ;
1958+
1959+ entry += 1 ;
1960+
1961+ /* Flush our cached entries if we are full */
1962+ if (entry == sizeof (entries ) / sizeof (entries [0 ])) {
1963+ Py_BLOCK_THREADS
1964+ for (int j = 0 ; j < entry ; ++ j ) {
1965+ PyObject * r = PyObject_CallFunction (
1966+ on_type_read , "uu" , entries [j ].type , entries [j ].ext
1967+ );
1968+ if (!r ) {
1969+ /* We blocked threads, so safe to return from here */
1970+ RegCloseKey (hkcr );
1971+ return NULL ;
1972+ }
1973+ Py_DECREF (r );
1974+ }
1975+ Py_UNBLOCK_THREADS
1976+ entry = 0 ;
1977+ }
1978+ }
1979+ if (hkcr ) {
1980+ RegCloseKey (hkcr );
1981+ }
1982+ Py_END_ALLOW_THREADS
1983+
1984+ if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_ITEMS ) {
1985+ PyErr_SetFromWindowsErr ((int )err );
1986+ return NULL ;
1987+ }
1988+
1989+ for (int j = 0 ; j < entry ; ++ j ) {
1990+ PyObject * r = PyObject_CallFunction (
1991+ on_type_read , "uu" , entries [j ].type , entries [j ].ext
1992+ );
1993+ if (!r ) {
1994+ return NULL ;
1995+ }
1996+ Py_DECREF (r );
1997+ }
1998+
1999+ Py_RETURN_NONE ;
2000+ #undef CCH_EXT
2001+ #undef CB_TYPE
2002+ }
2003+
18972004
18982005static PyMethodDef winapi_functions [] = {
18992006 _WINAPI_CLOSEHANDLE_METHODDEF
@@ -1926,6 +2033,7 @@ static PyMethodDef winapi_functions[] = {
19262033 _WINAPI_WRITEFILE_METHODDEF
19272034 _WINAPI_GETACP_METHODDEF
19282035 _WINAPI_GETFILETYPE_METHODDEF
2036+ _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
19292037 {NULL , NULL }
19302038};
19312039
0 commit comments