ynkdir / py-win32more

Python bindings for Win32 API generated from win32metadata.
MIT License
101 stars 12 forks source link

Feature Request: Auto Casting C-types #4

Open byehack opened 1 year ago

byehack commented 1 year ago

In continue of https://github.com/ynkdir/py-win32more/issues/2#issuecomment-1465049680

All functions are typed for both arguments and results. but current behavior is, it'll raise if our entered arguments types are not exact same as specified.

proposed behavior is that it should auto casting the types for both arguments and results.

here is current working script:

from Windows.Win32.System.Rpc import RpcStringBindingComposeW
from Windows import UInt16, c_wchar_p
from ctypes import POINTER, cast

strBinding = cast(c_wchar_p(), POINTER(UInt16))
rStatus = RpcStringBindingComposeW(
    cast(c_wchar_p("0767a036-0d22-48aa-ba69-b619480f38cb"), POINTER(UInt16)),
    cast(c_wchar_p("ncalrpc"), POINTER(UInt16)),
    None,
    None,
    None,
    strBinding)
strBinding = cast(strBinding, c_wchar_p)

print(rStatus, strBinding.value)

Auto Casting will remove cast from our side:

from Windows.Win32.System.Rpc import RpcStringBindingComposeW
from Windows import UInt16, c_wchar_p

strBinding = c_wchar_p()
rStatus = RpcStringBindingComposeW(
    c_wchar_p("0767a036-0d22-48aa-ba69-b619480f38cb"),
    c_wchar_p("ncalrpc"),
    None,
    None,
    None,
    strBinding)
print(rStatus, strBinding.value)
byehack commented 1 year ago

Auto Casting will remove cast from our side:

from Windows.Win32.System.Rpc import RpcStringBindingComposeW
from Windows import UInt16, c_wchar_p

strBinding = c_wchar_p()
rStatus = RpcStringBindingComposeW(
    c_wchar_p("0767a036-0d22-48aa-ba69-b619480f38cb"),
    c_wchar_p("ncalrpc"),
    None,
    None,
    None,
    strBinding)
print(rStatus, strBinding.value)

And if we assume string object type is c_wchar_p and byte object type is c_char_p, we can have even simpler call:

from Windows.Win32.System.Rpc import RpcStringBindingComposeW
from Windows import c_wchar_p

strBinding = c_wchar_p()
rStatus = RpcStringBindingComposeW("0767a036-0d22-48aa-ba69-b619480f38cb", "ncalrpc", None, None, None, strBinding)
print(rStatus, strBinding.value)

I think this is current behavior in ctypes module when we are calling a typed function.

ynkdir commented 1 year ago

WIP I have not confirmed yet that if getting pointer value with byref(c_wchar_p()) is safe.

ynkdir commented 1 year ago

It seems to work. I merged fix. Could you confirm that works for you.

byehack commented 1 year ago

That's great, I can confirm both WIP examples above have been tested and passed successfully,

byehack commented 1 year ago

Reopened bcz still need to work to be complete. Look at this example (you can try to repro):

currently working script:

from Windows.Win32.System.Rpc import RPC_SECURITY_QOS_V3_W
from Windows.Win32.Security import CreateWellKnownSid, WELL_KNOWN_SID_TYPE_WinLocalSystemSid
from ctypes import cast, c_ulong, c_void_p, create_string_buffer

SECURITY_MAX_SID_SIZE = 68
sidSize = c_ulong(SECURITY_MAX_SID_SIZE)
sid = create_string_buffer(SECURITY_MAX_SID_SIZE)
rStatus = CreateWellKnownSid(
    WELL_KNOWN_SID_TYPE_WinLocalSystemSid,
    None,
    sid,
    sidSize)
if not rStatus:
    raise
security = RPC_SECURITY_QOS_V3_W()
security.Sid = cast(sid, c_void_p)

Expected Work with auto casting:

from Windows.Win32.System.Rpc import RPC_SECURITY_QOS_V3_W
from Windows.Win32.Security import CreateWellKnownSid, WELL_KNOWN_SID_TYPE_WinLocalSystemSid
from ctypes import cast, c_ulong, c_void_p, create_string_buffer

SECURITY_MAX_SID_SIZE = 68
sidSize = SECURITY_MAX_SID_SIZE # removed c_ulong
sid = create_string_buffer(SECURITY_MAX_SID_SIZE)
rStatus = CreateWellKnownSid(
    WELL_KNOWN_SID_TYPE_WinLocalSystemSid,
    None,
    sid,
    sidSize) # not work after removed c_ulong
if not rStatus:
    raise
security = RPC_SECURITY_QOS_V3_W()
security.Sid = sid # not work after removed cast
byehack commented 1 year ago

^^^ This PR still not able to to cover removed cast(sid, c_void_p)

byehack commented 1 year ago

In continue of https://github.com/ynkdir/py-win32more/pull/8 I decided to create a TODO list to improve auto casting:

byehack commented 1 year ago

https://github.com/ynkdir/py-win32more/blob/c723275857ab6d104aa6afed2e731132f9de9a74/Windows/__init__.py#L65-L74

the function name is easycast but it has 2 more different abilities:

  1. it's convert related types in python object to c-type object: c_wchar_p(obj) at line 68.
  2. second is pointer(obj) at line 73.

I think these 2 should break into separate functions. if I had time, I'll send a PR for these.

ynkdir commented 1 year ago

sidSize) # not work after removed c_ulong

For POINTER(c_int) type, it is ambiguous that int should be converted as cast(123, POINTER(c_int)) or pointer(c_int(123)). I guess it is better to keep as is for now.

mominshaikhdevs commented 2 months ago

what's the latest update on this?

ynkdir commented 2 months ago

I am still not sure how it should be.