首页 > 解决方案 > Python ctypes winapi GetUserProfileDirectory 访问冲突读取

问题描述

我在第一次登录后尝试获取新的用户配置文件路径,但我收到“OSError:异常:访问冲突读取 0x********”

我调用 ctypes.windll.advapi32.LogonUserW() 并将令牌和 PROFILEINFOW 结构传递给 ctypes.windll.userenv.LoadUserProfileW()

用户配置文件被创建,但如果用户名之后的文件夹名称已经存在,则 Windows 会自动创建一个新文件夹。

PROFILEINFOW 结构内的配置文件路径为 None,所以我想调用 ctypes.windll.userenv.GetUserProfileDirectoryW()。如果我传入的缓冲区大小为零,那么我会收到一个响应,其中包含指示所需大小的缓冲区,但即使使用缓冲区 = MAX_PATH,我仍然会遇到读取冲突

token = ctypes.c_void_p()
ctypes.windll.advapi32.LogonUserW(username, domain, password, 2, 0, ctypes.byref(token))

class PROFILEINFOW(ctypes.Structure):
    _fields_ = [('Size', ctypes.c_ulong),
                ('Flags', ctypes.c_ulong),
                ('UserName', ctypes.c_wchar_p),
                ('ProfilePath', ctypes.c_wchar_p),
                ('DefaultPath', ctypes.c_wchar_p),
                ('ServerName', ctypes.c_wchar_p),
                ('PolicyPath', ctypes.c_wchar_p),
                ('Handle', ctypes.c_void_p)]

    def __init__(self, username):
        self.Size = ctypes.sizeof(self)
        self.UserName = username
        super().__init__()

profile = PROFILEINFOW(username)
ctypes.windll.userenv.LoadUserProfileW(token, ctypes.byref(profile))

这有效:

profile_directory_buffer = ctypes.c_ulong()
ctypes.windll.userenv.GetUserProfileDirectoryW(token, None, ctypes.byref(profile_directory_buffer))

以下都因读取冲突错误而失败:

profile_directory = ctypes.c_wchar_p()
ctypes.windll.userenv.GetUserProfileDirectoryW(token, ctypes.byref(profile_directory), 260)

profile_directory = ctypes.create_unicode_buffer(260)
ctypes.windll.userenv.GetUserProfileDirectoryW(token, profile_directory, 260)

profile_directory = ctypes.create_unicode_buffer(260)
ctypes.windll.userenv.GetUserProfileDirectoryW(token, ctypes.byref(profile_directory), 260)

前两个命令运行没有问题,但我可以找出第三个命令的语法来解决这个违规错误。

标签: python-3.xctypes

解决方案


所以我想这取决于函数,但在这种情况下,我可以通过执行以下操作来获取路径:

profile_directory = ctypes.create_unicode_buffer(260)
profile_buffer = ctypes.c_ulong(260)
ctypes.windll.userenv.GetUserProfileDirectoryW(self.token, ctypes.byref(profile_directory), ctypes.byref(profile_buffer))

推荐阅读