﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34294	File locking fails if argtypes redefined on Windows.	Simon Sawicki	Simon Sawicki	"`django.core.files.locks` uses `ctypes.windll.kernel32` which is a global instance. If other code redefines `windll.kernel32.LockFileEx.argtypes` the function fails with an error.
{{{#!python
import ctypes
import ctypes.wintypes

from django.core.files import locks


class OVERLAPPED(ctypes.Structure):
    _fields_ = [
        (""Internal"", ctypes.wintypes.LPVOID),
        (""InternalHigh"", ctypes.wintypes.LPVOID),
        (""Offset"", ctypes.wintypes.DWORD),
        (""OffsetHigh"", ctypes.wintypes.DWORD),
        (""hEvent"", ctypes.wintypes.HANDLE),
    ]


ctypes.windll.kernel32.LockFileEx.argtypes = [
    ctypes.wintypes.HANDLE,
    ctypes.wintypes.DWORD,
    ctypes.wintypes.DWORD,
    ctypes.wintypes.DWORD,
    ctypes.wintypes.DWORD,
    ctypes.wintypes.DWORD,
]

with open(""./file"", ""w"") as f:
    locks.lock(f, locks.LOCK_EX)
}}}
Possible patch:
{{{#!diff
diff --git a/django/core/files/locks.py b/django/core/files/locks.py
index 5752b08a69..c0f471f87d 100644
--- a/django/core/files/locks.py
+++ b/django/core/files/locks.py
@@ -32,12 +32,12 @@ if os.name == ""nt"":
         POINTER,
         Structure,
         Union,
+        WinDLL,
         byref,
         c_int64,
         c_ulong,
         c_void_p,
         sizeof,
-        windll,
     )
     from ctypes.wintypes import BOOL, DWORD, HANDLE
 
@@ -73,10 +73,11 @@ if os.name == ""nt"":
     LPOVERLAPPED = POINTER(OVERLAPPED)

     # --- Define function prototypes for extra safety ---
-    LockFileEx = windll.kernel32.LockFileEx
+    kernel32 = WinDLL(""kernel32"")
+    LockFileEx = kernel32.LockFileEx
     LockFileEx.restype = BOOL
     LockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, DWORD, LPOVERLAPPED]
-    UnlockFileEx = windll.kernel32.UnlockFileEx
+    UnlockFileEx = kernel32.UnlockFileEx
     UnlockFileEx.restype = BOOL
     UnlockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED]

diff --git a/tests/files/tests.py b/tests/files/tests.py
index b3478d2732..d0e633cb7a 100644
--- a/tests/files/tests.py
+++ b/tests/files/tests.py
@@ -200,6 +200,32 @@ class FileTests(unittest.TestCase):
             self.assertIs(locks.unlock(f1), True)
             self.assertIs(locks.unlock(f2), True)

+    @unittest.skipIf(os.name != ""nt"", ""File locking usees WinDLL on windows only"")      
+    def test_local_windll(self):
+        import ctypes
+        import ctypes.wintypes
+
+        old_argtypes = ctypes.windll.kernel32.LockFileEx.argtypes
+        try:
+            ctypes.windll.kernel32.LockFileEx.argtypes = [
+                ctypes.wintypes.HANDLE,
+                ctypes.wintypes.DWORD,
+                ctypes.wintypes.DWORD,
+                ctypes.wintypes.DWORD,
+                ctypes.wintypes.DWORD,
+                ctypes.wintypes.DWORD,
+            ]
+            file_path = Path(__file__).parent / ""test.png""
+            with open(file_path) as file:
+                try:
+                    locks.lock(file, locks.LOCK_EX)
+                except Exception:
+                    self.fail(""Locking raised exception with changed argtypes"")
+                else:
+                    locks.unlock(file)
+        finally:
+            ctypes.windll.kernel32.LockFileEx.argtypes = old_argtypes
+

 class NoNameFileTestCase(unittest.TestCase):
     """"""
}}}"	Bug	closed	File uploads/storage	dev	Normal	fixed			Accepted	1	0	0	0	0	0
