@@ -1894,6 +1894,110 @@ _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 512
1915+ struct {
1916+ wchar_t ext [CCH_EXT ];
1917+ wchar_t type [CB_TYPE / sizeof (wchar_t )];
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+ }
1955+
1956+ entry += 1 ;
1957+
1958+ /* Flush our cached entries if we are full */
1959+ if (entry == sizeof (entries ) / sizeof (entries [0 ])) {
1960+ Py_BLOCK_THREADS
1961+ for (int j = 0 ; j < entry ; ++ j ) {
1962+ PyObject * r = PyObject_CallFunction (
1963+ on_type_read , "uu" , entries [j ].type , entries [j ].ext
1964+ );
1965+ if (!r ) {
1966+ /* We blocked threads, so safe to return from here */
1967+ RegCloseKey (hkcr );
1968+ return NULL ;
1969+ }
1970+ Py_DECREF (r );
1971+ }
1972+ Py_UNBLOCK_THREADS
1973+ entry = 0 ;
1974+ }
1975+ }
1976+ if (hkcr ) {
1977+ RegCloseKey (hkcr );
1978+ }
1979+ Py_END_ALLOW_THREADS
1980+
1981+ if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_ITEMS ) {
1982+ PyErr_SetFromWindowsErr ((int )err );
1983+ return NULL ;
1984+ }
1985+
1986+ for (int j = 0 ; j < entry ; ++ j ) {
1987+ PyObject * r = PyObject_CallFunction (
1988+ on_type_read , "uu" , entries [j ].type , entries [j ].ext
1989+ );
1990+ if (!r ) {
1991+ return NULL ;
1992+ }
1993+ Py_DECREF (r );
1994+ }
1995+
1996+ Py_RETURN_NONE ;
1997+ #undef CCH_EXT
1998+ #undef CB_TYPE
1999+ }
2000+
18972001
18982002static PyMethodDef winapi_functions [] = {
18992003 _WINAPI_CLOSEHANDLE_METHODDEF
@@ -1926,6 +2030,7 @@ static PyMethodDef winapi_functions[] = {
19262030 _WINAPI_WRITEFILE_METHODDEF
19272031 _WINAPI_GETACP_METHODDEF
19282032 _WINAPI_GETFILETYPE_METHODDEF
2033+ _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
19292034 {NULL , NULL }
19302035};
19312036
0 commit comments