diff --git a/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/INSTALLER b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/INSTALLER new file mode 100644 index 0000000000000000000000000000000000000000..a1b589e38a32041e49332e5e81c2d363dc418d68 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/LICENSE.txt b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..c37cae49ec77ad6ebb25568c1605f1fee5313cfb --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/METADATA b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/METADATA new file mode 100644 index 0000000000000000000000000000000000000000..7e02aa4f246f105728a440f714cd02e520c5f944 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/METADATA @@ -0,0 +1,99 @@ +Metadata-Version: 2.1 +Name: Werkzeug +Version: 3.0.3 +Summary: The comprehensive WSGI web application library. +Maintainer-email: Pallets +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Classifier: Typing :: Typed +Requires-Dist: MarkupSafe>=2.1.1 +Requires-Dist: watchdog>=2.3 ; extra == "watchdog" +Project-URL: Changes, https://werkzeug.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://werkzeug.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Issue Tracker, https://github.com/pallets/werkzeug/issues/ +Project-URL: Source Code, https://github.com/pallets/werkzeug/ +Provides-Extra: watchdog + +# Werkzeug + +*werkzeug* German noun: "tool". Etymology: *werk* ("work"), *zeug* ("stuff") + +Werkzeug is a comprehensive [WSGI][] web application library. It began as +a simple collection of various utilities for WSGI applications and has +become one of the most advanced WSGI utility libraries. + +It includes: + +- An interactive debugger that allows inspecting stack traces and + source code in the browser with an interactive interpreter for any + frame in the stack. +- A full-featured request object with objects to interact with + headers, query args, form data, files, and cookies. +- A response object that can wrap other WSGI applications and handle + streaming data. +- A routing system for matching URLs to endpoints and generating URLs + for endpoints, with an extensible system for capturing variables + from URLs. +- HTTP utilities to handle entity tags, cache control, dates, user + agents, cookies, files, and more. +- A threaded WSGI server for use while developing applications + locally. +- A test client for simulating HTTP requests during testing without + requiring running a server. + +Werkzeug doesn't enforce any dependencies. It is up to the developer to +choose a template engine, database adapter, and even how to handle +requests. It can be used to build all sorts of end user applications +such as blogs, wikis, or bulletin boards. + +[Flask][] wraps Werkzeug, using it to handle the details of WSGI while +providing more structure and patterns for defining powerful +applications. + +[WSGI]: https://wsgi.readthedocs.io/en/latest/ +[Flask]: https://www.palletsprojects.com/p/flask/ + + +## A Simple Example + +```python +# save this as app.py +from werkzeug.wrappers import Request, Response + +@Request.application +def application(request: Request) -> Response: + return Response("Hello, World!") + +if __name__ == "__main__": + from werkzeug.serving import run_simple + run_simple("127.0.0.1", 5000, application) +``` + +``` +$ python -m app + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) +``` + + +## Donate + +The Pallets organization develops and supports Werkzeug and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +[please donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/RECORD b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/RECORD new file mode 100644 index 0000000000000000000000000000000000000000..30c7a6853f37b7c01714f25ac0789742a22781a8 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/RECORD @@ -0,0 +1,125 @@ +werkzeug-3.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +werkzeug-3.0.3.dist-info/LICENSE.txt,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +werkzeug-3.0.3.dist-info/METADATA,sha256=q6dwCfUWf4-0FFck9mU8Yfcy2DG29TXKG3u0YSsorLU,3682 +werkzeug-3.0.3.dist-info/RECORD,, +werkzeug-3.0.3.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +werkzeug/__init__.py,sha256=HX_PSY5E2vtVlD3R4YblwBRCjg7j3Tlm3LASbYqOSkU,727 +werkzeug/__pycache__/__init__.cpython-39.pyc,, +werkzeug/__pycache__/_internal.cpython-39.pyc,, +werkzeug/__pycache__/_reloader.cpython-39.pyc,, +werkzeug/__pycache__/exceptions.cpython-39.pyc,, +werkzeug/__pycache__/formparser.cpython-39.pyc,, +werkzeug/__pycache__/http.cpython-39.pyc,, +werkzeug/__pycache__/local.cpython-39.pyc,, +werkzeug/__pycache__/security.cpython-39.pyc,, +werkzeug/__pycache__/serving.cpython-39.pyc,, +werkzeug/__pycache__/test.cpython-39.pyc,, +werkzeug/__pycache__/testapp.cpython-39.pyc,, +werkzeug/__pycache__/urls.cpython-39.pyc,, +werkzeug/__pycache__/user_agent.cpython-39.pyc,, +werkzeug/__pycache__/utils.cpython-39.pyc,, +werkzeug/__pycache__/wsgi.cpython-39.pyc,, +werkzeug/_internal.py,sha256=su1olkbHMkzt0VKcEkPLCha8sdVzXNBuqW6YVpp8GHg,5545 +werkzeug/_reloader.py,sha256=YB1h2hopXAsnIVn2LIgt1lkEJLlTLE6qk2zlvGBCd3U,15082 +werkzeug/datastructures/__init__.py,sha256=yzBdOT9DdK3nraNG49pA3bVsvtPPLx2-t2N8ZmuAd9w,1900 +werkzeug/datastructures/__pycache__/__init__.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/accept.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/auth.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/cache_control.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/csp.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/etag.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/file_storage.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/headers.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/mixins.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/range.cpython-39.pyc,, +werkzeug/datastructures/__pycache__/structures.cpython-39.pyc,, +werkzeug/datastructures/accept.py,sha256=CuCvBAxNzbt4QUb17rH986vvOVGURFUjo0DX2PQy_yI,10670 +werkzeug/datastructures/accept.pyi,sha256=6P114gncjZoy-i_n_3OQy2nJVwjEAIe7PcBxKYqCEfc,1917 +werkzeug/datastructures/auth.py,sha256=tZz0wZ1sIpIcAQoEAVhrUvy8M3kqKvIytmvGvwkAdxo,10021 +werkzeug/datastructures/cache_control.py,sha256=RTUipZev50s-1TAn2rYGZrytm_6IOIxQd67fkR5bNF0,6043 +werkzeug/datastructures/cache_control.pyi,sha256=NI5myF8f4yzgiqOHJANgp6XtT8SGCWI_GBp5JuH3NIs,3870 +werkzeug/datastructures/csp.py,sha256=DAOAO266LK0JKbvlG80bbkAgfrNsnU9HBoz-FdIYNdo,3244 +werkzeug/datastructures/csp.pyi,sha256=AmDWiZU4rrJA4SZmyMNI1L5PLdIfJsI5Li9r5lE1q6M,5765 +werkzeug/datastructures/etag.py,sha256=JsyI-yXayF-hQu26MyFzbHFIZsaQ6odj3RZO_jF-_cc,2913 +werkzeug/datastructures/etag.pyi,sha256=N9cuUBrZnxHmsbW0BBmjKW-djNY7WKbI6t_WopB8Zo0,1047 +werkzeug/datastructures/file_storage.py,sha256=ePeMtr65s_1_sunXMv_SBOiFof5CX5BepYv5_W16fZk,6184 +werkzeug/datastructures/file_storage.pyi,sha256=PvUx7s2U3ifIf2YxMUhFtZFdkLFderInKG1U3VWwM9E,1457 +werkzeug/datastructures/headers.py,sha256=97-P-LgzterxEwxLbQsBEGiZpCOAXzZ7fExXXd4uH-o,17286 +werkzeug/datastructures/headers.pyi,sha256=66Gh9DbD8QNpLRBOuer4DMCj12csddHrcgxiJPLE5n8,4237 +werkzeug/datastructures/mixins.py,sha256=-IQSQ70UOMQlqtJEIyyhplOd4obaTOfzGvka-cunCtM,5337 +werkzeug/datastructures/mixins.pyi,sha256=Axe16elbs9zSOK9IuXIGs08ukgqSSPCxXFEjB_ACYSM,4189 +werkzeug/datastructures/range.py,sha256=JXSDPseG7iH5giJp3R1SnQC_SqQp634M8Iv6QTsbTxM,5669 +werkzeug/datastructures/range.pyi,sha256=bsM61iNp86gT2lyN0F_Dqg8xsnfPerdmElipuHppiJQ,1792 +werkzeug/datastructures/structures.py,sha256=8nRqvwHM8moZj_fEaxOqF-N7lguoXgnNJeT2l9LX7xA,31917 +werkzeug/datastructures/structures.pyi,sha256=9NeGm8NDS-x3XmE2ZP9676tKvQfo5G9GGvIlfV4v3aY,8237 +werkzeug/debug/__init__.py,sha256=QyiMgAHIDo7Is564apzqf5YuAw7kccQNQ7-EYPfrv8k,19838 +werkzeug/debug/__pycache__/__init__.cpython-39.pyc,, +werkzeug/debug/__pycache__/console.cpython-39.pyc,, +werkzeug/debug/__pycache__/repr.cpython-39.pyc,, +werkzeug/debug/__pycache__/tbtools.cpython-39.pyc,, +werkzeug/debug/console.py,sha256=t4hZ0Qg1p6Uu2MWimqoMDi7S3WYZvLMjnc8v_dPaxAo,6089 +werkzeug/debug/repr.py,sha256=iHMYny8whiiMDasvUqj0nm4-1VHVvwe697KleiZVK1s,9303 +werkzeug/debug/shared/ICON_LICENSE.md,sha256=DhA6Y1gUl5Jwfg0NFN9Rj4VWITt8tUx0IvdGf0ux9-s,222 +werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 +werkzeug/debug/shared/debugger.js,sha256=nkYRd_yUc23roybb4i4xs3jMQxr0cebQ5HR75_zxpdk,10544 +werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 +werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 +werkzeug/debug/shared/style.css,sha256=-xSxzUEZGw_IqlDR5iZxitNl8LQUjBM-_Y4UAvXVH8g,6078 +werkzeug/debug/tbtools.py,sha256=DN1JDaDV4J_BAGf9ItOr1bs6HJly7iFHiTpWEDAiYCU,13265 +werkzeug/exceptions.py,sha256=SX3MUTqvWVyA9SnfMPxowNPu5beR9DyrmbUJ4AD2XT0,26160 +werkzeug/formparser.py,sha256=BabxEz6Bu1Q1BlKUwkmllb7FN4QBn_5eX2K9tHPr80s,15420 +werkzeug/http.py,sha256=x_x5xj9FcJyS5rurfnF0KOl0csyy4YlV_ur4hb1IZ2w,43546 +werkzeug/local.py,sha256=KUFuAm8BAayQouzVg0MGqW_hiwY8Z_lY5l7d1Scvsx8,22492 +werkzeug/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +werkzeug/middleware/__pycache__/__init__.cpython-39.pyc,, +werkzeug/middleware/__pycache__/dispatcher.cpython-39.pyc,, +werkzeug/middleware/__pycache__/http_proxy.cpython-39.pyc,, +werkzeug/middleware/__pycache__/lint.cpython-39.pyc,, +werkzeug/middleware/__pycache__/profiler.cpython-39.pyc,, +werkzeug/middleware/__pycache__/proxy_fix.cpython-39.pyc,, +werkzeug/middleware/__pycache__/shared_data.cpython-39.pyc,, +werkzeug/middleware/dispatcher.py,sha256=zWN5_lqJr_sc9UDv-PPoSlDHN_zR33z6B74F_4Cxpo8,2602 +werkzeug/middleware/http_proxy.py,sha256=sdk-V6GoZ6aMny-D0QNKNf5MWD2OTO3AGbBg6upp4Hc,7834 +werkzeug/middleware/lint.py,sha256=lwsZhyDNTnsNr4D8dqsgG8Akp7YP9D_X49SCiZucE04,14478 +werkzeug/middleware/profiler.py,sha256=1ZAHlDeYNdhgp8THOXkV5lgmcLl307phAr2Ufy30-lY,5562 +werkzeug/middleware/proxy_fix.py,sha256=n-HW-MRWJquCIhmqiZKoGdbbEeHuWJqPRHhFpuj4pzY,6755 +werkzeug/middleware/shared_data.py,sha256=a6gT17zipdiYhxvGb-cKnayDk8VZi04CJwxf1fr2Is0,9499 +werkzeug/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +werkzeug/routing/__init__.py,sha256=d8TRxsk24IWu2BdoOYUfL--deolHwiGVCBJqLoEe3YM,4820 +werkzeug/routing/__pycache__/__init__.cpython-39.pyc,, +werkzeug/routing/__pycache__/converters.cpython-39.pyc,, +werkzeug/routing/__pycache__/exceptions.cpython-39.pyc,, +werkzeug/routing/__pycache__/map.cpython-39.pyc,, +werkzeug/routing/__pycache__/matcher.cpython-39.pyc,, +werkzeug/routing/__pycache__/rules.cpython-39.pyc,, +werkzeug/routing/converters.py,sha256=iqpee_mAjr1oGbq0etujYF9PiDv5U7DgNkARHXnMId0,7297 +werkzeug/routing/exceptions.py,sha256=wNBiUmUk4OtFOpbdDSr7KKKUjH7yn84JqwBicUup8p8,4846 +werkzeug/routing/map.py,sha256=mEXlHOyinkg1Jtx5L0UDYsvoX4eVLiEuEVQzD5LVAz8,36515 +werkzeug/routing/matcher.py,sha256=nfBbl37eGAkZ1dQlumshFcPuyfggmFjPuSSQOE6GuYs,7849 +werkzeug/routing/rules.py,sha256=rc7FcnN_nQ_k8fzgLYjnoU59WNgShhrqgeB2h7dhFIA,32133 +werkzeug/sansio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +werkzeug/sansio/__pycache__/__init__.cpython-39.pyc,, +werkzeug/sansio/__pycache__/http.cpython-39.pyc,, +werkzeug/sansio/__pycache__/multipart.cpython-39.pyc,, +werkzeug/sansio/__pycache__/request.cpython-39.pyc,, +werkzeug/sansio/__pycache__/response.cpython-39.pyc,, +werkzeug/sansio/__pycache__/utils.cpython-39.pyc,, +werkzeug/sansio/http.py,sha256=_5fVKoogLUyNH5O2BnKty6dFB1p4REBZieJ4vYoOUOA,5370 +werkzeug/sansio/multipart.py,sha256=u_XLs68tvP2AO704Yq5zZg7ZN0A33SQaZfQE40gsduo,11490 +werkzeug/sansio/request.py,sha256=MI59ROX1P_Y6F4FkCLjaV9hwPEXE7aTTqaVphiTw4UA,19983 +werkzeug/sansio/response.py,sha256=uhKYuDy5-Q5v0Mk5VIxiF-Xob9vfGdDzWiJG7J7MYYc,27585 +werkzeug/sansio/utils.py,sha256=Y7zkEmIvBLtVvgwSdtBhFpGqCclBtYx7GUhckiRSyhI,4957 +werkzeug/security.py,sha256=SrUfgJhGzW_Ex7qjcBINRGcfWdikaiponA5bsps4kLA,5376 +werkzeug/serving.py,sha256=l8LBIbbvDYPsvKNEB1KsB-1cW7KB0Yhc3YvBDlmXTyM,39531 +werkzeug/test.py,sha256=kMEWtC_bZ5LqvBya-Pvtq1Jvtb4RR_t7pBp27_4JpJo,52782 +werkzeug/testapp.py,sha256=5_IS5Dh_WfWfNcTLmbydj01lomgcKA_4l9PPCNZnmdI,6332 +werkzeug/urls.py,sha256=XyNKwHvK5IC37-wuIDMYWkiCJ3yLTLGv7wn2GF3ndqI,6430 +werkzeug/user_agent.py,sha256=lSlLYKCcbzCUSkbdAoO8zPk2UR-8Mdn6iu_iA2kYPBA,1416 +werkzeug/utils.py,sha256=6iV_-JdFaLXG6bCR3FMSMyUY0HCnsdzlKirANavAXkk,24699 +werkzeug/wrappers/__init__.py,sha256=b78jCM8x96kJUGLZ5FYFR3zlK-3pnFAmP9RJIGU0ses,138 +werkzeug/wrappers/__pycache__/__init__.cpython-39.pyc,, +werkzeug/wrappers/__pycache__/request.cpython-39.pyc,, +werkzeug/wrappers/__pycache__/response.cpython-39.pyc,, +werkzeug/wrappers/request.py,sha256=YygiRF1cu5fypJaGsib_ntGNIFReCnW1ONoDurKXBek,24661 +werkzeug/wrappers/response.py,sha256=u6zg7VpNYrCeEjpIgf8VqgfaSi9yR_9wi9ly2uudglg,32459 +werkzeug/wsgi.py,sha256=P7jB0VpG6X6miies4uk7Zgm7NVm4Yz8Ra6Inr5q_FMs,20894 diff --git a/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/WHEEL b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/WHEEL new file mode 100644 index 0000000000000000000000000000000000000000..3b5e64b5e6c4a210201d1676a891fd57b15cda99 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug-3.0.3.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/MLPY/Lib/site-packages/werkzeug/__init__.py b/MLPY/Lib/site-packages/werkzeug/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..57cb7539a3b099ade25272c9272629c6b2da4a53 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/__init__.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +import typing as t + +from .serving import run_simple as run_simple +from .test import Client as Client +from .wrappers import Request as Request +from .wrappers import Response as Response + + +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " Werkzeug 3.1. Use feature detection or" + " 'importlib.metadata.version(\"werkzeug\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("werkzeug") + + raise AttributeError(name) diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/__init__.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0129e59b0d8c8fcad62e935b906d524d08a882a Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/__init__.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/_internal.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/_internal.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1fab7127767d83db4ebcfc94a09058806cbc8a0d Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/_internal.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/_reloader.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/_reloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09957b37183bb199e1f4de5b6d02152529a1ad79 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/_reloader.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/exceptions.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/exceptions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60d68ad05256239cb4d20b4bfd86eecfc0b44a33 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/exceptions.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/formparser.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/formparser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7a9da2b0b6091506affe5e799c519ab44687616 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/formparser.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/http.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/http.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae48eebb8d5e752d35d56e1b1f987f5ce7c5217a Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/http.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/local.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/local.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..864f696f818f83a68cf944cff6493b6025bdc808 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/local.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/security.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/security.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..744267de1d4fe7c753930ea0dc4bd986aee489c3 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/security.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/serving.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/serving.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3444aca54fd39a1f6ea13eb1dad6e706174169e0 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/serving.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/test.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..41c41f5027eeb2542467663d79a9fc18ac5a438d Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/test.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/testapp.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/testapp.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a8e37319a3eaba6b2de2b2394121d115141d9cf Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/testapp.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/urls.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/urls.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26dd096e2e558d2cbb9a620ceb32e37f1311fcc7 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/urls.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/user_agent.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/user_agent.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d413a202c19630f5ca1695f074c010def859b164 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/user_agent.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/utils.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa3e1a42d8b3e34a9415cd3bc1d1ff648446df19 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/utils.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/__pycache__/wsgi.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/__pycache__/wsgi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42ac074f4a1d81b79cfe5ecb1a3bd6da56f21ae0 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/__pycache__/wsgi.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/_internal.py b/MLPY/Lib/site-packages/werkzeug/_internal.py new file mode 100644 index 0000000000000000000000000000000000000000..7dd2fbccda1012cd5b84a41f4438f7ac5684d151 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/_internal.py @@ -0,0 +1,211 @@ +from __future__ import annotations + +import logging +import re +import sys +import typing as t +from datetime import datetime +from datetime import timezone + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + + from .wrappers.request import Request + +_logger: logging.Logger | None = None + + +class _Missing: + def __repr__(self) -> str: + return "no value" + + def __reduce__(self) -> str: + return "_missing" + + +_missing = _Missing() + + +def _wsgi_decoding_dance(s: str) -> str: + return s.encode("latin1").decode(errors="replace") + + +def _wsgi_encoding_dance(s: str) -> str: + return s.encode().decode("latin1") + + +def _get_environ(obj: WSGIEnvironment | Request) -> WSGIEnvironment: + env = getattr(obj, "environ", obj) + assert isinstance( + env, dict + ), f"{type(obj).__name__!r} is not a WSGI environment (has to be a dict)" + return env + + +def _has_level_handler(logger: logging.Logger) -> bool: + """Check if there is a handler in the logging chain that will handle + the given logger's effective level. + """ + level = logger.getEffectiveLevel() + current = logger + + while current: + if any(handler.level <= level for handler in current.handlers): + return True + + if not current.propagate: + break + + current = current.parent # type: ignore + + return False + + +class _ColorStreamHandler(logging.StreamHandler): # type: ignore[type-arg] + """On Windows, wrap stream with Colorama for ANSI style support.""" + + def __init__(self) -> None: + try: + import colorama + except ImportError: + stream = None + else: + stream = colorama.AnsiToWin32(sys.stderr) + + super().__init__(stream) + + +def _log(type: str, message: str, *args: t.Any, **kwargs: t.Any) -> None: + """Log a message to the 'werkzeug' logger. + + The logger is created the first time it is needed. If there is no + level set, it is set to :data:`logging.INFO`. If there is no handler + for the logger's effective level, a :class:`logging.StreamHandler` + is added. + """ + global _logger + + if _logger is None: + _logger = logging.getLogger("werkzeug") + + if _logger.level == logging.NOTSET: + _logger.setLevel(logging.INFO) + + if not _has_level_handler(_logger): + _logger.addHandler(_ColorStreamHandler()) + + getattr(_logger, type)(message.rstrip(), *args, **kwargs) + + +@t.overload +def _dt_as_utc(dt: None) -> None: ... + + +@t.overload +def _dt_as_utc(dt: datetime) -> datetime: ... + + +def _dt_as_utc(dt: datetime | None) -> datetime | None: + if dt is None: + return dt + + if dt.tzinfo is None: + return dt.replace(tzinfo=timezone.utc) + elif dt.tzinfo != timezone.utc: + return dt.astimezone(timezone.utc) + + return dt + + +_TAccessorValue = t.TypeVar("_TAccessorValue") + + +class _DictAccessorProperty(t.Generic[_TAccessorValue]): + """Baseclass for `environ_property` and `header_property`.""" + + read_only = False + + def __init__( + self, + name: str, + default: _TAccessorValue | None = None, + load_func: t.Callable[[str], _TAccessorValue] | None = None, + dump_func: t.Callable[[_TAccessorValue], str] | None = None, + read_only: bool | None = None, + doc: str | None = None, + ) -> None: + self.name = name + self.default = default + self.load_func = load_func + self.dump_func = dump_func + if read_only is not None: + self.read_only = read_only + self.__doc__ = doc + + def lookup(self, instance: t.Any) -> t.MutableMapping[str, t.Any]: + raise NotImplementedError + + @t.overload + def __get__( + self, instance: None, owner: type + ) -> _DictAccessorProperty[_TAccessorValue]: ... + + @t.overload + def __get__(self, instance: t.Any, owner: type) -> _TAccessorValue: ... + + def __get__( + self, instance: t.Any | None, owner: type + ) -> _TAccessorValue | _DictAccessorProperty[_TAccessorValue]: + if instance is None: + return self + + storage = self.lookup(instance) + + if self.name not in storage: + return self.default # type: ignore + + value = storage[self.name] + + if self.load_func is not None: + try: + return self.load_func(value) + except (ValueError, TypeError): + return self.default # type: ignore + + return value # type: ignore + + def __set__(self, instance: t.Any, value: _TAccessorValue) -> None: + if self.read_only: + raise AttributeError("read only property") + + if self.dump_func is not None: + self.lookup(instance)[self.name] = self.dump_func(value) + else: + self.lookup(instance)[self.name] = value + + def __delete__(self, instance: t.Any) -> None: + if self.read_only: + raise AttributeError("read only property") + + self.lookup(instance).pop(self.name, None) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.name}>" + + +_plain_int_re = re.compile(r"-?\d+", re.ASCII) + + +def _plain_int(value: str) -> int: + """Parse an int only if it is only ASCII digits and ``-``. + + This disallows ``+``, ``_``, and non-ASCII digits, which are accepted by ``int`` but + are not allowed in HTTP header values. + + Any leading or trailing whitespace is stripped + """ + value = value.strip() + if _plain_int_re.fullmatch(value) is None: + raise ValueError + + return int(value) diff --git a/MLPY/Lib/site-packages/werkzeug/_reloader.py b/MLPY/Lib/site-packages/werkzeug/_reloader.py new file mode 100644 index 0000000000000000000000000000000000000000..d7e91a61c8a6f3a9931d281cba51862fda8f2ea4 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/_reloader.py @@ -0,0 +1,460 @@ +from __future__ import annotations + +import fnmatch +import os +import subprocess +import sys +import threading +import time +import typing as t +from itertools import chain +from pathlib import PurePath + +from ._internal import _log + +# The various system prefixes where imports are found. Base values are +# different when running in a virtualenv. All reloaders will ignore the +# base paths (usually the system installation). The stat reloader won't +# scan the virtualenv paths, it will only include modules that are +# already imported. +_ignore_always = tuple({sys.base_prefix, sys.base_exec_prefix}) +prefix = {*_ignore_always, sys.prefix, sys.exec_prefix} + +if hasattr(sys, "real_prefix"): + # virtualenv < 20 + prefix.add(sys.real_prefix) + +_stat_ignore_scan = tuple(prefix) +del prefix +_ignore_common_dirs = { + "__pycache__", + ".git", + ".hg", + ".tox", + ".nox", + ".pytest_cache", + ".mypy_cache", +} + + +def _iter_module_paths() -> t.Iterator[str]: + """Find the filesystem paths associated with imported modules.""" + # List is in case the value is modified by the app while updating. + for module in list(sys.modules.values()): + name = getattr(module, "__file__", None) + + if name is None or name.startswith(_ignore_always): + continue + + while not os.path.isfile(name): + # Zip file, find the base file without the module path. + old = name + name = os.path.dirname(name) + + if name == old: # skip if it was all directories somehow + break + else: + yield name + + +def _remove_by_pattern(paths: set[str], exclude_patterns: set[str]) -> None: + for pattern in exclude_patterns: + paths.difference_update(fnmatch.filter(paths, pattern)) + + +def _find_stat_paths( + extra_files: set[str], exclude_patterns: set[str] +) -> t.Iterable[str]: + """Find paths for the stat reloader to watch. Returns imported + module files, Python files under non-system paths. Extra files and + Python files under extra directories can also be scanned. + + System paths have to be excluded for efficiency. Non-system paths, + such as a project root or ``sys.path.insert``, should be the paths + of interest to the user anyway. + """ + paths = set() + + for path in chain(list(sys.path), extra_files): + path = os.path.abspath(path) + + if os.path.isfile(path): + # zip file on sys.path, or extra file + paths.add(path) + continue + + parent_has_py = {os.path.dirname(path): True} + + for root, dirs, files in os.walk(path): + # Optimizations: ignore system prefixes, __pycache__ will + # have a py or pyc module at the import path, ignore some + # common known dirs such as version control and tool caches. + if ( + root.startswith(_stat_ignore_scan) + or os.path.basename(root) in _ignore_common_dirs + ): + dirs.clear() + continue + + has_py = False + + for name in files: + if name.endswith((".py", ".pyc")): + has_py = True + paths.add(os.path.join(root, name)) + + # Optimization: stop scanning a directory if neither it nor + # its parent contained Python files. + if not (has_py or parent_has_py[os.path.dirname(root)]): + dirs.clear() + continue + + parent_has_py[root] = has_py + + paths.update(_iter_module_paths()) + _remove_by_pattern(paths, exclude_patterns) + return paths + + +def _find_watchdog_paths( + extra_files: set[str], exclude_patterns: set[str] +) -> t.Iterable[str]: + """Find paths for the stat reloader to watch. Looks at the same + sources as the stat reloader, but watches everything under + directories instead of individual files. + """ + dirs = set() + + for name in chain(list(sys.path), extra_files): + name = os.path.abspath(name) + + if os.path.isfile(name): + name = os.path.dirname(name) + + dirs.add(name) + + for name in _iter_module_paths(): + dirs.add(os.path.dirname(name)) + + _remove_by_pattern(dirs, exclude_patterns) + return _find_common_roots(dirs) + + +def _find_common_roots(paths: t.Iterable[str]) -> t.Iterable[str]: + root: dict[str, dict[str, t.Any]] = {} + + for chunks in sorted((PurePath(x).parts for x in paths), key=len, reverse=True): + node = root + + for chunk in chunks: + node = node.setdefault(chunk, {}) + + node.clear() + + rv = set() + + def _walk(node: t.Mapping[str, dict[str, t.Any]], path: tuple[str, ...]) -> None: + for prefix, child in node.items(): + _walk(child, path + (prefix,)) + + # If there are no more nodes, and a path has been accumulated, add it. + # Path may be empty if the "" entry is in sys.path. + if not node and path: + rv.add(os.path.join(*path)) + + _walk(root, ()) + return rv + + +def _get_args_for_reloading() -> list[str]: + """Determine how the script was executed, and return the args needed + to execute it again in a new process. + """ + if sys.version_info >= (3, 10): + # sys.orig_argv, added in Python 3.10, contains the exact args used to invoke + # Python. Still replace argv[0] with sys.executable for accuracy. + return [sys.executable, *sys.orig_argv[1:]] + + rv = [sys.executable] + py_script = sys.argv[0] + args = sys.argv[1:] + # Need to look at main module to determine how it was executed. + __main__ = sys.modules["__main__"] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + if getattr(__main__, "__package__", None) is None or ( + os.name == "nt" + and __main__.__package__ == "" + and not os.path.exists(py_script) + and os.path.exists(f"{py_script}.exe") + ): + # Executed a file, like "python app.py". + py_script = os.path.abspath(py_script) + + if os.name == "nt": + # Windows entry points have ".exe" extension and should be + # called directly. + if not os.path.exists(py_script) and os.path.exists(f"{py_script}.exe"): + py_script += ".exe" + + if ( + os.path.splitext(sys.executable)[1] == ".exe" + and os.path.splitext(py_script)[1] == ".exe" + ): + rv.pop(0) + + rv.append(py_script) + else: + # Executed a module, like "python -m werkzeug.serving". + if os.path.isfile(py_script): + # Rewritten by Python from "-m script" to "/path/to/script.py". + py_module = t.cast(str, __main__.__package__) + name = os.path.splitext(os.path.basename(py_script))[0] + + if name != "__main__": + py_module += f".{name}" + else: + # Incorrectly rewritten by pydevd debugger from "-m script" to "script". + py_module = py_script + + rv.extend(("-m", py_module.lstrip("."))) + + rv.extend(args) + return rv + + +class ReloaderLoop: + name = "" + + def __init__( + self, + extra_files: t.Iterable[str] | None = None, + exclude_patterns: t.Iterable[str] | None = None, + interval: int | float = 1, + ) -> None: + self.extra_files: set[str] = {os.path.abspath(x) for x in extra_files or ()} + self.exclude_patterns: set[str] = set(exclude_patterns or ()) + self.interval = interval + + def __enter__(self) -> ReloaderLoop: + """Do any setup, then run one step of the watch to populate the + initial filesystem state. + """ + self.run_step() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): # type: ignore + """Clean up any resources associated with the reloader.""" + pass + + def run(self) -> None: + """Continually run the watch step, sleeping for the configured + interval after each step. + """ + while True: + self.run_step() + time.sleep(self.interval) + + def run_step(self) -> None: + """Run one step for watching the filesystem. Called once to set + up initial state, then repeatedly to update it. + """ + pass + + def restart_with_reloader(self) -> int: + """Spawn a new Python interpreter with the same arguments as the + current one, but running the reloader thread. + """ + while True: + _log("info", f" * Restarting with {self.name}") + args = _get_args_for_reloading() + new_environ = os.environ.copy() + new_environ["WERKZEUG_RUN_MAIN"] = "true" + exit_code = subprocess.call(args, env=new_environ, close_fds=False) + + if exit_code != 3: + return exit_code + + def trigger_reload(self, filename: str) -> None: + self.log_reload(filename) + sys.exit(3) + + def log_reload(self, filename: str) -> None: + filename = os.path.abspath(filename) + _log("info", f" * Detected change in {filename!r}, reloading") + + +class StatReloaderLoop(ReloaderLoop): + name = "stat" + + def __enter__(self) -> ReloaderLoop: + self.mtimes: dict[str, float] = {} + return super().__enter__() + + def run_step(self) -> None: + for name in _find_stat_paths(self.extra_files, self.exclude_patterns): + try: + mtime = os.stat(name).st_mtime + except OSError: + continue + + old_time = self.mtimes.get(name) + + if old_time is None: + self.mtimes[name] = mtime + continue + + if mtime > old_time: + self.trigger_reload(name) + + +class WatchdogReloaderLoop(ReloaderLoop): + def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: + from watchdog.events import EVENT_TYPE_OPENED + from watchdog.events import FileModifiedEvent + from watchdog.events import PatternMatchingEventHandler + from watchdog.observers import Observer + + super().__init__(*args, **kwargs) + trigger_reload = self.trigger_reload + + class EventHandler(PatternMatchingEventHandler): + def on_any_event(self, event: FileModifiedEvent): # type: ignore + if event.event_type == EVENT_TYPE_OPENED: + return + + trigger_reload(event.src_path) + + reloader_name = Observer.__name__.lower() # type: ignore[attr-defined] + + if reloader_name.endswith("observer"): + reloader_name = reloader_name[:-8] + + self.name = f"watchdog ({reloader_name})" + self.observer = Observer() + # Extra patterns can be non-Python files, match them in addition + # to all Python files in default and extra directories. Ignore + # __pycache__ since a change there will always have a change to + # the source file (or initial pyc file) as well. Ignore Git and + # Mercurial internal changes. + extra_patterns = [p for p in self.extra_files if not os.path.isdir(p)] + self.event_handler = EventHandler( # type: ignore[no-untyped-call] + patterns=["*.py", "*.pyc", "*.zip", *extra_patterns], + ignore_patterns=[ + *[f"*/{d}/*" for d in _ignore_common_dirs], + *self.exclude_patterns, + ], + ) + self.should_reload = False + + def trigger_reload(self, filename: str) -> None: + # This is called inside an event handler, which means throwing + # SystemExit has no effect. + # https://github.com/gorakhargosh/watchdog/issues/294 + self.should_reload = True + self.log_reload(filename) + + def __enter__(self) -> ReloaderLoop: + self.watches: dict[str, t.Any] = {} + self.observer.start() # type: ignore[no-untyped-call] + return super().__enter__() + + def __exit__(self, exc_type, exc_val, exc_tb): # type: ignore + self.observer.stop() # type: ignore[no-untyped-call] + self.observer.join() + + def run(self) -> None: + while not self.should_reload: + self.run_step() + time.sleep(self.interval) + + sys.exit(3) + + def run_step(self) -> None: + to_delete = set(self.watches) + + for path in _find_watchdog_paths(self.extra_files, self.exclude_patterns): + if path not in self.watches: + try: + self.watches[path] = self.observer.schedule( # type: ignore[no-untyped-call] + self.event_handler, path, recursive=True + ) + except OSError: + # Clear this path from list of watches We don't want + # the same error message showing again in the next + # iteration. + self.watches[path] = None + + to_delete.discard(path) + + for path in to_delete: + watch = self.watches.pop(path, None) + + if watch is not None: + self.observer.unschedule(watch) # type: ignore[no-untyped-call] + + +reloader_loops: dict[str, type[ReloaderLoop]] = { + "stat": StatReloaderLoop, + "watchdog": WatchdogReloaderLoop, +} + +try: + __import__("watchdog.observers") +except ImportError: + reloader_loops["auto"] = reloader_loops["stat"] +else: + reloader_loops["auto"] = reloader_loops["watchdog"] + + +def ensure_echo_on() -> None: + """Ensure that echo mode is enabled. Some tools such as PDB disable + it which causes usability issues after a reload.""" + # tcgetattr will fail if stdin isn't a tty + if sys.stdin is None or not sys.stdin.isatty(): + return + + try: + import termios + except ImportError: + return + + attributes = termios.tcgetattr(sys.stdin) + + if not attributes[3] & termios.ECHO: + attributes[3] |= termios.ECHO + termios.tcsetattr(sys.stdin, termios.TCSANOW, attributes) + + +def run_with_reloader( + main_func: t.Callable[[], None], + extra_files: t.Iterable[str] | None = None, + exclude_patterns: t.Iterable[str] | None = None, + interval: int | float = 1, + reloader_type: str = "auto", +) -> None: + """Run the given function in an independent Python interpreter.""" + import signal + + signal.signal(signal.SIGTERM, lambda *args: sys.exit(0)) + reloader = reloader_loops[reloader_type]( + extra_files=extra_files, exclude_patterns=exclude_patterns, interval=interval + ) + + try: + if os.environ.get("WERKZEUG_RUN_MAIN") == "true": + ensure_echo_on() + t = threading.Thread(target=main_func, args=()) + t.daemon = True + + # Enter the reloader to set up initial state, then start + # the app thread and reloader update loop. + with reloader: + t.start() + reloader.run() + else: + sys.exit(reloader.restart_with_reloader()) + except KeyboardInterrupt: + pass diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__init__.py b/MLPY/Lib/site-packages/werkzeug/datastructures/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..846ffce678461d6f87bf1a01b3312f2ed895e440 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/__init__.py @@ -0,0 +1,34 @@ +from .accept import Accept as Accept +from .accept import CharsetAccept as CharsetAccept +from .accept import LanguageAccept as LanguageAccept +from .accept import MIMEAccept as MIMEAccept +from .auth import Authorization as Authorization +from .auth import WWWAuthenticate as WWWAuthenticate +from .cache_control import RequestCacheControl as RequestCacheControl +from .cache_control import ResponseCacheControl as ResponseCacheControl +from .csp import ContentSecurityPolicy as ContentSecurityPolicy +from .etag import ETags as ETags +from .file_storage import FileMultiDict as FileMultiDict +from .file_storage import FileStorage as FileStorage +from .headers import EnvironHeaders as EnvironHeaders +from .headers import Headers as Headers +from .mixins import ImmutableDictMixin as ImmutableDictMixin +from .mixins import ImmutableHeadersMixin as ImmutableHeadersMixin +from .mixins import ImmutableListMixin as ImmutableListMixin +from .mixins import ImmutableMultiDictMixin as ImmutableMultiDictMixin +from .mixins import UpdateDictMixin as UpdateDictMixin +from .range import ContentRange as ContentRange +from .range import IfRange as IfRange +from .range import Range as Range +from .structures import CallbackDict as CallbackDict +from .structures import CombinedMultiDict as CombinedMultiDict +from .structures import HeaderSet as HeaderSet +from .structures import ImmutableDict as ImmutableDict +from .structures import ImmutableList as ImmutableList +from .structures import ImmutableMultiDict as ImmutableMultiDict +from .structures import ImmutableOrderedMultiDict as ImmutableOrderedMultiDict +from .structures import ImmutableTypeConversionDict as ImmutableTypeConversionDict +from .structures import iter_multi_items as iter_multi_items +from .structures import MultiDict as MultiDict +from .structures import OrderedMultiDict as OrderedMultiDict +from .structures import TypeConversionDict as TypeConversionDict diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7a567cf18af89bd2340794af1e528b55bc6aabb Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8223bf5415406c8e7c3c71a91a2d81500587f8e Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34b5cfe4e1fa6371596d279a8d0174c34a2c6af5 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b546573d9f1cedb7c1b783f53ddeb2d6585c6558 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..352e9ebd043cbcb6a3aec54773a69b83c1834264 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47f7426dd2bebac4c19cd29562998450f288bcf6 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75c0d6d9e829981788a85bf8eb6876789887b57b Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e42d0d668be7ea678fe801df31c2f501e5e29a1e Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f0490ccf53cbeb623e2ca106b4a1196e5382ab2 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/range.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/range.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d582fdf34546446c839f6f4b380db5b9e35636b Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/range.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9df162db9bf4474615f1d9192b9945e6ca7a45f0 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/accept.py b/MLPY/Lib/site-packages/werkzeug/datastructures/accept.py new file mode 100644 index 0000000000000000000000000000000000000000..d80f0bbb850e9b0f967fe7a1dc2b4975527bd350 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/accept.py @@ -0,0 +1,326 @@ +from __future__ import annotations + +import codecs +import re + +from .structures import ImmutableList + + +class Accept(ImmutableList): + """An :class:`Accept` object is just a list subclass for lists of + ``(value, quality)`` tuples. It is automatically sorted by specificity + and quality. + + All :class:`Accept` objects work similar to a list but provide extra + functionality for working with the data. Containment checks are + normalized to the rules of that header: + + >>> a = CharsetAccept([('ISO-8859-1', 1), ('utf-8', 0.7)]) + >>> a.best + 'ISO-8859-1' + >>> 'iso-8859-1' in a + True + >>> 'UTF8' in a + True + >>> 'utf7' in a + False + + To get the quality for an item you can use normal item lookup: + + >>> print a['utf-8'] + 0.7 + >>> a['utf7'] + 0 + + .. versionchanged:: 0.5 + :class:`Accept` objects are forced immutable now. + + .. versionchanged:: 1.0.0 + :class:`Accept` internal values are no longer ordered + alphabetically for equal quality tags. Instead the initial + order is preserved. + + """ + + def __init__(self, values=()): + if values is None: + list.__init__(self) + self.provided = False + elif isinstance(values, Accept): + self.provided = values.provided + list.__init__(self, values) + else: + self.provided = True + values = sorted( + values, key=lambda x: (self._specificity(x[0]), x[1]), reverse=True + ) + list.__init__(self, values) + + def _specificity(self, value): + """Returns a tuple describing the value's specificity.""" + return (value != "*",) + + def _value_matches(self, value, item): + """Check if a value matches a given accept item.""" + return item == "*" or item.lower() == value.lower() + + def __getitem__(self, key): + """Besides index lookup (getting item n) you can also pass it a string + to get the quality for the item. If the item is not in the list, the + returned quality is ``0``. + """ + if isinstance(key, str): + return self.quality(key) + return list.__getitem__(self, key) + + def quality(self, key): + """Returns the quality of the key. + + .. versionadded:: 0.6 + In previous versions you had to use the item-lookup syntax + (eg: ``obj[key]`` instead of ``obj.quality(key)``) + """ + for item, quality in self: + if self._value_matches(key, item): + return quality + return 0 + + def __contains__(self, value): + for item, _quality in self: + if self._value_matches(value, item): + return True + return False + + def __repr__(self): + pairs_str = ", ".join(f"({x!r}, {y})" for x, y in self) + return f"{type(self).__name__}([{pairs_str}])" + + def index(self, key): + """Get the position of an entry or raise :exc:`ValueError`. + + :param key: The key to be looked up. + + .. versionchanged:: 0.5 + This used to raise :exc:`IndexError`, which was inconsistent + with the list API. + """ + if isinstance(key, str): + for idx, (item, _quality) in enumerate(self): + if self._value_matches(key, item): + return idx + raise ValueError(key) + return list.index(self, key) + + def find(self, key): + """Get the position of an entry or return -1. + + :param key: The key to be looked up. + """ + try: + return self.index(key) + except ValueError: + return -1 + + def values(self): + """Iterate over all values.""" + for item in self: + yield item[0] + + def to_header(self): + """Convert the header set into an HTTP header string.""" + result = [] + for value, quality in self: + if quality != 1: + value = f"{value};q={quality}" + result.append(value) + return ",".join(result) + + def __str__(self): + return self.to_header() + + def _best_single_match(self, match): + for client_item, quality in self: + if self._value_matches(match, client_item): + # self is sorted by specificity descending, we can exit + return client_item, quality + return None + + def best_match(self, matches, default=None): + """Returns the best match from a list of possible matches based + on the specificity and quality of the client. If two items have the + same quality and specificity, the one is returned that comes first. + + :param matches: a list of matches to check for + :param default: the value that is returned if none match + """ + result = default + best_quality = -1 + best_specificity = (-1,) + for server_item in matches: + match = self._best_single_match(server_item) + if not match: + continue + client_item, quality = match + specificity = self._specificity(client_item) + if quality <= 0 or quality < best_quality: + continue + # better quality or same quality but more specific => better match + if quality > best_quality or specificity > best_specificity: + result = server_item + best_quality = quality + best_specificity = specificity + return result + + @property + def best(self): + """The best match as value.""" + if self: + return self[0][0] + + +_mime_split_re = re.compile(r"/|(?:\s*;\s*)") + + +def _normalize_mime(value): + return _mime_split_re.split(value.lower()) + + +class MIMEAccept(Accept): + """Like :class:`Accept` but with special methods and behavior for + mimetypes. + """ + + def _specificity(self, value): + return tuple(x != "*" for x in _mime_split_re.split(value)) + + def _value_matches(self, value, item): + # item comes from the client, can't match if it's invalid. + if "/" not in item: + return False + + # value comes from the application, tell the developer when it + # doesn't look valid. + if "/" not in value: + raise ValueError(f"invalid mimetype {value!r}") + + # Split the match value into type, subtype, and a sorted list of parameters. + normalized_value = _normalize_mime(value) + value_type, value_subtype = normalized_value[:2] + value_params = sorted(normalized_value[2:]) + + # "*/*" is the only valid value that can start with "*". + if value_type == "*" and value_subtype != "*": + raise ValueError(f"invalid mimetype {value!r}") + + # Split the accept item into type, subtype, and parameters. + normalized_item = _normalize_mime(item) + item_type, item_subtype = normalized_item[:2] + item_params = sorted(normalized_item[2:]) + + # "*/not-*" from the client is invalid, can't match. + if item_type == "*" and item_subtype != "*": + return False + + return ( + (item_type == "*" and item_subtype == "*") + or (value_type == "*" and value_subtype == "*") + ) or ( + item_type == value_type + and ( + item_subtype == "*" + or value_subtype == "*" + or (item_subtype == value_subtype and item_params == value_params) + ) + ) + + @property + def accept_html(self): + """True if this object accepts HTML.""" + return ( + "text/html" in self or "application/xhtml+xml" in self or self.accept_xhtml + ) + + @property + def accept_xhtml(self): + """True if this object accepts XHTML.""" + return "application/xhtml+xml" in self or "application/xml" in self + + @property + def accept_json(self): + """True if this object accepts JSON.""" + return "application/json" in self + + +_locale_delim_re = re.compile(r"[_-]") + + +def _normalize_lang(value): + """Process a language tag for matching.""" + return _locale_delim_re.split(value.lower()) + + +class LanguageAccept(Accept): + """Like :class:`Accept` but with normalization for language tags.""" + + def _value_matches(self, value, item): + return item == "*" or _normalize_lang(value) == _normalize_lang(item) + + def best_match(self, matches, default=None): + """Given a list of supported values, finds the best match from + the list of accepted values. + + Language tags are normalized for the purpose of matching, but + are returned unchanged. + + If no exact match is found, this will fall back to matching + the first subtag (primary language only), first with the + accepted values then with the match values. This partial is not + applied to any other language subtags. + + The default is returned if no exact or fallback match is found. + + :param matches: A list of supported languages to find a match. + :param default: The value that is returned if none match. + """ + # Look for an exact match first. If a client accepts "en-US", + # "en-US" is a valid match at this point. + result = super().best_match(matches) + + if result is not None: + return result + + # Fall back to accepting primary tags. If a client accepts + # "en-US", "en" is a valid match at this point. Need to use + # re.split to account for 2 or 3 letter codes. + fallback = Accept( + [(_locale_delim_re.split(item[0], 1)[0], item[1]) for item in self] + ) + result = fallback.best_match(matches) + + if result is not None: + return result + + # Fall back to matching primary tags. If the client accepts + # "en", "en-US" is a valid match at this point. + fallback_matches = [_locale_delim_re.split(item, 1)[0] for item in matches] + result = super().best_match(fallback_matches) + + # Return a value from the original match list. Find the first + # original value that starts with the matched primary tag. + if result is not None: + return next(item for item in matches if item.startswith(result)) + + return default + + +class CharsetAccept(Accept): + """Like :class:`Accept` but with normalization for charsets.""" + + def _value_matches(self, value, item): + def _normalize(name): + try: + return codecs.lookup(name).name + except LookupError: + return name.lower() + + return item == "*" or _normalize(value) == _normalize(item) diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/accept.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/accept.pyi new file mode 100644 index 0000000000000000000000000000000000000000..4b74dd9505d9045f369a061ece565400887fb296 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/accept.pyi @@ -0,0 +1,54 @@ +from collections.abc import Iterable +from collections.abc import Iterator +from typing import overload + +from .structures import ImmutableList + +class Accept(ImmutableList[tuple[str, int]]): + provided: bool + def __init__( + self, values: Accept | Iterable[tuple[str, float]] | None = None + ) -> None: ... + def _specificity(self, value: str) -> tuple[bool, ...]: ... + def _value_matches(self, value: str, item: str) -> bool: ... + @overload # type: ignore + def __getitem__(self, key: str) -> int: ... + @overload + def __getitem__(self, key: int) -> tuple[str, int]: ... + @overload + def __getitem__(self, key: slice) -> Iterable[tuple[str, int]]: ... + def quality(self, key: str) -> int: ... + def __contains__(self, value: str) -> bool: ... # type: ignore + def index(self, key: str) -> int: ... # type: ignore + def find(self, key: str) -> int: ... + def values(self) -> Iterator[str]: ... + def to_header(self) -> str: ... + def _best_single_match(self, match: str) -> tuple[str, int] | None: ... + @overload + def best_match(self, matches: Iterable[str], default: str) -> str: ... + @overload + def best_match( + self, matches: Iterable[str], default: str | None = None + ) -> str | None: ... + @property + def best(self) -> str: ... + +def _normalize_mime(value: str) -> list[str]: ... + +class MIMEAccept(Accept): + def _specificity(self, value: str) -> tuple[bool, ...]: ... + def _value_matches(self, value: str, item: str) -> bool: ... + @property + def accept_html(self) -> bool: ... + @property + def accept_xhtml(self) -> bool: ... + @property + def accept_json(self) -> bool: ... + +def _normalize_lang(value: str) -> list[str]: ... + +class LanguageAccept(Accept): + def _value_matches(self, value: str, item: str) -> bool: ... + +class CharsetAccept(Accept): + def _value_matches(self, value: str, item: str) -> bool: ... diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/auth.py b/MLPY/Lib/site-packages/werkzeug/datastructures/auth.py new file mode 100644 index 0000000000000000000000000000000000000000..a3ca0de46c53f51f2d4e40b2d7e0f62f4a581b83 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/auth.py @@ -0,0 +1,316 @@ +from __future__ import annotations + +import base64 +import binascii +import typing as t + +from ..http import dump_header +from ..http import parse_dict_header +from ..http import quote_header_value +from .structures import CallbackDict + +if t.TYPE_CHECKING: + import typing_extensions as te + + +class Authorization: + """Represents the parts of an ``Authorization`` request header. + + :attr:`.Request.authorization` returns an instance if the header is set. + + An instance can be used with the test :class:`.Client` request methods' ``auth`` + parameter to send the header in test requests. + + Depending on the auth scheme, either :attr:`parameters` or :attr:`token` will be + set. The ``Basic`` scheme's token is decoded into the ``username`` and ``password`` + parameters. + + For convenience, ``auth["key"]`` and ``auth.key`` both access the key in the + :attr:`parameters` dict, along with ``auth.get("key")`` and ``"key" in auth``. + + .. versionchanged:: 2.3 + The ``token`` parameter and attribute was added to support auth schemes that use + a token instead of parameters, such as ``Bearer``. + + .. versionchanged:: 2.3 + The object is no longer a ``dict``. + + .. versionchanged:: 0.5 + The object is an immutable dict. + """ + + def __init__( + self, + auth_type: str, + data: dict[str, str | None] | None = None, + token: str | None = None, + ) -> None: + self.type = auth_type + """The authorization scheme, like ``basic``, ``digest``, or ``bearer``.""" + + if data is None: + data = {} + + self.parameters = data + """A dict of parameters parsed from the header. Either this or :attr:`token` + will have a value for a given scheme. + """ + + self.token = token + """A token parsed from the header. Either this or :attr:`parameters` will have a + value for a given scheme. + + .. versionadded:: 2.3 + """ + + def __getattr__(self, name: str) -> str | None: + return self.parameters.get(name) + + def __getitem__(self, name: str) -> str | None: + return self.parameters.get(name) + + def get(self, key: str, default: str | None = None) -> str | None: + return self.parameters.get(key, default) + + def __contains__(self, key: str) -> bool: + return key in self.parameters + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Authorization): + return NotImplemented + + return ( + other.type == self.type + and other.token == self.token + and other.parameters == self.parameters + ) + + @classmethod + def from_header(cls, value: str | None) -> te.Self | None: + """Parse an ``Authorization`` header value and return an instance, or ``None`` + if the value is empty. + + :param value: The header value to parse. + + .. versionadded:: 2.3 + """ + if not value: + return None + + scheme, _, rest = value.partition(" ") + scheme = scheme.lower() + rest = rest.strip() + + if scheme == "basic": + try: + username, _, password = base64.b64decode(rest).decode().partition(":") + except (binascii.Error, UnicodeError): + return None + + return cls(scheme, {"username": username, "password": password}) + + if "=" in rest.rstrip("="): + # = that is not trailing, this is parameters. + return cls(scheme, parse_dict_header(rest), None) + + # No = or only trailing =, this is a token. + return cls(scheme, None, rest) + + def to_header(self) -> str: + """Produce an ``Authorization`` header value representing this data. + + .. versionadded:: 2.0 + """ + if self.type == "basic": + value = base64.b64encode( + f"{self.username}:{self.password}".encode() + ).decode("ascii") + return f"Basic {value}" + + if self.token is not None: + return f"{self.type.title()} {self.token}" + + return f"{self.type.title()} {dump_header(self.parameters)}" + + def __str__(self) -> str: + return self.to_header() + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.to_header()}>" + + +class WWWAuthenticate: + """Represents the parts of a ``WWW-Authenticate`` response header. + + Set :attr:`.Response.www_authenticate` to an instance of list of instances to set + values for this header in the response. Modifying this instance will modify the + header value. + + Depending on the auth scheme, either :attr:`parameters` or :attr:`token` should be + set. The ``Basic`` scheme will encode ``username`` and ``password`` parameters to a + token. + + For convenience, ``auth["key"]`` and ``auth.key`` both act on the :attr:`parameters` + dict, and can be used to get, set, or delete parameters. ``auth.get("key")`` and + ``"key" in auth`` are also provided. + + .. versionchanged:: 2.3 + The ``token`` parameter and attribute was added to support auth schemes that use + a token instead of parameters, such as ``Bearer``. + + .. versionchanged:: 2.3 + The object is no longer a ``dict``. + + .. versionchanged:: 2.3 + The ``on_update`` parameter was removed. + """ + + def __init__( + self, + auth_type: str, + values: dict[str, str | None] | None = None, + token: str | None = None, + ): + self._type = auth_type.lower() + self._parameters: dict[str, str | None] = CallbackDict( + values, lambda _: self._trigger_on_update() + ) + self._token = token + self._on_update: t.Callable[[WWWAuthenticate], None] | None = None + + def _trigger_on_update(self) -> None: + if self._on_update is not None: + self._on_update(self) + + @property + def type(self) -> str: + """The authorization scheme, like ``basic``, ``digest``, or ``bearer``.""" + return self._type + + @type.setter + def type(self, value: str) -> None: + self._type = value + self._trigger_on_update() + + @property + def parameters(self) -> dict[str, str | None]: + """A dict of parameters for the header. Only one of this or :attr:`token` should + have a value for a given scheme. + """ + return self._parameters + + @parameters.setter + def parameters(self, value: dict[str, str]) -> None: + self._parameters = CallbackDict(value, lambda _: self._trigger_on_update()) + self._trigger_on_update() + + @property + def token(self) -> str | None: + """A dict of parameters for the header. Only one of this or :attr:`token` should + have a value for a given scheme. + """ + return self._token + + @token.setter + def token(self, value: str | None) -> None: + """A token for the header. Only one of this or :attr:`parameters` should have a + value for a given scheme. + + .. versionadded:: 2.3 + """ + self._token = value + self._trigger_on_update() + + def __getitem__(self, key: str) -> str | None: + return self.parameters.get(key) + + def __setitem__(self, key: str, value: str | None) -> None: + if value is None: + if key in self.parameters: + del self.parameters[key] + else: + self.parameters[key] = value + + self._trigger_on_update() + + def __delitem__(self, key: str) -> None: + if key in self.parameters: + del self.parameters[key] + self._trigger_on_update() + + def __getattr__(self, name: str) -> str | None: + return self[name] + + def __setattr__(self, name: str, value: str | None) -> None: + if name in {"_type", "_parameters", "_token", "_on_update"}: + super().__setattr__(name, value) + else: + self[name] = value + + def __delattr__(self, name: str) -> None: + del self[name] + + def __contains__(self, key: str) -> bool: + return key in self.parameters + + def __eq__(self, other: object) -> bool: + if not isinstance(other, WWWAuthenticate): + return NotImplemented + + return ( + other.type == self.type + and other.token == self.token + and other.parameters == self.parameters + ) + + def get(self, key: str, default: str | None = None) -> str | None: + return self.parameters.get(key, default) + + @classmethod + def from_header(cls, value: str | None) -> te.Self | None: + """Parse a ``WWW-Authenticate`` header value and return an instance, or ``None`` + if the value is empty. + + :param value: The header value to parse. + + .. versionadded:: 2.3 + """ + if not value: + return None + + scheme, _, rest = value.partition(" ") + scheme = scheme.lower() + rest = rest.strip() + + if "=" in rest.rstrip("="): + # = that is not trailing, this is parameters. + return cls(scheme, parse_dict_header(rest), None) + + # No = or only trailing =, this is a token. + return cls(scheme, None, rest) + + def to_header(self) -> str: + """Produce a ``WWW-Authenticate`` header value representing this data.""" + if self.token is not None: + return f"{self.type.title()} {self.token}" + + if self.type == "digest": + items = [] + + for key, value in self.parameters.items(): + if key in {"realm", "domain", "nonce", "opaque", "qop"}: + value = quote_header_value(value, allow_token=False) + else: + value = quote_header_value(value) + + items.append(f"{key}={value}") + + return f"Digest {', '.join(items)}" + + return f"{self.type.title()} {dump_header(self.parameters)}" + + def __str__(self) -> str: + return self.to_header() + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.to_header()}>" diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/cache_control.py b/MLPY/Lib/site-packages/werkzeug/datastructures/cache_control.py new file mode 100644 index 0000000000000000000000000000000000000000..bff4c18bbd5eaaf21c61561e6067ebba8f57b2d5 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/cache_control.py @@ -0,0 +1,175 @@ +from __future__ import annotations + +from .mixins import ImmutableDictMixin +from .mixins import UpdateDictMixin + + +def cache_control_property(key, empty, type): + """Return a new property object for a cache header. Useful if you + want to add support for a cache extension in a subclass. + + .. versionchanged:: 2.0 + Renamed from ``cache_property``. + """ + return property( + lambda x: x._get_cache_value(key, empty, type), + lambda x, v: x._set_cache_value(key, v, type), + lambda x: x._del_cache_value(key), + f"accessor for {key!r}", + ) + + +class _CacheControl(UpdateDictMixin, dict): + """Subclass of a dict that stores values for a Cache-Control header. It + has accessors for all the cache-control directives specified in RFC 2616. + The class does not differentiate between request and response directives. + + Because the cache-control directives in the HTTP header use dashes the + python descriptors use underscores for that. + + To get a header of the :class:`CacheControl` object again you can convert + the object into a string or call the :meth:`to_header` method. If you plan + to subclass it and add your own items have a look at the sourcecode for + that class. + + .. versionchanged:: 2.1.0 + Setting int properties such as ``max_age`` will convert the + value to an int. + + .. versionchanged:: 0.4 + + Setting `no_cache` or `private` to boolean `True` will set the implicit + none-value which is ``*``: + + >>> cc = ResponseCacheControl() + >>> cc.no_cache = True + >>> cc + + >>> cc.no_cache + '*' + >>> cc.no_cache = None + >>> cc + + + In versions before 0.5 the behavior documented here affected the now + no longer existing `CacheControl` class. + """ + + no_cache = cache_control_property("no-cache", "*", None) + no_store = cache_control_property("no-store", None, bool) + max_age = cache_control_property("max-age", -1, int) + no_transform = cache_control_property("no-transform", None, None) + + def __init__(self, values=(), on_update=None): + dict.__init__(self, values or ()) + self.on_update = on_update + self.provided = values is not None + + def _get_cache_value(self, key, empty, type): + """Used internally by the accessor properties.""" + if type is bool: + return key in self + if key in self: + value = self[key] + if value is None: + return empty + elif type is not None: + try: + value = type(value) + except ValueError: + pass + return value + return None + + def _set_cache_value(self, key, value, type): + """Used internally by the accessor properties.""" + if type is bool: + if value: + self[key] = None + else: + self.pop(key, None) + else: + if value is None: + self.pop(key, None) + elif value is True: + self[key] = None + else: + if type is not None: + self[key] = type(value) + else: + self[key] = value + + def _del_cache_value(self, key): + """Used internally by the accessor properties.""" + if key in self: + del self[key] + + def to_header(self): + """Convert the stored values into a cache control header.""" + return http.dump_header(self) + + def __str__(self): + return self.to_header() + + def __repr__(self): + kv_str = " ".join(f"{k}={v!r}" for k, v in sorted(self.items())) + return f"<{type(self).__name__} {kv_str}>" + + cache_property = staticmethod(cache_control_property) + + +class RequestCacheControl(ImmutableDictMixin, _CacheControl): + """A cache control for requests. This is immutable and gives access + to all the request-relevant cache control headers. + + To get a header of the :class:`RequestCacheControl` object again you can + convert the object into a string or call the :meth:`to_header` method. If + you plan to subclass it and add your own items have a look at the sourcecode + for that class. + + .. versionchanged:: 2.1.0 + Setting int properties such as ``max_age`` will convert the + value to an int. + + .. versionadded:: 0.5 + In previous versions a `CacheControl` class existed that was used + both for request and response. + """ + + max_stale = cache_control_property("max-stale", "*", int) + min_fresh = cache_control_property("min-fresh", "*", int) + only_if_cached = cache_control_property("only-if-cached", None, bool) + + +class ResponseCacheControl(_CacheControl): + """A cache control for responses. Unlike :class:`RequestCacheControl` + this is mutable and gives access to response-relevant cache control + headers. + + To get a header of the :class:`ResponseCacheControl` object again you can + convert the object into a string or call the :meth:`to_header` method. If + you plan to subclass it and add your own items have a look at the sourcecode + for that class. + + .. versionchanged:: 2.1.1 + ``s_maxage`` converts the value to an int. + + .. versionchanged:: 2.1.0 + Setting int properties such as ``max_age`` will convert the + value to an int. + + .. versionadded:: 0.5 + In previous versions a `CacheControl` class existed that was used + both for request and response. + """ + + public = cache_control_property("public", None, bool) + private = cache_control_property("private", "*", None) + must_revalidate = cache_control_property("must-revalidate", None, bool) + proxy_revalidate = cache_control_property("proxy-revalidate", None, bool) + s_maxage = cache_control_property("s-maxage", None, int) + immutable = cache_control_property("immutable", None, bool) + + +# circular dependencies +from .. import http diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/cache_control.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/cache_control.pyi new file mode 100644 index 0000000000000000000000000000000000000000..54ec020826d40da8557d309416e90ea950cd41ae --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/cache_control.pyi @@ -0,0 +1,115 @@ +from collections.abc import Callable +from collections.abc import Iterable +from collections.abc import Mapping +from typing import TypeVar + +from .mixins import ImmutableDictMixin +from .mixins import UpdateDictMixin + +T = TypeVar("T") +_CPT = TypeVar("_CPT", str, int, bool) + +def cache_control_property( + key: str, empty: _CPT | None, type: type[_CPT] +) -> property: ... + +class _CacheControl( + UpdateDictMixin[str, str | int | bool | None], dict[str, str | int | bool | None] +): + provided: bool + def __init__( + self, + values: Mapping[str, str | int | bool | None] + | Iterable[tuple[str, str | int | bool | None]] = (), + on_update: Callable[[_CacheControl], None] | None = None, + ) -> None: ... + @property + def no_cache(self) -> bool | None: ... + @no_cache.setter + def no_cache(self, value: bool | None) -> None: ... + @no_cache.deleter + def no_cache(self) -> None: ... + @property + def no_store(self) -> bool | None: ... + @no_store.setter + def no_store(self, value: bool | None) -> None: ... + @no_store.deleter + def no_store(self) -> None: ... + @property + def max_age(self) -> int | None: ... + @max_age.setter + def max_age(self, value: int | None) -> None: ... + @max_age.deleter + def max_age(self) -> None: ... + @property + def no_transform(self) -> bool | None: ... + @no_transform.setter + def no_transform(self, value: bool | None) -> None: ... + @no_transform.deleter + def no_transform(self) -> None: ... + def _get_cache_value(self, key: str, empty: T | None, type: type[T]) -> T: ... + def _set_cache_value(self, key: str, value: T | None, type: type[T]) -> None: ... + def _del_cache_value(self, key: str) -> None: ... + def to_header(self) -> str: ... + @staticmethod + def cache_property(key: str, empty: _CPT | None, type: type[_CPT]) -> property: ... + +class RequestCacheControl( # type: ignore[misc] + ImmutableDictMixin[str, str | int | bool | None], _CacheControl +): + @property + def max_stale(self) -> int | None: ... + @max_stale.setter + def max_stale(self, value: int | None) -> None: ... + @max_stale.deleter + def max_stale(self) -> None: ... + @property + def min_fresh(self) -> int | None: ... + @min_fresh.setter + def min_fresh(self, value: int | None) -> None: ... + @min_fresh.deleter + def min_fresh(self) -> None: ... + @property + def only_if_cached(self) -> bool | None: ... + @only_if_cached.setter + def only_if_cached(self, value: bool | None) -> None: ... + @only_if_cached.deleter + def only_if_cached(self) -> None: ... + +class ResponseCacheControl(_CacheControl): + @property + def public(self) -> bool | None: ... + @public.setter + def public(self, value: bool | None) -> None: ... + @public.deleter + def public(self) -> None: ... + @property + def private(self) -> bool | None: ... + @private.setter + def private(self, value: bool | None) -> None: ... + @private.deleter + def private(self) -> None: ... + @property + def must_revalidate(self) -> bool | None: ... + @must_revalidate.setter + def must_revalidate(self, value: bool | None) -> None: ... + @must_revalidate.deleter + def must_revalidate(self) -> None: ... + @property + def proxy_revalidate(self) -> bool | None: ... + @proxy_revalidate.setter + def proxy_revalidate(self, value: bool | None) -> None: ... + @proxy_revalidate.deleter + def proxy_revalidate(self) -> None: ... + @property + def s_maxage(self) -> int | None: ... + @s_maxage.setter + def s_maxage(self, value: int | None) -> None: ... + @s_maxage.deleter + def s_maxage(self) -> None: ... + @property + def immutable(self) -> bool | None: ... + @immutable.setter + def immutable(self, value: bool | None) -> None: ... + @immutable.deleter + def immutable(self) -> None: ... diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/csp.py b/MLPY/Lib/site-packages/werkzeug/datastructures/csp.py new file mode 100644 index 0000000000000000000000000000000000000000..dde9414951ce7ea6847ddeb6c252fc510dd49240 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/csp.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +from .mixins import UpdateDictMixin + + +def csp_property(key): + """Return a new property object for a content security policy header. + Useful if you want to add support for a csp extension in a + subclass. + """ + return property( + lambda x: x._get_value(key), + lambda x, v: x._set_value(key, v), + lambda x: x._del_value(key), + f"accessor for {key!r}", + ) + + +class ContentSecurityPolicy(UpdateDictMixin, dict): + """Subclass of a dict that stores values for a Content Security Policy + header. It has accessors for all the level 3 policies. + + Because the csp directives in the HTTP header use dashes the + python descriptors use underscores for that. + + To get a header of the :class:`ContentSecuirtyPolicy` object again + you can convert the object into a string or call the + :meth:`to_header` method. If you plan to subclass it and add your + own items have a look at the sourcecode for that class. + + .. versionadded:: 1.0.0 + Support for Content Security Policy headers was added. + + """ + + base_uri = csp_property("base-uri") + child_src = csp_property("child-src") + connect_src = csp_property("connect-src") + default_src = csp_property("default-src") + font_src = csp_property("font-src") + form_action = csp_property("form-action") + frame_ancestors = csp_property("frame-ancestors") + frame_src = csp_property("frame-src") + img_src = csp_property("img-src") + manifest_src = csp_property("manifest-src") + media_src = csp_property("media-src") + navigate_to = csp_property("navigate-to") + object_src = csp_property("object-src") + prefetch_src = csp_property("prefetch-src") + plugin_types = csp_property("plugin-types") + report_to = csp_property("report-to") + report_uri = csp_property("report-uri") + sandbox = csp_property("sandbox") + script_src = csp_property("script-src") + script_src_attr = csp_property("script-src-attr") + script_src_elem = csp_property("script-src-elem") + style_src = csp_property("style-src") + style_src_attr = csp_property("style-src-attr") + style_src_elem = csp_property("style-src-elem") + worker_src = csp_property("worker-src") + + def __init__(self, values=(), on_update=None): + dict.__init__(self, values or ()) + self.on_update = on_update + self.provided = values is not None + + def _get_value(self, key): + """Used internally by the accessor properties.""" + return self.get(key) + + def _set_value(self, key, value): + """Used internally by the accessor properties.""" + if value is None: + self.pop(key, None) + else: + self[key] = value + + def _del_value(self, key): + """Used internally by the accessor properties.""" + if key in self: + del self[key] + + def to_header(self): + """Convert the stored values into a cache control header.""" + from ..http import dump_csp_header + + return dump_csp_header(self) + + def __str__(self): + return self.to_header() + + def __repr__(self): + kv_str = " ".join(f"{k}={v!r}" for k, v in sorted(self.items())) + return f"<{type(self).__name__} {kv_str}>" diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/csp.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/csp.pyi new file mode 100644 index 0000000000000000000000000000000000000000..f9e2ac0f463713aa15abce736ca11df54105c0dc --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/csp.pyi @@ -0,0 +1,169 @@ +from collections.abc import Callable +from collections.abc import Iterable +from collections.abc import Mapping + +from .mixins import UpdateDictMixin + +def csp_property(key: str) -> property: ... + +class ContentSecurityPolicy(UpdateDictMixin[str, str], dict[str, str]): + @property + def base_uri(self) -> str | None: ... + @base_uri.setter + def base_uri(self, value: str | None) -> None: ... + @base_uri.deleter + def base_uri(self) -> None: ... + @property + def child_src(self) -> str | None: ... + @child_src.setter + def child_src(self, value: str | None) -> None: ... + @child_src.deleter + def child_src(self) -> None: ... + @property + def connect_src(self) -> str | None: ... + @connect_src.setter + def connect_src(self, value: str | None) -> None: ... + @connect_src.deleter + def connect_src(self) -> None: ... + @property + def default_src(self) -> str | None: ... + @default_src.setter + def default_src(self, value: str | None) -> None: ... + @default_src.deleter + def default_src(self) -> None: ... + @property + def font_src(self) -> str | None: ... + @font_src.setter + def font_src(self, value: str | None) -> None: ... + @font_src.deleter + def font_src(self) -> None: ... + @property + def form_action(self) -> str | None: ... + @form_action.setter + def form_action(self, value: str | None) -> None: ... + @form_action.deleter + def form_action(self) -> None: ... + @property + def frame_ancestors(self) -> str | None: ... + @frame_ancestors.setter + def frame_ancestors(self, value: str | None) -> None: ... + @frame_ancestors.deleter + def frame_ancestors(self) -> None: ... + @property + def frame_src(self) -> str | None: ... + @frame_src.setter + def frame_src(self, value: str | None) -> None: ... + @frame_src.deleter + def frame_src(self) -> None: ... + @property + def img_src(self) -> str | None: ... + @img_src.setter + def img_src(self, value: str | None) -> None: ... + @img_src.deleter + def img_src(self) -> None: ... + @property + def manifest_src(self) -> str | None: ... + @manifest_src.setter + def manifest_src(self, value: str | None) -> None: ... + @manifest_src.deleter + def manifest_src(self) -> None: ... + @property + def media_src(self) -> str | None: ... + @media_src.setter + def media_src(self, value: str | None) -> None: ... + @media_src.deleter + def media_src(self) -> None: ... + @property + def navigate_to(self) -> str | None: ... + @navigate_to.setter + def navigate_to(self, value: str | None) -> None: ... + @navigate_to.deleter + def navigate_to(self) -> None: ... + @property + def object_src(self) -> str | None: ... + @object_src.setter + def object_src(self, value: str | None) -> None: ... + @object_src.deleter + def object_src(self) -> None: ... + @property + def prefetch_src(self) -> str | None: ... + @prefetch_src.setter + def prefetch_src(self, value: str | None) -> None: ... + @prefetch_src.deleter + def prefetch_src(self) -> None: ... + @property + def plugin_types(self) -> str | None: ... + @plugin_types.setter + def plugin_types(self, value: str | None) -> None: ... + @plugin_types.deleter + def plugin_types(self) -> None: ... + @property + def report_to(self) -> str | None: ... + @report_to.setter + def report_to(self, value: str | None) -> None: ... + @report_to.deleter + def report_to(self) -> None: ... + @property + def report_uri(self) -> str | None: ... + @report_uri.setter + def report_uri(self, value: str | None) -> None: ... + @report_uri.deleter + def report_uri(self) -> None: ... + @property + def sandbox(self) -> str | None: ... + @sandbox.setter + def sandbox(self, value: str | None) -> None: ... + @sandbox.deleter + def sandbox(self) -> None: ... + @property + def script_src(self) -> str | None: ... + @script_src.setter + def script_src(self, value: str | None) -> None: ... + @script_src.deleter + def script_src(self) -> None: ... + @property + def script_src_attr(self) -> str | None: ... + @script_src_attr.setter + def script_src_attr(self, value: str | None) -> None: ... + @script_src_attr.deleter + def script_src_attr(self) -> None: ... + @property + def script_src_elem(self) -> str | None: ... + @script_src_elem.setter + def script_src_elem(self, value: str | None) -> None: ... + @script_src_elem.deleter + def script_src_elem(self) -> None: ... + @property + def style_src(self) -> str | None: ... + @style_src.setter + def style_src(self, value: str | None) -> None: ... + @style_src.deleter + def style_src(self) -> None: ... + @property + def style_src_attr(self) -> str | None: ... + @style_src_attr.setter + def style_src_attr(self, value: str | None) -> None: ... + @style_src_attr.deleter + def style_src_attr(self) -> None: ... + @property + def style_src_elem(self) -> str | None: ... + @style_src_elem.setter + def style_src_elem(self, value: str | None) -> None: ... + @style_src_elem.deleter + def style_src_elem(self) -> None: ... + @property + def worker_src(self) -> str | None: ... + @worker_src.setter + def worker_src(self, value: str | None) -> None: ... + @worker_src.deleter + def worker_src(self) -> None: ... + provided: bool + def __init__( + self, + values: Mapping[str, str] | Iterable[tuple[str, str]] = (), + on_update: Callable[[ContentSecurityPolicy], None] | None = None, + ) -> None: ... + def _get_value(self, key: str) -> str | None: ... + def _set_value(self, key: str, value: str) -> None: ... + def _del_value(self, key: str) -> None: ... + def to_header(self) -> str: ... diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/etag.py b/MLPY/Lib/site-packages/werkzeug/datastructures/etag.py new file mode 100644 index 0000000000000000000000000000000000000000..747d9966ddc7c8ea034c07aacb7dcb3499eaa1f8 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/etag.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +from collections.abc import Collection + + +class ETags(Collection): + """A set that can be used to check if one etag is present in a collection + of etags. + """ + + def __init__(self, strong_etags=None, weak_etags=None, star_tag=False): + if not star_tag and strong_etags: + self._strong = frozenset(strong_etags) + else: + self._strong = frozenset() + + self._weak = frozenset(weak_etags or ()) + self.star_tag = star_tag + + def as_set(self, include_weak=False): + """Convert the `ETags` object into a python set. Per default all the + weak etags are not part of this set.""" + rv = set(self._strong) + if include_weak: + rv.update(self._weak) + return rv + + def is_weak(self, etag): + """Check if an etag is weak.""" + return etag in self._weak + + def is_strong(self, etag): + """Check if an etag is strong.""" + return etag in self._strong + + def contains_weak(self, etag): + """Check if an etag is part of the set including weak and strong tags.""" + return self.is_weak(etag) or self.contains(etag) + + def contains(self, etag): + """Check if an etag is part of the set ignoring weak tags. + It is also possible to use the ``in`` operator. + """ + if self.star_tag: + return True + return self.is_strong(etag) + + def contains_raw(self, etag): + """When passed a quoted tag it will check if this tag is part of the + set. If the tag is weak it is checked against weak and strong tags, + otherwise strong only.""" + from ..http import unquote_etag + + etag, weak = unquote_etag(etag) + if weak: + return self.contains_weak(etag) + return self.contains(etag) + + def to_header(self): + """Convert the etags set into a HTTP header string.""" + if self.star_tag: + return "*" + return ", ".join( + [f'"{x}"' for x in self._strong] + [f'W/"{x}"' for x in self._weak] + ) + + def __call__(self, etag=None, data=None, include_weak=False): + if [etag, data].count(None) != 1: + raise TypeError("either tag or data required, but at least one") + if etag is None: + from ..http import generate_etag + + etag = generate_etag(data) + if include_weak: + if etag in self._weak: + return True + return etag in self._strong + + def __bool__(self): + return bool(self.star_tag or self._strong or self._weak) + + def __str__(self): + return self.to_header() + + def __len__(self): + return len(self._strong) + + def __iter__(self): + return iter(self._strong) + + def __contains__(self, etag): + return self.contains(etag) + + def __repr__(self): + return f"<{type(self).__name__} {str(self)!r}>" diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/etag.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/etag.pyi new file mode 100644 index 0000000000000000000000000000000000000000..88e54f1548b993cc7bfdffec8216942fb5510dfd --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/etag.pyi @@ -0,0 +1,30 @@ +from collections.abc import Collection +from collections.abc import Iterable +from collections.abc import Iterator + +class ETags(Collection[str]): + _strong: frozenset[str] + _weak: frozenset[str] + star_tag: bool + def __init__( + self, + strong_etags: Iterable[str] | None = None, + weak_etags: Iterable[str] | None = None, + star_tag: bool = False, + ) -> None: ... + def as_set(self, include_weak: bool = False) -> set[str]: ... + def is_weak(self, etag: str) -> bool: ... + def is_strong(self, etag: str) -> bool: ... + def contains_weak(self, etag: str) -> bool: ... + def contains(self, etag: str) -> bool: ... + def contains_raw(self, etag: str) -> bool: ... + def to_header(self) -> str: ... + def __call__( + self, + etag: str | None = None, + data: bytes | None = None, + include_weak: bool = False, + ) -> bool: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[str]: ... + def __contains__(self, item: str) -> bool: ... # type: ignore diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/file_storage.py b/MLPY/Lib/site-packages/werkzeug/datastructures/file_storage.py new file mode 100644 index 0000000000000000000000000000000000000000..e878a56d4f435e471d550dd77192c7bdc3a125ba --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/file_storage.py @@ -0,0 +1,196 @@ +from __future__ import annotations + +import mimetypes +from io import BytesIO +from os import fsdecode +from os import fspath + +from .._internal import _plain_int +from .structures import MultiDict + + +class FileStorage: + """The :class:`FileStorage` class is a thin wrapper over incoming files. + It is used by the request object to represent uploaded files. All the + attributes of the wrapper stream are proxied by the file storage so + it's possible to do ``storage.read()`` instead of the long form + ``storage.stream.read()``. + """ + + def __init__( + self, + stream=None, + filename=None, + name=None, + content_type=None, + content_length=None, + headers=None, + ): + self.name = name + self.stream = stream or BytesIO() + + # If no filename is provided, attempt to get the filename from + # the stream object. Python names special streams like + # ```` with angular brackets, skip these streams. + if filename is None: + filename = getattr(stream, "name", None) + + if filename is not None: + filename = fsdecode(filename) + + if filename and filename[0] == "<" and filename[-1] == ">": + filename = None + else: + filename = fsdecode(filename) + + self.filename = filename + + if headers is None: + from .headers import Headers + + headers = Headers() + self.headers = headers + if content_type is not None: + headers["Content-Type"] = content_type + if content_length is not None: + headers["Content-Length"] = str(content_length) + + def _parse_content_type(self): + if not hasattr(self, "_parsed_content_type"): + self._parsed_content_type = http.parse_options_header(self.content_type) + + @property + def content_type(self): + """The content-type sent in the header. Usually not available""" + return self.headers.get("content-type") + + @property + def content_length(self): + """The content-length sent in the header. Usually not available""" + if "content-length" in self.headers: + try: + return _plain_int(self.headers["content-length"]) + except ValueError: + pass + + return 0 + + @property + def mimetype(self): + """Like :attr:`content_type`, but without parameters (eg, without + charset, type etc.) and always lowercase. For example if the content + type is ``text/HTML; charset=utf-8`` the mimetype would be + ``'text/html'``. + + .. versionadded:: 0.7 + """ + self._parse_content_type() + return self._parsed_content_type[0].lower() + + @property + def mimetype_params(self): + """The mimetype parameters as dict. For example if the content + type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.7 + """ + self._parse_content_type() + return self._parsed_content_type[1] + + def save(self, dst, buffer_size=16384): + """Save the file to a destination path or file object. If the + destination is a file object you have to close it yourself after the + call. The buffer size is the number of bytes held in memory during + the copy process. It defaults to 16KB. + + For secure file saving also have a look at :func:`secure_filename`. + + :param dst: a filename, :class:`os.PathLike`, or open file + object to write to. + :param buffer_size: Passed as the ``length`` parameter of + :func:`shutil.copyfileobj`. + + .. versionchanged:: 1.0 + Supports :mod:`pathlib`. + """ + from shutil import copyfileobj + + close_dst = False + + if hasattr(dst, "__fspath__"): + dst = fspath(dst) + + if isinstance(dst, str): + dst = open(dst, "wb") + close_dst = True + + try: + copyfileobj(self.stream, dst, buffer_size) + finally: + if close_dst: + dst.close() + + def close(self): + """Close the underlying file if possible.""" + try: + self.stream.close() + except Exception: + pass + + def __bool__(self): + return bool(self.filename) + + def __getattr__(self, name): + try: + return getattr(self.stream, name) + except AttributeError: + # SpooledTemporaryFile doesn't implement IOBase, get the + # attribute from its backing file instead. + # https://github.com/python/cpython/pull/3249 + if hasattr(self.stream, "_file"): + return getattr(self.stream._file, name) + raise + + def __iter__(self): + return iter(self.stream) + + def __repr__(self): + return f"<{type(self).__name__}: {self.filename!r} ({self.content_type!r})>" + + +class FileMultiDict(MultiDict): + """A special :class:`MultiDict` that has convenience methods to add + files to it. This is used for :class:`EnvironBuilder` and generally + useful for unittesting. + + .. versionadded:: 0.5 + """ + + def add_file(self, name, file, filename=None, content_type=None): + """Adds a new file to the dict. `file` can be a file name or + a :class:`file`-like or a :class:`FileStorage` object. + + :param name: the name of the field. + :param file: a filename or :class:`file`-like object + :param filename: an optional filename + :param content_type: an optional content type + """ + if isinstance(file, FileStorage): + value = file + else: + if isinstance(file, str): + if filename is None: + filename = file + file = open(file, "rb") + if filename and content_type is None: + content_type = ( + mimetypes.guess_type(filename)[0] or "application/octet-stream" + ) + value = FileStorage(file, filename, name, content_type) + + self.add(name, value) + + +# circular dependencies +from .. import http diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/file_storage.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/file_storage.pyi new file mode 100644 index 0000000000000000000000000000000000000000..36a7ed9f297e85c445e396f00ae7896752e9e5cb --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/file_storage.pyi @@ -0,0 +1,49 @@ +from collections.abc import Iterator +from os import PathLike +from typing import Any +from typing import IO + +from .headers import Headers +from .structures import MultiDict + +class FileStorage: + name: str | None + stream: IO[bytes] + filename: str | None + headers: Headers + _parsed_content_type: tuple[str, dict[str, str]] + def __init__( + self, + stream: IO[bytes] | None = None, + filename: str | PathLike[str] | None = None, + name: str | None = None, + content_type: str | None = None, + content_length: int | None = None, + headers: Headers | None = None, + ) -> None: ... + def _parse_content_type(self) -> None: ... + @property + def content_type(self) -> str: ... + @property + def content_length(self) -> int: ... + @property + def mimetype(self) -> str: ... + @property + def mimetype_params(self) -> dict[str, str]: ... + def save( + self, dst: str | PathLike[str] | IO[bytes], buffer_size: int = ... + ) -> None: ... + def close(self) -> None: ... + def __bool__(self) -> bool: ... + def __getattr__(self, name: str) -> Any: ... + def __iter__(self) -> Iterator[bytes]: ... + def __repr__(self) -> str: ... + +class FileMultiDict(MultiDict[str, FileStorage]): + def add_file( + self, + name: str, + file: FileStorage | str | IO[bytes], + filename: str | None = None, + content_type: str | None = None, + ) -> None: ... diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/headers.py b/MLPY/Lib/site-packages/werkzeug/datastructures/headers.py new file mode 100644 index 0000000000000000000000000000000000000000..d9dd655c2e1c1a64f484cfc6894fa06b17a7223d --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/headers.py @@ -0,0 +1,515 @@ +from __future__ import annotations + +import re +import typing as t + +from .._internal import _missing +from ..exceptions import BadRequestKeyError +from .mixins import ImmutableHeadersMixin +from .structures import iter_multi_items +from .structures import MultiDict + + +class Headers: + """An object that stores some headers. It has a dict-like interface, + but is ordered, can store the same key multiple times, and iterating + yields ``(key, value)`` pairs instead of only keys. + + This data structure is useful if you want a nicer way to handle WSGI + headers which are stored as tuples in a list. + + From Werkzeug 0.3 onwards, the :exc:`KeyError` raised by this class is + also a subclass of the :class:`~exceptions.BadRequest` HTTP exception + and will render a page for a ``400 BAD REQUEST`` if caught in a + catch-all for HTTP exceptions. + + Headers is mostly compatible with the Python :class:`wsgiref.headers.Headers` + class, with the exception of `__getitem__`. :mod:`wsgiref` will return + `None` for ``headers['missing']``, whereas :class:`Headers` will raise + a :class:`KeyError`. + + To create a new ``Headers`` object, pass it a list, dict, or + other ``Headers`` object with default values. These values are + validated the same way values added later are. + + :param defaults: The list of default values for the :class:`Headers`. + + .. versionchanged:: 2.1.0 + Default values are validated the same as values added later. + + .. versionchanged:: 0.9 + This data structure now stores unicode values similar to how the + multi dicts do it. The main difference is that bytes can be set as + well which will automatically be latin1 decoded. + + .. versionchanged:: 0.9 + The :meth:`linked` function was removed without replacement as it + was an API that does not support the changes to the encoding model. + """ + + def __init__(self, defaults=None): + self._list = [] + if defaults is not None: + self.extend(defaults) + + def __getitem__(self, key, _get_mode=False): + if not _get_mode: + if isinstance(key, int): + return self._list[key] + elif isinstance(key, slice): + return self.__class__(self._list[key]) + if not isinstance(key, str): + raise BadRequestKeyError(key) + ikey = key.lower() + for k, v in self._list: + if k.lower() == ikey: + return v + # micro optimization: if we are in get mode we will catch that + # exception one stack level down so we can raise a standard + # key error instead of our special one. + if _get_mode: + raise KeyError() + raise BadRequestKeyError(key) + + def __eq__(self, other): + def lowered(item): + return (item[0].lower(),) + item[1:] + + return other.__class__ is self.__class__ and set( + map(lowered, other._list) + ) == set(map(lowered, self._list)) + + __hash__ = None + + def get(self, key, default=None, type=None): + """Return the default value if the requested data doesn't exist. + If `type` is provided and is a callable it should convert the value, + return it or raise a :exc:`ValueError` if that is not possible. In + this case the function will return the default as if the value was not + found: + + >>> d = Headers([('Content-Length', '42')]) + >>> d.get('Content-Length', type=int) + 42 + + :param key: The key to be looked up. + :param default: The default value to be returned if the key can't + be looked up. If not further specified `None` is + returned. + :param type: A callable that is used to cast the value in the + :class:`Headers`. If a :exc:`ValueError` is raised + by this callable the default value is returned. + + .. versionchanged:: 3.0 + The ``as_bytes`` parameter was removed. + + .. versionchanged:: 0.9 + The ``as_bytes`` parameter was added. + """ + try: + rv = self.__getitem__(key, _get_mode=True) + except KeyError: + return default + if type is None: + return rv + try: + return type(rv) + except ValueError: + return default + + def getlist(self, key, type=None): + """Return the list of items for a given key. If that key is not in the + :class:`Headers`, the return value will be an empty list. Just like + :meth:`get`, :meth:`getlist` accepts a `type` parameter. All items will + be converted with the callable defined there. + + :param key: The key to be looked up. + :param type: A callable that is used to cast the value in the + :class:`Headers`. If a :exc:`ValueError` is raised + by this callable the value will be removed from the list. + :return: a :class:`list` of all the values for the key. + + .. versionchanged:: 3.0 + The ``as_bytes`` parameter was removed. + + .. versionchanged:: 0.9 + The ``as_bytes`` parameter was added. + """ + ikey = key.lower() + result = [] + for k, v in self: + if k.lower() == ikey: + if type is not None: + try: + v = type(v) + except ValueError: + continue + result.append(v) + return result + + def get_all(self, name): + """Return a list of all the values for the named field. + + This method is compatible with the :mod:`wsgiref` + :meth:`~wsgiref.headers.Headers.get_all` method. + """ + return self.getlist(name) + + def items(self, lower=False): + for key, value in self: + if lower: + key = key.lower() + yield key, value + + def keys(self, lower=False): + for key, _ in self.items(lower): + yield key + + def values(self): + for _, value in self.items(): + yield value + + def extend(self, *args, **kwargs): + """Extend headers in this object with items from another object + containing header items as well as keyword arguments. + + To replace existing keys instead of extending, use + :meth:`update` instead. + + If provided, the first argument can be another :class:`Headers` + object, a :class:`MultiDict`, :class:`dict`, or iterable of + pairs. + + .. versionchanged:: 1.0 + Support :class:`MultiDict`. Allow passing ``kwargs``. + """ + if len(args) > 1: + raise TypeError(f"update expected at most 1 arguments, got {len(args)}") + + if args: + for key, value in iter_multi_items(args[0]): + self.add(key, value) + + for key, value in iter_multi_items(kwargs): + self.add(key, value) + + def __delitem__(self, key, _index_operation=True): + if _index_operation and isinstance(key, (int, slice)): + del self._list[key] + return + key = key.lower() + new = [] + for k, v in self._list: + if k.lower() != key: + new.append((k, v)) + self._list[:] = new + + def remove(self, key): + """Remove a key. + + :param key: The key to be removed. + """ + return self.__delitem__(key, _index_operation=False) + + def pop(self, key=None, default=_missing): + """Removes and returns a key or index. + + :param key: The key to be popped. If this is an integer the item at + that position is removed, if it's a string the value for + that key is. If the key is omitted or `None` the last + item is removed. + :return: an item. + """ + if key is None: + return self._list.pop() + if isinstance(key, int): + return self._list.pop(key) + try: + rv = self[key] + self.remove(key) + except KeyError: + if default is not _missing: + return default + raise + return rv + + def popitem(self): + """Removes a key or index and returns a (key, value) item.""" + return self.pop() + + def __contains__(self, key): + """Check if a key is present.""" + try: + self.__getitem__(key, _get_mode=True) + except KeyError: + return False + return True + + def __iter__(self): + """Yield ``(key, value)`` tuples.""" + return iter(self._list) + + def __len__(self): + return len(self._list) + + def add(self, _key, _value, **kw): + """Add a new header tuple to the list. + + Keyword arguments can specify additional parameters for the header + value, with underscores converted to dashes:: + + >>> d = Headers() + >>> d.add('Content-Type', 'text/plain') + >>> d.add('Content-Disposition', 'attachment', filename='foo.png') + + The keyword argument dumping uses :func:`dump_options_header` + behind the scenes. + + .. versionadded:: 0.4.1 + keyword arguments were added for :mod:`wsgiref` compatibility. + """ + if kw: + _value = _options_header_vkw(_value, kw) + _value = _str_header_value(_value) + self._list.append((_key, _value)) + + def add_header(self, _key, _value, **_kw): + """Add a new header tuple to the list. + + An alias for :meth:`add` for compatibility with the :mod:`wsgiref` + :meth:`~wsgiref.headers.Headers.add_header` method. + """ + self.add(_key, _value, **_kw) + + def clear(self): + """Clears all headers.""" + del self._list[:] + + def set(self, _key, _value, **kw): + """Remove all header tuples for `key` and add a new one. The newly + added key either appears at the end of the list if there was no + entry or replaces the first one. + + Keyword arguments can specify additional parameters for the header + value, with underscores converted to dashes. See :meth:`add` for + more information. + + .. versionchanged:: 0.6.1 + :meth:`set` now accepts the same arguments as :meth:`add`. + + :param key: The key to be inserted. + :param value: The value to be inserted. + """ + if kw: + _value = _options_header_vkw(_value, kw) + _value = _str_header_value(_value) + if not self._list: + self._list.append((_key, _value)) + return + listiter = iter(self._list) + ikey = _key.lower() + for idx, (old_key, _old_value) in enumerate(listiter): + if old_key.lower() == ikey: + # replace first occurrence + self._list[idx] = (_key, _value) + break + else: + self._list.append((_key, _value)) + return + self._list[idx + 1 :] = [t for t in listiter if t[0].lower() != ikey] + + def setlist(self, key, values): + """Remove any existing values for a header and add new ones. + + :param key: The header key to set. + :param values: An iterable of values to set for the key. + + .. versionadded:: 1.0 + """ + if values: + values_iter = iter(values) + self.set(key, next(values_iter)) + + for value in values_iter: + self.add(key, value) + else: + self.remove(key) + + def setdefault(self, key, default): + """Return the first value for the key if it is in the headers, + otherwise set the header to the value given by ``default`` and + return that. + + :param key: The header key to get. + :param default: The value to set for the key if it is not in the + headers. + """ + if key in self: + return self[key] + + self.set(key, default) + return default + + def setlistdefault(self, key, default): + """Return the list of values for the key if it is in the + headers, otherwise set the header to the list of values given + by ``default`` and return that. + + Unlike :meth:`MultiDict.setlistdefault`, modifying the returned + list will not affect the headers. + + :param key: The header key to get. + :param default: An iterable of values to set for the key if it + is not in the headers. + + .. versionadded:: 1.0 + """ + if key not in self: + self.setlist(key, default) + + return self.getlist(key) + + def __setitem__(self, key, value): + """Like :meth:`set` but also supports index/slice based setting.""" + if isinstance(key, (slice, int)): + if isinstance(key, int): + value = [value] + value = [(k, _str_header_value(v)) for (k, v) in value] + if isinstance(key, int): + self._list[key] = value[0] + else: + self._list[key] = value + else: + self.set(key, value) + + def update(self, *args, **kwargs): + """Replace headers in this object with items from another + headers object and keyword arguments. + + To extend existing keys instead of replacing, use :meth:`extend` + instead. + + If provided, the first argument can be another :class:`Headers` + object, a :class:`MultiDict`, :class:`dict`, or iterable of + pairs. + + .. versionadded:: 1.0 + """ + if len(args) > 1: + raise TypeError(f"update expected at most 1 arguments, got {len(args)}") + + if args: + mapping = args[0] + + if isinstance(mapping, (Headers, MultiDict)): + for key in mapping.keys(): + self.setlist(key, mapping.getlist(key)) + elif isinstance(mapping, dict): + for key, value in mapping.items(): + if isinstance(value, (list, tuple)): + self.setlist(key, value) + else: + self.set(key, value) + else: + for key, value in mapping: + self.set(key, value) + + for key, value in kwargs.items(): + if isinstance(value, (list, tuple)): + self.setlist(key, value) + else: + self.set(key, value) + + def to_wsgi_list(self): + """Convert the headers into a list suitable for WSGI. + + :return: list + """ + return list(self) + + def copy(self): + return self.__class__(self._list) + + def __copy__(self): + return self.copy() + + def __str__(self): + """Returns formatted headers suitable for HTTP transmission.""" + strs = [] + for key, value in self.to_wsgi_list(): + strs.append(f"{key}: {value}") + strs.append("\r\n") + return "\r\n".join(strs) + + def __repr__(self): + return f"{type(self).__name__}({list(self)!r})" + + +def _options_header_vkw(value: str, kw: dict[str, t.Any]): + return http.dump_options_header( + value, {k.replace("_", "-"): v for k, v in kw.items()} + ) + + +_newline_re = re.compile(r"[\r\n]") + + +def _str_header_value(value: t.Any) -> str: + if not isinstance(value, str): + value = str(value) + + if _newline_re.search(value) is not None: + raise ValueError("Header values must not contain newline characters.") + + return value + + +class EnvironHeaders(ImmutableHeadersMixin, Headers): + """Read only version of the headers from a WSGI environment. This + provides the same interface as `Headers` and is constructed from + a WSGI environment. + From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a + subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will + render a page for a ``400 BAD REQUEST`` if caught in a catch-all for + HTTP exceptions. + """ + + def __init__(self, environ): + self.environ = environ + + def __eq__(self, other): + return self.environ is other.environ + + __hash__ = None + + def __getitem__(self, key, _get_mode=False): + # _get_mode is a no-op for this class as there is no index but + # used because get() calls it. + if not isinstance(key, str): + raise KeyError(key) + key = key.upper().replace("-", "_") + if key in {"CONTENT_TYPE", "CONTENT_LENGTH"}: + return self.environ[key] + return self.environ[f"HTTP_{key}"] + + def __len__(self): + # the iter is necessary because otherwise list calls our + # len which would call list again and so forth. + return len(list(iter(self))) + + def __iter__(self): + for key, value in self.environ.items(): + if key.startswith("HTTP_") and key not in { + "HTTP_CONTENT_TYPE", + "HTTP_CONTENT_LENGTH", + }: + yield key[5:].replace("_", "-").title(), value + elif key in {"CONTENT_TYPE", "CONTENT_LENGTH"} and value: + yield key.replace("_", "-").title(), value + + def copy(self): + raise TypeError(f"cannot create {type(self).__name__!r} copies") + + +# circular dependencies +from .. import http diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/headers.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/headers.pyi new file mode 100644 index 0000000000000000000000000000000000000000..86502221ae86b415278bb369bcc542f29e76642f --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/headers.pyi @@ -0,0 +1,109 @@ +from collections.abc import Callable +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Mapping +from typing import Literal +from typing import NoReturn +from typing import overload +from typing import TypeVar + +from _typeshed import SupportsKeysAndGetItem +from _typeshed.wsgi import WSGIEnvironment + +from .mixins import ImmutableHeadersMixin + +D = TypeVar("D") +T = TypeVar("T") + +class Headers(dict[str, str]): + _list: list[tuple[str, str]] + def __init__( + self, + defaults: Mapping[str, str | Iterable[str]] + | Iterable[tuple[str, str]] + | None = None, + ) -> None: ... + @overload + def __getitem__(self, key: str) -> str: ... + @overload + def __getitem__(self, key: int) -> tuple[str, str]: ... + @overload + def __getitem__(self, key: slice) -> Headers: ... + @overload + def __getitem__(self, key: str, _get_mode: Literal[True] = ...) -> str: ... + def __eq__(self, other: object) -> bool: ... + @overload # type: ignore + def get(self, key: str, default: str) -> str: ... + @overload + def get(self, key: str, default: str | None = None) -> str | None: ... + @overload + def get( + self, key: str, default: T | None = None, type: Callable[[str], T] = ... + ) -> T | None: ... + @overload + def getlist(self, key: str) -> list[str]: ... + @overload + def getlist(self, key: str, type: Callable[[str], T]) -> list[T]: ... + def get_all(self, name: str) -> list[str]: ... + def items( # type: ignore + self, lower: bool = False + ) -> Iterator[tuple[str, str]]: ... + def keys(self, lower: bool = False) -> Iterator[str]: ... # type: ignore + def values(self) -> Iterator[str]: ... # type: ignore + def extend( + self, + *args: Mapping[str, str | Iterable[str]] | Iterable[tuple[str, str]], + **kwargs: str | Iterable[str], + ) -> None: ... + @overload + def __delitem__(self, key: str | int | slice) -> None: ... + @overload + def __delitem__(self, key: str, _index_operation: Literal[False]) -> None: ... + def remove(self, key: str) -> None: ... + @overload # type: ignore + def pop(self, key: str, default: str | None = None) -> str: ... + @overload + def pop( + self, key: int | None = None, default: tuple[str, str] | None = None + ) -> tuple[str, str]: ... + def popitem(self) -> tuple[str, str]: ... + def __contains__(self, key: str) -> bool: ... # type: ignore + def has_key(self, key: str) -> bool: ... + def __iter__(self) -> Iterator[tuple[str, str]]: ... # type: ignore + def add(self, _key: str, _value: str, **kw: str) -> None: ... + def _validate_value(self, value: str) -> None: ... + def add_header(self, _key: str, _value: str, **_kw: str) -> None: ... + def clear(self) -> None: ... + def set(self, _key: str, _value: str, **kw: str) -> None: ... + def setlist(self, key: str, values: Iterable[str]) -> None: ... + def setdefault(self, key: str, default: str) -> str: ... + def setlistdefault(self, key: str, default: Iterable[str]) -> None: ... + @overload + def __setitem__(self, key: str, value: str) -> None: ... + @overload + def __setitem__(self, key: int, value: tuple[str, str]) -> None: ... + @overload + def __setitem__(self, key: slice, value: Iterable[tuple[str, str]]) -> None: ... + @overload + def update( + self, __m: SupportsKeysAndGetItem[str, str], **kwargs: str | Iterable[str] + ) -> None: ... + @overload + def update( + self, __m: Iterable[tuple[str, str]], **kwargs: str | Iterable[str] + ) -> None: ... + @overload + def update(self, **kwargs: str | Iterable[str]) -> None: ... + def to_wsgi_list(self) -> list[tuple[str, str]]: ... + def copy(self) -> Headers: ... + def __copy__(self) -> Headers: ... + +class EnvironHeaders(ImmutableHeadersMixin, Headers): + environ: WSGIEnvironment + def __init__(self, environ: WSGIEnvironment) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __getitem__( # type: ignore + self, key: str, _get_mode: Literal[False] = False + ) -> str: ... + def __iter__(self) -> Iterator[tuple[str, str]]: ... # type: ignore + def copy(self) -> NoReturn: ... diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/mixins.py b/MLPY/Lib/site-packages/werkzeug/datastructures/mixins.py new file mode 100644 index 0000000000000000000000000000000000000000..2c84ca8f23d8a87d990b848b2f0472049022ac9a --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/mixins.py @@ -0,0 +1,242 @@ +from __future__ import annotations + +from itertools import repeat + +from .._internal import _missing + + +def is_immutable(self): + raise TypeError(f"{type(self).__name__!r} objects are immutable") + + +class ImmutableListMixin: + """Makes a :class:`list` immutable. + + .. versionadded:: 0.5 + + :private: + """ + + _hash_cache = None + + def __hash__(self): + if self._hash_cache is not None: + return self._hash_cache + rv = self._hash_cache = hash(tuple(self)) + return rv + + def __reduce_ex__(self, protocol): + return type(self), (list(self),) + + def __delitem__(self, key): + is_immutable(self) + + def __iadd__(self, other): + is_immutable(self) + + def __imul__(self, other): + is_immutable(self) + + def __setitem__(self, key, value): + is_immutable(self) + + def append(self, item): + is_immutable(self) + + def remove(self, item): + is_immutable(self) + + def extend(self, iterable): + is_immutable(self) + + def insert(self, pos, value): + is_immutable(self) + + def pop(self, index=-1): + is_immutable(self) + + def reverse(self): + is_immutable(self) + + def sort(self, key=None, reverse=False): + is_immutable(self) + + +class ImmutableDictMixin: + """Makes a :class:`dict` immutable. + + .. versionadded:: 0.5 + + :private: + """ + + _hash_cache = None + + @classmethod + def fromkeys(cls, keys, value=None): + instance = super().__new__(cls) + instance.__init__(zip(keys, repeat(value))) + return instance + + def __reduce_ex__(self, protocol): + return type(self), (dict(self),) + + def _iter_hashitems(self): + return self.items() + + def __hash__(self): + if self._hash_cache is not None: + return self._hash_cache + rv = self._hash_cache = hash(frozenset(self._iter_hashitems())) + return rv + + def setdefault(self, key, default=None): + is_immutable(self) + + def update(self, *args, **kwargs): + is_immutable(self) + + def pop(self, key, default=None): + is_immutable(self) + + def popitem(self): + is_immutable(self) + + def __setitem__(self, key, value): + is_immutable(self) + + def __delitem__(self, key): + is_immutable(self) + + def clear(self): + is_immutable(self) + + +class ImmutableMultiDictMixin(ImmutableDictMixin): + """Makes a :class:`MultiDict` immutable. + + .. versionadded:: 0.5 + + :private: + """ + + def __reduce_ex__(self, protocol): + return type(self), (list(self.items(multi=True)),) + + def _iter_hashitems(self): + return self.items(multi=True) + + def add(self, key, value): + is_immutable(self) + + def popitemlist(self): + is_immutable(self) + + def poplist(self, key): + is_immutable(self) + + def setlist(self, key, new_list): + is_immutable(self) + + def setlistdefault(self, key, default_list=None): + is_immutable(self) + + +class ImmutableHeadersMixin: + """Makes a :class:`Headers` immutable. We do not mark them as + hashable though since the only usecase for this datastructure + in Werkzeug is a view on a mutable structure. + + .. versionadded:: 0.5 + + :private: + """ + + def __delitem__(self, key, **kwargs): + is_immutable(self) + + def __setitem__(self, key, value): + is_immutable(self) + + def set(self, _key, _value, **kwargs): + is_immutable(self) + + def setlist(self, key, values): + is_immutable(self) + + def add(self, _key, _value, **kwargs): + is_immutable(self) + + def add_header(self, _key, _value, **_kwargs): + is_immutable(self) + + def remove(self, key): + is_immutable(self) + + def extend(self, *args, **kwargs): + is_immutable(self) + + def update(self, *args, **kwargs): + is_immutable(self) + + def insert(self, pos, value): + is_immutable(self) + + def pop(self, key=None, default=_missing): + is_immutable(self) + + def popitem(self): + is_immutable(self) + + def setdefault(self, key, default): + is_immutable(self) + + def setlistdefault(self, key, default): + is_immutable(self) + + +def _calls_update(name): + def oncall(self, *args, **kw): + rv = getattr(super(UpdateDictMixin, self), name)(*args, **kw) + + if self.on_update is not None: + self.on_update(self) + + return rv + + oncall.__name__ = name + return oncall + + +class UpdateDictMixin(dict): + """Makes dicts call `self.on_update` on modifications. + + .. versionadded:: 0.5 + + :private: + """ + + on_update = None + + def setdefault(self, key, default=None): + modified = key not in self + rv = super().setdefault(key, default) + if modified and self.on_update is not None: + self.on_update(self) + return rv + + def pop(self, key, default=_missing): + modified = key in self + if default is _missing: + rv = super().pop(key) + else: + rv = super().pop(key, default) + if modified and self.on_update is not None: + self.on_update(self) + return rv + + __setitem__ = _calls_update("__setitem__") + __delitem__ = _calls_update("__delitem__") + clear = _calls_update("clear") + popitem = _calls_update("popitem") + update = _calls_update("update") diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/mixins.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/mixins.pyi new file mode 100644 index 0000000000000000000000000000000000000000..40453f703daf917d3fcc170f87b47c7f73209500 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/mixins.pyi @@ -0,0 +1,97 @@ +from collections.abc import Callable +from collections.abc import Hashable +from collections.abc import Iterable +from typing import Any +from typing import NoReturn +from typing import overload +from typing import SupportsIndex +from typing import TypeVar + +from _typeshed import SupportsKeysAndGetItem + +from .headers import Headers + +K = TypeVar("K") +T = TypeVar("T") +V = TypeVar("V") + +def is_immutable(self: object) -> NoReturn: ... + +class ImmutableListMixin(list[V]): + _hash_cache: int | None + def __hash__(self) -> int: ... # type: ignore + def __delitem__(self, key: SupportsIndex | slice) -> NoReturn: ... + def __iadd__(self, other: Any) -> NoReturn: ... # type: ignore + def __imul__(self, other: SupportsIndex) -> NoReturn: ... + def __setitem__(self, key: int | slice, value: V) -> NoReturn: ... # type: ignore + def append(self, value: V) -> NoReturn: ... + def remove(self, value: V) -> NoReturn: ... + def extend(self, values: Iterable[V]) -> NoReturn: ... + def insert(self, pos: SupportsIndex, value: V) -> NoReturn: ... + def pop(self, index: SupportsIndex = -1) -> NoReturn: ... + def reverse(self) -> NoReturn: ... + def sort( + self, key: Callable[[V], Any] | None = None, reverse: bool = False + ) -> NoReturn: ... + +class ImmutableDictMixin(dict[K, V]): + _hash_cache: int | None + @classmethod + def fromkeys( # type: ignore + cls, keys: Iterable[K], value: V | None = None + ) -> ImmutableDictMixin[K, V]: ... + def _iter_hashitems(self) -> Iterable[Hashable]: ... + def __hash__(self) -> int: ... # type: ignore + def setdefault(self, key: K, default: V | None = None) -> NoReturn: ... + def update(self, *args: Any, **kwargs: V) -> NoReturn: ... + def pop(self, key: K, default: V | None = None) -> NoReturn: ... # type: ignore + def popitem(self) -> NoReturn: ... + def __setitem__(self, key: K, value: V) -> NoReturn: ... + def __delitem__(self, key: K) -> NoReturn: ... + def clear(self) -> NoReturn: ... + +class ImmutableMultiDictMixin(ImmutableDictMixin[K, V]): + def _iter_hashitems(self) -> Iterable[Hashable]: ... + def add(self, key: K, value: V) -> NoReturn: ... + def popitemlist(self) -> NoReturn: ... + def poplist(self, key: K) -> NoReturn: ... + def setlist(self, key: K, new_list: Iterable[V]) -> NoReturn: ... + def setlistdefault( + self, key: K, default_list: Iterable[V] | None = None + ) -> NoReturn: ... + +class ImmutableHeadersMixin(Headers): + def __delitem__(self, key: Any, _index_operation: bool = True) -> NoReturn: ... + def __setitem__(self, key: Any, value: Any) -> NoReturn: ... + def set(self, _key: Any, _value: Any, **kw: Any) -> NoReturn: ... + def setlist(self, key: Any, values: Any) -> NoReturn: ... + def add(self, _key: Any, _value: Any, **kw: Any) -> NoReturn: ... + def add_header(self, _key: Any, _value: Any, **_kw: Any) -> NoReturn: ... + def remove(self, key: Any) -> NoReturn: ... + def extend(self, *args: Any, **kwargs: Any) -> NoReturn: ... + def update(self, *args: Any, **kwargs: Any) -> NoReturn: ... + def insert(self, pos: Any, value: Any) -> NoReturn: ... + def pop(self, key: Any = None, default: Any = ...) -> NoReturn: ... + def popitem(self) -> NoReturn: ... + def setdefault(self, key: Any, default: Any) -> NoReturn: ... + def setlistdefault(self, key: Any, default: Any) -> NoReturn: ... + +def _calls_update(name: str) -> Callable[[UpdateDictMixin[K, V]], Any]: ... + +class UpdateDictMixin(dict[K, V]): + on_update: Callable[[UpdateDictMixin[K, V] | None, None], None] + def setdefault(self, key: K, default: V | None = None) -> V: ... + @overload + def pop(self, key: K) -> V: ... + @overload + def pop(self, key: K, default: V | T = ...) -> V | T: ... + def __setitem__(self, key: K, value: V) -> None: ... + def __delitem__(self, key: K) -> None: ... + def clear(self) -> None: ... + def popitem(self) -> tuple[K, V]: ... + @overload + def update(self, __m: SupportsKeysAndGetItem[K, V], **kwargs: V) -> None: ... + @overload + def update(self, __m: Iterable[tuple[K, V]], **kwargs: V) -> None: ... + @overload + def update(self, **kwargs: V) -> None: ... diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/range.py b/MLPY/Lib/site-packages/werkzeug/datastructures/range.py new file mode 100644 index 0000000000000000000000000000000000000000..7011ea4ae33a17984d45138be3fabd1529f591b1 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/range.py @@ -0,0 +1,180 @@ +from __future__ import annotations + + +class IfRange: + """Very simple object that represents the `If-Range` header in parsed + form. It will either have neither a etag or date or one of either but + never both. + + .. versionadded:: 0.7 + """ + + def __init__(self, etag=None, date=None): + #: The etag parsed and unquoted. Ranges always operate on strong + #: etags so the weakness information is not necessary. + self.etag = etag + #: The date in parsed format or `None`. + self.date = date + + def to_header(self): + """Converts the object back into an HTTP header.""" + if self.date is not None: + return http.http_date(self.date) + if self.etag is not None: + return http.quote_etag(self.etag) + return "" + + def __str__(self): + return self.to_header() + + def __repr__(self): + return f"<{type(self).__name__} {str(self)!r}>" + + +class Range: + """Represents a ``Range`` header. All methods only support only + bytes as the unit. Stores a list of ranges if given, but the methods + only work if only one range is provided. + + :raise ValueError: If the ranges provided are invalid. + + .. versionchanged:: 0.15 + The ranges passed in are validated. + + .. versionadded:: 0.7 + """ + + def __init__(self, units, ranges): + #: The units of this range. Usually "bytes". + self.units = units + #: A list of ``(begin, end)`` tuples for the range header provided. + #: The ranges are non-inclusive. + self.ranges = ranges + + for start, end in ranges: + if start is None or (end is not None and (start < 0 or start >= end)): + raise ValueError(f"{(start, end)} is not a valid range.") + + def range_for_length(self, length): + """If the range is for bytes, the length is not None and there is + exactly one range and it is satisfiable it returns a ``(start, stop)`` + tuple, otherwise `None`. + """ + if self.units != "bytes" or length is None or len(self.ranges) != 1: + return None + start, end = self.ranges[0] + if end is None: + end = length + if start < 0: + start += length + if http.is_byte_range_valid(start, end, length): + return start, min(end, length) + return None + + def make_content_range(self, length): + """Creates a :class:`~werkzeug.datastructures.ContentRange` object + from the current range and given content length. + """ + rng = self.range_for_length(length) + if rng is not None: + return ContentRange(self.units, rng[0], rng[1], length) + return None + + def to_header(self): + """Converts the object back into an HTTP header.""" + ranges = [] + for begin, end in self.ranges: + if end is None: + ranges.append(f"{begin}-" if begin >= 0 else str(begin)) + else: + ranges.append(f"{begin}-{end - 1}") + return f"{self.units}={','.join(ranges)}" + + def to_content_range_header(self, length): + """Converts the object into `Content-Range` HTTP header, + based on given length + """ + range = self.range_for_length(length) + if range is not None: + return f"{self.units} {range[0]}-{range[1] - 1}/{length}" + return None + + def __str__(self): + return self.to_header() + + def __repr__(self): + return f"<{type(self).__name__} {str(self)!r}>" + + +def _callback_property(name): + def fget(self): + return getattr(self, name) + + def fset(self, value): + setattr(self, name, value) + if self.on_update is not None: + self.on_update(self) + + return property(fget, fset) + + +class ContentRange: + """Represents the content range header. + + .. versionadded:: 0.7 + """ + + def __init__(self, units, start, stop, length=None, on_update=None): + assert http.is_byte_range_valid(start, stop, length), "Bad range provided" + self.on_update = on_update + self.set(start, stop, length, units) + + #: The units to use, usually "bytes" + units = _callback_property("_units") + #: The start point of the range or `None`. + start = _callback_property("_start") + #: The stop point of the range (non-inclusive) or `None`. Can only be + #: `None` if also start is `None`. + stop = _callback_property("_stop") + #: The length of the range or `None`. + length = _callback_property("_length") + + def set(self, start, stop, length=None, units="bytes"): + """Simple method to update the ranges.""" + assert http.is_byte_range_valid(start, stop, length), "Bad range provided" + self._units = units + self._start = start + self._stop = stop + self._length = length + if self.on_update is not None: + self.on_update(self) + + def unset(self): + """Sets the units to `None` which indicates that the header should + no longer be used. + """ + self.set(None, None, units=None) + + def to_header(self): + if self.units is None: + return "" + if self.length is None: + length = "*" + else: + length = self.length + if self.start is None: + return f"{self.units} */{length}" + return f"{self.units} {self.start}-{self.stop - 1}/{length}" + + def __bool__(self): + return self.units is not None + + def __str__(self): + return self.to_header() + + def __repr__(self): + return f"<{type(self).__name__} {str(self)!r}>" + + +# circular dependencies +from .. import http diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/range.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/range.pyi new file mode 100644 index 0000000000000000000000000000000000000000..f38ad69ef107582660501eebf969311b748e681c --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/range.pyi @@ -0,0 +1,57 @@ +from collections.abc import Callable +from datetime import datetime + +class IfRange: + etag: str | None + date: datetime | None + def __init__( + self, etag: str | None = None, date: datetime | None = None + ) -> None: ... + def to_header(self) -> str: ... + +class Range: + units: str + ranges: list[tuple[int, int | None]] + def __init__(self, units: str, ranges: list[tuple[int, int | None]]) -> None: ... + def range_for_length(self, length: int | None) -> tuple[int, int] | None: ... + def make_content_range(self, length: int | None) -> ContentRange | None: ... + def to_header(self) -> str: ... + def to_content_range_header(self, length: int | None) -> str | None: ... + +def _callback_property(name: str) -> property: ... + +class ContentRange: + on_update: Callable[[ContentRange], None] | None + def __init__( + self, + units: str | None, + start: int | None, + stop: int | None, + length: int | None = None, + on_update: Callable[[ContentRange], None] | None = None, + ) -> None: ... + @property + def units(self) -> str | None: ... + @units.setter + def units(self, value: str | None) -> None: ... + @property + def start(self) -> int | None: ... + @start.setter + def start(self, value: int | None) -> None: ... + @property + def stop(self) -> int | None: ... + @stop.setter + def stop(self, value: int | None) -> None: ... + @property + def length(self) -> int | None: ... + @length.setter + def length(self, value: int | None) -> None: ... + def set( + self, + start: int | None, + stop: int | None, + length: int | None = None, + units: str | None = "bytes", + ) -> None: ... + def unset(self) -> None: ... + def to_header(self) -> str: ... diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/structures.py b/MLPY/Lib/site-packages/werkzeug/datastructures/structures.py new file mode 100644 index 0000000000000000000000000000000000000000..4279ceb980ef6c58636d46b1b864d8ff5334eefd --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/structures.py @@ -0,0 +1,1010 @@ +from __future__ import annotations + +from collections.abc import MutableSet +from copy import deepcopy + +from .. import exceptions +from .._internal import _missing +from .mixins import ImmutableDictMixin +from .mixins import ImmutableListMixin +from .mixins import ImmutableMultiDictMixin +from .mixins import UpdateDictMixin + + +def is_immutable(self): + raise TypeError(f"{type(self).__name__!r} objects are immutable") + + +def iter_multi_items(mapping): + """Iterates over the items of a mapping yielding keys and values + without dropping any from more complex structures. + """ + if isinstance(mapping, MultiDict): + yield from mapping.items(multi=True) + elif isinstance(mapping, dict): + for key, value in mapping.items(): + if isinstance(value, (tuple, list)): + for v in value: + yield key, v + else: + yield key, value + else: + yield from mapping + + +class ImmutableList(ImmutableListMixin, list): + """An immutable :class:`list`. + + .. versionadded:: 0.5 + + :private: + """ + + def __repr__(self): + return f"{type(self).__name__}({list.__repr__(self)})" + + +class TypeConversionDict(dict): + """Works like a regular dict but the :meth:`get` method can perform + type conversions. :class:`MultiDict` and :class:`CombinedMultiDict` + are subclasses of this class and provide the same feature. + + .. versionadded:: 0.5 + """ + + def get(self, key, default=None, type=None): + """Return the default value if the requested data doesn't exist. + If `type` is provided and is a callable it should convert the value, + return it or raise a :exc:`ValueError` if that is not possible. In + this case the function will return the default as if the value was not + found: + + >>> d = TypeConversionDict(foo='42', bar='blub') + >>> d.get('foo', type=int) + 42 + >>> d.get('bar', -1, type=int) + -1 + + :param key: The key to be looked up. + :param default: The default value to be returned if the key can't + be looked up. If not further specified `None` is + returned. + :param type: A callable that is used to cast the value in the + :class:`MultiDict`. If a :exc:`ValueError` or a + :exc:`TypeError` is raised by this callable the default + value is returned. + + .. versionchanged:: 3.0.2 + Returns the default value on :exc:`TypeError`, too. + """ + try: + rv = self[key] + except KeyError: + return default + if type is not None: + try: + rv = type(rv) + except (ValueError, TypeError): + rv = default + return rv + + +class ImmutableTypeConversionDict(ImmutableDictMixin, TypeConversionDict): + """Works like a :class:`TypeConversionDict` but does not support + modifications. + + .. versionadded:: 0.5 + """ + + def copy(self): + """Return a shallow mutable copy of this object. Keep in mind that + the standard library's :func:`copy` function is a no-op for this class + like for any other python immutable type (eg: :class:`tuple`). + """ + return TypeConversionDict(self) + + def __copy__(self): + return self + + +class MultiDict(TypeConversionDict): + """A :class:`MultiDict` is a dictionary subclass customized to deal with + multiple values for the same key which is for example used by the parsing + functions in the wrappers. This is necessary because some HTML form + elements pass multiple values for the same key. + + :class:`MultiDict` implements all standard dictionary methods. + Internally, it saves all values for a key as a list, but the standard dict + access methods will only return the first value for a key. If you want to + gain access to the other values, too, you have to use the `list` methods as + explained below. + + Basic Usage: + + >>> d = MultiDict([('a', 'b'), ('a', 'c')]) + >>> d + MultiDict([('a', 'b'), ('a', 'c')]) + >>> d['a'] + 'b' + >>> d.getlist('a') + ['b', 'c'] + >>> 'a' in d + True + + It behaves like a normal dict thus all dict functions will only return the + first value when multiple values for one key are found. + + From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a + subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will + render a page for a ``400 BAD REQUEST`` if caught in a catch-all for HTTP + exceptions. + + A :class:`MultiDict` can be constructed from an iterable of + ``(key, value)`` tuples, a dict, a :class:`MultiDict` or from Werkzeug 0.2 + onwards some keyword parameters. + + :param mapping: the initial value for the :class:`MultiDict`. Either a + regular dict, an iterable of ``(key, value)`` tuples + or `None`. + """ + + def __init__(self, mapping=None): + if isinstance(mapping, MultiDict): + dict.__init__(self, ((k, vs[:]) for k, vs in mapping.lists())) + elif isinstance(mapping, dict): + tmp = {} + for key, value in mapping.items(): + if isinstance(value, (tuple, list)): + if len(value) == 0: + continue + value = list(value) + else: + value = [value] + tmp[key] = value + dict.__init__(self, tmp) + else: + tmp = {} + for key, value in mapping or (): + tmp.setdefault(key, []).append(value) + dict.__init__(self, tmp) + + def __getstate__(self): + return dict(self.lists()) + + def __setstate__(self, value): + dict.clear(self) + dict.update(self, value) + + def __iter__(self): + # Work around https://bugs.python.org/issue43246. + # (`return super().__iter__()` also works here, which makes this look + # even more like it should be a no-op, yet it isn't.) + return dict.__iter__(self) + + def __getitem__(self, key): + """Return the first data value for this key; + raises KeyError if not found. + + :param key: The key to be looked up. + :raise KeyError: if the key does not exist. + """ + + if key in self: + lst = dict.__getitem__(self, key) + if len(lst) > 0: + return lst[0] + raise exceptions.BadRequestKeyError(key) + + def __setitem__(self, key, value): + """Like :meth:`add` but removes an existing key first. + + :param key: the key for the value. + :param value: the value to set. + """ + dict.__setitem__(self, key, [value]) + + def add(self, key, value): + """Adds a new value for the key. + + .. versionadded:: 0.6 + + :param key: the key for the value. + :param value: the value to add. + """ + dict.setdefault(self, key, []).append(value) + + def getlist(self, key, type=None): + """Return the list of items for a given key. If that key is not in the + `MultiDict`, the return value will be an empty list. Just like `get`, + `getlist` accepts a `type` parameter. All items will be converted + with the callable defined there. + + :param key: The key to be looked up. + :param type: A callable that is used to cast the value in the + :class:`MultiDict`. If a :exc:`ValueError` is raised + by this callable the value will be removed from the list. + :return: a :class:`list` of all the values for the key. + """ + try: + rv = dict.__getitem__(self, key) + except KeyError: + return [] + if type is None: + return list(rv) + result = [] + for item in rv: + try: + result.append(type(item)) + except ValueError: + pass + return result + + def setlist(self, key, new_list): + """Remove the old values for a key and add new ones. Note that the list + you pass the values in will be shallow-copied before it is inserted in + the dictionary. + + >>> d = MultiDict() + >>> d.setlist('foo', ['1', '2']) + >>> d['foo'] + '1' + >>> d.getlist('foo') + ['1', '2'] + + :param key: The key for which the values are set. + :param new_list: An iterable with the new values for the key. Old values + are removed first. + """ + dict.__setitem__(self, key, list(new_list)) + + def setdefault(self, key, default=None): + """Returns the value for the key if it is in the dict, otherwise it + returns `default` and sets that value for `key`. + + :param key: The key to be looked up. + :param default: The default value to be returned if the key is not + in the dict. If not further specified it's `None`. + """ + if key not in self: + self[key] = default + else: + default = self[key] + return default + + def setlistdefault(self, key, default_list=None): + """Like `setdefault` but sets multiple values. The list returned + is not a copy, but the list that is actually used internally. This + means that you can put new values into the dict by appending items + to the list: + + >>> d = MultiDict({"foo": 1}) + >>> d.setlistdefault("foo").extend([2, 3]) + >>> d.getlist("foo") + [1, 2, 3] + + :param key: The key to be looked up. + :param default_list: An iterable of default values. It is either copied + (in case it was a list) or converted into a list + before returned. + :return: a :class:`list` + """ + if key not in self: + default_list = list(default_list or ()) + dict.__setitem__(self, key, default_list) + else: + default_list = dict.__getitem__(self, key) + return default_list + + def items(self, multi=False): + """Return an iterator of ``(key, value)`` pairs. + + :param multi: If set to `True` the iterator returned will have a pair + for each value of each key. Otherwise it will only + contain pairs for the first value of each key. + """ + for key, values in dict.items(self): + if multi: + for value in values: + yield key, value + else: + yield key, values[0] + + def lists(self): + """Return a iterator of ``(key, values)`` pairs, where values is the list + of all values associated with the key.""" + for key, values in dict.items(self): + yield key, list(values) + + def values(self): + """Returns an iterator of the first value on every key's value list.""" + for values in dict.values(self): + yield values[0] + + def listvalues(self): + """Return an iterator of all values associated with a key. Zipping + :meth:`keys` and this is the same as calling :meth:`lists`: + + >>> d = MultiDict({"foo": [1, 2, 3]}) + >>> zip(d.keys(), d.listvalues()) == d.lists() + True + """ + return dict.values(self) + + def copy(self): + """Return a shallow copy of this object.""" + return self.__class__(self) + + def deepcopy(self, memo=None): + """Return a deep copy of this object.""" + return self.__class__(deepcopy(self.to_dict(flat=False), memo)) + + def to_dict(self, flat=True): + """Return the contents as regular dict. If `flat` is `True` the + returned dict will only have the first item present, if `flat` is + `False` all values will be returned as lists. + + :param flat: If set to `False` the dict returned will have lists + with all the values in it. Otherwise it will only + contain the first value for each key. + :return: a :class:`dict` + """ + if flat: + return dict(self.items()) + return dict(self.lists()) + + def update(self, mapping): + """update() extends rather than replaces existing key lists: + + >>> a = MultiDict({'x': 1}) + >>> b = MultiDict({'x': 2, 'y': 3}) + >>> a.update(b) + >>> a + MultiDict([('y', 3), ('x', 1), ('x', 2)]) + + If the value list for a key in ``other_dict`` is empty, no new values + will be added to the dict and the key will not be created: + + >>> x = {'empty_list': []} + >>> y = MultiDict() + >>> y.update(x) + >>> y + MultiDict([]) + """ + for key, value in iter_multi_items(mapping): + MultiDict.add(self, key, value) + + def pop(self, key, default=_missing): + """Pop the first item for a list on the dict. Afterwards the + key is removed from the dict, so additional values are discarded: + + >>> d = MultiDict({"foo": [1, 2, 3]}) + >>> d.pop("foo") + 1 + >>> "foo" in d + False + + :param key: the key to pop. + :param default: if provided the value to return if the key was + not in the dictionary. + """ + try: + lst = dict.pop(self, key) + + if len(lst) == 0: + raise exceptions.BadRequestKeyError(key) + + return lst[0] + except KeyError: + if default is not _missing: + return default + + raise exceptions.BadRequestKeyError(key) from None + + def popitem(self): + """Pop an item from the dict.""" + try: + item = dict.popitem(self) + + if len(item[1]) == 0: + raise exceptions.BadRequestKeyError(item[0]) + + return (item[0], item[1][0]) + except KeyError as e: + raise exceptions.BadRequestKeyError(e.args[0]) from None + + def poplist(self, key): + """Pop the list for a key from the dict. If the key is not in the dict + an empty list is returned. + + .. versionchanged:: 0.5 + If the key does no longer exist a list is returned instead of + raising an error. + """ + return dict.pop(self, key, []) + + def popitemlist(self): + """Pop a ``(key, list)`` tuple from the dict.""" + try: + return dict.popitem(self) + except KeyError as e: + raise exceptions.BadRequestKeyError(e.args[0]) from None + + def __copy__(self): + return self.copy() + + def __deepcopy__(self, memo): + return self.deepcopy(memo=memo) + + def __repr__(self): + return f"{type(self).__name__}({list(self.items(multi=True))!r})" + + +class _omd_bucket: + """Wraps values in the :class:`OrderedMultiDict`. This makes it + possible to keep an order over multiple different keys. It requires + a lot of extra memory and slows down access a lot, but makes it + possible to access elements in O(1) and iterate in O(n). + """ + + __slots__ = ("prev", "key", "value", "next") + + def __init__(self, omd, key, value): + self.prev = omd._last_bucket + self.key = key + self.value = value + self.next = None + + if omd._first_bucket is None: + omd._first_bucket = self + if omd._last_bucket is not None: + omd._last_bucket.next = self + omd._last_bucket = self + + def unlink(self, omd): + if self.prev: + self.prev.next = self.next + if self.next: + self.next.prev = self.prev + if omd._first_bucket is self: + omd._first_bucket = self.next + if omd._last_bucket is self: + omd._last_bucket = self.prev + + +class OrderedMultiDict(MultiDict): + """Works like a regular :class:`MultiDict` but preserves the + order of the fields. To convert the ordered multi dict into a + list you can use the :meth:`items` method and pass it ``multi=True``. + + In general an :class:`OrderedMultiDict` is an order of magnitude + slower than a :class:`MultiDict`. + + .. admonition:: note + + Due to a limitation in Python you cannot convert an ordered + multi dict into a regular dict by using ``dict(multidict)``. + Instead you have to use the :meth:`to_dict` method, otherwise + the internal bucket objects are exposed. + """ + + def __init__(self, mapping=None): + dict.__init__(self) + self._first_bucket = self._last_bucket = None + if mapping is not None: + OrderedMultiDict.update(self, mapping) + + def __eq__(self, other): + if not isinstance(other, MultiDict): + return NotImplemented + if isinstance(other, OrderedMultiDict): + iter1 = iter(self.items(multi=True)) + iter2 = iter(other.items(multi=True)) + try: + for k1, v1 in iter1: + k2, v2 = next(iter2) + if k1 != k2 or v1 != v2: + return False + except StopIteration: + return False + try: + next(iter2) + except StopIteration: + return True + return False + if len(self) != len(other): + return False + for key, values in self.lists(): + if other.getlist(key) != values: + return False + return True + + __hash__ = None + + def __reduce_ex__(self, protocol): + return type(self), (list(self.items(multi=True)),) + + def __getstate__(self): + return list(self.items(multi=True)) + + def __setstate__(self, values): + dict.clear(self) + for key, value in values: + self.add(key, value) + + def __getitem__(self, key): + if key in self: + return dict.__getitem__(self, key)[0].value + raise exceptions.BadRequestKeyError(key) + + def __setitem__(self, key, value): + self.poplist(key) + self.add(key, value) + + def __delitem__(self, key): + self.pop(key) + + def keys(self): + return (key for key, value in self.items()) + + def __iter__(self): + return iter(self.keys()) + + def values(self): + return (value for key, value in self.items()) + + def items(self, multi=False): + ptr = self._first_bucket + if multi: + while ptr is not None: + yield ptr.key, ptr.value + ptr = ptr.next + else: + returned_keys = set() + while ptr is not None: + if ptr.key not in returned_keys: + returned_keys.add(ptr.key) + yield ptr.key, ptr.value + ptr = ptr.next + + def lists(self): + returned_keys = set() + ptr = self._first_bucket + while ptr is not None: + if ptr.key not in returned_keys: + yield ptr.key, self.getlist(ptr.key) + returned_keys.add(ptr.key) + ptr = ptr.next + + def listvalues(self): + for _key, values in self.lists(): + yield values + + def add(self, key, value): + dict.setdefault(self, key, []).append(_omd_bucket(self, key, value)) + + def getlist(self, key, type=None): + try: + rv = dict.__getitem__(self, key) + except KeyError: + return [] + if type is None: + return [x.value for x in rv] + result = [] + for item in rv: + try: + result.append(type(item.value)) + except ValueError: + pass + return result + + def setlist(self, key, new_list): + self.poplist(key) + for value in new_list: + self.add(key, value) + + def setlistdefault(self, key, default_list=None): + raise TypeError("setlistdefault is unsupported for ordered multi dicts") + + def update(self, mapping): + for key, value in iter_multi_items(mapping): + OrderedMultiDict.add(self, key, value) + + def poplist(self, key): + buckets = dict.pop(self, key, ()) + for bucket in buckets: + bucket.unlink(self) + return [x.value for x in buckets] + + def pop(self, key, default=_missing): + try: + buckets = dict.pop(self, key) + except KeyError: + if default is not _missing: + return default + + raise exceptions.BadRequestKeyError(key) from None + + for bucket in buckets: + bucket.unlink(self) + + return buckets[0].value + + def popitem(self): + try: + key, buckets = dict.popitem(self) + except KeyError as e: + raise exceptions.BadRequestKeyError(e.args[0]) from None + + for bucket in buckets: + bucket.unlink(self) + + return key, buckets[0].value + + def popitemlist(self): + try: + key, buckets = dict.popitem(self) + except KeyError as e: + raise exceptions.BadRequestKeyError(e.args[0]) from None + + for bucket in buckets: + bucket.unlink(self) + + return key, [x.value for x in buckets] + + +class CombinedMultiDict(ImmutableMultiDictMixin, MultiDict): + """A read only :class:`MultiDict` that you can pass multiple :class:`MultiDict` + instances as sequence and it will combine the return values of all wrapped + dicts: + + >>> from werkzeug.datastructures import CombinedMultiDict, MultiDict + >>> post = MultiDict([('foo', 'bar')]) + >>> get = MultiDict([('blub', 'blah')]) + >>> combined = CombinedMultiDict([get, post]) + >>> combined['foo'] + 'bar' + >>> combined['blub'] + 'blah' + + This works for all read operations and will raise a `TypeError` for + methods that usually change data which isn't possible. + + From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a + subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will + render a page for a ``400 BAD REQUEST`` if caught in a catch-all for HTTP + exceptions. + """ + + def __reduce_ex__(self, protocol): + return type(self), (self.dicts,) + + def __init__(self, dicts=None): + self.dicts = list(dicts) or [] + + @classmethod + def fromkeys(cls, keys, value=None): + raise TypeError(f"cannot create {cls.__name__!r} instances by fromkeys") + + def __getitem__(self, key): + for d in self.dicts: + if key in d: + return d[key] + raise exceptions.BadRequestKeyError(key) + + def get(self, key, default=None, type=None): + for d in self.dicts: + if key in d: + if type is not None: + try: + return type(d[key]) + except ValueError: + continue + return d[key] + return default + + def getlist(self, key, type=None): + rv = [] + for d in self.dicts: + rv.extend(d.getlist(key, type)) + return rv + + def _keys_impl(self): + """This function exists so __len__ can be implemented more efficiently, + saving one list creation from an iterator. + """ + rv = set() + rv.update(*self.dicts) + return rv + + def keys(self): + return self._keys_impl() + + def __iter__(self): + return iter(self.keys()) + + def items(self, multi=False): + found = set() + for d in self.dicts: + for key, value in d.items(multi): + if multi: + yield key, value + elif key not in found: + found.add(key) + yield key, value + + def values(self): + for _key, value in self.items(): + yield value + + def lists(self): + rv = {} + for d in self.dicts: + for key, values in d.lists(): + rv.setdefault(key, []).extend(values) + return list(rv.items()) + + def listvalues(self): + return (x[1] for x in self.lists()) + + def copy(self): + """Return a shallow mutable copy of this object. + + This returns a :class:`MultiDict` representing the data at the + time of copying. The copy will no longer reflect changes to the + wrapped dicts. + + .. versionchanged:: 0.15 + Return a mutable :class:`MultiDict`. + """ + return MultiDict(self) + + def to_dict(self, flat=True): + """Return the contents as regular dict. If `flat` is `True` the + returned dict will only have the first item present, if `flat` is + `False` all values will be returned as lists. + + :param flat: If set to `False` the dict returned will have lists + with all the values in it. Otherwise it will only + contain the first item for each key. + :return: a :class:`dict` + """ + if flat: + return dict(self.items()) + + return dict(self.lists()) + + def __len__(self): + return len(self._keys_impl()) + + def __contains__(self, key): + for d in self.dicts: + if key in d: + return True + return False + + def __repr__(self): + return f"{type(self).__name__}({self.dicts!r})" + + +class ImmutableDict(ImmutableDictMixin, dict): + """An immutable :class:`dict`. + + .. versionadded:: 0.5 + """ + + def __repr__(self): + return f"{type(self).__name__}({dict.__repr__(self)})" + + def copy(self): + """Return a shallow mutable copy of this object. Keep in mind that + the standard library's :func:`copy` function is a no-op for this class + like for any other python immutable type (eg: :class:`tuple`). + """ + return dict(self) + + def __copy__(self): + return self + + +class ImmutableMultiDict(ImmutableMultiDictMixin, MultiDict): + """An immutable :class:`MultiDict`. + + .. versionadded:: 0.5 + """ + + def copy(self): + """Return a shallow mutable copy of this object. Keep in mind that + the standard library's :func:`copy` function is a no-op for this class + like for any other python immutable type (eg: :class:`tuple`). + """ + return MultiDict(self) + + def __copy__(self): + return self + + +class ImmutableOrderedMultiDict(ImmutableMultiDictMixin, OrderedMultiDict): + """An immutable :class:`OrderedMultiDict`. + + .. versionadded:: 0.6 + """ + + def _iter_hashitems(self): + return enumerate(self.items(multi=True)) + + def copy(self): + """Return a shallow mutable copy of this object. Keep in mind that + the standard library's :func:`copy` function is a no-op for this class + like for any other python immutable type (eg: :class:`tuple`). + """ + return OrderedMultiDict(self) + + def __copy__(self): + return self + + +class CallbackDict(UpdateDictMixin, dict): + """A dict that calls a function passed every time something is changed. + The function is passed the dict instance. + """ + + def __init__(self, initial=None, on_update=None): + dict.__init__(self, initial or ()) + self.on_update = on_update + + def __repr__(self): + return f"<{type(self).__name__} {dict.__repr__(self)}>" + + +class HeaderSet(MutableSet): + """Similar to the :class:`ETags` class this implements a set-like structure. + Unlike :class:`ETags` this is case insensitive and used for vary, allow, and + content-language headers. + + If not constructed using the :func:`parse_set_header` function the + instantiation works like this: + + >>> hs = HeaderSet(['foo', 'bar', 'baz']) + >>> hs + HeaderSet(['foo', 'bar', 'baz']) + """ + + def __init__(self, headers=None, on_update=None): + self._headers = list(headers or ()) + self._set = {x.lower() for x in self._headers} + self.on_update = on_update + + def add(self, header): + """Add a new header to the set.""" + self.update((header,)) + + def remove(self, header): + """Remove a header from the set. This raises an :exc:`KeyError` if the + header is not in the set. + + .. versionchanged:: 0.5 + In older versions a :exc:`IndexError` was raised instead of a + :exc:`KeyError` if the object was missing. + + :param header: the header to be removed. + """ + key = header.lower() + if key not in self._set: + raise KeyError(header) + self._set.remove(key) + for idx, key in enumerate(self._headers): + if key.lower() == header: + del self._headers[idx] + break + if self.on_update is not None: + self.on_update(self) + + def update(self, iterable): + """Add all the headers from the iterable to the set. + + :param iterable: updates the set with the items from the iterable. + """ + inserted_any = False + for header in iterable: + key = header.lower() + if key not in self._set: + self._headers.append(header) + self._set.add(key) + inserted_any = True + if inserted_any and self.on_update is not None: + self.on_update(self) + + def discard(self, header): + """Like :meth:`remove` but ignores errors. + + :param header: the header to be discarded. + """ + try: + self.remove(header) + except KeyError: + pass + + def find(self, header): + """Return the index of the header in the set or return -1 if not found. + + :param header: the header to be looked up. + """ + header = header.lower() + for idx, item in enumerate(self._headers): + if item.lower() == header: + return idx + return -1 + + def index(self, header): + """Return the index of the header in the set or raise an + :exc:`IndexError`. + + :param header: the header to be looked up. + """ + rv = self.find(header) + if rv < 0: + raise IndexError(header) + return rv + + def clear(self): + """Clear the set.""" + self._set.clear() + del self._headers[:] + if self.on_update is not None: + self.on_update(self) + + def as_set(self, preserve_casing=False): + """Return the set as real python set type. When calling this, all + the items are converted to lowercase and the ordering is lost. + + :param preserve_casing: if set to `True` the items in the set returned + will have the original case like in the + :class:`HeaderSet`, otherwise they will + be lowercase. + """ + if preserve_casing: + return set(self._headers) + return set(self._set) + + def to_header(self): + """Convert the header set into an HTTP header string.""" + return ", ".join(map(http.quote_header_value, self._headers)) + + def __getitem__(self, idx): + return self._headers[idx] + + def __delitem__(self, idx): + rv = self._headers.pop(idx) + self._set.remove(rv.lower()) + if self.on_update is not None: + self.on_update(self) + + def __setitem__(self, idx, value): + old = self._headers[idx] + self._set.remove(old.lower()) + self._headers[idx] = value + self._set.add(value.lower()) + if self.on_update is not None: + self.on_update(self) + + def __contains__(self, header): + return header.lower() in self._set + + def __len__(self): + return len(self._set) + + def __iter__(self): + return iter(self._headers) + + def __bool__(self): + return bool(self._set) + + def __str__(self): + return self.to_header() + + def __repr__(self): + return f"{type(self).__name__}({self._headers!r})" + + +# circular dependencies +from .. import http diff --git a/MLPY/Lib/site-packages/werkzeug/datastructures/structures.pyi b/MLPY/Lib/site-packages/werkzeug/datastructures/structures.pyi new file mode 100644 index 0000000000000000000000000000000000000000..7086ddae1fb8b0aaf8de176b0c6d66b2598721ed --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/datastructures/structures.pyi @@ -0,0 +1,206 @@ +from collections.abc import Callable +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Mapping +from typing import Any +from typing import Generic +from typing import Literal +from typing import NoReturn +from typing import overload +from typing import TypeVar + +from .mixins import ImmutableDictMixin +from .mixins import ImmutableListMixin +from .mixins import ImmutableMultiDictMixin +from .mixins import UpdateDictMixin + +D = TypeVar("D") +K = TypeVar("K") +T = TypeVar("T") +V = TypeVar("V") +_CD = TypeVar("_CD", bound="CallbackDict[Any, Any]") + +def is_immutable(self: object) -> NoReturn: ... +def iter_multi_items( + mapping: Mapping[K, V | Iterable[V]] | Iterable[tuple[K, V]], +) -> Iterator[tuple[K, V]]: ... + +class ImmutableList(ImmutableListMixin[V]): ... + +class TypeConversionDict(dict[K, V]): + @overload + def get(self, key: K, default: None = ..., type: None = ...) -> V | None: ... + @overload + def get(self, key: K, default: D, type: None = ...) -> D | V: ... + @overload + def get(self, key: K, default: D, type: Callable[[V], T]) -> D | T: ... + @overload + def get(self, key: K, type: Callable[[V], T]) -> T | None: ... + +class ImmutableTypeConversionDict(ImmutableDictMixin[K, V], TypeConversionDict[K, V]): + def copy(self) -> TypeConversionDict[K, V]: ... + def __copy__(self) -> ImmutableTypeConversionDict[K, V]: ... + +class MultiDict(TypeConversionDict[K, V]): + def __init__( + self, + mapping: Mapping[K, Iterable[V] | V] | Iterable[tuple[K, V]] | None = None, + ) -> None: ... + def __getitem__(self, item: K) -> V: ... + def __setitem__(self, key: K, value: V) -> None: ... + def add(self, key: K, value: V) -> None: ... + @overload + def getlist(self, key: K) -> list[V]: ... + @overload + def getlist(self, key: K, type: Callable[[V], T] = ...) -> list[T]: ... + def setlist(self, key: K, new_list: Iterable[V]) -> None: ... + def setdefault(self, key: K, default: V | None = None) -> V: ... + def setlistdefault( + self, key: K, default_list: Iterable[V] | None = None + ) -> list[V]: ... + def items(self, multi: bool = False) -> Iterator[tuple[K, V]]: ... # type: ignore + def lists(self) -> Iterator[tuple[K, list[V]]]: ... + def values(self) -> Iterator[V]: ... # type: ignore + def listvalues(self) -> Iterator[list[V]]: ... + def copy(self) -> MultiDict[K, V]: ... + def deepcopy(self, memo: Any = None) -> MultiDict[K, V]: ... + @overload + def to_dict(self) -> dict[K, V]: ... + @overload + def to_dict(self, flat: Literal[False]) -> dict[K, list[V]]: ... + def update( # type: ignore + self, mapping: Mapping[K, Iterable[V] | V] | Iterable[tuple[K, V]] + ) -> None: ... + @overload + def pop(self, key: K) -> V: ... + @overload + def pop(self, key: K, default: V | T = ...) -> V | T: ... + def popitem(self) -> tuple[K, V]: ... + def poplist(self, key: K) -> list[V]: ... + def popitemlist(self) -> tuple[K, list[V]]: ... + def __copy__(self) -> MultiDict[K, V]: ... + def __deepcopy__(self, memo: Any) -> MultiDict[K, V]: ... + +class _omd_bucket(Generic[K, V]): + prev: _omd_bucket[K, V] | None + next: _omd_bucket[K, V] | None + key: K + value: V + def __init__(self, omd: OrderedMultiDict[K, V], key: K, value: V) -> None: ... + def unlink(self, omd: OrderedMultiDict[K, V]) -> None: ... + +class OrderedMultiDict(MultiDict[K, V]): + _first_bucket: _omd_bucket[K, V] | None + _last_bucket: _omd_bucket[K, V] | None + def __init__(self, mapping: Mapping[K, V] | None = None) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __getitem__(self, key: K) -> V: ... + def __setitem__(self, key: K, value: V) -> None: ... + def __delitem__(self, key: K) -> None: ... + def keys(self) -> Iterator[K]: ... # type: ignore + def __iter__(self) -> Iterator[K]: ... + def values(self) -> Iterator[V]: ... # type: ignore + def items(self, multi: bool = False) -> Iterator[tuple[K, V]]: ... # type: ignore + def lists(self) -> Iterator[tuple[K, list[V]]]: ... + def listvalues(self) -> Iterator[list[V]]: ... + def add(self, key: K, value: V) -> None: ... + @overload + def getlist(self, key: K) -> list[V]: ... + @overload + def getlist(self, key: K, type: Callable[[V], T] = ...) -> list[T]: ... + def setlist(self, key: K, new_list: Iterable[V]) -> None: ... + def setlistdefault( + self, key: K, default_list: Iterable[V] | None = None + ) -> list[V]: ... + def update( # type: ignore + self, mapping: Mapping[K, V] | Iterable[tuple[K, V]] + ) -> None: ... + def poplist(self, key: K) -> list[V]: ... + @overload + def pop(self, key: K) -> V: ... + @overload + def pop(self, key: K, default: V | T = ...) -> V | T: ... + def popitem(self) -> tuple[K, V]: ... + def popitemlist(self) -> tuple[K, list[V]]: ... + +class CombinedMultiDict(ImmutableMultiDictMixin[K, V], MultiDict[K, V]): # type: ignore + dicts: list[MultiDict[K, V]] + def __init__(self, dicts: Iterable[MultiDict[K, V]] | None) -> None: ... + @classmethod + def fromkeys(cls, keys: Any, value: Any = None) -> NoReturn: ... + def __getitem__(self, key: K) -> V: ... + @overload # type: ignore + def get(self, key: K) -> V | None: ... + @overload + def get(self, key: K, default: V | T = ...) -> V | T: ... + @overload + def get( + self, key: K, default: T | None = None, type: Callable[[V], T] = ... + ) -> T | None: ... + @overload + def getlist(self, key: K) -> list[V]: ... + @overload + def getlist(self, key: K, type: Callable[[V], T] = ...) -> list[T]: ... + def _keys_impl(self) -> set[K]: ... + def keys(self) -> set[K]: ... # type: ignore + def __iter__(self) -> set[K]: ... # type: ignore + def items(self, multi: bool = False) -> Iterator[tuple[K, V]]: ... # type: ignore + def values(self) -> Iterator[V]: ... # type: ignore + def lists(self) -> Iterator[tuple[K, list[V]]]: ... + def listvalues(self) -> Iterator[list[V]]: ... + def copy(self) -> MultiDict[K, V]: ... + @overload + def to_dict(self) -> dict[K, V]: ... + @overload + def to_dict(self, flat: Literal[False]) -> dict[K, list[V]]: ... + def __contains__(self, key: K) -> bool: ... # type: ignore + def has_key(self, key: K) -> bool: ... + +class ImmutableDict(ImmutableDictMixin[K, V], dict[K, V]): + def copy(self) -> dict[K, V]: ... + def __copy__(self) -> ImmutableDict[K, V]: ... + +class ImmutableMultiDict( # type: ignore + ImmutableMultiDictMixin[K, V], MultiDict[K, V] +): + def copy(self) -> MultiDict[K, V]: ... + def __copy__(self) -> ImmutableMultiDict[K, V]: ... + +class ImmutableOrderedMultiDict( # type: ignore + ImmutableMultiDictMixin[K, V], OrderedMultiDict[K, V] +): + def _iter_hashitems(self) -> Iterator[tuple[int, tuple[K, V]]]: ... + def copy(self) -> OrderedMultiDict[K, V]: ... + def __copy__(self) -> ImmutableOrderedMultiDict[K, V]: ... + +class CallbackDict(UpdateDictMixin[K, V], dict[K, V]): + def __init__( + self, + initial: Mapping[K, V] | Iterable[tuple[K, V]] | None = None, + on_update: Callable[[_CD], None] | None = None, + ) -> None: ... + +class HeaderSet(set[str]): + _headers: list[str] + _set: set[str] + on_update: Callable[[HeaderSet], None] | None + def __init__( + self, + headers: Iterable[str] | None = None, + on_update: Callable[[HeaderSet], None] | None = None, + ) -> None: ... + def add(self, header: str) -> None: ... + def remove(self, header: str) -> None: ... + def update(self, iterable: Iterable[str]) -> None: ... # type: ignore + def discard(self, header: str) -> None: ... + def find(self, header: str) -> int: ... + def index(self, header: str) -> int: ... + def clear(self) -> None: ... + def as_set(self, preserve_casing: bool = False) -> set[str]: ... + def to_header(self) -> str: ... + def __getitem__(self, idx: int) -> str: ... + def __delitem__(self, idx: int) -> None: ... + def __setitem__(self, idx: int, value: str) -> None: ... + def __contains__(self, header: str) -> bool: ... # type: ignore + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[str]: ... diff --git a/MLPY/Lib/site-packages/werkzeug/debug/__init__.py b/MLPY/Lib/site-packages/werkzeug/debug/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6bef30fbca51ed244bf897c0492b614b5237c899 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/debug/__init__.py @@ -0,0 +1,560 @@ +from __future__ import annotations + +import getpass +import hashlib +import json +import os +import pkgutil +import re +import sys +import time +import typing as t +import uuid +from contextlib import ExitStack +from io import BytesIO +from itertools import chain +from os.path import basename +from os.path import join +from zlib import adler32 + +from .._internal import _log +from ..exceptions import NotFound +from ..exceptions import SecurityError +from ..http import parse_cookie +from ..sansio.utils import host_is_trusted +from ..security import gen_salt +from ..utils import send_file +from ..wrappers.request import Request +from ..wrappers.response import Response +from .console import Console +from .tbtools import DebugFrameSummary +from .tbtools import DebugTraceback +from .tbtools import render_console_html + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + +# A week +PIN_TIME = 60 * 60 * 24 * 7 + + +def hash_pin(pin: str) -> str: + return hashlib.sha1(f"{pin} added salt".encode("utf-8", "replace")).hexdigest()[:12] + + +_machine_id: str | bytes | None = None + + +def get_machine_id() -> str | bytes | None: + global _machine_id + + if _machine_id is not None: + return _machine_id + + def _generate() -> str | bytes | None: + linux = b"" + + # machine-id is stable across boots, boot_id is not. + for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id": + try: + with open(filename, "rb") as f: + value = f.readline().strip() + except OSError: + continue + + if value: + linux += value + break + + # Containers share the same machine id, add some cgroup + # information. This is used outside containers too but should be + # relatively stable across boots. + try: + with open("/proc/self/cgroup", "rb") as f: + linux += f.readline().strip().rpartition(b"/")[2] + except OSError: + pass + + if linux: + return linux + + # On OS X, use ioreg to get the computer's serial number. + try: + # subprocess may not be available, e.g. Google App Engine + # https://github.com/pallets/werkzeug/issues/925 + from subprocess import PIPE + from subprocess import Popen + + dump = Popen( + ["ioreg", "-c", "IOPlatformExpertDevice", "-d", "2"], stdout=PIPE + ).communicate()[0] + match = re.search(b'"serial-number" = <([^>]+)', dump) + + if match is not None: + return match.group(1) + except (OSError, ImportError): + pass + + # On Windows, use winreg to get the machine guid. + if sys.platform == "win32": + import winreg + + try: + with winreg.OpenKey( + winreg.HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Cryptography", + 0, + winreg.KEY_READ | winreg.KEY_WOW64_64KEY, + ) as rk: + guid: str | bytes + guid_type: int + guid, guid_type = winreg.QueryValueEx(rk, "MachineGuid") + + if guid_type == winreg.REG_SZ: + return guid.encode() + + return guid + except OSError: + pass + + return None + + _machine_id = _generate() + return _machine_id + + +class _ConsoleFrame: + """Helper class so that we can reuse the frame console code for the + standalone console. + """ + + def __init__(self, namespace: dict[str, t.Any]): + self.console = Console(namespace) + self.id = 0 + + def eval(self, code: str) -> t.Any: + return self.console.eval(code) + + +def get_pin_and_cookie_name( + app: WSGIApplication, +) -> tuple[str, str] | tuple[None, None]: + """Given an application object this returns a semi-stable 9 digit pin + code and a random key. The hope is that this is stable between + restarts to not make debugging particularly frustrating. If the pin + was forcefully disabled this returns `None`. + + Second item in the resulting tuple is the cookie name for remembering. + """ + pin = os.environ.get("WERKZEUG_DEBUG_PIN") + rv = None + num = None + + # Pin was explicitly disabled + if pin == "off": + return None, None + + # Pin was provided explicitly + if pin is not None and pin.replace("-", "").isdecimal(): + # If there are separators in the pin, return it directly + if "-" in pin: + rv = pin + else: + num = pin + + modname = getattr(app, "__module__", t.cast(object, app).__class__.__module__) + username: str | None + + try: + # getuser imports the pwd module, which does not exist in Google + # App Engine. It may also raise a KeyError if the UID does not + # have a username, such as in Docker. + username = getpass.getuser() + except (ImportError, KeyError): + username = None + + mod = sys.modules.get(modname) + + # This information only exists to make the cookie unique on the + # computer, not as a security feature. + probably_public_bits = [ + username, + modname, + getattr(app, "__name__", type(app).__name__), + getattr(mod, "__file__", None), + ] + + # This information is here to make it harder for an attacker to + # guess the cookie name. They are unlikely to be contained anywhere + # within the unauthenticated debug page. + private_bits = [str(uuid.getnode()), get_machine_id()] + + h = hashlib.sha1() + for bit in chain(probably_public_bits, private_bits): + if not bit: + continue + if isinstance(bit, str): + bit = bit.encode() + h.update(bit) + h.update(b"cookiesalt") + + cookie_name = f"__wzd{h.hexdigest()[:20]}" + + # If we need to generate a pin we salt it a bit more so that we don't + # end up with the same value and generate out 9 digits + if num is None: + h.update(b"pinsalt") + num = f"{int(h.hexdigest(), 16):09d}"[:9] + + # Format the pincode in groups of digits for easier remembering if + # we don't have a result yet. + if rv is None: + for group_size in 5, 4, 3: + if len(num) % group_size == 0: + rv = "-".join( + num[x : x + group_size].rjust(group_size, "0") + for x in range(0, len(num), group_size) + ) + break + else: + rv = num + + return rv, cookie_name + + +class DebuggedApplication: + """Enables debugging support for a given application:: + + from werkzeug.debug import DebuggedApplication + from myapp import app + app = DebuggedApplication(app, evalex=True) + + The ``evalex`` argument allows evaluating expressions in any frame + of a traceback. This works by preserving each frame with its local + state. Some state, such as context globals, cannot be restored with + the frame by default. When ``evalex`` is enabled, + ``environ["werkzeug.debug.preserve_context"]`` will be a callable + that takes a context manager, and can be called multiple times. + Each context manager will be entered before evaluating code in the + frame, then exited again, so they can perform setup and cleanup for + each call. + + :param app: the WSGI application to run debugged. + :param evalex: enable exception evaluation feature (interactive + debugging). This requires a non-forking server. + :param request_key: The key that points to the request object in this + environment. This parameter is ignored in current + versions. + :param console_path: the URL for a general purpose console. + :param console_init_func: the function that is executed before starting + the general purpose console. The return value + is used as initial namespace. + :param show_hidden_frames: by default hidden traceback frames are skipped. + You can show them by setting this parameter + to `True`. + :param pin_security: can be used to disable the pin based security system. + :param pin_logging: enables the logging of the pin system. + + .. versionchanged:: 2.2 + Added the ``werkzeug.debug.preserve_context`` environ key. + """ + + _pin: str + _pin_cookie: str + + def __init__( + self, + app: WSGIApplication, + evalex: bool = False, + request_key: str = "werkzeug.request", + console_path: str = "/console", + console_init_func: t.Callable[[], dict[str, t.Any]] | None = None, + show_hidden_frames: bool = False, + pin_security: bool = True, + pin_logging: bool = True, + ) -> None: + if not console_init_func: + console_init_func = None + self.app = app + self.evalex = evalex + self.frames: dict[int, DebugFrameSummary | _ConsoleFrame] = {} + self.frame_contexts: dict[int, list[t.ContextManager[None]]] = {} + self.request_key = request_key + self.console_path = console_path + self.console_init_func = console_init_func + self.show_hidden_frames = show_hidden_frames + self.secret = gen_salt(20) + self._failed_pin_auth = 0 + + self.pin_logging = pin_logging + if pin_security: + # Print out the pin for the debugger on standard out. + if os.environ.get("WERKZEUG_RUN_MAIN") == "true" and pin_logging: + _log("warning", " * Debugger is active!") + if self.pin is None: + _log("warning", " * Debugger PIN disabled. DEBUGGER UNSECURED!") + else: + _log("info", " * Debugger PIN: %s", self.pin) + else: + self.pin = None + + self.trusted_hosts: list[str] = [".localhost", "127.0.0.1"] + """List of domains to allow requests to the debugger from. A leading dot + allows all subdomains. This only allows ``".localhost"`` domains by + default. + + .. versionadded:: 3.0.3 + """ + + @property + def pin(self) -> str | None: + if not hasattr(self, "_pin"): + pin_cookie = get_pin_and_cookie_name(self.app) + self._pin, self._pin_cookie = pin_cookie # type: ignore + return self._pin + + @pin.setter + def pin(self, value: str) -> None: + self._pin = value + + @property + def pin_cookie_name(self) -> str: + """The name of the pin cookie.""" + if not hasattr(self, "_pin_cookie"): + pin_cookie = get_pin_and_cookie_name(self.app) + self._pin, self._pin_cookie = pin_cookie # type: ignore + return self._pin_cookie + + def debug_application( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterator[bytes]: + """Run the application and conserve the traceback frames.""" + contexts: list[t.ContextManager[t.Any]] = [] + + if self.evalex: + environ["werkzeug.debug.preserve_context"] = contexts.append + + app_iter = None + try: + app_iter = self.app(environ, start_response) + yield from app_iter + if hasattr(app_iter, "close"): + app_iter.close() + except Exception as e: + if hasattr(app_iter, "close"): + app_iter.close() # type: ignore + + tb = DebugTraceback(e, skip=1, hide=not self.show_hidden_frames) + + for frame in tb.all_frames: + self.frames[id(frame)] = frame + self.frame_contexts[id(frame)] = contexts + + is_trusted = bool(self.check_pin_trust(environ)) + html = tb.render_debugger_html( + evalex=self.evalex and self.check_host_trust(environ), + secret=self.secret, + evalex_trusted=is_trusted, + ) + response = Response(html, status=500, mimetype="text/html") + + try: + yield from response(environ, start_response) + except Exception: + # if we end up here there has been output but an error + # occurred. in that situation we can do nothing fancy any + # more, better log something into the error log and fall + # back gracefully. + environ["wsgi.errors"].write( + "Debugging middleware caught exception in streamed " + "response at a point where response headers were already " + "sent.\n" + ) + + environ["wsgi.errors"].write("".join(tb.render_traceback_text())) + + def execute_command( # type: ignore[return] + self, + request: Request, + command: str, + frame: DebugFrameSummary | _ConsoleFrame, + ) -> Response: + """Execute a command in a console.""" + if not self.check_host_trust(request.environ): + return SecurityError() # type: ignore[return-value] + + contexts = self.frame_contexts.get(id(frame), []) + + with ExitStack() as exit_stack: + for cm in contexts: + exit_stack.enter_context(cm) + + return Response(frame.eval(command), mimetype="text/html") + + def display_console(self, request: Request) -> Response: + """Display a standalone shell.""" + if not self.check_host_trust(request.environ): + return SecurityError() # type: ignore[return-value] + + if 0 not in self.frames: + if self.console_init_func is None: + ns = {} + else: + ns = dict(self.console_init_func()) + ns.setdefault("app", self.app) + self.frames[0] = _ConsoleFrame(ns) + is_trusted = bool(self.check_pin_trust(request.environ)) + return Response( + render_console_html(secret=self.secret, evalex_trusted=is_trusted), + mimetype="text/html", + ) + + def get_resource(self, request: Request, filename: str) -> Response: + """Return a static resource from the shared folder.""" + path = join("shared", basename(filename)) + + try: + data = pkgutil.get_data(__package__, path) + except OSError: + return NotFound() # type: ignore[return-value] + else: + if data is None: + return NotFound() # type: ignore[return-value] + + etag = str(adler32(data) & 0xFFFFFFFF) + return send_file( + BytesIO(data), request.environ, download_name=filename, etag=etag + ) + + def check_pin_trust(self, environ: WSGIEnvironment) -> bool | None: + """Checks if the request passed the pin test. This returns `True` if the + request is trusted on a pin/cookie basis and returns `False` if not. + Additionally if the cookie's stored pin hash is wrong it will return + `None` so that appropriate action can be taken. + """ + if self.pin is None: + return True + val = parse_cookie(environ).get(self.pin_cookie_name) + if not val or "|" not in val: + return False + ts_str, pin_hash = val.split("|", 1) + + try: + ts = int(ts_str) + except ValueError: + return False + + if pin_hash != hash_pin(self.pin): + return None + return (time.time() - PIN_TIME) < ts + + def check_host_trust(self, environ: WSGIEnvironment) -> bool: + return host_is_trusted(environ.get("HTTP_HOST"), self.trusted_hosts) + + def _fail_pin_auth(self) -> None: + time.sleep(5.0 if self._failed_pin_auth > 5 else 0.5) + self._failed_pin_auth += 1 + + def pin_auth(self, request: Request) -> Response: + """Authenticates with the pin.""" + if not self.check_host_trust(request.environ): + return SecurityError() # type: ignore[return-value] + + exhausted = False + auth = False + trust = self.check_pin_trust(request.environ) + pin = t.cast(str, self.pin) + + # If the trust return value is `None` it means that the cookie is + # set but the stored pin hash value is bad. This means that the + # pin was changed. In this case we count a bad auth and unset the + # cookie. This way it becomes harder to guess the cookie name + # instead of the pin as we still count up failures. + bad_cookie = False + if trust is None: + self._fail_pin_auth() + bad_cookie = True + + # If we're trusted, we're authenticated. + elif trust: + auth = True + + # If we failed too many times, then we're locked out. + elif self._failed_pin_auth > 10: + exhausted = True + + # Otherwise go through pin based authentication + else: + entered_pin = request.args["pin"] + + if entered_pin.strip().replace("-", "") == pin.replace("-", ""): + self._failed_pin_auth = 0 + auth = True + else: + self._fail_pin_auth() + + rv = Response( + json.dumps({"auth": auth, "exhausted": exhausted}), + mimetype="application/json", + ) + if auth: + rv.set_cookie( + self.pin_cookie_name, + f"{int(time.time())}|{hash_pin(pin)}", + httponly=True, + samesite="Strict", + secure=request.is_secure, + ) + elif bad_cookie: + rv.delete_cookie(self.pin_cookie_name) + return rv + + def log_pin_request(self, request: Request) -> Response: + """Log the pin if needed.""" + if not self.check_host_trust(request.environ): + return SecurityError() # type: ignore[return-value] + + if self.pin_logging and self.pin is not None: + _log( + "info", " * To enable the debugger you need to enter the security pin:" + ) + _log("info", " * Debugger pin code: %s", self.pin) + return Response("") + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + """Dispatch the requests.""" + # important: don't ever access a function here that reads the incoming + # form data! Otherwise the application won't have access to that data + # any more! + request = Request(environ) + response = self.debug_application + if request.args.get("__debugger__") == "yes": + cmd = request.args.get("cmd") + arg = request.args.get("f") + secret = request.args.get("s") + frame = self.frames.get(request.args.get("frm", type=int)) # type: ignore + if cmd == "resource" and arg: + response = self.get_resource(request, arg) # type: ignore + elif cmd == "pinauth" and secret == self.secret: + response = self.pin_auth(request) # type: ignore + elif cmd == "printpin" and secret == self.secret: + response = self.log_pin_request(request) # type: ignore + elif ( + self.evalex + and cmd is not None + and frame is not None + and self.secret == secret + and self.check_pin_trust(environ) + ): + response = self.execute_command(request, cmd, frame) # type: ignore + elif ( + self.evalex + and self.console_path is not None + and request.path == self.console_path + ): + response = self.display_console(request) # type: ignore + return response(environ, start_response) diff --git a/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/__init__.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b391044206e0846c5b833a0fe81d44c92ea8003f Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/__init__.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/console.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/console.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..20bffe0019d838fe58ea0e8275f7ff215e8e83da Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/console.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/repr.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/repr.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5e214110d2de25a337f9c6cd5c59bc3d6a4fdca Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/repr.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f97a877d516a6a5d9fa4bbff558b6f850d041368 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/debug/console.py b/MLPY/Lib/site-packages/werkzeug/debug/console.py new file mode 100644 index 0000000000000000000000000000000000000000..4e40475a5351ddccc0ef72746a159a6a75da63c2 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/debug/console.py @@ -0,0 +1,219 @@ +from __future__ import annotations + +import code +import sys +import typing as t +from contextvars import ContextVar +from types import CodeType + +from markupsafe import escape + +from .repr import debug_repr +from .repr import dump +from .repr import helper + +_stream: ContextVar[HTMLStringO] = ContextVar("werkzeug.debug.console.stream") +_ipy: ContextVar[_InteractiveConsole] = ContextVar("werkzeug.debug.console.ipy") + + +class HTMLStringO: + """A StringO version that HTML escapes on write.""" + + def __init__(self) -> None: + self._buffer: list[str] = [] + + def isatty(self) -> bool: + return False + + def close(self) -> None: + pass + + def flush(self) -> None: + pass + + def seek(self, n: int, mode: int = 0) -> None: + pass + + def readline(self) -> str: + if len(self._buffer) == 0: + return "" + ret = self._buffer[0] + del self._buffer[0] + return ret + + def reset(self) -> str: + val = "".join(self._buffer) + del self._buffer[:] + return val + + def _write(self, x: str) -> None: + self._buffer.append(x) + + def write(self, x: str) -> None: + self._write(escape(x)) + + def writelines(self, x: t.Iterable[str]) -> None: + self._write(escape("".join(x))) + + +class ThreadedStream: + """Thread-local wrapper for sys.stdout for the interactive console.""" + + @staticmethod + def push() -> None: + if not isinstance(sys.stdout, ThreadedStream): + sys.stdout = t.cast(t.TextIO, ThreadedStream()) + + _stream.set(HTMLStringO()) + + @staticmethod + def fetch() -> str: + try: + stream = _stream.get() + except LookupError: + return "" + + return stream.reset() + + @staticmethod + def displayhook(obj: object) -> None: + try: + stream = _stream.get() + except LookupError: + return _displayhook(obj) # type: ignore + + # stream._write bypasses escaping as debug_repr is + # already generating HTML for us. + if obj is not None: + _ipy.get().locals["_"] = obj + stream._write(debug_repr(obj)) + + def __setattr__(self, name: str, value: t.Any) -> None: + raise AttributeError(f"read only attribute {name}") + + def __dir__(self) -> list[str]: + return dir(sys.__stdout__) + + def __getattribute__(self, name: str) -> t.Any: + try: + stream = _stream.get() + except LookupError: + stream = sys.__stdout__ # type: ignore[assignment] + + return getattr(stream, name) + + def __repr__(self) -> str: + return repr(sys.__stdout__) + + +# add the threaded stream as display hook +_displayhook = sys.displayhook +sys.displayhook = ThreadedStream.displayhook + + +class _ConsoleLoader: + def __init__(self) -> None: + self._storage: dict[int, str] = {} + + def register(self, code: CodeType, source: str) -> None: + self._storage[id(code)] = source + # register code objects of wrapped functions too. + for var in code.co_consts: + if isinstance(var, CodeType): + self._storage[id(var)] = source + + def get_source_by_code(self, code: CodeType) -> str | None: + try: + return self._storage[id(code)] + except KeyError: + return None + + +class _InteractiveConsole(code.InteractiveInterpreter): + locals: dict[str, t.Any] + + def __init__(self, globals: dict[str, t.Any], locals: dict[str, t.Any]) -> None: + self.loader = _ConsoleLoader() + locals = { + **globals, + **locals, + "dump": dump, + "help": helper, + "__loader__": self.loader, + } + super().__init__(locals) + original_compile = self.compile + + def compile(source: str, filename: str, symbol: str) -> CodeType | None: + code = original_compile(source, filename, symbol) + + if code is not None: + self.loader.register(code, source) + + return code + + self.compile = compile # type: ignore[assignment] + self.more = False + self.buffer: list[str] = [] + + def runsource(self, source: str, **kwargs: t.Any) -> str: # type: ignore + source = f"{source.rstrip()}\n" + ThreadedStream.push() + prompt = "... " if self.more else ">>> " + try: + source_to_eval = "".join(self.buffer + [source]) + if super().runsource(source_to_eval, "", "single"): + self.more = True + self.buffer.append(source) + else: + self.more = False + del self.buffer[:] + finally: + output = ThreadedStream.fetch() + return f"{prompt}{escape(source)}{output}" + + def runcode(self, code: CodeType) -> None: + try: + exec(code, self.locals) + except Exception: + self.showtraceback() + + def showtraceback(self) -> None: + from .tbtools import DebugTraceback + + exc = t.cast(BaseException, sys.exc_info()[1]) + te = DebugTraceback(exc, skip=1) + sys.stdout._write(te.render_traceback_html()) # type: ignore + + def showsyntaxerror(self, filename: str | None = None) -> None: + from .tbtools import DebugTraceback + + exc = t.cast(BaseException, sys.exc_info()[1]) + te = DebugTraceback(exc, skip=4) + sys.stdout._write(te.render_traceback_html()) # type: ignore + + def write(self, data: str) -> None: + sys.stdout.write(data) + + +class Console: + """An interactive console.""" + + def __init__( + self, + globals: dict[str, t.Any] | None = None, + locals: dict[str, t.Any] | None = None, + ) -> None: + if locals is None: + locals = {} + if globals is None: + globals = {} + self._ipy = _InteractiveConsole(globals, locals) + + def eval(self, code: str) -> str: + _ipy.set(self._ipy) + old_sys_stdout = sys.stdout + try: + return self._ipy.runsource(code) + finally: + sys.stdout = old_sys_stdout diff --git a/MLPY/Lib/site-packages/werkzeug/debug/repr.py b/MLPY/Lib/site-packages/werkzeug/debug/repr.py new file mode 100644 index 0000000000000000000000000000000000000000..2bbd9d5467f1c7adea105b038ab817ad6171ddad --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/debug/repr.py @@ -0,0 +1,282 @@ +"""Object representations for debugging purposes. Unlike the default +repr, these expose more information and produce HTML instead of ASCII. + +Together with the CSS and JavaScript of the debugger this gives a +colorful and more compact output. +""" + +from __future__ import annotations + +import codecs +import re +import sys +import typing as t +from collections import deque +from traceback import format_exception_only + +from markupsafe import escape + +missing = object() +_paragraph_re = re.compile(r"(?:\r\n|\r|\n){2,}") +RegexType = type(_paragraph_re) + +HELP_HTML = """\ +
+

%(title)s

+
%(text)s
+
\ +""" +OBJECT_DUMP_HTML = """\ +
+

%(title)s

+ %(repr)s + %(items)s
+
\ +""" + + +def debug_repr(obj: object) -> str: + """Creates a debug repr of an object as HTML string.""" + return DebugReprGenerator().repr(obj) + + +def dump(obj: object = missing) -> None: + """Print the object details to stdout._write (for the interactive + console of the web debugger. + """ + gen = DebugReprGenerator() + if obj is missing: + rv = gen.dump_locals(sys._getframe(1).f_locals) + else: + rv = gen.dump_object(obj) + sys.stdout._write(rv) # type: ignore + + +class _Helper: + """Displays an HTML version of the normal help, for the interactive + debugger only because it requires a patched sys.stdout. + """ + + def __repr__(self) -> str: + return "Type help(object) for help about object." + + def __call__(self, topic: t.Any | None = None) -> None: + if topic is None: + sys.stdout._write(f"{self!r}") # type: ignore + return + import pydoc + + pydoc.help(topic) + rv = sys.stdout.reset() # type: ignore + paragraphs = _paragraph_re.split(rv) + if len(paragraphs) > 1: + title = paragraphs[0] + text = "\n\n".join(paragraphs[1:]) + else: + title = "Help" + text = paragraphs[0] + sys.stdout._write(HELP_HTML % {"title": title, "text": text}) # type: ignore + + +helper = _Helper() + + +def _add_subclass_info(inner: str, obj: object, base: type | tuple[type, ...]) -> str: + if isinstance(base, tuple): + for cls in base: + if type(obj) is cls: + return inner + elif type(obj) is base: + return inner + module = "" + if obj.__class__.__module__ not in ("__builtin__", "exceptions"): + module = f'{obj.__class__.__module__}.' + return f"{module}{type(obj).__name__}({inner})" + + +def _sequence_repr_maker( + left: str, right: str, base: type, limit: int = 8 +) -> t.Callable[[DebugReprGenerator, t.Iterable[t.Any], bool], str]: + def proxy(self: DebugReprGenerator, obj: t.Iterable[t.Any], recursive: bool) -> str: + if recursive: + return _add_subclass_info(f"{left}...{right}", obj, base) + buf = [left] + have_extended_section = False + for idx, item in enumerate(obj): + if idx: + buf.append(", ") + if idx == limit: + buf.append('') + have_extended_section = True + buf.append(self.repr(item)) + if have_extended_section: + buf.append("") + buf.append(right) + return _add_subclass_info("".join(buf), obj, base) + + return proxy + + +class DebugReprGenerator: + def __init__(self) -> None: + self._stack: list[t.Any] = [] + + list_repr = _sequence_repr_maker("[", "]", list) + tuple_repr = _sequence_repr_maker("(", ")", tuple) + set_repr = _sequence_repr_maker("set([", "])", set) + frozenset_repr = _sequence_repr_maker("frozenset([", "])", frozenset) + deque_repr = _sequence_repr_maker( + 'collections.deque([', "])", deque + ) + + def regex_repr(self, obj: t.Pattern[t.AnyStr]) -> str: + pattern = repr(obj.pattern) + pattern = codecs.decode(pattern, "unicode-escape", "ignore") + pattern = f"r{pattern}" + return f're.compile({pattern})' + + def string_repr(self, obj: str | bytes, limit: int = 70) -> str: + buf = [''] + r = repr(obj) + + # shorten the repr when the hidden part would be at least 3 chars + if len(r) - limit > 2: + buf.extend( + ( + escape(r[:limit]), + '', + escape(r[limit:]), + "", + ) + ) + else: + buf.append(escape(r)) + + buf.append("") + out = "".join(buf) + + # if the repr looks like a standard string, add subclass info if needed + if r[0] in "'\"" or (r[0] == "b" and r[1] in "'\""): + return _add_subclass_info(out, obj, (bytes, str)) + + # otherwise, assume the repr distinguishes the subclass already + return out + + def dict_repr( + self, + d: dict[int, None] | dict[str, int] | dict[str | int, int], + recursive: bool, + limit: int = 5, + ) -> str: + if recursive: + return _add_subclass_info("{...}", d, dict) + buf = ["{"] + have_extended_section = False + for idx, (key, value) in enumerate(d.items()): + if idx: + buf.append(", ") + if idx == limit - 1: + buf.append('') + have_extended_section = True + buf.append( + f'{self.repr(key)}:' + f' {self.repr(value)}' + ) + if have_extended_section: + buf.append("") + buf.append("}") + return _add_subclass_info("".join(buf), d, dict) + + def object_repr(self, obj: t.Any) -> str: + r = repr(obj) + return f'{escape(r)}' + + def dispatch_repr(self, obj: t.Any, recursive: bool) -> str: + if obj is helper: + return f'{helper!r}' + if isinstance(obj, (int, float, complex)): + return f'{obj!r}' + if isinstance(obj, str) or isinstance(obj, bytes): + return self.string_repr(obj) + if isinstance(obj, RegexType): + return self.regex_repr(obj) + if isinstance(obj, list): + return self.list_repr(obj, recursive) + if isinstance(obj, tuple): + return self.tuple_repr(obj, recursive) + if isinstance(obj, set): + return self.set_repr(obj, recursive) + if isinstance(obj, frozenset): + return self.frozenset_repr(obj, recursive) + if isinstance(obj, dict): + return self.dict_repr(obj, recursive) + if isinstance(obj, deque): + return self.deque_repr(obj, recursive) + return self.object_repr(obj) + + def fallback_repr(self) -> str: + try: + info = "".join(format_exception_only(*sys.exc_info()[:2])) + except Exception: + info = "?" + return ( + '' + f"<broken repr ({escape(info.strip())})>" + ) + + def repr(self, obj: object) -> str: + recursive = False + for item in self._stack: + if item is obj: + recursive = True + break + self._stack.append(obj) + try: + try: + return self.dispatch_repr(obj, recursive) + except Exception: + return self.fallback_repr() + finally: + self._stack.pop() + + def dump_object(self, obj: object) -> str: + repr = None + items: list[tuple[str, str]] | None = None + + if isinstance(obj, dict): + title = "Contents of" + items = [] + for key, value in obj.items(): + if not isinstance(key, str): + items = None + break + items.append((key, self.repr(value))) + if items is None: + items = [] + repr = self.repr(obj) + for key in dir(obj): + try: + items.append((key, self.repr(getattr(obj, key)))) + except Exception: + pass + title = "Details for" + title += f" {object.__repr__(obj)[1:-1]}" + return self.render_object_dump(items, title, repr) + + def dump_locals(self, d: dict[str, t.Any]) -> str: + items = [(key, self.repr(value)) for key, value in d.items()] + return self.render_object_dump(items, "Local variables in frame") + + def render_object_dump( + self, items: list[tuple[str, str]], title: str, repr: str | None = None + ) -> str: + html_items = [] + for key, value in items: + html_items.append(f"{escape(key)}
{value}
") + if not html_items: + html_items.append("Nothing") + return OBJECT_DUMP_HTML % { + "title": escape(title), + "repr": f"
{repr if repr else ''}
", + "items": "\n".join(html_items), + } diff --git a/MLPY/Lib/site-packages/werkzeug/debug/shared/ICON_LICENSE.md b/MLPY/Lib/site-packages/werkzeug/debug/shared/ICON_LICENSE.md new file mode 100644 index 0000000000000000000000000000000000000000..3bdbfc739ea9c4d80d02f1a495cb0ee2f7be9b97 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/debug/shared/ICON_LICENSE.md @@ -0,0 +1,6 @@ +Silk icon set 1.3 by Mark James + +http://www.famfamfam.com/lab/icons/silk/ + +License: [CC-BY-2.5](https://creativecommons.org/licenses/by/2.5/) +or [CC-BY-3.0](https://creativecommons.org/licenses/by/3.0/) diff --git a/MLPY/Lib/site-packages/werkzeug/debug/shared/console.png b/MLPY/Lib/site-packages/werkzeug/debug/shared/console.png new file mode 100644 index 0000000000000000000000000000000000000000..c28dd63812d80e416682f835652f8e5824bdccb2 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/debug/shared/console.png differ diff --git a/MLPY/Lib/site-packages/werkzeug/debug/shared/debugger.js b/MLPY/Lib/site-packages/werkzeug/debug/shared/debugger.js new file mode 100644 index 0000000000000000000000000000000000000000..18c658344559adc4c6d3b1a36658df5c9258df6f --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/debug/shared/debugger.js @@ -0,0 +1,360 @@ +docReady(() => { + if (!EVALEX_TRUSTED) { + initPinBox(); + } + // if we are in console mode, show the console. + if (CONSOLE_MODE && EVALEX) { + createInteractiveConsole(); + } + + const frames = document.querySelectorAll("div.traceback div.frame"); + if (EVALEX) { + addConsoleIconToFrames(frames); + } + addEventListenersToElements(document.querySelectorAll("div.detail"), "click", () => + document.querySelector("div.traceback").scrollIntoView(false) + ); + addToggleFrameTraceback(frames); + addToggleTraceTypesOnClick(document.querySelectorAll("h2.traceback")); + addInfoPrompt(document.querySelectorAll("span.nojavascript")); + wrapPlainTraceback(); +}); + +function addToggleFrameTraceback(frames) { + frames.forEach((frame) => { + frame.addEventListener("click", () => { + frame.getElementsByTagName("pre")[0].parentElement.classList.toggle("expanded"); + }); + }) +} + + +function wrapPlainTraceback() { + const plainTraceback = document.querySelector("div.plain textarea"); + const wrapper = document.createElement("pre"); + const textNode = document.createTextNode(plainTraceback.textContent); + wrapper.appendChild(textNode); + plainTraceback.replaceWith(wrapper); +} + +function initPinBox() { + document.querySelector(".pin-prompt form").addEventListener( + "submit", + function (event) { + event.preventDefault(); + const pin = encodeURIComponent(this.pin.value); + const encodedSecret = encodeURIComponent(SECRET); + const btn = this.btn; + btn.disabled = true; + + fetch( + `${document.location}?__debugger__=yes&cmd=pinauth&pin=${pin}&s=${encodedSecret}` + ) + .then((res) => res.json()) + .then(({auth, exhausted}) => { + if (auth) { + EVALEX_TRUSTED = true; + fadeOut(document.getElementsByClassName("pin-prompt")[0]); + } else { + alert( + `Error: ${ + exhausted + ? "too many attempts. Restart server to retry." + : "incorrect pin" + }` + ); + } + }) + .catch((err) => { + alert("Error: Could not verify PIN. Network error?"); + console.error(err); + }) + .finally(() => (btn.disabled = false)); + }, + false + ); +} + +function promptForPin() { + if (!EVALEX_TRUSTED) { + const encodedSecret = encodeURIComponent(SECRET); + fetch( + `${document.location}?__debugger__=yes&cmd=printpin&s=${encodedSecret}` + ); + const pinPrompt = document.getElementsByClassName("pin-prompt")[0]; + fadeIn(pinPrompt); + document.querySelector('.pin-prompt input[name="pin"]').focus(); + } +} + +/** + * Helper function for shell initialization + */ +function openShell(consoleNode, target, frameID) { + promptForPin(); + if (consoleNode) { + slideToggle(consoleNode); + return consoleNode; + } + let historyPos = 0; + const history = [""]; + const consoleElement = createConsole(); + const output = createConsoleOutput(); + const form = createConsoleInputForm(); + const command = createConsoleInput(); + + target.parentNode.appendChild(consoleElement); + consoleElement.append(output); + consoleElement.append(form); + form.append(command); + command.focus(); + slideToggle(consoleElement); + + form.addEventListener("submit", (e) => { + handleConsoleSubmit(e, command, frameID).then((consoleOutput) => { + output.append(consoleOutput); + command.focus(); + consoleElement.scrollTo(0, consoleElement.scrollHeight); + const old = history.pop(); + history.push(command.value); + if (typeof old !== "undefined") { + history.push(old); + } + historyPos = history.length - 1; + command.value = ""; + }); + }); + + command.addEventListener("keydown", (e) => { + if (e.key === "l" && e.ctrlKey) { + output.innerText = "--- screen cleared ---"; + } else if (e.key === "ArrowUp" || e.key === "ArrowDown") { + // Handle up arrow and down arrow. + if (e.key === "ArrowUp" && historyPos > 0) { + e.preventDefault(); + historyPos--; + } else if (e.key === "ArrowDown" && historyPos < history.length - 1) { + historyPos++; + } + command.value = history[historyPos]; + } + return false; + }); + + return consoleElement; +} + +function addEventListenersToElements(elements, event, listener) { + elements.forEach((el) => el.addEventListener(event, listener)); +} + +/** + * Add extra info + */ +function addInfoPrompt(elements) { + for (let i = 0; i < elements.length; i++) { + elements[i].innerHTML = + "

To switch between the interactive traceback and the plaintext " + + 'one, you can click on the "Traceback" headline. From the text ' + + "traceback you can also create a paste of it. " + + (!EVALEX + ? "" + : "For code execution mouse-over the frame you want to debug and " + + "click on the console icon on the right side." + + "

You can execute arbitrary Python code in the stack frames and " + + "there are some extra helpers available for introspection:" + + "

  • dump() shows all variables in the frame" + + "
  • dump(obj) dumps all that's known about the object
"); + elements[i].classList.remove("nojavascript"); + } +} + +function addConsoleIconToFrames(frames) { + for (let i = 0; i < frames.length; i++) { + let consoleNode = null; + const target = frames[i]; + const frameID = frames[i].id.substring(6); + + for (let j = 0; j < target.getElementsByTagName("pre").length; j++) { + const img = createIconForConsole(); + img.addEventListener("click", (e) => { + e.stopPropagation(); + consoleNode = openShell(consoleNode, target, frameID); + return false; + }); + target.getElementsByTagName("pre")[j].append(img); + } + } +} + +function slideToggle(target) { + target.classList.toggle("active"); +} + +/** + * toggle traceback types on click. + */ +function addToggleTraceTypesOnClick(elements) { + for (let i = 0; i < elements.length; i++) { + elements[i].addEventListener("click", () => { + document.querySelector("div.traceback").classList.toggle("hidden"); + document.querySelector("div.plain").classList.toggle("hidden"); + }); + elements[i].style.cursor = "pointer"; + document.querySelector("div.plain").classList.toggle("hidden"); + } +} + +function createConsole() { + const consoleNode = document.createElement("pre"); + consoleNode.classList.add("console"); + consoleNode.classList.add("active"); + return consoleNode; +} + +function createConsoleOutput() { + const output = document.createElement("div"); + output.classList.add("output"); + output.innerHTML = "[console ready]"; + return output; +} + +function createConsoleInputForm() { + const form = document.createElement("form"); + form.innerHTML = ">>> "; + return form; +} + +function createConsoleInput() { + const command = document.createElement("input"); + command.type = "text"; + command.setAttribute("autocomplete", "off"); + command.setAttribute("spellcheck", false); + command.setAttribute("autocapitalize", "off"); + command.setAttribute("autocorrect", "off"); + return command; +} + +function createIconForConsole() { + const img = document.createElement("img"); + img.setAttribute("src", "?__debugger__=yes&cmd=resource&f=console.png"); + img.setAttribute("title", "Open an interactive python shell in this frame"); + return img; +} + +function createExpansionButtonForConsole() { + const expansionButton = document.createElement("a"); + expansionButton.setAttribute("href", "#"); + expansionButton.setAttribute("class", "toggle"); + expansionButton.innerHTML = "  "; + return expansionButton; +} + +function createInteractiveConsole() { + const target = document.querySelector("div.console div.inner"); + while (target.firstChild) { + target.removeChild(target.firstChild); + } + openShell(null, target, 0); +} + +function handleConsoleSubmit(e, command, frameID) { + // Prevent page from refreshing. + e.preventDefault(); + + return new Promise((resolve) => { + // Get input command. + const cmd = command.value; + + // Setup GET request. + const urlPath = ""; + const params = { + __debugger__: "yes", + cmd: cmd, + frm: frameID, + s: SECRET, + }; + const paramString = Object.keys(params) + .map((key) => { + return "&" + encodeURIComponent(key) + "=" + encodeURIComponent(params[key]); + }) + .join(""); + + fetch(urlPath + "?" + paramString) + .then((res) => { + return res.text(); + }) + .then((data) => { + const tmp = document.createElement("div"); + tmp.innerHTML = data; + resolve(tmp); + + // Handle expandable span for long list outputs. + // Example to test: list(range(13)) + let wrapperAdded = false; + const wrapperSpan = document.createElement("span"); + const expansionButton = createExpansionButtonForConsole(); + + tmp.querySelectorAll("span.extended").forEach((spanToWrap) => { + const parentDiv = spanToWrap.parentNode; + if (!wrapperAdded) { + parentDiv.insertBefore(wrapperSpan, spanToWrap); + wrapperAdded = true; + } + parentDiv.removeChild(spanToWrap); + wrapperSpan.append(spanToWrap); + spanToWrap.hidden = true; + + expansionButton.addEventListener("click", (event) => { + event.preventDefault(); + spanToWrap.hidden = !spanToWrap.hidden; + expansionButton.classList.toggle("open"); + return false; + }); + }); + + // Add expansion button at end of wrapper. + if (wrapperAdded) { + wrapperSpan.append(expansionButton); + } + }) + .catch((err) => { + console.error(err); + }); + return false; + }); +} + +function fadeOut(element) { + element.style.opacity = 1; + + (function fade() { + element.style.opacity -= 0.1; + if (element.style.opacity < 0) { + element.style.display = "none"; + } else { + requestAnimationFrame(fade); + } + })(); +} + +function fadeIn(element, display) { + element.style.opacity = 0; + element.style.display = display || "block"; + + (function fade() { + let val = parseFloat(element.style.opacity) + 0.1; + if (val <= 1) { + element.style.opacity = val; + requestAnimationFrame(fade); + } + })(); +} + +function docReady(fn) { + if (document.readyState === "complete" || document.readyState === "interactive") { + setTimeout(fn, 1); + } else { + document.addEventListener("DOMContentLoaded", fn); + } +} diff --git a/MLPY/Lib/site-packages/werkzeug/debug/shared/less.png b/MLPY/Lib/site-packages/werkzeug/debug/shared/less.png new file mode 100644 index 0000000000000000000000000000000000000000..5efefd62b43e4f11dd300be4355a4b413c7a70d2 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/debug/shared/less.png differ diff --git a/MLPY/Lib/site-packages/werkzeug/debug/shared/more.png b/MLPY/Lib/site-packages/werkzeug/debug/shared/more.png new file mode 100644 index 0000000000000000000000000000000000000000..804fa226fe3ed9e6cc2bd044a848f33a2d7b4e4f Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/debug/shared/more.png differ diff --git a/MLPY/Lib/site-packages/werkzeug/debug/shared/style.css b/MLPY/Lib/site-packages/werkzeug/debug/shared/style.css new file mode 100644 index 0000000000000000000000000000000000000000..e9397ca0a1b6c26f30cb28fc81510a48fc46ede9 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/debug/shared/style.css @@ -0,0 +1,150 @@ +body, input { font-family: sans-serif; color: #000; text-align: center; + margin: 1em; padding: 0; font-size: 15px; } +h1, h2, h3 { font-weight: normal; } + +input { background-color: #fff; margin: 0; text-align: left; + outline: none !important; } +input[type="submit"] { padding: 3px 6px; } +a { color: #11557C; } +a:hover { color: #177199; } +pre, code, +textarea { font-family: monospace; font-size: 14px; } + +div.debugger { text-align: left; padding: 12px; margin: auto; + background-color: white; } +h1 { font-size: 36px; margin: 0 0 0.3em 0; } +div.detail { cursor: pointer; } +div.detail p { margin: 0 0 8px 13px; font-size: 14px; white-space: pre-wrap; + font-family: monospace; } +div.explanation { margin: 20px 13px; font-size: 15px; color: #555; } +div.footer { font-size: 13px; text-align: right; margin: 30px 0; + color: #86989B; } + +h2 { font-size: 16px; margin: 1.3em 0 0.0 0; padding: 9px; + background-color: #11557C; color: white; } +h2 em, h3 em { font-style: normal; color: #A5D6D9; font-weight: normal; } + +div.traceback, div.plain { border: 1px solid #ddd; margin: 0 0 1em 0; padding: 10px; } +div.plain p { margin: 0; } +div.plain textarea, +div.plain pre { margin: 10px 0 0 0; padding: 4px; + background-color: #E8EFF0; border: 1px solid #D3E7E9; } +div.plain textarea { width: 99%; height: 300px; } +div.traceback h3 { font-size: 1em; margin: 0 0 0.8em 0; } +div.traceback ul { list-style: none; margin: 0; padding: 0 0 0 1em; } +div.traceback h4 { font-size: 13px; font-weight: normal; margin: 0.7em 0 0.1em 0; } +div.traceback pre { margin: 0; padding: 5px 0 3px 15px; + background-color: #E8EFF0; border: 1px solid #D3E7E9; } +div.traceback .library .current { background: white; color: #555; } +div.traceback .expanded .current { background: #E8EFF0; color: black; } +div.traceback pre:hover { background-color: #DDECEE; color: black; cursor: pointer; } +div.traceback div.source.expanded pre + pre { border-top: none; } + +div.traceback span.ws { display: none; } +div.traceback pre.before, div.traceback pre.after { display: none; background: white; } +div.traceback div.source.expanded pre.before, +div.traceback div.source.expanded pre.after { + display: block; +} + +div.traceback div.source.expanded span.ws { + display: inline; +} + +div.traceback blockquote { margin: 1em 0 0 0; padding: 0; white-space: pre-line; } +div.traceback img { float: right; padding: 2px; margin: -3px 2px 0 0; display: none; } +div.traceback img:hover { background-color: #ddd; cursor: pointer; + border-color: #BFDDE0; } +div.traceback pre:hover img { display: block; } +div.traceback cite.filename { font-style: normal; color: #3B666B; } + +pre.console { border: 1px solid #ccc; background: white!important; + color: black; padding: 5px!important; + margin: 3px 0 0 0!important; cursor: default!important; + max-height: 400px; overflow: auto; } +pre.console form { color: #555; } +pre.console input { background-color: transparent; color: #555; + width: 90%; font-family: monospace; font-size: 14px; + border: none!important; } + +span.string { color: #30799B; } +span.number { color: #9C1A1C; } +span.help { color: #3A7734; } +span.object { color: #485F6E; } +span.extended { opacity: 0.5; } +span.extended:hover { opacity: 1; } +a.toggle { text-decoration: none; background-repeat: no-repeat; + background-position: center center; + background-image: url(?__debugger__=yes&cmd=resource&f=more.png); } +a.toggle:hover { background-color: #444; } +a.open { background-image: url(?__debugger__=yes&cmd=resource&f=less.png); } + +pre.console div.traceback, +pre.console div.box { margin: 5px 10px; white-space: normal; + border: 1px solid #11557C; padding: 10px; + font-family: sans-serif; } +pre.console div.box h3, +pre.console div.traceback h3 { margin: -10px -10px 10px -10px; padding: 5px; + background: #11557C; color: white; } + +pre.console div.traceback pre:hover { cursor: default; background: #E8EFF0; } +pre.console div.traceback pre.syntaxerror { background: inherit; border: none; + margin: 20px -10px -10px -10px; + padding: 10px; border-top: 1px solid #BFDDE0; + background: #E8EFF0; } +pre.console div.noframe-traceback pre.syntaxerror { margin-top: -10px; border: none; } + +pre.console div.box pre.repr { padding: 0; margin: 0; background-color: white; border: none; } +pre.console div.box table { margin-top: 6px; } +pre.console div.box pre { border: none; } +pre.console div.box pre.help { background-color: white; } +pre.console div.box pre.help:hover { cursor: default; } +pre.console table tr { vertical-align: top; } +div.console { border: 1px solid #ccc; padding: 4px; background-color: #fafafa; } + +div.traceback pre, div.console pre { + white-space: pre-wrap; /* css-3 should we be so lucky... */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 ?? */ + white-space: -o-pre-wrap; /* Opera 7 ?? */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + _white-space: pre; /* IE only hack to re-specify in + addition to word-wrap */ +} + + +div.pin-prompt { + position: absolute; + display: none; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: rgba(255, 255, 255, 0.8); +} + +div.pin-prompt .inner { + background: #eee; + padding: 10px 50px; + width: 350px; + margin: 10% auto 0 auto; + border: 1px solid #ccc; + border-radius: 2px; +} + +div.exc-divider { + margin: 0.7em 0 0 -1em; + padding: 0.5em; + background: #11557C; + color: #ddd; + border: 1px solid #ddd; +} + +.console.active { + max-height: 0!important; + display: none; +} + +.hidden { + display: none; +} diff --git a/MLPY/Lib/site-packages/werkzeug/debug/tbtools.py b/MLPY/Lib/site-packages/werkzeug/debug/tbtools.py new file mode 100644 index 0000000000000000000000000000000000000000..0574c966b7ef7d2dab44b0667bc7a509c9cec365 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/debug/tbtools.py @@ -0,0 +1,439 @@ +from __future__ import annotations + +import itertools +import linecache +import os +import re +import sys +import sysconfig +import traceback +import typing as t + +from markupsafe import escape + +from ..utils import cached_property +from .console import Console + +HEADER = """\ + + + + %(title)s // Werkzeug Debugger + + + + + + +
+""" + +FOOTER = """\ + +
+ +
+
+

Console Locked

+

+ The console is locked and needs to be unlocked by entering the PIN. + You can find the PIN printed out on the standard output of your + shell that runs the server. +

+

PIN: + + +

+
+
+ + +""" + +PAGE_HTML = ( + HEADER + + """\ +

%(exception_type)s

+
+

%(exception)s

+
+

Traceback (most recent call last)

+%(summary)s +
+

+ This is the Copy/Paste friendly version of the traceback. +

+ +
+
+ The debugger caught an exception in your WSGI application. You can now + look at the traceback which led to the error. + If you enable JavaScript you can also use additional features such as code + execution (if the evalex feature is enabled), automatic pasting of the + exceptions and much more. +
+""" + + FOOTER + + """ + +""" +) + +CONSOLE_HTML = ( + HEADER + + """\ +

Interactive Console

+
+In this console you can execute Python expressions in the context of the +application. The initial namespace was created by the debugger automatically. +
+
The Console requires JavaScript.
+""" + + FOOTER +) + +SUMMARY_HTML = """\ +
+ %(title)s +
    %(frames)s
+ %(description)s +
+""" + +FRAME_HTML = """\ +
+

File "%(filename)s", + line %(lineno)s, + in %(function_name)s

+
%(lines)s
+
+""" + + +def _process_traceback( + exc: BaseException, + te: traceback.TracebackException | None = None, + *, + skip: int = 0, + hide: bool = True, +) -> traceback.TracebackException: + if te is None: + te = traceback.TracebackException.from_exception(exc, lookup_lines=False) + + # Get the frames the same way StackSummary.extract did, in order + # to match each frame with the FrameSummary to augment. + frame_gen = traceback.walk_tb(exc.__traceback__) + limit = getattr(sys, "tracebacklimit", None) + + if limit is not None: + if limit < 0: + limit = 0 + + frame_gen = itertools.islice(frame_gen, limit) + + if skip: + frame_gen = itertools.islice(frame_gen, skip, None) + del te.stack[:skip] + + new_stack: list[DebugFrameSummary] = [] + hidden = False + + # Match each frame with the FrameSummary that was generated. + # Hide frames using Paste's __traceback_hide__ rules. Replace + # all visible FrameSummary with DebugFrameSummary. + for (f, _), fs in zip(frame_gen, te.stack): + if hide: + hide_value = f.f_locals.get("__traceback_hide__", False) + + if hide_value in {"before", "before_and_this"}: + new_stack = [] + hidden = False + + if hide_value == "before_and_this": + continue + elif hide_value in {"reset", "reset_and_this"}: + hidden = False + + if hide_value == "reset_and_this": + continue + elif hide_value in {"after", "after_and_this"}: + hidden = True + + if hide_value == "after_and_this": + continue + elif hide_value or hidden: + continue + + frame_args: dict[str, t.Any] = { + "filename": fs.filename, + "lineno": fs.lineno, + "name": fs.name, + "locals": f.f_locals, + "globals": f.f_globals, + } + + if hasattr(fs, "colno"): + frame_args["colno"] = fs.colno + frame_args["end_colno"] = fs.end_colno + + new_stack.append(DebugFrameSummary(**frame_args)) + + # The codeop module is used to compile code from the interactive + # debugger. Hide any codeop frames from the bottom of the traceback. + while new_stack: + module = new_stack[0].global_ns.get("__name__") + + if module is None: + module = new_stack[0].local_ns.get("__name__") + + if module == "codeop": + del new_stack[0] + else: + break + + te.stack[:] = new_stack + + if te.__context__: + context_exc = t.cast(BaseException, exc.__context__) + te.__context__ = _process_traceback(context_exc, te.__context__, hide=hide) + + if te.__cause__: + cause_exc = t.cast(BaseException, exc.__cause__) + te.__cause__ = _process_traceback(cause_exc, te.__cause__, hide=hide) + + return te + + +class DebugTraceback: + __slots__ = ("_te", "_cache_all_tracebacks", "_cache_all_frames") + + def __init__( + self, + exc: BaseException, + te: traceback.TracebackException | None = None, + *, + skip: int = 0, + hide: bool = True, + ) -> None: + self._te = _process_traceback(exc, te, skip=skip, hide=hide) + + def __str__(self) -> str: + return f"<{type(self).__name__} {self._te}>" + + @cached_property + def all_tracebacks( + self, + ) -> list[tuple[str | None, traceback.TracebackException]]: + out = [] + current = self._te + + while current is not None: + if current.__cause__ is not None: + chained_msg = ( + "The above exception was the direct cause of the" + " following exception" + ) + chained_exc = current.__cause__ + elif current.__context__ is not None and not current.__suppress_context__: + chained_msg = ( + "During handling of the above exception, another" + " exception occurred" + ) + chained_exc = current.__context__ + else: + chained_msg = None + chained_exc = None + + out.append((chained_msg, current)) + current = chained_exc + + return out + + @cached_property + def all_frames(self) -> list[DebugFrameSummary]: + return [ + f # type: ignore[misc] + for _, te in self.all_tracebacks + for f in te.stack + ] + + def render_traceback_text(self) -> str: + return "".join(self._te.format()) + + def render_traceback_html(self, include_title: bool = True) -> str: + library_frames = [f.is_library for f in self.all_frames] + mark_library = 0 < sum(library_frames) < len(library_frames) + rows = [] + + if not library_frames: + classes = "traceback noframe-traceback" + else: + classes = "traceback" + + for msg, current in reversed(self.all_tracebacks): + row_parts = [] + + if msg is not None: + row_parts.append(f'
  • {msg}:
    ') + + for frame in current.stack: + frame = t.cast(DebugFrameSummary, frame) + info = f' title="{escape(frame.info)}"' if frame.info else "" + row_parts.append(f"{frame.render_html(mark_library)}") + + rows.append("\n".join(row_parts)) + + is_syntax_error = issubclass(self._te.exc_type, SyntaxError) + + if include_title: + if is_syntax_error: + title = "Syntax Error" + else: + title = "Traceback (most recent call last):" + else: + title = "" + + exc_full = escape("".join(self._te.format_exception_only())) + + if is_syntax_error: + description = f"
    {exc_full}
    " + else: + description = f"
    {exc_full}
    " + + return SUMMARY_HTML % { + "classes": classes, + "title": f"

    {title}

    ", + "frames": "\n".join(rows), + "description": description, + } + + def render_debugger_html( + self, evalex: bool, secret: str, evalex_trusted: bool + ) -> str: + exc_lines = list(self._te.format_exception_only()) + plaintext = "".join(self._te.format()) + return PAGE_HTML % { + "evalex": "true" if evalex else "false", + "evalex_trusted": "true" if evalex_trusted else "false", + "console": "false", + "title": escape(exc_lines[0]), + "exception": escape("".join(exc_lines)), + "exception_type": escape(self._te.exc_type.__name__), + "summary": self.render_traceback_html(include_title=False), + "plaintext": escape(plaintext), + "plaintext_cs": re.sub("-{2,}", "-", plaintext), + "secret": secret, + } + + +class DebugFrameSummary(traceback.FrameSummary): + """A :class:`traceback.FrameSummary` that can evaluate code in the + frame's namespace. + """ + + __slots__ = ( + "local_ns", + "global_ns", + "_cache_info", + "_cache_is_library", + "_cache_console", + ) + + def __init__( + self, + *, + locals: dict[str, t.Any], + globals: dict[str, t.Any], + **kwargs: t.Any, + ) -> None: + super().__init__(locals=None, **kwargs) + self.local_ns = locals + self.global_ns = globals + + @cached_property + def info(self) -> str | None: + return self.local_ns.get("__traceback_info__") + + @cached_property + def is_library(self) -> bool: + return any( + self.filename.startswith((path, os.path.realpath(path))) + for path in sysconfig.get_paths().values() + ) + + @cached_property + def console(self) -> Console: + return Console(self.global_ns, self.local_ns) + + def eval(self, code: str) -> t.Any: + return self.console.eval(code) + + def render_html(self, mark_library: bool) -> str: + context = 5 + lines = linecache.getlines(self.filename) + line_idx = self.lineno - 1 # type: ignore[operator] + start_idx = max(0, line_idx - context) + stop_idx = min(len(lines), line_idx + context + 1) + rendered_lines = [] + + def render_line(line: str, cls: str) -> None: + line = line.expandtabs().rstrip() + stripped_line = line.strip() + prefix = len(line) - len(stripped_line) + colno = getattr(self, "colno", 0) + end_colno = getattr(self, "end_colno", 0) + + if cls == "current" and colno and end_colno: + arrow = ( + f'\n{" " * prefix}' + f'{" " * (colno - prefix)}{"^" * (end_colno - colno)}' + ) + else: + arrow = "" + + rendered_lines.append( + f'
    {" " * prefix}'
    +                f"{escape(stripped_line) if stripped_line else ' '}"
    +                f"{arrow if arrow else ''}
    " + ) + + if lines: + for line in lines[start_idx:line_idx]: + render_line(line, "before") + + render_line(lines[line_idx], "current") + + for line in lines[line_idx + 1 : stop_idx]: + render_line(line, "after") + + return FRAME_HTML % { + "id": id(self), + "filename": escape(self.filename), + "lineno": self.lineno, + "function_name": escape(self.name), + "lines": "\n".join(rendered_lines), + "library": "library" if mark_library and self.is_library else "", + } + + +def render_console_html(secret: str, evalex_trusted: bool) -> str: + return CONSOLE_HTML % { + "evalex": "true", + "evalex_trusted": "true" if evalex_trusted else "false", + "console": "true", + "title": "Console", + "secret": secret, + } diff --git a/MLPY/Lib/site-packages/werkzeug/exceptions.py b/MLPY/Lib/site-packages/werkzeug/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..6ce7ef9559be0f246b9d6253e55bd8a2bafc6fe9 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/exceptions.py @@ -0,0 +1,881 @@ +"""Implements a number of Python exceptions which can be raised from within +a view to trigger a standard HTTP non-200 response. + +Usage Example +------------- + +.. code-block:: python + + from werkzeug.wrappers.request import Request + from werkzeug.exceptions import HTTPException, NotFound + + def view(request): + raise NotFound() + + @Request.application + def application(request): + try: + return view(request) + except HTTPException as e: + return e + +As you can see from this example those exceptions are callable WSGI +applications. However, they are not Werkzeug response objects. You +can get a response object by calling ``get_response()`` on a HTTP +exception. + +Keep in mind that you may have to pass an environ (WSGI) or scope +(ASGI) to ``get_response()`` because some errors fetch additional +information relating to the request. + +If you want to hook in a different exception page to say, a 404 status +code, you can add a second except for a specific subclass of an error: + +.. code-block:: python + + @Request.application + def application(request): + try: + return view(request) + except NotFound as e: + return not_found(request) + except HTTPException as e: + return e + +""" + +from __future__ import annotations + +import typing as t +from datetime import datetime + +from markupsafe import escape +from markupsafe import Markup + +from ._internal import _get_environ + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIEnvironment + + from .datastructures import WWWAuthenticate + from .sansio.response import Response + from .wrappers.request import Request as WSGIRequest + from .wrappers.response import Response as WSGIResponse + + +class HTTPException(Exception): + """The base class for all HTTP exceptions. This exception can be called as a WSGI + application to render a default error page or you can catch the subclasses + of it independently and render nicer error messages. + + .. versionchanged:: 2.1 + Removed the ``wrap`` class method. + """ + + code: int | None = None + description: str | None = None + + def __init__( + self, + description: str | None = None, + response: Response | None = None, + ) -> None: + super().__init__() + if description is not None: + self.description = description + self.response = response + + @property + def name(self) -> str: + """The status name.""" + from .http import HTTP_STATUS_CODES + + return HTTP_STATUS_CODES.get(self.code, "Unknown Error") # type: ignore + + def get_description( + self, + environ: WSGIEnvironment | None = None, + scope: dict[str, t.Any] | None = None, + ) -> str: + """Get the description.""" + if self.description is None: + description = "" + else: + description = self.description + + description = escape(description).replace("\n", Markup("
    ")) + return f"

    {description}

    " + + def get_body( + self, + environ: WSGIEnvironment | None = None, + scope: dict[str, t.Any] | None = None, + ) -> str: + """Get the HTML body.""" + return ( + "\n" + "\n" + f"{self.code} {escape(self.name)}\n" + f"

    {escape(self.name)}

    \n" + f"{self.get_description(environ)}\n" + ) + + def get_headers( + self, + environ: WSGIEnvironment | None = None, + scope: dict[str, t.Any] | None = None, + ) -> list[tuple[str, str]]: + """Get a list of headers.""" + return [("Content-Type", "text/html; charset=utf-8")] + + def get_response( + self, + environ: WSGIEnvironment | WSGIRequest | None = None, + scope: dict[str, t.Any] | None = None, + ) -> Response: + """Get a response object. If one was passed to the exception + it's returned directly. + + :param environ: the optional environ for the request. This + can be used to modify the response depending + on how the request looked like. + :return: a :class:`Response` object or a subclass thereof. + """ + from .wrappers.response import Response as WSGIResponse # noqa: F811 + + if self.response is not None: + return self.response + if environ is not None: + environ = _get_environ(environ) + headers = self.get_headers(environ, scope) + return WSGIResponse(self.get_body(environ, scope), self.code, headers) + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + """Call the exception as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + """ + response = t.cast("WSGIResponse", self.get_response(environ)) + return response(environ, start_response) + + def __str__(self) -> str: + code = self.code if self.code is not None else "???" + return f"{code} {self.name}: {self.description}" + + def __repr__(self) -> str: + code = self.code if self.code is not None else "???" + return f"<{type(self).__name__} '{code}: {self.name}'>" + + +class BadRequest(HTTPException): + """*400* `Bad Request` + + Raise if the browser sends something to the application the application + or server cannot handle. + """ + + code = 400 + description = ( + "The browser (or proxy) sent a request that this server could " + "not understand." + ) + + +class BadRequestKeyError(BadRequest, KeyError): + """An exception that is used to signal both a :exc:`KeyError` and a + :exc:`BadRequest`. Used by many of the datastructures. + """ + + _description = BadRequest.description + #: Show the KeyError along with the HTTP error message in the + #: response. This should be disabled in production, but can be + #: useful in a debug mode. + show_exception = False + + def __init__(self, arg: str | None = None, *args: t.Any, **kwargs: t.Any): + super().__init__(*args, **kwargs) + + if arg is None: + KeyError.__init__(self) + else: + KeyError.__init__(self, arg) + + @property # type: ignore + def description(self) -> str: + if self.show_exception: + return ( + f"{self._description}\n" + f"{KeyError.__name__}: {KeyError.__str__(self)}" + ) + + return self._description + + @description.setter + def description(self, value: str) -> None: + self._description = value + + +class ClientDisconnected(BadRequest): + """Internal exception that is raised if Werkzeug detects a disconnected + client. Since the client is already gone at that point attempting to + send the error message to the client might not work and might ultimately + result in another exception in the server. Mainly this is here so that + it is silenced by default as far as Werkzeug is concerned. + + Since disconnections cannot be reliably detected and are unspecified + by WSGI to a large extent this might or might not be raised if a client + is gone. + + .. versionadded:: 0.8 + """ + + +class SecurityError(BadRequest): + """Raised if something triggers a security error. This is otherwise + exactly like a bad request error. + + .. versionadded:: 0.9 + """ + + +class BadHost(BadRequest): + """Raised if the submitted host is badly formatted. + + .. versionadded:: 0.11.2 + """ + + +class Unauthorized(HTTPException): + """*401* ``Unauthorized`` + + Raise if the user is not authorized to access a resource. + + The ``www_authenticate`` argument should be used to set the + ``WWW-Authenticate`` header. This is used for HTTP basic auth and + other schemes. Use :class:`~werkzeug.datastructures.WWWAuthenticate` + to create correctly formatted values. Strictly speaking a 401 + response is invalid if it doesn't provide at least one value for + this header, although real clients typically don't care. + + :param description: Override the default message used for the body + of the response. + :param www-authenticate: A single value, or list of values, for the + WWW-Authenticate header(s). + + .. versionchanged:: 2.0 + Serialize multiple ``www_authenticate`` items into multiple + ``WWW-Authenticate`` headers, rather than joining them + into a single value, for better interoperability. + + .. versionchanged:: 0.15.3 + If the ``www_authenticate`` argument is not set, the + ``WWW-Authenticate`` header is not set. + + .. versionchanged:: 0.15.3 + The ``response`` argument was restored. + + .. versionchanged:: 0.15.1 + ``description`` was moved back as the first argument, restoring + its previous position. + + .. versionchanged:: 0.15.0 + ``www_authenticate`` was added as the first argument, ahead of + ``description``. + """ + + code = 401 + description = ( + "The server could not verify that you are authorized to access" + " the URL requested. You either supplied the wrong credentials" + " (e.g. a bad password), or your browser doesn't understand" + " how to supply the credentials required." + ) + + def __init__( + self, + description: str | None = None, + response: Response | None = None, + www_authenticate: None | (WWWAuthenticate | t.Iterable[WWWAuthenticate]) = None, + ) -> None: + super().__init__(description, response) + + from .datastructures import WWWAuthenticate + + if isinstance(www_authenticate, WWWAuthenticate): + www_authenticate = (www_authenticate,) + + self.www_authenticate = www_authenticate + + def get_headers( + self, + environ: WSGIEnvironment | None = None, + scope: dict[str, t.Any] | None = None, + ) -> list[tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.www_authenticate: + headers.extend(("WWW-Authenticate", str(x)) for x in self.www_authenticate) + return headers + + +class Forbidden(HTTPException): + """*403* `Forbidden` + + Raise if the user doesn't have the permission for the requested resource + but was authenticated. + """ + + code = 403 + description = ( + "You don't have the permission to access the requested" + " resource. It is either read-protected or not readable by the" + " server." + ) + + +class NotFound(HTTPException): + """*404* `Not Found` + + Raise if a resource does not exist and never existed. + """ + + code = 404 + description = ( + "The requested URL was not found on the server. If you entered" + " the URL manually please check your spelling and try again." + ) + + +class MethodNotAllowed(HTTPException): + """*405* `Method Not Allowed` + + Raise if the server used a method the resource does not handle. For + example `POST` if the resource is view only. Especially useful for REST. + + The first argument for this exception should be a list of allowed methods. + Strictly speaking the response would be invalid if you don't provide valid + methods in the header which you can do with that list. + """ + + code = 405 + description = "The method is not allowed for the requested URL." + + def __init__( + self, + valid_methods: t.Iterable[str] | None = None, + description: str | None = None, + response: Response | None = None, + ) -> None: + """Takes an optional list of valid http methods + starting with werkzeug 0.3 the list will be mandatory.""" + super().__init__(description=description, response=response) + self.valid_methods = valid_methods + + def get_headers( + self, + environ: WSGIEnvironment | None = None, + scope: dict[str, t.Any] | None = None, + ) -> list[tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.valid_methods: + headers.append(("Allow", ", ".join(self.valid_methods))) + return headers + + +class NotAcceptable(HTTPException): + """*406* `Not Acceptable` + + Raise if the server can't return any content conforming to the + `Accept` headers of the client. + """ + + code = 406 + description = ( + "The resource identified by the request is only capable of" + " generating response entities which have content" + " characteristics not acceptable according to the accept" + " headers sent in the request." + ) + + +class RequestTimeout(HTTPException): + """*408* `Request Timeout` + + Raise to signalize a timeout. + """ + + code = 408 + description = ( + "The server closed the network connection because the browser" + " didn't finish the request within the specified time." + ) + + +class Conflict(HTTPException): + """*409* `Conflict` + + Raise to signal that a request cannot be completed because it conflicts + with the current state on the server. + + .. versionadded:: 0.7 + """ + + code = 409 + description = ( + "A conflict happened while processing the request. The" + " resource might have been modified while the request was being" + " processed." + ) + + +class Gone(HTTPException): + """*410* `Gone` + + Raise if a resource existed previously and went away without new location. + """ + + code = 410 + description = ( + "The requested URL is no longer available on this server and" + " there is no forwarding address. If you followed a link from a" + " foreign page, please contact the author of this page." + ) + + +class LengthRequired(HTTPException): + """*411* `Length Required` + + Raise if the browser submitted data but no ``Content-Length`` header which + is required for the kind of processing the server does. + """ + + code = 411 + description = ( + "A request with this method requires a valid Content-" + "Length header." + ) + + +class PreconditionFailed(HTTPException): + """*412* `Precondition Failed` + + Status code used in combination with ``If-Match``, ``If-None-Match``, or + ``If-Unmodified-Since``. + """ + + code = 412 + description = ( + "The precondition on the request for the URL failed positive evaluation." + ) + + +class RequestEntityTooLarge(HTTPException): + """*413* `Request Entity Too Large` + + The status code one should return if the data submitted exceeded a given + limit. + """ + + code = 413 + description = "The data value transmitted exceeds the capacity limit." + + +class RequestURITooLarge(HTTPException): + """*414* `Request URI Too Large` + + Like *413* but for too long URLs. + """ + + code = 414 + description = ( + "The length of the requested URL exceeds the capacity limit for" + " this server. The request cannot be processed." + ) + + +class UnsupportedMediaType(HTTPException): + """*415* `Unsupported Media Type` + + The status code returned if the server is unable to handle the media type + the client transmitted. + """ + + code = 415 + description = ( + "The server does not support the media type transmitted in the request." + ) + + +class RequestedRangeNotSatisfiable(HTTPException): + """*416* `Requested Range Not Satisfiable` + + The client asked for an invalid part of the file. + + .. versionadded:: 0.7 + """ + + code = 416 + description = "The server cannot provide the requested range." + + def __init__( + self, + length: int | None = None, + units: str = "bytes", + description: str | None = None, + response: Response | None = None, + ) -> None: + """Takes an optional `Content-Range` header value based on ``length`` + parameter. + """ + super().__init__(description=description, response=response) + self.length = length + self.units = units + + def get_headers( + self, + environ: WSGIEnvironment | None = None, + scope: dict[str, t.Any] | None = None, + ) -> list[tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.length is not None: + headers.append(("Content-Range", f"{self.units} */{self.length}")) + return headers + + +class ExpectationFailed(HTTPException): + """*417* `Expectation Failed` + + The server cannot meet the requirements of the Expect request-header. + + .. versionadded:: 0.7 + """ + + code = 417 + description = "The server could not meet the requirements of the Expect header" + + +class ImATeapot(HTTPException): + """*418* `I'm a teapot` + + The server should return this if it is a teapot and someone attempted + to brew coffee with it. + + .. versionadded:: 0.7 + """ + + code = 418 + description = "This server is a teapot, not a coffee machine" + + +class UnprocessableEntity(HTTPException): + """*422* `Unprocessable Entity` + + Used if the request is well formed, but the instructions are otherwise + incorrect. + """ + + code = 422 + description = ( + "The request was well-formed but was unable to be followed due" + " to semantic errors." + ) + + +class Locked(HTTPException): + """*423* `Locked` + + Used if the resource that is being accessed is locked. + """ + + code = 423 + description = "The resource that is being accessed is locked." + + +class FailedDependency(HTTPException): + """*424* `Failed Dependency` + + Used if the method could not be performed on the resource + because the requested action depended on another action and that action failed. + """ + + code = 424 + description = ( + "The method could not be performed on the resource because the" + " requested action depended on another action and that action" + " failed." + ) + + +class PreconditionRequired(HTTPException): + """*428* `Precondition Required` + + The server requires this request to be conditional, typically to prevent + the lost update problem, which is a race condition between two or more + clients attempting to update a resource through PUT or DELETE. By requiring + each client to include a conditional header ("If-Match" or "If-Unmodified- + Since") with the proper value retained from a recent GET request, the + server ensures that each client has at least seen the previous revision of + the resource. + """ + + code = 428 + description = ( + "This request is required to be conditional; try using" + ' "If-Match" or "If-Unmodified-Since".' + ) + + +class _RetryAfter(HTTPException): + """Adds an optional ``retry_after`` parameter which will set the + ``Retry-After`` header. May be an :class:`int` number of seconds or + a :class:`~datetime.datetime`. + """ + + def __init__( + self, + description: str | None = None, + response: Response | None = None, + retry_after: datetime | int | None = None, + ) -> None: + super().__init__(description, response) + self.retry_after = retry_after + + def get_headers( + self, + environ: WSGIEnvironment | None = None, + scope: dict[str, t.Any] | None = None, + ) -> list[tuple[str, str]]: + headers = super().get_headers(environ, scope) + + if self.retry_after: + if isinstance(self.retry_after, datetime): + from .http import http_date + + value = http_date(self.retry_after) + else: + value = str(self.retry_after) + + headers.append(("Retry-After", value)) + + return headers + + +class TooManyRequests(_RetryAfter): + """*429* `Too Many Requests` + + The server is limiting the rate at which this user receives + responses, and this request exceeds that rate. (The server may use + any convenient method to identify users and their request rates). + The server may include a "Retry-After" header to indicate how long + the user should wait before retrying. + + :param retry_after: If given, set the ``Retry-After`` header to this + value. May be an :class:`int` number of seconds or a + :class:`~datetime.datetime`. + + .. versionchanged:: 1.0 + Added ``retry_after`` parameter. + """ + + code = 429 + description = "This user has exceeded an allotted request count. Try again later." + + +class RequestHeaderFieldsTooLarge(HTTPException): + """*431* `Request Header Fields Too Large` + + The server refuses to process the request because the header fields are too + large. One or more individual fields may be too large, or the set of all + headers is too large. + """ + + code = 431 + description = "One or more header fields exceeds the maximum size." + + +class UnavailableForLegalReasons(HTTPException): + """*451* `Unavailable For Legal Reasons` + + This status code indicates that the server is denying access to the + resource as a consequence of a legal demand. + """ + + code = 451 + description = "Unavailable for legal reasons." + + +class InternalServerError(HTTPException): + """*500* `Internal Server Error` + + Raise if an internal server error occurred. This is a good fallback if an + unknown error occurred in the dispatcher. + + .. versionchanged:: 1.0.0 + Added the :attr:`original_exception` attribute. + """ + + code = 500 + description = ( + "The server encountered an internal error and was unable to" + " complete your request. Either the server is overloaded or" + " there is an error in the application." + ) + + def __init__( + self, + description: str | None = None, + response: Response | None = None, + original_exception: BaseException | None = None, + ) -> None: + #: The original exception that caused this 500 error. Can be + #: used by frameworks to provide context when handling + #: unexpected errors. + self.original_exception = original_exception + super().__init__(description=description, response=response) + + +class NotImplemented(HTTPException): + """*501* `Not Implemented` + + Raise if the application does not support the action requested by the + browser. + """ + + code = 501 + description = "The server does not support the action requested by the browser." + + +class BadGateway(HTTPException): + """*502* `Bad Gateway` + + If you do proxying in your application you should return this status code + if you received an invalid response from the upstream server it accessed + in attempting to fulfill the request. + """ + + code = 502 + description = ( + "The proxy server received an invalid response from an upstream server." + ) + + +class ServiceUnavailable(_RetryAfter): + """*503* `Service Unavailable` + + Status code you should return if a service is temporarily + unavailable. + + :param retry_after: If given, set the ``Retry-After`` header to this + value. May be an :class:`int` number of seconds or a + :class:`~datetime.datetime`. + + .. versionchanged:: 1.0 + Added ``retry_after`` parameter. + """ + + code = 503 + description = ( + "The server is temporarily unable to service your request due" + " to maintenance downtime or capacity problems. Please try" + " again later." + ) + + +class GatewayTimeout(HTTPException): + """*504* `Gateway Timeout` + + Status code you should return if a connection to an upstream server + times out. + """ + + code = 504 + description = "The connection to an upstream server timed out." + + +class HTTPVersionNotSupported(HTTPException): + """*505* `HTTP Version Not Supported` + + The server does not support the HTTP protocol version used in the request. + """ + + code = 505 + description = ( + "The server does not support the HTTP protocol version used in the request." + ) + + +default_exceptions: dict[int, type[HTTPException]] = {} + + +def _find_exceptions() -> None: + for obj in globals().values(): + try: + is_http_exception = issubclass(obj, HTTPException) + except TypeError: + is_http_exception = False + if not is_http_exception or obj.code is None: + continue + old_obj = default_exceptions.get(obj.code, None) + if old_obj is not None and issubclass(obj, old_obj): + continue + default_exceptions[obj.code] = obj + + +_find_exceptions() +del _find_exceptions + + +class Aborter: + """When passed a dict of code -> exception items it can be used as + callable that raises exceptions. If the first argument to the + callable is an integer it will be looked up in the mapping, if it's + a WSGI application it will be raised in a proxy exception. + + The rest of the arguments are forwarded to the exception constructor. + """ + + def __init__( + self, + mapping: dict[int, type[HTTPException]] | None = None, + extra: dict[int, type[HTTPException]] | None = None, + ) -> None: + if mapping is None: + mapping = default_exceptions + self.mapping = dict(mapping) + if extra is not None: + self.mapping.update(extra) + + def __call__( + self, code: int | Response, *args: t.Any, **kwargs: t.Any + ) -> t.NoReturn: + from .sansio.response import Response + + if isinstance(code, Response): + raise HTTPException(response=code) + + if code not in self.mapping: + raise LookupError(f"no exception for {code!r}") + + raise self.mapping[code](*args, **kwargs) + + +def abort(status: int | Response, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: + """Raises an :py:exc:`HTTPException` for the given status code or WSGI + application. + + If a status code is given, it will be looked up in the list of + exceptions and will raise that exception. If passed a WSGI application, + it will wrap it in a proxy WSGI exception and raise that:: + + abort(404) # 404 Not Found + abort(Response('Hello World')) + + """ + _aborter(status, *args, **kwargs) + + +_aborter: Aborter = Aborter() diff --git a/MLPY/Lib/site-packages/werkzeug/formparser.py b/MLPY/Lib/site-packages/werkzeug/formparser.py new file mode 100644 index 0000000000000000000000000000000000000000..ba84721e3769b9d02fe7fdb1290a81a6945e70c6 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/formparser.py @@ -0,0 +1,423 @@ +from __future__ import annotations + +import typing as t +from io import BytesIO +from urllib.parse import parse_qsl + +from ._internal import _plain_int +from .datastructures import FileStorage +from .datastructures import Headers +from .datastructures import MultiDict +from .exceptions import RequestEntityTooLarge +from .http import parse_options_header +from .sansio.multipart import Data +from .sansio.multipart import Epilogue +from .sansio.multipart import Field +from .sansio.multipart import File +from .sansio.multipart import MultipartDecoder +from .sansio.multipart import NeedData +from .wsgi import get_content_length +from .wsgi import get_input_stream + +# there are some platforms where SpooledTemporaryFile is not available. +# In that case we need to provide a fallback. +try: + from tempfile import SpooledTemporaryFile +except ImportError: + from tempfile import TemporaryFile + + SpooledTemporaryFile = None # type: ignore + +if t.TYPE_CHECKING: + import typing as te + + from _typeshed.wsgi import WSGIEnvironment + + t_parse_result = t.Tuple[ + t.IO[bytes], MultiDict[str, str], MultiDict[str, FileStorage] + ] + + class TStreamFactory(te.Protocol): + def __call__( + self, + total_content_length: int | None, + content_type: str | None, + filename: str | None, + content_length: int | None = None, + ) -> t.IO[bytes]: ... + + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def default_stream_factory( + total_content_length: int | None, + content_type: str | None, + filename: str | None, + content_length: int | None = None, +) -> t.IO[bytes]: + max_size = 1024 * 500 + + if SpooledTemporaryFile is not None: + return t.cast(t.IO[bytes], SpooledTemporaryFile(max_size=max_size, mode="rb+")) + elif total_content_length is None or total_content_length > max_size: + return t.cast(t.IO[bytes], TemporaryFile("rb+")) + + return BytesIO() + + +def parse_form_data( + environ: WSGIEnvironment, + stream_factory: TStreamFactory | None = None, + max_form_memory_size: int | None = None, + max_content_length: int | None = None, + cls: type[MultiDict[str, t.Any]] | None = None, + silent: bool = True, + *, + max_form_parts: int | None = None, +) -> t_parse_result: + """Parse the form data in the environ and return it as tuple in the form + ``(stream, form, files)``. You should only call this method if the + transport method is `POST`, `PUT`, or `PATCH`. + + If the mimetype of the data transmitted is `multipart/form-data` the + files multidict will be filled with `FileStorage` objects. If the + mimetype is unknown the input stream is wrapped and returned as first + argument, else the stream is empty. + + This is a shortcut for the common usage of :class:`FormDataParser`. + + :param environ: the WSGI environment to be used for parsing. + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`Response._get_file_stream`. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + :param max_form_parts: The maximum number of multipart parts to be parsed. If this + is exceeded, a :exc:`~exceptions.RequestEntityTooLarge` exception is raised. + :return: A tuple in the form ``(stream, form, files)``. + + .. versionchanged:: 3.0 + The ``charset`` and ``errors`` parameters were removed. + + .. versionchanged:: 2.3 + Added the ``max_form_parts`` parameter. + + .. versionadded:: 0.5.1 + Added the ``silent`` parameter. + + .. versionadded:: 0.5 + Added the ``max_form_memory_size``, ``max_content_length``, and ``cls`` + parameters. + """ + return FormDataParser( + stream_factory=stream_factory, + max_form_memory_size=max_form_memory_size, + max_content_length=max_content_length, + max_form_parts=max_form_parts, + silent=silent, + cls=cls, + ).parse_from_environ(environ) + + +class FormDataParser: + """This class implements parsing of form data for Werkzeug. By itself + it can parse multipart and url encoded form data. It can be subclassed + and extended but for most mimetypes it is a better idea to use the + untouched stream and expose it as separate attributes on a request + object. + + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`Response._get_file_stream`. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + :param max_form_parts: The maximum number of multipart parts to be parsed. If this + is exceeded, a :exc:`~exceptions.RequestEntityTooLarge` exception is raised. + + .. versionchanged:: 3.0 + The ``charset`` and ``errors`` parameters were removed. + + .. versionchanged:: 3.0 + The ``parse_functions`` attribute and ``get_parse_func`` methods were removed. + + .. versionchanged:: 2.2.3 + Added the ``max_form_parts`` parameter. + + .. versionadded:: 0.8 + """ + + def __init__( + self, + stream_factory: TStreamFactory | None = None, + max_form_memory_size: int | None = None, + max_content_length: int | None = None, + cls: type[MultiDict[str, t.Any]] | None = None, + silent: bool = True, + *, + max_form_parts: int | None = None, + ) -> None: + if stream_factory is None: + stream_factory = default_stream_factory + + self.stream_factory = stream_factory + self.max_form_memory_size = max_form_memory_size + self.max_content_length = max_content_length + self.max_form_parts = max_form_parts + + if cls is None: + cls = t.cast("type[MultiDict[str, t.Any]]", MultiDict) + + self.cls = cls + self.silent = silent + + def parse_from_environ(self, environ: WSGIEnvironment) -> t_parse_result: + """Parses the information from the environment as form data. + + :param environ: the WSGI environment to be used for parsing. + :return: A tuple in the form ``(stream, form, files)``. + """ + stream = get_input_stream(environ, max_content_length=self.max_content_length) + content_length = get_content_length(environ) + mimetype, options = parse_options_header(environ.get("CONTENT_TYPE")) + return self.parse( + stream, + content_length=content_length, + mimetype=mimetype, + options=options, + ) + + def parse( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: int | None, + options: dict[str, str] | None = None, + ) -> t_parse_result: + """Parses the information from the given stream, mimetype, + content length and mimetype parameters. + + :param stream: an input stream + :param mimetype: the mimetype of the data + :param content_length: the content length of the incoming data + :param options: optional mimetype parameters (used for + the multipart boundary for instance) + :return: A tuple in the form ``(stream, form, files)``. + + .. versionchanged:: 3.0 + The invalid ``application/x-url-encoded`` content type is not + treated as ``application/x-www-form-urlencoded``. + """ + if mimetype == "multipart/form-data": + parse_func = self._parse_multipart + elif mimetype == "application/x-www-form-urlencoded": + parse_func = self._parse_urlencoded + else: + return stream, self.cls(), self.cls() + + if options is None: + options = {} + + try: + return parse_func(stream, mimetype, content_length, options) + except ValueError: + if not self.silent: + raise + + return stream, self.cls(), self.cls() + + def _parse_multipart( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: int | None, + options: dict[str, str], + ) -> t_parse_result: + parser = MultiPartParser( + stream_factory=self.stream_factory, + max_form_memory_size=self.max_form_memory_size, + max_form_parts=self.max_form_parts, + cls=self.cls, + ) + boundary = options.get("boundary", "").encode("ascii") + + if not boundary: + raise ValueError("Missing boundary") + + form, files = parser.parse(stream, boundary, content_length) + return stream, form, files + + def _parse_urlencoded( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: int | None, + options: dict[str, str], + ) -> t_parse_result: + if ( + self.max_form_memory_size is not None + and content_length is not None + and content_length > self.max_form_memory_size + ): + raise RequestEntityTooLarge() + + try: + items = parse_qsl( + stream.read().decode(), + keep_blank_values=True, + errors="werkzeug.url_quote", + ) + except ValueError as e: + raise RequestEntityTooLarge() from e + + return stream, self.cls(items), self.cls() + + +class MultiPartParser: + def __init__( + self, + stream_factory: TStreamFactory | None = None, + max_form_memory_size: int | None = None, + cls: type[MultiDict[str, t.Any]] | None = None, + buffer_size: int = 64 * 1024, + max_form_parts: int | None = None, + ) -> None: + self.max_form_memory_size = max_form_memory_size + self.max_form_parts = max_form_parts + + if stream_factory is None: + stream_factory = default_stream_factory + + self.stream_factory = stream_factory + + if cls is None: + cls = t.cast("type[MultiDict[str, t.Any]]", MultiDict) + + self.cls = cls + self.buffer_size = buffer_size + + def fail(self, message: str) -> te.NoReturn: + raise ValueError(message) + + def get_part_charset(self, headers: Headers) -> str: + # Figure out input charset for current part + content_type = headers.get("content-type") + + if content_type: + parameters = parse_options_header(content_type)[1] + ct_charset = parameters.get("charset", "").lower() + + # A safe list of encodings. Modern clients should only send ASCII or UTF-8. + # This list will not be extended further. + if ct_charset in {"ascii", "us-ascii", "utf-8", "iso-8859-1"}: + return ct_charset + + return "utf-8" + + def start_file_streaming( + self, event: File, total_content_length: int | None + ) -> t.IO[bytes]: + content_type = event.headers.get("content-type") + + try: + content_length = _plain_int(event.headers["content-length"]) + except (KeyError, ValueError): + content_length = 0 + + container = self.stream_factory( + total_content_length=total_content_length, + filename=event.filename, + content_type=content_type, + content_length=content_length, + ) + return container + + def parse( + self, stream: t.IO[bytes], boundary: bytes, content_length: int | None + ) -> tuple[MultiDict[str, str], MultiDict[str, FileStorage]]: + current_part: Field | File + container: t.IO[bytes] | list[bytes] + _write: t.Callable[[bytes], t.Any] + + parser = MultipartDecoder( + boundary, + max_form_memory_size=self.max_form_memory_size, + max_parts=self.max_form_parts, + ) + + fields = [] + files = [] + + for data in _chunk_iter(stream.read, self.buffer_size): + parser.receive_data(data) + event = parser.next_event() + while not isinstance(event, (Epilogue, NeedData)): + if isinstance(event, Field): + current_part = event + container = [] + _write = container.append + elif isinstance(event, File): + current_part = event + container = self.start_file_streaming(event, content_length) + _write = container.write + elif isinstance(event, Data): + _write(event.data) + if not event.more_data: + if isinstance(current_part, Field): + value = b"".join(container).decode( + self.get_part_charset(current_part.headers), "replace" + ) + fields.append((current_part.name, value)) + else: + container = t.cast(t.IO[bytes], container) + container.seek(0) + files.append( + ( + current_part.name, + FileStorage( + container, + current_part.filename, + current_part.name, + headers=current_part.headers, + ), + ) + ) + + event = parser.next_event() + + return self.cls(fields), self.cls(files) + + +def _chunk_iter(read: t.Callable[[int], bytes], size: int) -> t.Iterator[bytes | None]: + """Read data in chunks for multipart/form-data parsing. Stop if no data is read. + Yield ``None`` at the end to signal end of parsing. + """ + while True: + data = read(size) + + if not data: + break + + yield data + + yield None diff --git a/MLPY/Lib/site-packages/werkzeug/http.py b/MLPY/Lib/site-packages/werkzeug/http.py new file mode 100644 index 0000000000000000000000000000000000000000..27fa9af90f9b30ff76d9655553a81cce1db8c0f4 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/http.py @@ -0,0 +1,1370 @@ +from __future__ import annotations + +import email.utils +import re +import typing as t +import warnings +from datetime import date +from datetime import datetime +from datetime import time +from datetime import timedelta +from datetime import timezone +from enum import Enum +from hashlib import sha1 +from time import mktime +from time import struct_time +from urllib.parse import quote +from urllib.parse import unquote +from urllib.request import parse_http_list as _parse_list_header + +from ._internal import _dt_as_utc +from ._internal import _plain_int + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + +_token_chars = frozenset( + "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~" +) +_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)') +_entity_headers = frozenset( + [ + "allow", + "content-encoding", + "content-language", + "content-length", + "content-location", + "content-md5", + "content-range", + "content-type", + "expires", + "last-modified", + ] +) +_hop_by_hop_headers = frozenset( + [ + "connection", + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "te", + "trailer", + "transfer-encoding", + "upgrade", + ] +) +HTTP_STATUS_CODES = { + 100: "Continue", + 101: "Switching Protocols", + 102: "Processing", + 103: "Early Hints", # see RFC 8297 + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi Status", + 208: "Already Reported", # see RFC 5842 + 226: "IM Used", # see RFC 3229 + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 306: "Switch Proxy", # unused + 307: "Temporary Redirect", + 308: "Permanent Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", # unused + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 418: "I'm a teapot", # see RFC 2324 + 421: "Misdirected Request", # see RFC 7540 + 422: "Unprocessable Entity", + 423: "Locked", + 424: "Failed Dependency", + 425: "Too Early", # see RFC 8470 + 426: "Upgrade Required", + 428: "Precondition Required", # see RFC 6585 + 429: "Too Many Requests", + 431: "Request Header Fields Too Large", + 449: "Retry With", # proprietary MS extension + 451: "Unavailable For Legal Reasons", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported", + 506: "Variant Also Negotiates", # see RFC 2295 + 507: "Insufficient Storage", + 508: "Loop Detected", # see RFC 5842 + 510: "Not Extended", + 511: "Network Authentication Failed", +} + + +class COEP(Enum): + """Cross Origin Embedder Policies""" + + UNSAFE_NONE = "unsafe-none" + REQUIRE_CORP = "require-corp" + + +class COOP(Enum): + """Cross Origin Opener Policies""" + + UNSAFE_NONE = "unsafe-none" + SAME_ORIGIN_ALLOW_POPUPS = "same-origin-allow-popups" + SAME_ORIGIN = "same-origin" + + +def quote_header_value(value: t.Any, allow_token: bool = True) -> str: + """Add double quotes around a header value. If the header contains only ASCII token + characters, it will be returned unchanged. If the header contains ``"`` or ``\\`` + characters, they will be escaped with an additional ``\\`` character. + + This is the reverse of :func:`unquote_header_value`. + + :param value: The value to quote. Will be converted to a string. + :param allow_token: Disable to quote the value even if it only has token characters. + + .. versionchanged:: 3.0 + Passing bytes is not supported. + + .. versionchanged:: 3.0 + The ``extra_chars`` parameter is removed. + + .. versionchanged:: 2.3 + The value is quoted if it is the empty string. + + .. versionadded:: 0.5 + """ + value_str = str(value) + + if not value_str: + return '""' + + if allow_token: + token_chars = _token_chars + + if token_chars.issuperset(value_str): + return value_str + + value_str = value_str.replace("\\", "\\\\").replace('"', '\\"') + return f'"{value_str}"' + + +def unquote_header_value(value: str) -> str: + """Remove double quotes and decode slash-escaped ``"`` and ``\\`` characters in a + header value. + + This is the reverse of :func:`quote_header_value`. + + :param value: The header value to unquote. + + .. versionchanged:: 3.0 + The ``is_filename`` parameter is removed. + """ + if len(value) >= 2 and value[0] == value[-1] == '"': + value = value[1:-1] + return value.replace("\\\\", "\\").replace('\\"', '"') + + return value + + +def dump_options_header(header: str | None, options: t.Mapping[str, t.Any]) -> str: + """Produce a header value and ``key=value`` parameters separated by semicolons + ``;``. For example, the ``Content-Type`` header. + + .. code-block:: python + + dump_options_header("text/html", {"charset": "UTF-8"}) + 'text/html; charset=UTF-8' + + This is the reverse of :func:`parse_options_header`. + + If a value contains non-token characters, it will be quoted. + + If a value is ``None``, the parameter is skipped. + + In some keys for some headers, a UTF-8 value can be encoded using a special + ``key*=UTF-8''value`` form, where ``value`` is percent encoded. This function will + not produce that format automatically, but if a given key ends with an asterisk + ``*``, the value is assumed to have that form and will not be quoted further. + + :param header: The primary header value. + :param options: Parameters to encode as ``key=value`` pairs. + + .. versionchanged:: 2.3 + Keys with ``None`` values are skipped rather than treated as a bare key. + + .. versionchanged:: 2.2.3 + If a key ends with ``*``, its value will not be quoted. + """ + segments = [] + + if header is not None: + segments.append(header) + + for key, value in options.items(): + if value is None: + continue + + if key[-1] == "*": + segments.append(f"{key}={value}") + else: + segments.append(f"{key}={quote_header_value(value)}") + + return "; ".join(segments) + + +def dump_header(iterable: dict[str, t.Any] | t.Iterable[t.Any]) -> str: + """Produce a header value from a list of items or ``key=value`` pairs, separated by + commas ``,``. + + This is the reverse of :func:`parse_list_header`, :func:`parse_dict_header`, and + :func:`parse_set_header`. + + If a value contains non-token characters, it will be quoted. + + If a value is ``None``, the key is output alone. + + In some keys for some headers, a UTF-8 value can be encoded using a special + ``key*=UTF-8''value`` form, where ``value`` is percent encoded. This function will + not produce that format automatically, but if a given key ends with an asterisk + ``*``, the value is assumed to have that form and will not be quoted further. + + .. code-block:: python + + dump_header(["foo", "bar baz"]) + 'foo, "bar baz"' + + dump_header({"foo": "bar baz"}) + 'foo="bar baz"' + + :param iterable: The items to create a header from. + + .. versionchanged:: 3.0 + The ``allow_token`` parameter is removed. + + .. versionchanged:: 2.2.3 + If a key ends with ``*``, its value will not be quoted. + """ + if isinstance(iterable, dict): + items = [] + + for key, value in iterable.items(): + if value is None: + items.append(key) + elif key[-1] == "*": + items.append(f"{key}={value}") + else: + items.append(f"{key}={quote_header_value(value)}") + else: + items = [quote_header_value(x) for x in iterable] + + return ", ".join(items) + + +def dump_csp_header(header: ds.ContentSecurityPolicy) -> str: + """Dump a Content Security Policy header. + + These are structured into policies such as "default-src 'self'; + script-src 'self'". + + .. versionadded:: 1.0.0 + Support for Content Security Policy headers was added. + + """ + return "; ".join(f"{key} {value}" for key, value in header.items()) + + +def parse_list_header(value: str) -> list[str]: + """Parse a header value that consists of a list of comma separated items according + to `RFC 9110 `__. + + This extends :func:`urllib.request.parse_http_list` to remove surrounding quotes + from values. + + .. code-block:: python + + parse_list_header('token, "quoted value"') + ['token', 'quoted value'] + + This is the reverse of :func:`dump_header`. + + :param value: The header value to parse. + """ + result = [] + + for item in _parse_list_header(value): + if len(item) >= 2 and item[0] == item[-1] == '"': + item = item[1:-1] + + result.append(item) + + return result + + +def parse_dict_header(value: str) -> dict[str, str | None]: + """Parse a list header using :func:`parse_list_header`, then parse each item as a + ``key=value`` pair. + + .. code-block:: python + + parse_dict_header('a=b, c="d, e", f') + {"a": "b", "c": "d, e", "f": None} + + This is the reverse of :func:`dump_header`. + + If a key does not have a value, it is ``None``. + + This handles charsets for values as described in + `RFC 2231 `__. Only ASCII, UTF-8, + and ISO-8859-1 charsets are accepted, otherwise the value remains quoted. + + :param value: The header value to parse. + + .. versionchanged:: 3.0 + Passing bytes is not supported. + + .. versionchanged:: 3.0 + The ``cls`` argument is removed. + + .. versionchanged:: 2.3 + Added support for ``key*=charset''value`` encoded items. + + .. versionchanged:: 0.9 + The ``cls`` argument was added. + """ + result: dict[str, str | None] = {} + + for item in parse_list_header(value): + key, has_value, value = item.partition("=") + key = key.strip() + + if not has_value: + result[key] = None + continue + + value = value.strip() + encoding: str | None = None + + if key[-1] == "*": + # key*=charset''value becomes key=value, where value is percent encoded + # adapted from parse_options_header, without the continuation handling + key = key[:-1] + match = _charset_value_re.match(value) + + if match: + # If there is a charset marker in the value, split it off. + encoding, value = match.groups() + encoding = encoding.lower() + + # A safe list of encodings. Modern clients should only send ASCII or UTF-8. + # This list will not be extended further. An invalid encoding will leave the + # value quoted. + if encoding in {"ascii", "us-ascii", "utf-8", "iso-8859-1"}: + # invalid bytes are replaced during unquoting + value = unquote(value, encoding=encoding) + + if len(value) >= 2 and value[0] == value[-1] == '"': + value = value[1:-1] + + result[key] = value + + return result + + +# https://httpwg.org/specs/rfc9110.html#parameter +_parameter_re = re.compile( + r""" + # don't match multiple empty parts, that causes backtracking + \s*;\s* # find the part delimiter + (?: + ([\w!#$%&'*+\-.^`|~]+) # key, one or more token chars + = # equals, with no space on either side + ( # value, token or quoted string + [\w!#$%&'*+\-.^`|~]+ # one or more token chars + | + "(?:\\\\|\\"|.)*?" # quoted string, consuming slash escapes + ) + )? # optionally match key=value, to account for empty parts + """, + re.ASCII | re.VERBOSE, +) +# https://www.rfc-editor.org/rfc/rfc2231#section-4 +_charset_value_re = re.compile( + r""" + ([\w!#$%&*+\-.^`|~]*)' # charset part, could be empty + [\w!#$%&*+\-.^`|~]*' # don't care about language part, usually empty + ([\w!#$%&'*+\-.^`|~]+) # one or more token chars with percent encoding + """, + re.ASCII | re.VERBOSE, +) +# https://www.rfc-editor.org/rfc/rfc2231#section-3 +_continuation_re = re.compile(r"\*(\d+)$", re.ASCII) + + +def parse_options_header(value: str | None) -> tuple[str, dict[str, str]]: + """Parse a header that consists of a value with ``key=value`` parameters separated + by semicolons ``;``. For example, the ``Content-Type`` header. + + .. code-block:: python + + parse_options_header("text/html; charset=UTF-8") + ('text/html', {'charset': 'UTF-8'}) + + parse_options_header("") + ("", {}) + + This is the reverse of :func:`dump_options_header`. + + This parses valid parameter parts as described in + `RFC 9110 `__. Invalid parts are + skipped. + + This handles continuations and charsets as described in + `RFC 2231 `__, although not as + strictly as the RFC. Only ASCII, UTF-8, and ISO-8859-1 charsets are accepted, + otherwise the value remains quoted. + + Clients may not be consistent in how they handle a quote character within a quoted + value. The `HTML Standard `__ + replaces it with ``%22`` in multipart form data. + `RFC 9110 `__ uses backslash + escapes in HTTP headers. Both are decoded to the ``"`` character. + + Clients may not be consistent in how they handle non-ASCII characters. HTML + documents must declare ````, otherwise browsers may replace with + HTML character references, which can be decoded using :func:`html.unescape`. + + :param value: The header value to parse. + :return: ``(value, options)``, where ``options`` is a dict + + .. versionchanged:: 2.3 + Invalid parts, such as keys with no value, quoted keys, and incorrectly quoted + values, are discarded instead of treating as ``None``. + + .. versionchanged:: 2.3 + Only ASCII, UTF-8, and ISO-8859-1 are accepted for charset values. + + .. versionchanged:: 2.3 + Escaped quotes in quoted values, like ``%22`` and ``\\"``, are handled. + + .. versionchanged:: 2.2 + Option names are always converted to lowercase. + + .. versionchanged:: 2.2 + The ``multiple`` parameter was removed. + + .. versionchanged:: 0.15 + :rfc:`2231` parameter continuations are handled. + + .. versionadded:: 0.5 + """ + if value is None: + return "", {} + + value, _, rest = value.partition(";") + value = value.strip() + rest = rest.strip() + + if not value or not rest: + # empty (invalid) value, or value without options + return value, {} + + rest = f";{rest}" + options: dict[str, str] = {} + encoding: str | None = None + continued_encoding: str | None = None + + for pk, pv in _parameter_re.findall(rest): + if not pk: + # empty or invalid part + continue + + pk = pk.lower() + + if pk[-1] == "*": + # key*=charset''value becomes key=value, where value is percent encoded + pk = pk[:-1] + match = _charset_value_re.match(pv) + + if match: + # If there is a valid charset marker in the value, split it off. + encoding, pv = match.groups() + # This might be the empty string, handled next. + encoding = encoding.lower() + + # No charset marker, or marker with empty charset value. + if not encoding: + encoding = continued_encoding + + # A safe list of encodings. Modern clients should only send ASCII or UTF-8. + # This list will not be extended further. An invalid encoding will leave the + # value quoted. + if encoding in {"ascii", "us-ascii", "utf-8", "iso-8859-1"}: + # Continuation parts don't require their own charset marker. This is + # looser than the RFC, it will persist across different keys and allows + # changing the charset during a continuation. But this implementation is + # much simpler than tracking the full state. + continued_encoding = encoding + # invalid bytes are replaced during unquoting + pv = unquote(pv, encoding=encoding) + + # Remove quotes. At this point the value cannot be empty or a single quote. + if pv[0] == pv[-1] == '"': + # HTTP headers use slash, multipart form data uses percent + pv = pv[1:-1].replace("\\\\", "\\").replace('\\"', '"').replace("%22", '"') + + match = _continuation_re.search(pk) + + if match: + # key*0=a; key*1=b becomes key=ab + pk = pk[: match.start()] + options[pk] = options.get(pk, "") + pv + else: + options[pk] = pv + + return value, options + + +_q_value_re = re.compile(r"-?\d+(\.\d+)?", re.ASCII) +_TAnyAccept = t.TypeVar("_TAnyAccept", bound="ds.Accept") + + +@t.overload +def parse_accept_header(value: str | None) -> ds.Accept: ... + + +@t.overload +def parse_accept_header(value: str | None, cls: type[_TAnyAccept]) -> _TAnyAccept: ... + + +def parse_accept_header( + value: str | None, cls: type[_TAnyAccept] | None = None +) -> _TAnyAccept: + """Parse an ``Accept`` header according to + `RFC 9110 `__. + + Returns an :class:`.Accept` instance, which can sort and inspect items based on + their quality parameter. When parsing ``Accept-Charset``, ``Accept-Encoding``, or + ``Accept-Language``, pass the appropriate :class:`.Accept` subclass. + + :param value: The header value to parse. + :param cls: The :class:`.Accept` class to wrap the result in. + :return: An instance of ``cls``. + + .. versionchanged:: 2.3 + Parse according to RFC 9110. Items with invalid ``q`` values are skipped. + """ + if cls is None: + cls = t.cast(t.Type[_TAnyAccept], ds.Accept) + + if not value: + return cls(None) + + result = [] + + for item in parse_list_header(value): + item, options = parse_options_header(item) + + if "q" in options: + # pop q, remaining options are reconstructed + q_str = options.pop("q").strip() + + if _q_value_re.fullmatch(q_str) is None: + # ignore an invalid q + continue + + q = float(q_str) + + if q < 0 or q > 1: + # ignore an invalid q + continue + else: + q = 1 + + if options: + # reconstruct the media type with any options + item = dump_options_header(item, options) + + result.append((item, q)) + + return cls(result) + + +_TAnyCC = t.TypeVar("_TAnyCC", bound="ds.cache_control._CacheControl") + + +@t.overload +def parse_cache_control_header( + value: str | None, + on_update: t.Callable[[ds.cache_control._CacheControl], None] | None = None, +) -> ds.RequestCacheControl: ... + + +@t.overload +def parse_cache_control_header( + value: str | None, + on_update: t.Callable[[ds.cache_control._CacheControl], None] | None = None, + cls: type[_TAnyCC] = ..., +) -> _TAnyCC: ... + + +def parse_cache_control_header( + value: str | None, + on_update: t.Callable[[ds.cache_control._CacheControl], None] | None = None, + cls: type[_TAnyCC] | None = None, +) -> _TAnyCC: + """Parse a cache control header. The RFC differs between response and + request cache control, this method does not. It's your responsibility + to not use the wrong control statements. + + .. versionadded:: 0.5 + The `cls` was added. If not specified an immutable + :class:`~werkzeug.datastructures.RequestCacheControl` is returned. + + :param value: a cache control header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.CacheControl` + object is changed. + :param cls: the class for the returned object. By default + :class:`~werkzeug.datastructures.RequestCacheControl` is used. + :return: a `cls` object. + """ + if cls is None: + cls = t.cast("type[_TAnyCC]", ds.RequestCacheControl) + + if not value: + return cls((), on_update) + + return cls(parse_dict_header(value), on_update) + + +_TAnyCSP = t.TypeVar("_TAnyCSP", bound="ds.ContentSecurityPolicy") + + +@t.overload +def parse_csp_header( + value: str | None, + on_update: t.Callable[[ds.ContentSecurityPolicy], None] | None = None, +) -> ds.ContentSecurityPolicy: ... + + +@t.overload +def parse_csp_header( + value: str | None, + on_update: t.Callable[[ds.ContentSecurityPolicy], None] | None = None, + cls: type[_TAnyCSP] = ..., +) -> _TAnyCSP: ... + + +def parse_csp_header( + value: str | None, + on_update: t.Callable[[ds.ContentSecurityPolicy], None] | None = None, + cls: type[_TAnyCSP] | None = None, +) -> _TAnyCSP: + """Parse a Content Security Policy header. + + .. versionadded:: 1.0.0 + Support for Content Security Policy headers was added. + + :param value: a csp header to be parsed. + :param on_update: an optional callable that is called every time a value + on the object is changed. + :param cls: the class for the returned object. By default + :class:`~werkzeug.datastructures.ContentSecurityPolicy` is used. + :return: a `cls` object. + """ + if cls is None: + cls = t.cast("type[_TAnyCSP]", ds.ContentSecurityPolicy) + + if value is None: + return cls((), on_update) + + items = [] + + for policy in value.split(";"): + policy = policy.strip() + + # Ignore badly formatted policies (no space) + if " " in policy: + directive, value = policy.strip().split(" ", 1) + items.append((directive.strip(), value.strip())) + + return cls(items, on_update) + + +def parse_set_header( + value: str | None, + on_update: t.Callable[[ds.HeaderSet], None] | None = None, +) -> ds.HeaderSet: + """Parse a set-like header and return a + :class:`~werkzeug.datastructures.HeaderSet` object: + + >>> hs = parse_set_header('token, "quoted value"') + + The return value is an object that treats the items case-insensitively + and keeps the order of the items: + + >>> 'TOKEN' in hs + True + >>> hs.index('quoted value') + 1 + >>> hs + HeaderSet(['token', 'quoted value']) + + To create a header from the :class:`HeaderSet` again, use the + :func:`dump_header` function. + + :param value: a set header to be parsed. + :param on_update: an optional callable that is called every time a + value on the :class:`~werkzeug.datastructures.HeaderSet` + object is changed. + :return: a :class:`~werkzeug.datastructures.HeaderSet` + """ + if not value: + return ds.HeaderSet(None, on_update) + return ds.HeaderSet(parse_list_header(value), on_update) + + +def parse_if_range_header(value: str | None) -> ds.IfRange: + """Parses an if-range header which can be an etag or a date. Returns + a :class:`~werkzeug.datastructures.IfRange` object. + + .. versionchanged:: 2.0 + If the value represents a datetime, it is timezone-aware. + + .. versionadded:: 0.7 + """ + if not value: + return ds.IfRange() + date = parse_date(value) + if date is not None: + return ds.IfRange(date=date) + # drop weakness information + return ds.IfRange(unquote_etag(value)[0]) + + +def parse_range_header( + value: str | None, make_inclusive: bool = True +) -> ds.Range | None: + """Parses a range header into a :class:`~werkzeug.datastructures.Range` + object. If the header is missing or malformed `None` is returned. + `ranges` is a list of ``(start, stop)`` tuples where the ranges are + non-inclusive. + + .. versionadded:: 0.7 + """ + if not value or "=" not in value: + return None + + ranges = [] + last_end = 0 + units, rng = value.split("=", 1) + units = units.strip().lower() + + for item in rng.split(","): + item = item.strip() + if "-" not in item: + return None + if item.startswith("-"): + if last_end < 0: + return None + try: + begin = _plain_int(item) + except ValueError: + return None + end = None + last_end = -1 + elif "-" in item: + begin_str, end_str = item.split("-", 1) + begin_str = begin_str.strip() + end_str = end_str.strip() + + try: + begin = _plain_int(begin_str) + except ValueError: + return None + + if begin < last_end or last_end < 0: + return None + if end_str: + try: + end = _plain_int(end_str) + 1 + except ValueError: + return None + + if begin >= end: + return None + else: + end = None + last_end = end if end is not None else -1 + ranges.append((begin, end)) + + return ds.Range(units, ranges) + + +def parse_content_range_header( + value: str | None, + on_update: t.Callable[[ds.ContentRange], None] | None = None, +) -> ds.ContentRange | None: + """Parses a range header into a + :class:`~werkzeug.datastructures.ContentRange` object or `None` if + parsing is not possible. + + .. versionadded:: 0.7 + + :param value: a content range header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.ContentRange` + object is changed. + """ + if value is None: + return None + try: + units, rangedef = (value or "").strip().split(None, 1) + except ValueError: + return None + + if "/" not in rangedef: + return None + rng, length_str = rangedef.split("/", 1) + if length_str == "*": + length = None + else: + try: + length = _plain_int(length_str) + except ValueError: + return None + + if rng == "*": + if not is_byte_range_valid(None, None, length): + return None + + return ds.ContentRange(units, None, None, length, on_update=on_update) + elif "-" not in rng: + return None + + start_str, stop_str = rng.split("-", 1) + try: + start = _plain_int(start_str) + stop = _plain_int(stop_str) + 1 + except ValueError: + return None + + if is_byte_range_valid(start, stop, length): + return ds.ContentRange(units, start, stop, length, on_update=on_update) + + return None + + +def quote_etag(etag: str, weak: bool = False) -> str: + """Quote an etag. + + :param etag: the etag to quote. + :param weak: set to `True` to tag it "weak". + """ + if '"' in etag: + raise ValueError("invalid etag") + etag = f'"{etag}"' + if weak: + etag = f"W/{etag}" + return etag + + +def unquote_etag( + etag: str | None, +) -> tuple[str, bool] | tuple[None, None]: + """Unquote a single etag: + + >>> unquote_etag('W/"bar"') + ('bar', True) + >>> unquote_etag('"bar"') + ('bar', False) + + :param etag: the etag identifier to unquote. + :return: a ``(etag, weak)`` tuple. + """ + if not etag: + return None, None + etag = etag.strip() + weak = False + if etag.startswith(("W/", "w/")): + weak = True + etag = etag[2:] + if etag[:1] == etag[-1:] == '"': + etag = etag[1:-1] + return etag, weak + + +def parse_etags(value: str | None) -> ds.ETags: + """Parse an etag header. + + :param value: the tag header to parse + :return: an :class:`~werkzeug.datastructures.ETags` object. + """ + if not value: + return ds.ETags() + strong = [] + weak = [] + end = len(value) + pos = 0 + while pos < end: + match = _etag_re.match(value, pos) + if match is None: + break + is_weak, quoted, raw = match.groups() + if raw == "*": + return ds.ETags(star_tag=True) + elif quoted: + raw = quoted + if is_weak: + weak.append(raw) + else: + strong.append(raw) + pos = match.end() + return ds.ETags(strong, weak) + + +def generate_etag(data: bytes) -> str: + """Generate an etag for some data. + + .. versionchanged:: 2.0 + Use SHA-1. MD5 may not be available in some environments. + """ + return sha1(data).hexdigest() + + +def parse_date(value: str | None) -> datetime | None: + """Parse an :rfc:`2822` date into a timezone-aware + :class:`datetime.datetime` object, or ``None`` if parsing fails. + + This is a wrapper for :func:`email.utils.parsedate_to_datetime`. It + returns ``None`` if parsing fails instead of raising an exception, + and always returns a timezone-aware datetime object. If the string + doesn't have timezone information, it is assumed to be UTC. + + :param value: A string with a supported date format. + + .. versionchanged:: 2.0 + Return a timezone-aware datetime object. Use + ``email.utils.parsedate_to_datetime``. + """ + if value is None: + return None + + try: + dt = email.utils.parsedate_to_datetime(value) + except (TypeError, ValueError): + return None + + if dt.tzinfo is None: + return dt.replace(tzinfo=timezone.utc) + + return dt + + +def http_date( + timestamp: datetime | date | int | float | struct_time | None = None, +) -> str: + """Format a datetime object or timestamp into an :rfc:`2822` date + string. + + This is a wrapper for :func:`email.utils.format_datetime`. It + assumes naive datetime objects are in UTC instead of raising an + exception. + + :param timestamp: The datetime or timestamp to format. Defaults to + the current time. + + .. versionchanged:: 2.0 + Use ``email.utils.format_datetime``. Accept ``date`` objects. + """ + if isinstance(timestamp, date): + if not isinstance(timestamp, datetime): + # Assume plain date is midnight UTC. + timestamp = datetime.combine(timestamp, time(), tzinfo=timezone.utc) + else: + # Ensure datetime is timezone-aware. + timestamp = _dt_as_utc(timestamp) + + return email.utils.format_datetime(timestamp, usegmt=True) + + if isinstance(timestamp, struct_time): + timestamp = mktime(timestamp) + + return email.utils.formatdate(timestamp, usegmt=True) + + +def parse_age(value: str | None = None) -> timedelta | None: + """Parses a base-10 integer count of seconds into a timedelta. + + If parsing fails, the return value is `None`. + + :param value: a string consisting of an integer represented in base-10 + :return: a :class:`datetime.timedelta` object or `None`. + """ + if not value: + return None + try: + seconds = int(value) + except ValueError: + return None + if seconds < 0: + return None + try: + return timedelta(seconds=seconds) + except OverflowError: + return None + + +def dump_age(age: timedelta | int | None = None) -> str | None: + """Formats the duration as a base-10 integer. + + :param age: should be an integer number of seconds, + a :class:`datetime.timedelta` object, or, + if the age is unknown, `None` (default). + """ + if age is None: + return None + if isinstance(age, timedelta): + age = int(age.total_seconds()) + else: + age = int(age) + + if age < 0: + raise ValueError("age cannot be negative") + + return str(age) + + +def is_resource_modified( + environ: WSGIEnvironment, + etag: str | None = None, + data: bytes | None = None, + last_modified: datetime | str | None = None, + ignore_if_range: bool = True, +) -> bool: + """Convenience method for conditional requests. + + :param environ: the WSGI environment of the request to be checked. + :param etag: the etag for the response for comparison. + :param data: or alternatively the data of the response to automatically + generate an etag using :func:`generate_etag`. + :param last_modified: an optional date of the last modification. + :param ignore_if_range: If `False`, `If-Range` header will be taken into + account. + :return: `True` if the resource was modified, otherwise `False`. + + .. versionchanged:: 2.0 + SHA-1 is used to generate an etag value for the data. MD5 may + not be available in some environments. + + .. versionchanged:: 1.0.0 + The check is run for methods other than ``GET`` and ``HEAD``. + """ + return _sansio_http.is_resource_modified( + http_range=environ.get("HTTP_RANGE"), + http_if_range=environ.get("HTTP_IF_RANGE"), + http_if_modified_since=environ.get("HTTP_IF_MODIFIED_SINCE"), + http_if_none_match=environ.get("HTTP_IF_NONE_MATCH"), + http_if_match=environ.get("HTTP_IF_MATCH"), + etag=etag, + data=data, + last_modified=last_modified, + ignore_if_range=ignore_if_range, + ) + + +def remove_entity_headers( + headers: ds.Headers | list[tuple[str, str]], + allowed: t.Iterable[str] = ("expires", "content-location"), +) -> None: + """Remove all entity headers from a list or :class:`Headers` object. This + operation works in-place. `Expires` and `Content-Location` headers are + by default not removed. The reason for this is :rfc:`2616` section + 10.3.5 which specifies some entity headers that should be sent. + + .. versionchanged:: 0.5 + added `allowed` parameter. + + :param headers: a list or :class:`Headers` object. + :param allowed: a list of headers that should still be allowed even though + they are entity headers. + """ + allowed = {x.lower() for x in allowed} + headers[:] = [ + (key, value) + for key, value in headers + if not is_entity_header(key) or key.lower() in allowed + ] + + +def remove_hop_by_hop_headers(headers: ds.Headers | list[tuple[str, str]]) -> None: + """Remove all HTTP/1.1 "Hop-by-Hop" headers from a list or + :class:`Headers` object. This operation works in-place. + + .. versionadded:: 0.5 + + :param headers: a list or :class:`Headers` object. + """ + headers[:] = [ + (key, value) for key, value in headers if not is_hop_by_hop_header(key) + ] + + +def is_entity_header(header: str) -> bool: + """Check if a header is an entity header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an entity header, `False` otherwise. + """ + return header.lower() in _entity_headers + + +def is_hop_by_hop_header(header: str) -> bool: + """Check if a header is an HTTP/1.1 "Hop-by-Hop" header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an HTTP/1.1 "Hop-by-Hop" header, `False` otherwise. + """ + return header.lower() in _hop_by_hop_headers + + +def parse_cookie( + header: WSGIEnvironment | str | None, + cls: type[ds.MultiDict[str, str]] | None = None, +) -> ds.MultiDict[str, str]: + """Parse a cookie from a string or WSGI environ. + + The same key can be provided multiple times, the values are stored + in-order. The default :class:`MultiDict` will have the first value + first, and all values can be retrieved with + :meth:`MultiDict.getlist`. + + :param header: The cookie header as a string, or a WSGI environ dict + with a ``HTTP_COOKIE`` key. + :param cls: A dict-like class to store the parsed cookies in. + Defaults to :class:`MultiDict`. + + .. versionchanged:: 3.0 + Passing bytes, and the ``charset`` and ``errors`` parameters, were removed. + + .. versionchanged:: 1.0 + Returns a :class:`MultiDict` instead of a ``TypeConversionDict``. + + .. versionchanged:: 0.5 + Returns a :class:`TypeConversionDict` instead of a regular dict. The ``cls`` + parameter was added. + """ + if isinstance(header, dict): + cookie = header.get("HTTP_COOKIE") + else: + cookie = header + + if cookie: + cookie = cookie.encode("latin1").decode() + + return _sansio_http.parse_cookie(cookie=cookie, cls=cls) + + +_cookie_no_quote_re = re.compile(r"[\w!#$%&'()*+\-./:<=>?@\[\]^`{|}~]*", re.A) +_cookie_slash_re = re.compile(rb"[\x00-\x19\",;\\\x7f-\xff]", re.A) +_cookie_slash_map = {b'"': b'\\"', b"\\": b"\\\\"} +_cookie_slash_map.update( + (v.to_bytes(1, "big"), b"\\%03o" % v) + for v in [*range(0x20), *b",;", *range(0x7F, 256)] +) + + +def dump_cookie( + key: str, + value: str = "", + max_age: timedelta | int | None = None, + expires: str | datetime | int | float | None = None, + path: str | None = "/", + domain: str | None = None, + secure: bool = False, + httponly: bool = False, + sync_expires: bool = True, + max_size: int = 4093, + samesite: str | None = None, +) -> str: + """Create a Set-Cookie header without the ``Set-Cookie`` prefix. + + The return value is usually restricted to ascii as the vast majority + of values are properly escaped, but that is no guarantee. It's + tunneled through latin1 as required by :pep:`3333`. + + The return value is not ASCII safe if the key contains unicode + characters. This is technically against the specification but + happens in the wild. It's strongly recommended to not use + non-ASCII values for the keys. + + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. Additionally `timedelta` objects + are accepted, too. + :param expires: should be a `datetime` object or unix timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: Use this if you want to set a cross-domain cookie. For + example, ``domain="example.com"`` will set a cookie + that is readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: The cookie will only be available via HTTPS + :param httponly: disallow JavaScript to access the cookie. This is an + extension to the cookie standard and probably not + supported by all browsers. + :param charset: the encoding for string values. + :param sync_expires: automatically set expires if max_age is defined + but expires not. + :param max_size: Warn if the final header value exceeds this size. The + default, 4093, should be safely `supported by most browsers + `_. Set to 0 to disable this check. + :param samesite: Limits the scope of the cookie such that it will + only be attached to requests if those requests are same-site. + + .. _`cookie`: http://browsercookielimits.squawky.net/ + + .. versionchanged:: 3.0 + Passing bytes, and the ``charset`` parameter, were removed. + + .. versionchanged:: 2.3.3 + The ``path`` parameter is ``/`` by default. + + .. versionchanged:: 2.3.1 + The value allows more characters without quoting. + + .. versionchanged:: 2.3 + ``localhost`` and other names without a dot are allowed for the domain. A + leading dot is ignored. + + .. versionchanged:: 2.3 + The ``path`` parameter is ``None`` by default. + + .. versionchanged:: 1.0.0 + The string ``'None'`` is accepted for ``samesite``. + """ + if path is not None: + # safe = https://url.spec.whatwg.org/#url-path-segment-string + # as well as percent for things that are already quoted + # excluding semicolon since it's part of the header syntax + path = quote(path, safe="%!$&'()*+,/:=@") + + if domain: + domain = domain.partition(":")[0].lstrip(".").encode("idna").decode("ascii") + + if isinstance(max_age, timedelta): + max_age = int(max_age.total_seconds()) + + if expires is not None: + if not isinstance(expires, str): + expires = http_date(expires) + elif max_age is not None and sync_expires: + expires = http_date(datetime.now(tz=timezone.utc).timestamp() + max_age) + + if samesite is not None: + samesite = samesite.title() + + if samesite not in {"Strict", "Lax", "None"}: + raise ValueError("SameSite must be 'Strict', 'Lax', or 'None'.") + + # Quote value if it contains characters not allowed by RFC 6265. Slash-escape with + # three octal digits, which matches http.cookies, although the RFC suggests base64. + if not _cookie_no_quote_re.fullmatch(value): + # Work with bytes here, since a UTF-8 character could be multiple bytes. + value = _cookie_slash_re.sub( + lambda m: _cookie_slash_map[m.group()], value.encode() + ).decode("ascii") + value = f'"{value}"' + + # Send a non-ASCII key as mojibake. Everything else should already be ASCII. + # TODO Remove encoding dance, it seems like clients accept UTF-8 keys + buf = [f"{key.encode().decode('latin1')}={value}"] + + for k, v in ( + ("Domain", domain), + ("Expires", expires), + ("Max-Age", max_age), + ("Secure", secure), + ("HttpOnly", httponly), + ("Path", path), + ("SameSite", samesite), + ): + if v is None or v is False: + continue + + if v is True: + buf.append(k) + continue + + buf.append(f"{k}={v}") + + rv = "; ".join(buf) + + # Warn if the final value of the cookie is larger than the limit. If the cookie is + # too large, then it may be silently ignored by the browser, which can be quite hard + # to debug. + cookie_size = len(rv) + + if max_size and cookie_size > max_size: + value_size = len(value) + warnings.warn( + f"The '{key}' cookie is too large: the value was {value_size} bytes but the" + f" header required {cookie_size - value_size} extra bytes. The final size" + f" was {cookie_size} bytes but the limit is {max_size} bytes. Browsers may" + " silently ignore cookies larger than this.", + stacklevel=2, + ) + + return rv + + +def is_byte_range_valid( + start: int | None, stop: int | None, length: int | None +) -> bool: + """Checks if a given byte content range is valid for the given length. + + .. versionadded:: 0.7 + """ + if (start is None) != (stop is None): + return False + elif start is None: + return length is None or length >= 0 + elif length is None: + return 0 <= start < stop # type: ignore + elif start >= stop: # type: ignore + return False + return 0 <= start < length + + +# circular dependencies +from . import datastructures as ds +from .sansio import http as _sansio_http diff --git a/MLPY/Lib/site-packages/werkzeug/local.py b/MLPY/Lib/site-packages/werkzeug/local.py new file mode 100644 index 0000000000000000000000000000000000000000..302589bbab977ed39eb0a40bfc569350e2564224 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/local.py @@ -0,0 +1,653 @@ +from __future__ import annotations + +import copy +import math +import operator +import typing as t +from contextvars import ContextVar +from functools import partial +from functools import update_wrapper +from operator import attrgetter + +from .wsgi import ClosingIterator + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + +T = t.TypeVar("T") +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def release_local(local: Local | LocalStack[t.Any]) -> None: + """Release the data for the current context in a :class:`Local` or + :class:`LocalStack` without using a :class:`LocalManager`. + + This should not be needed for modern use cases, and may be removed + in the future. + + .. versionadded:: 0.6.1 + """ + local.__release_local__() + + +class Local: + """Create a namespace of context-local data. This wraps a + :class:`ContextVar` containing a :class:`dict` value. + + This may incur a performance penalty compared to using individual + context vars, as it has to copy data to avoid mutating the dict + between nested contexts. + + :param context_var: The :class:`~contextvars.ContextVar` to use as + storage for this local. If not given, one will be created. + Context vars not created at the global scope may interfere with + garbage collection. + + .. versionchanged:: 2.0 + Uses ``ContextVar`` instead of a custom storage implementation. + """ + + __slots__ = ("__storage",) + + def __init__(self, context_var: ContextVar[dict[str, t.Any]] | None = None) -> None: + if context_var is None: + # A ContextVar not created at global scope interferes with + # Python's garbage collection. However, a local only makes + # sense defined at the global scope as well, in which case + # the GC issue doesn't seem relevant. + context_var = ContextVar(f"werkzeug.Local<{id(self)}>.storage") + + object.__setattr__(self, "_Local__storage", context_var) + + def __iter__(self) -> t.Iterator[tuple[str, t.Any]]: + return iter(self.__storage.get({}).items()) + + def __call__( + self, name: str, *, unbound_message: str | None = None + ) -> LocalProxy[t.Any]: + """Create a :class:`LocalProxy` that access an attribute on this + local namespace. + + :param name: Proxy this attribute. + :param unbound_message: The error message that the proxy will + show if the attribute isn't set. + """ + return LocalProxy(self, name, unbound_message=unbound_message) + + def __release_local__(self) -> None: + self.__storage.set({}) + + def __getattr__(self, name: str) -> t.Any: + values = self.__storage.get({}) + + if name in values: + return values[name] + + raise AttributeError(name) + + def __setattr__(self, name: str, value: t.Any) -> None: + values = self.__storage.get({}).copy() + values[name] = value + self.__storage.set(values) + + def __delattr__(self, name: str) -> None: + values = self.__storage.get({}) + + if name in values: + values = values.copy() + del values[name] + self.__storage.set(values) + else: + raise AttributeError(name) + + +class LocalStack(t.Generic[T]): + """Create a stack of context-local data. This wraps a + :class:`ContextVar` containing a :class:`list` value. + + This may incur a performance penalty compared to using individual + context vars, as it has to copy data to avoid mutating the list + between nested contexts. + + :param context_var: The :class:`~contextvars.ContextVar` to use as + storage for this local. If not given, one will be created. + Context vars not created at the global scope may interfere with + garbage collection. + + .. versionchanged:: 2.0 + Uses ``ContextVar`` instead of a custom storage implementation. + + .. versionadded:: 0.6.1 + """ + + __slots__ = ("_storage",) + + def __init__(self, context_var: ContextVar[list[T]] | None = None) -> None: + if context_var is None: + # A ContextVar not created at global scope interferes with + # Python's garbage collection. However, a local only makes + # sense defined at the global scope as well, in which case + # the GC issue doesn't seem relevant. + context_var = ContextVar(f"werkzeug.LocalStack<{id(self)}>.storage") + + self._storage = context_var + + def __release_local__(self) -> None: + self._storage.set([]) + + def push(self, obj: T) -> list[T]: + """Add a new item to the top of the stack.""" + stack = self._storage.get([]).copy() + stack.append(obj) + self._storage.set(stack) + return stack + + def pop(self) -> T | None: + """Remove the top item from the stack and return it. If the + stack is empty, return ``None``. + """ + stack = self._storage.get([]) + + if len(stack) == 0: + return None + + rv = stack[-1] + self._storage.set(stack[:-1]) + return rv + + @property + def top(self) -> T | None: + """The topmost item on the stack. If the stack is empty, + `None` is returned. + """ + stack = self._storage.get([]) + + if len(stack) == 0: + return None + + return stack[-1] + + def __call__( + self, name: str | None = None, *, unbound_message: str | None = None + ) -> LocalProxy[t.Any]: + """Create a :class:`LocalProxy` that accesses the top of this + local stack. + + :param name: If given, the proxy access this attribute of the + top item, rather than the item itself. + :param unbound_message: The error message that the proxy will + show if the stack is empty. + """ + return LocalProxy(self, name, unbound_message=unbound_message) + + +class LocalManager: + """Manage releasing the data for the current context in one or more + :class:`Local` and :class:`LocalStack` objects. + + This should not be needed for modern use cases, and may be removed + in the future. + + :param locals: A local or list of locals to manage. + + .. versionchanged:: 2.1 + The ``ident_func`` was removed. + + .. versionchanged:: 0.7 + The ``ident_func`` parameter was added. + + .. versionchanged:: 0.6.1 + The :func:`release_local` function can be used instead of a + manager. + """ + + __slots__ = ("locals",) + + def __init__( + self, + locals: None + | (Local | LocalStack[t.Any] | t.Iterable[Local | LocalStack[t.Any]]) = None, + ) -> None: + if locals is None: + self.locals = [] + elif isinstance(locals, Local): + self.locals = [locals] + else: + self.locals = list(locals) # type: ignore[arg-type] + + def cleanup(self) -> None: + """Release the data in the locals for this context. Call this at + the end of each request or use :meth:`make_middleware`. + """ + for local in self.locals: + release_local(local) + + def make_middleware(self, app: WSGIApplication) -> WSGIApplication: + """Wrap a WSGI application so that local data is released + automatically after the response has been sent for a request. + """ + + def application( + environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + return ClosingIterator(app(environ, start_response), self.cleanup) + + return application + + def middleware(self, func: WSGIApplication) -> WSGIApplication: + """Like :meth:`make_middleware` but used as a decorator on the + WSGI application function. + + .. code-block:: python + + @manager.middleware + def application(environ, start_response): + ... + """ + return update_wrapper(self.make_middleware(func), func) + + def __repr__(self) -> str: + return f"<{type(self).__name__} storages: {len(self.locals)}>" + + +class _ProxyLookup: + """Descriptor that handles proxied attribute lookup for + :class:`LocalProxy`. + + :param f: The built-in function this attribute is accessed through. + Instead of looking up the special method, the function call + is redone on the object. + :param fallback: Return this function if the proxy is unbound + instead of raising a :exc:`RuntimeError`. + :param is_attr: This proxied name is an attribute, not a function. + Call the fallback immediately to get the value. + :param class_value: Value to return when accessed from the + ``LocalProxy`` class directly. Used for ``__doc__`` so building + docs still works. + """ + + __slots__ = ("bind_f", "fallback", "is_attr", "class_value", "name") + + def __init__( + self, + f: t.Callable[..., t.Any] | None = None, + fallback: t.Callable[[LocalProxy[t.Any]], t.Any] | None = None, + class_value: t.Any | None = None, + is_attr: bool = False, + ) -> None: + bind_f: t.Callable[[LocalProxy[t.Any], t.Any], t.Callable[..., t.Any]] | None + + if hasattr(f, "__get__"): + # A Python function, can be turned into a bound method. + + def bind_f( + instance: LocalProxy[t.Any], obj: t.Any + ) -> t.Callable[..., t.Any]: + return f.__get__(obj, type(obj)) # type: ignore + + elif f is not None: + # A C function, use partial to bind the first argument. + + def bind_f( + instance: LocalProxy[t.Any], obj: t.Any + ) -> t.Callable[..., t.Any]: + return partial(f, obj) + + else: + # Use getattr, which will produce a bound method. + bind_f = None + + self.bind_f = bind_f + self.fallback = fallback + self.class_value = class_value + self.is_attr = is_attr + + def __set_name__(self, owner: LocalProxy[t.Any], name: str) -> None: + self.name = name + + def __get__(self, instance: LocalProxy[t.Any], owner: type | None = None) -> t.Any: + if instance is None: + if self.class_value is not None: + return self.class_value + + return self + + try: + obj = instance._get_current_object() + except RuntimeError: + if self.fallback is None: + raise + + fallback = self.fallback.__get__(instance, owner) + + if self.is_attr: + # __class__ and __doc__ are attributes, not methods. + # Call the fallback to get the value. + return fallback() + + return fallback + + if self.bind_f is not None: + return self.bind_f(instance, obj) + + return getattr(obj, self.name) + + def __repr__(self) -> str: + return f"proxy {self.name}" + + def __call__( + self, instance: LocalProxy[t.Any], *args: t.Any, **kwargs: t.Any + ) -> t.Any: + """Support calling unbound methods from the class. For example, + this happens with ``copy.copy``, which does + ``type(x).__copy__(x)``. ``type(x)`` can't be proxied, so it + returns the proxy type and descriptor. + """ + return self.__get__(instance, type(instance))(*args, **kwargs) + + +class _ProxyIOp(_ProxyLookup): + """Look up an augmented assignment method on a proxied object. The + method is wrapped to return the proxy instead of the object. + """ + + __slots__ = () + + def __init__( + self, + f: t.Callable[..., t.Any] | None = None, + fallback: t.Callable[[LocalProxy[t.Any]], t.Any] | None = None, + ) -> None: + super().__init__(f, fallback) + + def bind_f(instance: LocalProxy[t.Any], obj: t.Any) -> t.Callable[..., t.Any]: + def i_op(self: t.Any, other: t.Any) -> LocalProxy[t.Any]: + f(self, other) # type: ignore + return instance + + return i_op.__get__(obj, type(obj)) # type: ignore + + self.bind_f = bind_f + + +def _l_to_r_op(op: F) -> F: + """Swap the argument order to turn an l-op into an r-op.""" + + def r_op(obj: t.Any, other: t.Any) -> t.Any: + return op(other, obj) + + return t.cast(F, r_op) + + +def _identity(o: T) -> T: + return o + + +class LocalProxy(t.Generic[T]): + """A proxy to the object bound to a context-local object. All + operations on the proxy are forwarded to the bound object. If no + object is bound, a ``RuntimeError`` is raised. + + :param local: The context-local object that provides the proxied + object. + :param name: Proxy this attribute from the proxied object. + :param unbound_message: The error message to show if the + context-local object is unbound. + + Proxy a :class:`~contextvars.ContextVar` to make it easier to + access. Pass a name to proxy that attribute. + + .. code-block:: python + + _request_var = ContextVar("request") + request = LocalProxy(_request_var) + session = LocalProxy(_request_var, "session") + + Proxy an attribute on a :class:`Local` namespace by calling the + local with the attribute name: + + .. code-block:: python + + data = Local() + user = data("user") + + Proxy the top item on a :class:`LocalStack` by calling the local. + Pass a name to proxy that attribute. + + .. code-block:: + + app_stack = LocalStack() + current_app = app_stack() + g = app_stack("g") + + Pass a function to proxy the return value from that function. This + was previously used to access attributes of local objects before + that was supported directly. + + .. code-block:: python + + session = LocalProxy(lambda: request.session) + + ``__repr__`` and ``__class__`` are proxied, so ``repr(x)`` and + ``isinstance(x, cls)`` will look like the proxied object. Use + ``issubclass(type(x), LocalProxy)`` to check if an object is a + proxy. + + .. code-block:: python + + repr(user) # + isinstance(user, User) # True + issubclass(type(user), LocalProxy) # True + + .. versionchanged:: 2.2.2 + ``__wrapped__`` is set when wrapping an object, not only when + wrapping a function, to prevent doctest from failing. + + .. versionchanged:: 2.2 + Can proxy a ``ContextVar`` or ``LocalStack`` directly. + + .. versionchanged:: 2.2 + The ``name`` parameter can be used with any proxied object, not + only ``Local``. + + .. versionchanged:: 2.2 + Added the ``unbound_message`` parameter. + + .. versionchanged:: 2.0 + Updated proxied attributes and methods to reflect the current + data model. + + .. versionchanged:: 0.6.1 + The class can be instantiated with a callable. + """ + + __slots__ = ("__wrapped", "_get_current_object") + + _get_current_object: t.Callable[[], T] + """Return the current object this proxy is bound to. If the proxy is + unbound, this raises a ``RuntimeError``. + + This should be used if you need to pass the object to something that + doesn't understand the proxy. It can also be useful for performance + if you are accessing the object multiple times in a function, rather + than going through the proxy multiple times. + """ + + def __init__( + self, + local: ContextVar[T] | Local | LocalStack[T] | t.Callable[[], T], + name: str | None = None, + *, + unbound_message: str | None = None, + ) -> None: + if name is None: + get_name = _identity + else: + get_name = attrgetter(name) # type: ignore[assignment] + + if unbound_message is None: + unbound_message = "object is not bound" + + if isinstance(local, Local): + if name is None: + raise TypeError("'name' is required when proxying a 'Local' object.") + + def _get_current_object() -> T: + try: + return get_name(local) # type: ignore[return-value] + except AttributeError: + raise RuntimeError(unbound_message) from None + + elif isinstance(local, LocalStack): + + def _get_current_object() -> T: + obj = local.top + + if obj is None: + raise RuntimeError(unbound_message) + + return get_name(obj) + + elif isinstance(local, ContextVar): + + def _get_current_object() -> T: + try: + obj = local.get() + except LookupError: + raise RuntimeError(unbound_message) from None + + return get_name(obj) + + elif callable(local): + + def _get_current_object() -> T: + return get_name(local()) + + else: + raise TypeError(f"Don't know how to proxy '{type(local)}'.") + + object.__setattr__(self, "_LocalProxy__wrapped", local) + object.__setattr__(self, "_get_current_object", _get_current_object) + + __doc__ = _ProxyLookup( # type: ignore[assignment] + class_value=__doc__, fallback=lambda self: type(self).__doc__, is_attr=True + ) + __wrapped__ = _ProxyLookup( + fallback=lambda self: self._LocalProxy__wrapped, # type: ignore[attr-defined] + is_attr=True, + ) + # __del__ should only delete the proxy + __repr__ = _ProxyLookup( # type: ignore[assignment] + repr, fallback=lambda self: f"<{type(self).__name__} unbound>" + ) + __str__ = _ProxyLookup(str) # type: ignore[assignment] + __bytes__ = _ProxyLookup(bytes) + __format__ = _ProxyLookup() # type: ignore[assignment] + __lt__ = _ProxyLookup(operator.lt) + __le__ = _ProxyLookup(operator.le) + __eq__ = _ProxyLookup(operator.eq) # type: ignore[assignment] + __ne__ = _ProxyLookup(operator.ne) # type: ignore[assignment] + __gt__ = _ProxyLookup(operator.gt) + __ge__ = _ProxyLookup(operator.ge) + __hash__ = _ProxyLookup(hash) # type: ignore[assignment] + __bool__ = _ProxyLookup(bool, fallback=lambda self: False) + __getattr__ = _ProxyLookup(getattr) + # __getattribute__ triggered through __getattr__ + __setattr__ = _ProxyLookup(setattr) # type: ignore[assignment] + __delattr__ = _ProxyLookup(delattr) # type: ignore[assignment] + __dir__ = _ProxyLookup(dir, fallback=lambda self: []) # type: ignore[assignment] + # __get__ (proxying descriptor not supported) + # __set__ (descriptor) + # __delete__ (descriptor) + # __set_name__ (descriptor) + # __objclass__ (descriptor) + # __slots__ used by proxy itself + # __dict__ (__getattr__) + # __weakref__ (__getattr__) + # __init_subclass__ (proxying metaclass not supported) + # __prepare__ (metaclass) + __class__ = _ProxyLookup(fallback=lambda self: type(self), is_attr=True) # type: ignore[assignment] + __instancecheck__ = _ProxyLookup(lambda self, other: isinstance(other, self)) + __subclasscheck__ = _ProxyLookup(lambda self, other: issubclass(other, self)) + # __class_getitem__ triggered through __getitem__ + __call__ = _ProxyLookup(lambda self, *args, **kwargs: self(*args, **kwargs)) + __len__ = _ProxyLookup(len) + __length_hint__ = _ProxyLookup(operator.length_hint) + __getitem__ = _ProxyLookup(operator.getitem) + __setitem__ = _ProxyLookup(operator.setitem) + __delitem__ = _ProxyLookup(operator.delitem) + # __missing__ triggered through __getitem__ + __iter__ = _ProxyLookup(iter) + __next__ = _ProxyLookup(next) + __reversed__ = _ProxyLookup(reversed) + __contains__ = _ProxyLookup(operator.contains) + __add__ = _ProxyLookup(operator.add) + __sub__ = _ProxyLookup(operator.sub) + __mul__ = _ProxyLookup(operator.mul) + __matmul__ = _ProxyLookup(operator.matmul) + __truediv__ = _ProxyLookup(operator.truediv) + __floordiv__ = _ProxyLookup(operator.floordiv) + __mod__ = _ProxyLookup(operator.mod) + __divmod__ = _ProxyLookup(divmod) + __pow__ = _ProxyLookup(pow) + __lshift__ = _ProxyLookup(operator.lshift) + __rshift__ = _ProxyLookup(operator.rshift) + __and__ = _ProxyLookup(operator.and_) + __xor__ = _ProxyLookup(operator.xor) + __or__ = _ProxyLookup(operator.or_) + __radd__ = _ProxyLookup(_l_to_r_op(operator.add)) + __rsub__ = _ProxyLookup(_l_to_r_op(operator.sub)) + __rmul__ = _ProxyLookup(_l_to_r_op(operator.mul)) + __rmatmul__ = _ProxyLookup(_l_to_r_op(operator.matmul)) + __rtruediv__ = _ProxyLookup(_l_to_r_op(operator.truediv)) + __rfloordiv__ = _ProxyLookup(_l_to_r_op(operator.floordiv)) + __rmod__ = _ProxyLookup(_l_to_r_op(operator.mod)) + __rdivmod__ = _ProxyLookup(_l_to_r_op(divmod)) + __rpow__ = _ProxyLookup(_l_to_r_op(pow)) + __rlshift__ = _ProxyLookup(_l_to_r_op(operator.lshift)) + __rrshift__ = _ProxyLookup(_l_to_r_op(operator.rshift)) + __rand__ = _ProxyLookup(_l_to_r_op(operator.and_)) + __rxor__ = _ProxyLookup(_l_to_r_op(operator.xor)) + __ror__ = _ProxyLookup(_l_to_r_op(operator.or_)) + __iadd__ = _ProxyIOp(operator.iadd) + __isub__ = _ProxyIOp(operator.isub) + __imul__ = _ProxyIOp(operator.imul) + __imatmul__ = _ProxyIOp(operator.imatmul) + __itruediv__ = _ProxyIOp(operator.itruediv) + __ifloordiv__ = _ProxyIOp(operator.ifloordiv) + __imod__ = _ProxyIOp(operator.imod) + __ipow__ = _ProxyIOp(operator.ipow) + __ilshift__ = _ProxyIOp(operator.ilshift) + __irshift__ = _ProxyIOp(operator.irshift) + __iand__ = _ProxyIOp(operator.iand) + __ixor__ = _ProxyIOp(operator.ixor) + __ior__ = _ProxyIOp(operator.ior) + __neg__ = _ProxyLookup(operator.neg) + __pos__ = _ProxyLookup(operator.pos) + __abs__ = _ProxyLookup(abs) + __invert__ = _ProxyLookup(operator.invert) + __complex__ = _ProxyLookup(complex) + __int__ = _ProxyLookup(int) + __float__ = _ProxyLookup(float) + __index__ = _ProxyLookup(operator.index) + __round__ = _ProxyLookup(round) + __trunc__ = _ProxyLookup(math.trunc) + __floor__ = _ProxyLookup(math.floor) + __ceil__ = _ProxyLookup(math.ceil) + __enter__ = _ProxyLookup() + __exit__ = _ProxyLookup() + __await__ = _ProxyLookup() + __aiter__ = _ProxyLookup() + __anext__ = _ProxyLookup() + __aenter__ = _ProxyLookup() + __aexit__ = _ProxyLookup() + __copy__ = _ProxyLookup(copy.copy) + __deepcopy__ = _ProxyLookup(copy.deepcopy) + # __getnewargs_ex__ (pickle through proxy not supported) + # __getnewargs__ (pickle) + # __getstate__ (pickle) + # __setstate__ (pickle) + # __reduce__ (pickle) + # __reduce_ex__ (pickle) diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__init__.py b/MLPY/Lib/site-packages/werkzeug/middleware/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48202764dba20f985079ce37cc11025324b8ab5a Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9018d9acb53704cc4cabe077a336341a267f276a Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a73c3402717811c0b8eaa5be28bdd2bdb6fb8f4 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/lint.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/lint.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a16b76e70568aa102749edd2be20c2d1a7080b01 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/lint.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..069532e526dfa98b03ed8e1d8f4fd0f3c312ad6d Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa80eda5177c60eb4bfc38221e3045323444392f Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3892ef64c93d60a0f658b30a11d4517416e55497 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/dispatcher.py b/MLPY/Lib/site-packages/werkzeug/middleware/dispatcher.py new file mode 100644 index 0000000000000000000000000000000000000000..e11bacc527b2c2ce82ff62ea0d4a9c3ef5514b12 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/middleware/dispatcher.py @@ -0,0 +1,81 @@ +""" +Application Dispatcher +====================== + +This middleware creates a single WSGI application that dispatches to +multiple other WSGI applications mounted at different URL paths. + +A common example is writing a Single Page Application, where you have a +backend API and a frontend written in JavaScript that does the routing +in the browser rather than requesting different pages from the server. +The frontend is a single HTML and JS file that should be served for any +path besides "/api". + +This example dispatches to an API app under "/api", an admin app +under "/admin", and an app that serves frontend files for all other +requests:: + + app = DispatcherMiddleware(serve_frontend, { + '/api': api_app, + '/admin': admin_app, + }) + +In production, you might instead handle this at the HTTP server level, +serving files or proxying to application servers based on location. The +API and admin apps would each be deployed with a separate WSGI server, +and the static files would be served directly by the HTTP server. + +.. autoclass:: DispatcherMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" + +from __future__ import annotations + +import typing as t + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class DispatcherMiddleware: + """Combine multiple applications as a single WSGI application. + Requests are dispatched to an application based on the path it is + mounted under. + + :param app: The WSGI application to dispatch to if the request + doesn't match a mounted path. + :param mounts: Maps path prefixes to applications for dispatching. + """ + + def __init__( + self, + app: WSGIApplication, + mounts: dict[str, WSGIApplication] | None = None, + ) -> None: + self.app = app + self.mounts = mounts or {} + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + script = environ.get("PATH_INFO", "") + path_info = "" + + while "/" in script: + if script in self.mounts: + app = self.mounts[script] + break + + script, last_item = script.rsplit("/", 1) + path_info = f"/{last_item}{path_info}" + else: + app = self.mounts.get(script, self.app) + + original_script_name = environ.get("SCRIPT_NAME", "") + environ["SCRIPT_NAME"] = original_script_name + script + environ["PATH_INFO"] = path_info + return app(environ, start_response) diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/http_proxy.py b/MLPY/Lib/site-packages/werkzeug/middleware/http_proxy.py new file mode 100644 index 0000000000000000000000000000000000000000..5e239156aa1aef21a9ca762281ecb1185d70ed20 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/middleware/http_proxy.py @@ -0,0 +1,236 @@ +""" +Basic HTTP Proxy +================ + +.. autoclass:: ProxyMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" + +from __future__ import annotations + +import typing as t +from http import client +from urllib.parse import quote +from urllib.parse import urlsplit + +from ..datastructures import EnvironHeaders +from ..http import is_hop_by_hop_header +from ..wsgi import get_input_stream + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProxyMiddleware: + """Proxy requests under a path to an external server, routing other + requests to the app. + + This middleware can only proxy HTTP requests, as HTTP is the only + protocol handled by the WSGI server. Other protocols, such as + WebSocket requests, cannot be proxied at this layer. This should + only be used for development, in production a real proxy server + should be used. + + The middleware takes a dict mapping a path prefix to a dict + describing the host to be proxied to:: + + app = ProxyMiddleware(app, { + "/static/": { + "target": "http://127.0.0.1:5001/", + } + }) + + Each host has the following options: + + ``target``: + The target URL to dispatch to. This is required. + ``remove_prefix``: + Whether to remove the prefix from the URL before dispatching it + to the target. The default is ``False``. + ``host``: + ``""`` (default): + The host header is automatically rewritten to the URL of the + target. + ``None``: + The host header is unmodified from the client request. + Any other value: + The host header is overwritten with the value. + ``headers``: + A dictionary of headers to be sent with the request to the + target. The default is ``{}``. + ``ssl_context``: + A :class:`ssl.SSLContext` defining how to verify requests if the + target is HTTPS. The default is ``None``. + + In the example above, everything under ``"/static/"`` is proxied to + the server on port 5001. The host header is rewritten to the target, + and the ``"/static/"`` prefix is removed from the URLs. + + :param app: The WSGI application to wrap. + :param targets: Proxy target configurations. See description above. + :param chunk_size: Size of chunks to read from input stream and + write to target. + :param timeout: Seconds before an operation to a target fails. + + .. versionadded:: 0.14 + """ + + def __init__( + self, + app: WSGIApplication, + targets: t.Mapping[str, dict[str, t.Any]], + chunk_size: int = 2 << 13, + timeout: int = 10, + ) -> None: + def _set_defaults(opts: dict[str, t.Any]) -> dict[str, t.Any]: + opts.setdefault("remove_prefix", False) + opts.setdefault("host", "") + opts.setdefault("headers", {}) + opts.setdefault("ssl_context", None) + return opts + + self.app = app + self.targets = { + f"/{k.strip('/')}/": _set_defaults(v) for k, v in targets.items() + } + self.chunk_size = chunk_size + self.timeout = timeout + + def proxy_to( + self, opts: dict[str, t.Any], path: str, prefix: str + ) -> WSGIApplication: + target = urlsplit(opts["target"]) + # socket can handle unicode host, but header must be ascii + host = target.hostname.encode("idna").decode("ascii") + + def application( + environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + headers = list(EnvironHeaders(environ).items()) + headers[:] = [ + (k, v) + for k, v in headers + if not is_hop_by_hop_header(k) + and k.lower() not in ("content-length", "host") + ] + headers.append(("Connection", "close")) + + if opts["host"] == "": + headers.append(("Host", host)) + elif opts["host"] is None: + headers.append(("Host", environ["HTTP_HOST"])) + else: + headers.append(("Host", opts["host"])) + + headers.extend(opts["headers"].items()) + remote_path = path + + if opts["remove_prefix"]: + remote_path = remote_path[len(prefix) :].lstrip("/") + remote_path = f"{target.path.rstrip('/')}/{remote_path}" + + content_length = environ.get("CONTENT_LENGTH") + chunked = False + + if content_length not in ("", None): + headers.append(("Content-Length", content_length)) # type: ignore + elif content_length is not None: + headers.append(("Transfer-Encoding", "chunked")) + chunked = True + + try: + if target.scheme == "http": + con = client.HTTPConnection( + host, target.port or 80, timeout=self.timeout + ) + elif target.scheme == "https": + con = client.HTTPSConnection( + host, + target.port or 443, + timeout=self.timeout, + context=opts["ssl_context"], + ) + else: + raise RuntimeError( + "Target scheme must be 'http' or 'https', got" + f" {target.scheme!r}." + ) + + con.connect() + # safe = https://url.spec.whatwg.org/#url-path-segment-string + # as well as percent for things that are already quoted + remote_url = quote(remote_path, safe="!$&'()*+,/:;=@%") + querystring = environ["QUERY_STRING"] + + if querystring: + remote_url = f"{remote_url}?{querystring}" + + con.putrequest(environ["REQUEST_METHOD"], remote_url, skip_host=True) + + for k, v in headers: + if k.lower() == "connection": + v = "close" + + con.putheader(k, v) + + con.endheaders() + stream = get_input_stream(environ) + + while True: + data = stream.read(self.chunk_size) + + if not data: + break + + if chunked: + con.send(b"%x\r\n%s\r\n" % (len(data), data)) + else: + con.send(data) + + resp = con.getresponse() + except OSError: + from ..exceptions import BadGateway + + return BadGateway()(environ, start_response) + + start_response( + f"{resp.status} {resp.reason}", + [ + (k.title(), v) + for k, v in resp.getheaders() + if not is_hop_by_hop_header(k) + ], + ) + + def read() -> t.Iterator[bytes]: + while True: + try: + data = resp.read(self.chunk_size) + except OSError: + break + + if not data: + break + + yield data + + return read() + + return application + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + path = environ["PATH_INFO"] + app = self.app + + for prefix, opts in self.targets.items(): + if path.startswith(prefix): + app = self.proxy_to(opts, path, prefix) + break + + return app(environ, start_response) diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/lint.py b/MLPY/Lib/site-packages/werkzeug/middleware/lint.py new file mode 100644 index 0000000000000000000000000000000000000000..de93b526a44aab77b1b623e295db10edf7f674a5 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/middleware/lint.py @@ -0,0 +1,439 @@ +""" +WSGI Protocol Linter +==================== + +This module provides a middleware that performs sanity checks on the +behavior of the WSGI server and application. It checks that the +:pep:`3333` WSGI spec is properly implemented. It also warns on some +common HTTP errors such as non-empty responses for 304 status codes. + +.. autoclass:: LintMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" + +from __future__ import annotations + +import typing as t +from types import TracebackType +from urllib.parse import urlparse +from warnings import warn + +from ..datastructures import Headers +from ..http import is_entity_header +from ..wsgi import FileWrapper + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class WSGIWarning(Warning): + """Warning class for WSGI warnings.""" + + +class HTTPWarning(Warning): + """Warning class for HTTP warnings.""" + + +def check_type(context: str, obj: object, need: type = str) -> None: + if type(obj) is not need: + warn( + f"{context!r} requires {need.__name__!r}, got {type(obj).__name__!r}.", + WSGIWarning, + stacklevel=3, + ) + + +class InputStream: + def __init__(self, stream: t.IO[bytes]) -> None: + self._stream = stream + + def read(self, *args: t.Any) -> bytes: + if len(args) == 0: + warn( + "WSGI does not guarantee an EOF marker on the input stream, thus making" + " calls to 'wsgi.input.read()' unsafe. Conforming servers may never" + " return from this call.", + WSGIWarning, + stacklevel=2, + ) + elif len(args) != 1: + warn( + "Too many parameters passed to 'wsgi.input.read()'.", + WSGIWarning, + stacklevel=2, + ) + return self._stream.read(*args) + + def readline(self, *args: t.Any) -> bytes: + if len(args) == 0: + warn( + "Calls to 'wsgi.input.readline()' without arguments are unsafe. Use" + " 'wsgi.input.read()' instead.", + WSGIWarning, + stacklevel=2, + ) + elif len(args) == 1: + warn( + "'wsgi.input.readline()' was called with a size hint. WSGI does not" + " support this, although it's available on all major servers.", + WSGIWarning, + stacklevel=2, + ) + else: + raise TypeError("Too many arguments passed to 'wsgi.input.readline()'.") + return self._stream.readline(*args) + + def __iter__(self) -> t.Iterator[bytes]: + try: + return iter(self._stream) + except TypeError: + warn("'wsgi.input' is not iterable.", WSGIWarning, stacklevel=2) + return iter(()) + + def close(self) -> None: + warn("The application closed the input stream!", WSGIWarning, stacklevel=2) + self._stream.close() + + +class ErrorStream: + def __init__(self, stream: t.IO[str]) -> None: + self._stream = stream + + def write(self, s: str) -> None: + check_type("wsgi.error.write()", s, str) + self._stream.write(s) + + def flush(self) -> None: + self._stream.flush() + + def writelines(self, seq: t.Iterable[str]) -> None: + for line in seq: + self.write(line) + + def close(self) -> None: + warn("The application closed the error stream!", WSGIWarning, stacklevel=2) + self._stream.close() + + +class GuardedWrite: + def __init__(self, write: t.Callable[[bytes], object], chunks: list[int]) -> None: + self._write = write + self._chunks = chunks + + def __call__(self, s: bytes) -> None: + check_type("write()", s, bytes) + self._write(s) + self._chunks.append(len(s)) + + +class GuardedIterator: + def __init__( + self, + iterator: t.Iterable[bytes], + headers_set: tuple[int, Headers], + chunks: list[int], + ) -> None: + self._iterator = iterator + self._next = iter(iterator).__next__ + self.closed = False + self.headers_set = headers_set + self.chunks = chunks + + def __iter__(self) -> GuardedIterator: + return self + + def __next__(self) -> bytes: + if self.closed: + warn("Iterated over closed 'app_iter'.", WSGIWarning, stacklevel=2) + + rv = self._next() + + if not self.headers_set: + warn( + "The application returned before it started the response.", + WSGIWarning, + stacklevel=2, + ) + + check_type("application iterator items", rv, bytes) + self.chunks.append(len(rv)) + return rv + + def close(self) -> None: + self.closed = True + + if hasattr(self._iterator, "close"): + self._iterator.close() + + if self.headers_set: + status_code, headers = self.headers_set + bytes_sent = sum(self.chunks) + content_length = headers.get("content-length", type=int) + + if status_code == 304: + for key, _value in headers: + key = key.lower() + if key not in ("expires", "content-location") and is_entity_header( + key + ): + warn( + f"Entity header {key!r} found in 304 response.", + HTTPWarning, + stacklevel=2, + ) + if bytes_sent: + warn( + "304 responses must not have a body.", + HTTPWarning, + stacklevel=2, + ) + elif 100 <= status_code < 200 or status_code == 204: + if content_length != 0: + warn( + f"{status_code} responses must have an empty content length.", + HTTPWarning, + stacklevel=2, + ) + if bytes_sent: + warn( + f"{status_code} responses must not have a body.", + HTTPWarning, + stacklevel=2, + ) + elif content_length is not None and content_length != bytes_sent: + warn( + "Content-Length and the number of bytes sent to the" + " client do not match.", + WSGIWarning, + stacklevel=2, + ) + + def __del__(self) -> None: + if not self.closed: + try: + warn( + "Iterator was garbage collected before it was closed.", + WSGIWarning, + stacklevel=2, + ) + except Exception: + pass + + +class LintMiddleware: + """Warns about common errors in the WSGI and HTTP behavior of the + server and wrapped application. Some of the issues it checks are: + + - invalid status codes + - non-bytes sent to the WSGI server + - strings returned from the WSGI application + - non-empty conditional responses + - unquoted etags + - relative URLs in the Location header + - unsafe calls to wsgi.input + - unclosed iterators + + Error information is emitted using the :mod:`warnings` module. + + :param app: The WSGI application to wrap. + + .. code-block:: python + + from werkzeug.middleware.lint import LintMiddleware + app = LintMiddleware(app) + """ + + def __init__(self, app: WSGIApplication) -> None: + self.app = app + + def check_environ(self, environ: WSGIEnvironment) -> None: + if type(environ) is not dict: # noqa: E721 + warn( + "WSGI environment is not a standard Python dict.", + WSGIWarning, + stacklevel=4, + ) + for key in ( + "REQUEST_METHOD", + "SERVER_NAME", + "SERVER_PORT", + "wsgi.version", + "wsgi.input", + "wsgi.errors", + "wsgi.multithread", + "wsgi.multiprocess", + "wsgi.run_once", + ): + if key not in environ: + warn( + f"Required environment key {key!r} not found", + WSGIWarning, + stacklevel=3, + ) + if environ["wsgi.version"] != (1, 0): + warn("Environ is not a WSGI 1.0 environ.", WSGIWarning, stacklevel=3) + + script_name = environ.get("SCRIPT_NAME", "") + path_info = environ.get("PATH_INFO", "") + + if script_name and script_name[0] != "/": + warn( + f"'SCRIPT_NAME' does not start with a slash: {script_name!r}", + WSGIWarning, + stacklevel=3, + ) + + if path_info and path_info[0] != "/": + warn( + f"'PATH_INFO' does not start with a slash: {path_info!r}", + WSGIWarning, + stacklevel=3, + ) + + def check_start_response( + self, + status: str, + headers: list[tuple[str, str]], + exc_info: None | (tuple[type[BaseException], BaseException, TracebackType]), + ) -> tuple[int, Headers]: + check_type("status", status, str) + status_code_str = status.split(None, 1)[0] + + if len(status_code_str) != 3 or not status_code_str.isdecimal(): + warn("Status code must be three digits.", WSGIWarning, stacklevel=3) + + if len(status) < 4 or status[3] != " ": + warn( + f"Invalid value for status {status!r}. Valid status strings are three" + " digits, a space and a status explanation.", + WSGIWarning, + stacklevel=3, + ) + + status_code = int(status_code_str) + + if status_code < 100: + warn("Status code < 100 detected.", WSGIWarning, stacklevel=3) + + if type(headers) is not list: # noqa: E721 + warn("Header list is not a list.", WSGIWarning, stacklevel=3) + + for item in headers: + if type(item) is not tuple or len(item) != 2: + warn("Header items must be 2-item tuples.", WSGIWarning, stacklevel=3) + name, value = item + if type(name) is not str or type(value) is not str: # noqa: E721 + warn( + "Header keys and values must be strings.", WSGIWarning, stacklevel=3 + ) + if name.lower() == "status": + warn( + "The status header is not supported due to" + " conflicts with the CGI spec.", + WSGIWarning, + stacklevel=3, + ) + + if exc_info is not None and not isinstance(exc_info, tuple): + warn("Invalid value for exc_info.", WSGIWarning, stacklevel=3) + + headers_obj = Headers(headers) + self.check_headers(headers_obj) + + return status_code, headers_obj + + def check_headers(self, headers: Headers) -> None: + etag = headers.get("etag") + + if etag is not None: + if etag.startswith(("W/", "w/")): + if etag.startswith("w/"): + warn( + "Weak etag indicator should be upper case.", + HTTPWarning, + stacklevel=4, + ) + + etag = etag[2:] + + if not (etag[:1] == etag[-1:] == '"'): + warn("Unquoted etag emitted.", HTTPWarning, stacklevel=4) + + location = headers.get("location") + + if location is not None: + if not urlparse(location).netloc: + warn( + "Absolute URLs required for location header.", + HTTPWarning, + stacklevel=4, + ) + + def check_iterator(self, app_iter: t.Iterable[bytes]) -> None: + if isinstance(app_iter, str): + warn( + "The application returned a string. The response will send one" + " character at a time to the client, which will kill performance." + " Return a list or iterable instead.", + WSGIWarning, + stacklevel=3, + ) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Iterable[bytes]: + if len(args) != 2: + warn("A WSGI app takes two arguments.", WSGIWarning, stacklevel=2) + + if kwargs: + warn( + "A WSGI app does not take keyword arguments.", WSGIWarning, stacklevel=2 + ) + + environ: WSGIEnvironment = args[0] + start_response: StartResponse = args[1] + + self.check_environ(environ) + environ["wsgi.input"] = InputStream(environ["wsgi.input"]) + environ["wsgi.errors"] = ErrorStream(environ["wsgi.errors"]) + + # Hook our own file wrapper in so that applications will always + # iterate to the end and we can check the content length. + environ["wsgi.file_wrapper"] = FileWrapper + + headers_set: list[t.Any] = [] + chunks: list[int] = [] + + def checking_start_response( + *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[bytes], None]: + if len(args) not in {2, 3}: + warn( + f"Invalid number of arguments: {len(args)}, expected 2 or 3.", + WSGIWarning, + stacklevel=2, + ) + + if kwargs: + warn( + "'start_response' does not take keyword arguments.", + WSGIWarning, + stacklevel=2, + ) + + status: str = args[0] + headers: list[tuple[str, str]] = args[1] + exc_info: ( + None | (tuple[type[BaseException], BaseException, TracebackType]) + ) = args[2] if len(args) == 3 else None + + headers_set[:] = self.check_start_response(status, headers, exc_info) + return GuardedWrite(start_response(status, headers, exc_info), chunks) + + app_iter = self.app(environ, t.cast("StartResponse", checking_start_response)) + self.check_iterator(app_iter) + return GuardedIterator( + app_iter, t.cast(t.Tuple[int, Headers], headers_set), chunks + ) diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/profiler.py b/MLPY/Lib/site-packages/werkzeug/middleware/profiler.py new file mode 100644 index 0000000000000000000000000000000000000000..112b877761c00ab34fd95dbb8ba938b91eb34c79 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/middleware/profiler.py @@ -0,0 +1,155 @@ +""" +Application Profiler +==================== + +This module provides a middleware that profiles each request with the +:mod:`cProfile` module. This can help identify bottlenecks in your code +that may be slowing down your application. + +.. autoclass:: ProfilerMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" + +from __future__ import annotations + +import os.path +import sys +import time +import typing as t +from pstats import Stats + +try: + from cProfile import Profile +except ImportError: + from profile import Profile # type: ignore + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProfilerMiddleware: + """Wrap a WSGI application and profile the execution of each + request. Responses are buffered so that timings are more exact. + + If ``stream`` is given, :class:`pstats.Stats` are written to it + after each request. If ``profile_dir`` is given, :mod:`cProfile` + data files are saved to that directory, one file per request. + + The filename can be customized by passing ``filename_format``. If + it is a string, it will be formatted using :meth:`str.format` with + the following fields available: + + - ``{method}`` - The request method; GET, POST, etc. + - ``{path}`` - The request path or 'root' should one not exist. + - ``{elapsed}`` - The elapsed time of the request in milliseconds. + - ``{time}`` - The time of the request. + + If it is a callable, it will be called with the WSGI ``environ`` and + be expected to return a filename string. The ``environ`` dictionary + will also have the ``"werkzeug.profiler"`` key populated with a + dictionary containing the following fields (more may be added in the + future): + - ``{elapsed}`` - The elapsed time of the request in milliseconds. + - ``{time}`` - The time of the request. + + :param app: The WSGI application to wrap. + :param stream: Write stats to this stream. Disable with ``None``. + :param sort_by: A tuple of columns to sort stats by. See + :meth:`pstats.Stats.sort_stats`. + :param restrictions: A tuple of restrictions to filter stats by. See + :meth:`pstats.Stats.print_stats`. + :param profile_dir: Save profile data files to this directory. + :param filename_format: Format string for profile data file names, + or a callable returning a name. See explanation above. + + .. code-block:: python + + from werkzeug.middleware.profiler import ProfilerMiddleware + app = ProfilerMiddleware(app) + + .. versionchanged:: 3.0 + Added the ``"werkzeug.profiler"`` key to the ``filename_format(environ)`` + parameter with the ``elapsed`` and ``time`` fields. + + .. versionchanged:: 0.15 + Stats are written even if ``profile_dir`` is given, and can be + disable by passing ``stream=None``. + + .. versionadded:: 0.15 + Added ``filename_format``. + + .. versionadded:: 0.9 + Added ``restrictions`` and ``profile_dir``. + """ + + def __init__( + self, + app: WSGIApplication, + stream: t.IO[str] | None = sys.stdout, + sort_by: t.Iterable[str] = ("time", "calls"), + restrictions: t.Iterable[str | int | float] = (), + profile_dir: str | None = None, + filename_format: str = "{method}.{path}.{elapsed:.0f}ms.{time:.0f}.prof", + ) -> None: + self._app = app + self._stream = stream + self._sort_by = sort_by + self._restrictions = restrictions + self._profile_dir = profile_dir + self._filename_format = filename_format + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + response_body: list[bytes] = [] + + def catching_start_response(status, headers, exc_info=None): # type: ignore + start_response(status, headers, exc_info) + return response_body.append + + def runapp() -> None: + app_iter = self._app( + environ, t.cast("StartResponse", catching_start_response) + ) + response_body.extend(app_iter) + + if hasattr(app_iter, "close"): + app_iter.close() + + profile = Profile() + start = time.time() + profile.runcall(runapp) + body = b"".join(response_body) + elapsed = time.time() - start + + if self._profile_dir is not None: + if callable(self._filename_format): + environ["werkzeug.profiler"] = { + "elapsed": elapsed * 1000.0, + "time": time.time(), + } + filename = self._filename_format(environ) + else: + filename = self._filename_format.format( + method=environ["REQUEST_METHOD"], + path=environ["PATH_INFO"].strip("/").replace("/", ".") or "root", + elapsed=elapsed * 1000.0, + time=time.time(), + ) + filename = os.path.join(self._profile_dir, filename) + profile.dump_stats(filename) + + if self._stream is not None: + stats = Stats(profile, stream=self._stream) + stats.sort_stats(*self._sort_by) + print("-" * 80, file=self._stream) + path_info = environ.get("PATH_INFO", "") + print(f"PATH: {path_info!r}", file=self._stream) + stats.print_stats(*self._restrictions) + print(f"{'-' * 80}\n", file=self._stream) + + return [body] diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/proxy_fix.py b/MLPY/Lib/site-packages/werkzeug/middleware/proxy_fix.py new file mode 100644 index 0000000000000000000000000000000000000000..cbf4e0bae0c1077f0f3db8e776efd655ab799596 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/middleware/proxy_fix.py @@ -0,0 +1,183 @@ +""" +X-Forwarded-For Proxy Fix +========================= + +This module provides a middleware that adjusts the WSGI environ based on +``X-Forwarded-`` headers that proxies in front of an application may +set. + +When an application is running behind a proxy server, WSGI may see the +request as coming from that server rather than the real client. Proxies +set various headers to track where the request actually came from. + +This middleware should only be used if the application is actually +behind such a proxy, and should be configured with the number of proxies +that are chained in front of it. Not all proxies set all the headers. +Since incoming headers can be faked, you must set how many proxies are +setting each header so the middleware knows what to trust. + +.. autoclass:: ProxyFix + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" + +from __future__ import annotations + +import typing as t + +from ..http import parse_list_header + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProxyFix: + """Adjust the WSGI environ based on ``X-Forwarded-`` that proxies in + front of the application may set. + + - ``X-Forwarded-For`` sets ``REMOTE_ADDR``. + - ``X-Forwarded-Proto`` sets ``wsgi.url_scheme``. + - ``X-Forwarded-Host`` sets ``HTTP_HOST``, ``SERVER_NAME``, and + ``SERVER_PORT``. + - ``X-Forwarded-Port`` sets ``HTTP_HOST`` and ``SERVER_PORT``. + - ``X-Forwarded-Prefix`` sets ``SCRIPT_NAME``. + + You must tell the middleware how many proxies set each header so it + knows what values to trust. It is a security issue to trust values + that came from the client rather than a proxy. + + The original values of the headers are stored in the WSGI + environ as ``werkzeug.proxy_fix.orig``, a dict. + + :param app: The WSGI application to wrap. + :param x_for: Number of values to trust for ``X-Forwarded-For``. + :param x_proto: Number of values to trust for ``X-Forwarded-Proto``. + :param x_host: Number of values to trust for ``X-Forwarded-Host``. + :param x_port: Number of values to trust for ``X-Forwarded-Port``. + :param x_prefix: Number of values to trust for + ``X-Forwarded-Prefix``. + + .. code-block:: python + + from werkzeug.middleware.proxy_fix import ProxyFix + # App is behind one proxy that sets the -For and -Host headers. + app = ProxyFix(app, x_for=1, x_host=1) + + .. versionchanged:: 1.0 + The ``num_proxies`` argument and attribute; the ``get_remote_addr`` method; and + the environ keys ``orig_remote_addr``, ``orig_wsgi_url_scheme``, and + ``orig_http_host`` were removed. + + .. versionchanged:: 0.15 + All headers support multiple values. Each header is configured with a separate + number of trusted proxies. + + .. versionchanged:: 0.15 + Original WSGI environ values are stored in the ``werkzeug.proxy_fix.orig`` dict. + + .. versionchanged:: 0.15 + Support ``X-Forwarded-Port`` and ``X-Forwarded-Prefix``. + + .. versionchanged:: 0.15 + ``X-Forwarded-Host`` and ``X-Forwarded-Port`` modify + ``SERVER_NAME`` and ``SERVER_PORT``. + """ + + def __init__( + self, + app: WSGIApplication, + x_for: int = 1, + x_proto: int = 1, + x_host: int = 0, + x_port: int = 0, + x_prefix: int = 0, + ) -> None: + self.app = app + self.x_for = x_for + self.x_proto = x_proto + self.x_host = x_host + self.x_port = x_port + self.x_prefix = x_prefix + + def _get_real_value(self, trusted: int, value: str | None) -> str | None: + """Get the real value from a list header based on the configured + number of trusted proxies. + + :param trusted: Number of values to trust in the header. + :param value: Comma separated list header value to parse. + :return: The real value, or ``None`` if there are fewer values + than the number of trusted proxies. + + .. versionchanged:: 1.0 + Renamed from ``_get_trusted_comma``. + + .. versionadded:: 0.15 + """ + if not (trusted and value): + return None + values = parse_list_header(value) + if len(values) >= trusted: + return values[-trusted] + return None + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + """Modify the WSGI environ based on the various ``Forwarded`` + headers before calling the wrapped application. Store the + original environ values in ``werkzeug.proxy_fix.orig_{key}``. + """ + environ_get = environ.get + orig_remote_addr = environ_get("REMOTE_ADDR") + orig_wsgi_url_scheme = environ_get("wsgi.url_scheme") + orig_http_host = environ_get("HTTP_HOST") + environ.update( + { + "werkzeug.proxy_fix.orig": { + "REMOTE_ADDR": orig_remote_addr, + "wsgi.url_scheme": orig_wsgi_url_scheme, + "HTTP_HOST": orig_http_host, + "SERVER_NAME": environ_get("SERVER_NAME"), + "SERVER_PORT": environ_get("SERVER_PORT"), + "SCRIPT_NAME": environ_get("SCRIPT_NAME"), + } + } + ) + + x_for = self._get_real_value(self.x_for, environ_get("HTTP_X_FORWARDED_FOR")) + if x_for: + environ["REMOTE_ADDR"] = x_for + + x_proto = self._get_real_value( + self.x_proto, environ_get("HTTP_X_FORWARDED_PROTO") + ) + if x_proto: + environ["wsgi.url_scheme"] = x_proto + + x_host = self._get_real_value(self.x_host, environ_get("HTTP_X_FORWARDED_HOST")) + if x_host: + environ["HTTP_HOST"] = environ["SERVER_NAME"] = x_host + # "]" to check for IPv6 address without port + if ":" in x_host and not x_host.endswith("]"): + environ["SERVER_NAME"], environ["SERVER_PORT"] = x_host.rsplit(":", 1) + + x_port = self._get_real_value(self.x_port, environ_get("HTTP_X_FORWARDED_PORT")) + if x_port: + host = environ.get("HTTP_HOST") + if host: + # "]" to check for IPv6 address without port + if ":" in host and not host.endswith("]"): + host = host.rsplit(":", 1)[0] + environ["HTTP_HOST"] = f"{host}:{x_port}" + environ["SERVER_PORT"] = x_port + + x_prefix = self._get_real_value( + self.x_prefix, environ_get("HTTP_X_FORWARDED_PREFIX") + ) + if x_prefix: + environ["SCRIPT_NAME"] = x_prefix + + return self.app(environ, start_response) diff --git a/MLPY/Lib/site-packages/werkzeug/middleware/shared_data.py b/MLPY/Lib/site-packages/werkzeug/middleware/shared_data.py new file mode 100644 index 0000000000000000000000000000000000000000..0a0c956757a0d110302450a897e73d664d21b331 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/middleware/shared_data.py @@ -0,0 +1,282 @@ +""" +Serve Shared Static Files +========================= + +.. autoclass:: SharedDataMiddleware + :members: is_allowed + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" + +from __future__ import annotations + +import importlib.util +import mimetypes +import os +import posixpath +import typing as t +from datetime import datetime +from datetime import timezone +from io import BytesIO +from time import time +from zlib import adler32 + +from ..http import http_date +from ..http import is_resource_modified +from ..security import safe_join +from ..utils import get_content_type +from ..wsgi import get_path_info +from ..wsgi import wrap_file + +_TOpener = t.Callable[[], t.Tuple[t.IO[bytes], datetime, int]] +_TLoader = t.Callable[[t.Optional[str]], t.Tuple[t.Optional[str], t.Optional[_TOpener]]] + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class SharedDataMiddleware: + """A WSGI middleware which provides static content for development + environments or simple server setups. Its usage is quite simple:: + + import os + from werkzeug.middleware.shared_data import SharedDataMiddleware + + app = SharedDataMiddleware(app, { + '/shared': os.path.join(os.path.dirname(__file__), 'shared') + }) + + The contents of the folder ``./shared`` will now be available on + ``http://example.com/shared/``. This is pretty useful during development + because a standalone media server is not required. Files can also be + mounted on the root folder and still continue to use the application because + the shared data middleware forwards all unhandled requests to the + application, even if the requests are below one of the shared folders. + + If `pkg_resources` is available you can also tell the middleware to serve + files from package data:: + + app = SharedDataMiddleware(app, { + '/static': ('myapplication', 'static') + }) + + This will then serve the ``static`` folder in the `myapplication` + Python package. + + The optional `disallow` parameter can be a list of :func:`~fnmatch.fnmatch` + rules for files that are not accessible from the web. If `cache` is set to + `False` no caching headers are sent. + + Currently the middleware does not support non-ASCII filenames. If the + encoding on the file system happens to match the encoding of the URI it may + work but this could also be by accident. We strongly suggest using ASCII + only file names for static files. + + The middleware will guess the mimetype using the Python `mimetype` + module. If it's unable to figure out the charset it will fall back + to `fallback_mimetype`. + + :param app: the application to wrap. If you don't want to wrap an + application you can pass it :exc:`NotFound`. + :param exports: a list or dict of exported files and folders. + :param disallow: a list of :func:`~fnmatch.fnmatch` rules. + :param cache: enable or disable caching headers. + :param cache_timeout: the cache timeout in seconds for the headers. + :param fallback_mimetype: The fallback mimetype for unknown files. + + .. versionchanged:: 1.0 + The default ``fallback_mimetype`` is + ``application/octet-stream``. If a filename looks like a text + mimetype, the ``utf-8`` charset is added to it. + + .. versionadded:: 0.6 + Added ``fallback_mimetype``. + + .. versionchanged:: 0.5 + Added ``cache_timeout``. + """ + + def __init__( + self, + app: WSGIApplication, + exports: ( + dict[str, str | tuple[str, str]] + | t.Iterable[tuple[str, str | tuple[str, str]]] + ), + disallow: None = None, + cache: bool = True, + cache_timeout: int = 60 * 60 * 12, + fallback_mimetype: str = "application/octet-stream", + ) -> None: + self.app = app + self.exports: list[tuple[str, _TLoader]] = [] + self.cache = cache + self.cache_timeout = cache_timeout + + if isinstance(exports, dict): + exports = exports.items() + + for key, value in exports: + if isinstance(value, tuple): + loader = self.get_package_loader(*value) + elif isinstance(value, str): + if os.path.isfile(value): + loader = self.get_file_loader(value) + else: + loader = self.get_directory_loader(value) + else: + raise TypeError(f"unknown def {value!r}") + + self.exports.append((key, loader)) + + if disallow is not None: + from fnmatch import fnmatch + + self.is_allowed = lambda x: not fnmatch(x, disallow) + + self.fallback_mimetype = fallback_mimetype + + def is_allowed(self, filename: str) -> bool: + """Subclasses can override this method to disallow the access to + certain files. However by providing `disallow` in the constructor + this method is overwritten. + """ + return True + + def _opener(self, filename: str) -> _TOpener: + return lambda: ( + open(filename, "rb"), + datetime.fromtimestamp(os.path.getmtime(filename), tz=timezone.utc), + int(os.path.getsize(filename)), + ) + + def get_file_loader(self, filename: str) -> _TLoader: + return lambda x: (os.path.basename(filename), self._opener(filename)) + + def get_package_loader(self, package: str, package_path: str) -> _TLoader: + load_time = datetime.now(timezone.utc) + spec = importlib.util.find_spec(package) + reader = spec.loader.get_resource_reader(package) # type: ignore[union-attr] + + def loader( + path: str | None, + ) -> tuple[str | None, _TOpener | None]: + if path is None: + return None, None + + path = safe_join(package_path, path) + + if path is None: + return None, None + + basename = posixpath.basename(path) + + try: + resource = reader.open_resource(path) + except OSError: + return None, None + + if isinstance(resource, BytesIO): + return ( + basename, + lambda: (resource, load_time, len(resource.getvalue())), + ) + + return ( + basename, + lambda: ( + resource, + datetime.fromtimestamp( + os.path.getmtime(resource.name), tz=timezone.utc + ), + os.path.getsize(resource.name), + ), + ) + + return loader + + def get_directory_loader(self, directory: str) -> _TLoader: + def loader( + path: str | None, + ) -> tuple[str | None, _TOpener | None]: + if path is not None: + path = safe_join(directory, path) + + if path is None: + return None, None + else: + path = directory + + if os.path.isfile(path): + return os.path.basename(path), self._opener(path) + + return None, None + + return loader + + def generate_etag(self, mtime: datetime, file_size: int, real_filename: str) -> str: + fn_str = os.fsencode(real_filename) + timestamp = mtime.timestamp() + checksum = adler32(fn_str) & 0xFFFFFFFF + return f"wzsdm-{timestamp}-{file_size}-{checksum}" + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + path = get_path_info(environ) + file_loader = None + + for search_path, loader in self.exports: + if search_path == path: + real_filename, file_loader = loader(None) + + if file_loader is not None: + break + + if not search_path.endswith("/"): + search_path += "/" + + if path.startswith(search_path): + real_filename, file_loader = loader(path[len(search_path) :]) + + if file_loader is not None: + break + + if file_loader is None or not self.is_allowed(real_filename): # type: ignore + return self.app(environ, start_response) + + guessed_type = mimetypes.guess_type(real_filename) # type: ignore + mime_type = get_content_type(guessed_type[0] or self.fallback_mimetype, "utf-8") + f, mtime, file_size = file_loader() + + headers = [("Date", http_date())] + + if self.cache: + timeout = self.cache_timeout + etag = self.generate_etag(mtime, file_size, real_filename) # type: ignore + headers += [ + ("Etag", f'"{etag}"'), + ("Cache-Control", f"max-age={timeout}, public"), + ] + + if not is_resource_modified(environ, etag, last_modified=mtime): + f.close() + start_response("304 Not Modified", headers) + return [] + + headers.append(("Expires", http_date(time() + timeout))) + else: + headers.append(("Cache-Control", "public")) + + headers.extend( + ( + ("Content-Type", mime_type), + ("Content-Length", str(file_size)), + ("Last-Modified", http_date(mtime)), + ) + ) + start_response("200 OK", headers) + return wrap_file(environ, f) diff --git a/MLPY/Lib/site-packages/werkzeug/py.typed b/MLPY/Lib/site-packages/werkzeug/py.typed new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MLPY/Lib/site-packages/werkzeug/routing/__init__.py b/MLPY/Lib/site-packages/werkzeug/routing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..62adc48fb03b5500e1e28f6887cc6ed582beb387 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/routing/__init__.py @@ -0,0 +1,134 @@ +"""When it comes to combining multiple controller or view functions +(however you want to call them) you need a dispatcher. A simple way +would be applying regular expression tests on the ``PATH_INFO`` and +calling registered callback functions that return the value then. + +This module implements a much more powerful system than simple regular +expression matching because it can also convert values in the URLs and +build URLs. + +Here a simple example that creates a URL map for an application with +two subdomains (www and kb) and some URL rules: + +.. code-block:: python + + m = Map([ + # Static URLs + Rule('/', endpoint='static/index'), + Rule('/about', endpoint='static/about'), + Rule('/help', endpoint='static/help'), + # Knowledge Base + Subdomain('kb', [ + Rule('/', endpoint='kb/index'), + Rule('/browse/', endpoint='kb/browse'), + Rule('/browse//', endpoint='kb/browse'), + Rule('/browse//', endpoint='kb/browse') + ]) + ], default_subdomain='www') + +If the application doesn't use subdomains it's perfectly fine to not set +the default subdomain and not use the `Subdomain` rule factory. The +endpoint in the rules can be anything, for example import paths or +unique identifiers. The WSGI application can use those endpoints to get the +handler for that URL. It doesn't have to be a string at all but it's +recommended. + +Now it's possible to create a URL adapter for one of the subdomains and +build URLs: + +.. code-block:: python + + c = m.bind('example.com') + + c.build("kb/browse", dict(id=42)) + 'http://kb.example.com/browse/42/' + + c.build("kb/browse", dict()) + 'http://kb.example.com/browse/' + + c.build("kb/browse", dict(id=42, page=3)) + 'http://kb.example.com/browse/42/3' + + c.build("static/about") + '/about' + + c.build("static/index", force_external=True) + 'http://www.example.com/' + + c = m.bind('example.com', subdomain='kb') + + c.build("static/about") + 'http://www.example.com/about' + +The first argument to bind is the server name *without* the subdomain. +Per default it will assume that the script is mounted on the root, but +often that's not the case so you can provide the real mount point as +second argument: + +.. code-block:: python + + c = m.bind('example.com', '/applications/example') + +The third argument can be the subdomain, if not given the default +subdomain is used. For more details about binding have a look at the +documentation of the `MapAdapter`. + +And here is how you can match URLs: + +.. code-block:: python + + c = m.bind('example.com') + + c.match("/") + ('static/index', {}) + + c.match("/about") + ('static/about', {}) + + c = m.bind('example.com', '/', 'kb') + + c.match("/") + ('kb/index', {}) + + c.match("/browse/42/23") + ('kb/browse', {'id': 42, 'page': 23}) + +If matching fails you get a ``NotFound`` exception, if the rule thinks +it's a good idea to redirect (for example because the URL was defined +to have a slash at the end but the request was missing that slash) it +will raise a ``RequestRedirect`` exception. Both are subclasses of +``HTTPException`` so you can use those errors as responses in the +application. + +If matching succeeded but the URL rule was incompatible to the given +method (for example there were only rules for ``GET`` and ``HEAD`` but +routing tried to match a ``POST`` request) a ``MethodNotAllowed`` +exception is raised. +""" + +from .converters import AnyConverter as AnyConverter +from .converters import BaseConverter as BaseConverter +from .converters import FloatConverter as FloatConverter +from .converters import IntegerConverter as IntegerConverter +from .converters import PathConverter as PathConverter +from .converters import UnicodeConverter as UnicodeConverter +from .converters import UUIDConverter as UUIDConverter +from .converters import ValidationError as ValidationError +from .exceptions import BuildError as BuildError +from .exceptions import NoMatch as NoMatch +from .exceptions import RequestAliasRedirect as RequestAliasRedirect +from .exceptions import RequestPath as RequestPath +from .exceptions import RequestRedirect as RequestRedirect +from .exceptions import RoutingException as RoutingException +from .exceptions import WebsocketMismatch as WebsocketMismatch +from .map import Map as Map +from .map import MapAdapter as MapAdapter +from .matcher import StateMachineMatcher as StateMachineMatcher +from .rules import EndpointPrefix as EndpointPrefix +from .rules import parse_converter_args as parse_converter_args +from .rules import Rule as Rule +from .rules import RuleFactory as RuleFactory +from .rules import RuleTemplate as RuleTemplate +from .rules import RuleTemplateFactory as RuleTemplateFactory +from .rules import Subdomain as Subdomain +from .rules import Submount as Submount diff --git a/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/__init__.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0249bdb9aad6662fb3e60badcf20d70ef68ea9ce Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/__init__.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/converters.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/converters.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19f5498df2aa4d762c7ddaba528b8b97019fd41b Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/converters.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a97a0441890e307ab68ba10ae97bbc82afcde812 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/map.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/map.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c911a7a3781d6633e64a64788fffe217f99309f6 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/map.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/matcher.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/matcher.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26253e6191725a553a73bb66c449537f3ac5e016 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/matcher.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/rules.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/rules.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6e18fca387a18ebba6dd37971258f510bd4b3f9 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/routing/__pycache__/rules.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/routing/converters.py b/MLPY/Lib/site-packages/werkzeug/routing/converters.py new file mode 100644 index 0000000000000000000000000000000000000000..6016a975edf0f2e830728d906f268cab336b8c0e --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/routing/converters.py @@ -0,0 +1,261 @@ +from __future__ import annotations + +import re +import typing as t +import uuid +from urllib.parse import quote + +if t.TYPE_CHECKING: + from .map import Map + + +class ValidationError(ValueError): + """Validation error. If a rule converter raises this exception the rule + does not match the current URL and the next URL is tried. + """ + + +class BaseConverter: + """Base class for all converters. + + .. versionchanged:: 2.3 + ``part_isolating`` defaults to ``False`` if ``regex`` contains a ``/``. + """ + + regex = "[^/]+" + weight = 100 + part_isolating = True + + def __init_subclass__(cls, **kwargs: t.Any) -> None: + super().__init_subclass__(**kwargs) + + # If the converter isn't inheriting its regex, disable part_isolating by default + # if the regex contains a / character. + if "regex" in cls.__dict__ and "part_isolating" not in cls.__dict__: + cls.part_isolating = "/" not in cls.regex + + def __init__(self, map: Map, *args: t.Any, **kwargs: t.Any) -> None: + self.map = map + + def to_python(self, value: str) -> t.Any: + return value + + def to_url(self, value: t.Any) -> str: + # safe = https://url.spec.whatwg.org/#url-path-segment-string + return quote(str(value), safe="!$&'()*+,/:;=@") + + +class UnicodeConverter(BaseConverter): + """This converter is the default converter and accepts any string but + only one path segment. Thus the string can not include a slash. + + This is the default validator. + + Example:: + + Rule('/pages/'), + Rule('/') + + :param map: the :class:`Map`. + :param minlength: the minimum length of the string. Must be greater + or equal 1. + :param maxlength: the maximum length of the string. + :param length: the exact length of the string. + """ + + def __init__( + self, + map: Map, + minlength: int = 1, + maxlength: int | None = None, + length: int | None = None, + ) -> None: + super().__init__(map) + if length is not None: + length_regex = f"{{{int(length)}}}" + else: + if maxlength is None: + maxlength_value = "" + else: + maxlength_value = str(int(maxlength)) + length_regex = f"{{{int(minlength)},{maxlength_value}}}" + self.regex = f"[^/]{length_regex}" + + +class AnyConverter(BaseConverter): + """Matches one of the items provided. Items can either be Python + identifiers or strings:: + + Rule('/') + + :param map: the :class:`Map`. + :param items: this function accepts the possible items as positional + arguments. + + .. versionchanged:: 2.2 + Value is validated when building a URL. + """ + + def __init__(self, map: Map, *items: str) -> None: + super().__init__(map) + self.items = set(items) + self.regex = f"(?:{'|'.join([re.escape(x) for x in items])})" + + def to_url(self, value: t.Any) -> str: + if value in self.items: + return str(value) + + valid_values = ", ".join(f"'{item}'" for item in sorted(self.items)) + raise ValueError(f"'{value}' is not one of {valid_values}") + + +class PathConverter(BaseConverter): + """Like the default :class:`UnicodeConverter`, but it also matches + slashes. This is useful for wikis and similar applications:: + + Rule('/') + Rule('//edit') + + :param map: the :class:`Map`. + """ + + part_isolating = False + regex = "[^/].*?" + weight = 200 + + +class NumberConverter(BaseConverter): + """Baseclass for `IntegerConverter` and `FloatConverter`. + + :internal: + """ + + weight = 50 + num_convert: t.Callable[[t.Any], t.Any] = int + + def __init__( + self, + map: Map, + fixed_digits: int = 0, + min: int | None = None, + max: int | None = None, + signed: bool = False, + ) -> None: + if signed: + self.regex = self.signed_regex + super().__init__(map) + self.fixed_digits = fixed_digits + self.min = min + self.max = max + self.signed = signed + + def to_python(self, value: str) -> t.Any: + if self.fixed_digits and len(value) != self.fixed_digits: + raise ValidationError() + value_num = self.num_convert(value) + if (self.min is not None and value_num < self.min) or ( + self.max is not None and value_num > self.max + ): + raise ValidationError() + return value_num + + def to_url(self, value: t.Any) -> str: + value_str = str(self.num_convert(value)) + if self.fixed_digits: + value_str = value_str.zfill(self.fixed_digits) + return value_str + + @property + def signed_regex(self) -> str: + return f"-?{self.regex}" + + +class IntegerConverter(NumberConverter): + """This converter only accepts integer values:: + + Rule("/page/") + + By default it only accepts unsigned, positive values. The ``signed`` + parameter will enable signed, negative values. :: + + Rule("/page/") + + :param map: The :class:`Map`. + :param fixed_digits: The number of fixed digits in the URL. If you + set this to ``4`` for example, the rule will only match if the + URL looks like ``/0001/``. The default is variable length. + :param min: The minimal value. + :param max: The maximal value. + :param signed: Allow signed (negative) values. + + .. versionadded:: 0.15 + The ``signed`` parameter. + """ + + regex = r"\d+" + + +class FloatConverter(NumberConverter): + """This converter only accepts floating point values:: + + Rule("/probability/") + + By default it only accepts unsigned, positive values. The ``signed`` + parameter will enable signed, negative values. :: + + Rule("/offset/") + + :param map: The :class:`Map`. + :param min: The minimal value. + :param max: The maximal value. + :param signed: Allow signed (negative) values. + + .. versionadded:: 0.15 + The ``signed`` parameter. + """ + + regex = r"\d+\.\d+" + num_convert = float + + def __init__( + self, + map: Map, + min: float | None = None, + max: float | None = None, + signed: bool = False, + ) -> None: + super().__init__(map, min=min, max=max, signed=signed) # type: ignore + + +class UUIDConverter(BaseConverter): + """This converter only accepts UUID strings:: + + Rule('/object/') + + .. versionadded:: 0.10 + + :param map: the :class:`Map`. + """ + + regex = ( + r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-" + r"[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}" + ) + + def to_python(self, value: str) -> uuid.UUID: + return uuid.UUID(value) + + def to_url(self, value: uuid.UUID) -> str: + return str(value) + + +#: the default converter mapping for the map. +DEFAULT_CONVERTERS: t.Mapping[str, type[BaseConverter]] = { + "default": UnicodeConverter, + "string": UnicodeConverter, + "any": AnyConverter, + "path": PathConverter, + "int": IntegerConverter, + "float": FloatConverter, + "uuid": UUIDConverter, +} diff --git a/MLPY/Lib/site-packages/werkzeug/routing/exceptions.py b/MLPY/Lib/site-packages/werkzeug/routing/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..eeabd4ed12f6828778c55588e6ddccd0b1f9240c --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/routing/exceptions.py @@ -0,0 +1,152 @@ +from __future__ import annotations + +import difflib +import typing as t + +from ..exceptions import BadRequest +from ..exceptions import HTTPException +from ..utils import cached_property +from ..utils import redirect + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + + from ..wrappers.request import Request + from ..wrappers.response import Response + from .map import MapAdapter + from .rules import Rule + + +class RoutingException(Exception): + """Special exceptions that require the application to redirect, notifying + about missing urls, etc. + + :internal: + """ + + +class RequestRedirect(HTTPException, RoutingException): + """Raise if the map requests a redirect. This is for example the case if + `strict_slashes` are activated and an url that requires a trailing slash. + + The attribute `new_url` contains the absolute destination url. + """ + + code = 308 + + def __init__(self, new_url: str) -> None: + super().__init__(new_url) + self.new_url = new_url + + def get_response( + self, + environ: WSGIEnvironment | Request | None = None, + scope: dict[str, t.Any] | None = None, + ) -> Response: + return redirect(self.new_url, self.code) + + +class RequestPath(RoutingException): + """Internal exception.""" + + __slots__ = ("path_info",) + + def __init__(self, path_info: str) -> None: + super().__init__() + self.path_info = path_info + + +class RequestAliasRedirect(RoutingException): # noqa: B903 + """This rule is an alias and wants to redirect to the canonical URL.""" + + def __init__(self, matched_values: t.Mapping[str, t.Any], endpoint: t.Any) -> None: + super().__init__() + self.matched_values = matched_values + self.endpoint = endpoint + + +class BuildError(RoutingException, LookupError): + """Raised if the build system cannot find a URL for an endpoint with the + values provided. + """ + + def __init__( + self, + endpoint: t.Any, + values: t.Mapping[str, t.Any], + method: str | None, + adapter: MapAdapter | None = None, + ) -> None: + super().__init__(endpoint, values, method) + self.endpoint = endpoint + self.values = values + self.method = method + self.adapter = adapter + + @cached_property + def suggested(self) -> Rule | None: + return self.closest_rule(self.adapter) + + def closest_rule(self, adapter: MapAdapter | None) -> Rule | None: + def _score_rule(rule: Rule) -> float: + return sum( + [ + 0.98 + * difflib.SequenceMatcher( + # endpoints can be any type, compare as strings + None, + str(rule.endpoint), + str(self.endpoint), + ).ratio(), + 0.01 * bool(set(self.values or ()).issubset(rule.arguments)), + 0.01 * bool(rule.methods and self.method in rule.methods), + ] + ) + + if adapter and adapter.map._rules: + return max(adapter.map._rules, key=_score_rule) + + return None + + def __str__(self) -> str: + message = [f"Could not build url for endpoint {self.endpoint!r}"] + if self.method: + message.append(f" ({self.method!r})") + if self.values: + message.append(f" with values {sorted(self.values)!r}") + message.append(".") + if self.suggested: + if self.endpoint == self.suggested.endpoint: + if ( + self.method + and self.suggested.methods is not None + and self.method not in self.suggested.methods + ): + message.append( + " Did you mean to use methods" + f" {sorted(self.suggested.methods)!r}?" + ) + missing_values = self.suggested.arguments.union( + set(self.suggested.defaults or ()) + ) - set(self.values.keys()) + if missing_values: + message.append( + f" Did you forget to specify values {sorted(missing_values)!r}?" + ) + else: + message.append(f" Did you mean {self.suggested.endpoint!r} instead?") + return "".join(message) + + +class WebsocketMismatch(BadRequest): + """The only matched rule is either a WebSocket and the request is + HTTP, or the rule is HTTP and the request is a WebSocket. + """ + + +class NoMatch(Exception): + __slots__ = ("have_match_for", "websocket_mismatch") + + def __init__(self, have_match_for: set[str], websocket_mismatch: bool) -> None: + self.have_match_for = have_match_for + self.websocket_mismatch = websocket_mismatch diff --git a/MLPY/Lib/site-packages/werkzeug/routing/map.py b/MLPY/Lib/site-packages/werkzeug/routing/map.py new file mode 100644 index 0000000000000000000000000000000000000000..4d15e88248b0126c3401ebdd83000878aaada9df --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/routing/map.py @@ -0,0 +1,951 @@ +from __future__ import annotations + +import typing as t +import warnings +from pprint import pformat +from threading import Lock +from urllib.parse import quote +from urllib.parse import urljoin +from urllib.parse import urlunsplit + +from .._internal import _get_environ +from .._internal import _wsgi_decoding_dance +from ..datastructures import ImmutableDict +from ..datastructures import MultiDict +from ..exceptions import BadHost +from ..exceptions import HTTPException +from ..exceptions import MethodNotAllowed +from ..exceptions import NotFound +from ..urls import _urlencode +from ..wsgi import get_host +from .converters import DEFAULT_CONVERTERS +from .exceptions import BuildError +from .exceptions import NoMatch +from .exceptions import RequestAliasRedirect +from .exceptions import RequestPath +from .exceptions import RequestRedirect +from .exceptions import WebsocketMismatch +from .matcher import StateMachineMatcher +from .rules import _simple_rule_re +from .rules import Rule + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + from ..wrappers.request import Request + from .converters import BaseConverter + from .rules import RuleFactory + + +class Map: + """The map class stores all the URL rules and some configuration + parameters. Some of the configuration values are only stored on the + `Map` instance since those affect all rules, others are just defaults + and can be overridden for each rule. Note that you have to specify all + arguments besides the `rules` as keyword arguments! + + :param rules: sequence of url rules for this map. + :param default_subdomain: The default subdomain for rules without a + subdomain defined. + :param strict_slashes: If a rule ends with a slash but the matched + URL does not, redirect to the URL with a trailing slash. + :param merge_slashes: Merge consecutive slashes when matching or + building URLs. Matches will redirect to the normalized URL. + Slashes in variable parts are not merged. + :param redirect_defaults: This will redirect to the default rule if it + wasn't visited that way. This helps creating + unique URLs. + :param converters: A dict of converters that adds additional converters + to the list of converters. If you redefine one + converter this will override the original one. + :param sort_parameters: If set to `True` the url parameters are sorted. + See `url_encode` for more details. + :param sort_key: The sort key function for `url_encode`. + :param host_matching: if set to `True` it enables the host matching + feature and disables the subdomain one. If + enabled the `host` parameter to rules is used + instead of the `subdomain` one. + + .. versionchanged:: 3.0 + The ``charset`` and ``encoding_errors`` parameters were removed. + + .. versionchanged:: 1.0 + If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules will match. + + .. versionchanged:: 1.0 + The ``merge_slashes`` parameter was added. + + .. versionchanged:: 0.7 + The ``encoding_errors`` and ``host_matching`` parameters were added. + + .. versionchanged:: 0.5 + The ``sort_parameters`` and ``sort_key`` paramters were added. + """ + + #: A dict of default converters to be used. + default_converters = ImmutableDict(DEFAULT_CONVERTERS) + + #: The type of lock to use when updating. + #: + #: .. versionadded:: 1.0 + lock_class = Lock + + def __init__( + self, + rules: t.Iterable[RuleFactory] | None = None, + default_subdomain: str = "", + strict_slashes: bool = True, + merge_slashes: bool = True, + redirect_defaults: bool = True, + converters: t.Mapping[str, type[BaseConverter]] | None = None, + sort_parameters: bool = False, + sort_key: t.Callable[[t.Any], t.Any] | None = None, + host_matching: bool = False, + ) -> None: + self._matcher = StateMachineMatcher(merge_slashes) + self._rules_by_endpoint: dict[t.Any, list[Rule]] = {} + self._remap = True + self._remap_lock = self.lock_class() + + self.default_subdomain = default_subdomain + self.strict_slashes = strict_slashes + self.redirect_defaults = redirect_defaults + self.host_matching = host_matching + + self.converters = self.default_converters.copy() + if converters: + self.converters.update(converters) + + self.sort_parameters = sort_parameters + self.sort_key = sort_key + + for rulefactory in rules or (): + self.add(rulefactory) + + @property + def merge_slashes(self) -> bool: + return self._matcher.merge_slashes + + @merge_slashes.setter + def merge_slashes(self, value: bool) -> None: + self._matcher.merge_slashes = value + + def is_endpoint_expecting(self, endpoint: t.Any, *arguments: str) -> bool: + """Iterate over all rules and check if the endpoint expects + the arguments provided. This is for example useful if you have + some URLs that expect a language code and others that do not and + you want to wrap the builder a bit so that the current language + code is automatically added if not provided but endpoints expect + it. + + :param endpoint: the endpoint to check. + :param arguments: this function accepts one or more arguments + as positional arguments. Each one of them is + checked. + """ + self.update() + arguments_set = set(arguments) + for rule in self._rules_by_endpoint[endpoint]: + if arguments_set.issubset(rule.arguments): + return True + return False + + @property + def _rules(self) -> list[Rule]: + return [rule for rules in self._rules_by_endpoint.values() for rule in rules] + + def iter_rules(self, endpoint: t.Any | None = None) -> t.Iterator[Rule]: + """Iterate over all rules or the rules of an endpoint. + + :param endpoint: if provided only the rules for that endpoint + are returned. + :return: an iterator + """ + self.update() + if endpoint is not None: + return iter(self._rules_by_endpoint[endpoint]) + return iter(self._rules) + + def add(self, rulefactory: RuleFactory) -> None: + """Add a new rule or factory to the map and bind it. Requires that the + rule is not bound to another map. + + :param rulefactory: a :class:`Rule` or :class:`RuleFactory` + """ + for rule in rulefactory.get_rules(self): + rule.bind(self) + if not rule.build_only: + self._matcher.add(rule) + self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule) + self._remap = True + + def bind( + self, + server_name: str, + script_name: str | None = None, + subdomain: str | None = None, + url_scheme: str = "http", + default_method: str = "GET", + path_info: str | None = None, + query_args: t.Mapping[str, t.Any] | str | None = None, + ) -> MapAdapter: + """Return a new :class:`MapAdapter` with the details specified to the + call. Note that `script_name` will default to ``'/'`` if not further + specified or `None`. The `server_name` at least is a requirement + because the HTTP RFC requires absolute URLs for redirects and so all + redirect exceptions raised by Werkzeug will contain the full canonical + URL. + + If no path_info is passed to :meth:`match` it will use the default path + info passed to bind. While this doesn't really make sense for + manual bind calls, it's useful if you bind a map to a WSGI + environment which already contains the path info. + + `subdomain` will default to the `default_subdomain` for this map if + no defined. If there is no `default_subdomain` you cannot use the + subdomain feature. + + .. versionchanged:: 1.0 + If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules + will match. + + .. versionchanged:: 0.15 + ``path_info`` defaults to ``'/'`` if ``None``. + + .. versionchanged:: 0.8 + ``query_args`` can be a string. + + .. versionchanged:: 0.7 + Added ``query_args``. + """ + server_name = server_name.lower() + if self.host_matching: + if subdomain is not None: + raise RuntimeError("host matching enabled and a subdomain was provided") + elif subdomain is None: + subdomain = self.default_subdomain + if script_name is None: + script_name = "/" + if path_info is None: + path_info = "/" + + # Port isn't part of IDNA, and might push a name over the 63 octet limit. + server_name, port_sep, port = server_name.partition(":") + + try: + server_name = server_name.encode("idna").decode("ascii") + except UnicodeError as e: + raise BadHost() from e + + return MapAdapter( + self, + f"{server_name}{port_sep}{port}", + script_name, + subdomain, + url_scheme, + path_info, + default_method, + query_args, + ) + + def bind_to_environ( + self, + environ: WSGIEnvironment | Request, + server_name: str | None = None, + subdomain: str | None = None, + ) -> MapAdapter: + """Like :meth:`bind` but you can pass it an WSGI environment and it + will fetch the information from that dictionary. Note that because of + limitations in the protocol there is no way to get the current + subdomain and real `server_name` from the environment. If you don't + provide it, Werkzeug will use `SERVER_NAME` and `SERVER_PORT` (or + `HTTP_HOST` if provided) as used `server_name` with disabled subdomain + feature. + + If `subdomain` is `None` but an environment and a server name is + provided it will calculate the current subdomain automatically. + Example: `server_name` is ``'example.com'`` and the `SERVER_NAME` + in the wsgi `environ` is ``'staging.dev.example.com'`` the calculated + subdomain will be ``'staging.dev'``. + + If the object passed as environ has an environ attribute, the value of + this attribute is used instead. This allows you to pass request + objects. Additionally `PATH_INFO` added as a default of the + :class:`MapAdapter` so that you don't have to pass the path info to + the match method. + + .. versionchanged:: 1.0.0 + If the passed server name specifies port 443, it will match + if the incoming scheme is ``https`` without a port. + + .. versionchanged:: 1.0.0 + A warning is shown when the passed server name does not + match the incoming WSGI server name. + + .. versionchanged:: 0.8 + This will no longer raise a ValueError when an unexpected server + name was passed. + + .. versionchanged:: 0.5 + previously this method accepted a bogus `calculate_subdomain` + parameter that did not have any effect. It was removed because + of that. + + :param environ: a WSGI environment. + :param server_name: an optional server name hint (see above). + :param subdomain: optionally the current subdomain (see above). + """ + env = _get_environ(environ) + wsgi_server_name = get_host(env).lower() + scheme = env["wsgi.url_scheme"] + upgrade = any( + v.strip() == "upgrade" + for v in env.get("HTTP_CONNECTION", "").lower().split(",") + ) + + if upgrade and env.get("HTTP_UPGRADE", "").lower() == "websocket": + scheme = "wss" if scheme == "https" else "ws" + + if server_name is None: + server_name = wsgi_server_name + else: + server_name = server_name.lower() + + # strip standard port to match get_host() + if scheme in {"http", "ws"} and server_name.endswith(":80"): + server_name = server_name[:-3] + elif scheme in {"https", "wss"} and server_name.endswith(":443"): + server_name = server_name[:-4] + + if subdomain is None and not self.host_matching: + cur_server_name = wsgi_server_name.split(".") + real_server_name = server_name.split(".") + offset = -len(real_server_name) + + if cur_server_name[offset:] != real_server_name: + # This can happen even with valid configs if the server was + # accessed directly by IP address under some situations. + # Instead of raising an exception like in Werkzeug 0.7 or + # earlier we go by an invalid subdomain which will result + # in a 404 error on matching. + warnings.warn( + f"Current server name {wsgi_server_name!r} doesn't match configured" + f" server name {server_name!r}", + stacklevel=2, + ) + subdomain = "" + else: + subdomain = ".".join(filter(None, cur_server_name[:offset])) + + def _get_wsgi_string(name: str) -> str | None: + val = env.get(name) + if val is not None: + return _wsgi_decoding_dance(val) + return None + + script_name = _get_wsgi_string("SCRIPT_NAME") + path_info = _get_wsgi_string("PATH_INFO") + query_args = _get_wsgi_string("QUERY_STRING") + return Map.bind( + self, + server_name, + script_name, + subdomain, + scheme, + env["REQUEST_METHOD"], + path_info, + query_args=query_args, + ) + + def update(self) -> None: + """Called before matching and building to keep the compiled rules + in the correct order after things changed. + """ + if not self._remap: + return + + with self._remap_lock: + if not self._remap: + return + + self._matcher.update() + for rules in self._rules_by_endpoint.values(): + rules.sort(key=lambda x: x.build_compare_key()) + self._remap = False + + def __repr__(self) -> str: + rules = self.iter_rules() + return f"{type(self).__name__}({pformat(list(rules))})" + + +class MapAdapter: + """Returned by :meth:`Map.bind` or :meth:`Map.bind_to_environ` and does + the URL matching and building based on runtime information. + """ + + def __init__( + self, + map: Map, + server_name: str, + script_name: str, + subdomain: str | None, + url_scheme: str, + path_info: str, + default_method: str, + query_args: t.Mapping[str, t.Any] | str | None = None, + ): + self.map = map + self.server_name = server_name + + if not script_name.endswith("/"): + script_name += "/" + + self.script_name = script_name + self.subdomain = subdomain + self.url_scheme = url_scheme + self.path_info = path_info + self.default_method = default_method + self.query_args = query_args + self.websocket = self.url_scheme in {"ws", "wss"} + + def dispatch( + self, + view_func: t.Callable[[str, t.Mapping[str, t.Any]], WSGIApplication], + path_info: str | None = None, + method: str | None = None, + catch_http_exceptions: bool = False, + ) -> WSGIApplication: + """Does the complete dispatching process. `view_func` is called with + the endpoint and a dict with the values for the view. It should + look up the view function, call it, and return a response object + or WSGI application. http exceptions are not caught by default + so that applications can display nicer error messages by just + catching them by hand. If you want to stick with the default + error messages you can pass it ``catch_http_exceptions=True`` and + it will catch the http exceptions. + + Here a small example for the dispatch usage:: + + from werkzeug.wrappers import Request, Response + from werkzeug.wsgi import responder + from werkzeug.routing import Map, Rule + + def on_index(request): + return Response('Hello from the index') + + url_map = Map([Rule('/', endpoint='index')]) + views = {'index': on_index} + + @responder + def application(environ, start_response): + request = Request(environ) + urls = url_map.bind_to_environ(environ) + return urls.dispatch(lambda e, v: views[e](request, **v), + catch_http_exceptions=True) + + Keep in mind that this method might return exception objects, too, so + use :class:`Response.force_type` to get a response object. + + :param view_func: a function that is called with the endpoint as + first argument and the value dict as second. Has + to dispatch to the actual view function with this + information. (see above) + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param catch_http_exceptions: set to `True` to catch any of the + werkzeug :class:`HTTPException`\\s. + """ + try: + try: + endpoint, args = self.match(path_info, method) + except RequestRedirect as e: + return e + return view_func(endpoint, args) + except HTTPException as e: + if catch_http_exceptions: + return e + raise + + @t.overload + def match( + self, + path_info: str | None = None, + method: str | None = None, + return_rule: t.Literal[False] = False, + query_args: t.Mapping[str, t.Any] | str | None = None, + websocket: bool | None = None, + ) -> tuple[t.Any, t.Mapping[str, t.Any]]: ... + + @t.overload + def match( + self, + path_info: str | None = None, + method: str | None = None, + return_rule: t.Literal[True] = True, + query_args: t.Mapping[str, t.Any] | str | None = None, + websocket: bool | None = None, + ) -> tuple[Rule, t.Mapping[str, t.Any]]: ... + + def match( + self, + path_info: str | None = None, + method: str | None = None, + return_rule: bool = False, + query_args: t.Mapping[str, t.Any] | str | None = None, + websocket: bool | None = None, + ) -> tuple[t.Any | Rule, t.Mapping[str, t.Any]]: + """The usage is simple: you just pass the match method the current + path info as well as the method (which defaults to `GET`). The + following things can then happen: + + - you receive a `NotFound` exception that indicates that no URL is + matching. A `NotFound` exception is also a WSGI application you + can call to get a default page not found page (happens to be the + same object as `werkzeug.exceptions.NotFound`) + + - you receive a `MethodNotAllowed` exception that indicates that there + is a match for this URL but not for the current request method. + This is useful for RESTful applications. + + - you receive a `RequestRedirect` exception with a `new_url` + attribute. This exception is used to notify you about a request + Werkzeug requests from your WSGI application. This is for example the + case if you request ``/foo`` although the correct URL is ``/foo/`` + You can use the `RequestRedirect` instance as response-like object + similar to all other subclasses of `HTTPException`. + + - you receive a ``WebsocketMismatch`` exception if the only + match is a WebSocket rule but the bind is an HTTP request, or + if the match is an HTTP rule but the bind is a WebSocket + request. + + - you get a tuple in the form ``(endpoint, arguments)`` if there is + a match (unless `return_rule` is True, in which case you get a tuple + in the form ``(rule, arguments)``) + + If the path info is not passed to the match method the default path + info of the map is used (defaults to the root URL if not defined + explicitly). + + All of the exceptions raised are subclasses of `HTTPException` so they + can be used as WSGI responses. They will all render generic error or + redirect pages. + + Here is a small example for matching: + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.match("/", "GET") + ('index', {}) + >>> urls.match("/downloads/42") + ('downloads/show', {'id': 42}) + + And here is what happens on redirect and missing URLs: + + >>> urls.match("/downloads") + Traceback (most recent call last): + ... + RequestRedirect: http://example.com/downloads/ + >>> urls.match("/missing") + Traceback (most recent call last): + ... + NotFound: 404 Not Found + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param return_rule: return the rule that matched instead of just the + endpoint (defaults to `False`). + :param query_args: optional query arguments that are used for + automatic redirects as string or dictionary. It's + currently not possible to use the query arguments + for URL matching. + :param websocket: Match WebSocket instead of HTTP requests. A + websocket request has a ``ws`` or ``wss`` + :attr:`url_scheme`. This overrides that detection. + + .. versionadded:: 1.0 + Added ``websocket``. + + .. versionchanged:: 0.8 + ``query_args`` can be a string. + + .. versionadded:: 0.7 + Added ``query_args``. + + .. versionadded:: 0.6 + Added ``return_rule``. + """ + self.map.update() + if path_info is None: + path_info = self.path_info + if query_args is None: + query_args = self.query_args or {} + method = (method or self.default_method).upper() + + if websocket is None: + websocket = self.websocket + + domain_part = self.server_name + + if not self.map.host_matching and self.subdomain is not None: + domain_part = self.subdomain + + path_part = f"/{path_info.lstrip('/')}" if path_info else "" + + try: + result = self.map._matcher.match(domain_part, path_part, method, websocket) + except RequestPath as e: + # safe = https://url.spec.whatwg.org/#url-path-segment-string + new_path = quote(e.path_info, safe="!$&'()*+,/:;=@") + raise RequestRedirect( + self.make_redirect_url(new_path, query_args) + ) from None + except RequestAliasRedirect as e: + raise RequestRedirect( + self.make_alias_redirect_url( + f"{domain_part}|{path_part}", + e.endpoint, + e.matched_values, + method, + query_args, + ) + ) from None + except NoMatch as e: + if e.have_match_for: + raise MethodNotAllowed(valid_methods=list(e.have_match_for)) from None + + if e.websocket_mismatch: + raise WebsocketMismatch() from None + + raise NotFound() from None + else: + rule, rv = result + + if self.map.redirect_defaults: + redirect_url = self.get_default_redirect(rule, method, rv, query_args) + if redirect_url is not None: + raise RequestRedirect(redirect_url) + + if rule.redirect_to is not None: + if isinstance(rule.redirect_to, str): + + def _handle_match(match: t.Match[str]) -> str: + value = rv[match.group(1)] + return rule._converters[match.group(1)].to_url(value) + + redirect_url = _simple_rule_re.sub(_handle_match, rule.redirect_to) + else: + redirect_url = rule.redirect_to(self, **rv) + + if self.subdomain: + netloc = f"{self.subdomain}.{self.server_name}" + else: + netloc = self.server_name + + raise RequestRedirect( + urljoin( + f"{self.url_scheme or 'http'}://{netloc}{self.script_name}", + redirect_url, + ) + ) + + if return_rule: + return rule, rv + else: + return rule.endpoint, rv + + def test(self, path_info: str | None = None, method: str | None = None) -> bool: + """Test if a rule would match. Works like `match` but returns `True` + if the URL matches, or `False` if it does not exist. + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + """ + try: + self.match(path_info, method) + except RequestRedirect: + pass + except HTTPException: + return False + return True + + def allowed_methods(self, path_info: str | None = None) -> t.Iterable[str]: + """Returns the valid methods that match for a given path. + + .. versionadded:: 0.7 + """ + try: + self.match(path_info, method="--") + except MethodNotAllowed as e: + return e.valid_methods # type: ignore + except HTTPException: + pass + return [] + + def get_host(self, domain_part: str | None) -> str: + """Figures out the full host name for the given domain part. The + domain part is a subdomain in case host matching is disabled or + a full host name. + """ + if self.map.host_matching: + if domain_part is None: + return self.server_name + + return domain_part + + if domain_part is None: + subdomain = self.subdomain + else: + subdomain = domain_part + + if subdomain: + return f"{subdomain}.{self.server_name}" + else: + return self.server_name + + def get_default_redirect( + self, + rule: Rule, + method: str, + values: t.MutableMapping[str, t.Any], + query_args: t.Mapping[str, t.Any] | str, + ) -> str | None: + """A helper that returns the URL to redirect to if it finds one. + This is used for default redirecting only. + + :internal: + """ + assert self.map.redirect_defaults + for r in self.map._rules_by_endpoint[rule.endpoint]: + # every rule that comes after this one, including ourself + # has a lower priority for the defaults. We order the ones + # with the highest priority up for building. + if r is rule: + break + if r.provides_defaults_for(rule) and r.suitable_for(values, method): + values.update(r.defaults) # type: ignore + domain_part, path = r.build(values) # type: ignore + return self.make_redirect_url(path, query_args, domain_part=domain_part) + return None + + def encode_query_args(self, query_args: t.Mapping[str, t.Any] | str) -> str: + if not isinstance(query_args, str): + return _urlencode(query_args) + return query_args + + def make_redirect_url( + self, + path_info: str, + query_args: t.Mapping[str, t.Any] | str | None = None, + domain_part: str | None = None, + ) -> str: + """Creates a redirect URL. + + :internal: + """ + if query_args is None: + query_args = self.query_args + + if query_args: + query_str = self.encode_query_args(query_args) + else: + query_str = None + + scheme = self.url_scheme or "http" + host = self.get_host(domain_part) + path = "/".join((self.script_name.strip("/"), path_info.lstrip("/"))) + return urlunsplit((scheme, host, path, query_str, None)) + + def make_alias_redirect_url( + self, + path: str, + endpoint: t.Any, + values: t.Mapping[str, t.Any], + method: str, + query_args: t.Mapping[str, t.Any] | str, + ) -> str: + """Internally called to make an alias redirect URL.""" + url = self.build( + endpoint, values, method, append_unknown=False, force_external=True + ) + if query_args: + url += f"?{self.encode_query_args(query_args)}" + assert url != path, "detected invalid alias setting. No canonical URL found" + return url + + def _partial_build( + self, + endpoint: t.Any, + values: t.Mapping[str, t.Any], + method: str | None, + append_unknown: bool, + ) -> tuple[str, str, bool] | None: + """Helper for :meth:`build`. Returns subdomain and path for the + rule that accepts this endpoint, values and method. + + :internal: + """ + # in case the method is none, try with the default method first + if method is None: + rv = self._partial_build( + endpoint, values, self.default_method, append_unknown + ) + if rv is not None: + return rv + + # Default method did not match or a specific method is passed. + # Check all for first match with matching host. If no matching + # host is found, go with first result. + first_match = None + + for rule in self.map._rules_by_endpoint.get(endpoint, ()): + if rule.suitable_for(values, method): + build_rv = rule.build(values, append_unknown) + + if build_rv is not None: + rv = (build_rv[0], build_rv[1], rule.websocket) + if self.map.host_matching: + if rv[0] == self.server_name: + return rv + elif first_match is None: + first_match = rv + else: + return rv + + return first_match + + def build( + self, + endpoint: t.Any, + values: t.Mapping[str, t.Any] | None = None, + method: str | None = None, + force_external: bool = False, + append_unknown: bool = True, + url_scheme: str | None = None, + ) -> str: + """Building URLs works pretty much the other way round. Instead of + `match` you call `build` and pass it the endpoint and a dict of + arguments for the placeholders. + + The `build` function also accepts an argument called `force_external` + which, if you set it to `True` will force external URLs. Per default + external URLs (include the server name) will only be used if the + target URL is on a different subdomain. + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.build("index", {}) + '/' + >>> urls.build("downloads/show", {'id': 42}) + '/downloads/42' + >>> urls.build("downloads/show", {'id': 42}, force_external=True) + 'http://example.com/downloads/42' + + Because URLs cannot contain non ASCII data you will always get + bytes back. Non ASCII characters are urlencoded with the + charset defined on the map instance. + + Additional values are converted to strings and appended to the URL as + URL querystring parameters: + + >>> urls.build("index", {'q': 'My Searchstring'}) + '/?q=My+Searchstring' + + When processing those additional values, lists are furthermore + interpreted as multiple values (as per + :py:class:`werkzeug.datastructures.MultiDict`): + + >>> urls.build("index", {'q': ['a', 'b', 'c']}) + '/?q=a&q=b&q=c' + + Passing a ``MultiDict`` will also add multiple values: + + >>> urls.build("index", MultiDict((('p', 'z'), ('q', 'a'), ('q', 'b')))) + '/?p=z&q=a&q=b' + + If a rule does not exist when building a `BuildError` exception is + raised. + + The build method accepts an argument called `method` which allows you + to specify the method you want to have an URL built for if you have + different methods for the same endpoint specified. + + :param endpoint: the endpoint of the URL to build. + :param values: the values for the URL to build. Unhandled values are + appended to the URL as query parameters. + :param method: the HTTP method for the rule if there are different + URLs for different methods on the same endpoint. + :param force_external: enforce full canonical external URLs. If the URL + scheme is not provided, this will generate + a protocol-relative URL. + :param append_unknown: unknown parameters are appended to the generated + URL as query string argument. Disable this + if you want the builder to ignore those. + :param url_scheme: Scheme to use in place of the bound + :attr:`url_scheme`. + + .. versionchanged:: 2.0 + Added the ``url_scheme`` parameter. + + .. versionadded:: 0.6 + Added the ``append_unknown`` parameter. + """ + self.map.update() + + if values: + if isinstance(values, MultiDict): + values = { + k: (v[0] if len(v) == 1 else v) + for k, v in dict.items(values) + if len(v) != 0 + } + else: # plain dict + values = {k: v for k, v in values.items() if v is not None} + else: + values = {} + + rv = self._partial_build(endpoint, values, method, append_unknown) + if rv is None: + raise BuildError(endpoint, values, method, self) + + domain_part, path, websocket = rv + host = self.get_host(domain_part) + + if url_scheme is None: + url_scheme = self.url_scheme + + # Always build WebSocket routes with the scheme (browsers + # require full URLs). If bound to a WebSocket, ensure that HTTP + # routes are built with an HTTP scheme. + secure = url_scheme in {"https", "wss"} + + if websocket: + force_external = True + url_scheme = "wss" if secure else "ws" + elif url_scheme: + url_scheme = "https" if secure else "http" + + # shortcut this. + if not force_external and ( + (self.map.host_matching and host == self.server_name) + or (not self.map.host_matching and domain_part == self.subdomain) + ): + return f"{self.script_name.rstrip('/')}/{path.lstrip('/')}" + + scheme = f"{url_scheme}:" if url_scheme else "" + return f"{scheme}//{host}{self.script_name[:-1]}/{path.lstrip('/')}" diff --git a/MLPY/Lib/site-packages/werkzeug/routing/matcher.py b/MLPY/Lib/site-packages/werkzeug/routing/matcher.py new file mode 100644 index 0000000000000000000000000000000000000000..1fd00efcae4958bca9ccba1cdb957c77835a3b08 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/routing/matcher.py @@ -0,0 +1,202 @@ +from __future__ import annotations + +import re +import typing as t +from dataclasses import dataclass +from dataclasses import field + +from .converters import ValidationError +from .exceptions import NoMatch +from .exceptions import RequestAliasRedirect +from .exceptions import RequestPath +from .rules import Rule +from .rules import RulePart + + +class SlashRequired(Exception): + pass + + +@dataclass +class State: + """A representation of a rule state. + + This includes the *rules* that correspond to the state and the + possible *static* and *dynamic* transitions to the next state. + """ + + dynamic: list[tuple[RulePart, State]] = field(default_factory=list) + rules: list[Rule] = field(default_factory=list) + static: dict[str, State] = field(default_factory=dict) + + +class StateMachineMatcher: + def __init__(self, merge_slashes: bool) -> None: + self._root = State() + self.merge_slashes = merge_slashes + + def add(self, rule: Rule) -> None: + state = self._root + for part in rule._parts: + if part.static: + state.static.setdefault(part.content, State()) + state = state.static[part.content] + else: + for test_part, new_state in state.dynamic: + if test_part == part: + state = new_state + break + else: + new_state = State() + state.dynamic.append((part, new_state)) + state = new_state + state.rules.append(rule) + + def update(self) -> None: + # For every state the dynamic transitions should be sorted by + # the weight of the transition + state = self._root + + def _update_state(state: State) -> None: + state.dynamic.sort(key=lambda entry: entry[0].weight) + for new_state in state.static.values(): + _update_state(new_state) + for _, new_state in state.dynamic: + _update_state(new_state) + + _update_state(state) + + def match( + self, domain: str, path: str, method: str, websocket: bool + ) -> tuple[Rule, t.MutableMapping[str, t.Any]]: + # To match to a rule we need to start at the root state and + # try to follow the transitions until we find a match, or find + # there is no transition to follow. + + have_match_for = set() + websocket_mismatch = False + + def _match( + state: State, parts: list[str], values: list[str] + ) -> tuple[Rule, list[str]] | None: + # This function is meant to be called recursively, and will attempt + # to match the head part to the state's transitions. + nonlocal have_match_for, websocket_mismatch + + # The base case is when all parts have been matched via + # transitions. Hence if there is a rule with methods & + # websocket that work return it and the dynamic values + # extracted. + if parts == []: + for rule in state.rules: + if rule.methods is not None and method not in rule.methods: + have_match_for.update(rule.methods) + elif rule.websocket != websocket: + websocket_mismatch = True + else: + return rule, values + + # Test if there is a match with this path with a + # trailing slash, if so raise an exception to report + # that matching is possible with an additional slash + if "" in state.static: + for rule in state.static[""].rules: + if websocket == rule.websocket and ( + rule.methods is None or method in rule.methods + ): + if rule.strict_slashes: + raise SlashRequired() + else: + return rule, values + return None + + part = parts[0] + # To match this part try the static transitions first + if part in state.static: + rv = _match(state.static[part], parts[1:], values) + if rv is not None: + return rv + # No match via the static transitions, so try the dynamic + # ones. + for test_part, new_state in state.dynamic: + target = part + remaining = parts[1:] + # A final part indicates a transition that always + # consumes the remaining parts i.e. transitions to a + # final state. + if test_part.final: + target = "/".join(parts) + remaining = [] + match = re.compile(test_part.content).match(target) + if match is not None: + if test_part.suffixed: + # If a part_isolating=False part has a slash suffix, remove the + # suffix from the match and check for the slash redirect next. + suffix = match.groups()[-1] + if suffix == "/": + remaining = [""] + + converter_groups = sorted( + match.groupdict().items(), key=lambda entry: entry[0] + ) + groups = [ + value + for key, value in converter_groups + if key[:11] == "__werkzeug_" + ] + rv = _match(new_state, remaining, values + groups) + if rv is not None: + return rv + + # If there is no match and the only part left is a + # trailing slash ("") consider rules that aren't + # strict-slashes as these should match if there is a final + # slash part. + if parts == [""]: + for rule in state.rules: + if rule.strict_slashes: + continue + if rule.methods is not None and method not in rule.methods: + have_match_for.update(rule.methods) + elif rule.websocket != websocket: + websocket_mismatch = True + else: + return rule, values + + return None + + try: + rv = _match(self._root, [domain, *path.split("/")], []) + except SlashRequired: + raise RequestPath(f"{path}/") from None + + if self.merge_slashes and rv is None: + # Try to match again, but with slashes merged + path = re.sub("/{2,}?", "/", path) + try: + rv = _match(self._root, [domain, *path.split("/")], []) + except SlashRequired: + raise RequestPath(f"{path}/") from None + if rv is None or rv[0].merge_slashes is False: + raise NoMatch(have_match_for, websocket_mismatch) + else: + raise RequestPath(f"{path}") + elif rv is not None: + rule, values = rv + + result = {} + for name, value in zip(rule._converters.keys(), values): + try: + value = rule._converters[name].to_python(value) + except ValidationError: + raise NoMatch(have_match_for, websocket_mismatch) from None + result[str(name)] = value + if rule.defaults: + result.update(rule.defaults) + + if rule.alias and rule.map.redirect_defaults: + raise RequestAliasRedirect(result, rule.endpoint) + + return rule, result + + raise NoMatch(have_match_for, websocket_mismatch) diff --git a/MLPY/Lib/site-packages/werkzeug/routing/rules.py b/MLPY/Lib/site-packages/werkzeug/routing/rules.py new file mode 100644 index 0000000000000000000000000000000000000000..6a02f8d3e53f034b1d5022f0075e3f0a42362fa3 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/routing/rules.py @@ -0,0 +1,917 @@ +from __future__ import annotations + +import ast +import re +import typing as t +from dataclasses import dataclass +from string import Template +from types import CodeType +from urllib.parse import quote + +from ..datastructures import iter_multi_items +from ..urls import _urlencode +from .converters import ValidationError + +if t.TYPE_CHECKING: + from .converters import BaseConverter + from .map import Map + + +class Weighting(t.NamedTuple): + number_static_weights: int + static_weights: list[tuple[int, int]] + number_argument_weights: int + argument_weights: list[int] + + +@dataclass +class RulePart: + """A part of a rule. + + Rules can be represented by parts as delimited by `/` with + instances of this class representing those parts. The *content* is + either the raw content if *static* or a regex string to match + against. The *weight* can be used to order parts when matching. + + """ + + content: str + final: bool + static: bool + suffixed: bool + weight: Weighting + + +_part_re = re.compile( + r""" + (?: + (?P/) # a slash + | + (?P[^[a-zA-Z_][a-zA-Z0-9_]*) # converter name + (?:\((?P.*?)\))? # converter arguments + : # variable delimiter + )? + (?P[a-zA-Z_][a-zA-Z0-9_]*) # variable name + > + ) + ) + """, + re.VERBOSE, +) + +_simple_rule_re = re.compile(r"<([^>]+)>") +_converter_args_re = re.compile( + r""" + \s* + ((?P\w+)\s*=\s*)? + (?P + True|False| + \d+.\d+| + \d+.| + \d+| + [\w\d_.]+| + [urUR]?(?P"[^"]*?"|'[^']*') + )\s*, + """, + re.VERBOSE, +) + + +_PYTHON_CONSTANTS = {"None": None, "True": True, "False": False} + + +def _find(value: str, target: str, pos: int) -> int: + """Find the *target* in *value* after *pos*. + + Returns the *value* length if *target* isn't found. + """ + try: + return value.index(target, pos) + except ValueError: + return len(value) + + +def _pythonize(value: str) -> None | bool | int | float | str: + if value in _PYTHON_CONSTANTS: + return _PYTHON_CONSTANTS[value] + for convert in int, float: + try: + return convert(value) # type: ignore + except ValueError: + pass + if value[:1] == value[-1:] and value[0] in "\"'": + value = value[1:-1] + return str(value) + + +def parse_converter_args(argstr: str) -> tuple[tuple[t.Any, ...], dict[str, t.Any]]: + argstr += "," + args = [] + kwargs = {} + position = 0 + + for item in _converter_args_re.finditer(argstr): + if item.start() != position: + raise ValueError( + f"Cannot parse converter argument '{argstr[position:item.start()]}'" + ) + + value = item.group("stringval") + if value is None: + value = item.group("value") + value = _pythonize(value) + if not item.group("name"): + args.append(value) + else: + name = item.group("name") + kwargs[name] = value + position = item.end() + + return tuple(args), kwargs + + +class RuleFactory: + """As soon as you have more complex URL setups it's a good idea to use rule + factories to avoid repetitive tasks. Some of them are builtin, others can + be added by subclassing `RuleFactory` and overriding `get_rules`. + """ + + def get_rules(self, map: Map) -> t.Iterable[Rule]: + """Subclasses of `RuleFactory` have to override this method and return + an iterable of rules.""" + raise NotImplementedError() + + +class Subdomain(RuleFactory): + """All URLs provided by this factory have the subdomain set to a + specific domain. For example if you want to use the subdomain for + the current language this can be a good setup:: + + url_map = Map([ + Rule('/', endpoint='#select_language'), + Subdomain('', [ + Rule('/', endpoint='index'), + Rule('/about', endpoint='about'), + Rule('/help', endpoint='help') + ]) + ]) + + All the rules except for the ``'#select_language'`` endpoint will now + listen on a two letter long subdomain that holds the language code + for the current request. + """ + + def __init__(self, subdomain: str, rules: t.Iterable[RuleFactory]) -> None: + self.subdomain = subdomain + self.rules = rules + + def get_rules(self, map: Map) -> t.Iterator[Rule]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.subdomain = self.subdomain + yield rule + + +class Submount(RuleFactory): + """Like `Subdomain` but prefixes the URL rule with a given string:: + + url_map = Map([ + Rule('/', endpoint='index'), + Submount('/blog', [ + Rule('/', endpoint='blog/index'), + Rule('/entry/', endpoint='blog/show') + ]) + ]) + + Now the rule ``'blog/show'`` matches ``/blog/entry/``. + """ + + def __init__(self, path: str, rules: t.Iterable[RuleFactory]) -> None: + self.path = path.rstrip("/") + self.rules = rules + + def get_rules(self, map: Map) -> t.Iterator[Rule]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.rule = self.path + rule.rule + yield rule + + +class EndpointPrefix(RuleFactory): + """Prefixes all endpoints (which must be strings for this factory) with + another string. This can be useful for sub applications:: + + url_map = Map([ + Rule('/', endpoint='index'), + EndpointPrefix('blog/', [Submount('/blog', [ + Rule('/', endpoint='index'), + Rule('/entry/', endpoint='show') + ])]) + ]) + """ + + def __init__(self, prefix: str, rules: t.Iterable[RuleFactory]) -> None: + self.prefix = prefix + self.rules = rules + + def get_rules(self, map: Map) -> t.Iterator[Rule]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.endpoint = self.prefix + rule.endpoint + yield rule + + +class RuleTemplate: + """Returns copies of the rules wrapped and expands string templates in + the endpoint, rule, defaults or subdomain sections. + + Here a small example for such a rule template:: + + from werkzeug.routing import Map, Rule, RuleTemplate + + resource = RuleTemplate([ + Rule('/$name/', endpoint='$name.list'), + Rule('/$name/', endpoint='$name.show') + ]) + + url_map = Map([resource(name='user'), resource(name='page')]) + + When a rule template is called the keyword arguments are used to + replace the placeholders in all the string parameters. + """ + + def __init__(self, rules: t.Iterable[Rule]) -> None: + self.rules = list(rules) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> RuleTemplateFactory: + return RuleTemplateFactory(self.rules, dict(*args, **kwargs)) + + +class RuleTemplateFactory(RuleFactory): + """A factory that fills in template variables into rules. Used by + `RuleTemplate` internally. + + :internal: + """ + + def __init__( + self, rules: t.Iterable[RuleFactory], context: dict[str, t.Any] + ) -> None: + self.rules = rules + self.context = context + + def get_rules(self, map: Map) -> t.Iterator[Rule]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + new_defaults = subdomain = None + if rule.defaults: + new_defaults = {} + for key, value in rule.defaults.items(): + if isinstance(value, str): + value = Template(value).substitute(self.context) + new_defaults[key] = value + if rule.subdomain is not None: + subdomain = Template(rule.subdomain).substitute(self.context) + new_endpoint = rule.endpoint + if isinstance(new_endpoint, str): + new_endpoint = Template(new_endpoint).substitute(self.context) + yield Rule( + Template(rule.rule).substitute(self.context), + new_defaults, + subdomain, + rule.methods, + rule.build_only, + new_endpoint, + rule.strict_slashes, + ) + + +def _prefix_names(src: str) -> ast.stmt: + """ast parse and prefix names with `.` to avoid collision with user vars""" + tree = ast.parse(src).body[0] + if isinstance(tree, ast.Expr): + tree = tree.value # type: ignore + for node in ast.walk(tree): + if isinstance(node, ast.Name): + node.id = f".{node.id}" + return tree + + +_CALL_CONVERTER_CODE_FMT = "self._converters[{elem!r}].to_url()" +_IF_KWARGS_URL_ENCODE_CODE = """\ +if kwargs: + params = self._encode_query_vars(kwargs) + q = "?" if params else "" +else: + q = params = "" +""" +_IF_KWARGS_URL_ENCODE_AST = _prefix_names(_IF_KWARGS_URL_ENCODE_CODE) +_URL_ENCODE_AST_NAMES = (_prefix_names("q"), _prefix_names("params")) + + +class Rule(RuleFactory): + """A Rule represents one URL pattern. There are some options for `Rule` + that change the way it behaves and are passed to the `Rule` constructor. + Note that besides the rule-string all arguments *must* be keyword arguments + in order to not break the application on Werkzeug upgrades. + + `string` + Rule strings basically are just normal URL paths with placeholders in + the format ```` where the converter and the + arguments are optional. If no converter is defined the `default` + converter is used which means `string` in the normal configuration. + + URL rules that end with a slash are branch URLs, others are leaves. + If you have `strict_slashes` enabled (which is the default), all + branch URLs that are matched without a trailing slash will trigger a + redirect to the same URL with the missing slash appended. + + The converters are defined on the `Map`. + + `endpoint` + The endpoint for this rule. This can be anything. A reference to a + function, a string, a number etc. The preferred way is using a string + because the endpoint is used for URL generation. + + `defaults` + An optional dict with defaults for other rules with the same endpoint. + This is a bit tricky but useful if you want to have unique URLs:: + + url_map = Map([ + Rule('/all/', defaults={'page': 1}, endpoint='all_entries'), + Rule('/all/page/', endpoint='all_entries') + ]) + + If a user now visits ``http://example.com/all/page/1`` they will be + redirected to ``http://example.com/all/``. If `redirect_defaults` is + disabled on the `Map` instance this will only affect the URL + generation. + + `subdomain` + The subdomain rule string for this rule. If not specified the rule + only matches for the `default_subdomain` of the map. If the map is + not bound to a subdomain this feature is disabled. + + Can be useful if you want to have user profiles on different subdomains + and all subdomains are forwarded to your application:: + + url_map = Map([ + Rule('/', subdomain='', endpoint='user/homepage'), + Rule('/stats', subdomain='', endpoint='user/stats') + ]) + + `methods` + A sequence of http methods this rule applies to. If not specified, all + methods are allowed. For example this can be useful if you want different + endpoints for `POST` and `GET`. If methods are defined and the path + matches but the method matched against is not in this list or in the + list of another rule for that path the error raised is of the type + `MethodNotAllowed` rather than `NotFound`. If `GET` is present in the + list of methods and `HEAD` is not, `HEAD` is added automatically. + + `strict_slashes` + Override the `Map` setting for `strict_slashes` only for this rule. If + not specified the `Map` setting is used. + + `merge_slashes` + Override :attr:`Map.merge_slashes` for this rule. + + `build_only` + Set this to True and the rule will never match but will create a URL + that can be build. This is useful if you have resources on a subdomain + or folder that are not handled by the WSGI application (like static data) + + `redirect_to` + If given this must be either a string or callable. In case of a + callable it's called with the url adapter that triggered the match and + the values of the URL as keyword arguments and has to return the target + for the redirect, otherwise it has to be a string with placeholders in + rule syntax:: + + def foo_with_slug(adapter, id): + # ask the database for the slug for the old id. this of + # course has nothing to do with werkzeug. + return f'foo/{Foo.get_slug_for_id(id)}' + + url_map = Map([ + Rule('/foo/', endpoint='foo'), + Rule('/some/old/url/', redirect_to='foo/'), + Rule('/other/old/url/', redirect_to=foo_with_slug) + ]) + + When the rule is matched the routing system will raise a + `RequestRedirect` exception with the target for the redirect. + + Keep in mind that the URL will be joined against the URL root of the + script so don't use a leading slash on the target URL unless you + really mean root of that domain. + + `alias` + If enabled this rule serves as an alias for another rule with the same + endpoint and arguments. + + `host` + If provided and the URL map has host matching enabled this can be + used to provide a match rule for the whole host. This also means + that the subdomain feature is disabled. + + `websocket` + If ``True``, this rule is only matches for WebSocket (``ws://``, + ``wss://``) requests. By default, rules will only match for HTTP + requests. + + .. versionchanged:: 2.1 + Percent-encoded newlines (``%0a``), which are decoded by WSGI + servers, are considered when routing instead of terminating the + match early. + + .. versionadded:: 1.0 + Added ``websocket``. + + .. versionadded:: 1.0 + Added ``merge_slashes``. + + .. versionadded:: 0.7 + Added ``alias`` and ``host``. + + .. versionchanged:: 0.6.1 + ``HEAD`` is added to ``methods`` if ``GET`` is present. + """ + + def __init__( + self, + string: str, + defaults: t.Mapping[str, t.Any] | None = None, + subdomain: str | None = None, + methods: t.Iterable[str] | None = None, + build_only: bool = False, + endpoint: t.Any | None = None, + strict_slashes: bool | None = None, + merge_slashes: bool | None = None, + redirect_to: str | t.Callable[..., str] | None = None, + alias: bool = False, + host: str | None = None, + websocket: bool = False, + ) -> None: + if not string.startswith("/"): + raise ValueError(f"URL rule '{string}' must start with a slash.") + + self.rule = string + self.is_leaf = not string.endswith("/") + self.is_branch = string.endswith("/") + + self.map: Map = None # type: ignore + self.strict_slashes = strict_slashes + self.merge_slashes = merge_slashes + self.subdomain = subdomain + self.host = host + self.defaults = defaults + self.build_only = build_only + self.alias = alias + self.websocket = websocket + + if methods is not None: + if isinstance(methods, str): + raise TypeError("'methods' should be a list of strings.") + + methods = {x.upper() for x in methods} + + if "HEAD" not in methods and "GET" in methods: + methods.add("HEAD") + + if websocket and methods - {"GET", "HEAD", "OPTIONS"}: + raise ValueError( + "WebSocket rules can only use 'GET', 'HEAD', and 'OPTIONS' methods." + ) + + self.methods = methods + self.endpoint: t.Any = endpoint + self.redirect_to = redirect_to + + if defaults: + self.arguments = set(map(str, defaults)) + else: + self.arguments = set() + + self._converters: dict[str, BaseConverter] = {} + self._trace: list[tuple[bool, str]] = [] + self._parts: list[RulePart] = [] + + def empty(self) -> Rule: + """ + Return an unbound copy of this rule. + + This can be useful if want to reuse an already bound URL for another + map. See ``get_empty_kwargs`` to override what keyword arguments are + provided to the new copy. + """ + return type(self)(self.rule, **self.get_empty_kwargs()) + + def get_empty_kwargs(self) -> t.Mapping[str, t.Any]: + """ + Provides kwargs for instantiating empty copy with empty() + + Use this method to provide custom keyword arguments to the subclass of + ``Rule`` when calling ``some_rule.empty()``. Helpful when the subclass + has custom keyword arguments that are needed at instantiation. + + Must return a ``dict`` that will be provided as kwargs to the new + instance of ``Rule``, following the initial ``self.rule`` value which + is always provided as the first, required positional argument. + """ + defaults = None + if self.defaults: + defaults = dict(self.defaults) + return dict( + defaults=defaults, + subdomain=self.subdomain, + methods=self.methods, + build_only=self.build_only, + endpoint=self.endpoint, + strict_slashes=self.strict_slashes, + redirect_to=self.redirect_to, + alias=self.alias, + host=self.host, + ) + + def get_rules(self, map: Map) -> t.Iterator[Rule]: + yield self + + def refresh(self) -> None: + """Rebinds and refreshes the URL. Call this if you modified the + rule in place. + + :internal: + """ + self.bind(self.map, rebind=True) + + def bind(self, map: Map, rebind: bool = False) -> None: + """Bind the url to a map and create a regular expression based on + the information from the rule itself and the defaults from the map. + + :internal: + """ + if self.map is not None and not rebind: + raise RuntimeError(f"url rule {self!r} already bound to map {self.map!r}") + self.map = map + if self.strict_slashes is None: + self.strict_slashes = map.strict_slashes + if self.merge_slashes is None: + self.merge_slashes = map.merge_slashes + if self.subdomain is None: + self.subdomain = map.default_subdomain + self.compile() + + def get_converter( + self, + variable_name: str, + converter_name: str, + args: tuple[t.Any, ...], + kwargs: t.Mapping[str, t.Any], + ) -> BaseConverter: + """Looks up the converter for the given parameter. + + .. versionadded:: 0.9 + """ + if converter_name not in self.map.converters: + raise LookupError(f"the converter {converter_name!r} does not exist") + return self.map.converters[converter_name](self.map, *args, **kwargs) + + def _encode_query_vars(self, query_vars: t.Mapping[str, t.Any]) -> str: + items: t.Iterable[tuple[str, str]] = iter_multi_items(query_vars) + + if self.map.sort_parameters: + items = sorted(items, key=self.map.sort_key) + + return _urlencode(items) + + def _parse_rule(self, rule: str) -> t.Iterable[RulePart]: + content = "" + static = True + argument_weights = [] + static_weights: list[tuple[int, int]] = [] + final = False + convertor_number = 0 + + pos = 0 + while pos < len(rule): + match = _part_re.match(rule, pos) + if match is None: + raise ValueError(f"malformed url rule: {rule!r}") + + data = match.groupdict() + if data["static"] is not None: + static_weights.append((len(static_weights), -len(data["static"]))) + self._trace.append((False, data["static"])) + content += data["static"] if static else re.escape(data["static"]) + + if data["variable"] is not None: + if static: + # Switching content to represent regex, hence the need to escape + content = re.escape(content) + static = False + c_args, c_kwargs = parse_converter_args(data["arguments"] or "") + convobj = self.get_converter( + data["variable"], data["converter"] or "default", c_args, c_kwargs + ) + self._converters[data["variable"]] = convobj + self.arguments.add(data["variable"]) + if not convobj.part_isolating: + final = True + content += f"(?P<__werkzeug_{convertor_number}>{convobj.regex})" + convertor_number += 1 + argument_weights.append(convobj.weight) + self._trace.append((True, data["variable"])) + + if data["slash"] is not None: + self._trace.append((False, "/")) + if final: + content += "/" + else: + if not static: + content += r"\Z" + weight = Weighting( + -len(static_weights), + static_weights, + -len(argument_weights), + argument_weights, + ) + yield RulePart( + content=content, + final=final, + static=static, + suffixed=False, + weight=weight, + ) + content = "" + static = True + argument_weights = [] + static_weights = [] + final = False + convertor_number = 0 + + pos = match.end() + + suffixed = False + if final and content[-1] == "/": + # If a converter is part_isolating=False (matches slashes) and ends with a + # slash, augment the regex to support slash redirects. + suffixed = True + content = content[:-1] + "(? None: + """Compiles the regular expression and stores it.""" + assert self.map is not None, "rule not bound" + + if self.map.host_matching: + domain_rule = self.host or "" + else: + domain_rule = self.subdomain or "" + self._parts = [] + self._trace = [] + self._converters = {} + if domain_rule == "": + self._parts = [ + RulePart( + content="", + final=False, + static=True, + suffixed=False, + weight=Weighting(0, [], 0, []), + ) + ] + else: + self._parts.extend(self._parse_rule(domain_rule)) + self._trace.append((False, "|")) + rule = self.rule + if self.merge_slashes: + rule = re.sub("/{2,}?", "/", self.rule) + self._parts.extend(self._parse_rule(rule)) + + self._build: t.Callable[..., tuple[str, str]] + self._build = self._compile_builder(False).__get__(self, None) + self._build_unknown: t.Callable[..., tuple[str, str]] + self._build_unknown = self._compile_builder(True).__get__(self, None) + + @staticmethod + def _get_func_code(code: CodeType, name: str) -> t.Callable[..., tuple[str, str]]: + globs: dict[str, t.Any] = {} + locs: dict[str, t.Any] = {} + exec(code, globs, locs) + return locs[name] # type: ignore + + def _compile_builder( + self, append_unknown: bool = True + ) -> t.Callable[..., tuple[str, str]]: + defaults = self.defaults or {} + dom_ops: list[tuple[bool, str]] = [] + url_ops: list[tuple[bool, str]] = [] + + opl = dom_ops + for is_dynamic, data in self._trace: + if data == "|" and opl is dom_ops: + opl = url_ops + continue + # this seems like a silly case to ever come up but: + # if a default is given for a value that appears in the rule, + # resolve it to a constant ahead of time + if is_dynamic and data in defaults: + data = self._converters[data].to_url(defaults[data]) + opl.append((False, data)) + elif not is_dynamic: + # safe = https://url.spec.whatwg.org/#url-path-segment-string + opl.append((False, quote(data, safe="!$&'()*+,/:;=@"))) + else: + opl.append((True, data)) + + def _convert(elem: str) -> ast.stmt: + ret = _prefix_names(_CALL_CONVERTER_CODE_FMT.format(elem=elem)) + ret.args = [ast.Name(str(elem), ast.Load())] # type: ignore # str for py2 + return ret + + def _parts(ops: list[tuple[bool, str]]) -> list[ast.AST]: + parts = [ + _convert(elem) if is_dynamic else ast.Constant(elem) + for is_dynamic, elem in ops + ] + parts = parts or [ast.Constant("")] + # constant fold + ret = [parts[0]] + for p in parts[1:]: + if isinstance(p, ast.Constant) and isinstance(ret[-1], ast.Constant): + ret[-1] = ast.Constant(ret[-1].value + p.value) + else: + ret.append(p) + return ret + + dom_parts = _parts(dom_ops) + url_parts = _parts(url_ops) + if not append_unknown: + body = [] + else: + body = [_IF_KWARGS_URL_ENCODE_AST] + url_parts.extend(_URL_ENCODE_AST_NAMES) + + def _join(parts: list[ast.AST]) -> ast.AST: + if len(parts) == 1: # shortcut + return parts[0] + return ast.JoinedStr(parts) + + body.append( + ast.Return(ast.Tuple([_join(dom_parts), _join(url_parts)], ast.Load())) + ) + + pargs = [ + elem + for is_dynamic, elem in dom_ops + url_ops + if is_dynamic and elem not in defaults + ] + kargs = [str(k) for k in defaults] + + func_ast: ast.FunctionDef = _prefix_names("def _(): pass") # type: ignore + func_ast.name = f"" + func_ast.args.args.append(ast.arg(".self", None)) + for arg in pargs + kargs: + func_ast.args.args.append(ast.arg(arg, None)) + func_ast.args.kwarg = ast.arg(".kwargs", None) + for _ in kargs: + func_ast.args.defaults.append(ast.Constant("")) + func_ast.body = body + + # Use `ast.parse` instead of `ast.Module` for better portability, since the + # signature of `ast.Module` can change. + module = ast.parse("") + module.body = [func_ast] + + # mark everything as on line 1, offset 0 + # less error-prone than `ast.fix_missing_locations` + # bad line numbers cause an assert to fail in debug builds + for node in ast.walk(module): + if "lineno" in node._attributes: + node.lineno = 1 + if "end_lineno" in node._attributes: + node.end_lineno = node.lineno + if "col_offset" in node._attributes: + node.col_offset = 0 + if "end_col_offset" in node._attributes: + node.end_col_offset = node.col_offset + + code = compile(module, "", "exec") + return self._get_func_code(code, func_ast.name) + + def build( + self, values: t.Mapping[str, t.Any], append_unknown: bool = True + ) -> tuple[str, str] | None: + """Assembles the relative url for that rule and the subdomain. + If building doesn't work for some reasons `None` is returned. + + :internal: + """ + try: + if append_unknown: + return self._build_unknown(**values) + else: + return self._build(**values) + except ValidationError: + return None + + def provides_defaults_for(self, rule: Rule) -> bool: + """Check if this rule has defaults for a given rule. + + :internal: + """ + return bool( + not self.build_only + and self.defaults + and self.endpoint == rule.endpoint + and self != rule + and self.arguments == rule.arguments + ) + + def suitable_for( + self, values: t.Mapping[str, t.Any], method: str | None = None + ) -> bool: + """Check if the dict of values has enough data for url generation. + + :internal: + """ + # if a method was given explicitly and that method is not supported + # by this rule, this rule is not suitable. + if ( + method is not None + and self.methods is not None + and method not in self.methods + ): + return False + + defaults = self.defaults or () + + # all arguments required must be either in the defaults dict or + # the value dictionary otherwise it's not suitable + for key in self.arguments: + if key not in defaults and key not in values: + return False + + # in case defaults are given we ensure that either the value was + # skipped or the value is the same as the default value. + if defaults: + for key, value in defaults.items(): + if key in values and value != values[key]: + return False + + return True + + def build_compare_key(self) -> tuple[int, int, int]: + """The build compare key for sorting. + + :internal: + """ + return (1 if self.alias else 0, -len(self.arguments), -len(self.defaults or ())) + + def __eq__(self, other: object) -> bool: + return isinstance(other, type(self)) and self._trace == other._trace + + __hash__ = None # type: ignore + + def __str__(self) -> str: + return self.rule + + def __repr__(self) -> str: + if self.map is None: + return f"<{type(self).__name__} (unbound)>" + parts = [] + for is_dynamic, data in self._trace: + if is_dynamic: + parts.append(f"<{data}>") + else: + parts.append(data) + parts_str = "".join(parts).lstrip("|") + methods = f" ({', '.join(self.methods)})" if self.methods is not None else "" + return f"<{type(self).__name__} {parts_str!r}{methods} -> {self.endpoint}>" diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/__init__.py b/MLPY/Lib/site-packages/werkzeug/sansio/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11cab24737d399edeb1cd45f62bfefd77ff14959 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/http.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/http.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..325d2acb7bd2d3023721705c05836ad2b35d6a76 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/http.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ffde407cd3522d80501215ddf989c0d61380f9d Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/request.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/request.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b49475034e2556a3315826afa19f0c957897a81b Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/request.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/response.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/response.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9191f211df151e2f5dbdb0a1c630fb76c53e1374 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/response.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/utils.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..629c233d17e259e0918407ad38f4502faca1b307 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/sansio/__pycache__/utils.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/http.py b/MLPY/Lib/site-packages/werkzeug/sansio/http.py new file mode 100644 index 0000000000000000000000000000000000000000..b2b887799fe5f5c95aa1668d25ba32c83886b8f2 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/sansio/http.py @@ -0,0 +1,171 @@ +from __future__ import annotations + +import re +import typing as t +from datetime import datetime + +from .._internal import _dt_as_utc +from ..http import generate_etag +from ..http import parse_date +from ..http import parse_etags +from ..http import parse_if_range_header +from ..http import unquote_etag + +_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)') + + +def is_resource_modified( + http_range: str | None = None, + http_if_range: str | None = None, + http_if_modified_since: str | None = None, + http_if_none_match: str | None = None, + http_if_match: str | None = None, + etag: str | None = None, + data: bytes | None = None, + last_modified: datetime | str | None = None, + ignore_if_range: bool = True, +) -> bool: + """Convenience method for conditional requests. + :param http_range: Range HTTP header + :param http_if_range: If-Range HTTP header + :param http_if_modified_since: If-Modified-Since HTTP header + :param http_if_none_match: If-None-Match HTTP header + :param http_if_match: If-Match HTTP header + :param etag: the etag for the response for comparison. + :param data: or alternatively the data of the response to automatically + generate an etag using :func:`generate_etag`. + :param last_modified: an optional date of the last modification. + :param ignore_if_range: If `False`, `If-Range` header will be taken into + account. + :return: `True` if the resource was modified, otherwise `False`. + + .. versionadded:: 2.2 + """ + if etag is None and data is not None: + etag = generate_etag(data) + elif data is not None: + raise TypeError("both data and etag given") + + unmodified = False + if isinstance(last_modified, str): + last_modified = parse_date(last_modified) + + # HTTP doesn't use microsecond, remove it to avoid false positive + # comparisons. Mark naive datetimes as UTC. + if last_modified is not None: + last_modified = _dt_as_utc(last_modified.replace(microsecond=0)) + + if_range = None + if not ignore_if_range and http_range is not None: + # https://tools.ietf.org/html/rfc7233#section-3.2 + # A server MUST ignore an If-Range header field received in a request + # that does not contain a Range header field. + if_range = parse_if_range_header(http_if_range) + + if if_range is not None and if_range.date is not None: + modified_since: datetime | None = if_range.date + else: + modified_since = parse_date(http_if_modified_since) + + if modified_since and last_modified and last_modified <= modified_since: + unmodified = True + + if etag: + etag, _ = unquote_etag(etag) + etag = t.cast(str, etag) + + if if_range is not None and if_range.etag is not None: + unmodified = parse_etags(if_range.etag).contains(etag) + else: + if_none_match = parse_etags(http_if_none_match) + if if_none_match: + # https://tools.ietf.org/html/rfc7232#section-3.2 + # "A recipient MUST use the weak comparison function when comparing + # entity-tags for If-None-Match" + unmodified = if_none_match.contains_weak(etag) + + # https://tools.ietf.org/html/rfc7232#section-3.1 + # "Origin server MUST use the strong comparison function when + # comparing entity-tags for If-Match" + if_match = parse_etags(http_if_match) + if if_match: + unmodified = not if_match.is_strong(etag) + + return not unmodified + + +_cookie_re = re.compile( + r""" + ([^=;]*) + (?:\s*=\s* + ( + "(?:[^\\"]|\\.)*" + | + .*? + ) + )? + \s*;\s* + """, + flags=re.ASCII | re.VERBOSE, +) +_cookie_unslash_re = re.compile(rb"\\([0-3][0-7]{2}|.)") + + +def _cookie_unslash_replace(m: t.Match[bytes]) -> bytes: + v = m.group(1) + + if len(v) == 1: + return v + + return int(v, 8).to_bytes(1, "big") + + +def parse_cookie( + cookie: str | None = None, + cls: type[ds.MultiDict[str, str]] | None = None, +) -> ds.MultiDict[str, str]: + """Parse a cookie from a string. + + The same key can be provided multiple times, the values are stored + in-order. The default :class:`MultiDict` will have the first value + first, and all values can be retrieved with + :meth:`MultiDict.getlist`. + + :param cookie: The cookie header as a string. + :param cls: A dict-like class to store the parsed cookies in. + Defaults to :class:`MultiDict`. + + .. versionchanged:: 3.0 + Passing bytes, and the ``charset`` and ``errors`` parameters, were removed. + + .. versionadded:: 2.2 + """ + if cls is None: + cls = t.cast("type[ds.MultiDict[str, str]]", ds.MultiDict) + + if not cookie: + return cls() + + cookie = f"{cookie};" + out = [] + + for ck, cv in _cookie_re.findall(cookie): + ck = ck.strip() + cv = cv.strip() + + if not ck: + continue + + if len(cv) >= 2 and cv[0] == cv[-1] == '"': + # Work with bytes here, since a UTF-8 character could be multiple bytes. + cv = _cookie_unslash_re.sub( + _cookie_unslash_replace, cv[1:-1].encode() + ).decode(errors="replace") + + out.append((ck, cv)) + + return cls(out) + + +# circular dependencies +from .. import datastructures as ds diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/multipart.py b/MLPY/Lib/site-packages/werkzeug/sansio/multipart.py new file mode 100644 index 0000000000000000000000000000000000000000..fc873537877a2036449149cb43de4e679a925b6c --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/sansio/multipart.py @@ -0,0 +1,321 @@ +from __future__ import annotations + +import re +import typing as t +from dataclasses import dataclass +from enum import auto +from enum import Enum + +from ..datastructures import Headers +from ..exceptions import RequestEntityTooLarge +from ..http import parse_options_header + + +class Event: + pass + + +@dataclass(frozen=True) +class Preamble(Event): + data: bytes + + +@dataclass(frozen=True) +class Field(Event): + name: str + headers: Headers + + +@dataclass(frozen=True) +class File(Event): + name: str + filename: str + headers: Headers + + +@dataclass(frozen=True) +class Data(Event): + data: bytes + more_data: bool + + +@dataclass(frozen=True) +class Epilogue(Event): + data: bytes + + +class NeedData(Event): + pass + + +NEED_DATA = NeedData() + + +class State(Enum): + PREAMBLE = auto() + PART = auto() + DATA = auto() + DATA_START = auto() + EPILOGUE = auto() + COMPLETE = auto() + + +# Multipart line breaks MUST be CRLF (\r\n) by RFC-7578, except that +# many implementations break this and either use CR or LF alone. +LINE_BREAK = b"(?:\r\n|\n|\r)" +BLANK_LINE_RE = re.compile(b"(?:\r\n\r\n|\r\r|\n\n)", re.MULTILINE) +LINE_BREAK_RE = re.compile(LINE_BREAK, re.MULTILINE) +# Header values can be continued via a space or tab after the linebreak, as +# per RFC2231 +HEADER_CONTINUATION_RE = re.compile(b"%s[ \t]" % LINE_BREAK, re.MULTILINE) +# This must be long enough to contain any line breaks plus any +# additional boundary markers (--) such that they will be found in a +# subsequent search +SEARCH_EXTRA_LENGTH = 8 + + +class MultipartDecoder: + """Decodes a multipart message as bytes into Python events. + + The part data is returned as available to allow the caller to save + the data from memory to disk, if desired. + """ + + def __init__( + self, + boundary: bytes, + max_form_memory_size: int | None = None, + *, + max_parts: int | None = None, + ) -> None: + self.buffer = bytearray() + self.complete = False + self.max_form_memory_size = max_form_memory_size + self.max_parts = max_parts + self.state = State.PREAMBLE + self.boundary = boundary + + # Note in the below \h i.e. horizontal whitespace is used + # as [^\S\n\r] as \h isn't supported in python. + + # The preamble must end with a boundary where the boundary is + # prefixed by a line break, RFC2046. Except that many + # implementations including Werkzeug's tests omit the line + # break prefix. In addition the first boundary could be the + # epilogue boundary (for empty form-data) hence the matching + # group to understand if it is an epilogue boundary. + self.preamble_re = re.compile( + rb"%s?--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)" + % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK), + re.MULTILINE, + ) + # A boundary must include a line break prefix and suffix, and + # may include trailing whitespace. In addition the boundary + # could be the epilogue boundary hence the matching group to + # understand if it is an epilogue boundary. + self.boundary_re = re.compile( + rb"%s--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)" + % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK), + re.MULTILINE, + ) + self._search_position = 0 + self._parts_decoded = 0 + + def last_newline(self, data: bytes) -> int: + try: + last_nl = data.rindex(b"\n") + except ValueError: + last_nl = len(data) + try: + last_cr = data.rindex(b"\r") + except ValueError: + last_cr = len(data) + + return min(last_nl, last_cr) + + def receive_data(self, data: bytes | None) -> None: + if data is None: + self.complete = True + elif ( + self.max_form_memory_size is not None + and len(self.buffer) + len(data) > self.max_form_memory_size + ): + raise RequestEntityTooLarge() + else: + self.buffer.extend(data) + + def next_event(self) -> Event: + event: Event = NEED_DATA + + if self.state == State.PREAMBLE: + match = self.preamble_re.search(self.buffer, self._search_position) + if match is not None: + if match.group(1).startswith(b"--"): + self.state = State.EPILOGUE + else: + self.state = State.PART + data = bytes(self.buffer[: match.start()]) + del self.buffer[: match.end()] + event = Preamble(data=data) + self._search_position = 0 + else: + # Update the search start position to be equal to the + # current buffer length (already searched) minus a + # safe buffer for part of the search target. + self._search_position = max( + 0, len(self.buffer) - len(self.boundary) - SEARCH_EXTRA_LENGTH + ) + + elif self.state == State.PART: + match = BLANK_LINE_RE.search(self.buffer, self._search_position) + if match is not None: + headers = self._parse_headers(self.buffer[: match.start()]) + # The final header ends with a single CRLF, however a + # blank line indicates the start of the + # body. Therefore the end is after the first CRLF. + headers_end = (match.start() + match.end()) // 2 + del self.buffer[:headers_end] + + if "content-disposition" not in headers: + raise ValueError("Missing Content-Disposition header") + + disposition, extra = parse_options_header( + headers["content-disposition"] + ) + name = t.cast(str, extra.get("name")) + filename = extra.get("filename") + if filename is not None: + event = File( + filename=filename, + headers=headers, + name=name, + ) + else: + event = Field( + headers=headers, + name=name, + ) + self.state = State.DATA_START + self._search_position = 0 + self._parts_decoded += 1 + + if self.max_parts is not None and self._parts_decoded > self.max_parts: + raise RequestEntityTooLarge() + else: + # Update the search start position to be equal to the + # current buffer length (already searched) minus a + # safe buffer for part of the search target. + self._search_position = max(0, len(self.buffer) - SEARCH_EXTRA_LENGTH) + + elif self.state == State.DATA_START: + data, del_index, more_data = self._parse_data(self.buffer, start=True) + del self.buffer[:del_index] + event = Data(data=data, more_data=more_data) + if more_data: + self.state = State.DATA + + elif self.state == State.DATA: + data, del_index, more_data = self._parse_data(self.buffer, start=False) + del self.buffer[:del_index] + if data or not more_data: + event = Data(data=data, more_data=more_data) + + elif self.state == State.EPILOGUE and self.complete: + event = Epilogue(data=bytes(self.buffer)) + del self.buffer[:] + self.state = State.COMPLETE + + if self.complete and isinstance(event, NeedData): + raise ValueError(f"Invalid form-data cannot parse beyond {self.state}") + + return event + + def _parse_headers(self, data: bytes) -> Headers: + headers: list[tuple[str, str]] = [] + # Merge the continued headers into one line + data = HEADER_CONTINUATION_RE.sub(b" ", data) + # Now there is one header per line + for line in data.splitlines(): + line = line.strip() + + if line != b"": + name, _, value = line.decode().partition(":") + headers.append((name.strip(), value.strip())) + return Headers(headers) + + def _parse_data(self, data: bytes, *, start: bool) -> tuple[bytes, int, bool]: + # Body parts must start with CRLF (or CR or LF) + if start: + match = LINE_BREAK_RE.match(data) + data_start = t.cast(t.Match[bytes], match).end() + else: + data_start = 0 + + boundary = b"--" + self.boundary + + if self.buffer.find(boundary) == -1: + # No complete boundary in the buffer, but there may be + # a partial boundary at the end. As the boundary + # starts with either a nl or cr find the earliest and + # return up to that as data. + data_end = del_index = self.last_newline(data[data_start:]) + data_start + # If amount of data after last newline is far from + # possible length of partial boundary, we should + # assume that there is no partial boundary in the buffer + # and return all pending data. + if (len(data) - data_end) > len(b"\n" + boundary): + data_end = del_index = len(data) + more_data = True + else: + match = self.boundary_re.search(data) + if match is not None: + if match.group(1).startswith(b"--"): + self.state = State.EPILOGUE + else: + self.state = State.PART + data_end = match.start() + del_index = match.end() + else: + data_end = del_index = self.last_newline(data[data_start:]) + data_start + more_data = match is None + + return bytes(data[data_start:data_end]), del_index, more_data + + +class MultipartEncoder: + def __init__(self, boundary: bytes) -> None: + self.boundary = boundary + self.state = State.PREAMBLE + + def send_event(self, event: Event) -> bytes: + if isinstance(event, Preamble) and self.state == State.PREAMBLE: + self.state = State.PART + return event.data + elif isinstance(event, (Field, File)) and self.state in { + State.PREAMBLE, + State.PART, + State.DATA, + }: + data = b"\r\n--" + self.boundary + b"\r\n" + data += b'Content-Disposition: form-data; name="%s"' % event.name.encode() + if isinstance(event, File): + data += b'; filename="%s"' % event.filename.encode() + data += b"\r\n" + for name, value in t.cast(Field, event).headers: + if name.lower() != "content-disposition": + data += f"{name}: {value}\r\n".encode() + self.state = State.DATA_START + return data + elif isinstance(event, Data) and self.state == State.DATA_START: + self.state = State.DATA + if len(event.data) > 0: + return b"\r\n" + event.data + else: + return event.data + elif isinstance(event, Data) and self.state == State.DATA: + return event.data + elif isinstance(event, Epilogue): + self.state = State.COMPLETE + return b"\r\n--" + self.boundary + b"--\r\n" + event.data + else: + raise ValueError(f"Cannot generate {event} in state: {self.state}") diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/request.py b/MLPY/Lib/site-packages/werkzeug/sansio/request.py new file mode 100644 index 0000000000000000000000000000000000000000..dd0805d7135ce014046d953064f92e3a3a51484d --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/sansio/request.py @@ -0,0 +1,536 @@ +from __future__ import annotations + +import typing as t +from datetime import datetime +from urllib.parse import parse_qsl + +from ..datastructures import Accept +from ..datastructures import Authorization +from ..datastructures import CharsetAccept +from ..datastructures import ETags +from ..datastructures import Headers +from ..datastructures import HeaderSet +from ..datastructures import IfRange +from ..datastructures import ImmutableList +from ..datastructures import ImmutableMultiDict +from ..datastructures import LanguageAccept +from ..datastructures import MIMEAccept +from ..datastructures import MultiDict +from ..datastructures import Range +from ..datastructures import RequestCacheControl +from ..http import parse_accept_header +from ..http import parse_cache_control_header +from ..http import parse_date +from ..http import parse_etags +from ..http import parse_if_range_header +from ..http import parse_list_header +from ..http import parse_options_header +from ..http import parse_range_header +from ..http import parse_set_header +from ..user_agent import UserAgent +from ..utils import cached_property +from ..utils import header_property +from .http import parse_cookie +from .utils import get_content_length +from .utils import get_current_url +from .utils import get_host + + +class Request: + """Represents the non-IO parts of a HTTP request, including the + method, URL info, and headers. + + This class is not meant for general use. It should only be used when + implementing WSGI, ASGI, or another HTTP application spec. Werkzeug + provides a WSGI implementation at :cls:`werkzeug.wrappers.Request`. + + :param method: The method the request was made with, such as + ``GET``. + :param scheme: The URL scheme of the protocol the request used, such + as ``https`` or ``wss``. + :param server: The address of the server. ``(host, port)``, + ``(path, None)`` for unix sockets, or ``None`` if not known. + :param root_path: The prefix that the application is mounted under. + This is prepended to generated URLs, but is not part of route + matching. + :param path: The path part of the URL after ``root_path``. + :param query_string: The part of the URL after the "?". + :param headers: The headers received with the request. + :param remote_addr: The address of the client sending the request. + + .. versionchanged:: 3.0 + The ``charset``, ``url_charset``, and ``encoding_errors`` attributes + were removed. + + .. versionadded:: 2.0 + """ + + #: the class to use for `args` and `form`. The default is an + #: :class:`~werkzeug.datastructures.ImmutableMultiDict` which supports + #: multiple values per key. alternatively it makes sense to use an + #: :class:`~werkzeug.datastructures.ImmutableOrderedMultiDict` which + #: preserves order or a :class:`~werkzeug.datastructures.ImmutableDict` + #: which is the fastest but only remembers the last key. It is also + #: possible to use mutable structures, but this is not recommended. + #: + #: .. versionadded:: 0.6 + parameter_storage_class: type[MultiDict[str, t.Any]] = ImmutableMultiDict + + #: The type to be used for dict values from the incoming WSGI + #: environment. (For example for :attr:`cookies`.) By default an + #: :class:`~werkzeug.datastructures.ImmutableMultiDict` is used. + #: + #: .. versionchanged:: 1.0.0 + #: Changed to ``ImmutableMultiDict`` to support multiple values. + #: + #: .. versionadded:: 0.6 + dict_storage_class: type[MultiDict[str, t.Any]] = ImmutableMultiDict + + #: the type to be used for list values from the incoming WSGI environment. + #: By default an :class:`~werkzeug.datastructures.ImmutableList` is used + #: (for example for :attr:`access_list`). + #: + #: .. versionadded:: 0.6 + list_storage_class: type[list[t.Any]] = ImmutableList + + user_agent_class: type[UserAgent] = UserAgent + """The class used and returned by the :attr:`user_agent` property to + parse the header. Defaults to + :class:`~werkzeug.user_agent.UserAgent`, which does no parsing. An + extension can provide a subclass that uses a parser to provide other + data. + + .. versionadded:: 2.0 + """ + + #: Valid host names when handling requests. By default all hosts are + #: trusted, which means that whatever the client says the host is + #: will be accepted. + #: + #: Because ``Host`` and ``X-Forwarded-Host`` headers can be set to + #: any value by a malicious client, it is recommended to either set + #: this property or implement similar validation in the proxy (if + #: the application is being run behind one). + #: + #: .. versionadded:: 0.9 + trusted_hosts: list[str] | None = None + + def __init__( + self, + method: str, + scheme: str, + server: tuple[str, int | None] | None, + root_path: str, + path: str, + query_string: bytes, + headers: Headers, + remote_addr: str | None, + ) -> None: + #: The method the request was made with, such as ``GET``. + self.method = method.upper() + #: The URL scheme of the protocol the request used, such as + #: ``https`` or ``wss``. + self.scheme = scheme + #: The address of the server. ``(host, port)``, ``(path, None)`` + #: for unix sockets, or ``None`` if not known. + self.server = server + #: The prefix that the application is mounted under, without a + #: trailing slash. :attr:`path` comes after this. + self.root_path = root_path.rstrip("/") + #: The path part of the URL after :attr:`root_path`. This is the + #: path used for routing within the application. + self.path = "/" + path.lstrip("/") + #: The part of the URL after the "?". This is the raw value, use + #: :attr:`args` for the parsed values. + self.query_string = query_string + #: The headers received with the request. + self.headers = headers + #: The address of the client sending the request. + self.remote_addr = remote_addr + + def __repr__(self) -> str: + try: + url = self.url + except Exception as e: + url = f"(invalid URL: {e})" + + return f"<{type(self).__name__} {url!r} [{self.method}]>" + + @cached_property + def args(self) -> MultiDict[str, str]: + """The parsed URL parameters (the part in the URL after the question + mark). + + By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + + .. versionchanged:: 2.3 + Invalid bytes remain percent encoded. + """ + return self.parameter_storage_class( + parse_qsl( + self.query_string.decode(), + keep_blank_values=True, + errors="werkzeug.url_quote", + ) + ) + + @cached_property + def access_route(self) -> list[str]: + """If a forwarded header exists this is a list of all ip addresses + from the client ip to the last proxy server. + """ + if "X-Forwarded-For" in self.headers: + return self.list_storage_class( + parse_list_header(self.headers["X-Forwarded-For"]) + ) + elif self.remote_addr is not None: + return self.list_storage_class([self.remote_addr]) + return self.list_storage_class() + + @cached_property + def full_path(self) -> str: + """Requested path, including the query string.""" + return f"{self.path}?{self.query_string.decode()}" + + @property + def is_secure(self) -> bool: + """``True`` if the request was made with a secure protocol + (HTTPS or WSS). + """ + return self.scheme in {"https", "wss"} + + @cached_property + def url(self) -> str: + """The full request URL with the scheme, host, root path, path, + and query string.""" + return get_current_url( + self.scheme, self.host, self.root_path, self.path, self.query_string + ) + + @cached_property + def base_url(self) -> str: + """Like :attr:`url` but without the query string.""" + return get_current_url(self.scheme, self.host, self.root_path, self.path) + + @cached_property + def root_url(self) -> str: + """The request URL scheme, host, and root path. This is the root + that the application is accessed from. + """ + return get_current_url(self.scheme, self.host, self.root_path) + + @cached_property + def host_url(self) -> str: + """The request URL scheme and host only.""" + return get_current_url(self.scheme, self.host) + + @cached_property + def host(self) -> str: + """The host name the request was made to, including the port if + it's non-standard. Validated with :attr:`trusted_hosts`. + """ + return get_host( + self.scheme, self.headers.get("host"), self.server, self.trusted_hosts + ) + + @cached_property + def cookies(self) -> ImmutableMultiDict[str, str]: + """A :class:`dict` with the contents of all cookies transmitted with + the request.""" + wsgi_combined_cookie = ";".join(self.headers.getlist("Cookie")) + return parse_cookie( # type: ignore + wsgi_combined_cookie, cls=self.dict_storage_class + ) + + # Common Descriptors + + content_type = header_property[str]( + "Content-Type", + doc="""The Content-Type entity-header field indicates the media + type of the entity-body sent to the recipient or, in the case of + the HEAD method, the media type that would have been sent had + the request been a GET.""", + read_only=True, + ) + + @cached_property + def content_length(self) -> int | None: + """The Content-Length entity-header field indicates the size of the + entity-body in bytes or, in the case of the HEAD method, the size of + the entity-body that would have been sent had the request been a + GET. + """ + return get_content_length( + http_content_length=self.headers.get("Content-Length"), + http_transfer_encoding=self.headers.get("Transfer-Encoding"), + ) + + content_encoding = header_property[str]( + "Content-Encoding", + doc="""The Content-Encoding entity-header field is used as a + modifier to the media-type. When present, its value indicates + what additional content codings have been applied to the + entity-body, and thus what decoding mechanisms must be applied + in order to obtain the media-type referenced by the Content-Type + header field. + + .. versionadded:: 0.9""", + read_only=True, + ) + content_md5 = header_property[str]( + "Content-MD5", + doc="""The Content-MD5 entity-header field, as defined in + RFC 1864, is an MD5 digest of the entity-body for the purpose of + providing an end-to-end message integrity check (MIC) of the + entity-body. (Note: a MIC is good for detecting accidental + modification of the entity-body in transit, but is not proof + against malicious attacks.) + + .. versionadded:: 0.9""", + read_only=True, + ) + referrer = header_property[str]( + "Referer", + doc="""The Referer[sic] request-header field allows the client + to specify, for the server's benefit, the address (URI) of the + resource from which the Request-URI was obtained (the + "referrer", although the header field is misspelled).""", + read_only=True, + ) + date = header_property( + "Date", + None, + parse_date, + doc="""The Date general-header field represents the date and + time at which the message was originated, having the same + semantics as orig-date in RFC 822. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + read_only=True, + ) + max_forwards = header_property( + "Max-Forwards", + None, + int, + doc="""The Max-Forwards request-header field provides a + mechanism with the TRACE and OPTIONS methods to limit the number + of proxies or gateways that can forward the request to the next + inbound server.""", + read_only=True, + ) + + def _parse_content_type(self) -> None: + if not hasattr(self, "_parsed_content_type"): + self._parsed_content_type = parse_options_header( + self.headers.get("Content-Type", "") + ) + + @property + def mimetype(self) -> str: + """Like :attr:`content_type`, but without parameters (eg, without + charset, type etc.) and always lowercase. For example if the content + type is ``text/HTML; charset=utf-8`` the mimetype would be + ``'text/html'``. + """ + self._parse_content_type() + return self._parsed_content_type[0].lower() + + @property + def mimetype_params(self) -> dict[str, str]: + """The mimetype parameters as dict. For example if the content + type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + """ + self._parse_content_type() + return self._parsed_content_type[1] + + @cached_property + def pragma(self) -> HeaderSet: + """The Pragma general-header field is used to include + implementation-specific directives that might apply to any recipient + along the request/response chain. All pragma directives specify + optional behavior from the viewpoint of the protocol; however, some + systems MAY require that behavior be consistent with the directives. + """ + return parse_set_header(self.headers.get("Pragma", "")) + + # Accept + + @cached_property + def accept_mimetypes(self) -> MIMEAccept: + """List of mimetypes this client supports as + :class:`~werkzeug.datastructures.MIMEAccept` object. + """ + return parse_accept_header(self.headers.get("Accept"), MIMEAccept) + + @cached_property + def accept_charsets(self) -> CharsetAccept: + """List of charsets this client supports as + :class:`~werkzeug.datastructures.CharsetAccept` object. + """ + return parse_accept_header(self.headers.get("Accept-Charset"), CharsetAccept) + + @cached_property + def accept_encodings(self) -> Accept: + """List of encodings this client accepts. Encodings in a HTTP term + are compression encodings such as gzip. For charsets have a look at + :attr:`accept_charset`. + """ + return parse_accept_header(self.headers.get("Accept-Encoding")) + + @cached_property + def accept_languages(self) -> LanguageAccept: + """List of languages this client accepts as + :class:`~werkzeug.datastructures.LanguageAccept` object. + + .. versionchanged 0.5 + In previous versions this was a regular + :class:`~werkzeug.datastructures.Accept` object. + """ + return parse_accept_header(self.headers.get("Accept-Language"), LanguageAccept) + + # ETag + + @cached_property + def cache_control(self) -> RequestCacheControl: + """A :class:`~werkzeug.datastructures.RequestCacheControl` object + for the incoming cache control headers. + """ + cache_control = self.headers.get("Cache-Control") + return parse_cache_control_header(cache_control, None, RequestCacheControl) + + @cached_property + def if_match(self) -> ETags: + """An object containing all the etags in the `If-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.headers.get("If-Match")) + + @cached_property + def if_none_match(self) -> ETags: + """An object containing all the etags in the `If-None-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.headers.get("If-None-Match")) + + @cached_property + def if_modified_since(self) -> datetime | None: + """The parsed `If-Modified-Since` header as a datetime object. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + return parse_date(self.headers.get("If-Modified-Since")) + + @cached_property + def if_unmodified_since(self) -> datetime | None: + """The parsed `If-Unmodified-Since` header as a datetime object. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + return parse_date(self.headers.get("If-Unmodified-Since")) + + @cached_property + def if_range(self) -> IfRange: + """The parsed ``If-Range`` header. + + .. versionchanged:: 2.0 + ``IfRange.date`` is timezone-aware. + + .. versionadded:: 0.7 + """ + return parse_if_range_header(self.headers.get("If-Range")) + + @cached_property + def range(self) -> Range | None: + """The parsed `Range` header. + + .. versionadded:: 0.7 + + :rtype: :class:`~werkzeug.datastructures.Range` + """ + return parse_range_header(self.headers.get("Range")) + + # User Agent + + @cached_property + def user_agent(self) -> UserAgent: + """The user agent. Use ``user_agent.string`` to get the header + value. Set :attr:`user_agent_class` to a subclass of + :class:`~werkzeug.user_agent.UserAgent` to provide parsing for + the other properties or other extended data. + + .. versionchanged:: 2.1 + The built-in parser was removed. Set ``user_agent_class`` to a ``UserAgent`` + subclass to parse data from the string. + """ + return self.user_agent_class(self.headers.get("User-Agent", "")) + + # Authorization + + @cached_property + def authorization(self) -> Authorization | None: + """The ``Authorization`` header parsed into an :class:`.Authorization` object. + ``None`` if the header is not present. + + .. versionchanged:: 2.3 + :class:`Authorization` is no longer a ``dict``. The ``token`` attribute + was added for auth schemes that use a token instead of parameters. + """ + return Authorization.from_header(self.headers.get("Authorization")) + + # CORS + + origin = header_property[str]( + "Origin", + doc=( + "The host that the request originated from. Set" + " :attr:`~CORSResponseMixin.access_control_allow_origin` on" + " the response to indicate which origins are allowed." + ), + read_only=True, + ) + + access_control_request_headers = header_property( + "Access-Control-Request-Headers", + load_func=parse_set_header, + doc=( + "Sent with a preflight request to indicate which headers" + " will be sent with the cross origin request. Set" + " :attr:`~CORSResponseMixin.access_control_allow_headers`" + " on the response to indicate which headers are allowed." + ), + read_only=True, + ) + + access_control_request_method = header_property[str]( + "Access-Control-Request-Method", + doc=( + "Sent with a preflight request to indicate which method" + " will be used for the cross origin request. Set" + " :attr:`~CORSResponseMixin.access_control_allow_methods`" + " on the response to indicate which methods are allowed." + ), + read_only=True, + ) + + @property + def is_json(self) -> bool: + """Check if the mimetype indicates JSON data, either + :mimetype:`application/json` or :mimetype:`application/*+json`. + """ + mt = self.mimetype + return ( + mt == "application/json" + or mt.startswith("application/") + and mt.endswith("+json") + ) diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/response.py b/MLPY/Lib/site-packages/werkzeug/sansio/response.py new file mode 100644 index 0000000000000000000000000000000000000000..9093b0a8cf228e71962fc3e882710734d64121fd --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/sansio/response.py @@ -0,0 +1,754 @@ +from __future__ import annotations + +import typing as t +from datetime import datetime +from datetime import timedelta +from datetime import timezone +from http import HTTPStatus + +from ..datastructures import CallbackDict +from ..datastructures import ContentRange +from ..datastructures import ContentSecurityPolicy +from ..datastructures import Headers +from ..datastructures import HeaderSet +from ..datastructures import ResponseCacheControl +from ..datastructures import WWWAuthenticate +from ..http import COEP +from ..http import COOP +from ..http import dump_age +from ..http import dump_cookie +from ..http import dump_header +from ..http import dump_options_header +from ..http import http_date +from ..http import HTTP_STATUS_CODES +from ..http import parse_age +from ..http import parse_cache_control_header +from ..http import parse_content_range_header +from ..http import parse_csp_header +from ..http import parse_date +from ..http import parse_options_header +from ..http import parse_set_header +from ..http import quote_etag +from ..http import unquote_etag +from ..utils import get_content_type +from ..utils import header_property + +if t.TYPE_CHECKING: + from ..datastructures.cache_control import _CacheControl + + +def _set_property(name: str, doc: str | None = None) -> property: + def fget(self: Response) -> HeaderSet: + def on_update(header_set: HeaderSet) -> None: + if not header_set and name in self.headers: + del self.headers[name] + elif header_set: + self.headers[name] = header_set.to_header() + + return parse_set_header(self.headers.get(name), on_update) + + def fset( + self: Response, + value: None | (str | dict[str, str | int] | t.Iterable[str]), + ) -> None: + if not value: + del self.headers[name] + elif isinstance(value, str): + self.headers[name] = value + else: + self.headers[name] = dump_header(value) + + return property(fget, fset, doc=doc) + + +class Response: + """Represents the non-IO parts of an HTTP response, specifically the + status and headers but not the body. + + This class is not meant for general use. It should only be used when + implementing WSGI, ASGI, or another HTTP application spec. Werkzeug + provides a WSGI implementation at :cls:`werkzeug.wrappers.Response`. + + :param status: The status code for the response. Either an int, in + which case the default status message is added, or a string in + the form ``{code} {message}``, like ``404 Not Found``. Defaults + to 200. + :param headers: A :class:`~werkzeug.datastructures.Headers` object, + or a list of ``(key, value)`` tuples that will be converted to a + ``Headers`` object. + :param mimetype: The mime type (content type without charset or + other parameters) of the response. If the value starts with + ``text/`` (or matches some other special cases), the charset + will be added to create the ``content_type``. + :param content_type: The full content type of the response. + Overrides building the value from ``mimetype``. + + .. versionchanged:: 3.0 + The ``charset`` attribute was removed. + + .. versionadded:: 2.0 + """ + + #: the default status if none is provided. + default_status = 200 + + #: the default mimetype if none is provided. + default_mimetype: str | None = "text/plain" + + #: Warn if a cookie header exceeds this size. The default, 4093, should be + #: safely `supported by most browsers `_. A cookie larger than + #: this size will still be sent, but it may be ignored or handled + #: incorrectly by some browsers. Set to 0 to disable this check. + #: + #: .. versionadded:: 0.13 + #: + #: .. _`cookie`: http://browsercookielimits.squawky.net/ + max_cookie_size = 4093 + + # A :class:`Headers` object representing the response headers. + headers: Headers + + def __init__( + self, + status: int | str | HTTPStatus | None = None, + headers: t.Mapping[str, str | t.Iterable[str]] + | t.Iterable[tuple[str, str]] + | None = None, + mimetype: str | None = None, + content_type: str | None = None, + ) -> None: + if isinstance(headers, Headers): + self.headers = headers + elif not headers: + self.headers = Headers() + else: + self.headers = Headers(headers) + + if content_type is None: + if mimetype is None and "content-type" not in self.headers: + mimetype = self.default_mimetype + if mimetype is not None: + mimetype = get_content_type(mimetype, "utf-8") + content_type = mimetype + if content_type is not None: + self.headers["Content-Type"] = content_type + if status is None: + status = self.default_status + self.status = status # type: ignore + + def __repr__(self) -> str: + return f"<{type(self).__name__} [{self.status}]>" + + @property + def status_code(self) -> int: + """The HTTP status code as a number.""" + return self._status_code + + @status_code.setter + def status_code(self, code: int) -> None: + self.status = code # type: ignore + + @property + def status(self) -> str: + """The HTTP status code as a string.""" + return self._status + + @status.setter + def status(self, value: str | int | HTTPStatus) -> None: + self._status, self._status_code = self._clean_status(value) + + def _clean_status(self, value: str | int | HTTPStatus) -> tuple[str, int]: + if isinstance(value, (int, HTTPStatus)): + status_code = int(value) + else: + value = value.strip() + + if not value: + raise ValueError("Empty status argument") + + code_str, sep, _ = value.partition(" ") + + try: + status_code = int(code_str) + except ValueError: + # only message + return f"0 {value}", 0 + + if sep: + # code and message + return value, status_code + + # only code, look up message + try: + status = f"{status_code} {HTTP_STATUS_CODES[status_code].upper()}" + except KeyError: + status = f"{status_code} UNKNOWN" + + return status, status_code + + def set_cookie( + self, + key: str, + value: str = "", + max_age: timedelta | int | None = None, + expires: str | datetime | int | float | None = None, + path: str | None = "/", + domain: str | None = None, + secure: bool = False, + httponly: bool = False, + samesite: str | None = None, + ) -> None: + """Sets a cookie. + + A warning is raised if the size of the cookie header exceeds + :attr:`max_cookie_size`, but the header will still be set. + + :param key: the key (name) of the cookie to be set. + :param value: the value of the cookie. + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. + :param expires: should be a `datetime` object or UNIX timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: if you want to set a cross-domain cookie. For example, + ``domain="example.com"`` will set a cookie that is + readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: If ``True``, the cookie will only be available + via HTTPS. + :param httponly: Disallow JavaScript access to the cookie. + :param samesite: Limit the scope of the cookie to only be + attached to requests that are "same-site". + """ + self.headers.add( + "Set-Cookie", + dump_cookie( + key, + value=value, + max_age=max_age, + expires=expires, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + max_size=self.max_cookie_size, + samesite=samesite, + ), + ) + + def delete_cookie( + self, + key: str, + path: str | None = "/", + domain: str | None = None, + secure: bool = False, + httponly: bool = False, + samesite: str | None = None, + ) -> None: + """Delete a cookie. Fails silently if key doesn't exist. + + :param key: the key (name) of the cookie to be deleted. + :param path: if the cookie that should be deleted was limited to a + path, the path has to be defined here. + :param domain: if the cookie that should be deleted was limited to a + domain, that domain has to be defined here. + :param secure: If ``True``, the cookie will only be available + via HTTPS. + :param httponly: Disallow JavaScript access to the cookie. + :param samesite: Limit the scope of the cookie to only be + attached to requests that are "same-site". + """ + self.set_cookie( + key, + expires=0, + max_age=0, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + @property + def is_json(self) -> bool: + """Check if the mimetype indicates JSON data, either + :mimetype:`application/json` or :mimetype:`application/*+json`. + """ + mt = self.mimetype + return mt is not None and ( + mt == "application/json" + or mt.startswith("application/") + and mt.endswith("+json") + ) + + # Common Descriptors + + @property + def mimetype(self) -> str | None: + """The mimetype (content type without charset etc.)""" + ct = self.headers.get("content-type") + + if ct: + return ct.split(";")[0].strip() + else: + return None + + @mimetype.setter + def mimetype(self, value: str) -> None: + self.headers["Content-Type"] = get_content_type(value, "utf-8") + + @property + def mimetype_params(self) -> dict[str, str]: + """The mimetype parameters as dict. For example if the + content type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.5 + """ + + def on_update(d: CallbackDict[str, str]) -> None: + self.headers["Content-Type"] = dump_options_header(self.mimetype, d) + + d = parse_options_header(self.headers.get("content-type", ""))[1] + return CallbackDict(d, on_update) + + location = header_property[str]( + "Location", + doc="""The Location response-header field is used to redirect + the recipient to a location other than the Request-URI for + completion of the request or identification of a new + resource.""", + ) + age = header_property( + "Age", + None, + parse_age, + dump_age, # type: ignore + doc="""The Age response-header field conveys the sender's + estimate of the amount of time since the response (or its + revalidation) was generated at the origin server. + + Age values are non-negative decimal integers, representing time + in seconds.""", + ) + content_type = header_property[str]( + "Content-Type", + doc="""The Content-Type entity-header field indicates the media + type of the entity-body sent to the recipient or, in the case of + the HEAD method, the media type that would have been sent had + the request been a GET.""", + ) + content_length = header_property( + "Content-Length", + None, + int, + str, + doc="""The Content-Length entity-header field indicates the size + of the entity-body, in decimal number of OCTETs, sent to the + recipient or, in the case of the HEAD method, the size of the + entity-body that would have been sent had the request been a + GET.""", + ) + content_location = header_property[str]( + "Content-Location", + doc="""The Content-Location entity-header field MAY be used to + supply the resource location for the entity enclosed in the + message when that entity is accessible from a location separate + from the requested resource's URI.""", + ) + content_encoding = header_property[str]( + "Content-Encoding", + doc="""The Content-Encoding entity-header field is used as a + modifier to the media-type. When present, its value indicates + what additional content codings have been applied to the + entity-body, and thus what decoding mechanisms must be applied + in order to obtain the media-type referenced by the Content-Type + header field.""", + ) + content_md5 = header_property[str]( + "Content-MD5", + doc="""The Content-MD5 entity-header field, as defined in + RFC 1864, is an MD5 digest of the entity-body for the purpose of + providing an end-to-end message integrity check (MIC) of the + entity-body. (Note: a MIC is good for detecting accidental + modification of the entity-body in transit, but is not proof + against malicious attacks.)""", + ) + date = header_property( + "Date", + None, + parse_date, + http_date, + doc="""The Date general-header field represents the date and + time at which the message was originated, having the same + semantics as orig-date in RFC 822. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + expires = header_property( + "Expires", + None, + parse_date, + http_date, + doc="""The Expires entity-header field gives the date/time after + which the response is considered stale. A stale cache entry may + not normally be returned by a cache. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + last_modified = header_property( + "Last-Modified", + None, + parse_date, + http_date, + doc="""The Last-Modified entity-header field indicates the date + and time at which the origin server believes the variant was + last modified. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + + @property + def retry_after(self) -> datetime | None: + """The Retry-After response-header field can be used with a + 503 (Service Unavailable) response to indicate how long the + service is expected to be unavailable to the requesting client. + + Time in seconds until expiration or date. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + value = self.headers.get("retry-after") + if value is None: + return None + + try: + seconds = int(value) + except ValueError: + return parse_date(value) + + return datetime.now(timezone.utc) + timedelta(seconds=seconds) + + @retry_after.setter + def retry_after(self, value: datetime | int | str | None) -> None: + if value is None: + if "retry-after" in self.headers: + del self.headers["retry-after"] + return + elif isinstance(value, datetime): + value = http_date(value) + else: + value = str(value) + self.headers["Retry-After"] = value + + vary = _set_property( + "Vary", + doc="""The Vary field value indicates the set of request-header + fields that fully determines, while the response is fresh, + whether a cache is permitted to use the response to reply to a + subsequent request without revalidation.""", + ) + content_language = _set_property( + "Content-Language", + doc="""The Content-Language entity-header field describes the + natural language(s) of the intended audience for the enclosed + entity. Note that this might not be equivalent to all the + languages used within the entity-body.""", + ) + allow = _set_property( + "Allow", + doc="""The Allow entity-header field lists the set of methods + supported by the resource identified by the Request-URI. The + purpose of this field is strictly to inform the recipient of + valid methods associated with the resource. An Allow header + field MUST be present in a 405 (Method Not Allowed) + response.""", + ) + + # ETag + + @property + def cache_control(self) -> ResponseCacheControl: + """The Cache-Control general-header field is used to specify + directives that MUST be obeyed by all caching mechanisms along the + request/response chain. + """ + + def on_update(cache_control: _CacheControl) -> None: + if not cache_control and "cache-control" in self.headers: + del self.headers["cache-control"] + elif cache_control: + self.headers["Cache-Control"] = cache_control.to_header() + + return parse_cache_control_header( + self.headers.get("cache-control"), on_update, ResponseCacheControl + ) + + def set_etag(self, etag: str, weak: bool = False) -> None: + """Set the etag, and override the old one if there was one.""" + self.headers["ETag"] = quote_etag(etag, weak) + + def get_etag(self) -> tuple[str, bool] | tuple[None, None]: + """Return a tuple in the form ``(etag, is_weak)``. If there is no + ETag the return value is ``(None, None)``. + """ + return unquote_etag(self.headers.get("ETag")) + + accept_ranges = header_property[str]( + "Accept-Ranges", + doc="""The `Accept-Ranges` header. Even though the name would + indicate that multiple values are supported, it must be one + string token only. + + The values ``'bytes'`` and ``'none'`` are common. + + .. versionadded:: 0.7""", + ) + + @property + def content_range(self) -> ContentRange: + """The ``Content-Range`` header as a + :class:`~werkzeug.datastructures.ContentRange` object. Available + even if the header is not set. + + .. versionadded:: 0.7 + """ + + def on_update(rng: ContentRange) -> None: + if not rng: + del self.headers["content-range"] + else: + self.headers["Content-Range"] = rng.to_header() + + rv = parse_content_range_header(self.headers.get("content-range"), on_update) + # always provide a content range object to make the descriptor + # more user friendly. It provides an unset() method that can be + # used to remove the header quickly. + if rv is None: + rv = ContentRange(None, None, None, on_update=on_update) + return rv + + @content_range.setter + def content_range(self, value: ContentRange | str | None) -> None: + if not value: + del self.headers["content-range"] + elif isinstance(value, str): + self.headers["Content-Range"] = value + else: + self.headers["Content-Range"] = value.to_header() + + # Authorization + + @property + def www_authenticate(self) -> WWWAuthenticate: + """The ``WWW-Authenticate`` header parsed into a :class:`.WWWAuthenticate` + object. Modifying the object will modify the header value. + + This header is not set by default. To set this header, assign an instance of + :class:`.WWWAuthenticate` to this attribute. + + .. code-block:: python + + response.www_authenticate = WWWAuthenticate( + "basic", {"realm": "Authentication Required"} + ) + + Multiple values for this header can be sent to give the client multiple options. + Assign a list to set multiple headers. However, modifying the items in the list + will not automatically update the header values, and accessing this attribute + will only ever return the first value. + + To unset this header, assign ``None`` or use ``del``. + + .. versionchanged:: 2.3 + This attribute can be assigned to to set the header. A list can be assigned + to set multiple header values. Use ``del`` to unset the header. + + .. versionchanged:: 2.3 + :class:`WWWAuthenticate` is no longer a ``dict``. The ``token`` attribute + was added for auth challenges that use a token instead of parameters. + """ + value = WWWAuthenticate.from_header(self.headers.get("WWW-Authenticate")) + + if value is None: + value = WWWAuthenticate("basic") + + def on_update(value: WWWAuthenticate) -> None: + self.www_authenticate = value + + value._on_update = on_update + return value + + @www_authenticate.setter + def www_authenticate( + self, value: WWWAuthenticate | list[WWWAuthenticate] | None + ) -> None: + if not value: # None or empty list + del self.www_authenticate + elif isinstance(value, list): + # Clear any existing header by setting the first item. + self.headers.set("WWW-Authenticate", value[0].to_header()) + + for item in value[1:]: + # Add additional header lines for additional items. + self.headers.add("WWW-Authenticate", item.to_header()) + else: + self.headers.set("WWW-Authenticate", value.to_header()) + + def on_update(value: WWWAuthenticate) -> None: + self.www_authenticate = value + + # When setting a single value, allow updating it directly. + value._on_update = on_update + + @www_authenticate.deleter + def www_authenticate(self) -> None: + if "WWW-Authenticate" in self.headers: + del self.headers["WWW-Authenticate"] + + # CSP + + @property + def content_security_policy(self) -> ContentSecurityPolicy: + """The ``Content-Security-Policy`` header as a + :class:`~werkzeug.datastructures.ContentSecurityPolicy` object. Available + even if the header is not set. + + The Content-Security-Policy header adds an additional layer of + security to help detect and mitigate certain types of attacks. + """ + + def on_update(csp: ContentSecurityPolicy) -> None: + if not csp: + del self.headers["content-security-policy"] + else: + self.headers["Content-Security-Policy"] = csp.to_header() + + rv = parse_csp_header(self.headers.get("content-security-policy"), on_update) + if rv is None: + rv = ContentSecurityPolicy(None, on_update=on_update) + return rv + + @content_security_policy.setter + def content_security_policy( + self, value: ContentSecurityPolicy | str | None + ) -> None: + if not value: + del self.headers["content-security-policy"] + elif isinstance(value, str): + self.headers["Content-Security-Policy"] = value + else: + self.headers["Content-Security-Policy"] = value.to_header() + + @property + def content_security_policy_report_only(self) -> ContentSecurityPolicy: + """The ``Content-Security-policy-report-only`` header as a + :class:`~werkzeug.datastructures.ContentSecurityPolicy` object. Available + even if the header is not set. + + The Content-Security-Policy-Report-Only header adds a csp policy + that is not enforced but is reported thereby helping detect + certain types of attacks. + """ + + def on_update(csp: ContentSecurityPolicy) -> None: + if not csp: + del self.headers["content-security-policy-report-only"] + else: + self.headers["Content-Security-policy-report-only"] = csp.to_header() + + rv = parse_csp_header( + self.headers.get("content-security-policy-report-only"), on_update + ) + if rv is None: + rv = ContentSecurityPolicy(None, on_update=on_update) + return rv + + @content_security_policy_report_only.setter + def content_security_policy_report_only( + self, value: ContentSecurityPolicy | str | None + ) -> None: + if not value: + del self.headers["content-security-policy-report-only"] + elif isinstance(value, str): + self.headers["Content-Security-policy-report-only"] = value + else: + self.headers["Content-Security-policy-report-only"] = value.to_header() + + # CORS + + @property + def access_control_allow_credentials(self) -> bool: + """Whether credentials can be shared by the browser to + JavaScript code. As part of the preflight request it indicates + whether credentials can be used on the cross origin request. + """ + return "Access-Control-Allow-Credentials" in self.headers + + @access_control_allow_credentials.setter + def access_control_allow_credentials(self, value: bool | None) -> None: + if value is True: + self.headers["Access-Control-Allow-Credentials"] = "true" + else: + self.headers.pop("Access-Control-Allow-Credentials", None) + + access_control_allow_headers = header_property( + "Access-Control-Allow-Headers", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which headers can be sent with the cross origin request.", + ) + + access_control_allow_methods = header_property( + "Access-Control-Allow-Methods", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which methods can be used for the cross origin request.", + ) + + access_control_allow_origin = header_property[str]( + "Access-Control-Allow-Origin", + doc="The origin or '*' for any origin that may make cross origin requests.", + ) + + access_control_expose_headers = header_property( + "Access-Control-Expose-Headers", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which headers can be shared by the browser to JavaScript code.", + ) + + access_control_max_age = header_property( + "Access-Control-Max-Age", + load_func=int, + dump_func=str, + doc="The maximum age in seconds the access control settings can be cached for.", + ) + + cross_origin_opener_policy = header_property[COOP]( + "Cross-Origin-Opener-Policy", + load_func=lambda value: COOP(value), + dump_func=lambda value: value.value, + default=COOP.UNSAFE_NONE, + doc="""Allows control over sharing of browsing context group with cross-origin + documents. Values must be a member of the :class:`werkzeug.http.COOP` enum.""", + ) + + cross_origin_embedder_policy = header_property[COEP]( + "Cross-Origin-Embedder-Policy", + load_func=lambda value: COEP(value), + dump_func=lambda value: value.value, + default=COEP.UNSAFE_NONE, + doc="""Prevents a document from loading any cross-origin resources that do not + explicitly grant the document permission. Values must be a member of the + :class:`werkzeug.http.COEP` enum.""", + ) diff --git a/MLPY/Lib/site-packages/werkzeug/sansio/utils.py b/MLPY/Lib/site-packages/werkzeug/sansio/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..14fa0ac88c91016868f424157773a7490ab08cc4 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/sansio/utils.py @@ -0,0 +1,159 @@ +from __future__ import annotations + +import typing as t +from urllib.parse import quote + +from .._internal import _plain_int +from ..exceptions import SecurityError +from ..urls import uri_to_iri + + +def host_is_trusted(hostname: str | None, trusted_list: t.Iterable[str]) -> bool: + """Check if a host matches a list of trusted names. + + :param hostname: The name to check. + :param trusted_list: A list of valid names to match. If a name + starts with a dot it will match all subdomains. + + .. versionadded:: 0.9 + """ + if not hostname: + return False + + try: + hostname = hostname.partition(":")[0].encode("idna").decode("ascii") + except UnicodeEncodeError: + return False + + if isinstance(trusted_list, str): + trusted_list = [trusted_list] + + for ref in trusted_list: + if ref.startswith("."): + ref = ref[1:] + suffix_match = True + else: + suffix_match = False + + try: + ref = ref.partition(":")[0].encode("idna").decode("ascii") + except UnicodeEncodeError: + return False + + if ref == hostname or (suffix_match and hostname.endswith(f".{ref}")): + return True + + return False + + +def get_host( + scheme: str, + host_header: str | None, + server: tuple[str, int | None] | None = None, + trusted_hosts: t.Iterable[str] | None = None, +) -> str: + """Return the host for the given parameters. + + This first checks the ``host_header``. If it's not present, then + ``server`` is used. The host will only contain the port if it is + different than the standard port for the protocol. + + Optionally, verify that the host is trusted using + :func:`host_is_trusted` and raise a + :exc:`~werkzeug.exceptions.SecurityError` if it is not. + + :param scheme: The protocol the request used, like ``"https"``. + :param host_header: The ``Host`` header value. + :param server: Address of the server. ``(host, port)``, or + ``(path, None)`` for unix sockets. + :param trusted_hosts: A list of trusted host names. + + :return: Host, with port if necessary. + :raise ~werkzeug.exceptions.SecurityError: If the host is not + trusted. + """ + host = "" + + if host_header is not None: + host = host_header + elif server is not None: + host = server[0] + + if server[1] is not None: + host = f"{host}:{server[1]}" + + if scheme in {"http", "ws"} and host.endswith(":80"): + host = host[:-3] + elif scheme in {"https", "wss"} and host.endswith(":443"): + host = host[:-4] + + if trusted_hosts is not None: + if not host_is_trusted(host, trusted_hosts): + raise SecurityError(f"Host {host!r} is not trusted.") + + return host + + +def get_current_url( + scheme: str, + host: str, + root_path: str | None = None, + path: str | None = None, + query_string: bytes | None = None, +) -> str: + """Recreate the URL for a request. If an optional part isn't + provided, it and subsequent parts are not included in the URL. + + The URL is an IRI, not a URI, so it may contain Unicode characters. + Use :func:`~werkzeug.urls.iri_to_uri` to convert it to ASCII. + + :param scheme: The protocol the request used, like ``"https"``. + :param host: The host the request was made to. See :func:`get_host`. + :param root_path: Prefix that the application is mounted under. This + is prepended to ``path``. + :param path: The path part of the URL after ``root_path``. + :param query_string: The portion of the URL after the "?". + """ + url = [scheme, "://", host] + + if root_path is None: + url.append("/") + return uri_to_iri("".join(url)) + + # safe = https://url.spec.whatwg.org/#url-path-segment-string + # as well as percent for things that are already quoted + url.append(quote(root_path.rstrip("/"), safe="!$&'()*+,/:;=@%")) + url.append("/") + + if path is None: + return uri_to_iri("".join(url)) + + url.append(quote(path.lstrip("/"), safe="!$&'()*+,/:;=@%")) + + if query_string: + url.append("?") + url.append(quote(query_string, safe="!$&'()*+,/:;=?@%")) + + return uri_to_iri("".join(url)) + + +def get_content_length( + http_content_length: str | None = None, + http_transfer_encoding: str | None = None, +) -> int | None: + """Return the ``Content-Length`` header value as an int. If the header is not given + or the ``Transfer-Encoding`` header is ``chunked``, ``None`` is returned to indicate + a streaming request. If the value is not an integer, or negative, 0 is returned. + + :param http_content_length: The Content-Length HTTP header. + :param http_transfer_encoding: The Transfer-Encoding HTTP header. + + .. versionadded:: 2.2 + """ + if http_transfer_encoding == "chunked" or http_content_length is None: + return None + + try: + return max(0, _plain_int(http_content_length)) + except ValueError: + return 0 diff --git a/MLPY/Lib/site-packages/werkzeug/security.py b/MLPY/Lib/site-packages/werkzeug/security.py new file mode 100644 index 0000000000000000000000000000000000000000..9999509d111704b1b259f7bedf8876dca9bb66df --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/security.py @@ -0,0 +1,161 @@ +from __future__ import annotations + +import hashlib +import hmac +import os +import posixpath +import secrets + +SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +DEFAULT_PBKDF2_ITERATIONS = 600000 + +_os_alt_seps: list[str] = list( + sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/" +) + + +def gen_salt(length: int) -> str: + """Generate a random string of SALT_CHARS with specified ``length``.""" + if length <= 0: + raise ValueError("Salt length must be at least 1.") + + return "".join(secrets.choice(SALT_CHARS) for _ in range(length)) + + +def _hash_internal(method: str, salt: str, password: str) -> tuple[str, str]: + method, *args = method.split(":") + salt_bytes = salt.encode() + password_bytes = password.encode() + + if method == "scrypt": + if not args: + n = 2**15 + r = 8 + p = 1 + else: + try: + n, r, p = map(int, args) + except ValueError: + raise ValueError("'scrypt' takes 3 arguments.") from None + + maxmem = 132 * n * r * p # ideally 128, but some extra seems needed + return ( + hashlib.scrypt( + password_bytes, salt=salt_bytes, n=n, r=r, p=p, maxmem=maxmem + ).hex(), + f"scrypt:{n}:{r}:{p}", + ) + elif method == "pbkdf2": + len_args = len(args) + + if len_args == 0: + hash_name = "sha256" + iterations = DEFAULT_PBKDF2_ITERATIONS + elif len_args == 1: + hash_name = args[0] + iterations = DEFAULT_PBKDF2_ITERATIONS + elif len_args == 2: + hash_name = args[0] + iterations = int(args[1]) + else: + raise ValueError("'pbkdf2' takes 2 arguments.") + + return ( + hashlib.pbkdf2_hmac( + hash_name, password_bytes, salt_bytes, iterations + ).hex(), + f"pbkdf2:{hash_name}:{iterations}", + ) + else: + raise ValueError(f"Invalid hash method '{method}'.") + + +def generate_password_hash( + password: str, method: str = "scrypt", salt_length: int = 16 +) -> str: + """Securely hash a password for storage. A password can be compared to a stored hash + using :func:`check_password_hash`. + + The following methods are supported: + + - ``scrypt``, the default. The parameters are ``n``, ``r``, and ``p``, the default + is ``scrypt:32768:8:1``. See :func:`hashlib.scrypt`. + - ``pbkdf2``, less secure. The parameters are ``hash_method`` and ``iterations``, + the default is ``pbkdf2:sha256:600000``. See :func:`hashlib.pbkdf2_hmac`. + + Default parameters may be updated to reflect current guidelines, and methods may be + deprecated and removed if they are no longer considered secure. To migrate old + hashes, you may generate a new hash when checking an old hash, or you may contact + users with a link to reset their password. + + :param password: The plaintext password. + :param method: The key derivation function and parameters. + :param salt_length: The number of characters to generate for the salt. + + .. versionchanged:: 2.3 + Scrypt support was added. + + .. versionchanged:: 2.3 + The default iterations for pbkdf2 was increased to 600,000. + + .. versionchanged:: 2.3 + All plain hashes are deprecated and will not be supported in Werkzeug 3.0. + """ + salt = gen_salt(salt_length) + h, actual_method = _hash_internal(method, salt, password) + return f"{actual_method}${salt}${h}" + + +def check_password_hash(pwhash: str, password: str) -> bool: + """Securely check that the given stored password hash, previously generated using + :func:`generate_password_hash`, matches the given password. + + Methods may be deprecated and removed if they are no longer considered secure. To + migrate old hashes, you may generate a new hash when checking an old hash, or you + may contact users with a link to reset their password. + + :param pwhash: The hashed password. + :param password: The plaintext password. + + .. versionchanged:: 2.3 + All plain hashes are deprecated and will not be supported in Werkzeug 3.0. + """ + try: + method, salt, hashval = pwhash.split("$", 2) + except ValueError: + return False + + return hmac.compare_digest(_hash_internal(method, salt, password)[0], hashval) + + +def safe_join(directory: str, *pathnames: str) -> str | None: + """Safely join zero or more untrusted path components to a base + directory to avoid escaping the base directory. + + :param directory: The trusted base directory. + :param pathnames: The untrusted path components relative to the + base directory. + :return: A safe path, otherwise ``None``. + """ + if not directory: + # Ensure we end up with ./path if directory="" is given, + # otherwise the first untrusted part could become trusted. + directory = "." + + parts = [directory] + + for filename in pathnames: + if filename != "": + filename = posixpath.normpath(filename) + + if ( + any(sep in filename for sep in _os_alt_seps) + or os.path.isabs(filename) + or filename == ".." + or filename.startswith("../") + ): + return None + + parts.append(filename) + + return posixpath.join(*parts) diff --git a/MLPY/Lib/site-packages/werkzeug/serving.py b/MLPY/Lib/site-packages/werkzeug/serving.py new file mode 100644 index 0000000000000000000000000000000000000000..859f9aacb69d015e4d001a3a8b807af498be9b44 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/serving.py @@ -0,0 +1,1116 @@ +"""A WSGI and HTTP server for use **during development only**. This +server is convenient to use, but is not designed to be particularly +stable, secure, or efficient. Use a dedicate WSGI server and HTTP +server when deploying to production. + +It provides features like interactive debugging and code reloading. Use +``run_simple`` to start the server. Put this in a ``run.py`` script: + +.. code-block:: python + + from myapp import create_app + from werkzeug import run_simple +""" + +from __future__ import annotations + +import errno +import io +import os +import selectors +import socket +import socketserver +import sys +import typing as t +from datetime import datetime as dt +from datetime import timedelta +from datetime import timezone +from http.server import BaseHTTPRequestHandler +from http.server import HTTPServer +from urllib.parse import unquote +from urllib.parse import urlsplit + +from ._internal import _log +from ._internal import _wsgi_encoding_dance +from .exceptions import InternalServerError +from .urls import uri_to_iri + +try: + import ssl +except ImportError: + + class _SslDummy: + def __getattr__(self, name: str) -> t.Any: + raise RuntimeError( # noqa: B904 + "SSL is unavailable because this Python runtime was not" + " compiled with SSL/TLS support." + ) + + ssl = _SslDummy() # type: ignore + +_log_add_style = True + +if os.name == "nt": + try: + __import__("colorama") + except ImportError: + _log_add_style = False + +can_fork = hasattr(os, "fork") + +if can_fork: + ForkingMixIn = socketserver.ForkingMixIn +else: + + class ForkingMixIn: # type: ignore + pass + + +try: + af_unix = socket.AF_UNIX +except AttributeError: + af_unix = None # type: ignore + +LISTEN_QUEUE = 128 + +_TSSLContextArg = t.Optional[ + t.Union["ssl.SSLContext", t.Tuple[str, t.Optional[str]], t.Literal["adhoc"]] +] + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + from cryptography.hazmat.primitives.asymmetric.rsa import ( + RSAPrivateKeyWithSerialization, + ) + from cryptography.x509 import Certificate + + +class DechunkedInput(io.RawIOBase): + """An input stream that handles Transfer-Encoding 'chunked'""" + + def __init__(self, rfile: t.IO[bytes]) -> None: + self._rfile = rfile + self._done = False + self._len = 0 + + def readable(self) -> bool: + return True + + def read_chunk_len(self) -> int: + try: + line = self._rfile.readline().decode("latin1") + _len = int(line.strip(), 16) + except ValueError as e: + raise OSError("Invalid chunk header") from e + if _len < 0: + raise OSError("Negative chunk length not allowed") + return _len + + def readinto(self, buf: bytearray) -> int: # type: ignore + read = 0 + while not self._done and read < len(buf): + if self._len == 0: + # This is the first chunk or we fully consumed the previous + # one. Read the next length of the next chunk + self._len = self.read_chunk_len() + + if self._len == 0: + # Found the final chunk of size 0. The stream is now exhausted, + # but there is still a final newline that should be consumed + self._done = True + + if self._len > 0: + # There is data (left) in this chunk, so append it to the + # buffer. If this operation fully consumes the chunk, this will + # reset self._len to 0. + n = min(len(buf), self._len) + + # If (read + chunk size) becomes more than len(buf), buf will + # grow beyond the original size and read more data than + # required. So only read as much data as can fit in buf. + if read + n > len(buf): + buf[read:] = self._rfile.read(len(buf) - read) + self._len -= len(buf) - read + read = len(buf) + else: + buf[read : read + n] = self._rfile.read(n) + self._len -= n + read += n + + if self._len == 0: + # Skip the terminating newline of a chunk that has been fully + # consumed. This also applies to the 0-sized final chunk + terminator = self._rfile.readline() + if terminator not in (b"\n", b"\r\n", b"\r"): + raise OSError("Missing chunk terminating newline") + + return read + + +class WSGIRequestHandler(BaseHTTPRequestHandler): + """A request handler that implements WSGI dispatching.""" + + server: BaseWSGIServer + + @property + def server_version(self) -> str: # type: ignore + return self.server._server_version + + def make_environ(self) -> WSGIEnvironment: + request_url = urlsplit(self.path) + url_scheme = "http" if self.server.ssl_context is None else "https" + + if not self.client_address: + self.client_address = ("", 0) + elif isinstance(self.client_address, str): + self.client_address = (self.client_address, 0) + + # If there was no scheme but the path started with two slashes, + # the first segment may have been incorrectly parsed as the + # netloc, prepend it to the path again. + if not request_url.scheme and request_url.netloc: + path_info = f"/{request_url.netloc}{request_url.path}" + else: + path_info = request_url.path + + path_info = unquote(path_info) + + environ: WSGIEnvironment = { + "wsgi.version": (1, 0), + "wsgi.url_scheme": url_scheme, + "wsgi.input": self.rfile, + "wsgi.errors": sys.stderr, + "wsgi.multithread": self.server.multithread, + "wsgi.multiprocess": self.server.multiprocess, + "wsgi.run_once": False, + "werkzeug.socket": self.connection, + "SERVER_SOFTWARE": self.server_version, + "REQUEST_METHOD": self.command, + "SCRIPT_NAME": "", + "PATH_INFO": _wsgi_encoding_dance(path_info), + "QUERY_STRING": _wsgi_encoding_dance(request_url.query), + # Non-standard, added by mod_wsgi, uWSGI + "REQUEST_URI": _wsgi_encoding_dance(self.path), + # Non-standard, added by gunicorn + "RAW_URI": _wsgi_encoding_dance(self.path), + "REMOTE_ADDR": self.address_string(), + "REMOTE_PORT": self.port_integer(), + "SERVER_NAME": self.server.server_address[0], + "SERVER_PORT": str(self.server.server_address[1]), + "SERVER_PROTOCOL": self.request_version, + } + + for key, value in self.headers.items(): + if "_" in key: + continue + + key = key.upper().replace("-", "_") + value = value.replace("\r\n", "") + if key not in ("CONTENT_TYPE", "CONTENT_LENGTH"): + key = f"HTTP_{key}" + if key in environ: + value = f"{environ[key]},{value}" + environ[key] = value + + if environ.get("HTTP_TRANSFER_ENCODING", "").strip().lower() == "chunked": + environ["wsgi.input_terminated"] = True + environ["wsgi.input"] = DechunkedInput(environ["wsgi.input"]) + + # Per RFC 2616, if the URL is absolute, use that as the host. + # We're using "has a scheme" to indicate an absolute URL. + if request_url.scheme and request_url.netloc: + environ["HTTP_HOST"] = request_url.netloc + + try: + # binary_form=False gives nicer information, but wouldn't be compatible with + # what Nginx or Apache could return. + peer_cert = self.connection.getpeercert(binary_form=True) + if peer_cert is not None: + # Nginx and Apache use PEM format. + environ["SSL_CLIENT_CERT"] = ssl.DER_cert_to_PEM_cert(peer_cert) + except ValueError: + # SSL handshake hasn't finished. + self.server.log("error", "Cannot fetch SSL peer certificate info") + except AttributeError: + # Not using TLS, the socket will not have getpeercert(). + pass + + return environ + + def run_wsgi(self) -> None: + if self.headers.get("Expect", "").lower().strip() == "100-continue": + self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n") + + self.environ = environ = self.make_environ() + status_set: str | None = None + headers_set: list[tuple[str, str]] | None = None + status_sent: str | None = None + headers_sent: list[tuple[str, str]] | None = None + chunk_response: bool = False + + def write(data: bytes) -> None: + nonlocal status_sent, headers_sent, chunk_response + assert status_set is not None, "write() before start_response" + assert headers_set is not None, "write() before start_response" + if status_sent is None: + status_sent = status_set + headers_sent = headers_set + try: + code_str, msg = status_sent.split(None, 1) + except ValueError: + code_str, msg = status_sent, "" + code = int(code_str) + self.send_response(code, msg) + header_keys = set() + for key, value in headers_sent: + self.send_header(key, value) + header_keys.add(key.lower()) + + # Use chunked transfer encoding if there is no content + # length. Do not use for 1xx and 204 responses. 304 + # responses and HEAD requests are also excluded, which + # is the more conservative behavior and matches other + # parts of the code. + # https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.1 + if ( + not ( + "content-length" in header_keys + or environ["REQUEST_METHOD"] == "HEAD" + or (100 <= code < 200) + or code in {204, 304} + ) + and self.protocol_version >= "HTTP/1.1" + ): + chunk_response = True + self.send_header("Transfer-Encoding", "chunked") + + # Always close the connection. This disables HTTP/1.1 + # keep-alive connections. They aren't handled well by + # Python's http.server because it doesn't know how to + # drain the stream before the next request line. + self.send_header("Connection", "close") + self.end_headers() + + assert isinstance(data, bytes), "applications must write bytes" + + if data: + if chunk_response: + self.wfile.write(hex(len(data))[2:].encode()) + self.wfile.write(b"\r\n") + + self.wfile.write(data) + + if chunk_response: + self.wfile.write(b"\r\n") + + self.wfile.flush() + + def start_response(status, headers, exc_info=None): # type: ignore + nonlocal status_set, headers_set + if exc_info: + try: + if headers_sent: + raise exc_info[1].with_traceback(exc_info[2]) + finally: + exc_info = None + elif headers_set: + raise AssertionError("Headers already set") + status_set = status + headers_set = headers + return write + + def execute(app: WSGIApplication) -> None: + application_iter = app(environ, start_response) + try: + for data in application_iter: + write(data) + if not headers_sent: + write(b"") + if chunk_response: + self.wfile.write(b"0\r\n\r\n") + finally: + # Check for any remaining data in the read socket, and discard it. This + # will read past request.max_content_length, but lets the client see a + # 413 response instead of a connection reset failure. If we supported + # keep-alive connections, this naive approach would break by reading the + # next request line. Since we know that write (above) closes every + # connection we can read everything. + selector = selectors.DefaultSelector() + selector.register(self.connection, selectors.EVENT_READ) + total_size = 0 + total_reads = 0 + + # A timeout of 0 tends to fail because a client needs a small amount of + # time to continue sending its data. + while selector.select(timeout=0.01): + # Only read 10MB into memory at a time. + data = self.rfile.read(10_000_000) + total_size += len(data) + total_reads += 1 + + # Stop reading on no data, >=10GB, or 1000 reads. If a client sends + # more than that, they'll get a connection reset failure. + if not data or total_size >= 10_000_000_000 or total_reads > 1000: + break + + selector.close() + + if hasattr(application_iter, "close"): + application_iter.close() + + try: + execute(self.server.app) + except (ConnectionError, socket.timeout) as e: + self.connection_dropped(e, environ) + except Exception as e: + if self.server.passthrough_errors: + raise + + if status_sent is not None and chunk_response: + self.close_connection = True + + try: + # if we haven't yet sent the headers but they are set + # we roll back to be able to set them again. + if status_sent is None: + status_set = None + headers_set = None + execute(InternalServerError()) + except Exception: + pass + + from .debug.tbtools import DebugTraceback + + msg = DebugTraceback(e).render_traceback_text() + self.server.log("error", f"Error on request:\n{msg}") + + def handle(self) -> None: + """Handles a request ignoring dropped connections.""" + try: + super().handle() + except (ConnectionError, socket.timeout) as e: + self.connection_dropped(e) + except Exception as e: + if self.server.ssl_context is not None and is_ssl_error(e): + self.log_error("SSL error occurred: %s", e) + else: + raise + + def connection_dropped( + self, error: BaseException, environ: WSGIEnvironment | None = None + ) -> None: + """Called if the connection was closed by the client. By default + nothing happens. + """ + + def __getattr__(self, name: str) -> t.Any: + # All HTTP methods are handled by run_wsgi. + if name.startswith("do_"): + return self.run_wsgi + + # All other attributes are forwarded to the base class. + return getattr(super(), name) + + def address_string(self) -> str: + if getattr(self, "environ", None): + return self.environ["REMOTE_ADDR"] # type: ignore + + if not self.client_address: + return "" + + return self.client_address[0] + + def port_integer(self) -> int: + return self.client_address[1] + + # Escape control characters. This is defined (but private) in Python 3.12. + _control_char_table = str.maketrans( + {c: rf"\x{c:02x}" for c in [*range(0x20), *range(0x7F, 0xA0)]} + ) + _control_char_table[ord("\\")] = r"\\" + + def log_request(self, code: int | str = "-", size: int | str = "-") -> None: + try: + path = uri_to_iri(self.path) + msg = f"{self.command} {path} {self.request_version}" + except AttributeError: + # path isn't set if the requestline was bad + msg = self.requestline + + # Escape control characters that may be in the decoded path. + msg = msg.translate(self._control_char_table) + code = str(code) + + if code[0] == "1": # 1xx - Informational + msg = _ansi_style(msg, "bold") + elif code == "200": # 2xx - Success + pass + elif code == "304": # 304 - Resource Not Modified + msg = _ansi_style(msg, "cyan") + elif code[0] == "3": # 3xx - Redirection + msg = _ansi_style(msg, "green") + elif code == "404": # 404 - Resource Not Found + msg = _ansi_style(msg, "yellow") + elif code[0] == "4": # 4xx - Client Error + msg = _ansi_style(msg, "bold", "red") + else: # 5xx, or any other response + msg = _ansi_style(msg, "bold", "magenta") + + self.log("info", '"%s" %s %s', msg, code, size) + + def log_error(self, format: str, *args: t.Any) -> None: + self.log("error", format, *args) + + def log_message(self, format: str, *args: t.Any) -> None: + self.log("info", format, *args) + + def log(self, type: str, message: str, *args: t.Any) -> None: + _log( + type, + f"{self.address_string()} - - [{self.log_date_time_string()}] {message}\n", + *args, + ) + + +def _ansi_style(value: str, *styles: str) -> str: + if not _log_add_style: + return value + + codes = { + "bold": 1, + "red": 31, + "green": 32, + "yellow": 33, + "magenta": 35, + "cyan": 36, + } + + for style in styles: + value = f"\x1b[{codes[style]}m{value}" + + return f"{value}\x1b[0m" + + +def generate_adhoc_ssl_pair( + cn: str | None = None, +) -> tuple[Certificate, RSAPrivateKeyWithSerialization]: + try: + from cryptography import x509 + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import rsa + from cryptography.x509.oid import NameOID + except ImportError: + raise TypeError( + "Using ad-hoc certificates requires the cryptography library." + ) from None + + backend = default_backend() + pkey = rsa.generate_private_key( + public_exponent=65537, key_size=2048, backend=backend + ) + + # pretty damn sure that this is not actually accepted by anyone + if cn is None: + cn = "*" + + subject = x509.Name( + [ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Dummy Certificate"), + x509.NameAttribute(NameOID.COMMON_NAME, cn), + ] + ) + + backend = default_backend() + cert = ( + x509.CertificateBuilder() + .subject_name(subject) + .issuer_name(subject) + .public_key(pkey.public_key()) + .serial_number(x509.random_serial_number()) + .not_valid_before(dt.now(timezone.utc)) + .not_valid_after(dt.now(timezone.utc) + timedelta(days=365)) + .add_extension(x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False) + .add_extension( + x509.SubjectAlternativeName([x509.DNSName(cn), x509.DNSName(f"*.{cn}")]), + critical=False, + ) + .sign(pkey, hashes.SHA256(), backend) + ) + return cert, pkey + + +def make_ssl_devcert( + base_path: str, host: str | None = None, cn: str | None = None +) -> tuple[str, str]: + """Creates an SSL key for development. This should be used instead of + the ``'adhoc'`` key which generates a new cert on each server start. + It accepts a path for where it should store the key and cert and + either a host or CN. If a host is given it will use the CN + ``*.host/CN=host``. + + For more information see :func:`run_simple`. + + .. versionadded:: 0.9 + + :param base_path: the path to the certificate and key. The extension + ``.crt`` is added for the certificate, ``.key`` is + added for the key. + :param host: the name of the host. This can be used as an alternative + for the `cn`. + :param cn: the `CN` to use. + """ + + if host is not None: + cn = host + cert, pkey = generate_adhoc_ssl_pair(cn=cn) + + from cryptography.hazmat.primitives import serialization + + cert_file = f"{base_path}.crt" + pkey_file = f"{base_path}.key" + + with open(cert_file, "wb") as f: + f.write(cert.public_bytes(serialization.Encoding.PEM)) + with open(pkey_file, "wb") as f: + f.write( + pkey.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ) + ) + + return cert_file, pkey_file + + +def generate_adhoc_ssl_context() -> ssl.SSLContext: + """Generates an adhoc SSL context for the development server.""" + import atexit + import tempfile + + cert, pkey = generate_adhoc_ssl_pair() + + from cryptography.hazmat.primitives import serialization + + cert_handle, cert_file = tempfile.mkstemp() + pkey_handle, pkey_file = tempfile.mkstemp() + atexit.register(os.remove, pkey_file) + atexit.register(os.remove, cert_file) + + os.write(cert_handle, cert.public_bytes(serialization.Encoding.PEM)) + os.write( + pkey_handle, + pkey.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ), + ) + + os.close(cert_handle) + os.close(pkey_handle) + ctx = load_ssl_context(cert_file, pkey_file) + return ctx + + +def load_ssl_context( + cert_file: str, pkey_file: str | None = None, protocol: int | None = None +) -> ssl.SSLContext: + """Loads SSL context from cert/private key files and optional protocol. + Many parameters are directly taken from the API of + :py:class:`ssl.SSLContext`. + + :param cert_file: Path of the certificate to use. + :param pkey_file: Path of the private key to use. If not given, the key + will be obtained from the certificate file. + :param protocol: A ``PROTOCOL`` constant from the :mod:`ssl` module. + Defaults to :data:`ssl.PROTOCOL_TLS_SERVER`. + """ + if protocol is None: + protocol = ssl.PROTOCOL_TLS_SERVER + + ctx = ssl.SSLContext(protocol) + ctx.load_cert_chain(cert_file, pkey_file) + return ctx + + +def is_ssl_error(error: Exception | None = None) -> bool: + """Checks if the given error (or the current one) is an SSL error.""" + if error is None: + error = t.cast(Exception, sys.exc_info()[1]) + return isinstance(error, ssl.SSLError) + + +def select_address_family(host: str, port: int) -> socket.AddressFamily: + """Return ``AF_INET4``, ``AF_INET6``, or ``AF_UNIX`` depending on + the host and port.""" + if host.startswith("unix://"): + return socket.AF_UNIX + elif ":" in host and hasattr(socket, "AF_INET6"): + return socket.AF_INET6 + return socket.AF_INET + + +def get_sockaddr( + host: str, port: int, family: socket.AddressFamily +) -> tuple[str, int] | str: + """Return a fully qualified socket address that can be passed to + :func:`socket.bind`.""" + if family == af_unix: + # Absolute path avoids IDNA encoding error when path starts with dot. + return os.path.abspath(host.partition("://")[2]) + try: + res = socket.getaddrinfo( + host, port, family, socket.SOCK_STREAM, socket.IPPROTO_TCP + ) + except socket.gaierror: + return host, port + return res[0][4] # type: ignore + + +def get_interface_ip(family: socket.AddressFamily) -> str: + """Get the IP address of an external interface. Used when binding to + 0.0.0.0 or ::1 to show a more useful URL. + + :meta private: + """ + # arbitrary private address + host = "fd31:f903:5ab5:1::1" if family == socket.AF_INET6 else "10.253.155.219" + + with socket.socket(family, socket.SOCK_DGRAM) as s: + try: + s.connect((host, 58162)) + except OSError: + return "::1" if family == socket.AF_INET6 else "127.0.0.1" + + return s.getsockname()[0] # type: ignore + + +class BaseWSGIServer(HTTPServer): + """A WSGI server that that handles one request at a time. + + Use :func:`make_server` to create a server instance. + """ + + multithread = False + multiprocess = False + request_queue_size = LISTEN_QUEUE + allow_reuse_address = True + + def __init__( + self, + host: str, + port: int, + app: WSGIApplication, + handler: type[WSGIRequestHandler] | None = None, + passthrough_errors: bool = False, + ssl_context: _TSSLContextArg | None = None, + fd: int | None = None, + ) -> None: + if handler is None: + handler = WSGIRequestHandler + + # If the handler doesn't directly set a protocol version and + # thread or process workers are used, then allow chunked + # responses and keep-alive connections by enabling HTTP/1.1. + if "protocol_version" not in vars(handler) and ( + self.multithread or self.multiprocess + ): + handler.protocol_version = "HTTP/1.1" + + self.host = host + self.port = port + self.app = app + self.passthrough_errors = passthrough_errors + + self.address_family = address_family = select_address_family(host, port) + server_address = get_sockaddr(host, int(port), address_family) + + # Remove a leftover Unix socket file from a previous run. Don't + # remove a file that was set up by run_simple. + if address_family == af_unix and fd is None: + server_address = t.cast(str, server_address) + + if os.path.exists(server_address): + os.unlink(server_address) + + # Bind and activate will be handled manually, it should only + # happen if we're not using a socket that was already set up. + super().__init__( + server_address, # type: ignore[arg-type] + handler, + bind_and_activate=False, + ) + + if fd is None: + # No existing socket descriptor, do bind_and_activate=True. + try: + self.server_bind() + self.server_activate() + except OSError as e: + # Catch connection issues and show them without the traceback. Show + # extra instructions for address not found, and for macOS. + self.server_close() + print(e.strerror, file=sys.stderr) + + if e.errno == errno.EADDRINUSE: + print( + f"Port {port} is in use by another program. Either identify and" + " stop that program, or start the server with a different" + " port.", + file=sys.stderr, + ) + + if sys.platform == "darwin" and port == 5000: + print( + "On macOS, try disabling the 'AirPlay Receiver' service" + " from System Preferences -> General -> AirDrop & Handoff.", + file=sys.stderr, + ) + + sys.exit(1) + except BaseException: + self.server_close() + raise + else: + # TCPServer automatically opens a socket even if bind_and_activate is False. + # Close it to silence a ResourceWarning. + self.server_close() + + # Use the passed in socket directly. + self.socket = socket.fromfd(fd, address_family, socket.SOCK_STREAM) + self.server_address = self.socket.getsockname() + + if address_family != af_unix: + # If port was 0, this will record the bound port. + self.port = self.server_address[1] + + if ssl_context is not None: + if isinstance(ssl_context, tuple): + ssl_context = load_ssl_context(*ssl_context) + elif ssl_context == "adhoc": + ssl_context = generate_adhoc_ssl_context() + + self.socket = ssl_context.wrap_socket(self.socket, server_side=True) + self.ssl_context: ssl.SSLContext | None = ssl_context + else: + self.ssl_context = None + + import importlib.metadata + + self._server_version = f"Werkzeug/{importlib.metadata.version('werkzeug')}" + + def log(self, type: str, message: str, *args: t.Any) -> None: + _log(type, message, *args) + + def serve_forever(self, poll_interval: float = 0.5) -> None: + try: + super().serve_forever(poll_interval=poll_interval) + except KeyboardInterrupt: + pass + finally: + self.server_close() + + def handle_error( + self, request: t.Any, client_address: tuple[str, int] | str + ) -> None: + if self.passthrough_errors: + raise + + return super().handle_error(request, client_address) + + def log_startup(self) -> None: + """Show information about the address when starting the server.""" + dev_warning = ( + "WARNING: This is a development server. Do not use it in a production" + " deployment. Use a production WSGI server instead." + ) + dev_warning = _ansi_style(dev_warning, "bold", "red") + messages = [dev_warning] + + if self.address_family == af_unix: + messages.append(f" * Running on {self.host}") + else: + scheme = "http" if self.ssl_context is None else "https" + display_hostname = self.host + + if self.host in {"0.0.0.0", "::"}: + messages.append(f" * Running on all addresses ({self.host})") + + if self.host == "0.0.0.0": + localhost = "127.0.0.1" + display_hostname = get_interface_ip(socket.AF_INET) + else: + localhost = "[::1]" + display_hostname = get_interface_ip(socket.AF_INET6) + + messages.append(f" * Running on {scheme}://{localhost}:{self.port}") + + if ":" in display_hostname: + display_hostname = f"[{display_hostname}]" + + messages.append(f" * Running on {scheme}://{display_hostname}:{self.port}") + + _log("info", "\n".join(messages)) + + +class ThreadedWSGIServer(socketserver.ThreadingMixIn, BaseWSGIServer): + """A WSGI server that handles concurrent requests in separate + threads. + + Use :func:`make_server` to create a server instance. + """ + + multithread = True + daemon_threads = True + + +class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer): + """A WSGI server that handles concurrent requests in separate forked + processes. + + Use :func:`make_server` to create a server instance. + """ + + multiprocess = True + + def __init__( + self, + host: str, + port: int, + app: WSGIApplication, + processes: int = 40, + handler: type[WSGIRequestHandler] | None = None, + passthrough_errors: bool = False, + ssl_context: _TSSLContextArg | None = None, + fd: int | None = None, + ) -> None: + if not can_fork: + raise ValueError("Your platform does not support forking.") + + super().__init__(host, port, app, handler, passthrough_errors, ssl_context, fd) + self.max_children = processes + + +def make_server( + host: str, + port: int, + app: WSGIApplication, + threaded: bool = False, + processes: int = 1, + request_handler: type[WSGIRequestHandler] | None = None, + passthrough_errors: bool = False, + ssl_context: _TSSLContextArg | None = None, + fd: int | None = None, +) -> BaseWSGIServer: + """Create an appropriate WSGI server instance based on the value of + ``threaded`` and ``processes``. + + This is called from :func:`run_simple`, but can be used separately + to have access to the server object, such as to run it in a separate + thread. + + See :func:`run_simple` for parameter docs. + """ + if threaded and processes > 1: + raise ValueError("Cannot have a multi-thread and multi-process server.") + + if threaded: + return ThreadedWSGIServer( + host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd + ) + + if processes > 1: + return ForkingWSGIServer( + host, + port, + app, + processes, + request_handler, + passthrough_errors, + ssl_context, + fd=fd, + ) + + return BaseWSGIServer( + host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd + ) + + +def is_running_from_reloader() -> bool: + """Check if the server is running as a subprocess within the + Werkzeug reloader. + + .. versionadded:: 0.10 + """ + return os.environ.get("WERKZEUG_RUN_MAIN") == "true" + + +def run_simple( + hostname: str, + port: int, + application: WSGIApplication, + use_reloader: bool = False, + use_debugger: bool = False, + use_evalex: bool = True, + extra_files: t.Iterable[str] | None = None, + exclude_patterns: t.Iterable[str] | None = None, + reloader_interval: int = 1, + reloader_type: str = "auto", + threaded: bool = False, + processes: int = 1, + request_handler: type[WSGIRequestHandler] | None = None, + static_files: dict[str, str | tuple[str, str]] | None = None, + passthrough_errors: bool = False, + ssl_context: _TSSLContextArg | None = None, +) -> None: + """Start a development server for a WSGI application. Various + optional features can be enabled. + + .. warning:: + + Do not use the development server when deploying to production. + It is intended for use only during local development. It is not + designed to be particularly efficient, stable, or secure. + + :param hostname: The host to bind to, for example ``'localhost'``. + Can be a domain, IPv4 or IPv6 address, or file path starting + with ``unix://`` for a Unix socket. + :param port: The port to bind to, for example ``8080``. Using ``0`` + tells the OS to pick a random free port. + :param application: The WSGI application to run. + :param use_reloader: Use a reloader process to restart the server + process when files are changed. + :param use_debugger: Use Werkzeug's debugger, which will show + formatted tracebacks on unhandled exceptions. + :param use_evalex: Make the debugger interactive. A Python terminal + can be opened for any frame in the traceback. Some protection is + provided by requiring a PIN, but this should never be enabled + on a publicly visible server. + :param extra_files: The reloader will watch these files for changes + in addition to Python modules. For example, watch a + configuration file. + :param exclude_patterns: The reloader will ignore changes to any + files matching these :mod:`fnmatch` patterns. For example, + ignore cache files. + :param reloader_interval: How often the reloader tries to check for + changes. + :param reloader_type: The reloader to use. The ``'stat'`` reloader + is built in, but may require significant CPU to watch files. The + ``'watchdog'`` reloader is much more efficient but requires + installing the ``watchdog`` package first. + :param threaded: Handle concurrent requests using threads. Cannot be + used with ``processes``. + :param processes: Handle concurrent requests using up to this number + of processes. Cannot be used with ``threaded``. + :param request_handler: Use a different + :class:`~BaseHTTPServer.BaseHTTPRequestHandler` subclass to + handle requests. + :param static_files: A dict mapping URL prefixes to directories to + serve static files from using + :class:`~werkzeug.middleware.SharedDataMiddleware`. + :param passthrough_errors: Don't catch unhandled exceptions at the + server level, let the server crash instead. If ``use_debugger`` + is enabled, the debugger will still catch such errors. + :param ssl_context: Configure TLS to serve over HTTPS. Can be an + :class:`ssl.SSLContext` object, a ``(cert_file, key_file)`` + tuple to create a typical context, or the string ``'adhoc'`` to + generate a temporary self-signed certificate. + + .. versionchanged:: 2.1 + Instructions are shown for dealing with an "address already in + use" error. + + .. versionchanged:: 2.1 + Running on ``0.0.0.0`` or ``::`` shows the loopback IP in + addition to a real IP. + + .. versionchanged:: 2.1 + The command-line interface was removed. + + .. versionchanged:: 2.0 + Running on ``0.0.0.0`` or ``::`` shows a real IP address that + was bound as well as a warning not to run the development server + in production. + + .. versionchanged:: 2.0 + The ``exclude_patterns`` parameter was added. + + .. versionchanged:: 0.15 + Bind to a Unix socket by passing a ``hostname`` that starts with + ``unix://``. + + .. versionchanged:: 0.10 + Improved the reloader and added support for changing the backend + through the ``reloader_type`` parameter. + + .. versionchanged:: 0.9 + A command-line interface was added. + + .. versionchanged:: 0.8 + ``ssl_context`` can be a tuple of paths to the certificate and + private key files. + + .. versionchanged:: 0.6 + The ``ssl_context`` parameter was added. + + .. versionchanged:: 0.5 + The ``static_files`` and ``passthrough_errors`` parameters were + added. + """ + if not isinstance(port, int): + raise TypeError("port must be an integer") + + if static_files: + from .middleware.shared_data import SharedDataMiddleware + + application = SharedDataMiddleware(application, static_files) + + if use_debugger: + from .debug import DebuggedApplication + + application = DebuggedApplication(application, evalex=use_evalex) + # Allow the specified hostname to use the debugger, in addition to + # localhost domains. + application.trusted_hosts.append(hostname) + + if not is_running_from_reloader(): + fd = None + else: + fd = int(os.environ["WERKZEUG_SERVER_FD"]) + + srv = make_server( + hostname, + port, + application, + threaded, + processes, + request_handler, + passthrough_errors, + ssl_context, + fd=fd, + ) + srv.socket.set_inheritable(True) + os.environ["WERKZEUG_SERVER_FD"] = str(srv.fileno()) + + if not is_running_from_reloader(): + srv.log_startup() + _log("info", _ansi_style("Press CTRL+C to quit", "yellow")) + + if use_reloader: + from ._reloader import run_with_reloader + + try: + run_with_reloader( + srv.serve_forever, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + interval=reloader_interval, + reloader_type=reloader_type, + ) + finally: + srv.server_close() + else: + srv.serve_forever() diff --git a/MLPY/Lib/site-packages/werkzeug/test.py b/MLPY/Lib/site-packages/werkzeug/test.py new file mode 100644 index 0000000000000000000000000000000000000000..38f69bfb9d7146ec3e87bf31e73afa2032e600ad --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/test.py @@ -0,0 +1,1464 @@ +from __future__ import annotations + +import dataclasses +import mimetypes +import sys +import typing as t +from collections import defaultdict +from datetime import datetime +from io import BytesIO +from itertools import chain +from random import random +from tempfile import TemporaryFile +from time import time +from urllib.parse import unquote +from urllib.parse import urlsplit +from urllib.parse import urlunsplit + +from ._internal import _get_environ +from ._internal import _wsgi_decoding_dance +from ._internal import _wsgi_encoding_dance +from .datastructures import Authorization +from .datastructures import CallbackDict +from .datastructures import CombinedMultiDict +from .datastructures import EnvironHeaders +from .datastructures import FileMultiDict +from .datastructures import Headers +from .datastructures import MultiDict +from .http import dump_cookie +from .http import dump_options_header +from .http import parse_cookie +from .http import parse_date +from .http import parse_options_header +from .sansio.multipart import Data +from .sansio.multipart import Epilogue +from .sansio.multipart import Field +from .sansio.multipart import File +from .sansio.multipart import MultipartEncoder +from .sansio.multipart import Preamble +from .urls import _urlencode +from .urls import iri_to_uri +from .utils import cached_property +from .utils import get_content_type +from .wrappers.request import Request +from .wrappers.response import Response +from .wsgi import ClosingIterator +from .wsgi import get_current_url + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +def stream_encode_multipart( + data: t.Mapping[str, t.Any], + use_tempfile: bool = True, + threshold: int = 1024 * 500, + boundary: str | None = None, +) -> tuple[t.IO[bytes], int, str]: + """Encode a dict of values (either strings or file descriptors or + :class:`FileStorage` objects.) into a multipart encoded string stored + in a file descriptor. + + .. versionchanged:: 3.0 + The ``charset`` parameter was removed. + """ + if boundary is None: + boundary = f"---------------WerkzeugFormPart_{time()}{random()}" + + stream: t.IO[bytes] = BytesIO() + total_length = 0 + on_disk = False + write_binary: t.Callable[[bytes], int] + + if use_tempfile: + + def write_binary(s: bytes) -> int: + nonlocal stream, total_length, on_disk + + if on_disk: + return stream.write(s) + else: + length = len(s) + + if length + total_length <= threshold: + stream.write(s) + else: + new_stream = t.cast(t.IO[bytes], TemporaryFile("wb+")) + new_stream.write(stream.getvalue()) # type: ignore + new_stream.write(s) + stream = new_stream + on_disk = True + + total_length += length + return length + + else: + write_binary = stream.write + + encoder = MultipartEncoder(boundary.encode()) + write_binary(encoder.send_event(Preamble(data=b""))) + for key, value in _iter_data(data): + reader = getattr(value, "read", None) + if reader is not None: + filename = getattr(value, "filename", getattr(value, "name", None)) + content_type = getattr(value, "content_type", None) + if content_type is None: + content_type = ( + filename + and mimetypes.guess_type(filename)[0] + or "application/octet-stream" + ) + headers = value.headers + headers.update([("Content-Type", content_type)]) + if filename is None: + write_binary(encoder.send_event(Field(name=key, headers=headers))) + else: + write_binary( + encoder.send_event( + File(name=key, filename=filename, headers=headers) + ) + ) + while True: + chunk = reader(16384) + + if not chunk: + write_binary(encoder.send_event(Data(data=chunk, more_data=False))) + break + + write_binary(encoder.send_event(Data(data=chunk, more_data=True))) + else: + if not isinstance(value, str): + value = str(value) + write_binary(encoder.send_event(Field(name=key, headers=Headers()))) + write_binary(encoder.send_event(Data(data=value.encode(), more_data=False))) + + write_binary(encoder.send_event(Epilogue(data=b""))) + + length = stream.tell() + stream.seek(0) + return stream, length, boundary + + +def encode_multipart( + values: t.Mapping[str, t.Any], boundary: str | None = None +) -> tuple[str, bytes]: + """Like `stream_encode_multipart` but returns a tuple in the form + (``boundary``, ``data``) where data is bytes. + + .. versionchanged:: 3.0 + The ``charset`` parameter was removed. + """ + stream, length, boundary = stream_encode_multipart( + values, use_tempfile=False, boundary=boundary + ) + return boundary, stream.read() + + +def _iter_data(data: t.Mapping[str, t.Any]) -> t.Iterator[tuple[str, t.Any]]: + """Iterate over a mapping that might have a list of values, yielding + all key, value pairs. Almost like iter_multi_items but only allows + lists, not tuples, of values so tuples can be used for files. + """ + if isinstance(data, MultiDict): + yield from data.items(multi=True) + else: + for key, value in data.items(): + if isinstance(value, list): + for v in value: + yield key, v + else: + yield key, value + + +_TAnyMultiDict = t.TypeVar("_TAnyMultiDict", bound="MultiDict[t.Any, t.Any]") + + +class EnvironBuilder: + """This class can be used to conveniently create a WSGI environment + for testing purposes. It can be used to quickly create WSGI environments + or request objects from arbitrary data. + + The signature of this class is also used in some other places as of + Werkzeug 0.5 (:func:`create_environ`, :meth:`Response.from_values`, + :meth:`Client.open`). Because of this most of the functionality is + available through the constructor alone. + + Files and regular form data can be manipulated independently of each + other with the :attr:`form` and :attr:`files` attributes, but are + passed with the same argument to the constructor: `data`. + + `data` can be any of these values: + + - a `str` or `bytes` object: The object is converted into an + :attr:`input_stream`, the :attr:`content_length` is set and you have to + provide a :attr:`content_type`. + - a `dict` or :class:`MultiDict`: The keys have to be strings. The values + have to be either any of the following objects, or a list of any of the + following objects: + + - a :class:`file`-like object: These are converted into + :class:`FileStorage` objects automatically. + - a `tuple`: The :meth:`~FileMultiDict.add_file` method is called + with the key and the unpacked `tuple` items as positional + arguments. + - a `str`: The string is set as form data for the associated key. + - a file-like object: The object content is loaded in memory and then + handled like a regular `str` or a `bytes`. + + :param path: the path of the request. In the WSGI environment this will + end up as `PATH_INFO`. If the `query_string` is not defined + and there is a question mark in the `path` everything after + it is used as query string. + :param base_url: the base URL is a URL that is used to extract the WSGI + URL scheme, host (server name + server port) and the + script root (`SCRIPT_NAME`). + :param query_string: an optional string or dict with URL parameters. + :param method: the HTTP method to use, defaults to `GET`. + :param input_stream: an optional input stream. Do not specify this and + `data`. As soon as an input stream is set you can't + modify :attr:`args` and :attr:`files` unless you + set the :attr:`input_stream` to `None` again. + :param content_type: The content type for the request. As of 0.5 you + don't have to provide this when specifying files + and form data via `data`. + :param content_length: The content length for the request. You don't + have to specify this when providing data via + `data`. + :param errors_stream: an optional error stream that is used for + `wsgi.errors`. Defaults to :data:`stderr`. + :param multithread: controls `wsgi.multithread`. Defaults to `False`. + :param multiprocess: controls `wsgi.multiprocess`. Defaults to `False`. + :param run_once: controls `wsgi.run_once`. Defaults to `False`. + :param headers: an optional list or :class:`Headers` object of headers. + :param data: a string or dict of form data or a file-object. + See explanation above. + :param json: An object to be serialized and assigned to ``data``. + Defaults the content type to ``"application/json"``. + Serialized with the function assigned to :attr:`json_dumps`. + :param environ_base: an optional dict of environment defaults. + :param environ_overrides: an optional dict of environment overrides. + :param auth: An authorization object to use for the + ``Authorization`` header value. A ``(username, password)`` tuple + is a shortcut for ``Basic`` authorization. + + .. versionchanged:: 3.0 + The ``charset`` parameter was removed. + + .. versionchanged:: 2.1 + ``CONTENT_TYPE`` and ``CONTENT_LENGTH`` are not duplicated as + header keys in the environ. + + .. versionchanged:: 2.0 + ``REQUEST_URI`` and ``RAW_URI`` is the full raw URI including + the query string, not only the path. + + .. versionchanged:: 2.0 + The default :attr:`request_class` is ``Request`` instead of + ``BaseRequest``. + + .. versionadded:: 2.0 + Added the ``auth`` parameter. + + .. versionadded:: 0.15 + The ``json`` param and :meth:`json_dumps` method. + + .. versionadded:: 0.15 + The environ has keys ``REQUEST_URI`` and ``RAW_URI`` containing + the path before percent-decoding. This is not part of the WSGI + PEP, but many WSGI servers include it. + + .. versionchanged:: 0.6 + ``path`` and ``base_url`` can now be unicode strings that are + encoded with :func:`iri_to_uri`. + """ + + #: the server protocol to use. defaults to HTTP/1.1 + server_protocol = "HTTP/1.1" + + #: the wsgi version to use. defaults to (1, 0) + wsgi_version = (1, 0) + + #: The default request class used by :meth:`get_request`. + request_class = Request + + import json + + #: The serialization function used when ``json`` is passed. + json_dumps = staticmethod(json.dumps) + del json + + _args: MultiDict[str, str] | None + _query_string: str | None + _input_stream: t.IO[bytes] | None + _form: MultiDict[str, str] | None + _files: FileMultiDict | None + + def __init__( + self, + path: str = "/", + base_url: str | None = None, + query_string: t.Mapping[str, str] | str | None = None, + method: str = "GET", + input_stream: t.IO[bytes] | None = None, + content_type: str | None = None, + content_length: int | None = None, + errors_stream: t.IO[str] | None = None, + multithread: bool = False, + multiprocess: bool = False, + run_once: bool = False, + headers: Headers | t.Iterable[tuple[str, str]] | None = None, + data: None | (t.IO[bytes] | str | bytes | t.Mapping[str, t.Any]) = None, + environ_base: t.Mapping[str, t.Any] | None = None, + environ_overrides: t.Mapping[str, t.Any] | None = None, + mimetype: str | None = None, + json: t.Mapping[str, t.Any] | None = None, + auth: Authorization | tuple[str, str] | None = None, + ) -> None: + if query_string is not None and "?" in path: + raise ValueError("Query string is defined in the path and as an argument") + request_uri = urlsplit(path) + if query_string is None and "?" in path: + query_string = request_uri.query + + self.path = iri_to_uri(request_uri.path) + self.request_uri = path + if base_url is not None: + base_url = iri_to_uri(base_url) + self.base_url = base_url # type: ignore + if isinstance(query_string, str): + self.query_string = query_string + else: + if query_string is None: + query_string = MultiDict() + elif not isinstance(query_string, MultiDict): + query_string = MultiDict(query_string) + self.args = query_string + self.method = method + if headers is None: + headers = Headers() + elif not isinstance(headers, Headers): + headers = Headers(headers) + self.headers = headers + if content_type is not None: + self.content_type = content_type + if errors_stream is None: + errors_stream = sys.stderr + self.errors_stream = errors_stream + self.multithread = multithread + self.multiprocess = multiprocess + self.run_once = run_once + self.environ_base = environ_base + self.environ_overrides = environ_overrides + self.input_stream = input_stream + self.content_length = content_length + self.closed = False + + if auth is not None: + if isinstance(auth, tuple): + auth = Authorization( + "basic", {"username": auth[0], "password": auth[1]} + ) + + self.headers.set("Authorization", auth.to_header()) + + if json is not None: + if data is not None: + raise TypeError("can't provide both json and data") + + data = self.json_dumps(json) + + if self.content_type is None: + self.content_type = "application/json" + + if data: + if input_stream is not None: + raise TypeError("can't provide input stream and data") + if hasattr(data, "read"): + data = data.read() + if isinstance(data, str): + data = data.encode() + if isinstance(data, bytes): + self.input_stream = BytesIO(data) + if self.content_length is None: + self.content_length = len(data) + else: + for key, value in _iter_data(data): + if isinstance(value, (tuple, dict)) or hasattr(value, "read"): + self._add_file_from_data(key, value) + else: + self.form.setlistdefault(key).append(value) + + if mimetype is not None: + self.mimetype = mimetype + + @classmethod + def from_environ(cls, environ: WSGIEnvironment, **kwargs: t.Any) -> EnvironBuilder: + """Turn an environ dict back into a builder. Any extra kwargs + override the args extracted from the environ. + + .. versionchanged:: 2.0 + Path and query values are passed through the WSGI decoding + dance to avoid double encoding. + + .. versionadded:: 0.15 + """ + headers = Headers(EnvironHeaders(environ)) + out = { + "path": _wsgi_decoding_dance(environ["PATH_INFO"]), + "base_url": cls._make_base_url( + environ["wsgi.url_scheme"], + headers.pop("Host"), + _wsgi_decoding_dance(environ["SCRIPT_NAME"]), + ), + "query_string": _wsgi_decoding_dance(environ["QUERY_STRING"]), + "method": environ["REQUEST_METHOD"], + "input_stream": environ["wsgi.input"], + "content_type": headers.pop("Content-Type", None), + "content_length": headers.pop("Content-Length", None), + "errors_stream": environ["wsgi.errors"], + "multithread": environ["wsgi.multithread"], + "multiprocess": environ["wsgi.multiprocess"], + "run_once": environ["wsgi.run_once"], + "headers": headers, + } + out.update(kwargs) + return cls(**out) + + def _add_file_from_data( + self, + key: str, + value: (t.IO[bytes] | tuple[t.IO[bytes], str] | tuple[t.IO[bytes], str, str]), + ) -> None: + """Called in the EnvironBuilder to add files from the data dict.""" + if isinstance(value, tuple): + self.files.add_file(key, *value) + else: + self.files.add_file(key, value) + + @staticmethod + def _make_base_url(scheme: str, host: str, script_root: str) -> str: + return urlunsplit((scheme, host, script_root, "", "")).rstrip("/") + "/" + + @property + def base_url(self) -> str: + """The base URL is used to extract the URL scheme, host name, + port, and root path. + """ + return self._make_base_url(self.url_scheme, self.host, self.script_root) + + @base_url.setter + def base_url(self, value: str | None) -> None: + if value is None: + scheme = "http" + netloc = "localhost" + script_root = "" + else: + scheme, netloc, script_root, qs, anchor = urlsplit(value) + if qs or anchor: + raise ValueError("base url must not contain a query string or fragment") + self.script_root = script_root.rstrip("/") + self.host = netloc + self.url_scheme = scheme + + @property + def content_type(self) -> str | None: + """The content type for the request. Reflected from and to + the :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection. + """ + ct = self.headers.get("Content-Type") + if ct is None and not self._input_stream: + if self._files: + return "multipart/form-data" + if self._form: + return "application/x-www-form-urlencoded" + return None + return ct + + @content_type.setter + def content_type(self, value: str | None) -> None: + if value is None: + self.headers.pop("Content-Type", None) + else: + self.headers["Content-Type"] = value + + @property + def mimetype(self) -> str | None: + """The mimetype (content type without charset etc.) + + .. versionadded:: 0.14 + """ + ct = self.content_type + return ct.split(";")[0].strip() if ct else None + + @mimetype.setter + def mimetype(self, value: str) -> None: + self.content_type = get_content_type(value, "utf-8") + + @property + def mimetype_params(self) -> t.Mapping[str, str]: + """The mimetype parameters as dict. For example if the + content type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.14 + """ + + def on_update(d: CallbackDict[str, str]) -> None: + self.headers["Content-Type"] = dump_options_header(self.mimetype, d) + + d = parse_options_header(self.headers.get("content-type", ""))[1] + return CallbackDict(d, on_update) + + @property + def content_length(self) -> int | None: + """The content length as integer. Reflected from and to the + :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection. + """ + return self.headers.get("Content-Length", type=int) + + @content_length.setter + def content_length(self, value: int | None) -> None: + if value is None: + self.headers.pop("Content-Length", None) + else: + self.headers["Content-Length"] = str(value) + + def _get_form(self, name: str, storage: type[_TAnyMultiDict]) -> _TAnyMultiDict: + """Common behavior for getting the :attr:`form` and + :attr:`files` properties. + + :param name: Name of the internal cached attribute. + :param storage: Storage class used for the data. + """ + if self.input_stream is not None: + raise AttributeError("an input stream is defined") + + rv = getattr(self, name) + + if rv is None: + rv = storage() + setattr(self, name, rv) + + return rv # type: ignore + + def _set_form(self, name: str, value: MultiDict[str, t.Any]) -> None: + """Common behavior for setting the :attr:`form` and + :attr:`files` properties. + + :param name: Name of the internal cached attribute. + :param value: Value to assign to the attribute. + """ + self._input_stream = None + setattr(self, name, value) + + @property + def form(self) -> MultiDict[str, str]: + """A :class:`MultiDict` of form values.""" + return self._get_form("_form", MultiDict) + + @form.setter + def form(self, value: MultiDict[str, str]) -> None: + self._set_form("_form", value) + + @property + def files(self) -> FileMultiDict: + """A :class:`FileMultiDict` of uploaded files. Use + :meth:`~FileMultiDict.add_file` to add new files. + """ + return self._get_form("_files", FileMultiDict) + + @files.setter + def files(self, value: FileMultiDict) -> None: + self._set_form("_files", value) + + @property + def input_stream(self) -> t.IO[bytes] | None: + """An optional input stream. This is mutually exclusive with + setting :attr:`form` and :attr:`files`, setting it will clear + those. Do not provide this if the method is not ``POST`` or + another method that has a body. + """ + return self._input_stream + + @input_stream.setter + def input_stream(self, value: t.IO[bytes] | None) -> None: + self._input_stream = value + self._form = None + self._files = None + + @property + def query_string(self) -> str: + """The query string. If you set this to a string + :attr:`args` will no longer be available. + """ + if self._query_string is None: + if self._args is not None: + return _urlencode(self._args) + return "" + return self._query_string + + @query_string.setter + def query_string(self, value: str | None) -> None: + self._query_string = value + self._args = None + + @property + def args(self) -> MultiDict[str, str]: + """The URL arguments as :class:`MultiDict`.""" + if self._query_string is not None: + raise AttributeError("a query string is defined") + if self._args is None: + self._args = MultiDict() + return self._args + + @args.setter + def args(self, value: MultiDict[str, str] | None) -> None: + self._query_string = None + self._args = value + + @property + def server_name(self) -> str: + """The server name (read-only, use :attr:`host` to set)""" + return self.host.split(":", 1)[0] + + @property + def server_port(self) -> int: + """The server port as integer (read-only, use :attr:`host` to set)""" + pieces = self.host.split(":", 1) + + if len(pieces) == 2: + try: + return int(pieces[1]) + except ValueError: + pass + + if self.url_scheme == "https": + return 443 + return 80 + + def __del__(self) -> None: + try: + self.close() + except Exception: + pass + + def close(self) -> None: + """Closes all files. If you put real :class:`file` objects into the + :attr:`files` dict you can call this method to automatically close + them all in one go. + """ + if self.closed: + return + try: + files = self.files.values() + except AttributeError: + files = () # type: ignore + for f in files: + try: + f.close() + except Exception: + pass + self.closed = True + + def get_environ(self) -> WSGIEnvironment: + """Return the built environ. + + .. versionchanged:: 0.15 + The content type and length headers are set based on + input stream detection. Previously this only set the WSGI + keys. + """ + input_stream = self.input_stream + content_length = self.content_length + + mimetype = self.mimetype + content_type = self.content_type + + if input_stream is not None: + start_pos = input_stream.tell() + input_stream.seek(0, 2) + end_pos = input_stream.tell() + input_stream.seek(start_pos) + content_length = end_pos - start_pos + elif mimetype == "multipart/form-data": + input_stream, content_length, boundary = stream_encode_multipart( + CombinedMultiDict([self.form, self.files]) + ) + content_type = f'{mimetype}; boundary="{boundary}"' + elif mimetype == "application/x-www-form-urlencoded": + form_encoded = _urlencode(self.form).encode("ascii") + content_length = len(form_encoded) + input_stream = BytesIO(form_encoded) + else: + input_stream = BytesIO() + + result: WSGIEnvironment = {} + if self.environ_base: + result.update(self.environ_base) + + def _path_encode(x: str) -> str: + return _wsgi_encoding_dance(unquote(x)) + + raw_uri = _wsgi_encoding_dance(self.request_uri) + result.update( + { + "REQUEST_METHOD": self.method, + "SCRIPT_NAME": _path_encode(self.script_root), + "PATH_INFO": _path_encode(self.path), + "QUERY_STRING": _wsgi_encoding_dance(self.query_string), + # Non-standard, added by mod_wsgi, uWSGI + "REQUEST_URI": raw_uri, + # Non-standard, added by gunicorn + "RAW_URI": raw_uri, + "SERVER_NAME": self.server_name, + "SERVER_PORT": str(self.server_port), + "HTTP_HOST": self.host, + "SERVER_PROTOCOL": self.server_protocol, + "wsgi.version": self.wsgi_version, + "wsgi.url_scheme": self.url_scheme, + "wsgi.input": input_stream, + "wsgi.errors": self.errors_stream, + "wsgi.multithread": self.multithread, + "wsgi.multiprocess": self.multiprocess, + "wsgi.run_once": self.run_once, + } + ) + + headers = self.headers.copy() + # Don't send these as headers, they're part of the environ. + headers.remove("Content-Type") + headers.remove("Content-Length") + + if content_type is not None: + result["CONTENT_TYPE"] = content_type + + if content_length is not None: + result["CONTENT_LENGTH"] = str(content_length) + + combined_headers = defaultdict(list) + + for key, value in headers.to_wsgi_list(): + combined_headers[f"HTTP_{key.upper().replace('-', '_')}"].append(value) + + for key, values in combined_headers.items(): + result[key] = ", ".join(values) + + if self.environ_overrides: + result.update(self.environ_overrides) + + return result + + def get_request(self, cls: type[Request] | None = None) -> Request: + """Returns a request with the data. If the request class is not + specified :attr:`request_class` is used. + + :param cls: The request wrapper to use. + """ + if cls is None: + cls = self.request_class + + return cls(self.get_environ()) + + +class ClientRedirectError(Exception): + """If a redirect loop is detected when using follow_redirects=True with + the :cls:`Client`, then this exception is raised. + """ + + +class Client: + """Simulate sending requests to a WSGI application without running a WSGI or HTTP + server. + + :param application: The WSGI application to make requests to. + :param response_wrapper: A :class:`.Response` class to wrap response data with. + Defaults to :class:`.TestResponse`. If it's not a subclass of ``TestResponse``, + one will be created. + :param use_cookies: Persist cookies from ``Set-Cookie`` response headers to the + ``Cookie`` header in subsequent requests. Domain and path matching is supported, + but other cookie parameters are ignored. + :param allow_subdomain_redirects: Allow requests to follow redirects to subdomains. + Enable this if the application handles subdomains and redirects between them. + + .. versionchanged:: 2.3 + Simplify cookie implementation, support domain and path matching. + + .. versionchanged:: 2.1 + All data is available as properties on the returned response object. The + response cannot be returned as a tuple. + + .. versionchanged:: 2.0 + ``response_wrapper`` is always a subclass of :class:``TestResponse``. + + .. versionchanged:: 0.5 + Added the ``use_cookies`` parameter. + """ + + def __init__( + self, + application: WSGIApplication, + response_wrapper: type[Response] | None = None, + use_cookies: bool = True, + allow_subdomain_redirects: bool = False, + ) -> None: + self.application = application + + if response_wrapper in {None, Response}: + response_wrapper = TestResponse + elif response_wrapper is not None and not issubclass( + response_wrapper, TestResponse + ): + response_wrapper = type( + "WrapperTestResponse", + (TestResponse, response_wrapper), + {}, + ) + + self.response_wrapper = t.cast(t.Type["TestResponse"], response_wrapper) + + if use_cookies: + self._cookies: dict[tuple[str, str, str], Cookie] | None = {} + else: + self._cookies = None + + self.allow_subdomain_redirects = allow_subdomain_redirects + + def get_cookie( + self, key: str, domain: str = "localhost", path: str = "/" + ) -> Cookie | None: + """Return a :class:`.Cookie` if it exists. Cookies are uniquely identified by + ``(domain, path, key)``. + + :param key: The decoded form of the key for the cookie. + :param domain: The domain the cookie was set for. + :param path: The path the cookie was set for. + + .. versionadded:: 2.3 + """ + if self._cookies is None: + raise TypeError( + "Cookies are disabled. Create a client with 'use_cookies=True'." + ) + + return self._cookies.get((domain, path, key)) + + def set_cookie( + self, + key: str, + value: str = "", + *, + domain: str = "localhost", + origin_only: bool = True, + path: str = "/", + **kwargs: t.Any, + ) -> None: + """Set a cookie to be sent in subsequent requests. + + This is a convenience to skip making a test request to a route that would set + the cookie. To test the cookie, make a test request to a route that uses the + cookie value. + + The client uses ``domain``, ``origin_only``, and ``path`` to determine which + cookies to send with a request. It does not use other cookie parameters that + browsers use, since they're not applicable in tests. + + :param key: The key part of the cookie. + :param value: The value part of the cookie. + :param domain: Send this cookie with requests that match this domain. If + ``origin_only`` is true, it must be an exact match, otherwise it may be a + suffix match. + :param origin_only: Whether the domain must be an exact match to the request. + :param path: Send this cookie with requests that match this path either exactly + or as a prefix. + :param kwargs: Passed to :func:`.dump_cookie`. + + .. versionchanged:: 3.0 + The parameter ``server_name`` is removed. The first parameter is + ``key``. Use the ``domain`` and ``origin_only`` parameters instead. + + .. versionchanged:: 2.3 + The ``origin_only`` parameter was added. + + .. versionchanged:: 2.3 + The ``domain`` parameter defaults to ``localhost``. + """ + if self._cookies is None: + raise TypeError( + "Cookies are disabled. Create a client with 'use_cookies=True'." + ) + + cookie = Cookie._from_response_header( + domain, "/", dump_cookie(key, value, domain=domain, path=path, **kwargs) + ) + cookie.origin_only = origin_only + + if cookie._should_delete: + self._cookies.pop(cookie._storage_key, None) + else: + self._cookies[cookie._storage_key] = cookie + + def delete_cookie( + self, + key: str, + *, + domain: str = "localhost", + path: str = "/", + ) -> None: + """Delete a cookie if it exists. Cookies are uniquely identified by + ``(domain, path, key)``. + + :param key: The decoded form of the key for the cookie. + :param domain: The domain the cookie was set for. + :param path: The path the cookie was set for. + + .. versionchanged:: 3.0 + The ``server_name`` parameter is removed. The first parameter is + ``key``. Use the ``domain`` parameter instead. + + .. versionchanged:: 3.0 + The ``secure``, ``httponly`` and ``samesite`` parameters are removed. + + .. versionchanged:: 2.3 + The ``domain`` parameter defaults to ``localhost``. + """ + if self._cookies is None: + raise TypeError( + "Cookies are disabled. Create a client with 'use_cookies=True'." + ) + + self._cookies.pop((domain, path, key), None) + + def _add_cookies_to_wsgi(self, environ: WSGIEnvironment) -> None: + """If cookies are enabled, set the ``Cookie`` header in the environ to the + cookies that are applicable to the request host and path. + + :meta private: + + .. versionadded:: 2.3 + """ + if self._cookies is None: + return + + url = urlsplit(get_current_url(environ)) + server_name = url.hostname or "localhost" + value = "; ".join( + c._to_request_header() + for c in self._cookies.values() + if c._matches_request(server_name, url.path) + ) + + if value: + environ["HTTP_COOKIE"] = value + else: + environ.pop("HTTP_COOKIE", None) + + def _update_cookies_from_response( + self, server_name: str, path: str, headers: list[str] + ) -> None: + """If cookies are enabled, update the stored cookies from any ``Set-Cookie`` + headers in the response. + + :meta private: + + .. versionadded:: 2.3 + """ + if self._cookies is None: + return + + for header in headers: + cookie = Cookie._from_response_header(server_name, path, header) + + if cookie._should_delete: + self._cookies.pop(cookie._storage_key, None) + else: + self._cookies[cookie._storage_key] = cookie + + def run_wsgi_app( + self, environ: WSGIEnvironment, buffered: bool = False + ) -> tuple[t.Iterable[bytes], str, Headers]: + """Runs the wrapped WSGI app with the given environment. + + :meta private: + """ + self._add_cookies_to_wsgi(environ) + rv = run_wsgi_app(self.application, environ, buffered=buffered) + url = urlsplit(get_current_url(environ)) + self._update_cookies_from_response( + url.hostname or "localhost", url.path, rv[2].getlist("Set-Cookie") + ) + return rv + + def resolve_redirect( + self, response: TestResponse, buffered: bool = False + ) -> TestResponse: + """Perform a new request to the location given by the redirect + response to the previous request. + + :meta private: + """ + scheme, netloc, path, qs, anchor = urlsplit(response.location) + builder = EnvironBuilder.from_environ( + response.request.environ, path=path, query_string=qs + ) + + to_name_parts = netloc.split(":", 1)[0].split(".") + from_name_parts = builder.server_name.split(".") + + if to_name_parts != [""]: + # The new location has a host, use it for the base URL. + builder.url_scheme = scheme + builder.host = netloc + else: + # A local redirect with autocorrect_location_header=False + # doesn't have a host, so use the request's host. + to_name_parts = from_name_parts + + # Explain why a redirect to a different server name won't be followed. + if to_name_parts != from_name_parts: + if to_name_parts[-len(from_name_parts) :] == from_name_parts: + if not self.allow_subdomain_redirects: + raise RuntimeError("Following subdomain redirects is not enabled.") + else: + raise RuntimeError("Following external redirects is not supported.") + + path_parts = path.split("/") + root_parts = builder.script_root.split("/") + + if path_parts[: len(root_parts)] == root_parts: + # Strip the script root from the path. + builder.path = path[len(builder.script_root) :] + else: + # The new location is not under the script root, so use the + # whole path and clear the previous root. + builder.path = path + builder.script_root = "" + + # Only 307 and 308 preserve all of the original request. + if response.status_code not in {307, 308}: + # HEAD is preserved, everything else becomes GET. + if builder.method != "HEAD": + builder.method = "GET" + + # Clear the body and the headers that describe it. + + if builder.input_stream is not None: + builder.input_stream.close() + builder.input_stream = None + + builder.content_type = None + builder.content_length = None + builder.headers.pop("Transfer-Encoding", None) + + return self.open(builder, buffered=buffered) + + def open( + self, + *args: t.Any, + buffered: bool = False, + follow_redirects: bool = False, + **kwargs: t.Any, + ) -> TestResponse: + """Generate an environ dict from the given arguments, make a + request to the application using it, and return the response. + + :param args: Passed to :class:`EnvironBuilder` to create the + environ for the request. If a single arg is passed, it can + be an existing :class:`EnvironBuilder` or an environ dict. + :param buffered: Convert the iterator returned by the app into + a list. If the iterator has a ``close()`` method, it is + called automatically. + :param follow_redirects: Make additional requests to follow HTTP + redirects until a non-redirect status is returned. + :attr:`TestResponse.history` lists the intermediate + responses. + + .. versionchanged:: 2.1 + Removed the ``as_tuple`` parameter. + + .. versionchanged:: 2.0 + The request input stream is closed when calling + ``response.close()``. Input streams for redirects are + automatically closed. + + .. versionchanged:: 0.5 + If a dict is provided as file in the dict for the ``data`` + parameter the content type has to be called ``content_type`` + instead of ``mimetype``. This change was made for + consistency with :class:`werkzeug.FileWrapper`. + + .. versionchanged:: 0.5 + Added the ``follow_redirects`` parameter. + """ + request: Request | None = None + + if not kwargs and len(args) == 1: + arg = args[0] + + if isinstance(arg, EnvironBuilder): + request = arg.get_request() + elif isinstance(arg, dict): + request = EnvironBuilder.from_environ(arg).get_request() + elif isinstance(arg, Request): + request = arg + + if request is None: + builder = EnvironBuilder(*args, **kwargs) + + try: + request = builder.get_request() + finally: + builder.close() + + response_parts = self.run_wsgi_app(request.environ, buffered=buffered) + response = self.response_wrapper(*response_parts, request=request) + + redirects = set() + history: list[TestResponse] = [] + + if not follow_redirects: + return response + + while response.status_code in { + 301, + 302, + 303, + 305, + 307, + 308, + }: + # Exhaust intermediate response bodies to ensure middleware + # that returns an iterator runs any cleanup code. + if not buffered: + response.make_sequence() + response.close() + + new_redirect_entry = (response.location, response.status_code) + + if new_redirect_entry in redirects: + raise ClientRedirectError( + f"Loop detected: A {response.status_code} redirect" + f" to {response.location} was already made." + ) + + redirects.add(new_redirect_entry) + response.history = tuple(history) + history.append(response) + response = self.resolve_redirect(response, buffered=buffered) + else: + # This is the final request after redirects. + response.history = tuple(history) + # Close the input stream when closing the response, in case + # the input is an open temporary file. + response.call_on_close(request.input_stream.close) + return response + + def get(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``GET``.""" + kw["method"] = "GET" + return self.open(*args, **kw) + + def post(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``POST``.""" + kw["method"] = "POST" + return self.open(*args, **kw) + + def put(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``PUT``.""" + kw["method"] = "PUT" + return self.open(*args, **kw) + + def delete(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``DELETE``.""" + kw["method"] = "DELETE" + return self.open(*args, **kw) + + def patch(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``PATCH``.""" + kw["method"] = "PATCH" + return self.open(*args, **kw) + + def options(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``OPTIONS``.""" + kw["method"] = "OPTIONS" + return self.open(*args, **kw) + + def head(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``HEAD``.""" + kw["method"] = "HEAD" + return self.open(*args, **kw) + + def trace(self, *args: t.Any, **kw: t.Any) -> TestResponse: + """Call :meth:`open` with ``method`` set to ``TRACE``.""" + kw["method"] = "TRACE" + return self.open(*args, **kw) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.application!r}>" + + +def create_environ(*args: t.Any, **kwargs: t.Any) -> WSGIEnvironment: + """Create a new WSGI environ dict based on the values passed. The first + parameter should be the path of the request which defaults to '/'. The + second one can either be an absolute path (in that case the host is + localhost:80) or a full path to the request with scheme, netloc port and + the path to the script. + + This accepts the same arguments as the :class:`EnvironBuilder` + constructor. + + .. versionchanged:: 0.5 + This function is now a thin wrapper over :class:`EnvironBuilder` which + was added in 0.5. The `headers`, `environ_base`, `environ_overrides` + and `charset` parameters were added. + """ + builder = EnvironBuilder(*args, **kwargs) + + try: + return builder.get_environ() + finally: + builder.close() + + +def run_wsgi_app( + app: WSGIApplication, environ: WSGIEnvironment, buffered: bool = False +) -> tuple[t.Iterable[bytes], str, Headers]: + """Return a tuple in the form (app_iter, status, headers) of the + application output. This works best if you pass it an application that + returns an iterator all the time. + + Sometimes applications may use the `write()` callable returned + by the `start_response` function. This tries to resolve such edge + cases automatically. But if you don't get the expected output you + should set `buffered` to `True` which enforces buffering. + + If passed an invalid WSGI application the behavior of this function is + undefined. Never pass non-conforming WSGI applications to this function. + + :param app: the application to execute. + :param buffered: set to `True` to enforce buffering. + :return: tuple in the form ``(app_iter, status, headers)`` + """ + # Copy environ to ensure any mutations by the app (ProxyFix, for + # example) don't affect subsequent requests (such as redirects). + environ = _get_environ(environ).copy() + status: str + response: tuple[str, list[tuple[str, str]]] | None = None + buffer: list[bytes] = [] + + def start_response(status, headers, exc_info=None): # type: ignore + nonlocal response + + if exc_info: + try: + raise exc_info[1].with_traceback(exc_info[2]) + finally: + exc_info = None + + response = (status, headers) + return buffer.append + + app_rv = app(environ, start_response) + close_func = getattr(app_rv, "close", None) + app_iter: t.Iterable[bytes] = iter(app_rv) + + # when buffering we emit the close call early and convert the + # application iterator into a regular list + if buffered: + try: + app_iter = list(app_iter) + finally: + if close_func is not None: + close_func() + + # otherwise we iterate the application iter until we have a response, chain + # the already received data with the already collected data and wrap it in + # a new `ClosingIterator` if we need to restore a `close` callable from the + # original return value. + else: + for item in app_iter: + buffer.append(item) + + if response is not None: + break + + if buffer: + app_iter = chain(buffer, app_iter) + + if close_func is not None and app_iter is not app_rv: + app_iter = ClosingIterator(app_iter, close_func) + + status, headers = response # type: ignore + return app_iter, status, Headers(headers) + + +class TestResponse(Response): + """:class:`~werkzeug.wrappers.Response` subclass that provides extra + information about requests made with the test :class:`Client`. + + Test client requests will always return an instance of this class. + If a custom response class is passed to the client, it is + subclassed along with this to support test information. + + If the test request included large files, or if the application is + serving a file, call :meth:`close` to close any open files and + prevent Python showing a ``ResourceWarning``. + + .. versionchanged:: 2.2 + Set the ``default_mimetype`` to None to prevent a mimetype being + assumed if missing. + + .. versionchanged:: 2.1 + Response instances cannot be treated as tuples. + + .. versionadded:: 2.0 + Test client methods always return instances of this class. + """ + + default_mimetype = None + # Don't assume a mimetype, instead use whatever the response provides + + request: Request + """A request object with the environ used to make the request that + resulted in this response. + """ + + history: tuple[TestResponse, ...] + """A list of intermediate responses. Populated when the test request + is made with ``follow_redirects`` enabled. + """ + + # Tell Pytest to ignore this, it's not a test class. + __test__ = False + + def __init__( + self, + response: t.Iterable[bytes], + status: str, + headers: Headers, + request: Request, + history: tuple[TestResponse] = (), # type: ignore + **kwargs: t.Any, + ) -> None: + super().__init__(response, status, headers, **kwargs) + self.request = request + self.history = history + self._compat_tuple = response, status, headers + + @cached_property + def text(self) -> str: + """The response data as text. A shortcut for + ``response.get_data(as_text=True)``. + + .. versionadded:: 2.1 + """ + return self.get_data(as_text=True) + + +@dataclasses.dataclass +class Cookie: + """A cookie key, value, and parameters. + + The class itself is not a public API. Its attributes are documented for inspection + with :meth:`.Client.get_cookie` only. + + .. versionadded:: 2.3 + """ + + key: str + """The cookie key, encoded as a client would see it.""" + + value: str + """The cookie key, encoded as a client would see it.""" + + decoded_key: str + """The cookie key, decoded as the application would set and see it.""" + + decoded_value: str + """The cookie value, decoded as the application would set and see it.""" + + expires: datetime | None + """The time at which the cookie is no longer valid.""" + + max_age: int | None + """The number of seconds from when the cookie was set at which it is + no longer valid. + """ + + domain: str + """The domain that the cookie was set for, or the request domain if not set.""" + + origin_only: bool + """Whether the cookie will be sent for exact domain matches only. This is ``True`` + if the ``Domain`` parameter was not present. + """ + + path: str + """The path that the cookie was set for.""" + + secure: bool | None + """The ``Secure`` parameter.""" + + http_only: bool | None + """The ``HttpOnly`` parameter.""" + + same_site: str | None + """The ``SameSite`` parameter.""" + + def _matches_request(self, server_name: str, path: str) -> bool: + return ( + server_name == self.domain + or ( + not self.origin_only + and server_name.endswith(self.domain) + and server_name[: -len(self.domain)].endswith(".") + ) + ) and ( + path == self.path + or ( + path.startswith(self.path) + and path[len(self.path) - self.path.endswith("/") :].startswith("/") + ) + ) + + def _to_request_header(self) -> str: + return f"{self.key}={self.value}" + + @classmethod + def _from_response_header(cls, server_name: str, path: str, header: str) -> te.Self: + header, _, parameters_str = header.partition(";") + key, _, value = header.partition("=") + decoded_key, decoded_value = next(parse_cookie(header).items()) + params = {} + + for item in parameters_str.split(";"): + k, sep, v = item.partition("=") + params[k.strip().lower()] = v.strip() if sep else None + + return cls( + key=key.strip(), + value=value.strip(), + decoded_key=decoded_key, + decoded_value=decoded_value, + expires=parse_date(params.get("expires")), + max_age=int(params["max-age"] or 0) if "max-age" in params else None, + domain=params.get("domain") or server_name, + origin_only="domain" not in params, + path=params.get("path") or path.rpartition("/")[0] or "/", + secure="secure" in params, + http_only="httponly" in params, + same_site=params.get("samesite"), + ) + + @property + def _storage_key(self) -> tuple[str, str, str]: + return self.domain, self.path, self.decoded_key + + @property + def _should_delete(self) -> bool: + return self.max_age == 0 or ( + self.expires is not None and self.expires.timestamp() == 0 + ) diff --git a/MLPY/Lib/site-packages/werkzeug/testapp.py b/MLPY/Lib/site-packages/werkzeug/testapp.py new file mode 100644 index 0000000000000000000000000000000000000000..cdf7fac1acb8266c011d842aec97d0ff2156d200 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/testapp.py @@ -0,0 +1,194 @@ +"""A small application that can be used to test a WSGI server and check +it for WSGI compliance. +""" + +from __future__ import annotations + +import importlib.metadata +import os +import sys +import typing as t +from textwrap import wrap + +from markupsafe import escape + +from .wrappers.request import Request +from .wrappers.response import Response + +TEMPLATE = """\ + + +WSGI Information + +
    +

    WSGI Information

    +

    + This page displays all available information about the WSGI server and + the underlying Python interpreter. +

    Python Interpreter

    + + + + + + +
    Python Version + %(python_version)s +
    Platform + %(platform)s [%(os)s] +
    API Version + %(api_version)s +
    Byteorder + %(byteorder)s +
    Werkzeug Version + %(werkzeug_version)s +
    +

    WSGI Environment

    + %(wsgi_env)s
    +

    Installed Eggs

    +

    + The following python packages were installed on the system as + Python eggs: +

      %(python_eggs)s
    +

    System Path

    +

    + The following paths are the current contents of the load path. The + following entries are looked up for Python packages. Note that not + all items in this path are folders. Gray and underlined items are + entries pointing to invalid resources or used by custom import hooks + such as the zip importer. +

    + Items with a bright background were expanded for display from a relative + path. If you encounter such paths in the output you might want to check + your setup as relative paths are usually problematic in multithreaded + environments. +

      %(sys_path)s
    +
    +""" + + +def iter_sys_path() -> t.Iterator[tuple[str, bool, bool]]: + if os.name == "posix": + + def strip(x: str) -> str: + prefix = os.path.expanduser("~") + if x.startswith(prefix): + x = f"~{x[len(prefix) :]}" + return x + + else: + + def strip(x: str) -> str: + return x + + cwd = os.path.abspath(os.getcwd()) + for item in sys.path: + path = os.path.join(cwd, item or os.path.curdir) + yield strip(os.path.normpath(path)), not os.path.isdir(path), path != item + + +@Request.application +def test_app(req: Request) -> Response: + """Simple test application that dumps the environment. You can use + it to check if Werkzeug is working properly: + + .. sourcecode:: pycon + + >>> from werkzeug.serving import run_simple + >>> from werkzeug.testapp import test_app + >>> run_simple('localhost', 3000, test_app) + * Running on http://localhost:3000/ + + The application displays important information from the WSGI environment, + the Python interpreter and the installed libraries. + """ + try: + import pkg_resources + except ImportError: + eggs: t.Iterable[t.Any] = () + else: + eggs = sorted( + pkg_resources.working_set, + key=lambda x: x.project_name.lower(), + ) + python_eggs = [] + for egg in eggs: + try: + version = egg.version + except (ValueError, AttributeError): + version = "unknown" + python_eggs.append( + f"
  • {escape(egg.project_name)} [{escape(version)}]" + ) + + wsgi_env = [] + sorted_environ = sorted(req.environ.items(), key=lambda x: repr(x[0]).lower()) + for key, value in sorted_environ: + value = "".join(wrap(str(escape(repr(value))))) + wsgi_env.append(f"{escape(key)}{value}") + + sys_path = [] + for item, virtual, expanded in iter_sys_path(): + css = [] + if virtual: + css.append("virtual") + if expanded: + css.append("exp") + class_str = f' class="{" ".join(css)}"' if css else "" + sys_path.append(f"{escape(item)}") + + context = { + "python_version": "
    ".join(escape(sys.version).splitlines()), + "platform": escape(sys.platform), + "os": escape(os.name), + "api_version": sys.api_version, + "byteorder": sys.byteorder, + "werkzeug_version": _get_werkzeug_version(), + "python_eggs": "\n".join(python_eggs), + "wsgi_env": "\n".join(wsgi_env), + "sys_path": "\n".join(sys_path), + } + return Response(TEMPLATE % context, mimetype="text/html") + + +_werkzeug_version = "" + + +def _get_werkzeug_version() -> str: + global _werkzeug_version + + if not _werkzeug_version: + _werkzeug_version = importlib.metadata.version("werkzeug") + + return _werkzeug_version + + +if __name__ == "__main__": + from .serving import run_simple + + run_simple("localhost", 5000, test_app, use_reloader=True) diff --git a/MLPY/Lib/site-packages/werkzeug/urls.py b/MLPY/Lib/site-packages/werkzeug/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..5bffe392801e287f086b0505786d60740e75fd03 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/urls.py @@ -0,0 +1,203 @@ +from __future__ import annotations + +import codecs +import re +import typing as t +import urllib.parse +from urllib.parse import quote +from urllib.parse import unquote +from urllib.parse import urlencode +from urllib.parse import urlsplit +from urllib.parse import urlunsplit + +from .datastructures import iter_multi_items + + +def _codec_error_url_quote(e: UnicodeError) -> tuple[str, int]: + """Used in :func:`uri_to_iri` after unquoting to re-quote any + invalid bytes. + """ + # the docs state that UnicodeError does have these attributes, + # but mypy isn't picking them up + out = quote(e.object[e.start : e.end], safe="") # type: ignore + return out, e.end # type: ignore + + +codecs.register_error("werkzeug.url_quote", _codec_error_url_quote) + + +def _make_unquote_part(name: str, chars: str) -> t.Callable[[str], str]: + """Create a function that unquotes all percent encoded characters except those + given. This allows working with unquoted characters if possible while not changing + the meaning of a given part of a URL. + """ + choices = "|".join(f"{ord(c):02X}" for c in sorted(chars)) + pattern = re.compile(f"((?:%(?:{choices}))+)", re.I) + + def _unquote_partial(value: str) -> str: + parts = iter(pattern.split(value)) + out = [] + + for part in parts: + out.append(unquote(part, "utf-8", "werkzeug.url_quote")) + out.append(next(parts, "")) + + return "".join(out) + + _unquote_partial.__name__ = f"_unquote_{name}" + return _unquote_partial + + +# characters that should remain quoted in URL parts +# based on https://url.spec.whatwg.org/#percent-encoded-bytes +# always keep all controls, space, and % quoted +_always_unsafe = bytes((*range(0x21), 0x25, 0x7F)).decode() +_unquote_fragment = _make_unquote_part("fragment", _always_unsafe) +_unquote_query = _make_unquote_part("query", _always_unsafe + "&=+#") +_unquote_path = _make_unquote_part("path", _always_unsafe + "/?#") +_unquote_user = _make_unquote_part("user", _always_unsafe + ":@/?#") + + +def uri_to_iri(uri: str) -> str: + """Convert a URI to an IRI. All valid UTF-8 characters are unquoted, + leaving all reserved and invalid characters quoted. If the URL has + a domain, it is decoded from Punycode. + + >>> uri_to_iri("http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF") + 'http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF' + + :param uri: The URI to convert. + + .. versionchanged:: 3.0 + Passing a tuple or bytes, and the ``charset`` and ``errors`` parameters, + are removed. + + .. versionchanged:: 2.3 + Which characters remain quoted is specific to each part of the URL. + + .. versionchanged:: 0.15 + All reserved and invalid characters remain quoted. Previously, + only some reserved characters were preserved, and invalid bytes + were replaced instead of left quoted. + + .. versionadded:: 0.6 + """ + parts = urlsplit(uri) + path = _unquote_path(parts.path) + query = _unquote_query(parts.query) + fragment = _unquote_fragment(parts.fragment) + + if parts.hostname: + netloc = _decode_idna(parts.hostname) + else: + netloc = "" + + if ":" in netloc: + netloc = f"[{netloc}]" + + if parts.port: + netloc = f"{netloc}:{parts.port}" + + if parts.username: + auth = _unquote_user(parts.username) + + if parts.password: + password = _unquote_user(parts.password) + auth = f"{auth}:{password}" + + netloc = f"{auth}@{netloc}" + + return urlunsplit((parts.scheme, netloc, path, query, fragment)) + + +def iri_to_uri(iri: str) -> str: + """Convert an IRI to a URI. All non-ASCII and unsafe characters are + quoted. If the URL has a domain, it is encoded to Punycode. + + >>> iri_to_uri('http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF') + 'http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF' + + :param iri: The IRI to convert. + + .. versionchanged:: 3.0 + Passing a tuple or bytes, the ``charset`` and ``errors`` parameters, + and the ``safe_conversion`` parameter, are removed. + + .. versionchanged:: 2.3 + Which characters remain unquoted is specific to each part of the URL. + + .. versionchanged:: 0.15 + All reserved characters remain unquoted. Previously, only some reserved + characters were left unquoted. + + .. versionchanged:: 0.9.6 + The ``safe_conversion`` parameter was added. + + .. versionadded:: 0.6 + """ + parts = urlsplit(iri) + # safe = https://url.spec.whatwg.org/#url-path-segment-string + # as well as percent for things that are already quoted + path = quote(parts.path, safe="%!$&'()*+,/:;=@") + query = quote(parts.query, safe="%!$&'()*+,/:;=?@") + fragment = quote(parts.fragment, safe="%!#$&'()*+,/:;=?@") + + if parts.hostname: + netloc = parts.hostname.encode("idna").decode("ascii") + else: + netloc = "" + + if ":" in netloc: + netloc = f"[{netloc}]" + + if parts.port: + netloc = f"{netloc}:{parts.port}" + + if parts.username: + auth = quote(parts.username, safe="%!$&'()*+,;=") + + if parts.password: + password = quote(parts.password, safe="%!$&'()*+,;=") + auth = f"{auth}:{password}" + + netloc = f"{auth}@{netloc}" + + return urlunsplit((parts.scheme, netloc, path, query, fragment)) + + +# Python < 3.12 +# itms-services was worked around in previous iri_to_uri implementations, but +# we can tell Python directly that it needs to preserve the //. +if "itms-services" not in urllib.parse.uses_netloc: + urllib.parse.uses_netloc.append("itms-services") + + +def _decode_idna(domain: str) -> str: + try: + data = domain.encode("ascii") + except UnicodeEncodeError: + # If the domain is not ASCII, it's decoded already. + return domain + + try: + # Try decoding in one shot. + return data.decode("idna") + except UnicodeDecodeError: + pass + + # Decode each part separately, leaving invalid parts as punycode. + parts = [] + + for part in data.split(b"."): + try: + parts.append(part.decode("idna")) + except UnicodeDecodeError: + parts.append(part.decode("ascii")) + + return ".".join(parts) + + +def _urlencode(query: t.Mapping[str, str] | t.Iterable[tuple[str, str]]) -> str: + items = [x for x in iter_multi_items(query) if x[1] is not None] + # safe = https://url.spec.whatwg.org/#percent-encoded-bytes + return urlencode(items, safe="!$'()*,/:;?@") diff --git a/MLPY/Lib/site-packages/werkzeug/user_agent.py b/MLPY/Lib/site-packages/werkzeug/user_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..17e5d3fdbf0560318981210c7c824fee10853d13 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/user_agent.py @@ -0,0 +1,47 @@ +from __future__ import annotations + + +class UserAgent: + """Represents a parsed user agent header value. + + The default implementation does no parsing, only the :attr:`string` + attribute is set. A subclass may parse the string to set the + common attributes or expose other information. Set + :attr:`werkzeug.wrappers.Request.user_agent_class` to use a + subclass. + + :param string: The header value to parse. + + .. versionadded:: 2.0 + This replaces the previous ``useragents`` module, but does not + provide a built-in parser. + """ + + platform: str | None = None + """The OS name, if it could be parsed from the string.""" + + browser: str | None = None + """The browser name, if it could be parsed from the string.""" + + version: str | None = None + """The browser version, if it could be parsed from the string.""" + + language: str | None = None + """The browser language, if it could be parsed from the string.""" + + def __init__(self, string: str) -> None: + self.string: str = string + """The original header value.""" + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.browser}/{self.version}>" + + def __str__(self) -> str: + return self.string + + def __bool__(self) -> bool: + return bool(self.browser) + + def to_header(self) -> str: + """Convert to a header value.""" + return self.string diff --git a/MLPY/Lib/site-packages/werkzeug/utils.py b/MLPY/Lib/site-packages/werkzeug/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..59b97b732daaaf249214cf29449593cc9b60e4ea --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/utils.py @@ -0,0 +1,691 @@ +from __future__ import annotations + +import io +import mimetypes +import os +import pkgutil +import re +import sys +import typing as t +import unicodedata +from datetime import datetime +from time import time +from urllib.parse import quote +from zlib import adler32 + +from markupsafe import escape + +from ._internal import _DictAccessorProperty +from ._internal import _missing +from ._internal import _TAccessorValue +from .datastructures import Headers +from .exceptions import NotFound +from .exceptions import RequestedRangeNotSatisfiable +from .security import safe_join +from .wsgi import wrap_file + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + + from .wrappers.request import Request + from .wrappers.response import Response + +_T = t.TypeVar("_T") + +_entity_re = re.compile(r"&([^;]+);") +_filename_ascii_strip_re = re.compile(r"[^A-Za-z0-9_.-]") +_windows_device_files = { + "CON", + "PRN", + "AUX", + "NUL", + *(f"COM{i}" for i in range(10)), + *(f"LPT{i}" for i in range(10)), +} + + +class cached_property(property, t.Generic[_T]): + """A :func:`property` that is only evaluated once. Subsequent access + returns the cached value. Setting the property sets the cached + value. Deleting the property clears the cached value, accessing it + again will evaluate it again. + + .. code-block:: python + + class Example: + @cached_property + def value(self): + # calculate something important here + return 42 + + e = Example() + e.value # evaluates + e.value # uses cache + e.value = 16 # sets cache + del e.value # clears cache + + If the class defines ``__slots__``, it must add ``_cache_{name}`` as + a slot. Alternatively, it can add ``__dict__``, but that's usually + not desirable. + + .. versionchanged:: 2.1 + Works with ``__slots__``. + + .. versionchanged:: 2.0 + ``del obj.name`` clears the cached value. + """ + + def __init__( + self, + fget: t.Callable[[t.Any], _T], + name: str | None = None, + doc: str | None = None, + ) -> None: + super().__init__(fget, doc=doc) + self.__name__ = name or fget.__name__ + self.slot_name = f"_cache_{self.__name__}" + self.__module__ = fget.__module__ + + def __set__(self, obj: object, value: _T) -> None: + if hasattr(obj, "__dict__"): + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) + + def __get__(self, obj: object, type: type = None) -> _T: # type: ignore + if obj is None: + return self # type: ignore + + obj_dict = getattr(obj, "__dict__", None) + + if obj_dict is not None: + value: _T = obj_dict.get(self.__name__, _missing) + else: + value = getattr(obj, self.slot_name, _missing) # type: ignore[arg-type] + + if value is _missing: + value = self.fget(obj) # type: ignore + + if obj_dict is not None: + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) + + return value + + def __delete__(self, obj: object) -> None: + if hasattr(obj, "__dict__"): + del obj.__dict__[self.__name__] + else: + setattr(obj, self.slot_name, _missing) + + +class environ_property(_DictAccessorProperty[_TAccessorValue]): + """Maps request attributes to environment variables. This works not only + for the Werkzeug request object, but also any other class with an + environ attribute: + + >>> class Test(object): + ... environ = {'key': 'value'} + ... test = environ_property('key') + >>> var = Test() + >>> var.test + 'value' + + If you pass it a second value it's used as default if the key does not + exist, the third one can be a converter that takes a value and converts + it. If it raises :exc:`ValueError` or :exc:`TypeError` the default value + is used. If no default value is provided `None` is used. + + Per default the property is read only. You have to explicitly enable it + by passing ``read_only=False`` to the constructor. + """ + + read_only = True + + def lookup(self, obj: Request) -> WSGIEnvironment: + return obj.environ + + +class header_property(_DictAccessorProperty[_TAccessorValue]): + """Like `environ_property` but for headers.""" + + def lookup(self, obj: Request | Response) -> Headers: + return obj.headers + + +# https://cgit.freedesktop.org/xdg/shared-mime-info/tree/freedesktop.org.xml.in +# https://www.iana.org/assignments/media-types/media-types.xhtml +# Types listed in the XDG mime info that have a charset in the IANA registration. +_charset_mimetypes = { + "application/ecmascript", + "application/javascript", + "application/sql", + "application/xml", + "application/xml-dtd", + "application/xml-external-parsed-entity", +} + + +def get_content_type(mimetype: str, charset: str) -> str: + """Returns the full content type string with charset for a mimetype. + + If the mimetype represents text, the charset parameter will be + appended, otherwise the mimetype is returned unchanged. + + :param mimetype: The mimetype to be used as content type. + :param charset: The charset to be appended for text mimetypes. + :return: The content type. + + .. versionchanged:: 0.15 + Any type that ends with ``+xml`` gets a charset, not just those + that start with ``application/``. Known text types such as + ``application/javascript`` are also given charsets. + """ + if ( + mimetype.startswith("text/") + or mimetype in _charset_mimetypes + or mimetype.endswith("+xml") + ): + mimetype += f"; charset={charset}" + + return mimetype + + +def secure_filename(filename: str) -> str: + r"""Pass it a filename and it will return a secure version of it. This + filename can then safely be stored on a regular file system and passed + to :func:`os.path.join`. The filename returned is an ASCII only string + for maximum portability. + + On windows systems the function also makes sure that the file is not + named after one of the special device files. + + >>> secure_filename("My cool movie.mov") + 'My_cool_movie.mov' + >>> secure_filename("../../../etc/passwd") + 'etc_passwd' + >>> secure_filename('i contain cool \xfcml\xe4uts.txt') + 'i_contain_cool_umlauts.txt' + + The function might return an empty filename. It's your responsibility + to ensure that the filename is unique and that you abort or + generate a random filename if the function returned an empty one. + + .. versionadded:: 0.5 + + :param filename: the filename to secure + """ + filename = unicodedata.normalize("NFKD", filename) + filename = filename.encode("ascii", "ignore").decode("ascii") + + for sep in os.sep, os.path.altsep: + if sep: + filename = filename.replace(sep, " ") + filename = str(_filename_ascii_strip_re.sub("", "_".join(filename.split()))).strip( + "._" + ) + + # on nt a couple of special files are present in each folder. We + # have to ensure that the target file is not such a filename. In + # this case we prepend an underline + if ( + os.name == "nt" + and filename + and filename.split(".")[0].upper() in _windows_device_files + ): + filename = f"_{filename}" + + return filename + + +def redirect( + location: str, code: int = 302, Response: type[Response] | None = None +) -> Response: + """Returns a response object (a WSGI application) that, if called, + redirects the client to the target location. Supported codes are + 301, 302, 303, 305, 307, and 308. 300 is not supported because + it's not a real redirect and 304 because it's the answer for a + request with a request with defined If-Modified-Since headers. + + .. versionadded:: 0.6 + The location can now be a unicode string that is encoded using + the :func:`iri_to_uri` function. + + .. versionadded:: 0.10 + The class used for the Response object can now be passed in. + + :param location: the location the response should redirect to. + :param code: the redirect status code. defaults to 302. + :param class Response: a Response class to use when instantiating a + response. The default is :class:`werkzeug.wrappers.Response` if + unspecified. + """ + if Response is None: + from .wrappers import Response + + html_location = escape(location) + response = Response( # type: ignore[misc] + "\n" + "\n" + "Redirecting...\n" + "

    Redirecting...

    \n" + "

    You should be redirected automatically to the target URL: " + f'{html_location}. If not, click the link.\n', + code, + mimetype="text/html", + ) + response.headers["Location"] = location + return response + + +def append_slash_redirect(environ: WSGIEnvironment, code: int = 308) -> Response: + """Redirect to the current URL with a slash appended. + + If the current URL is ``/user/42``, the redirect URL will be + ``42/``. When joined to the current URL during response + processing or by the browser, this will produce ``/user/42/``. + + The behavior is undefined if the path ends with a slash already. If + called unconditionally on a URL, it may produce a redirect loop. + + :param environ: Use the path and query from this WSGI environment + to produce the redirect URL. + :param code: the status code for the redirect. + + .. versionchanged:: 2.1 + Produce a relative URL that only modifies the last segment. + Relevant when the current path has multiple segments. + + .. versionchanged:: 2.1 + The default status code is 308 instead of 301. This preserves + the request method and body. + """ + tail = environ["PATH_INFO"].rpartition("/")[2] + + if not tail: + new_path = "./" + else: + new_path = f"{tail}/" + + query_string = environ.get("QUERY_STRING") + + if query_string: + new_path = f"{new_path}?{query_string}" + + return redirect(new_path, code) + + +def send_file( + path_or_file: os.PathLike[str] | str | t.IO[bytes], + environ: WSGIEnvironment, + mimetype: str | None = None, + as_attachment: bool = False, + download_name: str | None = None, + conditional: bool = True, + etag: bool | str = True, + last_modified: datetime | int | float | None = None, + max_age: None | (int | t.Callable[[str | None], int | None]) = None, + use_x_sendfile: bool = False, + response_class: type[Response] | None = None, + _root_path: os.PathLike[str] | str | None = None, +) -> Response: + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. Use :func:`send_from_directory` to safely serve user-provided paths. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, ``use_x_sendfile=True`` + will tell the server to send the given path, which is much more + efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param environ: The WSGI environ for the current request. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + :param use_x_sendfile: Set the ``X-Sendfile`` header to let the + server to efficiently send the file. Requires support from the + HTTP server. Requires passing a file path. + :param response_class: Build the response using this class. Defaults + to :class:`~werkzeug.wrappers.Response`. + :param _root_path: Do not use. For internal use only. Use + :func:`send_from_directory` to safely send files under a path. + + .. versionchanged:: 2.0.2 + ``send_file`` only sets a detected ``Content-Encoding`` if + ``as_attachment`` is disabled. + + .. versionadded:: 2.0 + Adapted from Flask's implementation. + + .. versionchanged:: 2.0 + ``download_name`` replaces Flask's ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces Flask's ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces Flask's ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + If an encoding is returned when guessing ``mimetype`` from + ``download_name``, set the ``Content-Encoding`` header. + """ + if response_class is None: + from .wrappers import Response + + response_class = Response + + path: str | None = None + file: t.IO[bytes] | None = None + size: int | None = None + mtime: float | None = None + headers = Headers() + + if isinstance(path_or_file, (os.PathLike, str)) or hasattr( + path_or_file, "__fspath__" + ): + path_or_file = t.cast("t.Union[os.PathLike[str], str]", path_or_file) + + # Flask will pass app.root_path, allowing its send_file wrapper + # to not have to deal with paths. + if _root_path is not None: + path = os.path.join(_root_path, path_or_file) + else: + path = os.path.abspath(path_or_file) + + stat = os.stat(path) + size = stat.st_size + mtime = stat.st_mtime + else: + file = path_or_file + + if download_name is None and path is not None: + download_name = os.path.basename(path) + + if mimetype is None: + if download_name is None: + raise TypeError( + "Unable to detect the MIME type because a file name is" + " not available. Either set 'download_name', pass a" + " path instead of a file, or set 'mimetype'." + ) + + mimetype, encoding = mimetypes.guess_type(download_name) + + if mimetype is None: + mimetype = "application/octet-stream" + + # Don't send encoding for attachments, it causes browsers to + # save decompress tar.gz files. + if encoding is not None and not as_attachment: + headers.set("Content-Encoding", encoding) + + if download_name is not None: + try: + download_name.encode("ascii") + except UnicodeEncodeError: + simple = unicodedata.normalize("NFKD", download_name) + simple = simple.encode("ascii", "ignore").decode("ascii") + # safe = RFC 5987 attr-char + quoted = quote(download_name, safe="!#$&+-.^_`|~") + names = {"filename": simple, "filename*": f"UTF-8''{quoted}"} + else: + names = {"filename": download_name} + + value = "attachment" if as_attachment else "inline" + headers.set("Content-Disposition", value, **names) + elif as_attachment: + raise TypeError( + "No name provided for attachment. Either set" + " 'download_name' or pass a path instead of a file." + ) + + if use_x_sendfile and path is not None: + headers["X-Sendfile"] = path + data = None + else: + if file is None: + file = open(path, "rb") # type: ignore + elif isinstance(file, io.BytesIO): + size = file.getbuffer().nbytes + elif isinstance(file, io.TextIOBase): + raise ValueError("Files must be opened in binary mode or use BytesIO.") + + data = wrap_file(environ, file) + + rv = response_class( + data, mimetype=mimetype, headers=headers, direct_passthrough=True + ) + + if size is not None: + rv.content_length = size + + if last_modified is not None: + rv.last_modified = last_modified # type: ignore + elif mtime is not None: + rv.last_modified = mtime # type: ignore + + rv.cache_control.no_cache = True + + # Flask will pass app.get_send_file_max_age, allowing its send_file + # wrapper to not have to deal with paths. + if callable(max_age): + max_age = max_age(path) + + if max_age is not None: + if max_age > 0: + rv.cache_control.no_cache = None + rv.cache_control.public = True + + rv.cache_control.max_age = max_age + rv.expires = int(time() + max_age) # type: ignore + + if isinstance(etag, str): + rv.set_etag(etag) + elif etag and path is not None: + check = adler32(path.encode()) & 0xFFFFFFFF + rv.set_etag(f"{mtime}-{size}-{check}") + + if conditional: + try: + rv = rv.make_conditional(environ, accept_ranges=True, complete_length=size) + except RequestedRangeNotSatisfiable: + if file is not None: + file.close() + + raise + + # Some x-sendfile implementations incorrectly ignore the 304 + # status code and send the file anyway. + if rv.status_code == 304: + rv.headers.pop("x-sendfile", None) + + return rv + + +def send_from_directory( + directory: os.PathLike[str] | str, + path: os.PathLike[str] | str, + environ: WSGIEnvironment, + **kwargs: t.Any, +) -> Response: + """Send a file from within a directory using :func:`send_file`. + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + returns a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under. This *must not* + be a value provided by the client, otherwise it becomes insecure. + :param path: The path to the file to send, relative to ``directory``. This is the + part of the path provided by the client, which is checked for security. + :param environ: The WSGI environ for the current request. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionadded:: 2.0 + Adapted from Flask's implementation. + """ + path_str = safe_join(os.fspath(directory), os.fspath(path)) + + if path_str is None: + raise NotFound() + + # Flask will pass app.root_path, allowing its send_from_directory + # wrapper to not have to deal with paths. + if "_root_path" in kwargs: + path_str = os.path.join(kwargs["_root_path"], path_str) + + if not os.path.isfile(path_str): + raise NotFound() + + return send_file(path_str, environ, **kwargs) + + +def import_string(import_name: str, silent: bool = False) -> t.Any: + """Imports an object based on a string. This is useful if you want to + use import paths as endpoints or something similar. An import path can + be specified either in dotted notation (``xml.sax.saxutils.escape``) + or with a colon as object delimiter (``xml.sax.saxutils:escape``). + + If `silent` is True the return value will be `None` if the import fails. + + :param import_name: the dotted name for the object to import. + :param silent: if set to `True` import errors are ignored and + `None` is returned instead. + :return: imported object + """ + import_name = import_name.replace(":", ".") + try: + try: + __import__(import_name) + except ImportError: + if "." not in import_name: + raise + else: + return sys.modules[import_name] + + module_name, obj_name = import_name.rsplit(".", 1) + module = __import__(module_name, globals(), locals(), [obj_name]) + try: + return getattr(module, obj_name) + except AttributeError as e: + raise ImportError(e) from None + + except ImportError as e: + if not silent: + raise ImportStringError(import_name, e).with_traceback( + sys.exc_info()[2] + ) from None + + return None + + +def find_modules( + import_path: str, include_packages: bool = False, recursive: bool = False +) -> t.Iterator[str]: + """Finds all the modules below a package. This can be useful to + automatically import all views / controllers so that their metaclasses / + function decorators have a chance to register themselves on the + application. + + Packages are not returned unless `include_packages` is `True`. This can + also recursively list modules but in that case it will import all the + packages to get the correct load path of that module. + + :param import_path: the dotted name for the package to find child modules. + :param include_packages: set to `True` if packages should be returned, too. + :param recursive: set to `True` if recursion should happen. + :return: generator + """ + module = import_string(import_path) + path = getattr(module, "__path__", None) + if path is None: + raise ValueError(f"{import_path!r} is not a package") + basename = f"{module.__name__}." + for _importer, modname, ispkg in pkgutil.iter_modules(path): + modname = basename + modname + if ispkg: + if include_packages: + yield modname + if recursive: + yield from find_modules(modname, include_packages, True) + else: + yield modname + + +class ImportStringError(ImportError): + """Provides information about a failed :func:`import_string` attempt.""" + + #: String in dotted notation that failed to be imported. + import_name: str + #: Wrapped exception. + exception: BaseException + + def __init__(self, import_name: str, exception: BaseException) -> None: + self.import_name = import_name + self.exception = exception + msg = import_name + name = "" + tracked = [] + for part in import_name.replace(":", ".").split("."): + name = f"{name}.{part}" if name else part + imported = import_string(name, silent=True) + if imported: + tracked.append((name, getattr(imported, "__file__", None))) + else: + track = [f"- {n!r} found in {i!r}." for n, i in tracked] + track.append(f"- {name!r} not found.") + track_str = "\n".join(track) + msg = ( + f"import_string() failed for {import_name!r}. Possible reasons" + f" are:\n\n" + "- missing __init__.py in a package;\n" + "- package or module path not included in sys.path;\n" + "- duplicated package or module name taking precedence in" + " sys.path;\n" + "- missing module, class, function or variable;\n\n" + f"Debugged import:\n\n{track_str}\n\n" + f"Original exception:\n\n{type(exception).__name__}: {exception}" + ) + break + + super().__init__(msg) + + def __repr__(self) -> str: + return f"<{type(self).__name__}({self.import_name!r}, {self.exception!r})>" diff --git a/MLPY/Lib/site-packages/werkzeug/wrappers/__init__.py b/MLPY/Lib/site-packages/werkzeug/wrappers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b36f228f2cef05a53bff1e07f241a6bd60576fac --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/wrappers/__init__.py @@ -0,0 +1,3 @@ +from .request import Request as Request +from .response import Response as Response +from .response import ResponseStream as ResponseStream diff --git a/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d93fca92a4a8a5b3d18d7068a9a8dc3fe1f8bca7 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/request.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/request.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09c403c3a5c0b7a8b92aa31e56f2c96aca9ad22c Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/request.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/response.cpython-39.pyc b/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/response.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..073a3514161c6eef4b325482f44eed5d8546fb87 Binary files /dev/null and b/MLPY/Lib/site-packages/werkzeug/wrappers/__pycache__/response.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/werkzeug/wrappers/request.py b/MLPY/Lib/site-packages/werkzeug/wrappers/request.py new file mode 100644 index 0000000000000000000000000000000000000000..38053c2105c7bbf1645f7eefe8eecbc031e8a78c --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/wrappers/request.py @@ -0,0 +1,647 @@ +from __future__ import annotations + +import collections.abc as cabc +import functools +import json +import typing as t +from io import BytesIO + +from .._internal import _wsgi_decoding_dance +from ..datastructures import CombinedMultiDict +from ..datastructures import EnvironHeaders +from ..datastructures import FileStorage +from ..datastructures import ImmutableMultiDict +from ..datastructures import iter_multi_items +from ..datastructures import MultiDict +from ..exceptions import BadRequest +from ..exceptions import UnsupportedMediaType +from ..formparser import default_stream_factory +from ..formparser import FormDataParser +from ..sansio.request import Request as _SansIORequest +from ..utils import cached_property +from ..utils import environ_property +from ..wsgi import _get_server +from ..wsgi import get_input_stream + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class Request(_SansIORequest): + """Represents an incoming WSGI HTTP request, with headers and body + taken from the WSGI environment. Has properties and methods for + using the functionality defined by various HTTP specs. The data in + requests object is read-only. + + Text data is assumed to use UTF-8 encoding, which should be true for + the vast majority of modern clients. Using an encoding set by the + client is unsafe in Python due to extra encodings it provides, such + as ``zip``. To change the assumed encoding, subclass and replace + :attr:`charset`. + + :param environ: The WSGI environ is generated by the WSGI server and + contains information about the server configuration and client + request. + :param populate_request: Add this request object to the WSGI environ + as ``environ['werkzeug.request']``. Can be useful when + debugging. + :param shallow: Makes reading from :attr:`stream` (and any method + that would read from it) raise a :exc:`RuntimeError`. Useful to + prevent consuming the form data in middleware, which would make + it unavailable to the final application. + + .. versionchanged:: 3.0 + The ``charset``, ``url_charset``, and ``encoding_errors`` parameters + were removed. + + .. versionchanged:: 2.1 + Old ``BaseRequest`` and mixin classes were removed. + + .. versionchanged:: 2.1 + Remove the ``disable_data_descriptor`` attribute. + + .. versionchanged:: 2.0 + Combine ``BaseRequest`` and mixins into a single ``Request`` + class. + + .. versionchanged:: 0.5 + Read-only mode is enforced with immutable classes for all data. + """ + + #: the maximum content length. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: parsing fails because more than the specified value is transmitted + #: a :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: .. versionadded:: 0.5 + max_content_length: int | None = None + + #: the maximum form field size. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: data in memory for post data is longer than the specified value a + #: :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: .. versionadded:: 0.5 + max_form_memory_size: int | None = None + + #: The maximum number of multipart parts to parse, passed to + #: :attr:`form_data_parser_class`. Parsing form data with more than this + #: many parts will raise :exc:`~.RequestEntityTooLarge`. + #: + #: .. versionadded:: 2.2.3 + max_form_parts = 1000 + + #: The form data parser that should be used. Can be replaced to customize + #: the form date parsing. + form_data_parser_class: type[FormDataParser] = FormDataParser + + #: The WSGI environment containing HTTP headers and information from + #: the WSGI server. + environ: WSGIEnvironment + + #: Set when creating the request object. If ``True``, reading from + #: the request body will cause a ``RuntimeException``. Useful to + #: prevent modifying the stream from middleware. + shallow: bool + + def __init__( + self, + environ: WSGIEnvironment, + populate_request: bool = True, + shallow: bool = False, + ) -> None: + super().__init__( + method=environ.get("REQUEST_METHOD", "GET"), + scheme=environ.get("wsgi.url_scheme", "http"), + server=_get_server(environ), + root_path=_wsgi_decoding_dance(environ.get("SCRIPT_NAME") or ""), + path=_wsgi_decoding_dance(environ.get("PATH_INFO") or ""), + query_string=environ.get("QUERY_STRING", "").encode("latin1"), + headers=EnvironHeaders(environ), + remote_addr=environ.get("REMOTE_ADDR"), + ) + self.environ = environ + self.shallow = shallow + + if populate_request and not shallow: + self.environ["werkzeug.request"] = self + + @classmethod + def from_values(cls, *args: t.Any, **kwargs: t.Any) -> Request: + """Create a new request object based on the values provided. If + environ is given missing values are filled from there. This method is + useful for small scripts when you need to simulate a request from an URL. + Do not use this method for unittesting, there is a full featured client + object (:class:`Client`) that allows to create multipart requests, + support for cookies etc. + + This accepts the same options as the + :class:`~werkzeug.test.EnvironBuilder`. + + .. versionchanged:: 0.5 + This method now accepts the same arguments as + :class:`~werkzeug.test.EnvironBuilder`. Because of this the + `environ` parameter is now called `environ_overrides`. + + :return: request object + """ + from ..test import EnvironBuilder + + builder = EnvironBuilder(*args, **kwargs) + try: + return builder.get_request(cls) + finally: + builder.close() + + @classmethod + def application(cls, f: t.Callable[[Request], WSGIApplication]) -> WSGIApplication: + """Decorate a function as responder that accepts the request as + the last argument. This works like the :func:`responder` + decorator but the function is passed the request object as the + last argument and the request object will be closed + automatically:: + + @Request.application + def my_wsgi_app(request): + return Response('Hello World!') + + As of Werkzeug 0.14 HTTP exceptions are automatically caught and + converted to responses instead of failing. + + :param f: the WSGI callable to decorate + :return: a new WSGI callable + """ + #: return a callable that wraps the -2nd argument with the request + #: and calls the function with all the arguments up to that one and + #: the request. The return value is then called with the latest + #: two arguments. This makes it possible to use this decorator for + #: both standalone WSGI functions as well as bound methods and + #: partially applied functions. + from ..exceptions import HTTPException + + @functools.wraps(f) + def application(*args: t.Any) -> cabc.Iterable[bytes]: + request = cls(args[-2]) + with request: + try: + resp = f(*args[:-2] + (request,)) + except HTTPException as e: + resp = t.cast("WSGIApplication", e.get_response(args[-2])) + return resp(*args[-2:]) + + return t.cast("WSGIApplication", application) + + def _get_file_stream( + self, + total_content_length: int | None, + content_type: str | None, + filename: str | None = None, + content_length: int | None = None, + ) -> t.IO[bytes]: + """Called to get a stream for the file upload. + + This must provide a file-like class with `read()`, `readline()` + and `seek()` methods that is both writeable and readable. + + The default implementation returns a temporary file if the total + content length is higher than 500KB. Because many browsers do not + provide a content length for the files only the total content + length matters. + + :param total_content_length: the total content length of all the + data in the request combined. This value + is guaranteed to be there. + :param content_type: the mimetype of the uploaded file. + :param filename: the filename of the uploaded file. May be `None`. + :param content_length: the length of this file. This value is usually + not provided because webbrowsers do not provide + this value. + """ + return default_stream_factory( + total_content_length=total_content_length, + filename=filename, + content_type=content_type, + content_length=content_length, + ) + + @property + def want_form_data_parsed(self) -> bool: + """``True`` if the request method carries content. By default + this is true if a ``Content-Type`` is sent. + + .. versionadded:: 0.8 + """ + return bool(self.environ.get("CONTENT_TYPE")) + + def make_form_data_parser(self) -> FormDataParser: + """Creates the form data parser. Instantiates the + :attr:`form_data_parser_class` with some parameters. + + .. versionadded:: 0.8 + """ + return self.form_data_parser_class( + stream_factory=self._get_file_stream, + max_form_memory_size=self.max_form_memory_size, + max_content_length=self.max_content_length, + max_form_parts=self.max_form_parts, + cls=self.parameter_storage_class, + ) + + def _load_form_data(self) -> None: + """Method used internally to retrieve submitted data. After calling + this sets `form` and `files` on the request object to multi dicts + filled with the incoming form data. As a matter of fact the input + stream will be empty afterwards. You can also call this method to + force the parsing of the form data. + + .. versionadded:: 0.8 + """ + # abort early if we have already consumed the stream + if "form" in self.__dict__: + return + + if self.want_form_data_parsed: + parser = self.make_form_data_parser() + data = parser.parse( + self._get_stream_for_parsing(), + self.mimetype, + self.content_length, + self.mimetype_params, + ) + else: + data = ( + self.stream, + self.parameter_storage_class(), + self.parameter_storage_class(), + ) + + # inject the values into the instance dict so that we bypass + # our cached_property non-data descriptor. + d = self.__dict__ + d["stream"], d["form"], d["files"] = data + + def _get_stream_for_parsing(self) -> t.IO[bytes]: + """This is the same as accessing :attr:`stream` with the difference + that if it finds cached data from calling :meth:`get_data` first it + will create a new stream out of the cached data. + + .. versionadded:: 0.9.3 + """ + cached_data = getattr(self, "_cached_data", None) + if cached_data is not None: + return BytesIO(cached_data) + return self.stream + + def close(self) -> None: + """Closes associated resources of this request object. This + closes all file handles explicitly. You can also use the request + object in a with statement which will automatically close it. + + .. versionadded:: 0.9 + """ + files = self.__dict__.get("files") + for _key, value in iter_multi_items(files or ()): + value.close() + + def __enter__(self) -> Request: + return self + + def __exit__(self, exc_type, exc_value, tb) -> None: # type: ignore + self.close() + + @cached_property + def stream(self) -> t.IO[bytes]: + """The WSGI input stream, with safety checks. This stream can only be consumed + once. + + Use :meth:`get_data` to get the full data as bytes or text. The :attr:`data` + attribute will contain the full bytes only if they do not represent form data. + The :attr:`form` attribute will contain the parsed form data in that case. + + Unlike :attr:`input_stream`, this stream guards against infinite streams or + reading past :attr:`content_length` or :attr:`max_content_length`. + + If ``max_content_length`` is set, it can be enforced on streams if + ``wsgi.input_terminated`` is set. Otherwise, an empty stream is returned. + + If the limit is reached before the underlying stream is exhausted (such as a + file that is too large, or an infinite stream), the remaining contents of the + stream cannot be read safely. Depending on how the server handles this, clients + may show a "connection reset" failure instead of seeing the 413 response. + + .. versionchanged:: 2.3 + Check ``max_content_length`` preemptively and while reading. + + .. versionchanged:: 0.9 + The stream is always set (but may be consumed) even if form parsing was + accessed first. + """ + if self.shallow: + raise RuntimeError( + "This request was created with 'shallow=True', reading" + " from the input stream is disabled." + ) + + return get_input_stream( + self.environ, max_content_length=self.max_content_length + ) + + input_stream = environ_property[t.IO[bytes]]( + "wsgi.input", + doc="""The raw WSGI input stream, without any safety checks. + + This is dangerous to use. It does not guard against infinite streams or reading + past :attr:`content_length` or :attr:`max_content_length`. + + Use :attr:`stream` instead. + """, + ) + + @cached_property + def data(self) -> bytes: + """The raw data read from :attr:`stream`. Will be empty if the request + represents form data. + + To get the raw data even if it represents form data, use :meth:`get_data`. + """ + return self.get_data(parse_form_data=True) + + @t.overload + def get_data( # type: ignore + self, + cache: bool = True, + as_text: t.Literal[False] = False, + parse_form_data: bool = False, + ) -> bytes: ... + + @t.overload + def get_data( + self, + cache: bool = True, + as_text: t.Literal[True] = ..., + parse_form_data: bool = False, + ) -> str: ... + + def get_data( + self, cache: bool = True, as_text: bool = False, parse_form_data: bool = False + ) -> bytes | str: + """This reads the buffered incoming data from the client into one + bytes object. By default this is cached but that behavior can be + changed by setting `cache` to `False`. + + Usually it's a bad idea to call this method without checking the + content length first as a client could send dozens of megabytes or more + to cause memory problems on the server. + + Note that if the form data was already parsed this method will not + return anything as form data parsing does not cache the data like + this method does. To implicitly invoke form data parsing function + set `parse_form_data` to `True`. When this is done the return value + of this method will be an empty string if the form parser handles + the data. This generally is not necessary as if the whole data is + cached (which is the default) the form parser will used the cached + data to parse the form data. Please be generally aware of checking + the content length first in any case before calling this method + to avoid exhausting server memory. + + If `as_text` is set to `True` the return value will be a decoded + string. + + .. versionadded:: 0.9 + """ + rv = getattr(self, "_cached_data", None) + if rv is None: + if parse_form_data: + self._load_form_data() + rv = self.stream.read() + if cache: + self._cached_data = rv + if as_text: + rv = rv.decode(errors="replace") + return rv + + @cached_property + def form(self) -> ImmutableMultiDict[str, str]: + """The form parameters. By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + + Please keep in mind that file uploads will not end up here, but instead + in the :attr:`files` attribute. + + .. versionchanged:: 0.9 + + Previous to Werkzeug 0.9 this would only contain form data for POST + and PUT requests. + """ + self._load_form_data() + return self.form + + @cached_property + def values(self) -> CombinedMultiDict[str, str]: + """A :class:`werkzeug.datastructures.CombinedMultiDict` that + combines :attr:`args` and :attr:`form`. + + For GET requests, only ``args`` are present, not ``form``. + + .. versionchanged:: 2.0 + For GET requests, only ``args`` are present, not ``form``. + """ + sources = [self.args] + + if self.method != "GET": + # GET requests can have a body, and some caching proxies + # might not treat that differently than a normal GET + # request, allowing form data to "invisibly" affect the + # cache without indication in the query string / URL. + sources.append(self.form) + + args = [] + + for d in sources: + if not isinstance(d, MultiDict): + d = MultiDict(d) + + args.append(d) + + return CombinedMultiDict(args) + + @cached_property + def files(self) -> ImmutableMultiDict[str, FileStorage]: + """:class:`~werkzeug.datastructures.MultiDict` object containing + all uploaded files. Each key in :attr:`files` is the name from the + ````. Each value in :attr:`files` is a + Werkzeug :class:`~werkzeug.datastructures.FileStorage` object. + + It basically behaves like a standard file object you know from Python, + with the difference that it also has a + :meth:`~werkzeug.datastructures.FileStorage.save` function that can + store the file on the filesystem. + + Note that :attr:`files` will only contain data if the request method was + POST, PUT or PATCH and the ``

    `` that posted to the request had + ``enctype="multipart/form-data"``. It will be empty otherwise. + + See the :class:`~werkzeug.datastructures.MultiDict` / + :class:`~werkzeug.datastructures.FileStorage` documentation for + more details about the used data structure. + """ + self._load_form_data() + return self.files + + @property + def script_root(self) -> str: + """Alias for :attr:`self.root_path`. ``environ["SCRIPT_ROOT"]`` + without a trailing slash. + """ + return self.root_path + + @cached_property + def url_root(self) -> str: + """Alias for :attr:`root_url`. The URL with scheme, host, and + root path. For example, ``https://example.com/app/``. + """ + return self.root_url + + remote_user = environ_property[str]( + "REMOTE_USER", + doc="""If the server supports user authentication, and the + script is protected, this attribute contains the username the + user has authenticated as.""", + ) + is_multithread = environ_property[bool]( + "wsgi.multithread", + doc="""boolean that is `True` if the application is served by a + multithreaded WSGI server.""", + ) + is_multiprocess = environ_property[bool]( + "wsgi.multiprocess", + doc="""boolean that is `True` if the application is served by a + WSGI server that spawns multiple processes.""", + ) + is_run_once = environ_property[bool]( + "wsgi.run_once", + doc="""boolean that is `True` if the application will be + executed only once in a process lifetime. This is the case for + CGI for example, but it's not guaranteed that the execution only + happens one time.""", + ) + + # JSON + + #: A module or other object that has ``dumps`` and ``loads`` + #: functions that match the API of the built-in :mod:`json` module. + json_module = json + + @property + def json(self) -> t.Any | None: + """The parsed JSON data if :attr:`mimetype` indicates JSON + (:mimetype:`application/json`, see :attr:`is_json`). + + Calls :meth:`get_json` with default arguments. + + If the request content type is not ``application/json``, this + will raise a 415 Unsupported Media Type error. + + .. versionchanged:: 2.3 + Raise a 415 error instead of 400. + + .. versionchanged:: 2.1 + Raise a 400 error if the content type is incorrect. + """ + return self.get_json() + + # Cached values for ``(silent=False, silent=True)``. Initialized + # with sentinel values. + _cached_json: tuple[t.Any, t.Any] = (Ellipsis, Ellipsis) + + @t.overload + def get_json( + self, force: bool = ..., silent: t.Literal[False] = ..., cache: bool = ... + ) -> t.Any: ... + + @t.overload + def get_json( + self, force: bool = ..., silent: bool = ..., cache: bool = ... + ) -> t.Any | None: ... + + def get_json( + self, force: bool = False, silent: bool = False, cache: bool = True + ) -> t.Any | None: + """Parse :attr:`data` as JSON. + + If the mimetype does not indicate JSON + (:mimetype:`application/json`, see :attr:`is_json`), or parsing + fails, :meth:`on_json_loading_failed` is called and + its return value is used as the return value. By default this + raises a 415 Unsupported Media Type resp. + + :param force: Ignore the mimetype and always try to parse JSON. + :param silent: Silence mimetype and parsing errors, and + return ``None`` instead. + :param cache: Store the parsed JSON to return for subsequent + calls. + + .. versionchanged:: 2.3 + Raise a 415 error instead of 400. + + .. versionchanged:: 2.1 + Raise a 400 error if the content type is incorrect. + """ + if cache and self._cached_json[silent] is not Ellipsis: + return self._cached_json[silent] + + if not (force or self.is_json): + if not silent: + return self.on_json_loading_failed(None) + else: + return None + + data = self.get_data(cache=cache) + + try: + rv = self.json_module.loads(data) + except ValueError as e: + if silent: + rv = None + + if cache: + normal_rv, _ = self._cached_json + self._cached_json = (normal_rv, rv) + else: + rv = self.on_json_loading_failed(e) + + if cache: + _, silent_rv = self._cached_json + self._cached_json = (rv, silent_rv) + else: + if cache: + self._cached_json = (rv, rv) + + return rv + + def on_json_loading_failed(self, e: ValueError | None) -> t.Any: + """Called if :meth:`get_json` fails and isn't silenced. + + If this method returns a value, it is used as the return value + for :meth:`get_json`. The default implementation raises + :exc:`~werkzeug.exceptions.BadRequest`. + + :param e: If parsing failed, this is the exception. It will be + ``None`` if the content type wasn't ``application/json``. + + .. versionchanged:: 2.3 + Raise a 415 error instead of 400. + """ + if e is not None: + raise BadRequest(f"Failed to decode JSON object: {e}") + + raise UnsupportedMediaType( + "Did not attempt to load JSON data because the request" + " Content-Type was not 'application/json'." + ) diff --git a/MLPY/Lib/site-packages/werkzeug/wrappers/response.py b/MLPY/Lib/site-packages/werkzeug/wrappers/response.py new file mode 100644 index 0000000000000000000000000000000000000000..7f01287c7184ab3955085b56d11bab78b650ff48 --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/wrappers/response.py @@ -0,0 +1,831 @@ +from __future__ import annotations + +import json +import typing as t +from http import HTTPStatus +from urllib.parse import urljoin + +from .._internal import _get_environ +from ..datastructures import Headers +from ..http import generate_etag +from ..http import http_date +from ..http import is_resource_modified +from ..http import parse_etags +from ..http import parse_range_header +from ..http import remove_entity_headers +from ..sansio.response import Response as _SansIOResponse +from ..urls import iri_to_uri +from ..utils import cached_property +from ..wsgi import _RangeWrapper +from ..wsgi import ClosingIterator +from ..wsgi import get_current_url + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + from .request import Request + + +def _iter_encoded(iterable: t.Iterable[str | bytes]) -> t.Iterator[bytes]: + for item in iterable: + if isinstance(item, str): + yield item.encode() + else: + yield item + + +class Response(_SansIOResponse): + """Represents an outgoing WSGI HTTP response with body, status, and + headers. Has properties and methods for using the functionality + defined by various HTTP specs. + + The response body is flexible to support different use cases. The + simple form is passing bytes, or a string which will be encoded as + UTF-8. Passing an iterable of bytes or strings makes this a + streaming response. A generator is particularly useful for building + a CSV file in memory or using SSE (Server Sent Events). A file-like + object is also iterable, although the + :func:`~werkzeug.utils.send_file` helper should be used in that + case. + + The response object is itself a WSGI application callable. When + called (:meth:`__call__`) with ``environ`` and ``start_response``, + it will pass its status and headers to ``start_response`` then + return its body as an iterable. + + .. code-block:: python + + from werkzeug.wrappers.response import Response + + def index(): + return Response("Hello, World!") + + def application(environ, start_response): + path = environ.get("PATH_INFO") or "/" + + if path == "/": + response = index() + else: + response = Response("Not Found", status=404) + + return response(environ, start_response) + + :param response: The data for the body of the response. A string or + bytes, or tuple or list of strings or bytes, for a fixed-length + response, or any other iterable of strings or bytes for a + streaming response. Defaults to an empty body. + :param status: The status code for the response. Either an int, in + which case the default status message is added, or a string in + the form ``{code} {message}``, like ``404 Not Found``. Defaults + to 200. + :param headers: A :class:`~werkzeug.datastructures.Headers` object, + or a list of ``(key, value)`` tuples that will be converted to a + ``Headers`` object. + :param mimetype: The mime type (content type without charset or + other parameters) of the response. If the value starts with + ``text/`` (or matches some other special cases), the charset + will be added to create the ``content_type``. + :param content_type: The full content type of the response. + Overrides building the value from ``mimetype``. + :param direct_passthrough: Pass the response body directly through + as the WSGI iterable. This can be used when the body is a binary + file or other iterator of bytes, to skip some unnecessary + checks. Use :func:`~werkzeug.utils.send_file` instead of setting + this manually. + + .. versionchanged:: 2.1 + Old ``BaseResponse`` and mixin classes were removed. + + .. versionchanged:: 2.0 + Combine ``BaseResponse`` and mixins into a single ``Response`` + class. + + .. versionchanged:: 0.5 + The ``direct_passthrough`` parameter was added. + """ + + #: if set to `False` accessing properties on the response object will + #: not try to consume the response iterator and convert it into a list. + #: + #: .. versionadded:: 0.6.2 + #: + #: That attribute was previously called `implicit_seqence_conversion`. + #: (Notice the typo). If you did use this feature, you have to adapt + #: your code to the name change. + implicit_sequence_conversion = True + + #: If a redirect ``Location`` header is a relative URL, make it an + #: absolute URL, including scheme and domain. + #: + #: .. versionchanged:: 2.1 + #: This is disabled by default, so responses will send relative + #: redirects. + #: + #: .. versionadded:: 0.8 + autocorrect_location_header = False + + #: Should this response object automatically set the content-length + #: header if possible? This is true by default. + #: + #: .. versionadded:: 0.8 + automatically_set_content_length = True + + #: The response body to send as the WSGI iterable. A list of strings + #: or bytes represents a fixed-length response, any other iterable + #: is a streaming response. Strings are encoded to bytes as UTF-8. + #: + #: Do not set to a plain string or bytes, that will cause sending + #: the response to be very inefficient as it will iterate one byte + #: at a time. + response: t.Iterable[str] | t.Iterable[bytes] + + def __init__( + self, + response: t.Iterable[bytes] | bytes | t.Iterable[str] | str | None = None, + status: int | str | HTTPStatus | None = None, + headers: t.Mapping[str, str | t.Iterable[str]] + | t.Iterable[tuple[str, str]] + | None = None, + mimetype: str | None = None, + content_type: str | None = None, + direct_passthrough: bool = False, + ) -> None: + super().__init__( + status=status, + headers=headers, + mimetype=mimetype, + content_type=content_type, + ) + + #: Pass the response body directly through as the WSGI iterable. + #: This can be used when the body is a binary file or other + #: iterator of bytes, to skip some unnecessary checks. Use + #: :func:`~werkzeug.utils.send_file` instead of setting this + #: manually. + self.direct_passthrough = direct_passthrough + self._on_close: list[t.Callable[[], t.Any]] = [] + + # we set the response after the headers so that if a class changes + # the charset attribute, the data is set in the correct charset. + if response is None: + self.response = [] + elif isinstance(response, (str, bytes, bytearray)): + self.set_data(response) + else: + self.response = response + + def call_on_close(self, func: t.Callable[[], t.Any]) -> t.Callable[[], t.Any]: + """Adds a function to the internal list of functions that should + be called as part of closing down the response. Since 0.7 this + function also returns the function that was passed so that this + can be used as a decorator. + + .. versionadded:: 0.6 + """ + self._on_close.append(func) + return func + + def __repr__(self) -> str: + if self.is_sequence: + body_info = f"{sum(map(len, self.iter_encoded()))} bytes" + else: + body_info = "streamed" if self.is_streamed else "likely-streamed" + return f"<{type(self).__name__} {body_info} [{self.status}]>" + + @classmethod + def force_type( + cls, response: Response, environ: WSGIEnvironment | None = None + ) -> Response: + """Enforce that the WSGI response is a response object of the current + type. Werkzeug will use the :class:`Response` internally in many + situations like the exceptions. If you call :meth:`get_response` on an + exception you will get back a regular :class:`Response` object, even + if you are using a custom subclass. + + This method can enforce a given response type, and it will also + convert arbitrary WSGI callables into response objects if an environ + is provided:: + + # convert a Werkzeug response object into an instance of the + # MyResponseClass subclass. + response = MyResponseClass.force_type(response) + + # convert any WSGI application into a response object + response = MyResponseClass.force_type(response, environ) + + This is especially useful if you want to post-process responses in + the main dispatcher and use functionality provided by your subclass. + + Keep in mind that this will modify response objects in place if + possible! + + :param response: a response object or wsgi application. + :param environ: a WSGI environment object. + :return: a response object. + """ + if not isinstance(response, Response): + if environ is None: + raise TypeError( + "cannot convert WSGI application into response" + " objects without an environ" + ) + + from ..test import run_wsgi_app + + response = Response(*run_wsgi_app(response, environ)) + + response.__class__ = cls + return response + + @classmethod + def from_app( + cls, app: WSGIApplication, environ: WSGIEnvironment, buffered: bool = False + ) -> Response: + """Create a new response object from an application output. This + works best if you pass it an application that returns a generator all + the time. Sometimes applications may use the `write()` callable + returned by the `start_response` function. This tries to resolve such + edge cases automatically. But if you don't get the expected output + you should set `buffered` to `True` which enforces buffering. + + :param app: the WSGI application to execute. + :param environ: the WSGI environment to execute against. + :param buffered: set to `True` to enforce buffering. + :return: a response object. + """ + from ..test import run_wsgi_app + + return cls(*run_wsgi_app(app, environ, buffered)) + + @t.overload + def get_data(self, as_text: t.Literal[False] = False) -> bytes: ... + + @t.overload + def get_data(self, as_text: t.Literal[True]) -> str: ... + + def get_data(self, as_text: bool = False) -> bytes | str: + """The string representation of the response body. Whenever you call + this property the response iterable is encoded and flattened. This + can lead to unwanted behavior if you stream big data. + + This behavior can be disabled by setting + :attr:`implicit_sequence_conversion` to `False`. + + If `as_text` is set to `True` the return value will be a decoded + string. + + .. versionadded:: 0.9 + """ + self._ensure_sequence() + rv = b"".join(self.iter_encoded()) + + if as_text: + return rv.decode() + + return rv + + def set_data(self, value: bytes | str) -> None: + """Sets a new string as response. The value must be a string or + bytes. If a string is set it's encoded to the charset of the + response (utf-8 by default). + + .. versionadded:: 0.9 + """ + if isinstance(value, str): + value = value.encode() + self.response = [value] + if self.automatically_set_content_length: + self.headers["Content-Length"] = str(len(value)) + + data = property( + get_data, + set_data, + doc="A descriptor that calls :meth:`get_data` and :meth:`set_data`.", + ) + + def calculate_content_length(self) -> int | None: + """Returns the content length if available or `None` otherwise.""" + try: + self._ensure_sequence() + except RuntimeError: + return None + return sum(len(x) for x in self.iter_encoded()) + + def _ensure_sequence(self, mutable: bool = False) -> None: + """This method can be called by methods that need a sequence. If + `mutable` is true, it will also ensure that the response sequence + is a standard Python list. + + .. versionadded:: 0.6 + """ + if self.is_sequence: + # if we need a mutable object, we ensure it's a list. + if mutable and not isinstance(self.response, list): + self.response = list(self.response) # type: ignore + return + if self.direct_passthrough: + raise RuntimeError( + "Attempted implicit sequence conversion but the" + " response object is in direct passthrough mode." + ) + if not self.implicit_sequence_conversion: + raise RuntimeError( + "The response object required the iterable to be a" + " sequence, but the implicit conversion was disabled." + " Call make_sequence() yourself." + ) + self.make_sequence() + + def make_sequence(self) -> None: + """Converts the response iterator in a list. By default this happens + automatically if required. If `implicit_sequence_conversion` is + disabled, this method is not automatically called and some properties + might raise exceptions. This also encodes all the items. + + .. versionadded:: 0.6 + """ + if not self.is_sequence: + # if we consume an iterable we have to ensure that the close + # method of the iterable is called if available when we tear + # down the response + close = getattr(self.response, "close", None) + self.response = list(self.iter_encoded()) + if close is not None: + self.call_on_close(close) + + def iter_encoded(self) -> t.Iterator[bytes]: + """Iter the response encoded with the encoding of the response. + If the response object is invoked as WSGI application the return + value of this method is used as application iterator unless + :attr:`direct_passthrough` was activated. + """ + # Encode in a separate function so that self.response is fetched + # early. This allows us to wrap the response with the return + # value from get_app_iter or iter_encoded. + return _iter_encoded(self.response) + + @property + def is_streamed(self) -> bool: + """If the response is streamed (the response is not an iterable with + a length information) this property is `True`. In this case streamed + means that there is no information about the number of iterations. + This is usually `True` if a generator is passed to the response object. + + This is useful for checking before applying some sort of post + filtering that should not take place for streamed responses. + """ + try: + len(self.response) # type: ignore + except (TypeError, AttributeError): + return True + return False + + @property + def is_sequence(self) -> bool: + """If the iterator is buffered, this property will be `True`. A + response object will consider an iterator to be buffered if the + response attribute is a list or tuple. + + .. versionadded:: 0.6 + """ + return isinstance(self.response, (tuple, list)) + + def close(self) -> None: + """Close the wrapped response if possible. You can also use the object + in a with statement which will automatically close it. + + .. versionadded:: 0.9 + Can now be used in a with statement. + """ + if hasattr(self.response, "close"): + self.response.close() + for func in self._on_close: + func() + + def __enter__(self) -> Response: + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.close() + + def freeze(self) -> None: + """Make the response object ready to be pickled. Does the + following: + + * Buffer the response into a list, ignoring + :attr:`implicity_sequence_conversion` and + :attr:`direct_passthrough`. + * Set the ``Content-Length`` header. + * Generate an ``ETag`` header if one is not already set. + + .. versionchanged:: 2.1 + Removed the ``no_etag`` parameter. + + .. versionchanged:: 2.0 + An ``ETag`` header is always added. + + .. versionchanged:: 0.6 + The ``Content-Length`` header is set. + """ + # Always freeze the encoded response body, ignore + # implicit_sequence_conversion and direct_passthrough. + self.response = list(self.iter_encoded()) + self.headers["Content-Length"] = str(sum(map(len, self.response))) + self.add_etag() + + def get_wsgi_headers(self, environ: WSGIEnvironment) -> Headers: + """This is automatically called right before the response is started + and returns headers modified for the given environment. It returns a + copy of the headers from the response with some modifications applied + if necessary. + + For example the location header (if present) is joined with the root + URL of the environment. Also the content length is automatically set + to zero here for certain status codes. + + .. versionchanged:: 0.6 + Previously that function was called `fix_headers` and modified + the response object in place. Also since 0.6, IRIs in location + and content-location headers are handled properly. + + Also starting with 0.6, Werkzeug will attempt to set the content + length if it is able to figure it out on its own. This is the + case if all the strings in the response iterable are already + encoded and the iterable is buffered. + + :param environ: the WSGI environment of the request. + :return: returns a new :class:`~werkzeug.datastructures.Headers` + object. + """ + headers = Headers(self.headers) + location: str | None = None + content_location: str | None = None + content_length: str | int | None = None + status = self.status_code + + # iterate over the headers to find all values in one go. Because + # get_wsgi_headers is used each response that gives us a tiny + # speedup. + for key, value in headers: + ikey = key.lower() + if ikey == "location": + location = value + elif ikey == "content-location": + content_location = value + elif ikey == "content-length": + content_length = value + + if location is not None: + location = iri_to_uri(location) + + if self.autocorrect_location_header: + # Make the location header an absolute URL. + current_url = get_current_url(environ, strip_querystring=True) + current_url = iri_to_uri(current_url) + location = urljoin(current_url, location) + + headers["Location"] = location + + # make sure the content location is a URL + if content_location is not None: + headers["Content-Location"] = iri_to_uri(content_location) + + if 100 <= status < 200 or status == 204: + # Per section 3.3.2 of RFC 7230, "a server MUST NOT send a + # Content-Length header field in any response with a status + # code of 1xx (Informational) or 204 (No Content)." + headers.remove("Content-Length") + elif status == 304: + remove_entity_headers(headers) + + # if we can determine the content length automatically, we + # should try to do that. But only if this does not involve + # flattening the iterator or encoding of strings in the + # response. We however should not do that if we have a 304 + # response. + if ( + self.automatically_set_content_length + and self.is_sequence + and content_length is None + and status not in (204, 304) + and not (100 <= status < 200) + ): + content_length = sum(len(x) for x in self.iter_encoded()) + headers["Content-Length"] = str(content_length) + + return headers + + def get_app_iter(self, environ: WSGIEnvironment) -> t.Iterable[bytes]: + """Returns the application iterator for the given environ. Depending + on the request method and the current status code the return value + might be an empty response rather than the one from the response. + + If the request method is `HEAD` or the status code is in a range + where the HTTP specification requires an empty response, an empty + iterable is returned. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: a response iterable. + """ + status = self.status_code + if ( + environ["REQUEST_METHOD"] == "HEAD" + or 100 <= status < 200 + or status in (204, 304) + ): + iterable: t.Iterable[bytes] = () + elif self.direct_passthrough: + return self.response # type: ignore + else: + iterable = self.iter_encoded() + return ClosingIterator(iterable, self.close) + + def get_wsgi_response( + self, environ: WSGIEnvironment + ) -> tuple[t.Iterable[bytes], str, list[tuple[str, str]]]: + """Returns the final WSGI response as tuple. The first item in + the tuple is the application iterator, the second the status and + the third the list of headers. The response returned is created + specially for the given environment. For example if the request + method in the WSGI environment is ``'HEAD'`` the response will + be empty and only the headers and status code will be present. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: an ``(app_iter, status, headers)`` tuple. + """ + headers = self.get_wsgi_headers(environ) + app_iter = self.get_app_iter(environ) + return app_iter, self.status, headers.to_wsgi_list() + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> t.Iterable[bytes]: + """Process this response as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + :return: an application iterator + """ + app_iter, status, headers = self.get_wsgi_response(environ) + start_response(status, headers) + return app_iter + + # JSON + + #: A module or other object that has ``dumps`` and ``loads`` + #: functions that match the API of the built-in :mod:`json` module. + json_module = json + + @property + def json(self) -> t.Any | None: + """The parsed JSON data if :attr:`mimetype` indicates JSON + (:mimetype:`application/json`, see :attr:`is_json`). + + Calls :meth:`get_json` with default arguments. + """ + return self.get_json() + + @t.overload + def get_json(self, force: bool = ..., silent: t.Literal[False] = ...) -> t.Any: ... + + @t.overload + def get_json(self, force: bool = ..., silent: bool = ...) -> t.Any | None: ... + + def get_json(self, force: bool = False, silent: bool = False) -> t.Any | None: + """Parse :attr:`data` as JSON. Useful during testing. + + If the mimetype does not indicate JSON + (:mimetype:`application/json`, see :attr:`is_json`), this + returns ``None``. + + Unlike :meth:`Request.get_json`, the result is not cached. + + :param force: Ignore the mimetype and always try to parse JSON. + :param silent: Silence parsing errors and return ``None`` + instead. + """ + if not (force or self.is_json): + return None + + data = self.get_data() + + try: + return self.json_module.loads(data) + except ValueError: + if not silent: + raise + + return None + + # Stream + + @cached_property + def stream(self) -> ResponseStream: + """The response iterable as write-only stream.""" + return ResponseStream(self) + + def _wrap_range_response(self, start: int, length: int) -> None: + """Wrap existing Response in case of Range Request context.""" + if self.status_code == 206: + self.response = _RangeWrapper(self.response, start, length) # type: ignore + + def _is_range_request_processable(self, environ: WSGIEnvironment) -> bool: + """Return ``True`` if `Range` header is present and if underlying + resource is considered unchanged when compared with `If-Range` header. + """ + return ( + "HTTP_IF_RANGE" not in environ + or not is_resource_modified( + environ, + self.headers.get("etag"), + None, + self.headers.get("last-modified"), + ignore_if_range=False, + ) + ) and "HTTP_RANGE" in environ + + def _process_range_request( + self, + environ: WSGIEnvironment, + complete_length: int | None, + accept_ranges: bool | str, + ) -> bool: + """Handle Range Request related headers (RFC7233). If `Accept-Ranges` + header is valid, and Range Request is processable, we set the headers + as described by the RFC, and wrap the underlying response in a + RangeWrapper. + + Returns ``True`` if Range Request can be fulfilled, ``False`` otherwise. + + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + + .. versionchanged:: 2.0 + Returns ``False`` if the length is 0. + """ + from ..exceptions import RequestedRangeNotSatisfiable + + if ( + not accept_ranges + or complete_length is None + or complete_length == 0 + or not self._is_range_request_processable(environ) + ): + return False + + if accept_ranges is True: + accept_ranges = "bytes" + + parsed_range = parse_range_header(environ.get("HTTP_RANGE")) + + if parsed_range is None: + raise RequestedRangeNotSatisfiable(complete_length) + + range_tuple = parsed_range.range_for_length(complete_length) + content_range_header = parsed_range.to_content_range_header(complete_length) + + if range_tuple is None or content_range_header is None: + raise RequestedRangeNotSatisfiable(complete_length) + + content_length = range_tuple[1] - range_tuple[0] + self.headers["Content-Length"] = str(content_length) + self.headers["Accept-Ranges"] = accept_ranges + self.content_range = content_range_header # type: ignore + self.status_code = 206 + self._wrap_range_response(range_tuple[0], content_length) + return True + + def make_conditional( + self, + request_or_environ: WSGIEnvironment | Request, + accept_ranges: bool | str = False, + complete_length: int | None = None, + ) -> Response: + """Make the response conditional to the request. This method works + best if an etag was defined for the response already. The `add_etag` + method can be used to do that. If called without etag just the date + header is set. + + This does nothing if the request method in the request or environ is + anything but GET or HEAD. + + For optimal performance when handling range requests, it's recommended + that your response data object implements `seekable`, `seek` and `tell` + methods as described by :py:class:`io.IOBase`. Objects returned by + :meth:`~werkzeug.wsgi.wrap_file` automatically implement those methods. + + It does not remove the body of the response because that's something + the :meth:`__call__` function does for us automatically. + + Returns self so that you can do ``return resp.make_conditional(req)`` + but modifies the object in-place. + + :param request_or_environ: a request object or WSGI environment to be + used to make the response conditional + against. + :param accept_ranges: This parameter dictates the value of + `Accept-Ranges` header. If ``False`` (default), + the header is not set. If ``True``, it will be set + to ``"bytes"``. If it's a string, it will use this + value. + :param complete_length: Will be used only in valid Range Requests. + It will set `Content-Range` complete length + value and compute `Content-Length` real value. + This parameter is mandatory for successful + Range Requests completion. + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + + .. versionchanged:: 2.0 + Range processing is skipped if length is 0 instead of + raising a 416 Range Not Satisfiable error. + """ + environ = _get_environ(request_or_environ) + if environ["REQUEST_METHOD"] in ("GET", "HEAD"): + # if the date is not in the headers, add it now. We however + # will not override an already existing header. Unfortunately + # this header will be overridden by many WSGI servers including + # wsgiref. + if "date" not in self.headers: + self.headers["Date"] = http_date() + is206 = self._process_range_request(environ, complete_length, accept_ranges) + if not is206 and not is_resource_modified( + environ, + self.headers.get("etag"), + None, + self.headers.get("last-modified"), + ): + if parse_etags(environ.get("HTTP_IF_MATCH")): + self.status_code = 412 + else: + self.status_code = 304 + if ( + self.automatically_set_content_length + and "content-length" not in self.headers + ): + length = self.calculate_content_length() + if length is not None: + self.headers["Content-Length"] = str(length) + return self + + def add_etag(self, overwrite: bool = False, weak: bool = False) -> None: + """Add an etag for the current response if there is none yet. + + .. versionchanged:: 2.0 + SHA-1 is used to generate the value. MD5 may not be + available in some environments. + """ + if overwrite or "etag" not in self.headers: + self.set_etag(generate_etag(self.get_data()), weak) + + +class ResponseStream: + """A file descriptor like object used by :meth:`Response.stream` to + represent the body of the stream. It directly pushes into the + response iterable of the response object. + """ + + mode = "wb+" + + def __init__(self, response: Response): + self.response = response + self.closed = False + + def write(self, value: bytes) -> int: + if self.closed: + raise ValueError("I/O operation on closed file") + self.response._ensure_sequence(mutable=True) + self.response.response.append(value) # type: ignore + self.response.headers.pop("Content-Length", None) + return len(value) + + def writelines(self, seq: t.Iterable[bytes]) -> None: + for item in seq: + self.write(item) + + def close(self) -> None: + self.closed = True + + def flush(self) -> None: + if self.closed: + raise ValueError("I/O operation on closed file") + + def isatty(self) -> bool: + if self.closed: + raise ValueError("I/O operation on closed file") + return False + + def tell(self) -> int: + self.response._ensure_sequence() + return sum(map(len, self.response.response)) + + @property + def encoding(self) -> str: + return "utf-8" diff --git a/MLPY/Lib/site-packages/werkzeug/wsgi.py b/MLPY/Lib/site-packages/werkzeug/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..01d40af2f134e24f23831e12fb6f14ccc435181d --- /dev/null +++ b/MLPY/Lib/site-packages/werkzeug/wsgi.py @@ -0,0 +1,595 @@ +from __future__ import annotations + +import io +import typing as t +from functools import partial +from functools import update_wrapper + +from .exceptions import ClientDisconnected +from .exceptions import RequestEntityTooLarge +from .sansio import utils as _sansio_utils +from .sansio.utils import host_is_trusted # noqa: F401 # Imported as part of API + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +def responder(f: t.Callable[..., WSGIApplication]) -> WSGIApplication: + """Marks a function as responder. Decorate a function with it and it + will automatically call the return value as WSGI application. + + Example:: + + @responder + def application(environ, start_response): + return Response('Hello World!') + """ + return update_wrapper(lambda *a: f(*a)(*a[-2:]), f) + + +def get_current_url( + environ: WSGIEnvironment, + root_only: bool = False, + strip_querystring: bool = False, + host_only: bool = False, + trusted_hosts: t.Iterable[str] | None = None, +) -> str: + """Recreate the URL for a request from the parts in a WSGI + environment. + + The URL is an IRI, not a URI, so it may contain Unicode characters. + Use :func:`~werkzeug.urls.iri_to_uri` to convert it to ASCII. + + :param environ: The WSGI environment to get the URL parts from. + :param root_only: Only build the root path, don't include the + remaining path or query string. + :param strip_querystring: Don't include the query string. + :param host_only: Only build the scheme and host. + :param trusted_hosts: A list of trusted host names to validate the + host against. + """ + parts = { + "scheme": environ["wsgi.url_scheme"], + "host": get_host(environ, trusted_hosts), + } + + if not host_only: + parts["root_path"] = environ.get("SCRIPT_NAME", "") + + if not root_only: + parts["path"] = environ.get("PATH_INFO", "") + + if not strip_querystring: + parts["query_string"] = environ.get("QUERY_STRING", "").encode("latin1") + + return _sansio_utils.get_current_url(**parts) + + +def _get_server( + environ: WSGIEnvironment, +) -> tuple[str, int | None] | None: + name = environ.get("SERVER_NAME") + + if name is None: + return None + + try: + port: int | None = int(environ.get("SERVER_PORT", None)) + except (TypeError, ValueError): + # unix socket + port = None + + return name, port + + +def get_host( + environ: WSGIEnvironment, trusted_hosts: t.Iterable[str] | None = None +) -> str: + """Return the host for the given WSGI environment. + + The ``Host`` header is preferred, then ``SERVER_NAME`` if it's not + set. The returned host will only contain the port if it is different + than the standard port for the protocol. + + Optionally, verify that the host is trusted using + :func:`host_is_trusted` and raise a + :exc:`~werkzeug.exceptions.SecurityError` if it is not. + + :param environ: A WSGI environment dict. + :param trusted_hosts: A list of trusted host names. + + :return: Host, with port if necessary. + :raise ~werkzeug.exceptions.SecurityError: If the host is not + trusted. + """ + return _sansio_utils.get_host( + environ["wsgi.url_scheme"], + environ.get("HTTP_HOST"), + _get_server(environ), + trusted_hosts, + ) + + +def get_content_length(environ: WSGIEnvironment) -> int | None: + """Return the ``Content-Length`` header value as an int. If the header is not given + or the ``Transfer-Encoding`` header is ``chunked``, ``None`` is returned to indicate + a streaming request. If the value is not an integer, or negative, 0 is returned. + + :param environ: The WSGI environ to get the content length from. + + .. versionadded:: 0.9 + """ + return _sansio_utils.get_content_length( + http_content_length=environ.get("CONTENT_LENGTH"), + http_transfer_encoding=environ.get("HTTP_TRANSFER_ENCODING"), + ) + + +def get_input_stream( + environ: WSGIEnvironment, + safe_fallback: bool = True, + max_content_length: int | None = None, +) -> t.IO[bytes]: + """Return the WSGI input stream, wrapped so that it may be read safely without going + past the ``Content-Length`` header value or ``max_content_length``. + + If ``Content-Length`` exceeds ``max_content_length``, a + :exc:`RequestEntityTooLarge`` ``413 Content Too Large`` error is raised. + + If the WSGI server sets ``environ["wsgi.input_terminated"]``, it indicates that the + server handles terminating the stream, so it is safe to read directly. For example, + a server that knows how to handle chunked requests safely would set this. + + If ``max_content_length`` is set, it can be enforced on streams if + ``wsgi.input_terminated`` is set. Otherwise, an empty stream is returned unless the + user explicitly disables this safe fallback. + + If the limit is reached before the underlying stream is exhausted (such as a file + that is too large, or an infinite stream), the remaining contents of the stream + cannot be read safely. Depending on how the server handles this, clients may show a + "connection reset" failure instead of seeing the 413 response. + + :param environ: The WSGI environ containing the stream. + :param safe_fallback: Return an empty stream when ``Content-Length`` is not set. + Disabling this allows infinite streams, which can be a denial-of-service risk. + :param max_content_length: The maximum length that content-length or streaming + requests may not exceed. + + .. versionchanged:: 2.3.2 + ``max_content_length`` is only applied to streaming requests if the server sets + ``wsgi.input_terminated``. + + .. versionchanged:: 2.3 + Check ``max_content_length`` and raise an error if it is exceeded. + + .. versionadded:: 0.9 + """ + stream = t.cast(t.IO[bytes], environ["wsgi.input"]) + content_length = get_content_length(environ) + + if content_length is not None and max_content_length is not None: + if content_length > max_content_length: + raise RequestEntityTooLarge() + + # A WSGI server can set this to indicate that it terminates the input stream. In + # that case the stream is safe without wrapping, or can enforce a max length. + if "wsgi.input_terminated" in environ: + if max_content_length is not None: + # If this is moved above, it can cause the stream to hang if a read attempt + # is made when the client sends no data. For example, the development server + # does not handle buffering except for chunked encoding. + return t.cast( + t.IO[bytes], LimitedStream(stream, max_content_length, is_max=True) + ) + + return stream + + # No limit given, return an empty stream unless the user explicitly allows the + # potentially infinite stream. An infinite stream is dangerous if it's not expected, + # as it can tie up a worker indefinitely. + if content_length is None: + return io.BytesIO() if safe_fallback else stream + + return t.cast(t.IO[bytes], LimitedStream(stream, content_length)) + + +def get_path_info(environ: WSGIEnvironment) -> str: + """Return ``PATH_INFO`` from the WSGI environment. + + :param environ: WSGI environment to get the path from. + + .. versionchanged:: 3.0 + The ``charset`` and ``errors`` parameters were removed. + + .. versionadded:: 0.9 + """ + path: bytes = environ.get("PATH_INFO", "").encode("latin1") + return path.decode(errors="replace") + + +class ClosingIterator: + """The WSGI specification requires that all middlewares and gateways + respect the `close` callback of the iterable returned by the application. + Because it is useful to add another close action to a returned iterable + and adding a custom iterable is a boring task this class can be used for + that:: + + return ClosingIterator(app(environ, start_response), [cleanup_session, + cleanup_locals]) + + If there is just one close function it can be passed instead of the list. + + A closing iterator is not needed if the application uses response objects + and finishes the processing if the response is started:: + + try: + return response(environ, start_response) + finally: + cleanup_session() + cleanup_locals() + """ + + def __init__( + self, + iterable: t.Iterable[bytes], + callbacks: None + | (t.Callable[[], None] | t.Iterable[t.Callable[[], None]]) = None, + ) -> None: + iterator = iter(iterable) + self._next = t.cast(t.Callable[[], bytes], partial(next, iterator)) + if callbacks is None: + callbacks = [] + elif callable(callbacks): + callbacks = [callbacks] + else: + callbacks = list(callbacks) + iterable_close = getattr(iterable, "close", None) + if iterable_close: + callbacks.insert(0, iterable_close) + self._callbacks = callbacks + + def __iter__(self) -> ClosingIterator: + return self + + def __next__(self) -> bytes: + return self._next() + + def close(self) -> None: + for callback in self._callbacks: + callback() + + +def wrap_file( + environ: WSGIEnvironment, file: t.IO[bytes], buffer_size: int = 8192 +) -> t.Iterable[bytes]: + """Wraps a file. This uses the WSGI server's file wrapper if available + or otherwise the generic :class:`FileWrapper`. + + .. versionadded:: 0.5 + + If the file wrapper from the WSGI server is used it's important to not + iterate over it from inside the application but to pass it through + unchanged. If you want to pass out a file wrapper inside a response + object you have to set :attr:`Response.direct_passthrough` to `True`. + + More information about file wrappers are available in :pep:`333`. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + return environ.get("wsgi.file_wrapper", FileWrapper)( # type: ignore + file, buffer_size + ) + + +class FileWrapper: + """This class can be used to convert a :class:`file`-like object into + an iterable. It yields `buffer_size` blocks until the file is fully + read. + + You should not use this class directly but rather use the + :func:`wrap_file` function that uses the WSGI server's file wrapper + support if it's available. + + .. versionadded:: 0.5 + + If you're using this object together with a :class:`Response` you have + to use the `direct_passthrough` mode. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + + def __init__(self, file: t.IO[bytes], buffer_size: int = 8192) -> None: + self.file = file + self.buffer_size = buffer_size + + def close(self) -> None: + if hasattr(self.file, "close"): + self.file.close() + + def seekable(self) -> bool: + if hasattr(self.file, "seekable"): + return self.file.seekable() + if hasattr(self.file, "seek"): + return True + return False + + def seek(self, *args: t.Any) -> None: + if hasattr(self.file, "seek"): + self.file.seek(*args) + + def tell(self) -> int | None: + if hasattr(self.file, "tell"): + return self.file.tell() + return None + + def __iter__(self) -> FileWrapper: + return self + + def __next__(self) -> bytes: + data = self.file.read(self.buffer_size) + if data: + return data + raise StopIteration() + + +class _RangeWrapper: + # private for now, but should we make it public in the future ? + + """This class can be used to convert an iterable object into + an iterable that will only yield a piece of the underlying content. + It yields blocks until the underlying stream range is fully read. + The yielded blocks will have a size that can't exceed the original + iterator defined block size, but that can be smaller. + + If you're using this object together with a :class:`Response` you have + to use the `direct_passthrough` mode. + + :param iterable: an iterable object with a :meth:`__next__` method. + :param start_byte: byte from which read will start. + :param byte_range: how many bytes to read. + """ + + def __init__( + self, + iterable: t.Iterable[bytes] | t.IO[bytes], + start_byte: int = 0, + byte_range: int | None = None, + ): + self.iterable = iter(iterable) + self.byte_range = byte_range + self.start_byte = start_byte + self.end_byte = None + + if byte_range is not None: + self.end_byte = start_byte + byte_range + + self.read_length = 0 + self.seekable = hasattr(iterable, "seekable") and iterable.seekable() + self.end_reached = False + + def __iter__(self) -> _RangeWrapper: + return self + + def _next_chunk(self) -> bytes: + try: + chunk = next(self.iterable) + self.read_length += len(chunk) + return chunk + except StopIteration: + self.end_reached = True + raise + + def _first_iteration(self) -> tuple[bytes | None, int]: + chunk = None + if self.seekable: + self.iterable.seek(self.start_byte) # type: ignore + self.read_length = self.iterable.tell() # type: ignore + contextual_read_length = self.read_length + else: + while self.read_length <= self.start_byte: + chunk = self._next_chunk() + if chunk is not None: + chunk = chunk[self.start_byte - self.read_length :] + contextual_read_length = self.start_byte + return chunk, contextual_read_length + + def _next(self) -> bytes: + if self.end_reached: + raise StopIteration() + chunk = None + contextual_read_length = self.read_length + if self.read_length == 0: + chunk, contextual_read_length = self._first_iteration() + if chunk is None: + chunk = self._next_chunk() + if self.end_byte is not None and self.read_length >= self.end_byte: + self.end_reached = True + return chunk[: self.end_byte - contextual_read_length] + return chunk + + def __next__(self) -> bytes: + chunk = self._next() + if chunk: + return chunk + self.end_reached = True + raise StopIteration() + + def close(self) -> None: + if hasattr(self.iterable, "close"): + self.iterable.close() + + +class LimitedStream(io.RawIOBase): + """Wrap a stream so that it doesn't read more than a given limit. This is used to + limit ``wsgi.input`` to the ``Content-Length`` header value or + :attr:`.Request.max_content_length`. + + When attempting to read after the limit has been reached, :meth:`on_exhausted` is + called. When the limit is a maximum, this raises :exc:`.RequestEntityTooLarge`. + + If reading from the stream returns zero bytes or raises an error, + :meth:`on_disconnect` is called, which raises :exc:`.ClientDisconnected`. When the + limit is a maximum and zero bytes were read, no error is raised, since it may be the + end of the stream. + + If the limit is reached before the underlying stream is exhausted (such as a file + that is too large, or an infinite stream), the remaining contents of the stream + cannot be read safely. Depending on how the server handles this, clients may show a + "connection reset" failure instead of seeing the 413 response. + + :param stream: The stream to read from. Must be a readable binary IO object. + :param limit: The limit in bytes to not read past. Should be either the + ``Content-Length`` header value or ``request.max_content_length``. + :param is_max: Whether the given ``limit`` is ``request.max_content_length`` instead + of the ``Content-Length`` header value. This changes how exhausted and + disconnect events are handled. + + .. versionchanged:: 2.3 + Handle ``max_content_length`` differently than ``Content-Length``. + + .. versionchanged:: 2.3 + Implements ``io.RawIOBase`` rather than ``io.IOBase``. + """ + + def __init__(self, stream: t.IO[bytes], limit: int, is_max: bool = False) -> None: + self._stream = stream + self._pos = 0 + self.limit = limit + self._limit_is_max = is_max + + @property + def is_exhausted(self) -> bool: + """Whether the current stream position has reached the limit.""" + return self._pos >= self.limit + + def on_exhausted(self) -> None: + """Called when attempting to read after the limit has been reached. + + The default behavior is to do nothing, unless the limit is a maximum, in which + case it raises :exc:`.RequestEntityTooLarge`. + + .. versionchanged:: 2.3 + Raises ``RequestEntityTooLarge`` if the limit is a maximum. + + .. versionchanged:: 2.3 + Any return value is ignored. + """ + if self._limit_is_max: + raise RequestEntityTooLarge() + + def on_disconnect(self, error: Exception | None = None) -> None: + """Called when an attempted read receives zero bytes before the limit was + reached. This indicates that the client disconnected before sending the full + request body. + + The default behavior is to raise :exc:`.ClientDisconnected`, unless the limit is + a maximum and no error was raised. + + .. versionchanged:: 2.3 + Added the ``error`` parameter. Do nothing if the limit is a maximum and no + error was raised. + + .. versionchanged:: 2.3 + Any return value is ignored. + """ + if not self._limit_is_max or error is not None: + raise ClientDisconnected() + + # If the limit is a maximum, then we may have read zero bytes because the + # streaming body is complete. There's no way to distinguish that from the + # client disconnecting early. + + def exhaust(self) -> bytes: + """Exhaust the stream by reading until the limit is reached or the client + disconnects, returning the remaining data. + + .. versionchanged:: 2.3 + Return the remaining data. + + .. versionchanged:: 2.2.3 + Handle case where wrapped stream returns fewer bytes than requested. + """ + if not self.is_exhausted: + return self.readall() + + return b"" + + def readinto(self, b: bytearray) -> int | None: # type: ignore[override] + size = len(b) + remaining = self.limit - self._pos + + if remaining <= 0: + self.on_exhausted() + return 0 + + if hasattr(self._stream, "readinto"): + # Use stream.readinto if it's available. + if size <= remaining: + # The size fits in the remaining limit, use the buffer directly. + try: + out_size: int | None = self._stream.readinto(b) + except (OSError, ValueError) as e: + self.on_disconnect(error=e) + return 0 + else: + # Use a temp buffer with the remaining limit as the size. + temp_b = bytearray(remaining) + + try: + out_size = self._stream.readinto(temp_b) + except (OSError, ValueError) as e: + self.on_disconnect(error=e) + return 0 + + if out_size: + b[:out_size] = temp_b + else: + # WSGI requires that stream.read is available. + try: + data = self._stream.read(min(size, remaining)) + except (OSError, ValueError) as e: + self.on_disconnect(error=e) + return 0 + + out_size = len(data) + b[:out_size] = data + + if not out_size: + # Read zero bytes from the stream. + self.on_disconnect() + return 0 + + self._pos += out_size + return out_size + + def readall(self) -> bytes: + if self.is_exhausted: + self.on_exhausted() + return b"" + + out = bytearray() + + # The parent implementation uses "while True", which results in an extra read. + while not self.is_exhausted: + data = self.read(1024 * 64) + + # Stream may return empty before a max limit is reached. + if not data: + break + + out.extend(data) + + return bytes(out) + + def tell(self) -> int: + """Return the current stream position. + + .. versionadded:: 0.9 + """ + return self._pos + + def readable(self) -> bool: + return True diff --git a/MLPY/Lib/site-packages/win32/Demos/BackupRead_BackupWrite.py b/MLPY/Lib/site-packages/win32/Demos/BackupRead_BackupWrite.py new file mode 100644 index 0000000000000000000000000000000000000000..0e9fc9f9200445571c375ef5bbd8331c61e3bf4b --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/BackupRead_BackupWrite.py @@ -0,0 +1,121 @@ +## demonstrates using BackupRead and BackupWrite to copy all of a file's data streams + + +import ntsecuritycon +import pythoncom +import pywintypes +import win32api +import win32con +import win32file +import win32security +from pywin32_testutil import ob2memory, str2bytes +from win32com import storagecon + +all_sd_info = ( + win32security.DACL_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION + | win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION +) + +tempdir = win32api.GetTempPath() +tempfile = win32api.GetTempFileName(tempdir, "bkr")[0] +outfile = win32api.GetTempFileName(tempdir, "out")[0] +print("Filename:", tempfile, "Output file:", outfile) + +f = open(tempfile, "w") +f.write("some random junk" + "x" * 100) +f.close() + +## add a couple of alternate data streams +f = open(tempfile + ":streamdata", "w") +f.write("data written to alternate stream" + "y" * 100) +f.close() + +f = open(tempfile + ":anotherstream", "w") +f.write("z" * 100) +f.close() + +## add Summary Information, which is stored as a separate stream +m = storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE | storagecon.STGM_DIRECT +pss = pythoncom.StgOpenStorageEx( + tempfile, m, storagecon.STGFMT_FILE, 0, pythoncom.IID_IPropertySetStorage, None +) +ps = pss.Create( + pythoncom.FMTID_SummaryInformation, + pythoncom.IID_IPropertyStorage, + 0, + storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE, +) +ps.WriteMultiple( + (storagecon.PIDSI_KEYWORDS, storagecon.PIDSI_COMMENTS), ("keywords", "comments") +) +ps = None +pss = None + +## add a custom security descriptor to make sure we don't +## get a default that would always be the same for both files in temp dir +new_sd = pywintypes.SECURITY_DESCRIPTOR() +sid = win32security.LookupAccountName("", "EveryOne")[0] +acl = pywintypes.ACL() +acl.AddAccessAllowedAce(1, win32con.GENERIC_READ, sid) +acl.AddAccessAllowedAce(1, ntsecuritycon.FILE_APPEND_DATA, sid) +acl.AddAccessAllowedAce(1, win32con.GENERIC_WRITE, sid) +acl.AddAccessAllowedAce(1, ntsecuritycon.FILE_ALL_ACCESS, sid) + +new_sd.SetSecurityDescriptorDacl(True, acl, False) +win32security.SetFileSecurity(tempfile, win32security.DACL_SECURITY_INFORMATION, new_sd) + + +sa = pywintypes.SECURITY_ATTRIBUTES() +sa.bInheritHandle = True +h = win32file.CreateFile( + tempfile, + win32con.GENERIC_ALL, + win32con.FILE_SHARE_READ, + sa, + win32con.OPEN_EXISTING, + win32file.FILE_FLAG_BACKUP_SEMANTICS, + None, +) + +outh = win32file.CreateFile( + outfile, + win32con.GENERIC_ALL, + win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, + sa, + win32con.OPEN_EXISTING, + win32file.FILE_FLAG_BACKUP_SEMANTICS, + None, +) + +ctxt = 0 +outctxt = 0 +buf = None +readsize = 100 + +while 1: + bytes_read, buf, ctxt = win32file.BackupRead(h, readsize, buf, False, True, ctxt) + if bytes_read == 0: + break + bytes_written, outctxt = win32file.BackupWrite( + outh, bytes_read, buf, False, True, outctxt + ) + print("Written:", bytes_written, "Context:", outctxt) +win32file.BackupRead(h, 0, buf, True, True, ctxt) +win32file.BackupWrite(outh, 0, str2bytes(""), True, True, outctxt) +win32file.CloseHandle(h) +win32file.CloseHandle(outh) + +assert open(tempfile).read() == open(outfile).read(), "File contents differ !" +assert ( + open(tempfile + ":streamdata").read() == open(outfile + ":streamdata").read() +), "streamdata contents differ !" +assert ( + open(tempfile + ":anotherstream").read() == open(outfile + ":anotherstream").read() +), "anotherstream contents differ !" +assert ( + ob2memory(win32security.GetFileSecurity(tempfile, all_sd_info))[:] + == ob2memory(win32security.GetFileSecurity(outfile, all_sd_info))[:] +), "Security descriptors are different !" +## also should check Summary Info programatically diff --git a/MLPY/Lib/site-packages/win32/Demos/BackupSeek_streamheaders.py b/MLPY/Lib/site-packages/win32/Demos/BackupSeek_streamheaders.py new file mode 100644 index 0000000000000000000000000000000000000000..8b828d1d5e377dae30c94725ae2af42cff073fee --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/BackupSeek_streamheaders.py @@ -0,0 +1,137 @@ +## demonstrates using BackupSeek to enumerate data streams for a file +import struct + +import pythoncom +import pywintypes +import win32api +import win32con +import win32file +from win32com import storagecon + +stream_types = { + win32con.BACKUP_DATA: "Standard data", + win32con.BACKUP_EA_DATA: "Extended attribute data", + win32con.BACKUP_SECURITY_DATA: "Security descriptor data", + win32con.BACKUP_ALTERNATE_DATA: "Alternative data streams", + win32con.BACKUP_LINK: "Hard link information", + win32con.BACKUP_PROPERTY_DATA: "Property data", + win32con.BACKUP_OBJECT_ID: "Objects identifiers", + win32con.BACKUP_REPARSE_DATA: "Reparse points", + win32con.BACKUP_SPARSE_BLOCK: "Sparse file", +} + +tempdir = win32api.GetTempPath() +tempfile = win32api.GetTempFileName(tempdir, "bkr")[0] +print("Filename:", tempfile) + +f = open(tempfile, "w") +f.write("some random junk" + "x" * 100) +f.close() + +f = open(tempfile + ":streamdata", "w") +f.write("data written to alternate stream" + "y" * 100) +f.close() + +f = open(tempfile + ":anotherstream", "w") +f.write("z" * 200) +f.close() + +## add Summary Information, which is stored as a separate stream +m = storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE | storagecon.STGM_DIRECT +pss = pythoncom.StgOpenStorageEx( + tempfile, m, storagecon.STGFMT_FILE, 0, pythoncom.IID_IPropertySetStorage, None +) +ps = pss.Create( + pythoncom.FMTID_SummaryInformation, + pythoncom.IID_IPropertyStorage, + 0, + storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE, +) +ps.WriteMultiple( + (storagecon.PIDSI_KEYWORDS, storagecon.PIDSI_COMMENTS), ("keywords", "comments") +) +ps = None +pss = None + +sa = pywintypes.SECURITY_ATTRIBUTES() +sa.bInheritHandle = False +h = win32file.CreateFile( + tempfile, + win32con.GENERIC_ALL, + win32con.FILE_SHARE_READ, + sa, + win32con.OPEN_EXISTING, + win32file.FILE_FLAG_BACKUP_SEMANTICS, + None, +) + + +""" stream header: +typedef struct _WIN32_STREAM_ID { + DWORD dwStreamId; DWORD dwStreamAttributes; LARGE_INTEGER Size; + DWORD dwStreamNameSize; WCHAR cStreamName[ANYSIZE_ARRAY]; +} +""" + +win32_stream_id_format = "LLQL" +win32_stream_id_size = struct.calcsize(win32_stream_id_format) + + +def parse_stream_header(h, ctxt, data): + stream_type, stream_attributes, stream_size, stream_name_size = struct.unpack( + win32_stream_id_format, data + ) + print( + "\nType:", + stream_type, + stream_types[stream_type], + "Attributes:", + stream_attributes, + "Size:", + stream_size, + "Name len:", + stream_name_size, + ) + if stream_name_size > 0: + ## ??? sdk says this size is in characters, but it appears to be number of bytes ??? + bytes_read, stream_name_buf, ctxt = win32file.BackupRead( + h, stream_name_size, None, False, True, ctxt + ) + stream_name = pywintypes.UnicodeFromRaw(stream_name_buf[:]) + else: + stream_name = "Unnamed" + print("Name:" + stream_name) + return ( + ctxt, + stream_type, + stream_attributes, + stream_size, + stream_name_size, + stream_name, + ) + + +ctxt = 0 +win32_stream_id_buf = ( + None ## gets rebound to a writable buffer on first call and reused +) +while 1: + bytes_read, win32_stream_id_buf, ctxt = win32file.BackupRead( + h, win32_stream_id_size, win32_stream_id_buf, False, True, ctxt + ) + if bytes_read == 0: + break + ( + ctxt, + stream_type, + stream_attributes, + stream_size, + stream_name_size, + stream_name, + ) = parse_stream_header(h, ctxt, win32_stream_id_buf[:]) + if stream_size > 0: + bytes_moved = win32file.BackupSeek(h, stream_size, ctxt) + print("Moved: ", bytes_moved) + +win32file.BackupRead(h, win32_stream_id_size, win32_stream_id_buf, True, True, ctxt) +win32file.CloseHandle(h) diff --git a/MLPY/Lib/site-packages/win32/Demos/CopyFileEx.py b/MLPY/Lib/site-packages/win32/Demos/CopyFileEx.py new file mode 100644 index 0000000000000000000000000000000000000000..cdac78e5d74714d9e1f427e4ce45238af3be80ff --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/CopyFileEx.py @@ -0,0 +1,57 @@ +import win32api +import win32file + + +def ProgressRoutine( + TotalFileSize, + TotalBytesTransferred, + StreamSize, + StreamBytesTransferred, + StreamNumber, + CallbackReason, + SourceFile, + DestinationFile, + Data, +): + print(Data) + print( + TotalFileSize, + TotalBytesTransferred, + StreamSize, + StreamBytesTransferred, + StreamNumber, + CallbackReason, + SourceFile, + DestinationFile, + ) + ##if TotalBytesTransferred > 100000: + ## return win32file.PROGRESS_STOP + return win32file.PROGRESS_CONTINUE + + +temp_dir = win32api.GetTempPath() +fsrc = win32api.GetTempFileName(temp_dir, "cfe")[0] +fdst = win32api.GetTempFileName(temp_dir, "cfe")[0] +print(fsrc, fdst) + +f = open(fsrc, "w") +f.write("xxxxxxxxxxxxxxxx\n" * 32768) +f.close() +## add a couple of extra data streams +f = open(fsrc + ":stream_y", "w") +f.write("yyyyyyyyyyyyyyyy\n" * 32768) +f.close() +f = open(fsrc + ":stream_z", "w") +f.write("zzzzzzzzzzzzzzzz\n" * 32768) +f.close() + +operation_desc = "Copying " + fsrc + " to " + fdst +win32file.CopyFileEx( + fsrc, + fdst, + ProgressRoutine, + Data=operation_desc, + Cancel=False, + CopyFlags=win32file.COPY_FILE_RESTARTABLE, + Transaction=None, +) diff --git a/MLPY/Lib/site-packages/win32/Demos/CreateFileTransacted_MiniVersion.py b/MLPY/Lib/site-packages/win32/Demos/CreateFileTransacted_MiniVersion.py new file mode 100644 index 0000000000000000000000000000000000000000..fd600b590812d4bd068d6aa865821d40934ceae8 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/CreateFileTransacted_MiniVersion.py @@ -0,0 +1,123 @@ +""" +This demonstrates the creation of miniversions of a file during a transaction. +The FSCTL_TXFS_CREATE_MINIVERSION control code saves any changes to a new +miniversion (effectively a savepoint within a transaction). +""" + +import os +import struct + +import win32api +import win32con +import win32file +import win32transaction +import winerror +import winioctlcon +from pywin32_testutil import str2bytes # py3k-friendly helper + + +def demo(): + """ + Definition of buffer used with FSCTL_TXFS_CREATE_MINIVERSION: + typedef struct _TXFS_CREATE_MINIVERSION_INFO{ + USHORT StructureVersion; + USHORT StructureLength; + ULONG BaseVersion; + USHORT MiniVersion;} + """ + buf_fmt = "HHLH0L" ## buffer size must include struct padding + buf_size = struct.calcsize(buf_fmt) + + tempdir = win32api.GetTempPath() + tempfile = win32api.GetTempFileName(tempdir, "cft")[0] + print("Demonstrating transactions on tempfile", tempfile) + f = open(tempfile, "w") + f.write("This is original file.\n") + f.close() + + trans = win32transaction.CreateTransaction( + Description="Test creating miniversions of a file" + ) + hfile = win32file.CreateFileW( + tempfile, + win32con.GENERIC_READ | win32con.GENERIC_WRITE, + win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, + None, + win32con.OPEN_EXISTING, + 0, + None, + Transaction=trans, + ) + + win32file.WriteFile(hfile, str2bytes("This is first miniversion.\n")) + buf = win32file.DeviceIoControl( + hfile, winioctlcon.FSCTL_TXFS_CREATE_MINIVERSION, None, buf_size, None + ) + struct_ver, struct_len, base_ver, ver_1 = struct.unpack(buf_fmt, buf) + + win32file.SetFilePointer(hfile, 0, win32con.FILE_BEGIN) + win32file.WriteFile(hfile, str2bytes("This is second miniversion!\n")) + buf = win32file.DeviceIoControl( + hfile, winioctlcon.FSCTL_TXFS_CREATE_MINIVERSION, None, buf_size, None + ) + struct_ver, struct_len, base_ver, ver_2 = struct.unpack(buf_fmt, buf) + hfile.Close() + + ## miniversions can't be opened with write access + hfile_0 = win32file.CreateFileW( + tempfile, + win32con.GENERIC_READ, + win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, + None, + win32con.OPEN_EXISTING, + 0, + None, + Transaction=trans, + MiniVersion=base_ver, + ) + print("version:", base_ver, win32file.ReadFile(hfile_0, 100)) + hfile_0.Close() + + hfile_1 = win32file.CreateFileW( + tempfile, + win32con.GENERIC_READ, + win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, + None, + win32con.OPEN_EXISTING, + 0, + None, + Transaction=trans, + MiniVersion=ver_1, + ) + print("version:", ver_1, win32file.ReadFile(hfile_1, 100)) + hfile_1.Close() + + hfile_2 = win32file.CreateFileW( + tempfile, + win32con.GENERIC_READ, + win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, + None, + win32con.OPEN_EXISTING, + 0, + None, + Transaction=trans, + MiniVersion=ver_2, + ) + print("version:", ver_2, win32file.ReadFile(hfile_2, 100)) + hfile_2.Close() + + ## MiniVersions are destroyed when transaction is committed or rolled back + win32transaction.CommitTransaction(trans) + + os.unlink(tempfile) + + +if __name__ == "__main__": + # When run on CI, this fails with NOT_SUPPORTED, so don't have that cause "failure" + try: + demo() + except win32file.error as e: + if e.winerror == winerror.ERROR_NOT_SUPPORTED: + print("These features are not supported by this filesystem.") + else: + raise diff --git a/MLPY/Lib/site-packages/win32/Demos/EvtFormatMessage.py b/MLPY/Lib/site-packages/win32/Demos/EvtFormatMessage.py new file mode 100644 index 0000000000000000000000000000000000000000..125438692ab3d1c54548264e0b95b865738f04f5 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/EvtFormatMessage.py @@ -0,0 +1,83 @@ +import sys + +import win32evtlog + + +def main(): + path = "System" + num_events = 5 + if len(sys.argv) > 2: + path = sys.argv[1] + num_events = int(sys.argv[2]) + elif len(sys.argv) > 1: + path = sys.argv[1] + + query = win32evtlog.EvtQuery(path, win32evtlog.EvtQueryForwardDirection) + events = win32evtlog.EvtNext(query, num_events) + context = win32evtlog.EvtCreateRenderContext(win32evtlog.EvtRenderContextSystem) + + for i, event in enumerate(events, 1): + result = win32evtlog.EvtRender( + event, win32evtlog.EvtRenderEventValues, Context=context + ) + + print("Event {}".format(i)) + + level_value, level_variant = result[win32evtlog.EvtSystemLevel] + if level_variant != win32evtlog.EvtVarTypeNull: + if level_value == 1: + print(" Level: CRITICAL") + elif level_value == 2: + print(" Level: ERROR") + elif level_value == 3: + print(" Level: WARNING") + elif level_value == 4: + print(" Level: INFO") + elif level_value == 5: + print(" Level: VERBOSE") + else: + print(" Level: UNKNOWN") + + time_created_value, time_created_variant = result[ + win32evtlog.EvtSystemTimeCreated + ] + if time_created_variant != win32evtlog.EvtVarTypeNull: + print(" Timestamp: {}".format(time_created_value.isoformat())) + + computer_value, computer_variant = result[win32evtlog.EvtSystemComputer] + if computer_variant != win32evtlog.EvtVarTypeNull: + print(" FQDN: {}".format(computer_value)) + + provider_name_value, provider_name_variant = result[ + win32evtlog.EvtSystemProviderName + ] + if provider_name_variant != win32evtlog.EvtVarTypeNull: + print(" Provider: {}".format(provider_name_value)) + + try: + metadata = win32evtlog.EvtOpenPublisherMetadata(provider_name_value) + # pywintypes.error: (2, 'EvtOpenPublisherMetadata', 'The system cannot find the file specified.') + except Exception: + pass + else: + try: + message = win32evtlog.EvtFormatMessage( + metadata, event, win32evtlog.EvtFormatMessageEvent + ) + # pywintypes.error: (15027, 'EvtFormatMessage: allocated 0, need buffer of size 0', 'The message resource is present but the message was not found in the message table.') + except Exception: + pass + else: + try: + print(" Message: {}".format(message)) + except UnicodeEncodeError: + # Obscure error when run under subprocess.Popen(), presumably due to + # not knowing the correct encoding for the console. + # > UnicodeEncodeError: \'charmap\' codec can\'t encode character \'\\u200e\' in position 57: character maps to \r\n' + # Can't reproduce when running manually, so it seems more a subprocess.Popen() + # than ours: + print(" Failed to decode:", repr(message)) + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/EvtSubscribe_pull.py b/MLPY/Lib/site-packages/win32/Demos/EvtSubscribe_pull.py new file mode 100644 index 0000000000000000000000000000000000000000..f40597964195077374b62f28f273163b10e1224f --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/EvtSubscribe_pull.py @@ -0,0 +1,28 @@ +## Demonstrates how to create a "pull" subscription +import win32con +import win32event +import win32evtlog + +query_text = '*[System[Provider[@Name="Microsoft-Windows-Winlogon"]]]' + +h = win32event.CreateEvent(None, 0, 0, None) +s = win32evtlog.EvtSubscribe( + "System", + win32evtlog.EvtSubscribeStartAtOldestRecord, + SignalEvent=h, + Query=query_text, +) + +while 1: + while 1: + events = win32evtlog.EvtNext(s, 10) + if len(events) == 0: + break + ##for event in events: + ## print(win32evtlog.EvtRender(event, win32evtlog.EvtRenderEventXml)) + print("retrieved %s events" % len(events)) + while 1: + print("waiting...") + w = win32event.WaitForSingleObjectEx(h, 2000, True) + if w == win32con.WAIT_OBJECT_0: + break diff --git a/MLPY/Lib/site-packages/win32/Demos/EvtSubscribe_push.py b/MLPY/Lib/site-packages/win32/Demos/EvtSubscribe_push.py new file mode 100644 index 0000000000000000000000000000000000000000..519ef0d72c19f213955ec1f1e481f66392d70e75 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/EvtSubscribe_push.py @@ -0,0 +1,25 @@ +## Demonstrates a "push" subscription with a callback function +import win32evtlog + +query_text = '*[System[Provider[@Name="Microsoft-Windows-Winlogon"]]]' + + +def c(reason, context, evt): + if reason == win32evtlog.EvtSubscribeActionError: + print("EvtSubscribeActionError") + elif reason == win32evtlog.EvtSubscribeActionDeliver: + print("EvtSubscribeActionDeliver") + else: + print("??? Unknown action ???", reason) + context.append(win32evtlog.EvtRender(evt, win32evtlog.EvtRenderEventXml)) + return 0 + + +evttext = [] +s = win32evtlog.EvtSubscribe( + "System", + win32evtlog.EvtSubscribeStartAtOldestRecord, + Query="*", + Callback=c, + Context=evttext, +) diff --git a/MLPY/Lib/site-packages/win32/Demos/FileSecurityTest.py b/MLPY/Lib/site-packages/win32/Demos/FileSecurityTest.py new file mode 100644 index 0000000000000000000000000000000000000000..90c454833f777971dcb19cd44c15de6c22457fc0 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/FileSecurityTest.py @@ -0,0 +1,137 @@ +# Contributed by Kelly Kranabetter. +import os +import sys + +import ntsecuritycon +import pywintypes +import win32security +import winerror + +# get security information +# name=r"c:\autoexec.bat" +# name= r"g:\!workgrp\lim" +name = sys.argv[0] + +if not os.path.exists(name): + print(name, "does not exist!") + sys.exit() + +print("On file ", name, "\n") + +# get owner SID +print("OWNER") +try: + sd = win32security.GetFileSecurity(name, win32security.OWNER_SECURITY_INFORMATION) + sid = sd.GetSecurityDescriptorOwner() + print(" ", win32security.LookupAccountSid(None, sid)) +except pywintypes.error as exc: + # in automation and network shares we see: + # pywintypes.error: (1332, 'LookupAccountName', 'No mapping between account names and security IDs was done.') + if exc.winerror != winerror.ERROR_NONE_MAPPED: + raise + print("No owner information is available") + +# get group SID +try: + print("GROUP") + sd = win32security.GetFileSecurity(name, win32security.GROUP_SECURITY_INFORMATION) + sid = sd.GetSecurityDescriptorGroup() + print(" ", win32security.LookupAccountSid(None, sid)) +except pywintypes.error as exc: + if exc.winerror != winerror.ERROR_NONE_MAPPED: + raise + print("No group information is available") + +# get ACEs +sd = win32security.GetFileSecurity(name, win32security.DACL_SECURITY_INFORMATION) +dacl = sd.GetSecurityDescriptorDacl() +if dacl == None: + print("No Discretionary ACL") +else: + for ace_no in range(0, dacl.GetAceCount()): + ace = dacl.GetAce(ace_no) + print("ACE", ace_no) + + print(" -Type") + for i in ( + "ACCESS_ALLOWED_ACE_TYPE", + "ACCESS_DENIED_ACE_TYPE", + "SYSTEM_AUDIT_ACE_TYPE", + "SYSTEM_ALARM_ACE_TYPE", + ): + if getattr(ntsecuritycon, i) == ace[0][0]: + print(" ", i) + + print(" -Flags", hex(ace[0][1])) + for i in ( + "OBJECT_INHERIT_ACE", + "CONTAINER_INHERIT_ACE", + "NO_PROPAGATE_INHERIT_ACE", + "INHERIT_ONLY_ACE", + "SUCCESSFUL_ACCESS_ACE_FLAG", + "FAILED_ACCESS_ACE_FLAG", + ): + if getattr(ntsecuritycon, i) & ace[0][1] == getattr(ntsecuritycon, i): + print(" ", i) + + print(" -mask", hex(ace[1])) + + # files and directories do permissions differently + permissions_file = ( + "DELETE", + "READ_CONTROL", + "WRITE_DAC", + "WRITE_OWNER", + "SYNCHRONIZE", + "FILE_GENERIC_READ", + "FILE_GENERIC_WRITE", + "FILE_GENERIC_EXECUTE", + "FILE_DELETE_CHILD", + ) + permissions_dir = ( + "DELETE", + "READ_CONTROL", + "WRITE_DAC", + "WRITE_OWNER", + "SYNCHRONIZE", + "FILE_ADD_SUBDIRECTORY", + "FILE_ADD_FILE", + "FILE_DELETE_CHILD", + "FILE_LIST_DIRECTORY", + "FILE_TRAVERSE", + "FILE_READ_ATTRIBUTES", + "FILE_WRITE_ATTRIBUTES", + "FILE_READ_EA", + "FILE_WRITE_EA", + ) + permissions_dir_inherit = ( + "DELETE", + "READ_CONTROL", + "WRITE_DAC", + "WRITE_OWNER", + "SYNCHRONIZE", + "GENERIC_READ", + "GENERIC_WRITE", + "GENERIC_EXECUTE", + "GENERIC_ALL", + ) + if os.path.isfile(name): + permissions = permissions_file + else: + permissions = permissions_dir + # directories also contain an ACE that is inherited by children (files) within them + if ( + ace[0][1] & ntsecuritycon.OBJECT_INHERIT_ACE + == ntsecuritycon.OBJECT_INHERIT_ACE + and ace[0][1] & ntsecuritycon.INHERIT_ONLY_ACE + == ntsecuritycon.INHERIT_ONLY_ACE + ): + permissions = permissions_dir_inherit + + calc_mask = 0 # calculate the mask so we can see if we are printing all of the permissions + for i in permissions: + if getattr(ntsecuritycon, i) & ace[1] == getattr(ntsecuritycon, i): + calc_mask = calc_mask | getattr(ntsecuritycon, i) + print(" ", i) + print(" ", "Calculated Check Mask=", hex(calc_mask)) + print(" -SID\n ", win32security.LookupAccountSid(None, ace[2])) diff --git a/MLPY/Lib/site-packages/win32/Demos/GetSaveFileName.py b/MLPY/Lib/site-packages/win32/Demos/GetSaveFileName.py new file mode 100644 index 0000000000000000000000000000000000000000..28587505294f89482f2be9d0580179fc61259b35 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/GetSaveFileName.py @@ -0,0 +1,43 @@ +import os + +import win32con +import win32gui + +filter = "Python Scripts\0*.py;*.pyw;*.pys\0Text files\0*.txt\0" +customfilter = "Other file types\0*.*\0" + +fname, customfilter, flags = win32gui.GetSaveFileNameW( + InitialDir=os.environ["temp"], + Flags=win32con.OFN_ALLOWMULTISELECT | win32con.OFN_EXPLORER, + File="somefilename", + DefExt="py", + Title="GetSaveFileNameW", + Filter=filter, + CustomFilter=customfilter, + FilterIndex=1, +) + +print("save file names:", repr(fname)) +print("filter used:", repr(customfilter)) +print("Flags:", flags) +for k, v in list(win32con.__dict__.items()): + if k.startswith("OFN_") and flags & v: + print("\t" + k) + +fname, customfilter, flags = win32gui.GetOpenFileNameW( + InitialDir=os.environ["temp"], + Flags=win32con.OFN_ALLOWMULTISELECT | win32con.OFN_EXPLORER, + File="somefilename", + DefExt="py", + Title="GetOpenFileNameW", + Filter=filter, + CustomFilter=customfilter, + FilterIndex=0, +) + +print("open file names:", repr(fname)) +print("filter used:", repr(customfilter)) +print("Flags:", flags) +for k, v in list(win32con.__dict__.items()): + if k.startswith("OFN_") and flags & v: + print("\t" + k) diff --git a/MLPY/Lib/site-packages/win32/Demos/NetValidatePasswordPolicy.py b/MLPY/Lib/site-packages/win32/Demos/NetValidatePasswordPolicy.py new file mode 100644 index 0000000000000000000000000000000000000000..86c3bc40bd20d508578f0a1878c749d6f8f40e51 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/NetValidatePasswordPolicy.py @@ -0,0 +1,127 @@ +"""A demo of using win32net.NetValidatePasswordPolicy. + +Example usage: + +% NetValidatePasswordPolicy.py --password=foo change +which might return: + +> Result of 'change' validation is 0: The operation completed successfully. + +or depending on the policy: + +> Result of 'change' validation is 2245: The password does not meet the +> password policy requirements. Check the minimum password length, +> password complexity and password history requirements. + +Adding --user doesn't seem to change the output (even the PasswordLastSet seen +when '-f' is used doesn't depend on the username), but theoretically it will +also check the password history for the specified user. + +% NetValidatePasswordPolicy.py auth + +which always (with and without '-m') seems to return: + +> Result of 'auth' validation is 2701: Password must change at next logon +""" + +import optparse +import sys +from pprint import pprint + +import win32api +import win32net +import win32netcon + + +def main(): + parser = optparse.OptionParser( + "%prog [options] auth|change ...", + description="A win32net.NetValidatePasswordPolicy demo.", + ) + + parser.add_option( + "-u", + "--username", + action="store", + help="The username to pass to the function (only for the " "change command", + ) + + parser.add_option( + "-p", + "--password", + action="store", + help="The clear-text password to pass to the function " + "(only for the 'change' command)", + ) + + parser.add_option( + "-m", + "--password-matched", + action="store_false", + default=True, + help="Used to specify the password does NOT match (ie, " + "uses False for the PasswordMatch/PasswordMatched " + "arg, both 'auth' and 'change' commands)", + ) + + parser.add_option( + "-s", + "--server", + action="store", + help="The name of the server to execute the command on", + ) + + parser.add_option( + "-f", + "--show_fields", + action="store_true", + default=False, + help="Print the NET_VALIDATE_PERSISTED_FIELDS returned", + ) + + options, args = parser.parse_args() + + if not args: + args = ["auth"] + + for arg in args: + if arg == "auth": + input = { + "PasswordMatched": options.password_matched, + } + val_type = win32netcon.NetValidateAuthentication + elif arg == "change": + input = { + "ClearPassword": options.password, + "PasswordMatch": options.password_matched, + "UserAccountName": options.username, + } + val_type = win32netcon.NetValidatePasswordChange + else: + parser.error("Invalid arg - must be 'auth' or 'change'") + + try: + fields, status = win32net.NetValidatePasswordPolicy( + options.server, None, val_type, input + ) + except NotImplementedError: + print("NetValidatePasswordPolicy not implemented on this platform.") + return 1 + except win32net.error as exc: + print("NetValidatePasswordPolicy failed: ", exc) + return 1 + + if options.show_fields: + print("NET_VALIDATE_PERSISTED_FIELDS fields:") + pprint(fields) + + print( + "Result of %r validation is %d: %s" + % (arg, status, win32api.FormatMessage(status).strip()) + ) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/MLPY/Lib/site-packages/win32/Demos/OpenEncryptedFileRaw.py b/MLPY/Lib/site-packages/win32/Demos/OpenEncryptedFileRaw.py new file mode 100644 index 0000000000000000000000000000000000000000..aa0f2a7c15239b36c356d23f8753536cf4acdc52 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/OpenEncryptedFileRaw.py @@ -0,0 +1,67 @@ +import os + +import win32api +import win32file +import winerror + + +def ReadCallback(input_buffer, data, buflen): + fnamein, fnameout, f = data + ## print fnamein, fnameout, buflen + f.write(input_buffer) + ## python 2.3 throws an error if return value is a plain int + return winerror.ERROR_SUCCESS + + +def WriteCallback(output_buffer, data, buflen): + fnamebackup, fnameout, f = data + file_data = f.read(buflen) + ## returning 0 as len terminates WriteEncryptedFileRaw + output_len = len(file_data) + output_buffer[:output_len] = file_data + return winerror.ERROR_SUCCESS, output_len + + +tmp_dir = win32api.GetTempPath() +dst_dir = win32api.GetTempFileName(tmp_dir, "oef")[0] +os.remove(dst_dir) +os.mkdir(dst_dir) +print("Destination dir:", dst_dir) + +## create an encrypted file +fname = win32api.GetTempFileName(dst_dir, "ref")[0] +print("orig file:", fname) +f = open(fname, "w") +f.write("xxxxxxxxxxxxxxxx\n" * 32768) +f.close() +## add a couple of extra data streams +f = open(fname + ":stream_y", "w") +f.write("yyyyyyyyyyyyyyyy\n" * 32768) +f.close() +f = open(fname + ":stream_z", "w") +f.write("zzzzzzzzzzzzzzzz\n" * 32768) +f.close() +win32file.EncryptFile(fname) + +## backup raw data of encrypted file +bkup_fname = win32api.GetTempFileName(dst_dir, "bef")[0] +print("backup file:", bkup_fname) +f = open(bkup_fname, "wb") +ctxt = win32file.OpenEncryptedFileRaw(fname, 0) +try: + win32file.ReadEncryptedFileRaw(ReadCallback, (fname, bkup_fname, f), ctxt) +finally: + ## if context is not closed, file remains locked even if calling process is killed + win32file.CloseEncryptedFileRaw(ctxt) + f.close() + +## restore data from backup to new encrypted file +dst_fname = win32api.GetTempFileName(dst_dir, "wef")[0] +print("restored file:", dst_fname) +f = open(bkup_fname, "rb") +ctxtout = win32file.OpenEncryptedFileRaw(dst_fname, win32file.CREATE_FOR_IMPORT) +try: + win32file.WriteEncryptedFileRaw(WriteCallback, (bkup_fname, dst_fname, f), ctxtout) +finally: + win32file.CloseEncryptedFileRaw(ctxtout) + f.close() diff --git a/MLPY/Lib/site-packages/win32/Demos/RegCreateKeyTransacted.py b/MLPY/Lib/site-packages/win32/Demos/RegCreateKeyTransacted.py new file mode 100644 index 0000000000000000000000000000000000000000..687f07ae6b83415a6c81258a4e4d67e9a5dbfa62 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/RegCreateKeyTransacted.py @@ -0,0 +1,60 @@ +import win32api +import win32con +import win32transaction + +keyname = "Pywin32 test transacted registry functions" +subkeyname = "test transacted subkey" +classname = "Transacted Class" + +trans = win32transaction.CreateTransaction(Description="test RegCreateKeyTransacted") +key, disp = win32api.RegCreateKeyEx( + win32con.HKEY_CURRENT_USER, + keyname, + samDesired=win32con.KEY_ALL_ACCESS, + Class=classname, +) +## clean up any existing keys +for subk in win32api.RegEnumKeyExW(key): + win32api.RegDeleteKey(key, subk[0]) + +## reopen key in transacted mode +transacted_key = win32api.RegOpenKeyTransacted( + Key=win32con.HKEY_CURRENT_USER, + SubKey=keyname, + Transaction=trans, + samDesired=win32con.KEY_ALL_ACCESS, +) +subkey, disp = win32api.RegCreateKeyEx( + transacted_key, + subkeyname, + Transaction=trans, + samDesired=win32con.KEY_ALL_ACCESS, + Class=classname, +) + +## Newly created key should not be visible from non-transacted handle +subkeys = [s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname not in subkeys + +transacted_subkeys = [s[0] for s in win32api.RegEnumKeyExW(transacted_key)] +assert subkeyname in transacted_subkeys + +## Key should be visible to non-transacted handle after commit +win32transaction.CommitTransaction(trans) +subkeys = [s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname in subkeys + +## test transacted delete +del_trans = win32transaction.CreateTransaction( + Description="test RegDeleteKeyTransacted" +) +win32api.RegDeleteKeyEx(key, subkeyname, Transaction=del_trans) +## subkey should still show up for non-transacted handle +subkeys = [s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname in subkeys +## ... and should be gone after commit +win32transaction.CommitTransaction(del_trans) +subkeys = [s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname not in subkeys + +win32api.RegDeleteKey(win32con.HKEY_CURRENT_USER, keyname) diff --git a/MLPY/Lib/site-packages/win32/Demos/RegRestoreKey.py b/MLPY/Lib/site-packages/win32/Demos/RegRestoreKey.py new file mode 100644 index 0000000000000000000000000000000000000000..69ce32ea6f2489a8bc62b4f26382eeff7e76f0a8 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/RegRestoreKey.py @@ -0,0 +1,71 @@ +import os + +import ntsecuritycon +import win32api +import win32con +import win32security +import winnt + +temp_dir = win32api.GetTempPath() +fname = win32api.GetTempFileName(temp_dir, "rsk")[0] +print(fname) +## file can't exist +os.remove(fname) + +## enable backup and restore privs +required_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_BACKUP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32con.TOKEN_READ | win32con.TOKEN_ADJUST_PRIVILEGES +) +adjusted_privs = win32security.AdjustTokenPrivileges(th, 0, required_privs) + +try: + sa = win32security.SECURITY_ATTRIBUTES() + my_sid = win32security.GetTokenInformation(th, ntsecuritycon.TokenUser)[0] + sa.SECURITY_DESCRIPTOR.SetSecurityDescriptorOwner(my_sid, 0) + + k, disp = win32api.RegCreateKeyEx( + win32con.HKEY_CURRENT_USER, + "Python test key", + SecurityAttributes=sa, + samDesired=win32con.KEY_ALL_ACCESS, + Class="some class", + Options=0, + ) + win32api.RegSetValue(k, None, win32con.REG_SZ, "Default value for python test key") + + subk, disp = win32api.RegCreateKeyEx( + k, + "python test subkey", + SecurityAttributes=sa, + samDesired=win32con.KEY_ALL_ACCESS, + Class="some other class", + Options=0, + ) + win32api.RegSetValue(subk, None, win32con.REG_SZ, "Default value for subkey") + + win32api.RegSaveKeyEx( + k, fname, Flags=winnt.REG_STANDARD_FORMAT, SecurityAttributes=sa + ) + + restored_key, disp = win32api.RegCreateKeyEx( + win32con.HKEY_CURRENT_USER, + "Python test key(restored)", + SecurityAttributes=sa, + samDesired=win32con.KEY_ALL_ACCESS, + Class="restored class", + Options=0, + ) + win32api.RegRestoreKey(restored_key, fname) +finally: + win32security.AdjustTokenPrivileges(th, 0, adjusted_privs) diff --git a/MLPY/Lib/site-packages/win32/Demos/SystemParametersInfo.py b/MLPY/Lib/site-packages/win32/Demos/SystemParametersInfo.py new file mode 100644 index 0000000000000000000000000000000000000000..55a331e6738aa32440f789d58b69848924368fd7 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/SystemParametersInfo.py @@ -0,0 +1,210 @@ +import glob +import os +import time + +import win32api +import win32con +import win32gui + +## some of these tests will fail for systems prior to XP + +for pname in ( + ## Set actions all take an unsigned int in pvParam + "SPI_GETMOUSESPEED", + "SPI_GETACTIVEWNDTRKTIMEOUT", + "SPI_GETCARETWIDTH", + "SPI_GETFOREGROUNDFLASHCOUNT", + "SPI_GETFOREGROUNDLOCKTIMEOUT", + ## Set actions all take an unsigned int in uiParam + "SPI_GETWHEELSCROLLLINES", + "SPI_GETKEYBOARDDELAY", + "SPI_GETKEYBOARDSPEED", + "SPI_GETMOUSEHOVERHEIGHT", + "SPI_GETMOUSEHOVERWIDTH", + "SPI_GETMOUSEHOVERTIME", + "SPI_GETSCREENSAVETIMEOUT", + "SPI_GETMENUSHOWDELAY", + "SPI_GETLOWPOWERTIMEOUT", + "SPI_GETPOWEROFFTIMEOUT", + "SPI_GETBORDER", + ## below are winxp only: + "SPI_GETFONTSMOOTHINGCONTRAST", + "SPI_GETFONTSMOOTHINGTYPE", + "SPI_GETFOCUSBORDERHEIGHT", + "SPI_GETFOCUSBORDERWIDTH", + "SPI_GETMOUSECLICKLOCKTIME", +): + print(pname) + cget = getattr(win32con, pname) + cset = getattr(win32con, pname.replace("_GET", "_SET")) + orig_value = win32gui.SystemParametersInfo(cget) + print("\toriginal setting:", orig_value) + win32gui.SystemParametersInfo(cset, orig_value + 1) + new_value = win32gui.SystemParametersInfo(cget) + print("\tnew value:", new_value) + # On Vista, some of these values seem to be ignored. So only "fail" if + # the new value isn't what we set or the original + if new_value != orig_value + 1: + assert new_value == orig_value + print("Strange - setting %s seems to have been ignored" % (pname,)) + win32gui.SystemParametersInfo(cset, orig_value) + assert win32gui.SystemParametersInfo(cget) == orig_value + + +# these take a boolean value in pvParam +# change to opposite, check that it was changed and change back +for pname in ( + "SPI_GETFLATMENU", + "SPI_GETDROPSHADOW", + "SPI_GETKEYBOARDCUES", + "SPI_GETMENUFADE", + "SPI_GETCOMBOBOXANIMATION", + "SPI_GETCURSORSHADOW", + "SPI_GETGRADIENTCAPTIONS", + "SPI_GETHOTTRACKING", + "SPI_GETLISTBOXSMOOTHSCROLLING", + "SPI_GETMENUANIMATION", + "SPI_GETSELECTIONFADE", + "SPI_GETTOOLTIPANIMATION", + "SPI_GETTOOLTIPFADE", + "SPI_GETUIEFFECTS", + "SPI_GETACTIVEWINDOWTRACKING", + "SPI_GETACTIVEWNDTRKZORDER", +): + print(pname) + cget = getattr(win32con, pname) + cset = getattr(win32con, pname.replace("_GET", "_SET")) + orig_value = win32gui.SystemParametersInfo(cget) + print(orig_value) + win32gui.SystemParametersInfo(cset, not orig_value) + new_value = win32gui.SystemParametersInfo(cget) + print(new_value) + assert orig_value != new_value + win32gui.SystemParametersInfo(cset, orig_value) + assert win32gui.SystemParametersInfo(cget) == orig_value + + +# these take a boolean in uiParam +# could combine with above section now that SystemParametersInfo only takes a single parameter +for pname in ( + "SPI_GETFONTSMOOTHING", + "SPI_GETICONTITLEWRAP", + "SPI_GETBEEP", + "SPI_GETBLOCKSENDINPUTRESETS", + "SPI_GETKEYBOARDPREF", + "SPI_GETSCREENSAVEACTIVE", + "SPI_GETMENUDROPALIGNMENT", + "SPI_GETDRAGFULLWINDOWS", + "SPI_GETSHOWIMEUI", +): + cget = getattr(win32con, pname) + cset = getattr(win32con, pname.replace("_GET", "_SET")) + orig_value = win32gui.SystemParametersInfo(cget) + win32gui.SystemParametersInfo(cset, not orig_value) + new_value = win32gui.SystemParametersInfo(cget) + # Some of these also can't be changed (eg, SPI_GETSCREENSAVEACTIVE) so + # don't actually get upset. + if orig_value != new_value: + print("successfully toggled", pname, "from", orig_value, "to", new_value) + else: + print("couldn't toggle", pname, "from", orig_value) + win32gui.SystemParametersInfo(cset, orig_value) + assert win32gui.SystemParametersInfo(cget) == orig_value + + +print("SPI_GETICONTITLELOGFONT") +lf = win32gui.SystemParametersInfo(win32con.SPI_GETICONTITLELOGFONT) +orig_height = lf.lfHeight +orig_italic = lf.lfItalic +print("Height:", orig_height, "Italic:", orig_italic) +lf.lfHeight += 2 +lf.lfItalic = not lf.lfItalic +win32gui.SystemParametersInfo(win32con.SPI_SETICONTITLELOGFONT, lf) +new_lf = win32gui.SystemParametersInfo(win32con.SPI_GETICONTITLELOGFONT) +print("New Height:", new_lf.lfHeight, "New Italic:", new_lf.lfItalic) +assert new_lf.lfHeight == orig_height + 2 +assert new_lf.lfItalic != orig_italic + +lf.lfHeight = orig_height +lf.lfItalic = orig_italic +win32gui.SystemParametersInfo(win32con.SPI_SETICONTITLELOGFONT, lf) +new_lf = win32gui.SystemParametersInfo(win32con.SPI_GETICONTITLELOGFONT) +assert new_lf.lfHeight == orig_height +assert new_lf.lfItalic == orig_italic + + +print("SPI_GETMOUSEHOVERWIDTH, SPI_GETMOUSEHOVERHEIGHT, SPI_GETMOUSEHOVERTIME") +w = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERWIDTH) +h = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERHEIGHT) +t = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME) +print("w,h,t:", w, h, t) + +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERWIDTH, w + 1) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERHEIGHT, h + 2) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERTIME, t + 3) +new_w = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERWIDTH) +new_h = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERHEIGHT) +new_t = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME) +print("new w,h,t:", new_w, new_h, new_t) +assert new_w == w + 1 +assert new_h == h + 2 +assert new_t == t + 3 + +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERWIDTH, w) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERHEIGHT, h) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERTIME, t) +new_w = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERWIDTH) +new_h = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERHEIGHT) +new_t = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME) +assert new_w == w +assert new_h == h +assert new_t == t + + +print("SPI_SETDOUBLECLKWIDTH, SPI_SETDOUBLECLKHEIGHT") +x = win32api.GetSystemMetrics(win32con.SM_CXDOUBLECLK) +y = win32api.GetSystemMetrics(win32con.SM_CYDOUBLECLK) +print("x,y:", x, y) +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKWIDTH, x + 1) +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKHEIGHT, y + 2) +new_x = win32api.GetSystemMetrics(win32con.SM_CXDOUBLECLK) +new_y = win32api.GetSystemMetrics(win32con.SM_CYDOUBLECLK) +print("new x,y:", new_x, new_y) +assert new_x == x + 1 +assert new_y == y + 2 +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKWIDTH, x) +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKHEIGHT, y) +new_x = win32api.GetSystemMetrics(win32con.SM_CXDOUBLECLK) +new_y = win32api.GetSystemMetrics(win32con.SM_CYDOUBLECLK) +assert new_x == x +assert new_y == y + + +print("SPI_SETDRAGWIDTH, SPI_SETDRAGHEIGHT") +dw = win32api.GetSystemMetrics(win32con.SM_CXDRAG) +dh = win32api.GetSystemMetrics(win32con.SM_CYDRAG) +print("dw,dh:", dw, dh) +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGWIDTH, dw + 1) +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGHEIGHT, dh + 2) +new_dw = win32api.GetSystemMetrics(win32con.SM_CXDRAG) +new_dh = win32api.GetSystemMetrics(win32con.SM_CYDRAG) +print("new dw,dh:", new_dw, new_dh) +assert new_dw == dw + 1 +assert new_dh == dh + 2 +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGWIDTH, dw) +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGHEIGHT, dh) +new_dw = win32api.GetSystemMetrics(win32con.SM_CXDRAG) +new_dh = win32api.GetSystemMetrics(win32con.SM_CYDRAG) +assert new_dw == dw +assert new_dh == dh + + +orig_wallpaper = win32gui.SystemParametersInfo(Action=win32con.SPI_GETDESKWALLPAPER) +print("Original: ", orig_wallpaper) +for bmp in glob.glob(os.path.join(os.environ["windir"], "*.bmp")): + print(bmp) + win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, Param=bmp) + print(win32gui.SystemParametersInfo(Action=win32con.SPI_GETDESKWALLPAPER)) + time.sleep(1) + +win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, Param=orig_wallpaper) diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/BackupRead_BackupWrite.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/BackupRead_BackupWrite.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60f8c72599d3fe4855ef914b21a5161c16129e3a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/BackupRead_BackupWrite.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/BackupSeek_streamheaders.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/BackupSeek_streamheaders.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9afff8dce1c14cb6871e961bfbe852f823f5e46f Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/BackupSeek_streamheaders.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/CopyFileEx.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/CopyFileEx.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2b7b73eba329b44e0b8733044881c12249af7f7c Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/CopyFileEx.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/CreateFileTransacted_MiniVersion.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/CreateFileTransacted_MiniVersion.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c136321cf06fab7583bf9609aaec4f6b48bb9629 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/CreateFileTransacted_MiniVersion.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtFormatMessage.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtFormatMessage.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8941a1e24a0ee6c44a6c16b58e1c2c043ebc891 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtFormatMessage.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtSubscribe_pull.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtSubscribe_pull.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7fe9ddcc697b1891135aaa4f4007f47153bb100 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtSubscribe_pull.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtSubscribe_push.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtSubscribe_push.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53c73fe14f450419592c94cba38fa2806f9301fd Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/EvtSubscribe_push.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/FileSecurityTest.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/FileSecurityTest.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f66765c4af3f6db8778945fd7344e531ee010ce Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/FileSecurityTest.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/GetSaveFileName.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/GetSaveFileName.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15a8d956792c4a846685eaa427aaede65db93bf9 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/GetSaveFileName.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/NetValidatePasswordPolicy.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/NetValidatePasswordPolicy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bed74023ac772ee54b8eb86b8fe56618821f448 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/NetValidatePasswordPolicy.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/OpenEncryptedFileRaw.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/OpenEncryptedFileRaw.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ec623a771e7e959c8a047fed7de224d08c71929 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/OpenEncryptedFileRaw.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/RegCreateKeyTransacted.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/RegCreateKeyTransacted.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c39abacf6d7d44fd0daf929ff1b016e8326cce3 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/RegCreateKeyTransacted.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/RegRestoreKey.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/RegRestoreKey.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60063de7f919dd5d9a55569ad981873c753600b5 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/RegRestoreKey.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/SystemParametersInfo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/SystemParametersInfo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e45c4734884fbbeb53a23b580c12fa2d736cc420 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/SystemParametersInfo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/cerapi.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/cerapi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c5bd60da3326a8cd4b484d2bcc546bb44941d8e1 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/cerapi.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/desktopmanager.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/desktopmanager.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2645322cd7b34ee4085ee8e518a8b82f4b879f1a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/desktopmanager.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/eventLogDemo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/eventLogDemo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..25ca8f4b8a17ee018eb60c42f38e219c40b60b6a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/eventLogDemo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/getfilever.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/getfilever.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59b26402e13b72368e5c7a1e8bce9672be2748e6 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/getfilever.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/mmapfile_demo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/mmapfile_demo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb0eeccce0aa4285f4fca105d60a58f827993c6f Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/mmapfile_demo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/print_desktop.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/print_desktop.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..44474281713694aae2adb26f23a6b655aefe8104 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/print_desktop.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/rastest.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/rastest.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..902b1448fb6fdc37391e9e3126b116e1490f862e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/rastest.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/timer_demo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/timer_demo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a5357b32cbff360aafd00810f1dc5fbff7c1ce67 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/timer_demo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32clipboardDemo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32clipboardDemo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..789772af2130a8b81699c1bad3c03b64136f814e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32clipboardDemo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32clipboard_bitmapdemo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32clipboard_bitmapdemo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6daa93e933c839867788a3003fc8677d623dd702 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32clipboard_bitmapdemo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32comport_demo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32comport_demo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e770590aea76699c115dfcf93549dd7d92e43f8 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32comport_demo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32console_demo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32console_demo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fe7beb50675a6e2bd68f0ab71cef015ca86d223 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32console_demo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32cred_demo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32cred_demo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32b2a2788c24ec323866723511a361bc03e3d97e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32cred_demo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32fileDemo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32fileDemo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..17eb6f5929054cde3145ccde7f38f40a583aea67 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32fileDemo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_demo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_demo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3f0c4b4c760879224c0bb4a5a3a61fb092886a8 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_demo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_devicenotify.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_devicenotify.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..788e46b7eae00f3057a46249bdcf7840e3696fa1 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_devicenotify.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_dialog.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_dialog.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bce6f4662fd040eb7f5a89b5b490b58ad03ba36 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_dialog.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_menu.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_menu.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c22a0ee47ed7056b01650787f99b36a5d1d039d6 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_menu.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_taskbar.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_taskbar.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a27c30062a019020dc69e28416e8a68d7d0977a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32gui_taskbar.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32netdemo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32netdemo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f788dce30731a076427d0cb5449079b1364f38f2 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32netdemo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32rcparser_demo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32rcparser_demo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..504bd517e0d1e71f389ce8a3cb3e99e207973498 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32rcparser_demo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32servicedemo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32servicedemo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccfb7def55a5e9f28c504e36bec522f658dd7a2e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32servicedemo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32ts_logoff_disconnected.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32ts_logoff_disconnected.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4f51ecbc9d8775520058a53b3f6d21aafc05a74 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/win32ts_logoff_disconnected.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/__pycache__/winprocess.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/__pycache__/winprocess.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d616f2c59e144fc350694954cde2a1c4d8426841 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/__pycache__/winprocess.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/c_extension/__pycache__/setup.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/c_extension/__pycache__/setup.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d05b0529633e77eebc64f2a6963b6bf30af45a9 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/c_extension/__pycache__/setup.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/c_extension/setup.py b/MLPY/Lib/site-packages/win32/Demos/c_extension/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..6f5cb41769875b5296daa1f88cd5125e2abbe290 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/c_extension/setup.py @@ -0,0 +1,26 @@ +# A sample distutils script to show to build your own +# extension module which extends pywintypes or pythoncom. +# +# Use 'python setup.py build' to build this extension. +import os +from distutils.core import Extension, setup +from sysconfig import get_paths + +sources = ["win32_extension.cpp"] +lib_dir = get_paths()["platlib"] + +# Specify the directory where the PyWin32 .h and .lib files are installed. +# If you are doing a win32com extension, you will also need to add +# win32com\Include and win32com\Libs. +ext = Extension( + "win32_extension", + sources, + include_dirs=[os.path.join(lib_dir, "win32", "include")], + library_dirs=[os.path.join(lib_dir, "win32", "libs")], +) + +setup( + name="win32 extension sample", + version="0.1", + ext_modules=[ext], +) diff --git a/MLPY/Lib/site-packages/win32/Demos/cerapi.py b/MLPY/Lib/site-packages/win32/Demos/cerapi.py new file mode 100644 index 0000000000000000000000000000000000000000..c5d93166013c6672d6b4c9c0979079878d2e66b7 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/cerapi.py @@ -0,0 +1,254 @@ +# A demo of the Windows CE Remote API +# +# This connects to a CE device, and interacts with it. + +import getopt +import os +import sys + +import win32api +import win32con +import win32event +import wincerapi + + +def DumpPythonRegistry(): + try: + h = wincerapi.CeRegOpenKeyEx( + win32con.HKEY_LOCAL_MACHINE, + "Software\\Python\\PythonCore\\%s\\PythonPath" % sys.winver, + ) + except win32api.error: + print("The remote device does not appear to have Python installed") + return 0 + path, typ = wincerapi.CeRegQueryValueEx(h, None) + print("The remote PythonPath is '%s'" % (str(path),)) + h.Close() + return 1 + + +def DumpRegistry(root, level=0): + # A recursive dump of the remote registry to test most functions. + h = wincerapi.CeRegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, None) + level_prefix = " " * level + index = 0 + # Enumerate values. + while 1: + try: + name, data, typ = wincerapi.CeRegEnumValue(root, index) + except win32api.error: + break + print("%s%s=%s" % (level_prefix, name, repr(str(data)))) + index = index + 1 + # Now enumerate all keys. + index = 0 + while 1: + try: + name, klass = wincerapi.CeRegEnumKeyEx(root, index) + except win32api.error: + break + print("%s%s\\" % (level_prefix, name)) + subkey = wincerapi.CeRegOpenKeyEx(root, name) + DumpRegistry(subkey, level + 1) + index = index + 1 + + +def DemoCopyFile(): + # Create a file on the device, and write a string. + cefile = wincerapi.CeCreateFile( + "TestPython", win32con.GENERIC_WRITE, 0, None, win32con.OPEN_ALWAYS, 0, None + ) + wincerapi.CeWriteFile(cefile, "Hello from Python") + cefile.Close() + # reopen the file and check the data. + cefile = wincerapi.CeCreateFile( + "TestPython", win32con.GENERIC_READ, 0, None, win32con.OPEN_EXISTING, 0, None + ) + if wincerapi.CeReadFile(cefile, 100) != "Hello from Python": + print("Couldnt read the data from the device!") + cefile.Close() + # Delete the test file + wincerapi.CeDeleteFile("TestPython") + print("Created, wrote to, read from and deleted a test file!") + + +def DemoCreateProcess(): + try: + hp, ht, pid, tid = wincerapi.CeCreateProcess( + "Windows\\Python.exe", "", None, None, 0, 0, None, "", None + ) + + # Not necessary, except to see if handle closing raises an exception + # (if auto-closed, the error is suppressed) + hp.Close() + ht.Close() + print("Python is running on the remote device!") + except win32api.error as xxx_todo_changeme1: + (hr, fn, msg) = xxx_todo_changeme1.args + print("Couldnt execute remote process -", msg) + + +def DumpRemoteMachineStatus(): + ( + ACLineStatus, + BatteryFlag, + BatteryLifePercent, + BatteryLifeTime, + BatteryFullLifeTime, + BackupBatteryFlag, + BackupBatteryLifePercent, + BackupBatteryLifeTime, + BackupBatteryLifeTime, + ) = wincerapi.CeGetSystemPowerStatusEx() + if ACLineStatus: + power = "AC" + else: + power = "battery" + if BatteryLifePercent == 255: + batPerc = "unknown" + else: + batPerc = BatteryLifePercent + print( + "The batteries are at %s%%, and is currently being powered by %s" + % (batPerc, power) + ) + + ( + memLoad, + totalPhys, + availPhys, + totalPage, + availPage, + totalVirt, + availVirt, + ) = wincerapi.CeGlobalMemoryStatus() + + print("The memory is %d%% utilized." % (memLoad)) + print("%-20s%-10s%-10s" % ("", "Total", "Avail")) + print("%-20s%-10s%-10s" % ("Physical Memory", totalPhys, availPhys)) + print("%-20s%-10s%-10s" % ("Virtual Memory", totalVirt, availVirt)) + print("%-20s%-10s%-10s" % ("Paging file", totalPage, availPage)) + + storeSize, freeSize = wincerapi.CeGetStoreInformation() + print("%-20s%-10s%-10s" % ("File store", storeSize, freeSize)) + + print("The CE temp path is", wincerapi.CeGetTempPath()) + print("The system info for the device is", wincerapi.CeGetSystemInfo()) + + +def DumpRemoteFolders(): + # Dump all special folders possible. + for name, val in list(wincerapi.__dict__.items()): + if name[:6] == "CSIDL_": + try: + loc = str(wincerapi.CeGetSpecialFolderPath(val)) + print("Folder %s is at %s" % (name, loc)) + except win32api.error as details: + pass + + # Get the shortcut targets for the "Start Menu" + print("Dumping start menu shortcuts...") + try: + startMenu = str(wincerapi.CeGetSpecialFolderPath(wincerapi.CSIDL_STARTMENU)) + except win32api.error as details: + print("This device has no start menu!", details) + startMenu = None + + if startMenu: + for fileAttr in wincerapi.CeFindFiles(os.path.join(startMenu, "*")): + fileName = fileAttr[8] + fullPath = os.path.join(startMenu, str(fileName)) + try: + resolved = wincerapi.CeSHGetShortcutTarget(fullPath) + except win32api.error as xxx_todo_changeme: + (rc, fn, msg) = xxx_todo_changeme.args + resolved = "#Error - %s" % msg + print("%s->%s" % (fileName, resolved)) + + # print "The start menu is at", + # print wincerapi.CeSHGetShortcutTarget("\\Windows\\Start Menu\\Shortcut to Python.exe.lnk") + + +def usage(): + print("Options:") + print("-a - Execute all demos") + print("-p - Execute Python process on remote device") + print("-r - Dump the remote registry") + print("-f - Dump all remote special folder locations") + print("-s - Dont dump machine status") + print("-y - Perform asynch init of CE connection") + + +def main(): + async_init = bStartPython = bDumpRegistry = bDumpFolders = 0 + bDumpStatus = 1 + try: + opts, args = getopt.getopt(sys.argv[1:], "apr") + except getopt.error as why: + print("Invalid usage:", why) + usage() + return + + for o, v in opts: + if o == "-a": + bStartPython = bDumpRegistry = bDumpStatus = bDumpFolders = asynch_init = 1 + if o == "-p": + bStartPython = 1 + if o == "-r": + bDumpRegistry = 1 + if o == "-s": + bDumpStatus = 0 + if o == "-f": + bDumpFolders = 1 + if o == "-y": + print("Doing asynch init of CE connection") + async_init = 1 + + if async_init: + event, rc = wincerapi.CeRapiInitEx() + while 1: + rc = win32event.WaitForSingleObject(event, 500) + if rc == win32event.WAIT_OBJECT_0: + # We connected. + break + else: + print( + "Waiting for Initialize to complete (picture a Cancel button here :)" + ) + else: + wincerapi.CeRapiInit() + print("Connected to remote CE device.") + try: + verinfo = wincerapi.CeGetVersionEx() + print( + "The device is running windows CE version %d.%d - %s" + % (verinfo[0], verinfo[1], verinfo[4]) + ) + + if bDumpStatus: + print("Dumping remote machine status") + DumpRemoteMachineStatus() + + if bDumpRegistry: + print("Dumping remote registry...") + DumpRegistry(win32con.HKEY_LOCAL_MACHINE) + + if bDumpFolders: + print("Dumping remote folder information") + DumpRemoteFolders() + + DemoCopyFile() + if bStartPython: + print("Starting remote Python process") + if DumpPythonRegistry(): + DemoCreateProcess() + else: + print("Not trying to start Python, as it's not installed") + + finally: + wincerapi.CeRapiUninit() + print("Disconnected") + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/dde/__pycache__/ddeclient.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/dde/__pycache__/ddeclient.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e1cf33fd74ab8158a6a9077399a9c4354190a5b Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/dde/__pycache__/ddeclient.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/dde/__pycache__/ddeserver.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/dde/__pycache__/ddeserver.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a6783abb596c9356bbdc456e378463be1c39e097 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/dde/__pycache__/ddeserver.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/dde/ddeclient.py b/MLPY/Lib/site-packages/win32/Demos/dde/ddeclient.py new file mode 100644 index 0000000000000000000000000000000000000000..32af3130ffe9dfd97164a36a045f09955abc7702 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/dde/ddeclient.py @@ -0,0 +1,18 @@ +# 'Request' example added jjk 11/20/98 + +import dde +import win32ui + +server = dde.CreateServer() +server.Create("TestClient") + +conversation = dde.CreateConversation(server) + +conversation.ConnectTo("RunAny", "RunAnyCommand") +conversation.Exec("DoSomething") +conversation.Exec("DoSomethingElse") + +conversation.ConnectTo("RunAny", "ComputeStringLength") +s = "abcdefghi" +sl = conversation.Request(s) +print('length of "%s" is %s' % (s, sl)) diff --git a/MLPY/Lib/site-packages/win32/Demos/dde/ddeserver.py b/MLPY/Lib/site-packages/win32/Demos/dde/ddeserver.py new file mode 100644 index 0000000000000000000000000000000000000000..0374827f0112299b2d657c17dc39ef72be1150dc --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/dde/ddeserver.py @@ -0,0 +1,42 @@ +# 'Request' example added jjk 11/20/98 + +import dde +import win32ui +from pywin.mfc import object + + +class MySystemTopic(object.Object): + def __init__(self): + object.Object.__init__(self, dde.CreateServerSystemTopic()) + + def Exec(self, cmd): + print("System Topic asked to exec", cmd) + + +class MyOtherTopic(object.Object): + def __init__(self, topicName): + object.Object.__init__(self, dde.CreateTopic(topicName)) + + def Exec(self, cmd): + print("Other Topic asked to exec", cmd) + + +class MyRequestTopic(object.Object): + def __init__(self, topicName): + topic = dde.CreateTopic(topicName) + topic.AddItem(dde.CreateStringItem("")) + object.Object.__init__(self, topic) + + def Request(self, aString): + print("Request Topic asked to compute length of:", aString) + return str(len(aString)) + + +server = dde.CreateServer() +server.AddTopic(MySystemTopic()) +server.AddTopic(MyOtherTopic("RunAnyCommand")) +server.AddTopic(MyRequestTopic("ComputeStringLength")) +server.Create("RunAny") + +while 1: + win32ui.PumpWaitingMessages(0, -1) diff --git a/MLPY/Lib/site-packages/win32/Demos/desktopmanager.py b/MLPY/Lib/site-packages/win32/Demos/desktopmanager.py new file mode 100644 index 0000000000000000000000000000000000000000..6ffaf2a94b9e8b19a5f0c3a76d7d20ff02907da7 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/desktopmanager.py @@ -0,0 +1,246 @@ +# Demonstrates using a taskbar icon to create and navigate between desktops + +import _thread +import io +import time +import traceback + +import pywintypes +import win32api +import win32con +import win32gui +import win32process +import win32service + +## "Shell_TrayWnd" is class of system tray window, broadcasts "TaskbarCreated" when initialized + + +def desktop_name_dlgproc(hwnd, msg, wparam, lparam): + """Handles messages from the desktop name dialog box""" + if msg in (win32con.WM_CLOSE, win32con.WM_DESTROY): + win32gui.DestroyWindow(hwnd) + elif msg == win32con.WM_COMMAND: + if wparam == win32con.IDOK: + desktop_name = win32gui.GetDlgItemText(hwnd, 72) + print("new desktop name: ", desktop_name) + win32gui.DestroyWindow(hwnd) + create_desktop(desktop_name) + + elif wparam == win32con.IDCANCEL: + win32gui.DestroyWindow(hwnd) + + +def get_new_desktop_name(parent_hwnd): + """Create a dialog box to ask the user for name of desktop to be created""" + msgs = { + win32con.WM_COMMAND: desktop_name_dlgproc, + win32con.WM_CLOSE: desktop_name_dlgproc, + win32con.WM_DESTROY: desktop_name_dlgproc, + } + # dlg item [type, caption, id, (x,y,cx,cy), style, ex style + style = ( + win32con.WS_BORDER + | win32con.WS_VISIBLE + | win32con.WS_CAPTION + | win32con.WS_SYSMENU + ) ## |win32con.DS_SYSMODAL + h = win32gui.CreateDialogIndirect( + win32api.GetModuleHandle(None), + [ + ["One ugly dialog box !", (100, 100, 200, 100), style, 0], + [ + "Button", + "Create", + win32con.IDOK, + (10, 10, 30, 20), + win32con.WS_VISIBLE + | win32con.WS_TABSTOP + | win32con.BS_HOLLOW + | win32con.BS_DEFPUSHBUTTON, + ], + [ + "Button", + "Never mind", + win32con.IDCANCEL, + (45, 10, 50, 20), + win32con.WS_VISIBLE | win32con.WS_TABSTOP | win32con.BS_HOLLOW, + ], + ["Static", "Desktop name:", 71, (10, 40, 70, 10), win32con.WS_VISIBLE], + ["Edit", "", 72, (75, 40, 90, 10), win32con.WS_VISIBLE], + ], + parent_hwnd, + msgs, + ) ## parent_hwnd, msgs) + + win32gui.EnableWindow(h, True) + hcontrol = win32gui.GetDlgItem(h, 72) + win32gui.EnableWindow(hcontrol, True) + win32gui.SetFocus(hcontrol) + + +def new_icon(hdesk, desktop_name): + """Runs as a thread on each desktop to create a new tray icon and handle its messages""" + global id + id = id + 1 + hdesk.SetThreadDesktop() + ## apparently the threads can't use same hinst, so each needs its own window class + windowclassname = "PythonDesktopManager" + desktop_name + wc = win32gui.WNDCLASS() + wc.hInstance = win32api.GetModuleHandle(None) + wc.lpszClassName = windowclassname + wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW | win32con.CS_GLOBALCLASS + wc.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW) + wc.hbrBackground = win32con.COLOR_WINDOW + wc.lpfnWndProc = icon_wndproc + windowclass = win32gui.RegisterClass(wc) + style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU + hwnd = win32gui.CreateWindow( + windowclass, + "dm_" + desktop_name, + win32con.WS_SYSMENU, + 0, + 0, + win32con.CW_USEDEFAULT, + win32con.CW_USEDEFAULT, + 0, + 0, + wc.hInstance, + None, + ) + win32gui.UpdateWindow(hwnd) + flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP + notify_info = ( + hwnd, + id, + flags, + win32con.WM_USER + 20, + hicon, + "Desktop Manager (%s)" % desktop_name, + ) + window_info[hwnd] = notify_info + ## wait for explorer to initialize system tray for new desktop + tray_found = 0 + while not tray_found: + try: + tray_found = win32gui.FindWindow("Shell_TrayWnd", None) + except win32gui.error: + traceback.print_exc + time.sleep(0.5) + win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, notify_info) + win32gui.PumpMessages() + + +def create_desktop(desktop_name, start_explorer=1): + """Creates a new desktop and spawns a thread running on it + Will also start a new icon thread on an existing desktop + """ + sa = pywintypes.SECURITY_ATTRIBUTES() + sa.bInheritHandle = 1 + + try: + hdesk = win32service.CreateDesktop( + desktop_name, 0, win32con.MAXIMUM_ALLOWED, sa + ) + except win32service.error: + traceback.print_exc() + errbuf = io.StringIO() + traceback.print_exc(None, errbuf) + win32api.MessageBox(0, errbuf.getvalue(), "Desktop creation failed") + return + if start_explorer: + s = win32process.STARTUPINFO() + s.lpDesktop = desktop_name + prc_info = win32process.CreateProcess( + None, + "Explorer.exe", + None, + None, + True, + win32con.CREATE_NEW_CONSOLE, + None, + "c:\\", + s, + ) + + th = _thread.start_new_thread(new_icon, (hdesk, desktop_name)) + hdesk.SwitchDesktop() + + +def icon_wndproc(hwnd, msg, wp, lp): + """Window proc for the tray icons""" + if lp == win32con.WM_LBUTTONDOWN: + ## popup menu won't disappear if you don't do this + win32gui.SetForegroundWindow(hwnd) + + curr_desktop = win32service.OpenInputDesktop(0, True, win32con.MAXIMUM_ALLOWED) + curr_desktop_name = win32service.GetUserObjectInformation( + curr_desktop, win32con.UOI_NAME + ) + winsta = win32service.GetProcessWindowStation() + desktops = winsta.EnumDesktops() + m = win32gui.CreatePopupMenu() + desktop_cnt = len(desktops) + ## *don't* create an item 0 + for d in range(1, desktop_cnt + 1): + mf_flags = win32con.MF_STRING + ## if you switch to winlogon yourself, there's nothing there and you're stuck + if desktops[d - 1].lower() in ("winlogon", "disconnect"): + mf_flags = mf_flags | win32con.MF_GRAYED | win32con.MF_DISABLED + if desktops[d - 1] == curr_desktop_name: + mf_flags = mf_flags | win32con.MF_CHECKED + win32gui.AppendMenu(m, mf_flags, d, desktops[d - 1]) + win32gui.AppendMenu(m, win32con.MF_STRING, desktop_cnt + 1, "Create new ...") + win32gui.AppendMenu(m, win32con.MF_STRING, desktop_cnt + 2, "Exit") + + x, y = win32gui.GetCursorPos() + d = win32gui.TrackPopupMenu( + m, + win32con.TPM_LEFTBUTTON | win32con.TPM_RETURNCMD | win32con.TPM_NONOTIFY, + x, + y, + 0, + hwnd, + None, + ) + win32gui.PumpWaitingMessages() + win32gui.DestroyMenu(m) + if d == desktop_cnt + 1: ## Create new + get_new_desktop_name(hwnd) + elif d == desktop_cnt + 2: ## Exit + win32gui.PostQuitMessage(0) + win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, window_info[hwnd]) + del window_info[hwnd] + origin_desktop.SwitchDesktop() + elif d > 0: + hdesk = win32service.OpenDesktop( + desktops[d - 1], 0, 0, win32con.MAXIMUM_ALLOWED + ) + hdesk.SwitchDesktop() + return 0 + else: + return win32gui.DefWindowProc(hwnd, msg, wp, lp) + + +window_info = {} +origin_desktop = win32service.OpenInputDesktop(0, True, win32con.MAXIMUM_ALLOWED) +origin_desktop_name = win32service.GetUserObjectInformation( + origin_desktop, win32service.UOI_NAME +) + +hinst = win32api.GetModuleHandle(None) +try: + hicon = win32gui.LoadIcon(hinst, 1) ## python.exe and pythonw.exe +except win32gui.error: + hicon = win32gui.LoadIcon(hinst, 135) ## pythonwin's icon +id = 0 + +create_desktop(str(origin_desktop_name), 0) + +## wait for first thread to initialize its icon +while not window_info: + time.sleep(1) + +## exit when last tray icon goes away +while window_info: + win32gui.PumpWaitingMessages() + time.sleep(3) diff --git a/MLPY/Lib/site-packages/win32/Demos/eventLogDemo.py b/MLPY/Lib/site-packages/win32/Demos/eventLogDemo.py new file mode 100644 index 0000000000000000000000000000000000000000..8d4220b070d2e68bbddd7c310e9aba5c7c8678da --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/eventLogDemo.py @@ -0,0 +1,142 @@ +import win32api # To translate NT Sids to account names. +import win32con +import win32evtlog +import win32evtlogutil +import win32security + + +def ReadLog(computer, logType="Application", dumpEachRecord=0): + # read the entire log back. + h = win32evtlog.OpenEventLog(computer, logType) + numRecords = win32evtlog.GetNumberOfEventLogRecords(h) + # print "There are %d records" % numRecords + + num = 0 + while 1: + objects = win32evtlog.ReadEventLog( + h, + win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ, + 0, + ) + if not objects: + break + for object in objects: + # get it for testing purposes, but dont print it. + msg = win32evtlogutil.SafeFormatMessage(object, logType) + if object.Sid is not None: + try: + domain, user, typ = win32security.LookupAccountSid( + computer, object.Sid + ) + sidDesc = "%s/%s" % (domain, user) + except win32security.error: + sidDesc = str(object.Sid) + user_desc = "Event associated with user %s" % (sidDesc,) + else: + user_desc = None + if dumpEachRecord: + print( + "Event record from %r generated at %s" + % (object.SourceName, object.TimeGenerated.Format()) + ) + if user_desc: + print(user_desc) + try: + print(msg) + except UnicodeError: + print("(unicode error printing message: repr() follows...)") + print(repr(msg)) + + num = num + len(objects) + + if numRecords == num: + print("Successfully read all", numRecords, "records") + else: + print( + "Couldn't get all records - reported %d, but found %d" % (numRecords, num) + ) + print( + "(Note that some other app may have written records while we were running!)" + ) + win32evtlog.CloseEventLog(h) + + +def usage(): + print("Writes an event to the event log.") + print("-w : Dont write any test records.") + print("-r : Dont read the event log") + print("-c : computerName : Process the log on the specified computer") + print("-v : Verbose") + print("-t : LogType - Use the specified log - default = 'Application'") + + +def test(): + # check if running on Windows NT, if not, display notice and terminate + if win32api.GetVersion() & 0x80000000: + print("This sample only runs on NT") + return + + import getopt + import sys + + opts, args = getopt.getopt(sys.argv[1:], "rwh?c:t:v") + computer = None + do_read = do_write = 1 + + logType = "Application" + verbose = 0 + + if len(args) > 0: + print("Invalid args") + usage() + return 1 + for opt, val in opts: + if opt == "-t": + logType = val + if opt == "-c": + computer = val + if opt in ["-h", "-?"]: + usage() + return + if opt == "-r": + do_read = 0 + if opt == "-w": + do_write = 0 + if opt == "-v": + verbose = verbose + 1 + if do_write: + ph = win32api.GetCurrentProcess() + th = win32security.OpenProcessToken(ph, win32con.TOKEN_READ) + my_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0] + + win32evtlogutil.ReportEvent( + logType, + 2, + strings=["The message text for event 2", "Another insert"], + data="Raw\0Data".encode("ascii"), + sid=my_sid, + ) + win32evtlogutil.ReportEvent( + logType, + 1, + eventType=win32evtlog.EVENTLOG_WARNING_TYPE, + strings=["A warning", "An even more dire warning"], + data="Raw\0Data".encode("ascii"), + sid=my_sid, + ) + win32evtlogutil.ReportEvent( + logType, + 1, + eventType=win32evtlog.EVENTLOG_INFORMATION_TYPE, + strings=["An info", "Too much info"], + data="Raw\0Data".encode("ascii"), + sid=my_sid, + ) + print("Successfully wrote 3 records to the log") + + if do_read: + ReadLog(computer, logType, verbose > 0) + + +if __name__ == "__main__": + test() diff --git a/MLPY/Lib/site-packages/win32/Demos/getfilever.py b/MLPY/Lib/site-packages/win32/Demos/getfilever.py new file mode 100644 index 0000000000000000000000000000000000000000..721e72f35d558a0de24d59a4de6eecc9f3f42eb5 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/getfilever.py @@ -0,0 +1,33 @@ +import os + +import win32api + +ver_strings = ( + "Comments", + "InternalName", + "ProductName", + "CompanyName", + "LegalCopyright", + "ProductVersion", + "FileDescription", + "LegalTrademarks", + "PrivateBuild", + "FileVersion", + "OriginalFilename", + "SpecialBuild", +) +fname = os.environ["comspec"] +d = win32api.GetFileVersionInfo(fname, "\\") +## backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc +for n, v in d.items(): + print(n, v) + +pairs = win32api.GetFileVersionInfo(fname, "\\VarFileInfo\\Translation") +## \VarFileInfo\Translation returns list of available (language, codepage) pairs that can be used to retreive string info +## any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle two are language/codepage pair returned from above +for lang, codepage in pairs: + print("lang: ", lang, "codepage:", codepage) + for ver_string in ver_strings: + str_info = "\\StringFileInfo\\%04X%04X\\%s" % (lang, codepage, ver_string) + ## print str_info + print(ver_string, repr(win32api.GetFileVersionInfo(fname, str_info))) diff --git a/MLPY/Lib/site-packages/win32/Demos/images/frowny.bmp b/MLPY/Lib/site-packages/win32/Demos/images/frowny.bmp new file mode 100644 index 0000000000000000000000000000000000000000..43e7621e2e081bc6200523f459f6d803d3133eaa Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/images/frowny.bmp differ diff --git a/MLPY/Lib/site-packages/win32/Demos/images/smiley.bmp b/MLPY/Lib/site-packages/win32/Demos/images/smiley.bmp new file mode 100644 index 0000000000000000000000000000000000000000..12ed5dee2d1df987c6c3bd5d134e6075ff160c39 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/images/smiley.bmp differ diff --git a/MLPY/Lib/site-packages/win32/Demos/mmapfile_demo.py b/MLPY/Lib/site-packages/win32/Demos/mmapfile_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..9068ce72fd00170d7f84f213264fb552df238fb1 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/mmapfile_demo.py @@ -0,0 +1,102 @@ +import os +import tempfile + +import mmapfile +import win32api +import winerror +from pywin32_testutil import str2bytes + +system_info = win32api.GetSystemInfo() +page_size = system_info[1] +alloc_size = system_info[7] + +fname = tempfile.mktemp() +mapping_name = os.path.split(fname)[1] +fsize = 8 * page_size +print(fname, fsize, mapping_name) + +m1 = mmapfile.mmapfile(File=fname, Name=mapping_name, MaximumSize=fsize) +m1.seek(100) +m1.write_byte(str2bytes("?")) +m1.seek(-1, 1) +assert m1.read_byte() == str2bytes("?") + +## A reopened named mapping should have exact same size as original mapping +m2 = mmapfile.mmapfile(Name=mapping_name, File=None, MaximumSize=fsize * 2) +assert m2.size() == m1.size() +m1.seek(0, 0) +m1.write(fsize * str2bytes("s")) +assert m2.read(fsize) == fsize * str2bytes("s") + +move_src = 100 +move_dest = 500 +move_size = 150 + +m2.seek(move_src, 0) +assert m2.tell() == move_src +m2.write(str2bytes("m") * move_size) +m2.move(move_dest, move_src, move_size) +m2.seek(move_dest, 0) +assert m2.read(move_size) == str2bytes("m") * move_size +## m2.write('x'* (fsize+1)) + +m2.close() +m1.resize(fsize * 2) +assert m1.size() == fsize * 2 +m1.seek(fsize) +m1.write(str2bytes("w") * fsize) +m1.flush() +m1.close() +os.remove(fname) + + +## Test a file with size larger than 32 bits +## need 10 GB free on drive where your temp folder lives +fname_large = tempfile.mktemp() +mapping_name = "Pywin32_large_mmap" +offsetdata = str2bytes("This is start of offset") + +## Deliberately use odd numbers to test rounding logic +fsize = (1024 * 1024 * 1024 * 10) + 333 +offset = (1024 * 1024 * 32) + 42 +view_size = (1024 * 1024 * 16) + 111 + +## round mapping size and view size up to multiple of system page size +if fsize % page_size: + fsize += page_size - (fsize % page_size) +if view_size % page_size: + view_size += page_size - (view_size % page_size) +## round offset down to multiple of allocation granularity +offset -= offset % alloc_size + +m1 = None +m2 = None +try: + try: + m1 = mmapfile.mmapfile(fname_large, mapping_name, fsize, 0, offset * 2) + except mmapfile.error as exc: + # if we don't have enough disk-space, that's OK. + if exc.winerror != winerror.ERROR_DISK_FULL: + raise + print("skipping large file test - need", fsize, "available bytes.") + else: + m1.seek(offset) + m1.write(offsetdata) + + ## When reopening an existing mapping without passing a file handle, you have + ## to specify a positive size even though it's ignored + m2 = mmapfile.mmapfile( + File=None, + Name=mapping_name, + MaximumSize=1, + FileOffset=offset, + NumberOfBytesToMap=view_size, + ) + assert m2.read(len(offsetdata)) == offsetdata +finally: + if m1 is not None: + m1.close() + if m2 is not None: + m2.close() + if os.path.exists(fname_large): + os.remove(fname_large) diff --git a/MLPY/Lib/site-packages/win32/Demos/pipes/__pycache__/cat.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/pipes/__pycache__/cat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23d0acb4835ef0df1a78271cab8b3f86c1ff3646 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/pipes/__pycache__/cat.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/pipes/__pycache__/runproc.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/pipes/__pycache__/runproc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a8744318a4a53f8cb0247a87671b0ee786dbfbb Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/pipes/__pycache__/runproc.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/pipes/cat.py b/MLPY/Lib/site-packages/win32/Demos/pipes/cat.py new file mode 100644 index 0000000000000000000000000000000000000000..13b6400a5854afaf2ebbb19774f4009ee86c0729 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/pipes/cat.py @@ -0,0 +1,17 @@ +"""cat.py +a version of unix cat, tweaked to show off runproc.py +""" + +import sys + +data = sys.stdin.read(1) +sys.stdout.write(data) +sys.stdout.flush() +while data: + data = sys.stdin.read(1) + sys.stdout.write(data) + sys.stdout.flush() +# Just here to have something to read from stderr. +sys.stderr.write("Blah...") + +# end of cat.py diff --git a/MLPY/Lib/site-packages/win32/Demos/pipes/runproc.py b/MLPY/Lib/site-packages/win32/Demos/pipes/runproc.py new file mode 100644 index 0000000000000000000000000000000000000000..2ed02dd3da1cef049cf46cd3d131a864c9b7fefb --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/pipes/runproc.py @@ -0,0 +1,114 @@ +"""runproc.py + +start a process with three inherited pipes. +Try to write to and read from those. +""" + +import msvcrt +import os + +import win32api +import win32con +import win32file +import win32pipe +import win32process +import win32security + + +class Process: + def run(self, cmdline): + # security attributes for pipes + sAttrs = win32security.SECURITY_ATTRIBUTES() + sAttrs.bInheritHandle = 1 + + # create pipes + hStdin_r, self.hStdin_w = win32pipe.CreatePipe(sAttrs, 0) + self.hStdout_r, hStdout_w = win32pipe.CreatePipe(sAttrs, 0) + self.hStderr_r, hStderr_w = win32pipe.CreatePipe(sAttrs, 0) + + # set the info structure for the new process. + StartupInfo = win32process.STARTUPINFO() + StartupInfo.hStdInput = hStdin_r + StartupInfo.hStdOutput = hStdout_w + StartupInfo.hStdError = hStderr_w + StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES + # Mark doesn't support wShowWindow yet. + # StartupInfo.dwFlags = StartupInfo.dwFlags | win32process.STARTF_USESHOWWINDOW + # StartupInfo.wShowWindow = win32con.SW_HIDE + + # Create new output read handles and the input write handle. Set + # the inheritance properties to FALSE. Otherwise, the child inherits + # the these handles; resulting in non-closeable handles to the pipes + # being created. + pid = win32api.GetCurrentProcess() + + tmp = win32api.DuplicateHandle( + pid, + self.hStdin_w, + pid, + 0, + 0, # non-inheritable!! + win32con.DUPLICATE_SAME_ACCESS, + ) + # Close the inhertible version of the handle + win32file.CloseHandle(self.hStdin_w) + self.hStdin_w = tmp + tmp = win32api.DuplicateHandle( + pid, + self.hStdout_r, + pid, + 0, + 0, # non-inheritable! + win32con.DUPLICATE_SAME_ACCESS, + ) + # Close the inhertible version of the handle + win32file.CloseHandle(self.hStdout_r) + self.hStdout_r = tmp + + # start the process. + hProcess, hThread, dwPid, dwTid = win32process.CreateProcess( + None, # program + cmdline, # command line + None, # process security attributes + None, # thread attributes + 1, # inherit handles, or USESTDHANDLES won't work. + # creation flags. Don't access the console. + 0, # Don't need anything here. + # If you're in a GUI app, you should use + # CREATE_NEW_CONSOLE here, or any subprocesses + # might fall victim to the problem described in: + # KB article: Q156755, cmd.exe requires + # an NT console in order to perform redirection.. + None, # no new environment + None, # current directory (stay where we are) + StartupInfo, + ) + # normally, we would save the pid etc. here... + + # Child is launched. Close the parents copy of those pipe handles + # that only the child should have open. + # You need to make sure that no handles to the write end of the + # output pipe are maintained in this process or else the pipe will + # not close when the child process exits and the ReadFile will hang. + win32file.CloseHandle(hStderr_w) + win32file.CloseHandle(hStdout_w) + win32file.CloseHandle(hStdin_r) + + self.stdin = os.fdopen(msvcrt.open_osfhandle(self.hStdin_w, 0), "wb") + self.stdin.write("hmmmmm\r\n") + self.stdin.flush() + self.stdin.close() + + self.stdout = os.fdopen(msvcrt.open_osfhandle(self.hStdout_r, 0), "rb") + print("Read on stdout: ", repr(self.stdout.read())) + + self.stderr = os.fdopen(msvcrt.open_osfhandle(self.hStderr_r, 0), "rb") + print("Read on stderr: ", repr(self.stderr.read())) + + +if __name__ == "__main__": + p = Process() + exe = win32api.GetModuleFileName(0) + p.run(exe + " cat.py") + +# end of runproc.py diff --git a/MLPY/Lib/site-packages/win32/Demos/print_desktop.py b/MLPY/Lib/site-packages/win32/Demos/print_desktop.py new file mode 100644 index 0000000000000000000000000000000000000000..d06504e21b169e5e8669f9b34faf401e0286ad6c --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/print_desktop.py @@ -0,0 +1,113 @@ +import pywintypes +import win32api +import win32con +import win32gui +import win32print + +pname = win32print.GetDefaultPrinter() +print(pname) +p = win32print.OpenPrinter(pname) +print("Printer handle: ", p) +print_processor = win32print.GetPrinter(p, 2)["pPrintProcessor"] +## call with last parm set to 0 to get total size needed for printer's DEVMODE +dmsize = win32print.DocumentProperties(0, p, pname, None, None, 0) +## dmDriverExtra should be total size - fixed size +driverextra = ( + dmsize - pywintypes.DEVMODEType().Size +) ## need a better way to get DEVMODE.dmSize +dm = pywintypes.DEVMODEType(driverextra) +dm.Fields = dm.Fields | win32con.DM_ORIENTATION | win32con.DM_COPIES +dm.Orientation = win32con.DMORIENT_LANDSCAPE +dm.Copies = 2 +win32print.DocumentProperties( + 0, p, pname, dm, dm, win32con.DM_IN_BUFFER | win32con.DM_OUT_BUFFER +) + +pDC = win32gui.CreateDC(print_processor, pname, dm) +printerwidth = win32print.GetDeviceCaps(pDC, win32con.PHYSICALWIDTH) +printerheight = win32print.GetDeviceCaps(pDC, win32con.PHYSICALHEIGHT) + +hwnd = win32gui.GetDesktopWindow() +l, t, r, b = win32gui.GetWindowRect(hwnd) +desktopheight = b - t +desktopwidth = r - l +dDC = win32gui.GetWindowDC(hwnd) + +dcDC = win32gui.CreateCompatibleDC(dDC) +dcBM = win32gui.CreateCompatibleBitmap(dDC, desktopwidth, desktopheight) +win32gui.SelectObject(dcDC, dcBM) +win32gui.StretchBlt( + dcDC, + 0, + 0, + desktopwidth, + desktopheight, + dDC, + 0, + 0, + desktopwidth, + desktopheight, + win32con.SRCCOPY, +) + +pcDC = win32gui.CreateCompatibleDC(pDC) +pcBM = win32gui.CreateCompatibleBitmap(pDC, printerwidth, printerheight) +win32gui.SelectObject(pcDC, pcBM) +win32gui.StretchBlt( + pcDC, + 0, + 0, + printerwidth, + printerheight, + dcDC, + 0, + 0, + desktopwidth, + desktopheight, + win32con.SRCCOPY, +) + +win32print.StartDoc(pDC, ("desktop.bmp", None, None, 0)) +win32print.StartPage(pDC) +win32gui.StretchBlt( + pDC, + 0, + 0, + int(printerwidth * 0.9), + int(printerheight * 0.9), + pcDC, + 0, + 0, + printerwidth, + printerheight, + win32con.SRCCOPY, +) + +font = win32gui.LOGFONT() +font.lfHeight = int(printerheight / 20) +font.lfWidth = font.lfHeight +font.lfWeight = 150 +font.lfItalic = 1 +font.lfUnderline = 1 +hf = win32gui.CreateFontIndirect(font) +win32gui.SelectObject(pDC, hf) +win32gui.SetBkMode(pDC, win32con.TRANSPARENT) +win32gui.SetTextColor(pDC, win32api.RGB(0, 255, 0)) +win32gui.DrawText( + pDC, + "Printed by Python!", + -1, + (0, 0, int(printerwidth * 0.9), int(printerheight * 0.9)), + win32con.DT_RIGHT | win32con.DT_BOTTOM | win32con.DT_SINGLELINE, +) +win32print.EndPage(pDC) +win32print.EndDoc(pDC) + +win32print.ClosePrinter(p) +win32gui.DeleteObject(dcBM) +win32gui.DeleteObject(pcBM) +win32gui.DeleteObject(hf) +win32gui.DeleteDC(dDC) +win32gui.DeleteDC(dcDC) +win32gui.DeleteDC(pDC) +win32gui.DeleteDC(pcDC) diff --git a/MLPY/Lib/site-packages/win32/Demos/rastest.py b/MLPY/Lib/site-packages/win32/Demos/rastest.py new file mode 100644 index 0000000000000000000000000000000000000000..669a2a800b2b1ff37c5a6bc337e0982efc6807eb --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/rastest.py @@ -0,0 +1,168 @@ +# rastest.py - test/demonstrate the win32ras module. +# Much of the code here contributed by Jethro Wright. + +import os +import sys + +import win32ras + +# Build a little dictionary of RAS states to decent strings. +# eg win32ras.RASCS_OpenPort -> "OpenPort" +stateMap = {} +for name, val in list(win32ras.__dict__.items()): + if name[:6] == "RASCS_": + stateMap[val] = name[6:] + +# Use a lock so the callback can tell the main thread when it is finished. +import win32event + +callbackEvent = win32event.CreateEvent(None, 0, 0, None) + + +def Callback(hras, msg, state, error, exterror): + # print "Callback called with ", hras, msg, state, error, exterror + stateName = stateMap.get(state, "Unknown state?") + print("Status is %s (%04lx), error code is %d" % (stateName, state, error)) + finished = state in [win32ras.RASCS_Connected] + if finished: + win32event.SetEvent(callbackEvent) + if error != 0 or int(state) == win32ras.RASCS_Disconnected: + # we know for sure this is a good place to hangup.... + print("Detected call failure: %s" % win32ras.GetErrorString(error)) + HangUp(hras) + win32event.SetEvent(callbackEvent) + + +def ShowConnections(): + print("All phone-book entries:") + for (name,) in win32ras.EnumEntries(): + print(" ", name) + print("Current Connections:") + for con in win32ras.EnumConnections(): + print(" ", con) + + +def EditEntry(entryName): + try: + win32ras.EditPhonebookEntry(0, None, entryName) + except win32ras.error as xxx_todo_changeme: + (rc, function, msg) = xxx_todo_changeme.args + print("Can not edit/find the RAS entry -", msg) + + +def HangUp(hras): + # trap potential, irrelevant errors from win32ras.... + try: + win32ras.HangUp(hras) + except: + print("Tried to hang up gracefully on error, but didn't work....") + return None + + +def Connect(entryName, bUseCallback): + if bUseCallback: + theCallback = Callback + win32event.ResetEvent(callbackEvent) + else: + theCallback = None + # in order to *use* the username/password of a particular dun entry, one must + # explicitly get those params under win95.... + try: + dp, b = win32ras.GetEntryDialParams(None, entryName) + except: + print("Couldn't find DUN entry: %s" % entryName) + else: + hras, rc = win32ras.Dial( + None, None, (entryName, "", "", dp[3], dp[4], ""), theCallback + ) + # hras, rc = win32ras.Dial(None, None, (entryName, ),theCallback) + # print hras, rc + if not bUseCallback and rc != 0: + print("Could not dial the RAS connection:", win32ras.GetErrorString(rc)) + hras = HangUp(hras) + # don't wait here if there's no need to.... + elif ( + bUseCallback + and win32event.WaitForSingleObject(callbackEvent, 60000) + != win32event.WAIT_OBJECT_0 + ): + print("Gave up waiting for the process to complete!") + # sdk docs state one must explcitly hangup, even if there's an error.... + try: + cs = win32ras.GetConnectStatus(hras) + except: + # on error, attempt a hang up anyway.... + hras = HangUp(hras) + else: + if int(cs[0]) == win32ras.RASCS_Disconnected: + hras = HangUp(hras) + return hras, rc + + +def Disconnect(rasEntry): + # Need to find the entry + name = rasEntry.lower() + for hcon, entryName, devName, devType in win32ras.EnumConnections(): + if entryName.lower() == name: + win32ras.HangUp(hcon) + print("Disconnected from", rasEntry) + break + else: + print("Could not find an open connection to", entryName) + + +usage = """ +Usage: %s [-s] [-l] [-c connection] [-d connection] +-l : List phone-book entries and current connections. +-s : Show status while connecting/disconnecting (uses callbacks) +-c : Connect to the specified phonebook name. +-d : Disconnect from the specified phonebook name. +-e : Edit the specified phonebook entry. +""" + + +def main(): + import getopt + + try: + opts, args = getopt.getopt(sys.argv[1:], "slc:d:e:") + except getopt.error as why: + print(why) + print( + usage + % ( + os.path.basename( + sys.argv[0], + ) + ) + ) + return + + bCallback = 0 + if args or not opts: + print( + usage + % ( + os.path.basename( + sys.argv[0], + ) + ) + ) + return + for opt, val in opts: + if opt == "-s": + bCallback = 1 + if opt == "-l": + ShowConnections() + if opt == "-c": + hras, rc = Connect(val, bCallback) + if hras != None: + print("hras: 0x%8lx, rc: 0x%04x" % (hras, rc)) + if opt == "-d": + Disconnect(val) + if opt == "-e": + EditEntry(val) + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/security/GetTokenInformation.py b/MLPY/Lib/site-packages/win32/Demos/security/GetTokenInformation.py new file mode 100644 index 0000000000000000000000000000000000000000..192c549e1ba8907c753cd9afbfe5ca2323afd474 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/GetTokenInformation.py @@ -0,0 +1,110 @@ +""" Lists various types of information about current user's access token, + including UAC status on Vista +""" + +import pywintypes +import win32api +import win32con +import win32security +import winerror +from security_enums import ( + SECURITY_IMPERSONATION_LEVEL, + TOKEN_ELEVATION_TYPE, + TOKEN_GROUP_ATTRIBUTES, + TOKEN_PRIVILEGE_ATTRIBUTES, + TOKEN_TYPE, +) + + +def dump_token(th): + token_type = win32security.GetTokenInformation(th, win32security.TokenType) + print("TokenType:", token_type, TOKEN_TYPE.lookup_name(token_type)) + if token_type == win32security.TokenImpersonation: + imp_lvl = win32security.GetTokenInformation( + th, win32security.TokenImpersonationLevel + ) + print( + "TokenImpersonationLevel:", + imp_lvl, + SECURITY_IMPERSONATION_LEVEL.lookup_name(imp_lvl), + ) + + print( + "TokenSessionId:", + win32security.GetTokenInformation(th, win32security.TokenSessionId), + ) + + privs = win32security.GetTokenInformation(th, win32security.TokenPrivileges) + print("TokenPrivileges:") + for priv_luid, priv_flags in privs: + flag_names, unk = TOKEN_PRIVILEGE_ATTRIBUTES.lookup_flags(priv_flags) + flag_desc = " ".join(flag_names) + if unk: + flag_desc += "(" + str(unk) + ")" + + priv_name = win32security.LookupPrivilegeName("", priv_luid) + priv_desc = win32security.LookupPrivilegeDisplayName("", priv_name) + print("\t", priv_name, priv_desc, priv_flags, flag_desc) + + print("TokenGroups:") + groups = win32security.GetTokenInformation(th, win32security.TokenGroups) + for group_sid, group_attr in groups: + flag_names, unk = TOKEN_GROUP_ATTRIBUTES.lookup_flags(group_attr) + flag_desc = " ".join(flag_names) + if unk: + flag_desc += "(" + str(unk) + ")" + if group_attr & TOKEN_GROUP_ATTRIBUTES.SE_GROUP_LOGON_ID: + sid_desc = "Logon sid" + else: + sid_desc = win32security.LookupAccountSid("", group_sid) + print("\t", group_sid, sid_desc, group_attr, flag_desc) + + ## Vista token information types, will throw (87, 'GetTokenInformation', 'The parameter is incorrect.') on earier OS + try: + is_elevated = win32security.GetTokenInformation( + th, win32security.TokenElevation + ) + print("TokenElevation:", is_elevated) + except pywintypes.error as details: + if details.winerror != winerror.ERROR_INVALID_PARAMETER: + raise + return None + print( + "TokenHasRestrictions:", + win32security.GetTokenInformation(th, win32security.TokenHasRestrictions), + ) + print( + "TokenMandatoryPolicy", + win32security.GetTokenInformation(th, win32security.TokenMandatoryPolicy), + ) + print( + "TokenVirtualizationAllowed:", + win32security.GetTokenInformation(th, win32security.TokenVirtualizationAllowed), + ) + print( + "TokenVirtualizationEnabled:", + win32security.GetTokenInformation(th, win32security.TokenVirtualizationEnabled), + ) + + elevation_type = win32security.GetTokenInformation( + th, win32security.TokenElevationType + ) + print( + "TokenElevationType:", + elevation_type, + TOKEN_ELEVATION_TYPE.lookup_name(elevation_type), + ) + if elevation_type != win32security.TokenElevationTypeDefault: + lt = win32security.GetTokenInformation(th, win32security.TokenLinkedToken) + print("TokenLinkedToken:", lt) + else: + lt = None + return lt + + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph, win32con.MAXIMUM_ALLOWED) +lt = dump_token(th) +if lt: + print("\n\nlinked token info:") + dump_token(lt) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/GetTokenInformation.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/GetTokenInformation.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ded48928bed47a7aac12d42e384dde99d4faaf2d Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/GetTokenInformation.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/account_rights.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/account_rights.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0790b331a6bd8894ecf683b6e13df8a024b0dd7f Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/account_rights.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/explicit_entries.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/explicit_entries.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..87f87fb63f8aafd82d3e090315255a485ee02a14 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/explicit_entries.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/get_policy_info.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/get_policy_info.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4507c582b9b59e63ee7cd3f25928ee3cb846ba0a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/get_policy_info.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/list_rights.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/list_rights.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9fb2ccc4a11fd85b9bd513de6a6a7d453aff3783 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/list_rights.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/localized_names.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/localized_names.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00d70a9dcee573205e36a9c228c9bd67dafc750e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/localized_names.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/lsaregevent.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/lsaregevent.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab74889930c2617ec0c5fffeb5a7a9c32d4fb3cf Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/lsaregevent.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/lsastore.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/lsastore.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..698e7a83b2c447b0fe10b43bc0967a169d06e42b Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/lsastore.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/query_information.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/query_information.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ca2f8ee54c7cbf930bee69d0cd4b54d14b0d315 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/query_information.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/regsave_sa.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/regsave_sa.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0291a461c4dd63bdf70ad8e13459f8626e746d54 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/regsave_sa.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/regsecurity.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/regsecurity.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0079328b57e72eed6e59fdd30f0e0de14e74fd04 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/regsecurity.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/sa_inherit.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/sa_inherit.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59dd8330f57840bcf38cb70beaee3ad4cd32c909 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/sa_inherit.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/security_enums.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/security_enums.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..031b269f12af1257d8e18d745699adc7c16a40df Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/security_enums.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_file_audit.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_file_audit.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b14582dec3d964114634161dbff342da2af17173 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_file_audit.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_file_owner.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_file_owner.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1a1761c955f93979e4f3a8d2e9e6df8311797fd Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_file_owner.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_policy_info.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_policy_info.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3dfc3ee95953686c423be8498195453d7a843a42 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/set_policy_info.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setkernelobjectsecurity.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setkernelobjectsecurity.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8ef0ce0677a322fab9e5ec9cdbf53b96b2834f0 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setkernelobjectsecurity.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setnamedsecurityinfo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setnamedsecurityinfo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6844eadde1b6ab330240fae5bb583f8d29e88b46 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setnamedsecurityinfo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setsecurityinfo.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setsecurityinfo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19d9584baf5ceae32159ab78cbe0ce1010d348dc Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setsecurityinfo.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setuserobjectsecurity.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setuserobjectsecurity.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bca3a0a809c1e79ba1ff3f78cb9920e518c01169 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/__pycache__/setuserobjectsecurity.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/account_rights.py b/MLPY/Lib/site-packages/win32/Demos/security/account_rights.py new file mode 100644 index 0000000000000000000000000000000000000000..357b789a515c7b926fe3f7d90e90999bb5af951d --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/account_rights.py @@ -0,0 +1,51 @@ +import ntsecuritycon +import win32api +import win32con +import win32file +import win32security +from security_enums import ACCESS_MODE, ACE_FLAGS, TRUSTEE_FORM, TRUSTEE_TYPE + +new_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", "SeEnableDelegationPrivilege"), + win32con.SE_PRIVILEGE_ENABLED, + ), ##doesn't seem to be in ntsecuritycon.py ? +) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS +) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th, 0, new_privs) + +policy_handle = win32security.GetPolicyHandle("", win32security.POLICY_ALL_ACCESS) +tmp_sid = win32security.LookupAccountName("", "tmp")[0] + +privs = [ + ntsecuritycon.SE_DEBUG_NAME, + ntsecuritycon.SE_TCB_NAME, + ntsecuritycon.SE_RESTORE_NAME, + ntsecuritycon.SE_REMOTE_SHUTDOWN_NAME, +] +win32security.LsaAddAccountRights(policy_handle, tmp_sid, privs) + +privlist = win32security.LsaEnumerateAccountRights(policy_handle, tmp_sid) +for priv in privlist: + print(priv) + +privs = [ntsecuritycon.SE_DEBUG_NAME, ntsecuritycon.SE_TCB_NAME] +win32security.LsaRemoveAccountRights(policy_handle, tmp_sid, 0, privs) + +privlist = win32security.LsaEnumerateAccountRights(policy_handle, tmp_sid) +for priv in privlist: + print(priv) + +win32security.LsaClose(policy_handle) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/explicit_entries.py b/MLPY/Lib/site-packages/win32/Demos/security/explicit_entries.py new file mode 100644 index 0000000000000000000000000000000000000000..b04f45173fda27949a885125bf1db0488ba633a5 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/explicit_entries.py @@ -0,0 +1,171 @@ +import os + +import ntsecuritycon +import win32api +import win32con +import win32file +import win32security +from security_enums import ACCESS_MODE, ACE_FLAGS, TRUSTEE_FORM, TRUSTEE_TYPE + +fname = os.path.join(win32api.GetTempPath(), "win32security_test.txt") +f = open(fname, "w") +f.write("Hello from Python\n") +f.close() +print("Testing on file", fname) + +new_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SHUTDOWN_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_TAKE_OWNERSHIP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", "SeEnableDelegationPrivilege"), + win32con.SE_PRIVILEGE_ENABLED, + ), ##doesn't seem to be in ntsecuritycon.py ? +) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS +) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th, 0, new_privs) + +all_security_info = ( + win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION + | win32security.SACL_SECURITY_INFORMATION +) + +sd = win32security.GetFileSecurity(fname, all_security_info) + +old_sacl = sd.GetSecurityDescriptorSacl() +if old_sacl == None: + old_sacl = win32security.ACL() +old_dacl = sd.GetSecurityDescriptorDacl() +if old_dacl == None: + old_dacl = win32security.ACL() + +my_sid = win32security.GetTokenInformation(th, ntsecuritycon.TokenUser)[0] +tmp_sid = win32security.LookupAccountName("", "tmp")[0] +pwr_sid = win32security.LookupAccountName("", "Power Users")[0] + + +## MultipleTrustee,MultipleTrusteeOperation,TrusteeForm,TrusteeType,Identifier +## first two are ignored +my_trustee = {} +my_trustee["MultipleTrustee"] = None +my_trustee["MultipleTrusteeOperation"] = 0 +my_trustee["TrusteeForm"] = TRUSTEE_FORM.TRUSTEE_IS_SID +my_trustee["TrusteeType"] = TRUSTEE_TYPE.TRUSTEE_IS_USER +my_trustee["Identifier"] = my_sid + +tmp_trustee = {} +tmp_trustee["MultipleTrustee"] = None +tmp_trustee["MultipleTrusteeOperation"] = 0 +tmp_trustee["TrusteeForm"] = TRUSTEE_FORM.TRUSTEE_IS_NAME +tmp_trustee["TrusteeType"] = TRUSTEE_TYPE.TRUSTEE_IS_USER +tmp_trustee["Identifier"] = "rupole\\tmp" + +pwr_trustee = {} +pwr_trustee["MultipleTrustee"] = None +pwr_trustee["MultipleTrusteeOperation"] = 0 +pwr_trustee["TrusteeForm"] = TRUSTEE_FORM.TRUSTEE_IS_SID +pwr_trustee["TrusteeType"] = TRUSTEE_TYPE.TRUSTEE_IS_USER +pwr_trustee["Identifier"] = pwr_sid + +expl_list = [] +expl_list.append( + { + "Trustee": my_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.SET_AUDIT_SUCCESS, ##|ACCESS_MODE.SET_AUDIT_FAILURE, + "AccessPermissions": win32con.GENERIC_ALL, + } +) + +expl_list.append( + { + "Trustee": my_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.SET_AUDIT_FAILURE, + "AccessPermissions": win32con.GENERIC_ALL, + } +) + +expl_list.append( + { + "Trustee": tmp_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.SET_AUDIT_SUCCESS, + "AccessPermissions": win32con.GENERIC_ALL, + } +) + +expl_list.append( + { + "Trustee": tmp_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.SET_AUDIT_FAILURE, + "AccessPermissions": win32con.GENERIC_ALL, + } +) +old_sacl.SetEntriesInAcl(expl_list) + +expl_list = [] +expl_list.append( + { + "Trustee": tmp_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.DENY_ACCESS, + "AccessPermissions": win32con.DELETE, + } +) + +expl_list.append( + { + "Trustee": tmp_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.GRANT_ACCESS, + "AccessPermissions": win32con.WRITE_OWNER, + } +) +expl_list.append( + { + "Trustee": pwr_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.GRANT_ACCESS, + "AccessPermissions": win32con.GENERIC_READ, + } +) +expl_list.append( + { + "Trustee": my_trustee, + "Inheritance": ACE_FLAGS.NO_INHERITANCE, + "AccessMode": ACCESS_MODE.GRANT_ACCESS, + "AccessPermissions": win32con.GENERIC_ALL, + } +) + +old_dacl.SetEntriesInAcl(expl_list) +sd.SetSecurityDescriptorSacl(1, old_sacl, 1) +sd.SetSecurityDescriptorDacl(1, old_dacl, 1) +sd.SetSecurityDescriptorOwner(pwr_sid, 1) + +win32security.SetFileSecurity(fname, all_security_info, sd) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/get_policy_info.py b/MLPY/Lib/site-packages/win32/Demos/security/get_policy_info.py new file mode 100644 index 0000000000000000000000000000000000000000..1eba9cd0d09a3de59ee228e6bc4a17c839359564 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/get_policy_info.py @@ -0,0 +1,42 @@ +import ntsecuritycon +import win32api +import win32file +import win32security + +policy_handle = win32security.GetPolicyHandle("rupole", win32security.POLICY_ALL_ACCESS) + +## mod_nbr, mod_time = win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyModificationInformation) +## print mod_nbr, mod_time + +( + domain_name, + dns_domain_name, + dns_forest_name, + domain_guid, + domain_sid, +) = win32security.LsaQueryInformationPolicy( + policy_handle, win32security.PolicyDnsDomainInformation +) +print(domain_name, dns_domain_name, dns_forest_name, domain_guid, domain_sid) + +event_audit_info = win32security.LsaQueryInformationPolicy( + policy_handle, win32security.PolicyAuditEventsInformation +) +print(event_audit_info) + +domain_name, sid = win32security.LsaQueryInformationPolicy( + policy_handle, win32security.PolicyPrimaryDomainInformation +) +print(domain_name, sid) + +domain_name, sid = win32security.LsaQueryInformationPolicy( + policy_handle, win32security.PolicyAccountDomainInformation +) +print(domain_name, sid) + +server_role = win32security.LsaQueryInformationPolicy( + policy_handle, win32security.PolicyLsaServerRoleInformation +) +print("server role: ", server_role) + +win32security.LsaClose(policy_handle) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/list_rights.py b/MLPY/Lib/site-packages/win32/Demos/security/list_rights.py new file mode 100644 index 0000000000000000000000000000000000000000..780008a252f5d7c72c9341c6307b570261be7bb3 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/list_rights.py @@ -0,0 +1,37 @@ +import ntsecuritycon +import win32api +import win32con +import win32file +import win32security +from security_enums import ACCESS_MODE, ACE_FLAGS, TRUSTEE_FORM, TRUSTEE_TYPE + +new_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", "SeEnableDelegationPrivilege"), + win32con.SE_PRIVILEGE_ENABLED, + ), ##doesn't seem to be in ntsecuritycon.py ? +) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS +) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th, 0, new_privs) + +policy_handle = win32security.GetPolicyHandle("", win32security.POLICY_ALL_ACCESS) + +sidlist = win32security.LsaEnumerateAccountsWithUserRight( + policy_handle, ntsecuritycon.SE_RESTORE_NAME +) +for sid in sidlist: + print(win32security.LookupAccountSid("", sid)) + +win32security.LsaClose(policy_handle) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/localized_names.py b/MLPY/Lib/site-packages/win32/Demos/security/localized_names.py new file mode 100644 index 0000000000000000000000000000000000000000..30a0bde6d373ed421b0e6b5a3ed91a295e806b63 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/localized_names.py @@ -0,0 +1,65 @@ +# A Python port of the MS knowledge base article Q157234 +# "How to deal with localized and renamed user and group names" +# http://support.microsoft.com/default.aspx?kbid=157234 + +import sys + +import pywintypes +from ntsecuritycon import * +from win32net import NetUserModalsGet +from win32security import LookupAccountSid + + +def LookupAliasFromRid(TargetComputer, Rid): + # Sid is the same regardless of machine, since the well-known + # BUILTIN domain is referenced. + sid = pywintypes.SID() + sid.Initialize(SECURITY_NT_AUTHORITY, 2) + + for i, r in enumerate((SECURITY_BUILTIN_DOMAIN_RID, Rid)): + sid.SetSubAuthority(i, r) + + name, domain, typ = LookupAccountSid(TargetComputer, sid) + return name + + +def LookupUserGroupFromRid(TargetComputer, Rid): + # get the account domain Sid on the target machine + # note: if you were looking up multiple sids based on the same + # account domain, only need to call this once. + umi2 = NetUserModalsGet(TargetComputer, 2) + domain_sid = umi2["domain_id"] + + SubAuthorityCount = domain_sid.GetSubAuthorityCount() + + # create and init new sid with acct domain Sid + acct Rid + sid = pywintypes.SID() + sid.Initialize(domain_sid.GetSidIdentifierAuthority(), SubAuthorityCount + 1) + + # copy existing subauthorities from account domain Sid into + # new Sid + for i in range(SubAuthorityCount): + sid.SetSubAuthority(i, domain_sid.GetSubAuthority(i)) + + # append Rid to new Sid + sid.SetSubAuthority(SubAuthorityCount, Rid) + + name, domain, typ = LookupAccountSid(TargetComputer, sid) + return name + + +def main(): + if len(sys.argv) == 2: + targetComputer = sys.argv[1] + else: + targetComputer = None + + name = LookupUserGroupFromRid(targetComputer, DOMAIN_USER_RID_ADMIN) + print("'Administrator' user name = %s" % (name,)) + + name = LookupAliasFromRid(targetComputer, DOMAIN_ALIAS_RID_ADMINS) + print("'Administrators' local group/alias name = %s" % (name,)) + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/security/lsaregevent.py b/MLPY/Lib/site-packages/win32/Demos/security/lsaregevent.py new file mode 100644 index 0000000000000000000000000000000000000000..38e7adc9cb00c9dfe54ae3bec08be8e95977b99c --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/lsaregevent.py @@ -0,0 +1,14 @@ +import win32event +import win32security + +evt = win32event.CreateEvent(None, 0, 0, None) +win32security.LsaRegisterPolicyChangeNotification( + win32security.PolicyNotifyAuditEventsInformation, evt +) +print("Waiting for you change Audit policy in Management console ...") +ret_code = win32event.WaitForSingleObject(evt, 1000000000) +## should come back when you change Audit policy in Management console ... +print(ret_code) +win32security.LsaUnregisterPolicyChangeNotification( + win32security.PolicyNotifyAuditEventsInformation, evt +) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/lsastore.py b/MLPY/Lib/site-packages/win32/Demos/security/lsastore.py new file mode 100644 index 0000000000000000000000000000000000000000..dd9ff384e5dba4caecb6f987588b3bee959ac1e6 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/lsastore.py @@ -0,0 +1,12 @@ +import win32security + +policy_handle = win32security.GetPolicyHandle("", win32security.POLICY_ALL_ACCESS) +privatedata = "some sensitive data" +keyname = "tmp" +win32security.LsaStorePrivateData(policy_handle, keyname, privatedata) +retrieveddata = win32security.LsaRetrievePrivateData(policy_handle, keyname) +assert retrieveddata == privatedata + +## passing None deletes key +win32security.LsaStorePrivateData(policy_handle, keyname, None) +win32security.LsaClose(policy_handle) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/query_information.py b/MLPY/Lib/site-packages/win32/Demos/security/query_information.py new file mode 100644 index 0000000000000000000000000000000000000000..9fa3e4a9561418288468a0f1d60167ebd47a396a --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/query_information.py @@ -0,0 +1,25 @@ +import win32api +import win32security +import winerror +from ntsecuritycon import * + + +# This is a Python implementation of win32api.GetDomainName() +def GetDomainName(): + try: + tok = win32security.OpenThreadToken(win32api.GetCurrentThread(), TOKEN_QUERY, 1) + except win32api.error as details: + if details[0] != winerror.ERROR_NO_TOKEN: + raise + # attempt to open the process token, since no thread token + # exists + tok = win32security.OpenProcessToken(win32api.GetCurrentProcess(), TOKEN_QUERY) + sid, attr = win32security.GetTokenInformation(tok, TokenUser) + win32api.CloseHandle(tok) + + name, dom, typ = win32security.LookupAccountSid(None, sid) + return dom + + +if __name__ == "__main__": + print("Domain name is", GetDomainName()) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/regsave_sa.py b/MLPY/Lib/site-packages/win32/Demos/security/regsave_sa.py new file mode 100644 index 0000000000000000000000000000000000000000..29a6ac1059e5ee321c6bf9e8f80cfd3e9ed3d134 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/regsave_sa.py @@ -0,0 +1,61 @@ +fname = "h:\\tmp.reg" + +import os + +import ntsecuritycon +import pywintypes +import win32api +import win32con +import win32security + +## regsave will not overwrite a file +if os.path.isfile(fname): + os.remove(fname) + +new_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_TCB_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_BACKUP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS | win32con.TOKEN_ADJUST_PRIVILEGES +) +win32security.AdjustTokenPrivileges(th, 0, new_privs) +my_sid = win32security.GetTokenInformation(th, ntsecuritycon.TokenUser)[0] + +hklm = win32api.RegOpenKey( + win32con.HKEY_LOCAL_MACHINE, None, 0, win32con.KEY_ALL_ACCESS +) +skey = win32api.RegOpenKey(hklm, "SYSTEM", 0, win32con.KEY_ALL_ACCESS) + +sa = pywintypes.SECURITY_ATTRIBUTES() +sd = pywintypes.SECURITY_DESCRIPTOR() +sa.SECURITY_DESCRIPTOR = sd +acl = pywintypes.ACL() + +pwr_sid = win32security.LookupAccountName("", "Power Users")[0] +acl.AddAccessAllowedAce( + win32con.ACL_REVISION, + win32con.GENERIC_READ | win32con.ACCESS_SYSTEM_SECURITY, + my_sid, +) +sd.SetSecurityDescriptorDacl(1, acl, 0) +sd.SetSecurityDescriptorOwner(pwr_sid, 0) +sa.bInheritHandle = 1 +assert sa.SECURITY_DESCRIPTOR is sd + +win32api.RegSaveKey(skey, fname, sa) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/regsecurity.py b/MLPY/Lib/site-packages/win32/Demos/security/regsecurity.py new file mode 100644 index 0000000000000000000000000000000000000000..3bac65c08e6d49dfe2769e44ce002a1faa6969fd --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/regsecurity.py @@ -0,0 +1,36 @@ +import ntsecuritycon +import win32api +import win32con +import win32security + +new_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_TCB_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS | win32con.TOKEN_ADJUST_PRIVILEGES +) + +win32security.AdjustTokenPrivileges(th, 0, new_privs) +hkey = win32api.RegOpenKey( + win32con.HKEY_LOCAL_MACHINE, None, 0, win32con.KEY_ALL_ACCESS +) +win32api.RegCreateKey(hkey, "SYSTEM\\NOTMP") +notmpkey = win32api.RegOpenKey( + hkey, "SYSTEM\\notmp", 0, win32con.ACCESS_SYSTEM_SECURITY +) + +tmp_sid = win32security.LookupAccountName("", "tmp")[0] +sacl = win32security.ACL() +sacl.AddAuditAccessAce(win32security.ACL_REVISION, win32con.GENERIC_ALL, tmp_sid, 1, 1) + +sd = win32security.SECURITY_DESCRIPTOR() +sd.SetSecurityDescriptorSacl(1, sacl, 1) +win32api.RegSetKeySecurity(notmpkey, win32con.SACL_SECURITY_INFORMATION, sd) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sa_inherit.py b/MLPY/Lib/site-packages/win32/Demos/security/sa_inherit.py new file mode 100644 index 0000000000000000000000000000000000000000..a2855e5044284c7970ccbda016c91b862b0579d8 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/sa_inherit.py @@ -0,0 +1,8 @@ +import pywintypes +import win32security + +sa = pywintypes.SECURITY_ATTRIBUTES() +tmp_sid = win32security.LookupAccountName("", "tmp")[0] +sa.SetSecurityDescriptorOwner(tmp_sid, 0) +sid = sa.SECURITY_DESCRIPTOR.GetSecurityDescriptorOwner() +print(win32security.LookupAccountSid("", sid)) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/security_enums.py b/MLPY/Lib/site-packages/win32/Demos/security/security_enums.py new file mode 100644 index 0000000000000000000000000000000000000000..ab3cc6d3618817043ad4e6b80511e8ebc9cf2401 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/security_enums.py @@ -0,0 +1,336 @@ +import ntsecuritycon +import win32security +import winnt + + +class Enum: + def __init__(self, *const_names): + """Accepts variable number of constant names that can be found in either + win32security, ntsecuritycon, or winnt.""" + for const_name in const_names: + try: + const_val = getattr(win32security, const_name) + except AttributeError: + try: + const_val = getattr(ntsecuritycon, const_name) + except AttributeError: + try: + const_val = getattr(winnt, const_name) + except AttributeError: + raise AttributeError( + 'Constant "%s" not found in win32security, ntsecuritycon, or winnt.' + % const_name + ) + setattr(self, const_name, const_val) + + def lookup_name(self, const_val): + """Looks up the name of a particular value.""" + for k, v in self.__dict__.items(): + if v == const_val: + return k + raise AttributeError("Value %s not found in enum" % const_val) + + def lookup_flags(self, flags): + """Returns the names of all recognized flags in input, and any flags not found in the enum.""" + flag_names = [] + unknown_flags = flags + for k, v in self.__dict__.items(): + if flags & v == v: + flag_names.append(k) + unknown_flags = unknown_flags & ~v + return flag_names, unknown_flags + + +TOKEN_INFORMATION_CLASS = Enum( + "TokenUser", + "TokenGroups", + "TokenPrivileges", + "TokenOwner", + "TokenPrimaryGroup", + "TokenDefaultDacl", + "TokenSource", + "TokenType", + "TokenImpersonationLevel", + "TokenStatistics", + "TokenRestrictedSids", + "TokenSessionId", + "TokenGroupsAndPrivileges", + "TokenSessionReference", + "TokenSandBoxInert", + "TokenAuditPolicy", + "TokenOrigin", + "TokenElevationType", + "TokenLinkedToken", + "TokenElevation", + "TokenHasRestrictions", + "TokenAccessInformation", + "TokenVirtualizationAllowed", + "TokenVirtualizationEnabled", + "TokenIntegrityLevel", + "TokenUIAccess", + "TokenMandatoryPolicy", + "TokenLogonSid", +) + +TOKEN_TYPE = Enum("TokenPrimary", "TokenImpersonation") + +TOKEN_ELEVATION_TYPE = Enum( + "TokenElevationTypeDefault", "TokenElevationTypeFull", "TokenElevationTypeLimited" +) + +POLICY_AUDIT_EVENT_TYPE = Enum( + "AuditCategorySystem", + "AuditCategoryLogon", + "AuditCategoryObjectAccess", + "AuditCategoryPrivilegeUse", + "AuditCategoryDetailedTracking", + "AuditCategoryPolicyChange", + "AuditCategoryAccountManagement", + "AuditCategoryDirectoryServiceAccess", + "AuditCategoryAccountLogon", +) + +POLICY_INFORMATION_CLASS = Enum( + "PolicyAuditLogInformation", + "PolicyAuditEventsInformation", + "PolicyPrimaryDomainInformation", + "PolicyPdAccountInformation", + "PolicyAccountDomainInformation", + "PolicyLsaServerRoleInformation", + "PolicyReplicaSourceInformation", + "PolicyDefaultQuotaInformation", + "PolicyModificationInformation", + "PolicyAuditFullSetInformation", + "PolicyAuditFullQueryInformation", + "PolicyDnsDomainInformation", +) + +POLICY_LSA_SERVER_ROLE = Enum("PolicyServerRoleBackup", "PolicyServerRolePrimary") + +## access modes for opening a policy handle - this is not a real enum +POLICY_ACCESS_MODES = Enum( + "POLICY_VIEW_LOCAL_INFORMATION", + "POLICY_VIEW_AUDIT_INFORMATION", + "POLICY_GET_PRIVATE_INFORMATION", + "POLICY_TRUST_ADMIN", + "POLICY_CREATE_ACCOUNT", + "POLICY_CREATE_SECRET", + "POLICY_CREATE_PRIVILEGE", + "POLICY_SET_DEFAULT_QUOTA_LIMITS", + "POLICY_SET_AUDIT_REQUIREMENTS", + "POLICY_AUDIT_LOG_ADMIN", + "POLICY_SERVER_ADMIN", + "POLICY_LOOKUP_NAMES", + "POLICY_NOTIFICATION", + "POLICY_ALL_ACCESS", + "POLICY_READ", + "POLICY_WRITE", + "POLICY_EXECUTE", +) + +## EventAuditingOptions flags - not a real enum +POLICY_AUDIT_EVENT_OPTIONS_FLAGS = Enum( + "POLICY_AUDIT_EVENT_UNCHANGED", + "POLICY_AUDIT_EVENT_SUCCESS", + "POLICY_AUDIT_EVENT_FAILURE", + "POLICY_AUDIT_EVENT_NONE", +) + +# AceType in ACE_HEADER - not a real enum +ACE_TYPE = Enum( + "ACCESS_MIN_MS_ACE_TYPE", + "ACCESS_ALLOWED_ACE_TYPE", + "ACCESS_DENIED_ACE_TYPE", + "SYSTEM_AUDIT_ACE_TYPE", + "SYSTEM_ALARM_ACE_TYPE", + "ACCESS_MAX_MS_V2_ACE_TYPE", + "ACCESS_ALLOWED_COMPOUND_ACE_TYPE", + "ACCESS_MAX_MS_V3_ACE_TYPE", + "ACCESS_MIN_MS_OBJECT_ACE_TYPE", + "ACCESS_ALLOWED_OBJECT_ACE_TYPE", + "ACCESS_DENIED_OBJECT_ACE_TYPE", + "SYSTEM_AUDIT_OBJECT_ACE_TYPE", + "SYSTEM_ALARM_OBJECT_ACE_TYPE", + "ACCESS_MAX_MS_OBJECT_ACE_TYPE", + "ACCESS_MAX_MS_V4_ACE_TYPE", + "ACCESS_MAX_MS_ACE_TYPE", + "ACCESS_ALLOWED_CALLBACK_ACE_TYPE", + "ACCESS_DENIED_CALLBACK_ACE_TYPE", + "ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE", + "ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE", + "SYSTEM_AUDIT_CALLBACK_ACE_TYPE", + "SYSTEM_ALARM_CALLBACK_ACE_TYPE", + "SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE", + "SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE", + "SYSTEM_MANDATORY_LABEL_ACE_TYPE", + "ACCESS_MAX_MS_V5_ACE_TYPE", +) + +# bit flags for AceFlags - not a real enum +ACE_FLAGS = Enum( + "CONTAINER_INHERIT_ACE", + "FAILED_ACCESS_ACE_FLAG", + "INHERIT_ONLY_ACE", + "INHERITED_ACE", + "NO_PROPAGATE_INHERIT_ACE", + "OBJECT_INHERIT_ACE", + "SUCCESSFUL_ACCESS_ACE_FLAG", + "NO_INHERITANCE", + "SUB_CONTAINERS_AND_OBJECTS_INHERIT", + "SUB_CONTAINERS_ONLY_INHERIT", + "SUB_OBJECTS_ONLY_INHERIT", +) + +# used in SetEntriesInAcl - very similar to ACE_TYPE +ACCESS_MODE = Enum( + "NOT_USED_ACCESS", + "GRANT_ACCESS", + "SET_ACCESS", + "DENY_ACCESS", + "REVOKE_ACCESS", + "SET_AUDIT_SUCCESS", + "SET_AUDIT_FAILURE", +) + +# Bit flags in PSECURITY_DESCRIPTOR->Control - not a real enum +SECURITY_DESCRIPTOR_CONTROL_FLAGS = Enum( + "SE_DACL_AUTO_INHERITED", ## win2k and up + "SE_SACL_AUTO_INHERITED", ## win2k and up + "SE_DACL_PROTECTED", ## win2k and up + "SE_SACL_PROTECTED", ## win2k and up + "SE_DACL_DEFAULTED", + "SE_DACL_PRESENT", + "SE_GROUP_DEFAULTED", + "SE_OWNER_DEFAULTED", + "SE_SACL_PRESENT", + "SE_SELF_RELATIVE", + "SE_SACL_DEFAULTED", +) + +# types of SID +SID_NAME_USE = Enum( + "SidTypeUser", + "SidTypeGroup", + "SidTypeDomain", + "SidTypeAlias", + "SidTypeWellKnownGroup", + "SidTypeDeletedAccount", + "SidTypeInvalid", + "SidTypeUnknown", + "SidTypeComputer", + "SidTypeLabel", +) + +## bit flags, not a real enum +TOKEN_ACCESS_PRIVILEGES = Enum( + "TOKEN_ADJUST_DEFAULT", + "TOKEN_ADJUST_GROUPS", + "TOKEN_ADJUST_PRIVILEGES", + "TOKEN_ALL_ACCESS", + "TOKEN_ASSIGN_PRIMARY", + "TOKEN_DUPLICATE", + "TOKEN_EXECUTE", + "TOKEN_IMPERSONATE", + "TOKEN_QUERY", + "TOKEN_QUERY_SOURCE", + "TOKEN_READ", + "TOKEN_WRITE", +) + +SECURITY_IMPERSONATION_LEVEL = Enum( + "SecurityAnonymous", + "SecurityIdentification", + "SecurityImpersonation", + "SecurityDelegation", +) + +POLICY_SERVER_ENABLE_STATE = Enum("PolicyServerEnabled", "PolicyServerDisabled") + +POLICY_NOTIFICATION_INFORMATION_CLASS = Enum( + "PolicyNotifyAuditEventsInformation", + "PolicyNotifyAccountDomainInformation", + "PolicyNotifyServerRoleInformation", + "PolicyNotifyDnsDomainInformation", + "PolicyNotifyDomainEfsInformation", + "PolicyNotifyDomainKerberosTicketInformation", + "PolicyNotifyMachineAccountPasswordInformation", +) + +TRUSTED_INFORMATION_CLASS = Enum( + "TrustedDomainNameInformation", + "TrustedControllersInformation", + "TrustedPosixOffsetInformation", + "TrustedPasswordInformation", + "TrustedDomainInformationBasic", + "TrustedDomainInformationEx", + "TrustedDomainAuthInformation", + "TrustedDomainFullInformation", + "TrustedDomainAuthInformationInternal", + "TrustedDomainFullInformationInternal", + "TrustedDomainInformationEx2Internal", + "TrustedDomainFullInformation2Internal", +) + +TRUSTEE_FORM = Enum( + "TRUSTEE_IS_SID", + "TRUSTEE_IS_NAME", + "TRUSTEE_BAD_FORM", + "TRUSTEE_IS_OBJECTS_AND_SID", + "TRUSTEE_IS_OBJECTS_AND_NAME", +) + +TRUSTEE_TYPE = Enum( + "TRUSTEE_IS_UNKNOWN", + "TRUSTEE_IS_USER", + "TRUSTEE_IS_GROUP", + "TRUSTEE_IS_DOMAIN", + "TRUSTEE_IS_ALIAS", + "TRUSTEE_IS_WELL_KNOWN_GROUP", + "TRUSTEE_IS_DELETED", + "TRUSTEE_IS_INVALID", + "TRUSTEE_IS_COMPUTER", +) + +## SE_OBJECT_TYPE - securable objects +SE_OBJECT_TYPE = Enum( + "SE_UNKNOWN_OBJECT_TYPE", + "SE_FILE_OBJECT", + "SE_SERVICE", + "SE_PRINTER", + "SE_REGISTRY_KEY", + "SE_LMSHARE", + "SE_KERNEL_OBJECT", + "SE_WINDOW_OBJECT", + "SE_DS_OBJECT", + "SE_DS_OBJECT_ALL", + "SE_PROVIDER_DEFINED_OBJECT", + "SE_WMIGUID_OBJECT", + "SE_REGISTRY_WOW64_32KEY", +) + +PRIVILEGE_FLAGS = Enum( + "SE_PRIVILEGE_ENABLED_BY_DEFAULT", + "SE_PRIVILEGE_ENABLED", + "SE_PRIVILEGE_USED_FOR_ACCESS", +) + +# Group flags used with TokenGroups +TOKEN_GROUP_ATTRIBUTES = Enum( + "SE_GROUP_MANDATORY", + "SE_GROUP_ENABLED_BY_DEFAULT", + "SE_GROUP_ENABLED", + "SE_GROUP_OWNER", + "SE_GROUP_USE_FOR_DENY_ONLY", + "SE_GROUP_INTEGRITY", + "SE_GROUP_INTEGRITY_ENABLED", + "SE_GROUP_LOGON_ID", + "SE_GROUP_RESOURCE", +) + +# Privilege flags returned by TokenPrivileges +TOKEN_PRIVILEGE_ATTRIBUTES = Enum( + "SE_PRIVILEGE_ENABLED_BY_DEFAULT", + "SE_PRIVILEGE_ENABLED", + "SE_PRIVILEGE_REMOVED", + "SE_PRIVILEGE_USED_FOR_ACCESS", +) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/set_file_audit.py b/MLPY/Lib/site-packages/win32/Demos/security/set_file_audit.py new file mode 100644 index 0000000000000000000000000000000000000000..324d72748d32d67424b7a71f80080f947394f1c4 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/set_file_audit.py @@ -0,0 +1,107 @@ +import os + +import ntsecuritycon +import win32api +import win32con +import win32file +import win32security +from win32security import ( + ACL_REVISION_DS, + CONTAINER_INHERIT_ACE, + DACL_SECURITY_INFORMATION, + GROUP_SECURITY_INFORMATION, + OBJECT_INHERIT_ACE, + OWNER_SECURITY_INFORMATION, + PROTECTED_DACL_SECURITY_INFORMATION, + SACL_SECURITY_INFORMATION, + SE_FILE_OBJECT, +) + +## SE_SECURITY_NAME needed to access SACL, SE_RESTORE_NAME needed to change owner to someone other than yourself +new_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS | win32con.TOKEN_ADJUST_PRIVILEGES +) +modified_privs = win32security.AdjustTokenPrivileges(th, 0, new_privs) + +## look up a few sids that should be available on most systems +my_sid = win32security.GetTokenInformation(th, ntsecuritycon.TokenUser)[0] +pwr_sid = win32security.LookupAccountName("", "Power Users")[0] +admin_sid = win32security.LookupAccountName("", "Administrators")[0] +everyone_sid = win32security.LookupAccountName("", "EveryOne")[0] + +## create a dir and set security so Everyone has read permissions, and all files and subdirs inherit its ACLs +temp_dir = win32api.GetTempPath() +dir_name = win32api.GetTempFileName(temp_dir, "sfa")[0] +os.remove(dir_name) +os.mkdir(dir_name) +dir_dacl = win32security.ACL() +dir_dacl.AddAccessAllowedAceEx( + ACL_REVISION_DS, + CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + win32con.GENERIC_READ, + everyone_sid, +) +## make sure current user has permissions on dir +dir_dacl.AddAccessAllowedAceEx( + ACL_REVISION_DS, + CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + win32con.GENERIC_ALL, + my_sid, +) +## keep dir from inheriting any permissions so it only has ACEs explicitely set here +win32security.SetNamedSecurityInfo( + dir_name, + SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION + | PROTECTED_DACL_SECURITY_INFORMATION, + pwr_sid, + pwr_sid, + dir_dacl, + None, +) + +## Create a file in the dir and add some specific permissions to it +fname = win32api.GetTempFileName(dir_name, "sfa")[0] +print(fname) +file_sd = win32security.GetNamedSecurityInfo( + fname, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION +) +file_dacl = file_sd.GetSecurityDescriptorDacl() +file_sacl = file_sd.GetSecurityDescriptorSacl() + +if file_dacl is None: + file_dacl = win32security.ACL() +if file_sacl is None: + file_sacl = win32security.ACL() + +file_dacl.AddAccessDeniedAce(file_dacl.GetAclRevision(), win32con.DELETE, admin_sid) +file_dacl.AddAccessDeniedAce(file_dacl.GetAclRevision(), win32con.DELETE, my_sid) +file_dacl.AddAccessAllowedAce(file_dacl.GetAclRevision(), win32con.GENERIC_ALL, pwr_sid) +file_sacl.AddAuditAccessAce( + file_dacl.GetAclRevision(), win32con.GENERIC_ALL, my_sid, True, True +) + +win32security.SetNamedSecurityInfo( + fname, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, + None, + None, + file_dacl, + file_sacl, +) + +win32security.AdjustTokenPrivileges(th, 0, modified_privs) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/set_file_owner.py b/MLPY/Lib/site-packages/win32/Demos/security/set_file_owner.py new file mode 100644 index 0000000000000000000000000000000000000000..5a384da0901dd5b3e4b9a55988d1632d07457b23 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/set_file_owner.py @@ -0,0 +1,74 @@ +fname = r"h:\tmp.txt" + +import ntsecuritycon +import win32api +import win32con +import win32file +import win32security + +new_privs = ( + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_SHUTDOWN_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_TCB_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_TAKE_OWNERSHIP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", ntsecuritycon.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", "SeEnableDelegationPrivilege"), + win32con.SE_PRIVILEGE_ENABLED, + ), ##doesn't seem to be in ntsecuritycon.py ? +) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS | win32con.TOKEN_ADJUST_PRIVILEGES +) +win32security.AdjustTokenPrivileges(th, 0, new_privs) + +all_security_info = ( + win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION + | win32security.SACL_SECURITY_INFORMATION +) + +sd = win32security.GetFileSecurity(fname, all_security_info) +old_dacl = sd.GetSecurityDescriptorDacl() +old_sacl = sd.GetSecurityDescriptorSacl() +old_group = sd.GetSecurityDescriptorGroup() + +new_sd = win32security.SECURITY_DESCRIPTOR() +print( + "relative, valid, size: ", + new_sd.IsSelfRelative(), + new_sd.IsValid(), + new_sd.GetLength(), +) + +my_sid = win32security.GetTokenInformation(th, ntsecuritycon.TokenUser)[0] +tmp_sid = win32security.LookupAccountName("", "tmp")[0] + +new_sd.SetSecurityDescriptorSacl(1, old_sacl, 1) +new_sd.SetSecurityDescriptorDacl(1, old_dacl, 1) +new_sd.SetSecurityDescriptorOwner(tmp_sid, 0) +new_sd.SetSecurityDescriptorGroup(old_group, 0) + +win32security.SetFileSecurity(fname, all_security_info, new_sd) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/set_policy_info.py b/MLPY/Lib/site-packages/win32/Demos/security/set_policy_info.py new file mode 100644 index 0000000000000000000000000000000000000000..5dd3cf819dd6a2a681a3b83b4e2cc8bbaa3958b6 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/set_policy_info.py @@ -0,0 +1,28 @@ +import ntsecuritycon +import win32api +import win32file +import win32security + +policy_handle = win32security.GetPolicyHandle("rupole", win32security.POLICY_ALL_ACCESS) + +event_audit_info = win32security.LsaQueryInformationPolicy( + policy_handle, win32security.PolicyAuditEventsInformation +) +print(event_audit_info) + +new_audit_info = list(event_audit_info[1]) +new_audit_info[win32security.AuditCategoryPolicyChange] = ( + win32security.POLICY_AUDIT_EVENT_SUCCESS | win32security.POLICY_AUDIT_EVENT_FAILURE +) +new_audit_info[win32security.AuditCategoryAccountLogon] = ( + win32security.POLICY_AUDIT_EVENT_SUCCESS | win32security.POLICY_AUDIT_EVENT_FAILURE +) +new_audit_info[win32security.AuditCategoryLogon] = ( + win32security.POLICY_AUDIT_EVENT_SUCCESS | win32security.POLICY_AUDIT_EVENT_FAILURE +) + +win32security.LsaSetInformationPolicy( + policy_handle, win32security.PolicyAuditEventsInformation, (1, new_audit_info) +) + +win32security.LsaClose(policy_handle) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/setkernelobjectsecurity.py b/MLPY/Lib/site-packages/win32/Demos/security/setkernelobjectsecurity.py new file mode 100644 index 0000000000000000000000000000000000000000..34c8f44692b392cefdb33cd42067c87fd72bb6c8 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/setkernelobjectsecurity.py @@ -0,0 +1,135 @@ +import win32api +import win32con +import win32process +import win32security + +## You need SE_RESTORE_NAME to be able to set the owner of a security descriptor to anybody +## other than yourself or your primary group. Most admin logins don't have it by default, so +## enabling it may fail +new_privs = ( + ( + win32security.LookupPrivilegeValue("", win32security.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TCB_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SHUTDOWN_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TAKE_OWNERSHIP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_ENABLE_DELEGATION_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CHANGE_NOTIFY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_DEBUG_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue( + "", win32security.SE_PROF_SINGLE_PROCESS_NAME + ), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SYSTEM_PROFILE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_LOCK_MEMORY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) + +all_info = ( + win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION + | win32security.SACL_SECURITY_INFORMATION +) + +pid = win32api.GetCurrentProcessId() +ph = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, pid) +## PROCESS_ALL_ACCESS does not contain ACCESS_SYSTEM_SECURITY (neccessy to do SACLs) +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS +) ##win32con.TOKEN_ADJUST_PRIVILEGES) +old_privs = win32security.GetTokenInformation(th, win32security.TokenPrivileges) +desired_privs = tuple((e[0], win32con.SE_PRIVILEGE_ENABLED) for e in old_privs) +modified_privs = win32security.AdjustTokenPrivileges( + th, 0, desired_privs +) # Will (partially) fail for new_privs (unless they are a subset of current ones) +gle = win32api.GetLastError() +if gle != 0: + print("AdjustTokenPrivileges error:", gle) +# print(modified_privs) +my_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0] +pwr_sid = win32security.LookupAccountName("", "Power Users")[0] +## reopen process with ACCESS_SYSTEM_SECURITY now that sufficent privs are enabled +ph = win32api.OpenProcess( + win32con.PROCESS_ALL_ACCESS | win32con.ACCESS_SYSTEM_SECURITY, 0, pid +) + +sd = win32security.GetKernelObjectSecurity(ph, all_info) +dacl = sd.GetSecurityDescriptorDacl() +if dacl is None: + dacl = win32security.ACL() +sacl = sd.GetSecurityDescriptorSacl() +if sacl is None: + sacl = win32security.ACL() + +dacl_ace_cnt = dacl.GetAceCount() +sacl_ace_cnt = sacl.GetAceCount() + +dacl.AddAccessAllowedAce( + dacl.GetAclRevision(), win32con.ACCESS_SYSTEM_SECURITY | win32con.WRITE_DAC, my_sid +) +sacl.AddAuditAccessAce(sacl.GetAclRevision(), win32con.GENERIC_ALL, my_sid, 1, 1) +sd.SetSecurityDescriptorDacl(1, dacl, 0) +sd.SetSecurityDescriptorSacl(1, sacl, 0) +sd.SetSecurityDescriptorGroup(pwr_sid, 0) +sd.SetSecurityDescriptorOwner(pwr_sid, 0) + +win32security.SetKernelObjectSecurity(ph, all_info, sd) +new_sd = win32security.GetKernelObjectSecurity(ph, all_info) + +if new_sd.GetSecurityDescriptorDacl().GetAceCount() != dacl_ace_cnt + 1: + print("New dacl doesn" "t contain extra ace ????") +if new_sd.GetSecurityDescriptorSacl().GetAceCount() != sacl_ace_cnt + 1: + print("New Sacl doesn" "t contain extra ace ????") +if ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorOwner())[0] + != "Power Users" +): + print("Owner not successfully set to Power Users !!!!!") +if ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorGroup())[0] + != "Power Users" +): + print("Group not successfully set to Power Users !!!!!") + +sd.SetSecurityDescriptorSacl(0, None, 0) +win32security.SetKernelObjectSecurity(ph, win32security.SACL_SECURITY_INFORMATION, sd) +new_sd_1 = win32security.GetKernelObjectSecurity( + ph, win32security.SACL_SECURITY_INFORMATION +) +if new_sd_1.GetSecurityDescriptorSacl() is not None: + print("Unable to set Sacl to NULL !!!!!!!!") diff --git a/MLPY/Lib/site-packages/win32/Demos/security/setnamedsecurityinfo.py b/MLPY/Lib/site-packages/win32/Demos/security/setnamedsecurityinfo.py new file mode 100644 index 0000000000000000000000000000000000000000..8915a0df1adebea54a36238515722f3a338bb28d --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/setnamedsecurityinfo.py @@ -0,0 +1,131 @@ +import win32api +import win32con +import win32process +import win32security + +fname, tmp = win32api.GetTempFileName(win32api.GetTempPath(), "tmp") +print(fname) +## You need SE_RESTORE_NAME to be able to set the owner of a security descriptor to anybody +## other than yourself or your primary group. Most admin logins don't have it by default, so +## enabling it may fail +new_privs = ( + ( + win32security.LookupPrivilegeValue("", win32security.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TCB_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SHUTDOWN_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TAKE_OWNERSHIP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_ENABLE_DELEGATION_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CHANGE_NOTIFY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_DEBUG_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue( + "", win32security.SE_PROF_SINGLE_PROCESS_NAME + ), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SYSTEM_PROFILE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_LOCK_MEMORY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) + +all_info = ( + win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION + | win32security.SACL_SECURITY_INFORMATION +) + +ph = win32process.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS +) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th, 0, new_privs) +my_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0] +pwr_sid = win32security.LookupAccountName("", "Power Users")[0] + +sd = win32security.GetNamedSecurityInfo(fname, win32security.SE_FILE_OBJECT, all_info) +dacl = sd.GetSecurityDescriptorDacl() +if dacl is None: + dacl = win32security.ACL() +sacl = sd.GetSecurityDescriptorSacl() +if sacl is None: + sacl = win32security.ACL() + +dacl_ace_cnt = dacl.GetAceCount() +sacl_ace_cnt = sacl.GetAceCount() + +dacl.AddAccessAllowedAce( + dacl.GetAclRevision(), win32con.ACCESS_SYSTEM_SECURITY | win32con.WRITE_DAC, my_sid +) +sacl.AddAuditAccessAce(sacl.GetAclRevision(), win32con.GENERIC_ALL, my_sid, 1, 1) + +win32security.SetNamedSecurityInfo( + fname, win32security.SE_FILE_OBJECT, all_info, pwr_sid, pwr_sid, dacl, sacl +) +new_sd = win32security.GetNamedSecurityInfo( + fname, win32security.SE_FILE_OBJECT, all_info +) + +## could do additional checking to make sure added ACE contains expected info +if new_sd.GetSecurityDescriptorDacl().GetAceCount() != dacl_ace_cnt + 1: + print("New dacl doesn" "t contain extra ace ????") +if new_sd.GetSecurityDescriptorSacl().GetAceCount() != sacl_ace_cnt + 1: + print("New Sacl doesn" "t contain extra ace ????") +if ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorOwner())[0] + != "Power Users" +): + print("Owner not successfully set to Power Users !!!!!") +if ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorGroup())[0] + != "Power Users" +): + print("Group not successfully set to Power Users !!!!!") + +win32security.SetNamedSecurityInfo( + fname, + win32security.SE_FILE_OBJECT, + win32security.SACL_SECURITY_INFORMATION, + None, + None, + None, + None, +) +new_sd_1 = win32security.GetNamedSecurityInfo( + fname, win32security.SE_FILE_OBJECT, win32security.SACL_SECURITY_INFORMATION +) +if new_sd_1.GetSecurityDescriptorSacl() is not None: + print("Unable to set Sacl to NULL !!!!!!!!") diff --git a/MLPY/Lib/site-packages/win32/Demos/security/setsecurityinfo.py b/MLPY/Lib/site-packages/win32/Demos/security/setsecurityinfo.py new file mode 100644 index 0000000000000000000000000000000000000000..d784d9509988a7621d3a8e73b03f4a55dafec076 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/setsecurityinfo.py @@ -0,0 +1,132 @@ +import win32api +import win32con +import win32process +import win32security + +## You need SE_RESTORE_NAME to be able to set the owner of a security descriptor to anybody +## other than yourself or your primary group. Most admin logins don't have it by default, so +## enabling it may fail +new_privs = ( + ( + win32security.LookupPrivilegeValue("", win32security.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TCB_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SHUTDOWN_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TAKE_OWNERSHIP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_ENABLE_DELEGATION_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CHANGE_NOTIFY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_DEBUG_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue( + "", win32security.SE_PROF_SINGLE_PROCESS_NAME + ), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SYSTEM_PROFILE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_LOCK_MEMORY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) + +all_info = ( + win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION + | win32security.SACL_SECURITY_INFORMATION +) + +pid = win32api.GetCurrentProcessId() +ph = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, pid) +## PROCESS_ALL_ACCESS does not contain ACCESS_SYSTEM_SECURITY (neccessy to do SACLs) +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS +) ##win32con.TOKEN_ADJUST_PRIVILEGES) +old_privs = win32security.AdjustTokenPrivileges(th, 0, new_privs) +my_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0] +pwr_sid = win32security.LookupAccountName("", "Power Users")[0] +## reopen process with ACCESS_SYSTEM_SECURITY now that sufficent privs are enabled +ph = win32api.OpenProcess( + win32con.PROCESS_ALL_ACCESS | win32con.ACCESS_SYSTEM_SECURITY, 0, pid +) + +sd = win32security.GetSecurityInfo(ph, win32security.SE_KERNEL_OBJECT, all_info) +dacl = sd.GetSecurityDescriptorDacl() +if dacl is None: + dacl = win32security.ACL() +sacl = sd.GetSecurityDescriptorSacl() +if sacl is None: + sacl = win32security.ACL() + +dacl_ace_cnt = dacl.GetAceCount() +sacl_ace_cnt = sacl.GetAceCount() + +dacl.AddAccessAllowedAce( + dacl.GetAclRevision(), win32con.ACCESS_SYSTEM_SECURITY | win32con.WRITE_DAC, my_sid +) +sacl.AddAuditAccessAce(sacl.GetAclRevision(), win32con.GENERIC_ALL, my_sid, 1, 1) + +win32security.SetSecurityInfo( + ph, win32security.SE_KERNEL_OBJECT, all_info, pwr_sid, pwr_sid, dacl, sacl +) +new_sd = win32security.GetSecurityInfo(ph, win32security.SE_KERNEL_OBJECT, all_info) + +if new_sd.GetSecurityDescriptorDacl().GetAceCount() != dacl_ace_cnt + 1: + print("New dacl doesn" "t contain extra ace ????") +if new_sd.GetSecurityDescriptorSacl().GetAceCount() != sacl_ace_cnt + 1: + print("New Sacl doesn" "t contain extra ace ????") +if ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorOwner())[0] + != "Power Users" +): + print("Owner not successfully set to Power Users !!!!!") +if ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorGroup())[0] + != "Power Users" +): + print("Group not successfully set to Power Users !!!!!") + +win32security.SetSecurityInfo( + ph, + win32security.SE_KERNEL_OBJECT, + win32security.SACL_SECURITY_INFORMATION, + None, + None, + None, + None, +) +new_sd_1 = win32security.GetSecurityInfo( + ph, win32security.SE_KERNEL_OBJECT, win32security.SACL_SECURITY_INFORMATION +) +if new_sd_1.GetSecurityDescriptorSacl() is not None: + print("Unable to set Sacl to NULL !!!!!!!!") diff --git a/MLPY/Lib/site-packages/win32/Demos/security/setuserobjectsecurity.py b/MLPY/Lib/site-packages/win32/Demos/security/setuserobjectsecurity.py new file mode 100644 index 0000000000000000000000000000000000000000..668571f6765044b74b34ce9c29184e956f7d676f --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/setuserobjectsecurity.py @@ -0,0 +1,103 @@ +import win32api +import win32con +import win32process +import win32security + +new_privs = ( + ( + win32security.LookupPrivilegeValue("", win32security.SE_SECURITY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TCB_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SHUTDOWN_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_RESTORE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_TAKE_OWNERSHIP_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CREATE_PERMANENT_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_ENABLE_DELEGATION_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_CHANGE_NOTIFY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_DEBUG_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue( + "", win32security.SE_PROF_SINGLE_PROCESS_NAME + ), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_SYSTEM_PROFILE_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), + ( + win32security.LookupPrivilegeValue("", win32security.SE_LOCK_MEMORY_NAME), + win32con.SE_PRIVILEGE_ENABLED, + ), +) + +all_info = ( + win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION + | win32security.SACL_SECURITY_INFORMATION +) +info = ( + win32security.OWNER_SECURITY_INFORMATION + | win32security.GROUP_SECURITY_INFORMATION + | win32security.DACL_SECURITY_INFORMATION +) + +ph = win32process.GetCurrentProcess() +th = win32security.OpenProcessToken( + ph, win32security.TOKEN_ALL_ACCESS +) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th, 0, new_privs) +my_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0] +pwr_sid = win32security.LookupAccountName("", "Power Users")[0] + +h = win32process.GetProcessWindowStation() +sd = win32security.GetUserObjectSecurity(h, info) +dacl = sd.GetSecurityDescriptorDacl() +ace_cnt = dacl.GetAceCount() + +dacl.AddAccessAllowedAce( + dacl.GetAclRevision(), win32con.ACCESS_SYSTEM_SECURITY | win32con.WRITE_DAC, my_sid +) +sd.SetSecurityDescriptorDacl(1, dacl, 0) +sd.SetSecurityDescriptorGroup(pwr_sid, 0) +sd.SetSecurityDescriptorOwner(pwr_sid, 0) + +win32security.SetUserObjectSecurity(h, info, sd) +new_sd = win32security.GetUserObjectSecurity(h, info) +assert ( + new_sd.GetSecurityDescriptorDacl().GetAceCount() == ace_cnt + 1 +), "Did not add an ace to the Dacl !!!!!!" +assert ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorOwner())[0] + == "Power Users" +), "Owner not successfully set to Power Users !!!!!" +assert ( + win32security.LookupAccountSid("", new_sd.GetSecurityDescriptorGroup())[0] + == "Power Users" +), "Group not successfully set to Power Users !!!!!" diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/fetch_url.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/fetch_url.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62daed05f60b7e0a12e7307289249afb14be08f3 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/fetch_url.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/simple_auth.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/simple_auth.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b30596f7fab87ca83563df05fb075bf3c9686bd Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/simple_auth.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/socket_server.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/socket_server.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7d87c24014b76cac5987fd7e02987b2fdcd336a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/socket_server.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/validate_password.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/validate_password.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3781300ca42e7df263736984a08f0e0f3530de17 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/security/sspi/__pycache__/validate_password.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/fetch_url.py b/MLPY/Lib/site-packages/win32/Demos/security/sspi/fetch_url.py new file mode 100644 index 0000000000000000000000000000000000000000..3b43b7e46cedb4df9f41c4f87472743527e5c3bc --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/sspi/fetch_url.py @@ -0,0 +1,160 @@ +""" +Fetches a URL from a web-server supporting NTLM authentication +eg, IIS. + +If no arguments are specified, a default of http://localhost/localstart.asp +is used. This script does follow simple 302 redirections, so pointing at the +root of an IIS server is should work. +""" + +import http.client # sorry, this demo needs 2.3+ +import optparse +import urllib.error +import urllib.parse +import urllib.request +from base64 import decodestring, encodestring + +from sspi import ClientAuth + +options = None # set to optparse options object + + +def open_url(host, url): + h = http.client.HTTPConnection(host) + # h.set_debuglevel(9) + h.putrequest("GET", url) + h.endheaders() + resp = h.getresponse() + print("Initial response is", resp.status, resp.reason) + body = resp.read() + if resp.status == 302: # object moved + url = "/" + resp.msg["location"] + resp.close() + h.putrequest("GET", url) + h.endheaders() + resp = h.getresponse() + print("After redirect response is", resp.status, resp.reason) + if options.show_headers: + print("Initial response headers:") + for name, val in list(resp.msg.items()): + print(" %s: %s" % (name, val)) + if options.show_body: + print(body) + if resp.status == 401: + # 401: Unauthorized - here is where the real work starts + auth_info = None + if options.user or options.domain or options.password: + auth_info = options.user, options.domain, options.password + ca = ClientAuth("NTLM", auth_info=auth_info) + auth_scheme = ca.pkg_info["Name"] + data = None + while 1: + err, out_buf = ca.authorize(data) + data = out_buf[0].Buffer + # Encode it as base64 as required by HTTP + auth = encodestring(data).replace("\012", "") + h.putrequest("GET", url) + h.putheader("Authorization", auth_scheme + " " + auth) + h.putheader("Content-Length", "0") + h.endheaders() + resp = h.getresponse() + if options.show_headers: + print("Token dance headers:") + for name, val in list(resp.msg.items()): + print(" %s: %s" % (name, val)) + + if err == 0: + break + else: + if resp.status != 401: + print("Eeek - got response", resp.status) + cl = resp.msg.get("content-length") + if cl: + print(repr(resp.read(int(cl)))) + else: + print("no content!") + + assert resp.status == 401, resp.status + + assert not resp.will_close, "NTLM is per-connection - must not close" + schemes = [ + s.strip() for s in resp.msg.get("WWW-Authenticate", "").split(",") + ] + for scheme in schemes: + if scheme.startswith(auth_scheme): + data = decodestring(scheme[len(auth_scheme) + 1 :]) + break + else: + print( + "Could not find scheme '%s' in schemes %r" % (auth_scheme, schemes) + ) + break + + resp.read() + print("Final response status is", resp.status, resp.reason) + if resp.status == 200: + # Worked! + # Check we can read it again without re-authenticating. + if resp.will_close: + print( + "EEEK - response will close, but NTLM is per connection - it must stay open" + ) + body = resp.read() + if options.show_body: + print("Final response body:") + print(body) + h.putrequest("GET", url) + h.endheaders() + resp = h.getresponse() + print("Second fetch response is", resp.status, resp.reason) + if options.show_headers: + print("Second response headers:") + for name, val in list(resp.msg.items()): + print(" %s: %s" % (name, val)) + + resp.read(int(resp.msg.get("content-length", 0))) + elif resp.status == 500: + print("Error text") + print(resp.read()) + else: + if options.show_body: + cl = resp.msg.get("content-length") + print(resp.read(int(cl))) + + +if __name__ == "__main__": + parser = optparse.OptionParser(description=__doc__) + + parser.add_option( + "", + "--show-body", + action="store_true", + help="print the body of each response as it is received", + ) + + parser.add_option( + "", + "--show-headers", + action="store_true", + help="print the headers of each response as it is received", + ) + + parser.add_option("", "--user", action="store", help="The username to login with") + + parser.add_option( + "", "--password", action="store", help="The password to login with" + ) + + parser.add_option("", "--domain", action="store", help="The domain to login to") + + options, args = parser.parse_args() + if not args: + print("Run with --help for usage details") + args = ["http://localhost/localstart.asp"] + for url in args: + scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) + if (scheme != "http") or params or query or fragment: + parser.error("Scheme must be http, URL must be simple") + + print("Opening '%s' from '%s'" % (path, netloc)) + r = open_url(netloc, path) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/simple_auth.py b/MLPY/Lib/site-packages/win32/Demos/security/sspi/simple_auth.py new file mode 100644 index 0000000000000000000000000000000000000000..cc0ce5cf929f2d79bbea5172abdead72a78eafd3 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/sspi/simple_auth.py @@ -0,0 +1,72 @@ +# A demo of basic SSPI authentication. +# There is a 'client' context and a 'server' context - typically these will +# be on different machines (here they are in the same process, but the same +# concepts apply) +import sspi +import sspicon +import win32api +import win32security + + +def lookup_ret_code(err): + for k, v in list(sspicon.__dict__.items()): + if k[0:6] in ("SEC_I_", "SEC_E_") and v == err: + return k + + +""" +pkg_name='Kerberos' +sspiclient=SSPIClient(pkg_name, win32api.GetUserName(), ## target spn is ourself + None, None, ## use none for client name and authentication information for current context + ## u'username', (u'username',u'domain.com',u'passwd'), + sspicon.ISC_REQ_INTEGRITY|sspicon.ISC_REQ_SEQUENCE_DETECT|sspicon.ISC_REQ_REPLAY_DETECT| \ + sspicon.ISC_REQ_DELEGATE|sspicon.ISC_REQ_CONFIDENTIALITY|sspicon.ISC_REQ_USE_SESSION_KEY) +sspiserver=SSPIServer(pkg_name, None, + sspicon.ASC_REQ_INTEGRITY|sspicon.ASC_REQ_SEQUENCE_DETECT|sspicon.ASC_REQ_REPLAY_DETECT| \ + sspicon.ASC_REQ_DELEGATE|sspicon.ASC_REQ_CONFIDENTIALITY|sspicon.ASC_REQ_STREAM|sspicon.ASC_REQ_USE_SESSION_KEY) +""" + +pkg_name = "NTLM" + +# Setup the 2 contexts. +sspiclient = sspi.ClientAuth(pkg_name) +sspiserver = sspi.ServerAuth(pkg_name) + +# Perform the authentication dance, each loop exchanging more information +# on the way to completing authentication. +sec_buffer = None +while 1: + err, sec_buffer = sspiclient.authorize(sec_buffer) + err, sec_buffer = sspiserver.authorize(sec_buffer) + if err == 0: + break + +# The server can now impersonate the client. In this demo the 2 users will +# always be the same. +sspiserver.ctxt.ImpersonateSecurityContext() +print("Impersonated user: ", win32api.GetUserNameEx(win32api.NameSamCompatible)) +sspiserver.ctxt.RevertSecurityContext() +print("Reverted to self: ", win32api.GetUserName()) + +pkg_size_info = sspiclient.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES) +# Now sign some data +msg = "some data to be encrypted ......" + +sigsize = pkg_size_info["MaxSignature"] +sigbuf = win32security.PySecBufferDescType() +sigbuf.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA)) +sigbuf.append(win32security.PySecBufferType(sigsize, sspicon.SECBUFFER_TOKEN)) +sigbuf[0].Buffer = msg +sspiclient.ctxt.MakeSignature(0, sigbuf, 1) +sspiserver.ctxt.VerifySignature(sigbuf, 1) + +# And finally encrypt some. +trailersize = pkg_size_info["SecurityTrailer"] +encbuf = win32security.PySecBufferDescType() +encbuf.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA)) +encbuf.append(win32security.PySecBufferType(trailersize, sspicon.SECBUFFER_TOKEN)) +encbuf[0].Buffer = msg +sspiclient.ctxt.EncryptMessage(0, encbuf, 1) +print("Encrypted data:", repr(encbuf[0].Buffer)) +sspiserver.ctxt.DecryptMessage(encbuf, 1) +print("Unencrypted data:", encbuf[0].Buffer) diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/socket_server.py b/MLPY/Lib/site-packages/win32/Demos/security/sspi/socket_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4d606bb86b802b4f76538c98874a5d2ce635bd0c --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/sspi/socket_server.py @@ -0,0 +1,201 @@ +"""A sample socket server and client using SSPI authentication and encryption. + +You must run with either 'client' or 'server' as arguments. A server must be +running before a client can connect. + +To use with Kerberos you should include in the client options +--target-spn=username, where 'username' is the user under which the server is +being run. + +Running either the client or server as a different user can be informative. +A command-line such as the following may be useful: +`runas /user:{user} {fqp}\python.exe {fqp}\socket_server.py --wait client|server` + +{fqp} should specify the relevant fully-qualified path names. + +To use 'runas' with Kerberos, the client program will need to +specify --target-spn with the username under which the *server* is running. + +See the SSPI documentation for more details. +""" + + +import http.client # sorry, this demo needs 2.3+ +import optparse +import socketserver +import struct +import traceback + +import sspi +import win32api +import win32security + +options = None # set to optparse object. + + +def GetUserName(): + try: + return win32api.GetUserName() + except win32api.error as details: + # Seeing 'access denied' errors here for non-local users (presumably + # without permission to login locally). Get the fully-qualified + # username, although a side-effect of these permission-denied errors + # is a lack of Python codecs - so printing the Unicode value fails. + # So just return the repr(), and avoid codecs completely. + return repr(win32api.GetUserNameEx(win32api.NameSamCompatible)) + + +# Send a simple "message" over a socket - send the number of bytes first, +# then the string. Ditto for receive. +def _send_msg(s, m): + s.send(struct.pack("i", len(m))) + s.send(m) + + +def _get_msg(s): + size_data = s.recv(struct.calcsize("i")) + if not size_data: + return None + cb = struct.unpack("i", size_data)[0] + return s.recv(cb) + + +class SSPISocketServer(socketserver.TCPServer): + def __init__(self, *args, **kw): + socketserver.TCPServer.__init__(self, *args, **kw) + self.sa = sspi.ServerAuth(options.package) + + def verify_request(self, sock, ca): + # Do the sspi auth dance + self.sa.reset() + while 1: + data = _get_msg(sock) + if data is None: + return False + try: + err, sec_buffer = self.sa.authorize(data) + except sspi.error as details: + print("FAILED to authorize client:", details) + return False + + if err == 0: + break + _send_msg(sock, sec_buffer[0].Buffer) + return True + + def process_request(self, request, client_address): + # An example using the connection once it is established. + print("The server is running as user", GetUserName()) + self.sa.ctxt.ImpersonateSecurityContext() + try: + print("Having conversation with client as user", GetUserName()) + while 1: + # we need to grab 2 bits of data - the encrypted data, and the + # 'key' + data = _get_msg(request) + key = _get_msg(request) + if data is None or key is None: + break + data = self.sa.decrypt(data, key) + print("Client sent:", repr(data)) + finally: + self.sa.ctxt.RevertSecurityContext() + self.close_request(request) + print("The server is back to user", GetUserName()) + + +def serve(): + s = SSPISocketServer(("localhost", options.port), None) + print("Running test server...") + s.serve_forever() + + +def sspi_client(): + c = http.client.HTTPConnection("localhost", options.port) + c.connect() + # Do the auth dance. + ca = sspi.ClientAuth(options.package, targetspn=options.target_spn) + data = None + while 1: + err, out_buf = ca.authorize(data) + _send_msg(c.sock, out_buf[0].Buffer) + if err == 0: + break + data = _get_msg(c.sock) + print("Auth dance complete - sending a few encryted messages") + # Assume out data is sensitive - encrypt the message. + for data in "Hello from the client".split(): + blob, key = ca.encrypt(data) + _send_msg(c.sock, blob) + _send_msg(c.sock, key) + c.sock.close() + print("Client completed.") + + +if __name__ == "__main__": + parser = optparse.OptionParser("%prog [options] client|server", description=__doc__) + + parser.add_option( + "", + "--package", + action="store", + default="NTLM", + help="The SSPI package to use (eg, Kerberos) - default is NTLM", + ) + + parser.add_option( + "", + "--target-spn", + action="store", + help="""The target security provider name to use. The + string contents are security-package specific. For + example, 'Kerberos' or 'Negotiate' require the server + principal name (SPN) (ie, the username) of the remote + process. For NTLM this must be blank.""", + ) + + parser.add_option( + "", + "--port", + action="store", + default="8181", + help="The port number to use (default=8181)", + ) + + parser.add_option( + "", + "--wait", + action="store_true", + help="""Cause the program to wait for input just before + terminating. Useful when using via runas to see + any error messages before termination. + """, + ) + + options, args = parser.parse_args() + try: + options.port = int(options.port) + except (ValueError, TypeError): + parser.error("--port must be an integer") + + try: + try: + if not args: + args = [""] + if args[0] == "client": + sspi_client() + elif args[0] == "server": + serve() + else: + parser.error( + "You must supply 'client' or 'server' - " "use --help for details" + ) + except KeyboardInterrupt: + pass + except SystemExit: + pass + except: + traceback.print_exc() + finally: + if options.wait: + input("Press enter to continue") diff --git a/MLPY/Lib/site-packages/win32/Demos/security/sspi/validate_password.py b/MLPY/Lib/site-packages/win32/Demos/security/sspi/validate_password.py new file mode 100644 index 0000000000000000000000000000000000000000..40b6ad5b2fdeb1d985a76f6b71a8a10dcd20105b --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/security/sspi/validate_password.py @@ -0,0 +1,41 @@ +# Demonstrates how to validate a password. +# See also MSKB article Q180548 +# +# To use with Kerberos you need to jump through the 'targetspn' hoops. + +import sys + +import win32security +from sspi import ClientAuth, ServerAuth + + +def validate(username, password, domain=""): + auth_info = username, domain, password + ca = ClientAuth("NTLM", auth_info=auth_info) + sa = ServerAuth("NTLM") + + data = err = None + while err != 0: + err, data = ca.authorize(data) + err, data = sa.authorize(data) + # If we get here without exception, we worked! + + +if __name__ == "__main__": + if len(sys.argv) not in [2, 3, 4]: + print("Usage: %s username [password [domain]]" % (__file__,)) + sys.exit(1) + + # password and domain are optional! + password = None + if len(sys.argv) >= 3: + password = sys.argv[2] + domain = "" + if len(sys.argv) >= 4: + domain = sys.argv[3] + try: + validate(sys.argv[1], password, domain) + print("Validated OK") + except win32security.error as details: + hr, func, msg = details + print("Validation failed: %s (%d)" % (msg, hr)) diff --git a/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/nativePipeTestService.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/nativePipeTestService.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53f13bfbfa6a6dbcce21c27d67ece0b5fc257f62 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/nativePipeTestService.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/pipeTestService.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/pipeTestService.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8f836100d654b15837fd10b4b645a10243f3e6e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/pipeTestService.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/pipeTestServiceClient.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/pipeTestServiceClient.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..193c37771d4a70d6eb5b3ccaf921f1fc88d4b20a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/pipeTestServiceClient.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/serviceEvents.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/serviceEvents.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f658c17159f2037044623d40d343947d9e4894e1 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/service/__pycache__/serviceEvents.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/service/nativePipeTestService.py b/MLPY/Lib/site-packages/win32/Demos/service/nativePipeTestService.py new file mode 100644 index 0000000000000000000000000000000000000000..4ac05ebafa94460db7a042d2b315a01217fa30d1 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/service/nativePipeTestService.py @@ -0,0 +1,63 @@ +# This is an example of a service hosted by python.exe rather than +# pythonservice.exe. + +# Note that it is very rare that using python.exe is a better option +# than the default pythonservice.exe - the latter has better error handling +# so that if Python itself can't be initialized or there are very early +# import errors, you will get error details written to the event log. When +# using python.exe instead, you are forced to wait for the interpreter startup +# and imports to succeed before you are able to effectively setup your own +# error handling. + +# So in short, please make sure you *really* want to do this, otherwise just +# stick with the default. + +import os +import sys + +import servicemanager +import win32serviceutil +from pipeTestService import TestPipeService + + +class NativeTestPipeService(TestPipeService): + _svc_name_ = "PyNativePipeTestService" + _svc_display_name_ = "Python Native Pipe Test Service" + _svc_description_ = "Tests Python.exe hosted services" + # tell win32serviceutil we have a custom executable and custom args + # so registration does the right thing. + _exe_name_ = sys.executable + _exe_args_ = '"' + os.path.abspath(sys.argv[0]) + '"' + + +def main(): + if len(sys.argv) == 1: + # service must be starting... + print("service is starting...") + print("(execute this script with '--help' if that isn't what you want)") + + # for the sake of debugging etc, we use win32traceutil to see + # any unhandled exceptions and print statements. + import win32traceutil + + print("service is still starting...") + + servicemanager.Initialize() + servicemanager.PrepareToHostSingle(NativeTestPipeService) + # Now ask the service manager to fire things up for us... + servicemanager.StartServiceCtrlDispatcher() + print("service done!") + else: + win32serviceutil.HandleCommandLine(NativeTestPipeService) + + +if __name__ == "__main__": + try: + main() + except (SystemExit, KeyboardInterrupt): + raise + except: + print("Something went bad!") + import traceback + + traceback.print_exc() diff --git a/MLPY/Lib/site-packages/win32/Demos/service/pipeTestService.py b/MLPY/Lib/site-packages/win32/Demos/service/pipeTestService.py new file mode 100644 index 0000000000000000000000000000000000000000..2efda606471ad7666c6abd42b325c3cc98e6eccf --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/service/pipeTestService.py @@ -0,0 +1,184 @@ +# A Demo of services and named pipes. + +# A multi-threaded service that simply echos back its input. + +# * Install as a service using "pipeTestService.py install" +# * Use Control Panel to change the user name of the service +# to a real user name (ie, NOT the SystemAccount) +# * Start the service. +# * Run the "pipeTestServiceClient.py" program as the client pipe side. + +import _thread +import traceback + +# Old versions of the service framework would not let you import this +# module at the top-level. Now you can, and can check 'Debugging()' and +# 'RunningAsService()' to check your context. +import pywintypes +import servicemanager +import win32con +import win32service +import win32serviceutil +import winerror +from ntsecuritycon import * +from win32api import * + +# Use "import *" to keep this looking as much as a "normal" service +# as possible. Real code shouldn't do this. +from win32event import * +from win32file import * +from win32pipe import * + + +def ApplyIgnoreError(fn, args): + try: + return fn(*args) + except error: # Ignore win32api errors. + return None + + +class TestPipeService(win32serviceutil.ServiceFramework): + _svc_name_ = "PyPipeTestService" + _svc_display_name_ = "Python Pipe Test Service" + _svc_description_ = "Tests Python service framework by receiving and echoing messages over a named pipe" + + def __init__(self, args): + win32serviceutil.ServiceFramework.__init__(self, args) + self.hWaitStop = CreateEvent(None, 0, 0, None) + self.overlapped = pywintypes.OVERLAPPED() + self.overlapped.hEvent = CreateEvent(None, 0, 0, None) + self.thread_handles = [] + + def CreatePipeSecurityObject(self): + # Create a security object giving World read/write access, + # but only "Owner" modify access. + sa = pywintypes.SECURITY_ATTRIBUTES() + sidEveryone = pywintypes.SID() + sidEveryone.Initialize(SECURITY_WORLD_SID_AUTHORITY, 1) + sidEveryone.SetSubAuthority(0, SECURITY_WORLD_RID) + sidCreator = pywintypes.SID() + sidCreator.Initialize(SECURITY_CREATOR_SID_AUTHORITY, 1) + sidCreator.SetSubAuthority(0, SECURITY_CREATOR_OWNER_RID) + + acl = pywintypes.ACL() + acl.AddAccessAllowedAce(FILE_GENERIC_READ | FILE_GENERIC_WRITE, sidEveryone) + acl.AddAccessAllowedAce(FILE_ALL_ACCESS, sidCreator) + + sa.SetSecurityDescriptorDacl(1, acl, 0) + return sa + + # The functions executed in their own thread to process a client request. + def DoProcessClient(self, pipeHandle, tid): + try: + try: + # Create a loop, reading large data. If we knew the data stream was + # was small, a simple ReadFile would do. + d = "".encode("ascii") # ensure bytes on py2k and py3k... + hr = winerror.ERROR_MORE_DATA + while hr == winerror.ERROR_MORE_DATA: + hr, thisd = ReadFile(pipeHandle, 256) + d = d + thisd + print("Read", d) + ok = 1 + except error: + # Client disconnection - do nothing + ok = 0 + + # A secure service would handle (and ignore!) errors writing to the + # pipe, but for the sake of this demo we dont (if only to see what errors + # we can get when our clients break at strange times :-) + if ok: + msg = ( + "%s (on thread %d) sent me %s" + % (GetNamedPipeHandleState(pipeHandle, False, True)[4], tid, d) + ).encode("ascii") + WriteFile(pipeHandle, msg) + finally: + ApplyIgnoreError(DisconnectNamedPipe, (pipeHandle,)) + ApplyIgnoreError(CloseHandle, (pipeHandle,)) + + def ProcessClient(self, pipeHandle): + try: + procHandle = GetCurrentProcess() + th = DuplicateHandle( + procHandle, + GetCurrentThread(), + procHandle, + 0, + 0, + win32con.DUPLICATE_SAME_ACCESS, + ) + try: + self.thread_handles.append(th) + try: + return self.DoProcessClient(pipeHandle, th) + except: + traceback.print_exc() + finally: + self.thread_handles.remove(th) + except: + traceback.print_exc() + + def SvcStop(self): + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) + SetEvent(self.hWaitStop) + + def SvcDoRun(self): + # Write an event log record - in debug mode we will also + # see this message printed. + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + servicemanager.PYS_SERVICE_STARTED, + (self._svc_name_, ""), + ) + + num_connections = 0 + while 1: + pipeHandle = CreateNamedPipe( + "\\\\.\\pipe\\PyPipeTest", + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE, + PIPE_UNLIMITED_INSTANCES, # max instances + 0, + 0, + 6000, + self.CreatePipeSecurityObject(), + ) + try: + hr = ConnectNamedPipe(pipeHandle, self.overlapped) + except error as details: + print("Error connecting pipe!", details) + CloseHandle(pipeHandle) + break + if hr == winerror.ERROR_PIPE_CONNECTED: + # Client is already connected - signal event + SetEvent(self.overlapped.hEvent) + rc = WaitForMultipleObjects( + (self.hWaitStop, self.overlapped.hEvent), 0, INFINITE + ) + if rc == WAIT_OBJECT_0: + # Stop event + break + else: + # Pipe event - spawn thread to deal with it. + _thread.start_new_thread(self.ProcessClient, (pipeHandle,)) + num_connections = num_connections + 1 + + # Sleep to ensure that any new threads are in the list, and then + # wait for all current threads to finish. + # What is a better way? + Sleep(500) + while self.thread_handles: + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING, 5000) + print("Waiting for %d threads to finish..." % (len(self.thread_handles))) + WaitForMultipleObjects(self.thread_handles, 1, 3000) + # Write another event log record. + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + servicemanager.PYS_SERVICE_STOPPED, + (self._svc_name_, " after processing %d connections" % (num_connections,)), + ) + + +if __name__ == "__main__": + win32serviceutil.HandleCommandLine(TestPipeService) diff --git a/MLPY/Lib/site-packages/win32/Demos/service/pipeTestServiceClient.py b/MLPY/Lib/site-packages/win32/Demos/service/pipeTestServiceClient.py new file mode 100644 index 0000000000000000000000000000000000000000..98fdb3c9600ca4fa1fbd1edf12230d67ed61b03d --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/service/pipeTestServiceClient.py @@ -0,0 +1,156 @@ +# A Test Program for pipeTestService.py +# +# Install and start the Pipe Test service, then run this test +# either from the same machine, or from another using the "-s" param. +# +# Eg: pipeTestServiceClient.py -s server_name Hi There +# Should work. + +import os +import sys +import traceback + +import pywintypes +import win32api +import winerror +from win32event import * +from win32file import * +from win32pipe import * + +verbose = 0 + +# def ReadFromPipe(pipeName): +# Could (Should?) use CallNamedPipe, but this technique allows variable size +# messages (whereas you must supply a buffer size for CallNamedPipe! +# hPipe = CreateFile(pipeName, GENERIC_WRITE, 0, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) +# more = 1 +# while more: +# hr = ReadFile(hPipe, 256) +# if hr==0: +# more = 0 +# except win32api.error (hr, fn, desc): +# if hr==winerror.ERROR_MORE_DATA: +# data = dat +# + + +def CallPipe(fn, args): + ret = None + retryCount = 0 + while retryCount < 8: # Keep looping until user cancels. + retryCount = retryCount + 1 + try: + return fn(*args) + except win32api.error as exc: + if exc.winerror == winerror.ERROR_PIPE_BUSY: + win32api.Sleep(5000) + continue + else: + raise + + raise RuntimeError("Could not make a connection to the server") + + +def testClient(server, msg): + if verbose: + print("Sending", msg) + data = CallPipe( + CallNamedPipe, + ("\\\\%s\\pipe\\PyPipeTest" % server, msg, 256, NMPWAIT_WAIT_FOREVER), + ) + if verbose: + print("Server sent back '%s'" % data) + print("Sent and received a message!") + + +def testLargeMessage(server, size=4096): + if verbose: + print("Sending message of size %d" % (size)) + msg = "*" * size + data = CallPipe( + CallNamedPipe, + ("\\\\%s\\pipe\\PyPipeTest" % server, msg, 512, NMPWAIT_WAIT_FOREVER), + ) + if len(data) - size: + print("Sizes are all wrong - send %d, got back %d" % (size, len(data))) + + +def stressThread(server, numMessages, wait): + try: + try: + for i in range(numMessages): + r = CallPipe( + CallNamedPipe, + ( + "\\\\%s\\pipe\\PyPipeTest" % server, + "#" * 512, + 1024, + NMPWAIT_WAIT_FOREVER, + ), + ) + except: + traceback.print_exc() + print("Failed after %d messages" % i) + finally: + SetEvent(wait) + + +def stressTestClient(server, numThreads, numMessages): + import _thread + + thread_waits = [] + for t_num in range(numThreads): + # Note I could just wait on thread handles (after calling DuplicateHandle) + # See the service itself for an example of waiting for the clients... + wait = CreateEvent(None, 0, 0, None) + thread_waits.append(wait) + _thread.start_new_thread(stressThread, (server, numMessages, wait)) + # Wait for all threads to finish. + WaitForMultipleObjects(thread_waits, 1, INFINITE) + + +def main(): + import getopt + import sys + + server = "." + thread_count = 0 + msg_count = 500 + try: + opts, args = getopt.getopt(sys.argv[1:], "s:t:m:vl") + for o, a in opts: + if o == "-s": + server = a + if o == "-m": + msg_count = int(a) + if o == "-t": + thread_count = int(a) + if o == "-v": + global verbose + verbose = 1 + if o == "-l": + testLargeMessage(server) + msg = " ".join(args).encode("mbcs") + except getopt.error as msg: + print(msg) + my_name = os.path.split(sys.argv[0])[1] + print( + "Usage: %s [-v] [-s server] [-t thread_count=0] [-m msg_count=500] msg ..." + % my_name + ) + print(" -v = verbose") + print( + " Specifying a value for -t will stress test using that many threads." + ) + return + testClient(server, msg) + if thread_count > 0: + print( + "Spawning %d threads each sending %d messages..." + % (thread_count, msg_count) + ) + stressTestClient(server, thread_count, msg_count) + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/service/serviceEvents.py b/MLPY/Lib/site-packages/win32/Demos/service/serviceEvents.py new file mode 100644 index 0000000000000000000000000000000000000000..a62784f954423bb07aba5bae3622bedf73d66588 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/service/serviceEvents.py @@ -0,0 +1,98 @@ +# A Demo of a service that takes advantage of the additional notifications +# available in later Windows versions. + +# Note that all output is written as event log entries - so you must install +# and start the service, then look at the event log for messages as events +# are generated. + +# Events are generated for USB device insertion and removal, power state +# changes and hardware profile events - so try putting your computer to +# sleep and waking it, inserting a memory stick, etc then check the event log + +# Most event notification support lives around win32gui +import servicemanager +import win32con +import win32event +import win32gui +import win32gui_struct +import win32service +import win32serviceutil + +GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}" + + +class EventDemoService(win32serviceutil.ServiceFramework): + _svc_name_ = "PyServiceEventDemo" + _svc_display_name_ = "Python Service Event Demo" + _svc_description_ = ( + "Demonstrates a Python service which takes advantage of the extra notifications" + ) + + def __init__(self, args): + win32serviceutil.ServiceFramework.__init__(self, args) + self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) + # register for a device notification - we pass our service handle + # instead of a window handle. + filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE( + GUID_DEVINTERFACE_USB_DEVICE + ) + self.hdn = win32gui.RegisterDeviceNotification( + self.ssh, filter, win32con.DEVICE_NOTIFY_SERVICE_HANDLE + ) + + # Override the base class so we can accept additional events. + def GetAcceptedControls(self): + # say we accept them all. + rc = win32serviceutil.ServiceFramework.GetAcceptedControls(self) + rc |= ( + win32service.SERVICE_ACCEPT_PARAMCHANGE + | win32service.SERVICE_ACCEPT_NETBINDCHANGE + | win32service.SERVICE_CONTROL_DEVICEEVENT + | win32service.SERVICE_ACCEPT_HARDWAREPROFILECHANGE + | win32service.SERVICE_ACCEPT_POWEREVENT + | win32service.SERVICE_ACCEPT_SESSIONCHANGE + ) + return rc + + # All extra events are sent via SvcOtherEx (SvcOther remains as a + # function taking only the first args for backwards compat) + def SvcOtherEx(self, control, event_type, data): + # This is only showing a few of the extra events - see the MSDN + # docs for "HandlerEx callback" for more info. + if control == win32service.SERVICE_CONTROL_DEVICEEVENT: + info = win32gui_struct.UnpackDEV_BROADCAST(data) + msg = "A device event occurred: %x - %s" % (event_type, info) + elif control == win32service.SERVICE_CONTROL_HARDWAREPROFILECHANGE: + msg = "A hardware profile changed: type=%s, data=%s" % (event_type, data) + elif control == win32service.SERVICE_CONTROL_POWEREVENT: + msg = "A power event: setting %s" % data + elif control == win32service.SERVICE_CONTROL_SESSIONCHANGE: + # data is a single elt tuple, but this could potentially grow + # in the future if the win32 struct does + msg = "Session event: type=%s, data=%s" % (event_type, data) + else: + msg = "Other event: code=%d, type=%s, data=%s" % (control, event_type, data) + + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + 0xF000, # generic message + (msg, ""), + ) + + def SvcStop(self): + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) + win32event.SetEvent(self.hWaitStop) + + def SvcDoRun(self): + # do nothing at all - just wait to be stopped + win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) + # Write a stop message. + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + servicemanager.PYS_SERVICE_STOPPED, + (self._svc_name_, ""), + ) + + +if __name__ == "__main__": + win32serviceutil.HandleCommandLine(EventDemoService) diff --git a/MLPY/Lib/site-packages/win32/Demos/timer_demo.py b/MLPY/Lib/site-packages/win32/Demos/timer_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..61115f065523c625c33c2c51ed5aa555b6869bcf --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/timer_demo.py @@ -0,0 +1,72 @@ +# -*- Mode: Python; tab-width: 4 -*- +# + +# This module, and the timer.pyd core timer support, were written by +# Sam Rushing (rushing@nightmare.com) + +import time + +# Timers are based on Windows messages. So we need +# to do the event-loop thing! +import timer +import win32event +import win32gui + +# glork holds a simple counter for us. + + +class glork: + def __init__(self, delay=1000, max=10): + self.x = 0 + self.max = max + self.id = timer.set_timer(delay, self.increment) + # Could use the threading module, but this is + # a win32 extension test after all! :-) + self.event = win32event.CreateEvent(None, 0, 0, None) + + def increment(self, id, time): + print("x = %d" % self.x) + self.x = self.x + 1 + # if we've reached the max count, + # kill off the timer. + if self.x > self.max: + # we could have used 'self.id' here, too + timer.kill_timer(id) + win32event.SetEvent(self.event) + + +# create a counter that will count from '1' thru '10', incrementing +# once a second, and then stop. + + +def demo(delay=1000, stop=10): + g = glork(delay, stop) + # Timers are message based - so we need + # To run a message loop while waiting for our timers + # to expire. + start_time = time.time() + while 1: + # We can't simply give a timeout of 30 seconds, as + # we may continouusly be recieving other input messages, + # and therefore never expire. + rc = win32event.MsgWaitForMultipleObjects( + (g.event,), # list of objects + 0, # wait all + 500, # timeout + win32event.QS_ALLEVENTS, # type of input + ) + if rc == win32event.WAIT_OBJECT_0: + # Event signalled. + break + elif rc == win32event.WAIT_OBJECT_0 + 1: + # Message waiting. + if win32gui.PumpWaitingMessages(): + raise RuntimeError("We got an unexpected WM_QUIT message!") + else: + # This wait timed-out. + if time.time() - start_time > 30: + raise RuntimeError("We timed out waiting for the timers to expire!") + + +if __name__ == "__main__": + demo() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32clipboardDemo.py b/MLPY/Lib/site-packages/win32/Demos/win32clipboardDemo.py new file mode 100644 index 0000000000000000000000000000000000000000..1252ff7d59be7904aedcc3c6a363bd931d2bfa44 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32clipboardDemo.py @@ -0,0 +1,145 @@ +# win32clipboardDemo.py +# +# Demo/test of the win32clipboard module. + +import win32con +from pywin32_testutil import str2bytes # py3k-friendly helper +from win32clipboard import * + +if not __debug__: + print("WARNING: The test code in this module uses assert") + print("This instance of Python has asserts disabled, so many tests will be skipped") + +cf_names = {} +# Build map of CF_* constants to names. +for name, val in list(win32con.__dict__.items()): + if name[:3] == "CF_" and name != "CF_SCREENFONTS": # CF_SCREEN_FONTS==CF_TEXT!?!? + cf_names[val] = name + + +def TestEmptyClipboard(): + OpenClipboard() + try: + EmptyClipboard() + assert ( + EnumClipboardFormats(0) == 0 + ), "Clipboard formats were available after emptying it!" + finally: + CloseClipboard() + + +def TestText(): + OpenClipboard() + try: + text = "Hello from Python" + text_bytes = str2bytes(text) + SetClipboardText(text) + got = GetClipboardData(win32con.CF_TEXT) + # CF_TEXT always gives us 'bytes' back . + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + finally: + CloseClipboard() + + OpenClipboard() + try: + # CF_UNICODE text always gives unicode objects back. + got = GetClipboardData(win32con.CF_UNICODETEXT) + assert got == text, "Didnt get the correct result back - '%r'." % (got,) + assert type(got) == str, "Didnt get the correct result back - '%r'." % (got,) + + # CF_OEMTEXT is a bytes-based format. + got = GetClipboardData(win32con.CF_OEMTEXT) + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + + # Unicode tests + EmptyClipboard() + text = "Hello from Python unicode" + text_bytes = str2bytes(text) + # Now set the Unicode value + SetClipboardData(win32con.CF_UNICODETEXT, text) + # Get it in Unicode. + got = GetClipboardData(win32con.CF_UNICODETEXT) + assert got == text, "Didnt get the correct result back - '%r'." % (got,) + assert type(got) == str, "Didnt get the correct result back - '%r'." % (got,) + + # Close and open the clipboard to ensure auto-conversions take place. + finally: + CloseClipboard() + + OpenClipboard() + try: + # Make sure I can still get the text as bytes + got = GetClipboardData(win32con.CF_TEXT) + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + # Make sure we get back the correct types. + got = GetClipboardData(win32con.CF_UNICODETEXT) + assert type(got) == str, "Didnt get the correct result back - '%r'." % (got,) + got = GetClipboardData(win32con.CF_OEMTEXT) + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + print("Clipboard text tests worked correctly") + finally: + CloseClipboard() + + +def TestClipboardEnum(): + OpenClipboard() + try: + # Enumerate over the clipboard types + enum = 0 + while 1: + enum = EnumClipboardFormats(enum) + if enum == 0: + break + assert IsClipboardFormatAvailable( + enum + ), "Have format, but clipboard says it is not available!" + n = cf_names.get(enum, "") + if not n: + try: + n = GetClipboardFormatName(enum) + except error: + n = "unknown (%s)" % (enum,) + + print("Have format", n) + print("Clipboard enumerator tests worked correctly") + finally: + CloseClipboard() + + +class Foo: + def __init__(self, **kw): + self.__dict__.update(kw) + + def __cmp__(self, other): + return cmp(self.__dict__, other.__dict__) + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + +def TestCustomFormat(): + OpenClipboard() + try: + # Just for the fun of it pickle Python objects through the clipboard + fmt = RegisterClipboardFormat("Python Pickle Format") + import pickle + + pickled_object = Foo(a=1, b=2, Hi=3) + SetClipboardData(fmt, pickle.dumps(pickled_object)) + # Now read it back. + data = GetClipboardData(fmt) + loaded_object = pickle.loads(data) + assert pickle.loads(data) == pickled_object, "Didnt get the correct data!" + + print("Clipboard custom format tests worked correctly") + finally: + CloseClipboard() + + +if __name__ == "__main__": + TestEmptyClipboard() + TestText() + TestCustomFormat() + TestClipboardEnum() + # And leave it empty at the end! + TestEmptyClipboard() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32clipboard_bitmapdemo.py b/MLPY/Lib/site-packages/win32/Demos/win32clipboard_bitmapdemo.py new file mode 100644 index 0000000000000000000000000000000000000000..7d453025fb1fd07cc23feafb7f7f6615ea48c6c1 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32clipboard_bitmapdemo.py @@ -0,0 +1,117 @@ +import win32api +import win32clipboard +import win32con +import win32gui + + +class ViewerWindow: + def __init__(self): + self.hwndNextViewer = None + + def OnPaint(self, hwnd, msg, wp, lp): + dc, ps = win32gui.BeginPaint(hwnd) + wndrect = win32gui.GetClientRect(hwnd) + wndwidth = wndrect[2] - wndrect[0] + wndheight = wndrect[3] - wndrect[1] + win32clipboard.OpenClipboard() + try: + try: + hbitmap = win32clipboard.GetClipboardData(win32clipboard.CF_BITMAP) + except TypeError: + font = win32gui.LOGFONT() + font.lfHeight = 15 # int(wndheight/20) + font.lfWidth = 15 # font.lfHeight + # font.lfWeight=150 + hf = win32gui.CreateFontIndirect(font) + win32gui.SelectObject(dc, hf) + win32gui.SetBkMode(dc, win32con.TRANSPARENT) + win32gui.SetTextColor(dc, win32api.RGB(0, 0, 0)) + win32gui.DrawText( + dc, + "No bitmaps are in the clipboard\n(try pressing the PrtScn button)", + -1, + (0, 0, wndwidth, wndheight), + win32con.DT_CENTER, + ) + else: + bminfo = win32gui.GetObject(hbitmap) + dcDC = win32gui.CreateCompatibleDC(None) + win32gui.SelectObject(dcDC, hbitmap) + win32gui.StretchBlt( + dc, + 0, + 0, + wndwidth, + wndheight, + dcDC, + 0, + 0, + bminfo.bmWidth, + bminfo.bmHeight, + win32con.SRCCOPY, + ) + win32gui.DeleteDC(dcDC) + win32gui.EndPaint(hwnd, ps) + finally: + win32clipboard.CloseClipboard() + return 0 + + def OnDrawClipboard(self, hwnd, msg, wp, lp): + win32gui.InvalidateRect(hwnd, None, True) + + def OnChangeCBChain(self, hwnd, msg, wp, lp): + # If the next window is closing, repair the chain. + if wp == self.hwndNextViewer: + self.hwndNextViewer = lp + # Otherwise, pass the message to the next link. + elif self.hwndNextViewer: + win32gui.SendMessage(self.hwndNextViewer, msg, wp, lp) + + def OnCreate(self, hwnd, msg, wp, lp): + self.hwndNextViewer = win32gui.SetClipboardViewer(hwnd) + + def OnClose(self, hwnd, msg, wp, lp): + win32clipboard.ChangeClipboardChain(hwnd, self.hwndNextViewer) + win32gui.DestroyWindow(hwnd) + win32gui.PostQuitMessage(0) + + def go(self): + wndproc = { + win32con.WM_PAINT: self.OnPaint, + win32con.WM_CLOSE: self.OnClose, + win32con.WM_CREATE: self.OnCreate, + win32con.WM_DRAWCLIPBOARD: self.OnDrawClipboard, + win32con.WM_CHANGECBCHAIN: self.OnChangeCBChain, + } + + wc = win32gui.WNDCLASS() + wc.lpszClassName = "test_win32clipboard_bmp" + wc.style = win32con.CS_GLOBALCLASS | win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW + 1 + wc.lpfnWndProc = wndproc + class_atom = win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindowEx( + 0, + class_atom, + "ClipboardViewer", + win32con.WS_CAPTION + | win32con.WS_VISIBLE + | win32con.WS_THICKFRAME + | win32con.WS_SYSMENU, + 100, + 100, + 900, + 900, + 0, + 0, + 0, + None, + ) + win32clipboard.SetClipboardViewer(hwnd) + win32gui.PumpMessages() + win32gui.UnregisterClass(class_atom, None) + + +if __name__ == "__main__": + w = ViewerWindow() + w.go() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32comport_demo.py b/MLPY/Lib/site-packages/win32/Demos/win32comport_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..c0be23917ed18ed956fa137662ebd9afaf04538e --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32comport_demo.py @@ -0,0 +1,144 @@ +# This is a simple serial port terminal demo. +# +# Its primary purpose is to demonstrate the native serial port access offered via +# win32file. + +# It uses 3 threads: +# - The main thread, which cranks up the other 2 threads, then simply waits for them to exit. +# - The user-input thread - blocks waiting for a keyboard character, and when found sends it +# out the COM port. If the character is Ctrl+C, it stops, signalling the COM port thread to stop. +# - The COM port thread is simply listening for input on the COM port, and prints it to the screen. + +# This demo uses userlapped IO, so that none of the read or write operations actually block (however, +# in this sample, the very next thing we do _is_ block - so it shows off the concepts even though it +# doesnt exploit them. + +import msvcrt # For the getch() function. +import sys +import threading + +import win32con # constants. +from win32event import * # We use events and the WaitFor[Multiple]Objects functions. +from win32file import * # The base COM port and file IO functions. + + +def FindModem(): + # Snoop over the comports, seeing if it is likely we have a modem. + for i in range(1, 5): + port = "COM%d" % (i,) + try: + handle = CreateFile( + port, + win32con.GENERIC_READ | win32con.GENERIC_WRITE, + 0, # exclusive access + None, # no security + win32con.OPEN_EXISTING, + win32con.FILE_ATTRIBUTE_NORMAL, + None, + ) + # It appears that an available COM port will always success here, + # just return 0 for the status flags. We only care that it has _any_ status + # flags (and therefore probably a real modem) + if GetCommModemStatus(handle) != 0: + return port + except error: + pass # No port, or modem status failed. + return None + + +# A basic synchronous COM port file-like object +class SerialTTY: + def __init__(self, port): + if type(port) == type(0): + port = "COM%d" % (port,) + self.handle = CreateFile( + port, + win32con.GENERIC_READ | win32con.GENERIC_WRITE, + 0, # exclusive access + None, # no security + win32con.OPEN_EXISTING, + win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_FLAG_OVERLAPPED, + None, + ) + # Tell the port we want a notification on each char. + SetCommMask(self.handle, EV_RXCHAR) + # Setup a 4k buffer + SetupComm(self.handle, 4096, 4096) + # Remove anything that was there + PurgeComm( + self.handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR + ) + # Setup for overlapped IO. + timeouts = 0xFFFFFFFF, 0, 1000, 0, 1000 + SetCommTimeouts(self.handle, timeouts) + # Setup the connection info. + dcb = GetCommState(self.handle) + dcb.BaudRate = CBR_115200 + dcb.ByteSize = 8 + dcb.Parity = NOPARITY + dcb.StopBits = ONESTOPBIT + SetCommState(self.handle, dcb) + print("Connected to %s at %s baud" % (port, dcb.BaudRate)) + + def _UserInputReaderThread(self): + overlapped = OVERLAPPED() + overlapped.hEvent = CreateEvent(None, 1, 0, None) + try: + while 1: + ch = msvcrt.getch() + if ord(ch) == 3: + break + WriteFile(self.handle, ch, overlapped) + # Wait for the write to complete. + WaitForSingleObject(overlapped.hEvent, INFINITE) + finally: + SetEvent(self.eventStop) + + def _ComPortThread(self): + overlapped = OVERLAPPED() + overlapped.hEvent = CreateEvent(None, 1, 0, None) + while 1: + # XXX - note we could _probably_ just use overlapped IO on the win32file.ReadFile() statement + # XXX but this tests the COM stuff! + rc, mask = WaitCommEvent(self.handle, overlapped) + if rc == 0: # Character already ready! + SetEvent(overlapped.hEvent) + rc = WaitForMultipleObjects( + [overlapped.hEvent, self.eventStop], 0, INFINITE + ) + if rc == WAIT_OBJECT_0: + # Some input - read and print it + flags, comstat = ClearCommError(self.handle) + rc, data = ReadFile(self.handle, comstat.cbInQue, overlapped) + WaitForSingleObject(overlapped.hEvent, INFINITE) + sys.stdout.write(data) + else: + # Stop the thread! + # Just incase the user input thread uis still going, close it + sys.stdout.close() + break + + def Run(self): + self.eventStop = CreateEvent(None, 0, 0, None) + # Start the reader and writer threads. + user_thread = threading.Thread(target=self._UserInputReaderThread) + user_thread.start() + com_thread = threading.Thread(target=self._ComPortThread) + com_thread.start() + user_thread.join() + com_thread.join() + + +if __name__ == "__main__": + print("Serial port terminal demo - press Ctrl+C to exit") + if len(sys.argv) <= 1: + port = FindModem() + if port is None: + print("No COM port specified, and no modem could be found") + print("Please re-run this script with the name of a COM port (eg COM3)") + sys.exit(1) + else: + port = sys.argv[1] + + tty = SerialTTY(port) + tty.Run() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32console_demo.py b/MLPY/Lib/site-packages/win32/Demos/win32console_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..bb9162bff5ab023abd8575bd4a471b78d7814ef3 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32console_demo.py @@ -0,0 +1,135 @@ +import time + +import win32con +import win32console + +virtual_keys = {} +for k, v in list(win32con.__dict__.items()): + if k.startswith("VK_"): + virtual_keys[v] = k + +free_console = True +try: + win32console.AllocConsole() +except win32console.error as exc: + if exc.winerror != 5: + raise + ## only free console if one was created successfully + free_console = False + +stdout = win32console.GetStdHandle(win32console.STD_OUTPUT_HANDLE) +stdin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE) +newbuffer = win32console.CreateConsoleScreenBuffer() +newbuffer.SetConsoleActiveScreenBuffer() +newbuffer.SetConsoleTextAttribute( + win32console.FOREGROUND_RED + | win32console.FOREGROUND_INTENSITY + | win32console.BACKGROUND_GREEN + | win32console.BACKGROUND_INTENSITY +) +newbuffer.WriteConsole("This is a new screen buffer\n") + +## test setting screen buffer and window size +## screen buffer size cannot be smaller than window size +window_size = newbuffer.GetConsoleScreenBufferInfo()["Window"] +coord = win32console.PyCOORDType(X=window_size.Right + 20, Y=window_size.Bottom + 20) +newbuffer.SetConsoleScreenBufferSize(coord) + +window_size.Right += 10 +window_size.Bottom += 10 +newbuffer.SetConsoleWindowInfo(Absolute=True, ConsoleWindow=window_size) + +## write some records to the input queue +x = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT) +x.Char = "X" +x.KeyDown = True +x.RepeatCount = 1 +x.VirtualKeyCode = 0x58 +x.ControlKeyState = win32con.SHIFT_PRESSED + +z = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT) +z.Char = "Z" +z.KeyDown = True +z.RepeatCount = 1 +z.VirtualKeyCode = 0x5A +z.ControlKeyState = win32con.SHIFT_PRESSED + +stdin.WriteConsoleInput([x, z, x]) + +newbuffer.SetConsoleTextAttribute( + win32console.FOREGROUND_RED + | win32console.FOREGROUND_INTENSITY + | win32console.BACKGROUND_GREEN + | win32console.BACKGROUND_INTENSITY +) +newbuffer.WriteConsole("Press some keys, click some characters with the mouse\n") + +newbuffer.SetConsoleTextAttribute( + win32console.FOREGROUND_BLUE + | win32console.FOREGROUND_INTENSITY + | win32console.BACKGROUND_RED + | win32console.BACKGROUND_INTENSITY +) +newbuffer.WriteConsole('Hit "End" key to quit\n') + +breakout = False +while not breakout: + input_records = stdin.ReadConsoleInput(10) + for input_record in input_records: + if input_record.EventType == win32console.KEY_EVENT: + if input_record.KeyDown: + if input_record.Char == "\0": + newbuffer.WriteConsole( + virtual_keys.get( + input_record.VirtualKeyCode, + "VirtualKeyCode: %s" % input_record.VirtualKeyCode, + ) + ) + else: + newbuffer.WriteConsole(input_record.Char) + if input_record.VirtualKeyCode == win32con.VK_END: + breakout = True + break + elif input_record.EventType == win32console.MOUSE_EVENT: + if input_record.EventFlags == 0: ## 0 indicates a button event + if input_record.ButtonState != 0: ## exclude button releases + pos = input_record.MousePosition + # switch the foreground and background colors of the character that was clicked + attr = newbuffer.ReadConsoleOutputAttribute( + Length=1, ReadCoord=pos + )[0] + new_attr = attr + if attr & win32console.FOREGROUND_BLUE: + new_attr = ( + new_attr & ~win32console.FOREGROUND_BLUE + ) | win32console.BACKGROUND_BLUE + if attr & win32console.FOREGROUND_RED: + new_attr = ( + new_attr & ~win32console.FOREGROUND_RED + ) | win32console.BACKGROUND_RED + if attr & win32console.FOREGROUND_GREEN: + new_attr = ( + new_attr & ~win32console.FOREGROUND_GREEN + ) | win32console.BACKGROUND_GREEN + + if attr & win32console.BACKGROUND_BLUE: + new_attr = ( + new_attr & ~win32console.BACKGROUND_BLUE + ) | win32console.FOREGROUND_BLUE + if attr & win32console.BACKGROUND_RED: + new_attr = ( + new_attr & ~win32console.BACKGROUND_RED + ) | win32console.FOREGROUND_RED + if attr & win32console.BACKGROUND_GREEN: + new_attr = ( + new_attr & ~win32console.BACKGROUND_GREEN + ) | win32console.FOREGROUND_GREEN + newbuffer.WriteConsoleOutputAttribute((new_attr,), pos) + else: + newbuffer.WriteConsole(str(input_record)) + time.sleep(0.1) + +stdout.SetConsoleActiveScreenBuffer() +newbuffer.Close() +if free_console: + win32console.FreeConsole() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32cred_demo.py b/MLPY/Lib/site-packages/win32/Demos/win32cred_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..3b49ca7c8f8f4efa1d6073c24e17b91f967825e0 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32cred_demo.py @@ -0,0 +1,82 @@ +""" +Demonstrates prompting for credentials, saving, and loggging on with marshalled credential. +Also shows how to load user's profile +""" + +import win32api +import win32con +import win32cred +import win32net +import win32profile +import win32security + +## Prompt for a username/pwd for local computer +uiinfo = { + "MessageText": "Enter credentials for local machine", + "CaptionText": "win32cred_demo.py", +} +target, pwd, save = win32cred.CredUIPromptForCredentials( + TargetName=win32api.GetComputerName(), + AuthError=0, + Flags=win32cred.CREDUI_FLAGS_DO_NOT_PERSIST + | win32cred.CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX, + Save=False, + UiInfo=uiinfo, +) + +attrs = [ + {"Keyword": "attr1", "Flags": 0, "Value": "unicode data"}, + {"Keyword": "attr2", "Flags": 0, "Value": b"character data"}, +] +cred = { + "Comment": "Created by win32cred_demo.py", + "UserName": target, + "TargetAlias": None, + "TargetName": target, + "CredentialBlob": pwd, + "Flags": win32cred.CRED_FLAGS_USERNAME_TARGET, + "Persist": win32cred.CRED_PERSIST_ENTERPRISE, + "Type": win32cred.CRED_TYPE_DOMAIN_PASSWORD, + "Attributes": attrs, +} +win32cred.CredWrite(cred) +pwd = None +print(win32cred.CredRead(target, win32cred.CRED_TYPE_DOMAIN_PASSWORD)) + +## Marshal saved credential and use it to log on +mc = win32cred.CredMarshalCredential(win32cred.UsernameTargetCredential, target) + +# As of pywin32 301 this no longer works for markh and unclear when it stopped, or +# even if it ever did! # Fails in Python 2.7 too, so not a 3.x regression. +try: + th = win32security.LogonUser( + mc, + None, + "", + win32con.LOGON32_LOGON_INTERACTIVE, + win32con.LOGON32_PROVIDER_DEFAULT, + ) + win32security.ImpersonateLoggedOnUser(th) + print("GetUserName:", win32api.GetUserName()) + win32security.RevertToSelf() + + ## Load user's profile. (first check if user has a roaming profile) + username, domain = win32cred.CredUIParseUserName(target) + user_info_4 = win32net.NetUserGetInfo(None, username, 4) + profilepath = user_info_4["profile"] + ## LoadUserProfile apparently doesn't like an empty string + if not profilepath: + profilepath = None + + ## leave Flags in since 2.3 still chokes on some types of optional keyword args + hk = win32profile.LoadUserProfile( + th, {"UserName": username, "Flags": 0, "ProfilePath": profilepath} + ) + ## Get user's environment variables in a form that can be passed to win32process.CreateProcessAsUser + env = win32profile.CreateEnvironmentBlock(th, False) + + ## Cleanup should probably be in a finally block + win32profile.UnloadUserProfile(th, hk) + th.Close() +except win32security.error as exc: + print("Failed to login for some reason", exc) diff --git a/MLPY/Lib/site-packages/win32/Demos/win32fileDemo.py b/MLPY/Lib/site-packages/win32/Demos/win32fileDemo.py new file mode 100644 index 0000000000000000000000000000000000000000..a80999251abd86c450c12031ab200fd39c2db8a4 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32fileDemo.py @@ -0,0 +1,41 @@ +# This is a "demo" of win32file - it used to be more a test case than a +# demo, so has been moved to the test directory. + +import os + +# Please contribute your favourite simple little demo. +import win32api +import win32con +import win32file + + +# A very simple demo - note that this does no more than you can do with +# builtin Python file objects, so for something as simple as this, you +# generally *should* use builtin Python objects. Only use win32file etc +# when you need win32 specific features not available in Python. +def SimpleFileDemo(): + testName = os.path.join(win32api.GetTempPath(), "win32file_demo_test_file") + if os.path.exists(testName): + os.unlink(testName) + # Open the file for writing. + handle = win32file.CreateFile( + testName, win32file.GENERIC_WRITE, 0, None, win32con.CREATE_NEW, 0, None + ) + test_data = "Hello\0there".encode("ascii") + win32file.WriteFile(handle, test_data) + handle.Close() + # Open it for reading. + handle = win32file.CreateFile( + testName, win32file.GENERIC_READ, 0, None, win32con.OPEN_EXISTING, 0, None + ) + rc, data = win32file.ReadFile(handle, 1024) + handle.Close() + if data == test_data: + print("Successfully wrote and read a file") + else: + raise Exception("Got different data back???") + os.unlink(testName) + + +if __name__ == "__main__": + SimpleFileDemo() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32gui_demo.py b/MLPY/Lib/site-packages/win32/Demos/win32gui_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..41844a929c368fc223db642df89f73167dc5ce89 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32gui_demo.py @@ -0,0 +1,177 @@ +# The start of a win32gui generic demo. +# Feel free to contribute more demos back ;-) + +import math +import random +import time + +import win32api +import win32con +import win32gui + + +def _MyCallback(hwnd, extra): + hwnds, classes = extra + hwnds.append(hwnd) + classes[win32gui.GetClassName(hwnd)] = 1 + + +def TestEnumWindows(): + windows = [] + classes = {} + win32gui.EnumWindows(_MyCallback, (windows, classes)) + print( + "Enumerated a total of %d windows with %d classes" + % (len(windows), len(classes)) + ) + if "tooltips_class32" not in classes: + print("Hrmmmm - I'm very surprised to not find a 'tooltips_class32' class.") + + +def OnPaint_1(hwnd, msg, wp, lp): + dc, ps = win32gui.BeginPaint(hwnd) + win32gui.SetGraphicsMode(dc, win32con.GM_ADVANCED) + br = win32gui.CreateSolidBrush(win32api.RGB(255, 0, 0)) + win32gui.SelectObject(dc, br) + angle = win32gui.GetWindowLong(hwnd, win32con.GWL_USERDATA) + win32gui.SetWindowLong(hwnd, win32con.GWL_USERDATA, angle + 2) + r_angle = angle * (math.pi / 180) + win32gui.SetWorldTransform( + dc, + { + "M11": math.cos(r_angle), + "M12": math.sin(r_angle), + "M21": math.sin(r_angle) * -1, + "M22": math.cos(r_angle), + "Dx": 250, + "Dy": 250, + }, + ) + win32gui.MoveToEx(dc, 250, 250) + win32gui.BeginPath(dc) + win32gui.Pie(dc, 10, 70, 200, 200, 350, 350, 75, 10) + win32gui.Chord(dc, 200, 200, 850, 0, 350, 350, 75, 10) + win32gui.LineTo(dc, 300, 300) + win32gui.LineTo(dc, 100, 20) + win32gui.LineTo(dc, 20, 100) + win32gui.LineTo(dc, 400, 0) + win32gui.LineTo(dc, 0, 400) + win32gui.EndPath(dc) + win32gui.StrokeAndFillPath(dc) + win32gui.EndPaint(hwnd, ps) + return 0 + + +wndproc_1 = {win32con.WM_PAINT: OnPaint_1} + + +def OnPaint_2(hwnd, msg, wp, lp): + dc, ps = win32gui.BeginPaint(hwnd) + win32gui.SetGraphicsMode(dc, win32con.GM_ADVANCED) + l, t, r, b = win32gui.GetClientRect(hwnd) + + for x in range(25): + vertices = ( + { + "x": int(random.random() * r), + "y": int(random.random() * b), + "Red": int(random.random() * 0xFF00), + "Green": 0, + "Blue": 0, + "Alpha": 0, + }, + { + "x": int(random.random() * r), + "y": int(random.random() * b), + "Red": 0, + "Green": int(random.random() * 0xFF00), + "Blue": 0, + "Alpha": 0, + }, + { + "x": int(random.random() * r), + "y": int(random.random() * b), + "Red": 0, + "Green": 0, + "Blue": int(random.random() * 0xFF00), + "Alpha": 0, + }, + ) + mesh = ((0, 1, 2),) + win32gui.GradientFill(dc, vertices, mesh, win32con.GRADIENT_FILL_TRIANGLE) + win32gui.EndPaint(hwnd, ps) + return 0 + + +wndproc_2 = {win32con.WM_PAINT: OnPaint_2} + + +def TestSetWorldTransform(): + wc = win32gui.WNDCLASS() + wc.lpszClassName = "test_win32gui_1" + wc.style = win32con.CS_GLOBALCLASS | win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW + 1 + wc.lpfnWndProc = wndproc_1 + class_atom = win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindow( + wc.lpszClassName, + "Spin the Lobster!", + win32con.WS_CAPTION | win32con.WS_VISIBLE, + 100, + 100, + 900, + 900, + 0, + 0, + 0, + None, + ) + for x in range(500): + win32gui.InvalidateRect(hwnd, None, True) + win32gui.PumpWaitingMessages() + time.sleep(0.01) + win32gui.DestroyWindow(hwnd) + win32gui.UnregisterClass(wc.lpszClassName, None) + + +def TestGradientFill(): + wc = win32gui.WNDCLASS() + wc.lpszClassName = "test_win32gui_2" + wc.style = win32con.CS_GLOBALCLASS | win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW + 1 + wc.lpfnWndProc = wndproc_2 + class_atom = win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindowEx( + 0, + class_atom, + "Kaleidoscope", + win32con.WS_CAPTION + | win32con.WS_VISIBLE + | win32con.WS_THICKFRAME + | win32con.WS_SYSMENU, + 100, + 100, + 900, + 900, + 0, + 0, + 0, + None, + ) + s = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, s | win32con.WS_EX_LAYERED) + win32gui.SetLayeredWindowAttributes(hwnd, 0, 175, win32con.LWA_ALPHA) + for x in range(30): + win32gui.InvalidateRect(hwnd, None, True) + win32gui.PumpWaitingMessages() + time.sleep(0.3) + win32gui.DestroyWindow(hwnd) + win32gui.UnregisterClass(class_atom, None) + + +print("Enumerating all windows...") +TestEnumWindows() +print("Testing drawing functions ...") +TestSetWorldTransform() +TestGradientFill() +print("All tests done!") diff --git a/MLPY/Lib/site-packages/win32/Demos/win32gui_devicenotify.py b/MLPY/Lib/site-packages/win32/Demos/win32gui_devicenotify.py new file mode 100644 index 0000000000000000000000000000000000000000..34ad8a259cb6035956775933035884c73a734807 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32gui_devicenotify.py @@ -0,0 +1,107 @@ +# Demo RegisterDeviceNotification etc. Creates a hidden window to receive +# notifications. See serviceEvents.py for an example of a service doing +# that. +import sys +import time + +import win32api +import win32con +import win32file +import win32gui +import win32gui_struct +import winnt + +# These device GUIDs are from Ioevent.h in the Windows SDK. Ideally they +# could be collected somewhere for pywin32... +GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}" + + +# WM_DEVICECHANGE message handler. +def OnDeviceChange(hwnd, msg, wp, lp): + # Unpack the 'lp' into the appropriate DEV_BROADCAST_* structure, + # using the self-identifying data inside the DEV_BROADCAST_HDR. + info = win32gui_struct.UnpackDEV_BROADCAST(lp) + print("Device change notification:", wp, str(info)) + if ( + wp == win32con.DBT_DEVICEQUERYREMOVE + and info.devicetype == win32con.DBT_DEVTYP_HANDLE + ): + # Our handle is stored away in the structure - just close it + print("Device being removed - closing handle") + win32file.CloseHandle(info.handle) + # and cancel our notifications - if it gets plugged back in we get + # the same notification and try and close the same handle... + win32gui.UnregisterDeviceNotification(info.hdevnotify) + return True + + +def TestDeviceNotifications(dir_names): + wc = win32gui.WNDCLASS() + wc.lpszClassName = "test_devicenotify" + wc.style = win32con.CS_GLOBALCLASS | win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW + 1 + wc.lpfnWndProc = {win32con.WM_DEVICECHANGE: OnDeviceChange} + class_atom = win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindow( + wc.lpszClassName, + "Testing some devices", + # no need for it to be visible. + win32con.WS_CAPTION, + 100, + 100, + 900, + 900, + 0, + 0, + 0, + None, + ) + + hdevs = [] + # Watch for all USB device notifications + filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE( + GUID_DEVINTERFACE_USB_DEVICE + ) + hdev = win32gui.RegisterDeviceNotification( + hwnd, filter, win32con.DEVICE_NOTIFY_WINDOW_HANDLE + ) + hdevs.append(hdev) + # and create handles for all specified directories + for d in dir_names: + hdir = win32file.CreateFile( + d, + winnt.FILE_LIST_DIRECTORY, + winnt.FILE_SHARE_READ | winnt.FILE_SHARE_WRITE | winnt.FILE_SHARE_DELETE, + None, # security attributes + win32con.OPEN_EXISTING, + win32con.FILE_FLAG_BACKUP_SEMANTICS + | win32con.FILE_FLAG_OVERLAPPED, # required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME. + None, + ) + + filter = win32gui_struct.PackDEV_BROADCAST_HANDLE(hdir) + hdev = win32gui.RegisterDeviceNotification( + hwnd, filter, win32con.DEVICE_NOTIFY_WINDOW_HANDLE + ) + hdevs.append(hdev) + + # now start a message pump and wait for messages to be delivered. + print("Watching", len(hdevs), "handles - press Ctrl+C to terminate, or") + print("add and remove some USB devices...") + if not dir_names: + print("(Note you can also pass paths to watch on the command-line - eg,") + print("pass the root of an inserted USB stick to see events specific to") + print("that volume)") + while 1: + win32gui.PumpWaitingMessages() + time.sleep(0.01) + win32gui.DestroyWindow(hwnd) + win32gui.UnregisterClass(wc.lpszClassName, None) + + +if __name__ == "__main__": + # optionally pass device/directory names to watch for notifications. + # Eg, plug in a USB device - assume it connects as E: - then execute: + # % win32gui_devicenotify.py E: + # Then remove and insert the device. + TestDeviceNotifications(sys.argv[1:]) diff --git a/MLPY/Lib/site-packages/win32/Demos/win32gui_dialog.py b/MLPY/Lib/site-packages/win32/Demos/win32gui_dialog.py new file mode 100644 index 0000000000000000000000000000000000000000..e3b89ba9d37b085cf563185bb05970e80e88f4fe --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32gui_dialog.py @@ -0,0 +1,458 @@ +# A demo of a fairly complex dialog. +# +# Features: +# * Uses a "dynamic dialog resource" to build the dialog. +# * Uses a ListView control. +# * Dynamically resizes content. +# * Uses a second worker thread to fill the list. +# * Demostrates support for windows XP themes. + +# If you are on Windows XP, and specify a '--noxp' argument, you will see: +# * alpha-blend issues with icons +# * The buttons are "old" style, rather than based on the XP theme. +# Hence, using: +# import winxpgui as win32gui +# is recommended. +# Please report any problems. +import sys + +if "--noxp" in sys.argv: + import win32gui +else: + import winxpgui as win32gui + +import array +import os +import queue +import struct + +import commctrl +import win32api +import win32con +import win32gui_struct +import winerror + +IDC_SEARCHTEXT = 1024 +IDC_BUTTON_SEARCH = 1025 +IDC_BUTTON_DISPLAY = 1026 +IDC_LISTBOX = 1027 + +WM_SEARCH_RESULT = win32con.WM_USER + 512 +WM_SEARCH_FINISHED = win32con.WM_USER + 513 + + +class _WIN32MASKEDSTRUCT: + def __init__(self, **kw): + full_fmt = "" + for name, fmt, default, mask in self._struct_items_: + self.__dict__[name] = None + if fmt == "z": + full_fmt += "pi" + else: + full_fmt += fmt + for name, val in kw.items(): + if name not in self.__dict__: + raise ValueError("LVITEM structures do not have an item '%s'" % (name,)) + self.__dict__[name] = val + + def __setattr__(self, attr, val): + if not attr.startswith("_") and attr not in self.__dict__: + raise AttributeError(attr) + self.__dict__[attr] = val + + def toparam(self): + self._buffs = [] + full_fmt = "" + vals = [] + mask = 0 + # calc the mask + for name, fmt, default, this_mask in self._struct_items_: + if this_mask is not None and self.__dict__.get(name) is not None: + mask |= this_mask + self.mask = mask + for name, fmt, default, this_mask in self._struct_items_: + val = self.__dict__[name] + if fmt == "z": + fmt = "Pi" + if val is None: + vals.append(0) + vals.append(0) + else: + # Note this demo still works with byte strings. An + # alternate strategy would be to use unicode natively + # and use the 'W' version of the messages - eg, + # LVM_SETITEMW etc. + val = val + "\0" + if isinstance(val, str): + val = val.encode("mbcs") + str_buf = array.array("b", val) + vals.append(str_buf.buffer_info()[0]) + vals.append(len(val)) + self._buffs.append(str_buf) # keep alive during the call. + else: + if val is None: + val = default + vals.append(val) + full_fmt += fmt + return struct.pack(*(full_fmt,) + tuple(vals)) + + +# NOTE: See the win32gui_struct module for an alternative way of dealing +# with these structures +class LVITEM(_WIN32MASKEDSTRUCT): + _struct_items_ = [ + ("mask", "I", 0, None), + ("iItem", "i", 0, None), + ("iSubItem", "i", 0, None), + ("state", "I", 0, commctrl.LVIF_STATE), + ("stateMask", "I", 0, None), + ("text", "z", None, commctrl.LVIF_TEXT), + ("iImage", "i", 0, commctrl.LVIF_IMAGE), + ("lParam", "i", 0, commctrl.LVIF_PARAM), + ("iIdent", "i", 0, None), + ] + + +class LVCOLUMN(_WIN32MASKEDSTRUCT): + _struct_items_ = [ + ("mask", "I", 0, None), + ("fmt", "i", 0, commctrl.LVCF_FMT), + ("cx", "i", 0, commctrl.LVCF_WIDTH), + ("text", "z", None, commctrl.LVCF_TEXT), + ("iSubItem", "i", 0, commctrl.LVCF_SUBITEM), + ("iImage", "i", 0, commctrl.LVCF_IMAGE), + ("iOrder", "i", 0, commctrl.LVCF_ORDER), + ] + + +class DemoWindowBase: + def __init__(self): + win32gui.InitCommonControls() + self.hinst = win32gui.dllhandle + self.list_data = {} + + def _RegisterWndClass(self): + className = "PythonDocSearch" + message_map = {} + wc = win32gui.WNDCLASS() + wc.SetDialogProc() # Make it a dialog class. + wc.hInstance = self.hinst + wc.lpszClassName = className + wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW) + wc.hbrBackground = win32con.COLOR_WINDOW + 1 + wc.lpfnWndProc = message_map # could also specify a wndproc. + # C code: wc.cbWndExtra = DLGWINDOWEXTRA + sizeof(HBRUSH) + (sizeof(COLORREF)); + wc.cbWndExtra = win32con.DLGWINDOWEXTRA + struct.calcsize("Pi") + icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE + + ## py.ico went away in python 2.5, load from executable instead + this_app = win32api.GetModuleHandle(None) + try: + wc.hIcon = win32gui.LoadIcon(this_app, 1) ## python.exe and pythonw.exe + except win32gui.error: + wc.hIcon = win32gui.LoadIcon(this_app, 135) ## pythonwin's icon + try: + classAtom = win32gui.RegisterClass(wc) + except win32gui.error as err_info: + if err_info.winerror != winerror.ERROR_CLASS_ALREADY_EXISTS: + raise + return className + + def _GetDialogTemplate(self, dlgClassName): + style = ( + win32con.WS_THICKFRAME + | win32con.WS_POPUP + | win32con.WS_VISIBLE + | win32con.WS_CAPTION + | win32con.WS_SYSMENU + | win32con.DS_SETFONT + | win32con.WS_MINIMIZEBOX + ) + cs = win32con.WS_CHILD | win32con.WS_VISIBLE + title = "Dynamic Dialog Demo" + + # Window frame and title + dlg = [ + [ + title, + (0, 0, 210, 250), + style, + None, + (8, "MS Sans Serif"), + None, + dlgClassName, + ], + ] + + # ID label and text box + dlg.append([130, "Enter something", -1, (5, 5, 200, 9), cs | win32con.SS_LEFT]) + s = cs | win32con.WS_TABSTOP | win32con.WS_BORDER + dlg.append(["EDIT", None, IDC_SEARCHTEXT, (5, 15, 200, 12), s]) + + # Search/Display Buttons + # (x positions don't matter here) + s = cs | win32con.WS_TABSTOP + dlg.append( + [ + 128, + "Fill List", + IDC_BUTTON_SEARCH, + (5, 35, 50, 14), + s | win32con.BS_DEFPUSHBUTTON, + ] + ) + s = win32con.BS_PUSHBUTTON | s + dlg.append([128, "Display", IDC_BUTTON_DISPLAY, (100, 35, 50, 14), s]) + + # List control. + # Can't make this work :( + ## s = cs | win32con.WS_TABSTOP + ## dlg.append(['SysListView32', "Title", IDC_LISTBOX, (5, 505, 200, 200), s]) + + return dlg + + def _DoCreate(self, fn): + message_map = { + win32con.WM_SIZE: self.OnSize, + win32con.WM_COMMAND: self.OnCommand, + win32con.WM_NOTIFY: self.OnNotify, + win32con.WM_INITDIALOG: self.OnInitDialog, + win32con.WM_CLOSE: self.OnClose, + win32con.WM_DESTROY: self.OnDestroy, + WM_SEARCH_RESULT: self.OnSearchResult, + WM_SEARCH_FINISHED: self.OnSearchFinished, + } + dlgClassName = self._RegisterWndClass() + template = self._GetDialogTemplate(dlgClassName) + return fn(self.hinst, template, 0, message_map) + + def _SetupList(self): + child_style = ( + win32con.WS_CHILD + | win32con.WS_VISIBLE + | win32con.WS_BORDER + | win32con.WS_HSCROLL + | win32con.WS_VSCROLL + ) + child_style |= ( + commctrl.LVS_SINGLESEL | commctrl.LVS_SHOWSELALWAYS | commctrl.LVS_REPORT + ) + self.hwndList = win32gui.CreateWindow( + "SysListView32", + None, + child_style, + 0, + 0, + 100, + 100, + self.hwnd, + IDC_LISTBOX, + self.hinst, + None, + ) + + child_ex_style = win32gui.SendMessage( + self.hwndList, commctrl.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0 + ) + child_ex_style |= commctrl.LVS_EX_FULLROWSELECT + win32gui.SendMessage( + self.hwndList, commctrl.LVM_SETEXTENDEDLISTVIEWSTYLE, 0, child_ex_style + ) + + # Add an image list - use the builtin shell folder icon - this + # demonstrates the problem with alpha-blending of icons on XP if + # winxpgui is not used in place of win32gui. + il = win32gui.ImageList_Create( + win32api.GetSystemMetrics(win32con.SM_CXSMICON), + win32api.GetSystemMetrics(win32con.SM_CYSMICON), + commctrl.ILC_COLOR32 | commctrl.ILC_MASK, + 1, # initial size + 0, + ) # cGrow + + shell_dll = os.path.join(win32api.GetSystemDirectory(), "shell32.dll") + large, small = win32gui.ExtractIconEx(shell_dll, 4, 1) + win32gui.ImageList_ReplaceIcon(il, -1, small[0]) + win32gui.DestroyIcon(small[0]) + win32gui.DestroyIcon(large[0]) + win32gui.SendMessage( + self.hwndList, commctrl.LVM_SETIMAGELIST, commctrl.LVSIL_SMALL, il + ) + + # Setup the list control columns. + lvc = LVCOLUMN( + mask=commctrl.LVCF_FMT + | commctrl.LVCF_WIDTH + | commctrl.LVCF_TEXT + | commctrl.LVCF_SUBITEM + ) + lvc.fmt = commctrl.LVCFMT_LEFT + lvc.iSubItem = 1 + lvc.text = "Title" + lvc.cx = 200 + win32gui.SendMessage(self.hwndList, commctrl.LVM_INSERTCOLUMN, 0, lvc.toparam()) + lvc.iSubItem = 0 + lvc.text = "Order" + lvc.cx = 50 + win32gui.SendMessage(self.hwndList, commctrl.LVM_INSERTCOLUMN, 0, lvc.toparam()) + + win32gui.UpdateWindow(self.hwnd) + + def ClearListItems(self): + win32gui.SendMessage(self.hwndList, commctrl.LVM_DELETEALLITEMS) + self.list_data = {} + + def AddListItem(self, data, *columns): + num_items = win32gui.SendMessage(self.hwndList, commctrl.LVM_GETITEMCOUNT) + item = LVITEM(text=columns[0], iItem=num_items) + new_index = win32gui.SendMessage( + self.hwndList, commctrl.LVM_INSERTITEM, 0, item.toparam() + ) + col_no = 1 + for col in columns[1:]: + item = LVITEM(text=col, iItem=new_index, iSubItem=col_no) + win32gui.SendMessage(self.hwndList, commctrl.LVM_SETITEM, 0, item.toparam()) + col_no += 1 + self.list_data[new_index] = data + + def OnInitDialog(self, hwnd, msg, wparam, lparam): + self.hwnd = hwnd + # centre the dialog + desktop = win32gui.GetDesktopWindow() + l, t, r, b = win32gui.GetWindowRect(self.hwnd) + dt_l, dt_t, dt_r, dt_b = win32gui.GetWindowRect(desktop) + centre_x, centre_y = win32gui.ClientToScreen( + desktop, ((dt_r - dt_l) // 2, (dt_b - dt_t) // 2) + ) + win32gui.MoveWindow( + hwnd, centre_x - (r // 2), centre_y - (b // 2), r - l, b - t, 0 + ) + self._SetupList() + l, t, r, b = win32gui.GetClientRect(self.hwnd) + self._DoSize(r - l, b - t, 1) + + def _DoSize(self, cx, cy, repaint=1): + # right-justify the textbox. + ctrl = win32gui.GetDlgItem(self.hwnd, IDC_SEARCHTEXT) + l, t, r, b = win32gui.GetWindowRect(ctrl) + l, t = win32gui.ScreenToClient(self.hwnd, (l, t)) + r, b = win32gui.ScreenToClient(self.hwnd, (r, b)) + win32gui.MoveWindow(ctrl, l, t, cx - l - 5, b - t, repaint) + # The button. + ctrl = win32gui.GetDlgItem(self.hwnd, IDC_BUTTON_DISPLAY) + l, t, r, b = win32gui.GetWindowRect(ctrl) + l, t = win32gui.ScreenToClient(self.hwnd, (l, t)) + r, b = win32gui.ScreenToClient(self.hwnd, (r, b)) + list_y = b + 10 + w = r - l + win32gui.MoveWindow(ctrl, cx - 5 - w, t, w, b - t, repaint) + + # The list control + win32gui.MoveWindow(self.hwndList, 0, list_y, cx, cy - list_y, repaint) + # The last column of the list control. + new_width = cx - win32gui.SendMessage( + self.hwndList, commctrl.LVM_GETCOLUMNWIDTH, 0 + ) + win32gui.SendMessage(self.hwndList, commctrl.LVM_SETCOLUMNWIDTH, 1, new_width) + + def OnSize(self, hwnd, msg, wparam, lparam): + x = win32api.LOWORD(lparam) + y = win32api.HIWORD(lparam) + self._DoSize(x, y) + return 1 + + def OnSearchResult(self, hwnd, msg, wparam, lparam): + try: + while 1: + params = self.result_queue.get(0) + self.AddListItem(*params) + except queue.Empty: + pass + + def OnSearchFinished(self, hwnd, msg, wparam, lparam): + print("OnSearchFinished") + + def OnNotify(self, hwnd, msg, wparam, lparam): + info = win32gui_struct.UnpackNMITEMACTIVATE(lparam) + if info.code == commctrl.NM_DBLCLK: + print("Double click on item", info.iItem + 1) + return 1 + + def OnCommand(self, hwnd, msg, wparam, lparam): + id = win32api.LOWORD(wparam) + if id == IDC_BUTTON_SEARCH: + self.ClearListItems() + + def fill_slowly(q, hwnd): + import time + + for i in range(20): + q.put(("whatever", str(i + 1), "Search result " + str(i))) + win32gui.PostMessage(hwnd, WM_SEARCH_RESULT, 0, 0) + time.sleep(0.25) + win32gui.PostMessage(hwnd, WM_SEARCH_FINISHED, 0, 0) + + import threading + + self.result_queue = queue.Queue() + thread = threading.Thread( + target=fill_slowly, args=(self.result_queue, self.hwnd) + ) + thread.start() + elif id == IDC_BUTTON_DISPLAY: + print("Display button selected") + sel = win32gui.SendMessage( + self.hwndList, commctrl.LVM_GETNEXTITEM, -1, commctrl.LVNI_SELECTED + ) + print("The selected item is", sel + 1) + + # These function differ based on how the window is used, so may be overridden + def OnClose(self, hwnd, msg, wparam, lparam): + raise NotImplementedError + + def OnDestroy(self, hwnd, msg, wparam, lparam): + pass + + +# An implementation suitable for use with the Win32 Window functions (ie, not +# a true dialog) +class DemoWindow(DemoWindowBase): + def CreateWindow(self): + # Create the window via CreateDialogBoxIndirect - it can then + # work as a "normal" window, once a message loop is established. + self._DoCreate(win32gui.CreateDialogIndirect) + + def OnClose(self, hwnd, msg, wparam, lparam): + win32gui.DestroyWindow(hwnd) + + # We need to arrange to a WM_QUIT message to be sent to our + # PumpMessages() loop. + def OnDestroy(self, hwnd, msg, wparam, lparam): + win32gui.PostQuitMessage(0) # Terminate the app. + + +# An implementation suitable for use with the Win32 Dialog functions. +class DemoDialog(DemoWindowBase): + def DoModal(self): + return self._DoCreate(win32gui.DialogBoxIndirect) + + def OnClose(self, hwnd, msg, wparam, lparam): + win32gui.EndDialog(hwnd, 0) + + +def DemoModal(): + w = DemoDialog() + w.DoModal() + + +def DemoCreateWindow(): + w = DemoWindow() + w.CreateWindow() + # PumpMessages runs until PostQuitMessage() is called by someone. + win32gui.PumpMessages() + + +if __name__ == "__main__": + DemoModal() + DemoCreateWindow() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32gui_menu.py b/MLPY/Lib/site-packages/win32/Demos/win32gui_menu.py new file mode 100644 index 0000000000000000000000000000000000000000..c462b06227832077906de9f9de1d1fb52feda222 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32gui_menu.py @@ -0,0 +1,420 @@ +# Demonstrates some advanced menu concepts using win32gui. +# This creates a taskbar icon which has some fancy menus (but note that +# selecting the menu items does nothing useful - see win32gui_taskbar.py +# for examples of this. + +# NOTE: This is a work in progress. Todo: +# * The "Checked" menu items don't work correctly - I'm not sure why. +# * No support for GetMenuItemInfo. + +# Based on Andy McKay's demo code. +from win32api import * + +# Try and use XP features, so we get alpha-blending etc. +try: + from winxpgui import * +except ImportError: + from win32gui import * + +import array +import os +import struct +import sys + +import win32con +from win32gui_struct import * + +this_dir = os.path.split(sys.argv[0])[0] + + +class MainWindow: + def __init__(self): + message_map = { + win32con.WM_DESTROY: self.OnDestroy, + win32con.WM_COMMAND: self.OnCommand, + win32con.WM_USER + 20: self.OnTaskbarNotify, + # owner-draw related handlers. + win32con.WM_MEASUREITEM: self.OnMeasureItem, + win32con.WM_DRAWITEM: self.OnDrawItem, + } + # Register the Window class. + wc = WNDCLASS() + hinst = wc.hInstance = GetModuleHandle(None) + wc.lpszClassName = "PythonTaskbarDemo" + wc.lpfnWndProc = message_map # could also specify a wndproc. + classAtom = RegisterClass(wc) + # Create the Window. + style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU + self.hwnd = CreateWindow( + classAtom, + "Taskbar Demo", + style, + 0, + 0, + win32con.CW_USEDEFAULT, + win32con.CW_USEDEFAULT, + 0, + 0, + hinst, + None, + ) + UpdateWindow(self.hwnd) + iconPathName = os.path.abspath(os.path.join(sys.prefix, "pyc.ico")) + # py2.5 includes the .ico files in the DLLs dir for some reason. + if not os.path.isfile(iconPathName): + iconPathName = os.path.abspath( + os.path.join(os.path.split(sys.executable)[0], "DLLs", "pyc.ico") + ) + if not os.path.isfile(iconPathName): + # Look in the source tree. + iconPathName = os.path.abspath( + os.path.join(os.path.split(sys.executable)[0], "..\\PC\\pyc.ico") + ) + if os.path.isfile(iconPathName): + icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE + hicon = LoadImage( + hinst, iconPathName, win32con.IMAGE_ICON, 0, 0, icon_flags + ) + else: + iconPathName = None + print("Can't find a Python icon file - using default") + hicon = LoadIcon(0, win32con.IDI_APPLICATION) + self.iconPathName = iconPathName + + # Load up some information about menus needed by our owner-draw code. + # The font to use on the menu. + ncm = SystemParametersInfo(win32con.SPI_GETNONCLIENTMETRICS) + self.font_menu = CreateFontIndirect(ncm["lfMenuFont"]) + # spacing for our ownerdraw menus - not sure exactly what constants + # should be used (and if you owner-draw all items on the menu, it + # doesn't matter!) + self.menu_icon_height = GetSystemMetrics(win32con.SM_CYMENU) - 4 + self.menu_icon_width = self.menu_icon_height + self.icon_x_pad = 8 # space from end of icon to start of text. + # A map we use to stash away data we need for ownerdraw. Keyed + # by integer ID - that ID will be set in dwTypeData of the menu item. + self.menu_item_map = {} + + # Finally, create the menu + self.createMenu() + + flags = NIF_ICON | NIF_MESSAGE | NIF_TIP + nid = (self.hwnd, 0, flags, win32con.WM_USER + 20, hicon, "Python Demo") + Shell_NotifyIcon(NIM_ADD, nid) + print("Please right-click on the Python icon in the taskbar") + + def createMenu(self): + self.hmenu = menu = CreatePopupMenu() + # Create our 'Exit' item with the standard, ugly 'close' icon. + item, extras = PackMENUITEMINFO( + text="Exit", hbmpItem=win32con.HBMMENU_MBAR_CLOSE, wID=1000 + ) + InsertMenuItem(menu, 0, 1, item) + # Create a 'text only' menu via InsertMenuItem rather then + # AppendMenu, just to prove we can! + item, extras = PackMENUITEMINFO(text="Text only item", wID=1001) + InsertMenuItem(menu, 0, 1, item) + + load_bmp_flags = win32con.LR_LOADFROMFILE | win32con.LR_LOADTRANSPARENT + # These images are "over sized", so we load them scaled. + hbmp = LoadImage( + 0, + os.path.join(this_dir, "images/smiley.bmp"), + win32con.IMAGE_BITMAP, + 20, + 20, + load_bmp_flags, + ) + + # Create a top-level menu with a bitmap + item, extras = PackMENUITEMINFO( + text="Menu with bitmap", hbmpItem=hbmp, wID=1002 + ) + InsertMenuItem(menu, 0, 1, item) + + # Owner-draw menus mainly from: + # http://windowssdk.msdn.microsoft.com/en-us/library/ms647558.aspx + # and: + # http://www.codeguru.com/cpp/controls/menu/bitmappedmenus/article.php/c165 + + # Create one with an icon - this is *lots* more work - we do it + # owner-draw! The primary reason is to handle transparency better - + # converting to a bitmap causes the background to be incorrect when + # the menu item is selected. I can't see a simpler way. + # First, load the icon we want to use. + ico_x = GetSystemMetrics(win32con.SM_CXSMICON) + ico_y = GetSystemMetrics(win32con.SM_CYSMICON) + if self.iconPathName: + hicon = LoadImage( + 0, + self.iconPathName, + win32con.IMAGE_ICON, + ico_x, + ico_y, + win32con.LR_LOADFROMFILE, + ) + else: + shell_dll = os.path.join(GetSystemDirectory(), "shell32.dll") + large, small = win32gui.ExtractIconEx(shell_dll, 4, 1) + hicon = small[0] + DestroyIcon(large[0]) + + # Stash away the text and hicon in our map, and add the owner-draw + # item to the menu. + index = 0 + self.menu_item_map[index] = (hicon, "Menu with owner-draw icon") + item, extras = PackMENUITEMINFO( + fType=win32con.MFT_OWNERDRAW, dwItemData=index, wID=1009 + ) + InsertMenuItem(menu, 0, 1, item) + + # Add another icon-based icon - but this time using HBMMENU_CALLBACK + # in the hbmpItem elt, so we only need to draw the icon (ie, not the + # text or checkmark) + index = 1 + self.menu_item_map[index] = (hicon, None) + item, extras = PackMENUITEMINFO( + text="Menu with o-d icon 2", + dwItemData=index, + hbmpItem=win32con.HBMMENU_CALLBACK, + wID=1010, + ) + InsertMenuItem(menu, 0, 1, item) + + # Add another icon-based icon - this time by converting + # via bitmap. Note the icon background when selected is ugly :( + hdcBitmap = CreateCompatibleDC(0) + hdcScreen = GetDC(0) + hbm = CreateCompatibleBitmap(hdcScreen, ico_x, ico_y) + hbmOld = SelectObject(hdcBitmap, hbm) + SetBkMode(hdcBitmap, win32con.TRANSPARENT) + # Fill the background. + brush = GetSysColorBrush(win32con.COLOR_MENU) + FillRect(hdcBitmap, (0, 0, 16, 16), brush) + # unclear if brush needs to be freed. Best clue I can find is: + # "GetSysColorBrush returns a cached brush instead of allocating a new + # one." - implies no DeleteObject. + # draw the icon + DrawIconEx(hdcBitmap, 0, 0, hicon, ico_x, ico_y, 0, 0, win32con.DI_NORMAL) + SelectObject(hdcBitmap, hbmOld) + DeleteDC(hdcBitmap) + item, extras = PackMENUITEMINFO( + text="Menu with icon", hbmpItem=hbm.Detach(), wID=1011 + ) + InsertMenuItem(menu, 0, 1, item) + + # Create a sub-menu, and put a few funky ones there. + self.sub_menu = sub_menu = CreatePopupMenu() + # A 'checkbox' menu. + item, extras = PackMENUITEMINFO( + fState=win32con.MFS_CHECKED, text="Checkbox menu", hbmpItem=hbmp, wID=1003 + ) + InsertMenuItem(sub_menu, 0, 1, item) + # A 'radio' menu. + InsertMenu(sub_menu, 0, win32con.MF_BYPOSITION, win32con.MF_SEPARATOR, None) + item, extras = PackMENUITEMINFO( + fType=win32con.MFT_RADIOCHECK, + fState=win32con.MFS_CHECKED, + text="Checkbox menu - bullet 1", + hbmpItem=hbmp, + wID=1004, + ) + InsertMenuItem(sub_menu, 0, 1, item) + item, extras = PackMENUITEMINFO( + fType=win32con.MFT_RADIOCHECK, + fState=win32con.MFS_UNCHECKED, + text="Checkbox menu - bullet 2", + hbmpItem=hbmp, + wID=1005, + ) + InsertMenuItem(sub_menu, 0, 1, item) + # And add the sub-menu to the top-level menu. + item, extras = PackMENUITEMINFO(text="Sub-Menu", hSubMenu=sub_menu) + InsertMenuItem(menu, 0, 1, item) + + # Set 'Exit' as the default option. + SetMenuDefaultItem(menu, 1000, 0) + + def OnDestroy(self, hwnd, msg, wparam, lparam): + nid = (self.hwnd, 0) + Shell_NotifyIcon(NIM_DELETE, nid) + PostQuitMessage(0) # Terminate the app. + + def OnTaskbarNotify(self, hwnd, msg, wparam, lparam): + if lparam == win32con.WM_RBUTTONUP: + print("You right clicked me.") + # display the menu at the cursor pos. + pos = GetCursorPos() + SetForegroundWindow(self.hwnd) + TrackPopupMenu( + self.hmenu, win32con.TPM_LEFTALIGN, pos[0], pos[1], 0, self.hwnd, None + ) + PostMessage(self.hwnd, win32con.WM_NULL, 0, 0) + elif lparam == win32con.WM_LBUTTONDBLCLK: + print("You double-clicked me") + # find the default menu item and fire it. + cmd = GetMenuDefaultItem(self.hmenu, False, 0) + if cmd == -1: + print("Can't find a default!") + # and just pretend it came from the menu + self.OnCommand(hwnd, win32con.WM_COMMAND, cmd, 0) + return 1 + + def OnCommand(self, hwnd, msg, wparam, lparam): + id = LOWORD(wparam) + if id == 1000: + print("Goodbye") + DestroyWindow(self.hwnd) + elif id in (1003, 1004, 1005): + # Our 'checkbox' and 'radio' items + state = GetMenuState(self.sub_menu, id, win32con.MF_BYCOMMAND) + if state == -1: + raise RuntimeError("No item found") + if state & win32con.MF_CHECKED: + check_flags = win32con.MF_UNCHECKED + print("Menu was checked - unchecking") + else: + check_flags = win32con.MF_CHECKED + print("Menu was unchecked - checking") + + if id == 1003: + # simple checkbox + rc = CheckMenuItem( + self.sub_menu, id, win32con.MF_BYCOMMAND | check_flags + ) + else: + # radio button - must pass the first and last IDs in the + # "group", and the ID in the group that is to be selected. + rc = CheckMenuRadioItem( + self.sub_menu, 1004, 1005, id, win32con.MF_BYCOMMAND + ) + # Get and check the new state - first the simple way... + new_state = GetMenuState(self.sub_menu, id, win32con.MF_BYCOMMAND) + if new_state & win32con.MF_CHECKED != check_flags: + raise RuntimeError("The new item didn't get the new checked state!") + # Now the long-winded way via GetMenuItemInfo... + buf, extras = EmptyMENUITEMINFO() + win32gui.GetMenuItemInfo(self.sub_menu, id, False, buf) + ( + fType, + fState, + wID, + hSubMenu, + hbmpChecked, + hbmpUnchecked, + dwItemData, + text, + hbmpItem, + ) = UnpackMENUITEMINFO(buf) + + if fState & win32con.MF_CHECKED != check_flags: + raise RuntimeError("The new item didn't get the new checked state!") + else: + print("OnCommand for ID", id) + + # Owner-draw related functions. We only have 1 owner-draw item, but + # we pretend we have more than that :) + def OnMeasureItem(self, hwnd, msg, wparam, lparam): + ## Last item of MEASUREITEMSTRUCT is a ULONG_PTR + fmt = "5iP" + buf = PyMakeBuffer(struct.calcsize(fmt), lparam) + data = struct.unpack(fmt, buf) + ctlType, ctlID, itemID, itemWidth, itemHeight, itemData = data + + hicon, text = self.menu_item_map[itemData] + if text is None: + # Only drawing icon due to HBMMENU_CALLBACK + cx = self.menu_icon_width + cy = self.menu_icon_height + else: + # drawing the lot! + dc = GetDC(hwnd) + oldFont = SelectObject(dc, self.font_menu) + cx, cy = GetTextExtentPoint32(dc, text) + SelectObject(dc, oldFont) + ReleaseDC(hwnd, dc) + + cx += GetSystemMetrics(win32con.SM_CXMENUCHECK) + cx += self.menu_icon_width + self.icon_x_pad + + cy = GetSystemMetrics(win32con.SM_CYMENU) + + new_data = struct.pack(fmt, ctlType, ctlID, itemID, cx, cy, itemData) + PySetMemory(lparam, new_data) + return True + + def OnDrawItem(self, hwnd, msg, wparam, lparam): + ## lparam is a DRAWITEMSTRUCT + fmt = "5i2P4iP" + data = struct.unpack(fmt, PyGetMemory(lparam, struct.calcsize(fmt))) + ( + ctlType, + ctlID, + itemID, + itemAction, + itemState, + hwndItem, + hDC, + left, + top, + right, + bot, + itemData, + ) = data + + rect = left, top, right, bot + hicon, text = self.menu_item_map[itemData] + + if text is None: + # This means the menu-item had HBMMENU_CALLBACK - so all we + # draw is the icon. rect is the entire area we should use. + DrawIconEx( + hDC, left, top, hicon, right - left, bot - top, 0, 0, win32con.DI_NORMAL + ) + else: + # If the user has selected the item, use the selected + # text and background colors to display the item. + selected = itemState & win32con.ODS_SELECTED + if selected: + crText = SetTextColor(hDC, GetSysColor(win32con.COLOR_HIGHLIGHTTEXT)) + crBkgnd = SetBkColor(hDC, GetSysColor(win32con.COLOR_HIGHLIGHT)) + + each_pad = self.icon_x_pad // 2 + x_icon = left + GetSystemMetrics(win32con.SM_CXMENUCHECK) + each_pad + x_text = x_icon + self.menu_icon_width + each_pad + + # Draw text first, specifying a complete rect to fill - this sets + # up the background (but overwrites anything else already there!) + # Select the font, draw it, and restore the previous font. + hfontOld = SelectObject(hDC, self.font_menu) + ExtTextOut(hDC, x_text, top + 2, win32con.ETO_OPAQUE, rect, text) + SelectObject(hDC, hfontOld) + + # Icon image next. Icons are transparent - no need to handle + # selection specially. + DrawIconEx( + hDC, + x_icon, + top + 2, + hicon, + self.menu_icon_width, + self.menu_icon_height, + 0, + 0, + win32con.DI_NORMAL, + ) + + # Return the text and background colors to their + # normal state (not selected). + if selected: + SetTextColor(hDC, crText) + SetBkColor(hDC, crBkgnd) + + +def main(): + w = MainWindow() + PumpMessages() + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32gui_taskbar.py b/MLPY/Lib/site-packages/win32/Demos/win32gui_taskbar.py new file mode 100644 index 0000000000000000000000000000000000000000..84d642a9cd0b743777d0857e0fd551ad2c91a19b --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32gui_taskbar.py @@ -0,0 +1,141 @@ +# Creates a task-bar icon. Run from Python.exe to see the +# messages printed. +import os +import sys + +import win32api +import win32con +import win32gui +import winerror + + +class MainWindow: + def __init__(self): + msg_TaskbarRestart = win32gui.RegisterWindowMessage("TaskbarCreated") + message_map = { + msg_TaskbarRestart: self.OnRestart, + win32con.WM_DESTROY: self.OnDestroy, + win32con.WM_COMMAND: self.OnCommand, + win32con.WM_USER + 20: self.OnTaskbarNotify, + } + # Register the Window class. + wc = win32gui.WNDCLASS() + hinst = wc.hInstance = win32api.GetModuleHandle(None) + wc.lpszClassName = "PythonTaskbarDemo" + wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hCursor = win32api.LoadCursor(0, win32con.IDC_ARROW) + wc.hbrBackground = win32con.COLOR_WINDOW + wc.lpfnWndProc = message_map # could also specify a wndproc. + + # Don't blow up if class already registered to make testing easier + try: + classAtom = win32gui.RegisterClass(wc) + except win32gui.error as err_info: + if err_info.winerror != winerror.ERROR_CLASS_ALREADY_EXISTS: + raise + + # Create the Window. + style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU + self.hwnd = win32gui.CreateWindow( + wc.lpszClassName, + "Taskbar Demo", + style, + 0, + 0, + win32con.CW_USEDEFAULT, + win32con.CW_USEDEFAULT, + 0, + 0, + hinst, + None, + ) + win32gui.UpdateWindow(self.hwnd) + self._DoCreateIcons() + + def _DoCreateIcons(self): + # Try and find a custom icon + hinst = win32api.GetModuleHandle(None) + iconPathName = os.path.abspath( + os.path.join(os.path.split(sys.executable)[0], "pyc.ico") + ) + if not os.path.isfile(iconPathName): + # Look in DLLs dir, a-la py 2.5 + iconPathName = os.path.abspath( + os.path.join(os.path.split(sys.executable)[0], "DLLs", "pyc.ico") + ) + if not os.path.isfile(iconPathName): + # Look in the source tree. + iconPathName = os.path.abspath( + os.path.join(os.path.split(sys.executable)[0], "..\\PC\\pyc.ico") + ) + if os.path.isfile(iconPathName): + icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE + hicon = win32gui.LoadImage( + hinst, iconPathName, win32con.IMAGE_ICON, 0, 0, icon_flags + ) + else: + print("Can't find a Python icon file - using default") + hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION) + + flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP + nid = (self.hwnd, 0, flags, win32con.WM_USER + 20, hicon, "Python Demo") + try: + win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid) + except win32gui.error: + # This is common when windows is starting, and this code is hit + # before the taskbar has been created. + print("Failed to add the taskbar icon - is explorer running?") + # but keep running anyway - when explorer starts, we get the + # TaskbarCreated message. + + def OnRestart(self, hwnd, msg, wparam, lparam): + self._DoCreateIcons() + + def OnDestroy(self, hwnd, msg, wparam, lparam): + nid = (self.hwnd, 0) + win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid) + win32gui.PostQuitMessage(0) # Terminate the app. + + def OnTaskbarNotify(self, hwnd, msg, wparam, lparam): + if lparam == win32con.WM_LBUTTONUP: + print("You clicked me.") + elif lparam == win32con.WM_LBUTTONDBLCLK: + print("You double-clicked me - goodbye") + win32gui.DestroyWindow(self.hwnd) + elif lparam == win32con.WM_RBUTTONUP: + print("You right clicked me.") + menu = win32gui.CreatePopupMenu() + win32gui.AppendMenu(menu, win32con.MF_STRING, 1023, "Display Dialog") + win32gui.AppendMenu(menu, win32con.MF_STRING, 1024, "Say Hello") + win32gui.AppendMenu(menu, win32con.MF_STRING, 1025, "Exit program") + pos = win32gui.GetCursorPos() + # See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/menus_0hdi.asp + win32gui.SetForegroundWindow(self.hwnd) + win32gui.TrackPopupMenu( + menu, win32con.TPM_LEFTALIGN, pos[0], pos[1], 0, self.hwnd, None + ) + win32gui.PostMessage(self.hwnd, win32con.WM_NULL, 0, 0) + return 1 + + def OnCommand(self, hwnd, msg, wparam, lparam): + id = win32api.LOWORD(wparam) + if id == 1023: + import win32gui_dialog + + win32gui_dialog.DemoModal() + elif id == 1024: + print("Hello") + elif id == 1025: + print("Goodbye") + win32gui.DestroyWindow(self.hwnd) + else: + print("Unknown command -", id) + + +def main(): + w = MainWindow() + win32gui.PumpMessages() + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32netdemo.py b/MLPY/Lib/site-packages/win32/Demos/win32netdemo.py new file mode 100644 index 0000000000000000000000000000000000000000..36c495424b7d2719eccba289001ccc5a20faf225 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32netdemo.py @@ -0,0 +1,274 @@ +import getopt +import sys +import traceback + +import win32api +import win32net +import win32netcon +import win32security + +verbose_level = 0 + +server = None # Run on local machine. + + +def verbose(msg): + if verbose_level: + print(msg) + + +def CreateUser(): + "Creates a new test user, then deletes the user" + testName = "PyNetTestUser" + try: + win32net.NetUserDel(server, testName) + print("Warning - deleted user before creating it!") + except win32net.error: + pass + + d = {} + d["name"] = testName + d["password"] = "deleteme" + d["priv"] = win32netcon.USER_PRIV_USER + d["comment"] = "Delete me - created by Python test code" + d["flags"] = win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_SCRIPT + win32net.NetUserAdd(server, 1, d) + try: + try: + win32net.NetUserChangePassword(server, testName, "wrong", "new") + print("ERROR: NetUserChangePassword worked with a wrong password!") + except win32net.error: + pass + win32net.NetUserChangePassword(server, testName, "deleteme", "new") + finally: + win32net.NetUserDel(server, testName) + print("Created a user, changed their password, and deleted them!") + + +def UserEnum(): + "Enumerates all the local users" + resume = 0 + nuser = 0 + while 1: + data, total, resume = win32net.NetUserEnum( + server, 3, win32netcon.FILTER_NORMAL_ACCOUNT, resume + ) + verbose( + "Call to NetUserEnum obtained %d entries of %d total" % (len(data), total) + ) + for user in data: + verbose("Found user %s" % user["name"]) + nuser = nuser + 1 + if not resume: + break + assert nuser, "Could not find any users!" + print("Enumerated all the local users") + + +def GroupEnum(): + "Enumerates all the domain groups" + nmembers = 0 + resume = 0 + while 1: + data, total, resume = win32net.NetGroupEnum(server, 1, resume) + # print "Call to NetGroupEnum obtained %d entries of %d total" % (len(data), total) + for group in data: + verbose("Found group %(name)s:%(comment)s " % group) + memberresume = 0 + while 1: + memberdata, total, memberresume = win32net.NetGroupGetUsers( + server, group["name"], 0, resume + ) + for member in memberdata: + verbose(" Member %(name)s" % member) + nmembers = nmembers + 1 + if memberresume == 0: + break + if not resume: + break + assert nmembers, "Couldnt find a single member in a single group!" + print("Enumerated all the groups") + + +def LocalGroupEnum(): + "Enumerates all the local groups" + resume = 0 + nmembers = 0 + while 1: + data, total, resume = win32net.NetLocalGroupEnum(server, 1, resume) + for group in data: + verbose("Found group %(name)s:%(comment)s " % group) + memberresume = 0 + while 1: + memberdata, total, memberresume = win32net.NetLocalGroupGetMembers( + server, group["name"], 2, resume + ) + for member in memberdata: + # Just for the sake of it, we convert the SID to a username + username, domain, type = win32security.LookupAccountSid( + server, member["sid"] + ) + nmembers = nmembers + 1 + verbose(" Member %s (%s)" % (username, member["domainandname"])) + if memberresume == 0: + break + if not resume: + break + assert nmembers, "Couldnt find a single member in a single group!" + print("Enumerated all the local groups") + + +def ServerEnum(): + "Enumerates all servers on the network" + resume = 0 + while 1: + data, total, resume = win32net.NetServerEnum( + server, 100, win32netcon.SV_TYPE_ALL, None, resume + ) + for s in data: + verbose("Found server %s" % s["name"]) + # Now loop over the shares. + shareresume = 0 + while 1: + sharedata, total, shareresume = win32net.NetShareEnum( + server, 2, shareresume + ) + for share in sharedata: + verbose( + " %(netname)s (%(path)s):%(remark)s - in use by %(current_uses)d users" + % share + ) + if not shareresume: + break + if not resume: + break + print("Enumerated all the servers on the network") + + +def LocalGroup(uname=None): + "Creates a local group, adds some members, deletes them, then removes the group" + level = 3 + if uname is None: + uname = win32api.GetUserName() + if uname.find("\\") < 0: + uname = win32api.GetDomainName() + "\\" + uname + group = "python_test_group" + # delete the group if it already exists + try: + win32net.NetLocalGroupDel(server, group) + print("WARNING: existing local group '%s' has been deleted.") + except win32net.error: + pass + group_data = {"name": group} + win32net.NetLocalGroupAdd(server, 1, group_data) + try: + u = {"domainandname": uname} + win32net.NetLocalGroupAddMembers(server, group, level, [u]) + mem, tot, res = win32net.NetLocalGroupGetMembers(server, group, level) + print("members are", mem) + if mem[0]["domainandname"] != uname: + print("ERROR: LocalGroup just added %s, but members are %r" % (uname, mem)) + # Convert the list of dicts to a list of strings. + win32net.NetLocalGroupDelMembers( + server, group, [m["domainandname"] for m in mem] + ) + finally: + win32net.NetLocalGroupDel(server, group) + print("Created a local group, added and removed members, then deleted the group") + + +def GetInfo(userName=None): + "Dumps level 3 information about the current user" + if userName is None: + userName = win32api.GetUserName() + print("Dumping level 3 information about user") + info = win32net.NetUserGetInfo(server, userName, 3) + for key, val in list(info.items()): + verbose("%s=%s" % (key, val)) + + +def SetInfo(userName=None): + "Attempts to change the current users comment, then set it back" + if userName is None: + userName = win32api.GetUserName() + oldData = win32net.NetUserGetInfo(server, userName, 3) + try: + d = oldData.copy() + d["usr_comment"] = "Test comment" + win32net.NetUserSetInfo(server, userName, 3, d) + new = win32net.NetUserGetInfo(server, userName, 3)["usr_comment"] + if str(new) != "Test comment": + raise RuntimeError("Could not read the same comment back - got %s" % new) + print("Changed the data for the user") + finally: + win32net.NetUserSetInfo(server, userName, 3, oldData) + + +def SetComputerInfo(): + "Doesnt actually change anything, just make sure we could ;-)" + info = win32net.NetWkstaGetInfo(None, 502) + # *sob* - but we can't! Why not!!! + # win32net.NetWkstaSetInfo(None, 502, info) + + +def usage(tests): + import os + + print("Usage: %s [-s server ] [-v] [Test ...]" % os.path.basename(sys.argv[0])) + print(" -v : Verbose - print more information") + print(" -s : server - execute the tests against the named server") + print(" -c : include the CreateUser test by default") + print("where Test is one of:") + for t in tests: + print(t.__name__, ":", t.__doc__) + print() + print("If not tests are specified, all tests are run") + sys.exit(1) + + +def main(): + tests = [] + for ob in list(globals().values()): + if type(ob) == type(main) and ob.__doc__: + tests.append(ob) + opts, args = getopt.getopt(sys.argv[1:], "s:hvc") + create_user = False + for opt, val in opts: + if opt == "-s": + global server + server = val + if opt == "-h": + usage(tests) + if opt == "-v": + global verbose_level + verbose_level = verbose_level + 1 + if opt == "-c": + create_user = True + + if len(args) == 0: + print("Running all tests - use '-h' to see command-line options...") + dotests = tests + if not create_user: + dotests.remove(CreateUser) + else: + dotests = [] + for arg in args: + for t in tests: + if t.__name__ == arg: + dotests.append(t) + break + else: + print("Test '%s' unknown - skipping" % arg) + if not len(dotests): + print("Nothing to do!") + usage(tests) + for test in dotests: + try: + test() + except: + print("Test %s failed" % test.__name__) + traceback.print_exc() + + +if __name__ == "__main__": + main() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32rcparser_demo.py b/MLPY/Lib/site-packages/win32/Demos/win32rcparser_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..6a41d453ac200c7498a452e2661c5f2e75126bf0 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32rcparser_demo.py @@ -0,0 +1,86 @@ +# A demo of the win32rcparser module and using win32gui + +import os + +import commctrl +import win32api +import win32con +import win32gui +import win32rcparser + +this_dir = os.path.abspath(os.path.dirname(__file__)) +g_rcname = os.path.abspath( + os.path.join(this_dir, "..", "test", "win32rcparser", "test.rc") +) + +if not os.path.isfile(g_rcname): + raise RuntimeError("Can't locate test.rc (should be at '%s')" % (g_rcname,)) + + +class DemoWindow: + def __init__(self, dlg_template): + self.dlg_template = dlg_template + + def CreateWindow(self): + self._DoCreate(win32gui.CreateDialogIndirect) + + def DoModal(self): + return self._DoCreate(win32gui.DialogBoxIndirect) + + def _DoCreate(self, fn): + message_map = { + win32con.WM_INITDIALOG: self.OnInitDialog, + win32con.WM_CLOSE: self.OnClose, + win32con.WM_DESTROY: self.OnDestroy, + win32con.WM_COMMAND: self.OnCommand, + } + return fn(0, self.dlg_template, 0, message_map) + + def OnInitDialog(self, hwnd, msg, wparam, lparam): + self.hwnd = hwnd + # centre the dialog + desktop = win32gui.GetDesktopWindow() + l, t, r, b = win32gui.GetWindowRect(self.hwnd) + dt_l, dt_t, dt_r, dt_b = win32gui.GetWindowRect(desktop) + centre_x, centre_y = win32gui.ClientToScreen( + desktop, ((dt_r - dt_l) // 2, (dt_b - dt_t) // 2) + ) + win32gui.MoveWindow( + hwnd, centre_x - (r // 2), centre_y - (b // 2), r - l, b - t, 0 + ) + + def OnCommand(self, hwnd, msg, wparam, lparam): + # Needed to make OK/Cancel work - no other controls are handled. + id = win32api.LOWORD(wparam) + if id in [win32con.IDOK, win32con.IDCANCEL]: + win32gui.EndDialog(hwnd, id) + + def OnClose(self, hwnd, msg, wparam, lparam): + win32gui.EndDialog(hwnd, 0) + + def OnDestroy(self, hwnd, msg, wparam, lparam): + pass + + +def DemoModal(): + # Load the .rc file. + resources = win32rcparser.Parse(g_rcname) + for id, ddef in resources.dialogs.items(): + print("Displaying dialog", id) + w = DemoWindow(ddef) + w.DoModal() + + +if __name__ == "__main__": + flags = 0 + for flag in """ICC_DATE_CLASSES ICC_ANIMATE_CLASS ICC_ANIMATE_CLASS + ICC_BAR_CLASSES ICC_COOL_CLASSES ICC_DATE_CLASSES + ICC_HOTKEY_CLASS ICC_INTERNET_CLASSES ICC_LISTVIEW_CLASSES + ICC_PAGESCROLLER_CLASS ICC_PROGRESS_CLASS ICC_TAB_CLASSES + ICC_TREEVIEW_CLASSES ICC_UPDOWN_CLASS ICC_USEREX_CLASSES + ICC_WIN95_CLASSES """.split(): + flags |= getattr(commctrl, flag) + win32gui.InitCommonControlsEx(flags) + # Need to do this go get rich-edit working. + win32api.LoadLibrary("riched20.dll") + DemoModal() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32servicedemo.py b/MLPY/Lib/site-packages/win32/Demos/win32servicedemo.py new file mode 100644 index 0000000000000000000000000000000000000000..75967ef3aee450680ea741a65b0eddb0e492d588 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32servicedemo.py @@ -0,0 +1,23 @@ +import win32con +import win32service + + +def EnumServices(): + resume = 0 + accessSCM = win32con.GENERIC_READ + accessSrv = win32service.SC_MANAGER_ALL_ACCESS + + # Open Service Control Manager + hscm = win32service.OpenSCManager(None, None, accessSCM) + + # Enumerate Service Control Manager DB + + typeFilter = win32service.SERVICE_WIN32 + stateFilter = win32service.SERVICE_STATE_ALL + + statuses = win32service.EnumServicesStatus(hscm, typeFilter, stateFilter) + for short_name, desc, status in statuses: + print(short_name, desc, status) + + +EnumServices() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32ts_logoff_disconnected.py b/MLPY/Lib/site-packages/win32/Demos/win32ts_logoff_disconnected.py new file mode 100644 index 0000000000000000000000000000000000000000..be61e5d1f316adca6f86c8247a65ef001b64dab1 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32ts_logoff_disconnected.py @@ -0,0 +1,24 @@ +""" Finds any disconnected terminal service sessions and logs them off""" +import pywintypes +import win32ts +import winerror + +sessions = win32ts.WTSEnumerateSessions(win32ts.WTS_CURRENT_SERVER_HANDLE) +for session in sessions: + """ + WTS_CONNECTSTATE_CLASS: WTSActive,WTSConnected,WTSConnectQuery,WTSShadow,WTSDisconnected, + WTSIdle,WTSListen,WTSReset,WTSDown,WTSInit + """ + if session["State"] == win32ts.WTSDisconnected: + sessionid = session["SessionId"] + username = win32ts.WTSQuerySessionInformation( + win32ts.WTS_CURRENT_SERVER_HANDLE, sessionid, win32ts.WTSUserName + ) + print("Logging off disconnected user:", username) + try: + win32ts.WTSLogoffSession(win32ts.WTS_CURRENT_SERVER_HANDLE, sessionid, True) + except pywintypes.error as e: + if e.winerror == winerror.ERROR_ACCESS_DENIED: + print("Can't kill that session:", e.strerror) + else: + raise diff --git a/MLPY/Lib/site-packages/win32/Demos/win32wnet/__pycache__/testwnet.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/win32wnet/__pycache__/testwnet.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51a51e109acf81539fcfc808743be5823c3930ca Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/win32wnet/__pycache__/testwnet.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/win32wnet/__pycache__/winnetwk.cpython-39.pyc b/MLPY/Lib/site-packages/win32/Demos/win32wnet/__pycache__/winnetwk.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8530efe7cdeb04527a82eea436f958033a002de5 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/Demos/win32wnet/__pycache__/winnetwk.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/Demos/win32wnet/testwnet.py b/MLPY/Lib/site-packages/win32/Demos/win32wnet/testwnet.py new file mode 100644 index 0000000000000000000000000000000000000000..3b21ac29c442c30fdf50f77d3d9fdc2bb0cf22fe --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32wnet/testwnet.py @@ -0,0 +1,125 @@ +import os + +import win32api +import win32wnet +from winnetwk import * + +possible_shares = [] + + +def _doDumpHandle(handle, level=0): + indent = " " * level + while 1: + items = win32wnet.WNetEnumResource(handle, 0) + if len(items) == 0: + break + for item in items: + try: + if item.dwDisplayType == RESOURCEDISPLAYTYPE_SHARE: + print(indent + "Have share with name:", item.lpRemoteName) + possible_shares.append(item) + elif item.dwDisplayType == RESOURCEDISPLAYTYPE_GENERIC: + print( + indent + "Have generic resource with name:", item.lpRemoteName + ) + else: + # Try generic! + print(indent + "Enumerating " + item.lpRemoteName, end=" ") + k = win32wnet.WNetOpenEnum( + RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, item + ) + print() + _doDumpHandle(k, level + 1) + win32wnet.WNetCloseEnum( + k + ) # could do k.Close(), but this is a good test! + except win32wnet.error as details: + print(indent + "Couldn't enumerate this resource: " + details.strerror) + + +def TestOpenEnum(): + print("Enumerating all resources on the network - this may take some time...") + handle = win32wnet.WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, None) + + try: + _doDumpHandle(handle) + finally: + handle.Close() + print("Finished dumping all resources.") + + +def findUnusedDriveLetter(): + existing = [ + x[0].lower() for x in win32api.GetLogicalDriveStrings().split("\0") if x + ] + handle = win32wnet.WNetOpenEnum(RESOURCE_REMEMBERED, RESOURCETYPE_DISK, 0, None) + try: + while 1: + items = win32wnet.WNetEnumResource(handle, 0) + if len(items) == 0: + break + xtra = [i.lpLocalName[0].lower() for i in items if i.lpLocalName] + existing.extend(xtra) + finally: + handle.Close() + for maybe in "defghijklmnopqrstuvwxyz": + if maybe not in existing: + return maybe + raise RuntimeError("All drive mappings are taken?") + + +def TestConnection(): + if len(possible_shares) == 0: + print("Couldn't find any potential shares to connect to") + return + localName = findUnusedDriveLetter() + ":" + for share in possible_shares: + print("Attempting connection of", localName, "to", share.lpRemoteName) + try: + win32wnet.WNetAddConnection2(share.dwType, localName, share.lpRemoteName) + except win32wnet.error as details: + print("Couldn't connect: " + details.strerror) + continue + # Have a connection. + try: + fname = os.path.join(localName + "\\", os.listdir(localName + "\\")[0]) + try: + print( + "Universal name of '%s' is '%s'" + % (fname, win32wnet.WNetGetUniversalName(fname)) + ) + except win32wnet.error as details: + print( + "Couldn't get universal name of '%s': %s" + % (fname, details.strerror) + ) + print("User name for this connection is", win32wnet.WNetGetUser(localName)) + finally: + win32wnet.WNetCancelConnection2(localName, 0, 0) + # and do it again, but this time by using the more modern + # NETRESOURCE way. + nr = win32wnet.NETRESOURCE() + nr.dwType = share.dwType + nr.lpLocalName = localName + nr.lpRemoteName = share.lpRemoteName + win32wnet.WNetAddConnection2(nr) + win32wnet.WNetCancelConnection2(localName, 0, 0) + + # and one more time using WNetAddConnection3 + win32wnet.WNetAddConnection3(0, nr) + win32wnet.WNetCancelConnection2(localName, 0, 0) + + # Only do the first share that succeeds. + break + + +def TestGetUser(): + u = win32wnet.WNetGetUser() + print("Current global user is", repr(u)) + if u != win32wnet.WNetGetUser(None): + raise RuntimeError("Default value didnt seem to work!") + + +TestGetUser() +TestOpenEnum() +TestConnection() diff --git a/MLPY/Lib/site-packages/win32/Demos/win32wnet/winnetwk.py b/MLPY/Lib/site-packages/win32/Demos/win32wnet/winnetwk.py new file mode 100644 index 0000000000000000000000000000000000000000..036e2ebf81870affea3eaadf9010d6f194763fba --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/win32wnet/winnetwk.py @@ -0,0 +1,100 @@ +# Generated by h2py from d:\mssdk\include\winnetwk.h +WNNC_NET_MSNET = 0x00010000 +WNNC_NET_LANMAN = 0x00020000 +WNNC_NET_NETWARE = 0x00030000 +WNNC_NET_VINES = 0x00040000 +WNNC_NET_10NET = 0x00050000 +WNNC_NET_LOCUS = 0x00060000 +WNNC_NET_SUN_PC_NFS = 0x00070000 +WNNC_NET_LANSTEP = 0x00080000 +WNNC_NET_9TILES = 0x00090000 +WNNC_NET_LANTASTIC = 0x000A0000 +WNNC_NET_AS400 = 0x000B0000 +WNNC_NET_FTP_NFS = 0x000C0000 +WNNC_NET_PATHWORKS = 0x000D0000 +WNNC_NET_LIFENET = 0x000E0000 +WNNC_NET_POWERLAN = 0x000F0000 +WNNC_NET_BWNFS = 0x00100000 +WNNC_NET_COGENT = 0x00110000 +WNNC_NET_FARALLON = 0x00120000 +WNNC_NET_APPLETALK = 0x00130000 +WNNC_NET_INTERGRAPH = 0x00140000 +WNNC_NET_SYMFONET = 0x00150000 +WNNC_NET_CLEARCASE = 0x00160000 +WNNC_NET_FRONTIER = 0x00170000 +WNNC_NET_BMC = 0x00180000 +WNNC_NET_DCE = 0x00190000 +WNNC_NET_DECORB = 0x00200000 +WNNC_NET_PROTSTOR = 0x00210000 +WNNC_NET_FJ_REDIR = 0x00220000 +WNNC_NET_DISTINCT = 0x00230000 +WNNC_NET_TWINS = 0x00240000 +WNNC_NET_RDR2SAMPLE = 0x00250000 +RESOURCE_CONNECTED = 0x00000001 +RESOURCE_GLOBALNET = 0x00000002 +RESOURCE_REMEMBERED = 0x00000003 +RESOURCE_RECENT = 0x00000004 +RESOURCE_CONTEXT = 0x00000005 +RESOURCETYPE_ANY = 0x00000000 +RESOURCETYPE_DISK = 0x00000001 +RESOURCETYPE_PRINT = 0x00000002 +RESOURCETYPE_RESERVED = 0x00000008 +RESOURCETYPE_UNKNOWN = 0xFFFFFFFF +RESOURCEUSAGE_CONNECTABLE = 0x00000001 +RESOURCEUSAGE_CONTAINER = 0x00000002 +RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004 +RESOURCEUSAGE_SIBLING = 0x00000008 +RESOURCEUSAGE_ATTACHED = 0x00000010 +RESOURCEUSAGE_ALL = ( + RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED +) +RESOURCEUSAGE_RESERVED = 0x80000000 +RESOURCEDISPLAYTYPE_GENERIC = 0x00000000 +RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001 +RESOURCEDISPLAYTYPE_SERVER = 0x00000002 +RESOURCEDISPLAYTYPE_SHARE = 0x00000003 +RESOURCEDISPLAYTYPE_FILE = 0x00000004 +RESOURCEDISPLAYTYPE_GROUP = 0x00000005 +RESOURCEDISPLAYTYPE_NETWORK = 0x00000006 +RESOURCEDISPLAYTYPE_ROOT = 0x00000007 +RESOURCEDISPLAYTYPE_SHAREADMIN = 0x00000008 +RESOURCEDISPLAYTYPE_DIRECTORY = 0x00000009 +RESOURCEDISPLAYTYPE_TREE = 0x0000000A +RESOURCEDISPLAYTYPE_NDSCONTAINER = 0x0000000B +NETPROPERTY_PERSISTENT = 1 +CONNECT_UPDATE_PROFILE = 0x00000001 +CONNECT_UPDATE_RECENT = 0x00000002 +CONNECT_TEMPORARY = 0x00000004 +CONNECT_INTERACTIVE = 0x00000008 +CONNECT_PROMPT = 0x00000010 +CONNECT_NEED_DRIVE = 0x00000020 +CONNECT_REFCOUNT = 0x00000040 +CONNECT_REDIRECT = 0x00000080 +CONNECT_LOCALDRIVE = 0x00000100 +CONNECT_CURRENT_MEDIA = 0x00000200 +CONNECT_DEFERRED = 0x00000400 +CONNECT_RESERVED = 0xFF000000 +CONNDLG_RO_PATH = 0x00000001 +CONNDLG_CONN_POINT = 0x00000002 +CONNDLG_USE_MRU = 0x00000004 +CONNDLG_HIDE_BOX = 0x00000008 +CONNDLG_PERSIST = 0x00000010 +CONNDLG_NOT_PERSIST = 0x00000020 +DISC_UPDATE_PROFILE = 0x00000001 +DISC_NO_FORCE = 0x00000040 +UNIVERSAL_NAME_INFO_LEVEL = 0x00000001 +REMOTE_NAME_INFO_LEVEL = 0x00000002 +WNFMT_MULTILINE = 0x01 +WNFMT_ABBREVIATED = 0x02 +WNFMT_INENUM = 0x10 +WNFMT_CONNECTION = 0x20 +NETINFO_DLL16 = 0x00000001 +NETINFO_DISKRED = 0x00000004 +NETINFO_PRINTERRED = 0x00000008 +RP_LOGON = 0x01 +RP_INIFILE = 0x02 +PP_DISPLAYERRORS = 0x01 +WNCON_FORNETCARD = 0x00000001 +WNCON_NOTROUTED = 0x00000002 +WNCON_SLOWLINK = 0x00000004 +WNCON_DYNAMIC = 0x00000008 diff --git a/MLPY/Lib/site-packages/win32/Demos/winprocess.py b/MLPY/Lib/site-packages/win32/Demos/winprocess.py new file mode 100644 index 0000000000000000000000000000000000000000..48f6fe719427160a0e5c3d9bcc9f3a59f37cf313 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/Demos/winprocess.py @@ -0,0 +1,230 @@ +""" +Windows Process Control + +winprocess.run launches a child process and returns the exit code. +Optionally, it can: + redirect stdin, stdout & stderr to files + run the command as another user + limit the process's running time + control the process window (location, size, window state, desktop) +Works on Windows NT, 2000 & XP. Requires Mark Hammond's win32 +extensions. + +This code is free for any purpose, with no warranty of any kind. +-- John B. Dell'Aquila +""" + +import msvcrt +import os + +import win32api +import win32con +import win32event +import win32gui +import win32process +import win32security + + +def logonUser(loginString): + """ + Login as specified user and return handle. + loginString: 'Domain\nUser\nPassword'; for local + login use . or empty string as domain + e.g. '.\nadministrator\nsecret_password' + """ + domain, user, passwd = loginString.split("\n") + return win32security.LogonUser( + user, + domain, + passwd, + win32con.LOGON32_LOGON_INTERACTIVE, + win32con.LOGON32_PROVIDER_DEFAULT, + ) + + +class Process: + """ + A Windows process. + """ + + def __init__( + self, + cmd, + login=None, + hStdin=None, + hStdout=None, + hStderr=None, + show=1, + xy=None, + xySize=None, + desktop=None, + ): + """ + Create a Windows process. + cmd: command to run + login: run as user 'Domain\nUser\nPassword' + hStdin, hStdout, hStderr: + handles for process I/O; default is caller's stdin, + stdout & stderr + show: wShowWindow (0=SW_HIDE, 1=SW_NORMAL, ...) + xy: window offset (x, y) of upper left corner in pixels + xySize: window size (width, height) in pixels + desktop: lpDesktop - name of desktop e.g. 'winsta0\\default' + None = inherit current desktop + '' = create new desktop if necessary + + User calling login requires additional privileges: + Act as part of the operating system [not needed on Windows XP] + Increase quotas + Replace a process level token + Login string must EITHER be an administrator's account + (ordinary user can't access current desktop - see Microsoft + Q165194) OR use desktop='' to run another desktop invisibly + (may be very slow to startup & finalize). + """ + si = win32process.STARTUPINFO() + si.dwFlags = win32con.STARTF_USESTDHANDLES ^ win32con.STARTF_USESHOWWINDOW + if hStdin is None: + si.hStdInput = win32api.GetStdHandle(win32api.STD_INPUT_HANDLE) + else: + si.hStdInput = hStdin + if hStdout is None: + si.hStdOutput = win32api.GetStdHandle(win32api.STD_OUTPUT_HANDLE) + else: + si.hStdOutput = hStdout + if hStderr is None: + si.hStdError = win32api.GetStdHandle(win32api.STD_ERROR_HANDLE) + else: + si.hStdError = hStderr + si.wShowWindow = show + if xy is not None: + si.dwX, si.dwY = xy + si.dwFlags ^= win32con.STARTF_USEPOSITION + if xySize is not None: + si.dwXSize, si.dwYSize = xySize + si.dwFlags ^= win32con.STARTF_USESIZE + if desktop is not None: + si.lpDesktop = desktop + procArgs = ( + None, # appName + cmd, # commandLine + None, # processAttributes + None, # threadAttributes + 1, # bInheritHandles + win32process.CREATE_NEW_CONSOLE, # dwCreationFlags + None, # newEnvironment + None, # currentDirectory + si, + ) # startupinfo + if login is not None: + hUser = logonUser(login) + win32security.ImpersonateLoggedOnUser(hUser) + procHandles = win32process.CreateProcessAsUser(hUser, *procArgs) + win32security.RevertToSelf() + else: + procHandles = win32process.CreateProcess(*procArgs) + self.hProcess, self.hThread, self.PId, self.TId = procHandles + + def wait(self, mSec=None): + """ + Wait for process to finish or for specified number of + milliseconds to elapse. + """ + if mSec is None: + mSec = win32event.INFINITE + return win32event.WaitForSingleObject(self.hProcess, mSec) + + def kill(self, gracePeriod=5000): + """ + Kill process. Try for an orderly shutdown via WM_CLOSE. If + still running after gracePeriod (5 sec. default), terminate. + """ + win32gui.EnumWindows(self.__close__, 0) + if self.wait(gracePeriod) != win32event.WAIT_OBJECT_0: + win32process.TerminateProcess(self.hProcess, 0) + win32api.Sleep(100) # wait for resources to be released + + def __close__(self, hwnd, dummy): + """ + EnumWindows callback - sends WM_CLOSE to any window + owned by this process. + """ + TId, PId = win32process.GetWindowThreadProcessId(hwnd) + if PId == self.PId: + win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0) + + def exitCode(self): + """ + Return process exit code. + """ + return win32process.GetExitCodeProcess(self.hProcess) + + +def run(cmd, mSec=None, stdin=None, stdout=None, stderr=None, **kw): + """ + Run cmd as a child process and return exit code. + mSec: terminate cmd after specified number of milliseconds + stdin, stdout, stderr: + file objects for child I/O (use hStdin etc. to attach + handles instead of files); default is caller's stdin, + stdout & stderr; + kw: see Process.__init__ for more keyword options + """ + if stdin is not None: + kw["hStdin"] = msvcrt.get_osfhandle(stdin.fileno()) + if stdout is not None: + kw["hStdout"] = msvcrt.get_osfhandle(stdout.fileno()) + if stderr is not None: + kw["hStderr"] = msvcrt.get_osfhandle(stderr.fileno()) + child = Process(cmd, **kw) + if child.wait(mSec) != win32event.WAIT_OBJECT_0: + child.kill() + raise WindowsError("process timeout exceeded") + return child.exitCode() + + +if __name__ == "__main__": + # Pipe commands to a shell and display the output in notepad + print("Testing winprocess.py...") + + import tempfile + + timeoutSeconds = 15 + cmdString = ( + """\ +REM Test of winprocess.py piping commands to a shell.\r +REM This 'notepad' process will terminate in %d seconds.\r +vol\r +net user\r +_this_is_a_test_of_stderr_\r +""" + % timeoutSeconds + ) + + cmd_name = tempfile.mktemp() + out_name = cmd_name + ".txt" + try: + cmd = open(cmd_name, "w+b") + out = open(out_name, "w+b") + cmd.write(cmdString.encode("mbcs")) + cmd.seek(0) + print( + "CMD.EXE exit code:", + run("cmd.exe", show=0, stdin=cmd, stdout=out, stderr=out), + ) + cmd.close() + print( + "NOTEPAD exit code:", + run( + "notepad.exe %s" % out.name, + show=win32con.SW_MAXIMIZE, + mSec=timeoutSeconds * 1000, + ), + ) + out.close() + finally: + for n in (cmd_name, out_name): + try: + os.unlink(cmd_name) + except os.error: + pass diff --git a/MLPY/Lib/site-packages/win32/_win32sysloader.pyd b/MLPY/Lib/site-packages/win32/_win32sysloader.pyd new file mode 100644 index 0000000000000000000000000000000000000000..416f3478e2360dd6496b343df5ae9209f5615de3 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/_win32sysloader.pyd differ diff --git a/MLPY/Lib/site-packages/win32/_winxptheme.pyd b/MLPY/Lib/site-packages/win32/_winxptheme.pyd new file mode 100644 index 0000000000000000000000000000000000000000..c55273d675f6a7bc75ae066871ed760bd14f278a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/_winxptheme.pyd differ diff --git a/MLPY/Lib/site-packages/win32/include/PyWinTypes.h b/MLPY/Lib/site-packages/win32/include/PyWinTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..edfdb0b69afe1a8da880c4854d43506fd56eeb3e --- /dev/null +++ b/MLPY/Lib/site-packages/win32/include/PyWinTypes.h @@ -0,0 +1,727 @@ + +#ifndef __PYWINTYPES_H__ +#define __PYWINTYPES_H__ + +// If building under a GCC, tweak what we need. +#if defined(__GNUC__) && defined(_POSIX_C_SOURCE) +// python.h complains if _POSIX_C_SOURCE is already defined +#undef _POSIX_C_SOURCE +#endif + +// windows rpc.h defines "small" as "char" which breaks Python's accu.h, +// so we undefine it before including python. +#ifdef small +#undef small +#endif + +#include "Python.h" +#include "structmember.h" +#include "windows.h" + +// Helpers for our modules. +// Some macros to help the pywin32 modules co-exist in py2x and py3k. +// Creates and initializes local variables called 'module' and 'dict'. + +// Maybe these should all be removed - they existed to help in the py2->3 +// transition. +// On one hand: the code would be cleaner if they were all just re-inlined? +// On the other: high confidence everything uses the exact same patterns? +// (Regardless, *some*, eg, PYWIN_MODULE_INIT_RETURN_* should be re-inlined!) + +// Use to define the function itself (ie, its name, linkage, params) +#define PYWIN_MODULE_INIT_FUNC(module_name) extern "C" __declspec(dllexport) PyObject *PyInit_##module_name(void) + +// If the module needs to early-exit on an error condition. +#define PYWIN_MODULE_INIT_RETURN_ERROR return NULL; + +// When the module has successfully initialized. +#define PYWIN_MODULE_INIT_RETURN_SUCCESS return module; + +// To setup the module object itself and the module's dictionary. +#define PYWIN_MODULE_INIT_PREPARE(module_name, functions, docstring) \ + PyObject *dict, *module; \ + static PyModuleDef module_name##_def = {PyModuleDef_HEAD_INIT, #module_name, docstring, -1, functions}; \ + if (PyWinGlobals_Ensure() == -1) \ + return NULL; \ + if (!(module = PyModule_Create(&module_name##_def))) \ + return NULL; \ + if (!(dict = PyModule_GetDict(module))) \ + return NULL; + +// Helpers for our types. +// Macro to handle PyObject layout changes in Py3k +#define PYWIN_OBJECT_HEAD PyVarObject_HEAD_INIT(NULL, 0) + +/* Attribute names are passed as Unicode in Py3k, so use a macro to + switch between string and unicode conversion. This function is not + documented, but is used extensively in the Python codebase itself, + so it's reasonable to assume it won't disappear anytime soon. +*/ +#define PYWIN_ATTR_CONVERT (char *)_PyUnicode_AsString + +typedef Py_ssize_t Py_hash_t; + +// This only enables runtime checks in debug builds - so we use +// our own so we can enable it always should we desire... +#define PyWin_SAFE_DOWNCAST Py_SAFE_DOWNCAST + +// Lars: for WAVEFORMATEX +#include "mmsystem.h" + +#ifdef BUILD_PYWINTYPES +/* We are building pywintypesxx.dll */ +#define PYWINTYPES_EXPORT __declspec(dllexport) +#else +/* This module uses pywintypesxx.dll */ +#define PYWINTYPES_EXPORT __declspec(dllimport) +#if defined(_MSC_VER) +#if defined(DEBUG) || defined(_DEBUG) +#pragma comment(lib, "pywintypes_d.lib") +#else +#pragma comment(lib, "pywintypes.lib") +#endif // DEBUG/_DEBUG +#endif // _MSC_VER +#endif // BUILD_PYWINTYPES + +// Py3k uses memoryview object in place of buffer, and we don't yet. +extern PYWINTYPES_EXPORT PyObject *PyBuffer_New(Py_ssize_t size); +extern PYWINTYPES_EXPORT PyObject *PyBuffer_FromMemory(void *buf, Py_ssize_t size); + +// Formats a python traceback into a character string - result must be free()ed +PYWINTYPES_EXPORT WCHAR *GetPythonTraceback(PyObject *exc_type, PyObject *exc_value, PyObject *exc_tb); + +#include +/* +** Error/Exception handling +*/ +extern PYWINTYPES_EXPORT PyObject *PyWinExc_ApiError; +// Register a Windows DLL that contains the messages in the specified range. +extern PYWINTYPES_EXPORT BOOL PyWin_RegisterErrorMessageModule(DWORD first, DWORD last, HINSTANCE hmod); +// Get the previously registered hmodule for an error code. +extern PYWINTYPES_EXPORT HINSTANCE PyWin_GetErrorMessageModule(DWORD err); + +/* A global function that sets an API style error (ie, (code, fn, errTest)) */ +PYWINTYPES_EXPORT PyObject *PyWin_SetAPIError(char *fnName, long err = 0); + +/* Basic COM Exception handling. The main COM exception object + is actually defined here. However, the most useful functions + for raising the exception are still in the COM package. Therefore, + you can use the fn below to raise a basic COM exception - no fancy error + messages available, just the HRESULT. It will, however, _be_ a COM + exception, and therefore trappable like any other COM exception +*/ +extern PYWINTYPES_EXPORT PyObject *PyWinExc_COMError; +PYWINTYPES_EXPORT PyObject *PyWin_SetBasicCOMError(HRESULT hr); + +// ************* +// strings, which are a bit of a mess! +// +// This has gone from 2.x ascii-only, to 2.x+3.x ascii-or-unicode, to 3.x unicode-only, +// - this baggage means some strange APIs which convert to and from "char *" in various ways. +// +// A sizes/lengths are reported as a `DWORD` rather than a `Py_ssize_t`, that's what the callers +// need. `Py_ssize_t` used as the "in" type. +// (We also use this for UINT and ULONG, all of which are 32bit unsigned ints.) + +// Sometimes we need to downcast from a ssize_t to a DWORD +inline bool PyWin_is_ssize_dword(Py_ssize_t val) { + return val <= MAXDWORD; +} + +#define PYWIN_CHECK_SSIZE_DWORD(val, failResult) \ + if (!PyWin_is_ssize_dword(val)) { \ + PyErr_SetString(PyExc_ValueError, "value is larger than a DWORD"); \ + return failResult; \ + } + +// Almost all of these are roughly identical! But start with BSTR +// Given a PyObject (string, Unicode, etc) create a "BSTR" with the value +PYWINTYPES_EXPORT BOOL PyWinObject_AsBstr(PyObject *stringObject, BSTR *pResult, BOOL bNoneOK = FALSE, + DWORD *pResultLen = NULL); +// And free it when finished. +PYWINTYPES_EXPORT void PyWinObject_FreeBstr(BSTR pResult); + +PYWINTYPES_EXPORT PyObject *PyWinObject_FromBstr(const BSTR bstr, BOOL takeOwnership = FALSE); + +// Given a string or Unicode object, get WCHAR characters. +PYWINTYPES_EXPORT BOOL PyWinObject_AsWCHAR(PyObject *stringObject, WCHAR **pResult, BOOL bNoneOK = FALSE, + DWORD *pResultLen = NULL); +// And free it when finished. +PYWINTYPES_EXPORT void PyWinObject_FreeWCHAR(WCHAR *pResult); + +inline BOOL PyWinObject_AsWCHAR(PyObject *stringObject, unsigned short **pResult, BOOL bNoneOK = FALSE, + DWORD *pResultLen = NULL) +{ + return PyWinObject_AsWCHAR(stringObject, (WCHAR **)pResult, bNoneOK, pResultLen); +} +inline void PyWinObject_FreeWCHAR(unsigned short *pResult) { PyWinObject_FreeWCHAR((WCHAR *)pResult); } + +// A bit unfortunate, but used when we logically want a "string" but only have +// a "char *" to put it in. +// * accepts bytes but boesn't try to accept buffer-like objects. +// * accepts unicode objects and converts via the code-page. +PYWINTYPES_EXPORT BOOL PyWinObject_AsChars(PyObject *stringObject, char **pResult, BOOL bNoneOK = FALSE, + DWORD *pResultLen = NULL); +// And free it when finished. +PYWINTYPES_EXPORT void PyWinObject_FreeChars(char *pResult); + +// Automatically freed WCHAR that can be used anywhere WCHAR * is required +class TmpWCHAR { + public: + WCHAR *tmp; // (NULL after conversion error) + Py_ssize_t length; // only set after successful auto-conversion; w/o trailing \0 + PyObject *u; // auxiliary slot for u2w() + + TmpWCHAR() { tmp = NULL; } + TmpWCHAR(WCHAR *t) { tmp = t; } + TmpWCHAR(PyObject *ob) : tmp(NULL) { *this = ob; } + WCHAR *u2w() { return *this = u; } + WCHAR *operator=(PyObject *ob) { + if (tmp) + PyMem_Free(tmp); + if (ob == NULL) + tmp = NULL; // (exception already has been set in this case) + else + tmp = PyUnicode_AsWideCharString(ob, &length); + return tmp; + } + WCHAR *operator=(WCHAR *t) + { + if (tmp) + PyMem_Free(tmp); + tmp = t; + return t; + } + WCHAR **operator&() { return &tmp; } + boolean operator==(WCHAR *t) { return tmp == t; } + operator WCHAR *() { return tmp; } + ~TmpWCHAR() { if (tmp) PyMem_Free(tmp); } + private: + // Block unwanted copy construction + TmpWCHAR(const TmpWCHAR& o); // = delete; + const TmpWCHAR& operator=(const TmpWCHAR& o); // = delete; +}; + +// More string helpers - how many do we need? +// A couple which should die or be modernized and have some `char *` vs `wchar_t *` confusion. +PYWINTYPES_EXPORT PyObject *PyWinCoreString_FromString(const char *str, Py_ssize_t len = (Py_ssize_t)-1); +PYWINTYPES_EXPORT PyObject *PyWinCoreString_FromString(const WCHAR *str, Py_ssize_t len = (Py_ssize_t)-1); + +#define PyWinObject_FromWCHAR PyWinObject_FromOLECHAR + +PYWINTYPES_EXPORT PyObject *PyWinObject_FromOLECHAR(const OLECHAR *str); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromOLECHAR(const OLECHAR *str, Py_ssize_t numChars); + +#define PyWinObject_AsTCHAR PyWinObject_AsWCHAR +#define PyWinObject_FreeTCHAR PyWinObject_FreeWCHAR +#define PyWinObject_FromTCHAR PyWinObject_FromOLECHAR + +// String support for buffers allocated via CoTaskMemAlloc and CoTaskMemFree +PYWINTYPES_EXPORT BOOL PyWinObject_AsTaskAllocatedWCHAR(PyObject *stringObject, WCHAR **ppResult, BOOL bNoneOK = FALSE); +PYWINTYPES_EXPORT void PyWinObject_FreeTaskAllocatedWCHAR(WCHAR *str); + +// Copy null terminated string with same allocator as PyWinObject_AsWCHAR, etc +// ? wot? +PYWINTYPES_EXPORT WCHAR *PyWin_CopyString(const WCHAR *input); +PYWINTYPES_EXPORT char *PyWin_CopyString(const char *input); + +// Some helpers for arrays of strings. +// +// Converts a series of consecutive null terminated strings into a list +// ??? wot? +PYWINTYPES_EXPORT PyObject *PyWinObject_FromMultipleString(WCHAR *multistring); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromMultipleString(char *multistring); +// Converts a sequence of str/unicode objects into a series of consecutive null-terminated +// wide character strings with extra terminating null +PYWINTYPES_EXPORT BOOL PyWinObject_AsMultipleString(PyObject *ob, WCHAR **pmultistring, BOOL bNoneOK = TRUE, + DWORD *chars_returned = NULL); +PYWINTYPES_EXPORT void PyWinObject_FreeMultipleString(WCHAR *pmultistring); + +// Convert a sequence of strings to an array of WCHAR pointers +PYWINTYPES_EXPORT void PyWinObject_FreeWCHARArray(LPWSTR *wchars, DWORD str_cnt); +PYWINTYPES_EXPORT BOOL PyWinObject_AsWCHARArray(PyObject *str_seq, LPWSTR **wchars, DWORD *str_cnt, + BOOL bNoneOK = FALSE); + +// Convert a sequence of string or unicode objects to an array of char * +PYWINTYPES_EXPORT void PyWinObject_FreeCharArray(char **pchars, DWORD str_cnt); +PYWINTYPES_EXPORT BOOL PyWinObject_AsCharArray(PyObject *str_seq, char ***pchars, DWORD *str_cnt, BOOL bNoneOK = FALSE); + +// Bytes/Buffer helpers. +// replacement for PyWinObject_AsReadBuffer and PyWinObject_AsWriteBuffer +class PYWINTYPES_EXPORT PyWinBufferView +{ +public: + PyWinBufferView() { m_view.obj = NULL; } + PyWinBufferView(PyObject *ob, bool bWrite = false, bool bNoneOk = false) { + m_view.obj = NULL; + init(ob, bWrite, bNoneOk); + } + ~PyWinBufferView() { release(); } + bool init(PyObject *ob, bool bWrite = false, bool bNoneOk = false); + void release() { + if (m_view.obj != NULL && m_view.obj != Py_None) { + PyBuffer_Release(&m_view); // sets view->obj = NULL + } + } + bool ok() { return m_view.obj != NULL; } + void* ptr() { return m_view.buf; } + DWORD len() { return static_cast(m_view.len); } + +private: + Py_buffer m_view; + + // don't copy objects and don't use C++ >= 11 -> not implemented private + // copy ctor and assignment operator + PyWinBufferView(const PyWinBufferView& src); + PyWinBufferView& operator=(PyWinBufferView const &); +}; + + +// For 64-bit python compatibility, convert sequence to tuple and check length fits in a DWORD +PYWINTYPES_EXPORT PyObject *PyWinSequence_Tuple(PyObject *obseq, DWORD *len); + +// Pointers. +// Substitute for Python's inconsistent PyLong_AsVoidPtr +PYWINTYPES_EXPORT BOOL PyWinLong_AsVoidPtr(PyObject *ob, void **pptr); +PYWINTYPES_EXPORT PyObject *PyWinLong_FromVoidPtr(const void *ptr); + +/* +** LARGE_INTEGER objects +*/ +// AsLARGE_INTEGER takes either int or long +PYWINTYPES_EXPORT BOOL PyWinObject_AsLARGE_INTEGER(PyObject *ob, LARGE_INTEGER *pResult); +PYWINTYPES_EXPORT BOOL PyWinObject_AsULARGE_INTEGER(PyObject *ob, ULARGE_INTEGER *pResult); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromLARGE_INTEGER(const LARGE_INTEGER &val); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromULARGE_INTEGER(const ULARGE_INTEGER &val); +// Helpers that take a Py_LONG_LONG, but (a) have pywin32 consistent signatures +// and (b) handle int *and* long (where Python only starts doing that in the +// PyLong_* APIs post 2.4) +// We also happen to know a LARGE_INTEGER is an __int64, so do it the easy way +#define PyWinObject_AsPY_LONG_LONG(ob, pResult) PyWinObject_AsLARGE_INTEGER((ob), (LARGE_INTEGER *)(pResult)) +#define PyWinObject_AsUPY_LONG_LONG(ob, pResult) PyWinObject_AsULARGE_INTEGER((ob), (ULARGE_INTEGER *)(pResult)) +#define PyWinObject_FromPY_LONG_LONG(val) PyWinObject_FromLARGE_INTEGER((LARGE_INTEGER)val) +#define PyWinObject_FromUPY_LONG_LONG(val) PyWinObject_FromULARGE_INTEGER((ULARGE_INTEGER)val) + +// A DWORD_PTR and ULONG_PTR appear to mean "integer long enough to hold a pointer" +// It is *not* actually a pointer (but is the same size as a pointer) +inline PyObject *PyWinObject_FromULONG_PTR(ULONG_PTR v) { return PyWinLong_FromVoidPtr((void *)v); } +inline BOOL PyWinLong_AsULONG_PTR(PyObject *ob, ULONG_PTR *r) { return PyWinLong_AsVoidPtr(ob, (void **)r); } + +inline PyObject *PyWinObject_FromDWORD_PTR(DWORD_PTR v) { return PyLong_FromVoidPtr((void *)v); } +inline BOOL PyWinLong_AsDWORD_PTR(PyObject *ob, DWORD_PTR *r) { return PyWinLong_AsVoidPtr(ob, (void **)r); } + +/* +** OVERLAPPED Object and API +*/ +class PyOVERLAPPED; // forward declare +extern PYWINTYPES_EXPORT PyTypeObject PyOVERLAPPEDType; // the Type for PyOVERLAPPED +#define PyOVERLAPPED_Check(ob) ((ob)->ob_type == &PyOVERLAPPEDType) +PYWINTYPES_EXPORT BOOL PyWinObject_AsOVERLAPPED(PyObject *ob, OVERLAPPED **ppOverlapped, BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT BOOL PyWinObject_AsPyOVERLAPPED(PyObject *ob, PyOVERLAPPED **ppOverlapped, BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromOVERLAPPED(const OVERLAPPED *pOverlapped); + +// A global function that can work as a module method for making an OVERLAPPED object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewOVERLAPPED(PyObject *self, PyObject *args); + +#ifndef NO_PYWINTYPES_IID +/* +** IID/GUID support +*/ + +extern PYWINTYPES_EXPORT PyTypeObject PyIIDType; // the Type for PyIID +#define PyIID_Check(ob) ((ob)->ob_type == &PyIIDType) + +// Given an object repring a CLSID (either PyIID or string), fill the CLSID. +PYWINTYPES_EXPORT BOOL PyWinObject_AsIID(PyObject *obCLSID, CLSID *clsid); + +// return a native PyIID object representing an IID +PYWINTYPES_EXPORT PyObject *PyWinObject_FromIID(const IID &riid); + +// return a string/Unicode object representing an IID +PYWINTYPES_EXPORT PyObject *PyWinCoreString_FromIID(const IID &riid); + +// A global function that can work as a module method for making an IID object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewIID(PyObject *self, PyObject *args); +#endif /*NO_PYWINTYPES_IID */ + +/* +** TIME support +** +** We use a subclass of the builtin datetime. +*/ + +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSYSTEMTIME(const SYSTEMTIME &t); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromFILETIME(const FILETIME &t); + +// Converts a TimeStamp, which is in 100 nanosecond units like a FILETIME +// TimeStamp is actually defined as a LARGE_INTEGER, so this function will also +// accept Windows security "TimeStamp" objects directly - however, we use a +// LARGE_INTEGER prototype to avoid pulling in the windows security headers. +PYWINTYPES_EXPORT PyObject *PyWinObject_FromTimeStamp(const LARGE_INTEGER &t); +PYWINTYPES_EXPORT PyObject *PyWinTimeObject_Fromtime_t(time_t t); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromDATE(DATE t); + +PYWINTYPES_EXPORT BOOL PyWinObject_AsDATE(PyObject *ob, DATE *pDate); +PYWINTYPES_EXPORT BOOL PyWinObject_AsFILETIME(PyObject *ob, FILETIME *pDate); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSYSTEMTIME(PyObject *ob, SYSTEMTIME *pDate); + +// A global function that can work as a module method for making a time object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewTime(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewTimeStamp(PyObject *self, PyObject *args); + +PYWINTYPES_EXPORT BOOL PyWinTime_Check(PyObject *ob); + +// functions to return WIN32_FIND_DATA tuples, used in shell, win32api, and win32file +PYWINTYPES_EXPORT PyObject *PyObject_FromWIN32_FIND_DATAW(WIN32_FIND_DATAW *pData); +#define PyObject_FromWIN32_FIND_DATA PyObject_FromWIN32_FIND_DATAW + +// POINT tuple, used in win32api_display.cpp and win32gui.i +PYWINTYPES_EXPORT BOOL PyWinObject_AsPOINT(PyObject *obpoint, LPPOINT ppoint); + +// IO_COUNTERS dict, used in win32process and win32job +PYWINTYPES_EXPORT PyObject *PyWinObject_FromIO_COUNTERS(PIO_COUNTERS pioc); + +// Make an array of DWORD's from a sequence of Python ints +PYWINTYPES_EXPORT BOOL PyWinObject_AsDWORDArray(PyObject *obdwords, DWORD **pdwords, DWORD *item_cnt, + BOOL bNoneOk = TRUE); + +// Conversion for resource id/name and class atom +PYWINTYPES_EXPORT BOOL PyWinObject_AsResourceIdA(PyObject *ob, char **presource_id, BOOL bNoneOK = FALSE); +PYWINTYPES_EXPORT void PyWinObject_FreeResourceIdA(char *resource_id); + +PYWINTYPES_EXPORT BOOL PyWinObject_AsResourceId(PyObject *ob, WCHAR **presource_id, BOOL bNoneOK = FALSE); +PYWINTYPES_EXPORT void PyWinObject_FreeResourceId(WCHAR *resource_id); + +// WPARAM and LPARAM conversion. +// Auto-freed WPARAM / LPARAM which ensure any memory referenced remains valid when a String or +// Buffer object is used. Make sure the destructor is called with the GIL held. +class PyWin_PARAMHolder { + protected: + WPARAM _pa; + // Holds *either* a PyWinBufferView (which will auto-free) *or* a "void *" that we + // will auto-free. + void *_pymem; + void _free() { + if (_pymem) { + PyMem_Free(_pymem); + _pymem = NULL; + } + } + public: + PyWinBufferView bufferView; + + PyWin_PARAMHolder(WPARAM t=0):_pa(t),_pymem(NULL) {} + ~PyWin_PARAMHolder() { + _free(); + } + WCHAR *set_allocated(WCHAR *t) { + assert(!bufferView.ok()); // should be one or the other. + _free(); + _pymem = t; + _pa = (WPARAM)t; + return t; + } + // When init_buffer() fails, an appropriate Python error has been set too + bool init_buffer(PyObject *ob) { + assert(!_pymem); // should be one or the other! + _free(); + if (!bufferView.init(ob)) { + return false; + } + _pa = (WPARAM)bufferView.ptr(); + return true; + } + + WPARAM operator=(WPARAM t) { + return _pa = t; + } + operator WPARAM() { return _pa; } + operator LPARAM() { return (LPARAM)_pa; } +}; + +PYWINTYPES_EXPORT BOOL PyWinObject_AsPARAM(PyObject *ob, PyWin_PARAMHolder *pparam); +inline PyObject *PyWinObject_FromPARAM(WPARAM param) { return PyWinObject_FromULONG_PTR(param); } +inline PyObject *PyWinObject_FromPARAM(LPARAM param) { return PyWinObject_FromULONG_PTR(param); } + +PYWINTYPES_EXPORT BOOL PyWinObject_AsSimplePARAM(PyObject *ob, WPARAM *pparam); +inline BOOL PyWinObject_AsSimplePARAM(PyObject *ob, LPARAM *pparam) { return PyWinObject_AsSimplePARAM(ob, (WPARAM *)pparam); } + +// RECT conversions +// @object PyRECT|Tuple of 4 ints defining a rectangle: (left, top, right, bottom) +PYWINTYPES_EXPORT BOOL PyWinObject_AsRECT(PyObject *obrect, LPRECT prect); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromRECT(LPRECT prect); + +/* +** SECURITY_ATTRIBUTES support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PySECURITY_ATTRIBUTESType; +#define PySECURITY_ATTRIBUTES_Check(ob) ((ob)->ob_type == &PySECURITY_ATTRIBUTESType) +extern PYWINTYPES_EXPORT PyTypeObject PyDEVMODEWType; + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewSECURITY_ATTRIBUTES(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSECURITY_ATTRIBUTES(PyObject *ob, SECURITY_ATTRIBUTES **ppSECURITY_ATTRIBUTES, + BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSECURITY_ATTRIBUTES(const SECURITY_ATTRIBUTES &sa); +PYWINTYPES_EXPORT BOOL PyWinObject_AsDEVMODE(PyObject *ob, PDEVMODEW *ppDEVMODE, BOOL bNoneOK); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromDEVMODE(PDEVMODEW); + +/* +** WAVEFORMATEX support +*/ + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewWAVEFORMATEX(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromWAVEFROMATEX(const WAVEFORMATEX &wfx); +PYWINTYPES_EXPORT BOOL PyWinObject_AsWAVEFORMATEX(PyObject *ob, WAVEFORMATEX **ppWAVEFORMATEX, BOOL bNoneOK = TRUE); +extern PYWINTYPES_EXPORT PyTypeObject PyWAVEFORMATEXType; +#define PyWAVEFORMATEX_Check(ob) ((ob)->ob_type == &PyWAVEFORMATEXType) + +/* +** SECURITY_DESCRIPTOR support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PySECURITY_DESCRIPTORType; +#define PySECURITY_DESCRIPTOR_Check(ob) ((ob)->ob_type == &PySECURITY_DESCRIPTORType) + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewSECURITY_DESCRIPTOR(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSECURITY_DESCRIPTOR(PyObject *ob, PSECURITY_DESCRIPTOR *ppSECURITY_DESCRIPTOR, + BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSECURITY_DESCRIPTOR(PSECURITY_DESCRIPTOR psd); + +PYWINTYPES_EXPORT BOOL _MakeAbsoluteSD(PSECURITY_DESCRIPTOR psd_relative, PSECURITY_DESCRIPTOR *ppsd_absolute); +PYWINTYPES_EXPORT void FreeAbsoluteSD(PSECURITY_DESCRIPTOR psd); + +/* +** SID support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PySIDType; +#define PySID_Check(ob) ((ob)->ob_type == &PySIDType) + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewSID(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSID(PyObject *ob, PSID *ppSID, BOOL bNoneOK = FALSE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSID(PSID pSID); + +/* +** ACL support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PyACLType; +#define PyACL_Check(ob) ((ob)->ob_type == &PyACLType) + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewACL(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsACL(PyObject *ob, PACL *ppACL, BOOL bNoneOK = FALSE); + +/* +** Win32 HANDLE wrapper - any handle closable by "CloseHandle()" +*/ +extern PYWINTYPES_EXPORT PyTypeObject PyHANDLEType; // the Type for PyHANDLE +#define PyHANDLE_Check(ob) ((ob)->ob_type == &PyHANDLEType) + +// Convert an object to a HANDLE - None is always OK, as are ints, etc. +PYWINTYPES_EXPORT BOOL PyWinObject_AsHANDLE(PyObject *ob, HANDLE *pRes); +// For handles that use PyHANDLE. +PYWINTYPES_EXPORT PyObject *PyWinObject_FromHANDLE(HANDLE h); +// For handles that aren't returned as PyHANDLE or a subclass thereof (HDC, HWND, etc). +// Return as python ints or longs +PYWINTYPES_EXPORT PyObject *PyWinLong_FromHANDLE(HANDLE h); + +// A global function that can work as a module method for making a HANDLE object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewHANDLE(PyObject *self, PyObject *args); + +// A global function that does the right thing wrt closing a "handle". +// The object can be either a PyHANDLE or an integer. +// If result is FALSE, a Python error is all setup (cf PyHANDLE::Close(), which doesnt set the Python error) +PYWINTYPES_EXPORT BOOL PyWinObject_CloseHANDLE(PyObject *obHandle); + +PYWINTYPES_EXPORT BOOL PyWinObject_AsHKEY(PyObject *ob, HKEY *pRes); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromHKEY(HKEY h); +PYWINTYPES_EXPORT BOOL PyWinObject_CloseHKEY(PyObject *obHandle); + +// MSG structure keeps coming up... +PYWINTYPES_EXPORT BOOL PyWinObject_AsMSG(PyObject *ob, MSG *pMsg); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromMSG(const MSG *pMsg); + +#include "winsock.h" +/* +** SOCKET support. +*/ +PYWINTYPES_EXPORT +BOOL PySocket_AsSOCKET + //------------------------------------------------------------------------- + // Helper function for dealing with socket arguments. + (PyObject *obSocket, + // [in] Python object being converted into a SOCKET handle. + SOCKET *ps + // [out] Returned socket handle + ); + +/* +** Other Utilities +*/ +// ---------------------------------------------------------------------- +// WARNING - NEVER EVER USE new() ON THIS CLASS +// This class can be used as a local variable, typically in a Python/C +// function, and can be passed whereever a TCHAR/WCHAR is expected. +// Typical Usage: +// PyWin_AutoFreeBstr arg; +// PyArg_ParseTuple("O", &obStr); +// PyWinObject_AsAutoFreeBstr(obStr, &arg); +// CallTheFunction(arg); // Will correctly pass BSTR/OLECHAR +// -- when the function goes out of scope, the string owned by "arg" will +// -- automatically be freed. +// ---------------------------------------------------------------------- +class PYWINTYPES_EXPORT PyWin_AutoFreeBstr { + public: + PyWin_AutoFreeBstr(BSTR bstr = NULL); + ~PyWin_AutoFreeBstr(); + void SetBstr(BSTR bstr); + operator BSTR() { return m_bstr; } + + private: + BSTR m_bstr; +}; + +inline BOOL PyWinObject_AsAutoFreeBstr(PyObject *stringObject, PyWin_AutoFreeBstr *pResult, BOOL bNoneOK = FALSE) +{ + if (bNoneOK && stringObject == Py_None) { + pResult->SetBstr(NULL); + return TRUE; + } + BSTR bs; + if (!PyWinObject_AsBstr(stringObject, &bs, bNoneOK)) + return FALSE; + pResult->SetBstr(bs); + return TRUE; +} + +// ---------------------------------------------------------------------- +// +// THREAD MANAGEMENT +// + +// ### need to rename the PYCOM_ stuff soon... + +// We have 2 discrete locks in use (when no free-threaded is used, anyway). +// The first type of lock is the global Python lock. This is the standard lock +// in use by Python, and must be used as documented by Python. Specifically, no +// 2 threads may _ever_ call _any_ Python code (including INCREF/DECREF) without +// first having this thread lock. +// +// The second type of lock is a "global framework lock". This lock is simply a +// critical section, and used whenever 2 threads of C code need access to global +// data. This is different than the Python lock - this lock is used when no Python +// code can ever be called by the threads, but the C code still needs thread-safety. + +// We also supply helper classes which make the usage of these locks a one-liner. + +// The "framework" lock, implemented as a critical section. +PYWINTYPES_EXPORT void PyWin_AcquireGlobalLock(void); +PYWINTYPES_EXPORT void PyWin_ReleaseGlobalLock(void); + +// Helper class for the DLL global lock. +// +// This class magically waits for the Win32/COM framework global lock, and releases it +// when finished. +// NEVER new one of these objects - only use on the stack! +class CEnterLeaveFramework { + public: + CEnterLeaveFramework() { PyWin_AcquireGlobalLock(); } + ~CEnterLeaveFramework() { PyWin_ReleaseGlobalLock(); } +}; + +// Python thread-lock stuff. Free-threading patches use different semantics, but +// these are abstracted away here... +#ifndef FORCE_NO_FREE_THREAD +#ifdef WITH_FREE_THREAD +#define PYCOM_USE_FREE_THREAD +#endif +#endif +#ifdef PYCOM_USE_FREE_THREAD +#include +#else +#include +#endif + +// Helper class for Enter/Leave Python +// +// This class magically waits for the Python global lock, and releases it +// when finished. + +// Nested invocations will deadlock, so be careful. + +// NEVER new one of these objects - only use on the stack! +#ifndef PYCOM_USE_FREE_THREAD +extern PYWINTYPES_EXPORT PyInterpreterState *PyWin_InterpreterState; +extern PYWINTYPES_EXPORT BOOL PyWinThreadState_Ensure(); +extern PYWINTYPES_EXPORT void PyWinThreadState_Free(); +extern PYWINTYPES_EXPORT void PyWinThreadState_Clear(); +extern PYWINTYPES_EXPORT void PyWinInterpreterLock_Acquire(); +extern PYWINTYPES_EXPORT void PyWinInterpreterLock_Release(); + +extern PYWINTYPES_EXPORT int PyWinGlobals_Ensure(); +extern PYWINTYPES_EXPORT void PyWinGlobals_Free(); +#else +#define PyWinThreadState_Ensure PyThreadState_Ensure +#define PyWinThreadState_Free PyThreadState_Free +#define PyWinThreadState_Clear PyThreadState_ClearExc + +#endif + +extern PYWINTYPES_EXPORT void PyWin_MakePendingCalls(); + +class CEnterLeavePython { + public: + CEnterLeavePython() : released(TRUE) { acquire(); } + void acquire(void) + { + if (!released) + return; + state = PyGILState_Ensure(); + released = FALSE; + } + ~CEnterLeavePython() { release(); } + void release(void) + { + if (!released) { + PyGILState_Release(state); + released = TRUE; + } + } + + private: + PyGILState_STATE state; + BOOL released; +}; + +// A helper for simple exception handling. +// try/__try +#if defined(__MINGW32__) || defined(MAINWIN) +#define PYWINTYPES_TRY try +#else +#define PYWINTYPES_TRY __try +#endif /* MAINWIN */ + +// catch/__except +#if defined(__MINGW32__) || defined(MAINWIN) +#define PYWINTYPES_EXCEPT catch (...) +#else +#define PYWINTYPES_EXCEPT __except (EXCEPTION_EXECUTE_HANDLER) +#endif +// End of exception helper macros. + +// Class to hold a temporary reference that decrements itself +class TmpPyObject { + public: + PyObject *tmp; + TmpPyObject() { tmp = NULL; } + TmpPyObject(PyObject *ob) { tmp = ob; } + PyObject *operator=(PyObject *ob) + { + Py_XDECREF(tmp); + tmp = ob; + return tmp; + } + + boolean operator==(PyObject *ob) { return tmp == ob; } + operator PyObject *() { return tmp; } + ~TmpPyObject() { Py_XDECREF(tmp); } +}; + +#endif // __PYWINTYPES_H__ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/afxres.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/afxres.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acff63ed441bbdf61bf59a1857f2dc7424137f47 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/afxres.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/commctrl.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/commctrl.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3afb4c489e9be296bcdbb4356e4c4fa7ec9a43eb Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/commctrl.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/dbi.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/dbi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf573a5c99af7a436d3ec405bb70fe9689de7316 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/dbi.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/mmsystem.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/mmsystem.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d4a3bfa6cd0ee1816cc4b22240c849a691d66a48 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/mmsystem.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/netbios.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/netbios.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b217cf3638733caf4eca94a81dbde0366aa2659 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/netbios.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/ntsecuritycon.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/ntsecuritycon.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f76353614a37ef397ebfc3d26b5173c6209c2c7 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/ntsecuritycon.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/pywin32_bootstrap.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/pywin32_bootstrap.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5ebc732b924023c740fab1175ddf7b6ca77e6e4 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/pywin32_bootstrap.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/pywin32_testutil.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/pywin32_testutil.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07a5e65837e05e79151a06d2fed3b83b568e4d2e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/pywin32_testutil.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/pywintypes.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/pywintypes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b86bd43409e9b3e0625be95d9f8fe467884a597 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/pywintypes.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/rasutil.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/rasutil.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a30f05494e8dd5d5c5423b194714912df9b342e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/rasutil.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/regcheck.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/regcheck.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4bca8ea7f12c0919b62e5735acd9631643996ce Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/regcheck.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/regutil.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/regutil.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c69af4ac36f2948e7c372cd0a08cd828bc018a16 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/regutil.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/sspi.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/sspi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6927a3ed6bd772e724247ad1329b1bb1619fbb7 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/sspi.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/sspicon.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/sspicon.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4006bebfc09ef96fb2096eebaf4273df95e83698 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/sspicon.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win2kras.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win2kras.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..735de346a24d780111233c0b0602aee107a88d5e Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win2kras.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32con.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32con.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..382a07d19b58a7a1f4cc51e3852ffea59f7f8abe Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32con.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32cryptcon.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32cryptcon.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e6c784ec06aa9fced3acae0b14668f766d0a81a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32cryptcon.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32evtlogutil.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32evtlogutil.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..954d2550c7551ba69c07bff333a8ba7f8593fd52 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32evtlogutil.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32gui_struct.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32gui_struct.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ee77b8db4629b6df602223a63659e72d758827f Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32gui_struct.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32inetcon.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32inetcon.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7433035d6ef7b409ceb795796c95974a7bf14c69 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32inetcon.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32netcon.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32netcon.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57e6b19d1c9591d58351ba0cfbf1ef3e88017e07 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32netcon.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32pdhquery.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32pdhquery.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4656b7e5f215899c5a595c2d5d464c93117b91d9 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32pdhquery.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32pdhutil.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32pdhutil.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75c5d1dd1d274abd368d0c5704d97e6d89e793f0 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32pdhutil.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32rcparser.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32rcparser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9258b3ebdbea2b2a4aa30b450842278c5c8ff3a5 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32rcparser.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32serviceutil.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32serviceutil.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4abe10433f40c3a28bca6883134d36df1409edf9 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32serviceutil.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32timezone.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32timezone.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3763987fdc5386c0b72a3308e132c8474ce6a8e4 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32timezone.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32traceutil.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32traceutil.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3858e7d9e1228422575ecf8d0b182b1fb1de600 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32traceutil.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/win32verstamp.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32verstamp.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..36d9c4c6e2092d28b46cb15087b93e12d287fdd9 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/win32verstamp.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/winerror.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/winerror.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4eb80816b9716d4c00462bdb1b40388fed3886ae Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/winerror.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/winioctlcon.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/winioctlcon.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d1ebbd6954162f7b221e6d2c1ac1793bdae4f5a Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/winioctlcon.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/winnt.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/winnt.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..919bd382e1fc443f0cfd34cc585b4a482c65c571 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/winnt.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/winperf.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/winperf.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95e4060a882178af64e029d149964bd3faf3d342 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/winperf.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/__pycache__/winxptheme.cpython-39.pyc b/MLPY/Lib/site-packages/win32/lib/__pycache__/winxptheme.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea585968303c4b147e211fd286c7b766f2b9f429 Binary files /dev/null and b/MLPY/Lib/site-packages/win32/lib/__pycache__/winxptheme.cpython-39.pyc differ diff --git a/MLPY/Lib/site-packages/win32/lib/afxres.py b/MLPY/Lib/site-packages/win32/lib/afxres.py new file mode 100644 index 0000000000000000000000000000000000000000..249211ff359e746a17995d28a2ead6c89bac4f64 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/afxres.py @@ -0,0 +1,501 @@ +# Generated by h2py from stdin +TCS_MULTILINE = 0x0200 +CBRS_ALIGN_LEFT = 0x1000 +CBRS_ALIGN_TOP = 0x2000 +CBRS_ALIGN_RIGHT = 0x4000 +CBRS_ALIGN_BOTTOM = 0x8000 +CBRS_ALIGN_ANY = 0xF000 +CBRS_BORDER_LEFT = 0x0100 +CBRS_BORDER_TOP = 0x0200 +CBRS_BORDER_RIGHT = 0x0400 +CBRS_BORDER_BOTTOM = 0x0800 +CBRS_BORDER_ANY = 0x0F00 +CBRS_TOOLTIPS = 0x0010 +CBRS_FLYBY = 0x0020 +CBRS_FLOAT_MULTI = 0x0040 +CBRS_BORDER_3D = 0x0080 +CBRS_HIDE_INPLACE = 0x0008 +CBRS_SIZE_DYNAMIC = 0x0004 +CBRS_SIZE_FIXED = 0x0002 +CBRS_FLOATING = 0x0001 +CBRS_GRIPPER = 0x00400000 +CBRS_ORIENT_HORZ = CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM +CBRS_ORIENT_VERT = CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT +CBRS_ORIENT_ANY = CBRS_ORIENT_HORZ | CBRS_ORIENT_VERT +CBRS_ALL = 0xFFFF +CBRS_NOALIGN = 0x00000000 +CBRS_LEFT = CBRS_ALIGN_LEFT | CBRS_BORDER_RIGHT +CBRS_TOP = CBRS_ALIGN_TOP | CBRS_BORDER_BOTTOM +CBRS_RIGHT = CBRS_ALIGN_RIGHT | CBRS_BORDER_LEFT +CBRS_BOTTOM = CBRS_ALIGN_BOTTOM | CBRS_BORDER_TOP +SBPS_NORMAL = 0x0000 +SBPS_NOBORDERS = 0x0100 +SBPS_POPOUT = 0x0200 +SBPS_OWNERDRAW = 0x1000 +SBPS_DISABLED = 0x04000000 +SBPS_STRETCH = 0x08000000 +ID_INDICATOR_EXT = 0xE700 +ID_INDICATOR_CAPS = 0xE701 +ID_INDICATOR_NUM = 0xE702 +ID_INDICATOR_SCRL = 0xE703 +ID_INDICATOR_OVR = 0xE704 +ID_INDICATOR_REC = 0xE705 +ID_INDICATOR_KANA = 0xE706 +ID_SEPARATOR = 0 +AFX_IDW_CONTROLBAR_FIRST = 0xE800 +AFX_IDW_CONTROLBAR_LAST = 0xE8FF +AFX_IDW_TOOLBAR = 0xE800 +AFX_IDW_STATUS_BAR = 0xE801 +AFX_IDW_PREVIEW_BAR = 0xE802 +AFX_IDW_RESIZE_BAR = 0xE803 +AFX_IDW_DOCKBAR_TOP = 0xE81B +AFX_IDW_DOCKBAR_LEFT = 0xE81C +AFX_IDW_DOCKBAR_RIGHT = 0xE81D +AFX_IDW_DOCKBAR_BOTTOM = 0xE81E +AFX_IDW_DOCKBAR_FLOAT = 0xE81F + + +def AFX_CONTROLBAR_MASK(nIDC): + return 1 << (nIDC - AFX_IDW_CONTROLBAR_FIRST) + + +AFX_IDW_PANE_FIRST = 0xE900 +AFX_IDW_PANE_LAST = 0xE9FF +AFX_IDW_HSCROLL_FIRST = 0xEA00 +AFX_IDW_VSCROLL_FIRST = 0xEA10 +AFX_IDW_SIZE_BOX = 0xEA20 +AFX_IDW_PANE_SAVE = 0xEA21 +AFX_IDS_APP_TITLE = 0xE000 +AFX_IDS_IDLEMESSAGE = 0xE001 +AFX_IDS_HELPMODEMESSAGE = 0xE002 +AFX_IDS_APP_TITLE_EMBEDDING = 0xE003 +AFX_IDS_COMPANY_NAME = 0xE004 +AFX_IDS_OBJ_TITLE_INPLACE = 0xE005 +ID_FILE_NEW = 0xE100 +ID_FILE_OPEN = 0xE101 +ID_FILE_CLOSE = 0xE102 +ID_FILE_SAVE = 0xE103 +ID_FILE_SAVE_AS = 0xE104 +ID_FILE_PAGE_SETUP = 0xE105 +ID_FILE_PRINT_SETUP = 0xE106 +ID_FILE_PRINT = 0xE107 +ID_FILE_PRINT_DIRECT = 0xE108 +ID_FILE_PRINT_PREVIEW = 0xE109 +ID_FILE_UPDATE = 0xE10A +ID_FILE_SAVE_COPY_AS = 0xE10B +ID_FILE_SEND_MAIL = 0xE10C +ID_FILE_MRU_FIRST = 0xE110 +ID_FILE_MRU_FILE1 = 0xE110 +ID_FILE_MRU_FILE2 = 0xE111 +ID_FILE_MRU_FILE3 = 0xE112 +ID_FILE_MRU_FILE4 = 0xE113 +ID_FILE_MRU_FILE5 = 0xE114 +ID_FILE_MRU_FILE6 = 0xE115 +ID_FILE_MRU_FILE7 = 0xE116 +ID_FILE_MRU_FILE8 = 0xE117 +ID_FILE_MRU_FILE9 = 0xE118 +ID_FILE_MRU_FILE10 = 0xE119 +ID_FILE_MRU_FILE11 = 0xE11A +ID_FILE_MRU_FILE12 = 0xE11B +ID_FILE_MRU_FILE13 = 0xE11C +ID_FILE_MRU_FILE14 = 0xE11D +ID_FILE_MRU_FILE15 = 0xE11E +ID_FILE_MRU_FILE16 = 0xE11F +ID_FILE_MRU_LAST = 0xE11F +ID_EDIT_CLEAR = 0xE120 +ID_EDIT_CLEAR_ALL = 0xE121 +ID_EDIT_COPY = 0xE122 +ID_EDIT_CUT = 0xE123 +ID_EDIT_FIND = 0xE124 +ID_EDIT_PASTE = 0xE125 +ID_EDIT_PASTE_LINK = 0xE126 +ID_EDIT_PASTE_SPECIAL = 0xE127 +ID_EDIT_REPEAT = 0xE128 +ID_EDIT_REPLACE = 0xE129 +ID_EDIT_SELECT_ALL = 0xE12A +ID_EDIT_UNDO = 0xE12B +ID_EDIT_REDO = 0xE12C +ID_WINDOW_NEW = 0xE130 +ID_WINDOW_ARRANGE = 0xE131 +ID_WINDOW_CASCADE = 0xE132 +ID_WINDOW_TILE_HORZ = 0xE133 +ID_WINDOW_TILE_VERT = 0xE134 +ID_WINDOW_SPLIT = 0xE135 +AFX_IDM_WINDOW_FIRST = 0xE130 +AFX_IDM_WINDOW_LAST = 0xE13F +AFX_IDM_FIRST_MDICHILD = 0xFF00 +ID_APP_ABOUT = 0xE140 +ID_APP_EXIT = 0xE141 +ID_HELP_INDEX = 0xE142 +ID_HELP_FINDER = 0xE143 +ID_HELP_USING = 0xE144 +ID_CONTEXT_HELP = 0xE145 +ID_HELP = 0xE146 +ID_DEFAULT_HELP = 0xE147 +ID_NEXT_PANE = 0xE150 +ID_PREV_PANE = 0xE151 +ID_FORMAT_FONT = 0xE160 +ID_OLE_INSERT_NEW = 0xE200 +ID_OLE_EDIT_LINKS = 0xE201 +ID_OLE_EDIT_CONVERT = 0xE202 +ID_OLE_EDIT_CHANGE_ICON = 0xE203 +ID_OLE_EDIT_PROPERTIES = 0xE204 +ID_OLE_VERB_FIRST = 0xE210 +ID_OLE_VERB_LAST = 0xE21F +AFX_ID_PREVIEW_CLOSE = 0xE300 +AFX_ID_PREVIEW_NUMPAGE = 0xE301 +AFX_ID_PREVIEW_NEXT = 0xE302 +AFX_ID_PREVIEW_PREV = 0xE303 +AFX_ID_PREVIEW_PRINT = 0xE304 +AFX_ID_PREVIEW_ZOOMIN = 0xE305 +AFX_ID_PREVIEW_ZOOMOUT = 0xE306 +ID_VIEW_TOOLBAR = 0xE800 +ID_VIEW_STATUS_BAR = 0xE801 +ID_RECORD_FIRST = 0xE900 +ID_RECORD_LAST = 0xE901 +ID_RECORD_NEXT = 0xE902 +ID_RECORD_PREV = 0xE903 +IDC_STATIC = -1 +AFX_IDS_SCFIRST = 0xEF00 +AFX_IDS_SCSIZE = 0xEF00 +AFX_IDS_SCMOVE = 0xEF01 +AFX_IDS_SCMINIMIZE = 0xEF02 +AFX_IDS_SCMAXIMIZE = 0xEF03 +AFX_IDS_SCNEXTWINDOW = 0xEF04 +AFX_IDS_SCPREVWINDOW = 0xEF05 +AFX_IDS_SCCLOSE = 0xEF06 +AFX_IDS_SCRESTORE = 0xEF12 +AFX_IDS_SCTASKLIST = 0xEF13 +AFX_IDS_MDICHILD = 0xEF1F +AFX_IDS_DESKACCESSORY = 0xEFDA +AFX_IDS_OPENFILE = 0xF000 +AFX_IDS_SAVEFILE = 0xF001 +AFX_IDS_ALLFILTER = 0xF002 +AFX_IDS_UNTITLED = 0xF003 +AFX_IDS_SAVEFILECOPY = 0xF004 +AFX_IDS_PREVIEW_CLOSE = 0xF005 +AFX_IDS_UNNAMED_FILE = 0xF006 +AFX_IDS_ABOUT = 0xF010 +AFX_IDS_HIDE = 0xF011 +AFX_IDP_NO_ERROR_AVAILABLE = 0xF020 +AFX_IDS_NOT_SUPPORTED_EXCEPTION = 0xF021 +AFX_IDS_RESOURCE_EXCEPTION = 0xF022 +AFX_IDS_MEMORY_EXCEPTION = 0xF023 +AFX_IDS_USER_EXCEPTION = 0xF024 +AFX_IDS_PRINTONPORT = 0xF040 +AFX_IDS_ONEPAGE = 0xF041 +AFX_IDS_TWOPAGE = 0xF042 +AFX_IDS_PRINTPAGENUM = 0xF043 +AFX_IDS_PREVIEWPAGEDESC = 0xF044 +AFX_IDS_PRINTDEFAULTEXT = 0xF045 +AFX_IDS_PRINTDEFAULT = 0xF046 +AFX_IDS_PRINTFILTER = 0xF047 +AFX_IDS_PRINTCAPTION = 0xF048 +AFX_IDS_PRINTTOFILE = 0xF049 +AFX_IDS_OBJECT_MENUITEM = 0xF080 +AFX_IDS_EDIT_VERB = 0xF081 +AFX_IDS_ACTIVATE_VERB = 0xF082 +AFX_IDS_CHANGE_LINK = 0xF083 +AFX_IDS_AUTO = 0xF084 +AFX_IDS_MANUAL = 0xF085 +AFX_IDS_FROZEN = 0xF086 +AFX_IDS_ALL_FILES = 0xF087 +AFX_IDS_SAVE_MENU = 0xF088 +AFX_IDS_UPDATE_MENU = 0xF089 +AFX_IDS_SAVE_AS_MENU = 0xF08A +AFX_IDS_SAVE_COPY_AS_MENU = 0xF08B +AFX_IDS_EXIT_MENU = 0xF08C +AFX_IDS_UPDATING_ITEMS = 0xF08D +AFX_IDS_METAFILE_FORMAT = 0xF08E +AFX_IDS_DIB_FORMAT = 0xF08F +AFX_IDS_BITMAP_FORMAT = 0xF090 +AFX_IDS_LINKSOURCE_FORMAT = 0xF091 +AFX_IDS_EMBED_FORMAT = 0xF092 +AFX_IDS_PASTELINKEDTYPE = 0xF094 +AFX_IDS_UNKNOWNTYPE = 0xF095 +AFX_IDS_RTF_FORMAT = 0xF096 +AFX_IDS_TEXT_FORMAT = 0xF097 +AFX_IDS_INVALID_CURRENCY = 0xF098 +AFX_IDS_INVALID_DATETIME = 0xF099 +AFX_IDS_INVALID_DATETIMESPAN = 0xF09A +AFX_IDP_INVALID_FILENAME = 0xF100 +AFX_IDP_FAILED_TO_OPEN_DOC = 0xF101 +AFX_IDP_FAILED_TO_SAVE_DOC = 0xF102 +AFX_IDP_ASK_TO_SAVE = 0xF103 +AFX_IDP_FAILED_TO_CREATE_DOC = 0xF104 +AFX_IDP_FILE_TOO_LARGE = 0xF105 +AFX_IDP_FAILED_TO_START_PRINT = 0xF106 +AFX_IDP_FAILED_TO_LAUNCH_HELP = 0xF107 +AFX_IDP_INTERNAL_FAILURE = 0xF108 +AFX_IDP_COMMAND_FAILURE = 0xF109 +AFX_IDP_FAILED_MEMORY_ALLOC = 0xF10A +AFX_IDP_PARSE_INT = 0xF110 +AFX_IDP_PARSE_REAL = 0xF111 +AFX_IDP_PARSE_INT_RANGE = 0xF112 +AFX_IDP_PARSE_REAL_RANGE = 0xF113 +AFX_IDP_PARSE_STRING_SIZE = 0xF114 +AFX_IDP_PARSE_RADIO_BUTTON = 0xF115 +AFX_IDP_PARSE_BYTE = 0xF116 +AFX_IDP_PARSE_UINT = 0xF117 +AFX_IDP_PARSE_DATETIME = 0xF118 +AFX_IDP_PARSE_CURRENCY = 0xF119 +AFX_IDP_FAILED_INVALID_FORMAT = 0xF120 +AFX_IDP_FAILED_INVALID_PATH = 0xF121 +AFX_IDP_FAILED_DISK_FULL = 0xF122 +AFX_IDP_FAILED_ACCESS_READ = 0xF123 +AFX_IDP_FAILED_ACCESS_WRITE = 0xF124 +AFX_IDP_FAILED_IO_ERROR_READ = 0xF125 +AFX_IDP_FAILED_IO_ERROR_WRITE = 0xF126 +AFX_IDP_STATIC_OBJECT = 0xF180 +AFX_IDP_FAILED_TO_CONNECT = 0xF181 +AFX_IDP_SERVER_BUSY = 0xF182 +AFX_IDP_BAD_VERB = 0xF183 +AFX_IDP_FAILED_TO_NOTIFY = 0xF185 +AFX_IDP_FAILED_TO_LAUNCH = 0xF186 +AFX_IDP_ASK_TO_UPDATE = 0xF187 +AFX_IDP_FAILED_TO_UPDATE = 0xF188 +AFX_IDP_FAILED_TO_REGISTER = 0xF189 +AFX_IDP_FAILED_TO_AUTO_REGISTER = 0xF18A +AFX_IDP_FAILED_TO_CONVERT = 0xF18B +AFX_IDP_GET_NOT_SUPPORTED = 0xF18C +AFX_IDP_SET_NOT_SUPPORTED = 0xF18D +AFX_IDP_ASK_TO_DISCARD = 0xF18E +AFX_IDP_FAILED_TO_CREATE = 0xF18F +AFX_IDP_FAILED_MAPI_LOAD = 0xF190 +AFX_IDP_INVALID_MAPI_DLL = 0xF191 +AFX_IDP_FAILED_MAPI_SEND = 0xF192 +AFX_IDP_FILE_NONE = 0xF1A0 +AFX_IDP_FILE_GENERIC = 0xF1A1 +AFX_IDP_FILE_NOT_FOUND = 0xF1A2 +AFX_IDP_FILE_BAD_PATH = 0xF1A3 +AFX_IDP_FILE_TOO_MANY_OPEN = 0xF1A4 +AFX_IDP_FILE_ACCESS_DENIED = 0xF1A5 +AFX_IDP_FILE_INVALID_FILE = 0xF1A6 +AFX_IDP_FILE_REMOVE_CURRENT = 0xF1A7 +AFX_IDP_FILE_DIR_FULL = 0xF1A8 +AFX_IDP_FILE_BAD_SEEK = 0xF1A9 +AFX_IDP_FILE_HARD_IO = 0xF1AA +AFX_IDP_FILE_SHARING = 0xF1AB +AFX_IDP_FILE_LOCKING = 0xF1AC +AFX_IDP_FILE_DISKFULL = 0xF1AD +AFX_IDP_FILE_EOF = 0xF1AE +AFX_IDP_ARCH_NONE = 0xF1B0 +AFX_IDP_ARCH_GENERIC = 0xF1B1 +AFX_IDP_ARCH_READONLY = 0xF1B2 +AFX_IDP_ARCH_ENDOFFILE = 0xF1B3 +AFX_IDP_ARCH_WRITEONLY = 0xF1B4 +AFX_IDP_ARCH_BADINDEX = 0xF1B5 +AFX_IDP_ARCH_BADCLASS = 0xF1B6 +AFX_IDP_ARCH_BADSCHEMA = 0xF1B7 +AFX_IDS_OCC_SCALEUNITS_PIXELS = 0xF1C0 +AFX_IDS_STATUS_FONT = 0xF230 +AFX_IDS_TOOLTIP_FONT = 0xF231 +AFX_IDS_UNICODE_FONT = 0xF232 +AFX_IDS_MINI_FONT = 0xF233 +AFX_IDP_SQL_FIRST = 0xF280 +AFX_IDP_SQL_CONNECT_FAIL = 0xF281 +AFX_IDP_SQL_RECORDSET_FORWARD_ONLY = 0xF282 +AFX_IDP_SQL_EMPTY_COLUMN_LIST = 0xF283 +AFX_IDP_SQL_FIELD_SCHEMA_MISMATCH = 0xF284 +AFX_IDP_SQL_ILLEGAL_MODE = 0xF285 +AFX_IDP_SQL_MULTIPLE_ROWS_AFFECTED = 0xF286 +AFX_IDP_SQL_NO_CURRENT_RECORD = 0xF287 +AFX_IDP_SQL_NO_ROWS_AFFECTED = 0xF288 +AFX_IDP_SQL_RECORDSET_READONLY = 0xF289 +AFX_IDP_SQL_SQL_NO_TOTAL = 0xF28A +AFX_IDP_SQL_ODBC_LOAD_FAILED = 0xF28B +AFX_IDP_SQL_DYNASET_NOT_SUPPORTED = 0xF28C +AFX_IDP_SQL_SNAPSHOT_NOT_SUPPORTED = 0xF28D +AFX_IDP_SQL_API_CONFORMANCE = 0xF28E +AFX_IDP_SQL_SQL_CONFORMANCE = 0xF28F +AFX_IDP_SQL_NO_DATA_FOUND = 0xF290 +AFX_IDP_SQL_ROW_UPDATE_NOT_SUPPORTED = 0xF291 +AFX_IDP_SQL_ODBC_V2_REQUIRED = 0xF292 +AFX_IDP_SQL_NO_POSITIONED_UPDATES = 0xF293 +AFX_IDP_SQL_LOCK_MODE_NOT_SUPPORTED = 0xF294 +AFX_IDP_SQL_DATA_TRUNCATED = 0xF295 +AFX_IDP_SQL_ROW_FETCH = 0xF296 +AFX_IDP_SQL_INCORRECT_ODBC = 0xF297 +AFX_IDP_SQL_UPDATE_DELETE_FAILED = 0xF298 +AFX_IDP_SQL_DYNAMIC_CURSOR_NOT_SUPPORTED = 0xF299 +AFX_IDP_DAO_FIRST = 0xF2A0 +AFX_IDP_DAO_ENGINE_INITIALIZATION = 0xF2A0 +AFX_IDP_DAO_DFX_BIND = 0xF2A1 +AFX_IDP_DAO_OBJECT_NOT_OPEN = 0xF2A2 +AFX_IDP_DAO_ROWTOOSHORT = 0xF2A3 +AFX_IDP_DAO_BADBINDINFO = 0xF2A4 +AFX_IDP_DAO_COLUMNUNAVAILABLE = 0xF2A5 +AFX_IDC_LISTBOX = 100 +AFX_IDC_CHANGE = 101 +AFX_IDC_PRINT_DOCNAME = 201 +AFX_IDC_PRINT_PRINTERNAME = 202 +AFX_IDC_PRINT_PORTNAME = 203 +AFX_IDC_PRINT_PAGENUM = 204 +ID_APPLY_NOW = 0x3021 +ID_WIZBACK = 0x3023 +ID_WIZNEXT = 0x3024 +ID_WIZFINISH = 0x3025 +AFX_IDC_TAB_CONTROL = 0x3020 +AFX_IDD_FILEOPEN = 28676 +AFX_IDD_FILESAVE = 28677 +AFX_IDD_FONT = 28678 +AFX_IDD_COLOR = 28679 +AFX_IDD_PRINT = 28680 +AFX_IDD_PRINTSETUP = 28681 +AFX_IDD_FIND = 28682 +AFX_IDD_REPLACE = 28683 +AFX_IDD_NEWTYPEDLG = 30721 +AFX_IDD_PRINTDLG = 30722 +AFX_IDD_PREVIEW_TOOLBAR = 30723 +AFX_IDD_PREVIEW_SHORTTOOLBAR = 30731 +AFX_IDD_INSERTOBJECT = 30724 +AFX_IDD_CHANGEICON = 30725 +AFX_IDD_CONVERT = 30726 +AFX_IDD_PASTESPECIAL = 30727 +AFX_IDD_EDITLINKS = 30728 +AFX_IDD_FILEBROWSE = 30729 +AFX_IDD_BUSY = 30730 +AFX_IDD_OBJECTPROPERTIES = 30732 +AFX_IDD_CHANGESOURCE = 30733 +AFX_IDC_CONTEXTHELP = 30977 +AFX_IDC_MAGNIFY = 30978 +AFX_IDC_SMALLARROWS = 30979 +AFX_IDC_HSPLITBAR = 30980 +AFX_IDC_VSPLITBAR = 30981 +AFX_IDC_NODROPCRSR = 30982 +AFX_IDC_TRACKNWSE = 30983 +AFX_IDC_TRACKNESW = 30984 +AFX_IDC_TRACKNS = 30985 +AFX_IDC_TRACKWE = 30986 +AFX_IDC_TRACK4WAY = 30987 +AFX_IDC_MOVE4WAY = 30988 +AFX_IDB_MINIFRAME_MENU = 30994 +AFX_IDB_CHECKLISTBOX_NT = 30995 +AFX_IDB_CHECKLISTBOX_95 = 30996 +AFX_IDR_PREVIEW_ACCEL = 30997 +AFX_IDI_STD_MDIFRAME = 31233 +AFX_IDI_STD_FRAME = 31234 +AFX_IDC_FONTPROP = 1000 +AFX_IDC_FONTNAMES = 1001 +AFX_IDC_FONTSTYLES = 1002 +AFX_IDC_FONTSIZES = 1003 +AFX_IDC_STRIKEOUT = 1004 +AFX_IDC_UNDERLINE = 1005 +AFX_IDC_SAMPLEBOX = 1006 +AFX_IDC_COLOR_BLACK = 1100 +AFX_IDC_COLOR_WHITE = 1101 +AFX_IDC_COLOR_RED = 1102 +AFX_IDC_COLOR_GREEN = 1103 +AFX_IDC_COLOR_BLUE = 1104 +AFX_IDC_COLOR_YELLOW = 1105 +AFX_IDC_COLOR_MAGENTA = 1106 +AFX_IDC_COLOR_CYAN = 1107 +AFX_IDC_COLOR_GRAY = 1108 +AFX_IDC_COLOR_LIGHTGRAY = 1109 +AFX_IDC_COLOR_DARKRED = 1110 +AFX_IDC_COLOR_DARKGREEN = 1111 +AFX_IDC_COLOR_DARKBLUE = 1112 +AFX_IDC_COLOR_LIGHTBROWN = 1113 +AFX_IDC_COLOR_DARKMAGENTA = 1114 +AFX_IDC_COLOR_DARKCYAN = 1115 +AFX_IDC_COLORPROP = 1116 +AFX_IDC_SYSTEMCOLORS = 1117 +AFX_IDC_PROPNAME = 1201 +AFX_IDC_PICTURE = 1202 +AFX_IDC_BROWSE = 1203 +AFX_IDC_CLEAR = 1204 +AFX_IDD_PROPPAGE_COLOR = 32257 +AFX_IDD_PROPPAGE_FONT = 32258 +AFX_IDD_PROPPAGE_PICTURE = 32259 +AFX_IDB_TRUETYPE = 32384 +AFX_IDS_PROPPAGE_UNKNOWN = 0xFE01 +AFX_IDS_COLOR_DESKTOP = 0xFE04 +AFX_IDS_COLOR_APPWORKSPACE = 0xFE05 +AFX_IDS_COLOR_WNDBACKGND = 0xFE06 +AFX_IDS_COLOR_WNDTEXT = 0xFE07 +AFX_IDS_COLOR_MENUBAR = 0xFE08 +AFX_IDS_COLOR_MENUTEXT = 0xFE09 +AFX_IDS_COLOR_ACTIVEBAR = 0xFE0A +AFX_IDS_COLOR_INACTIVEBAR = 0xFE0B +AFX_IDS_COLOR_ACTIVETEXT = 0xFE0C +AFX_IDS_COLOR_INACTIVETEXT = 0xFE0D +AFX_IDS_COLOR_ACTIVEBORDER = 0xFE0E +AFX_IDS_COLOR_INACTIVEBORDER = 0xFE0F +AFX_IDS_COLOR_WNDFRAME = 0xFE10 +AFX_IDS_COLOR_SCROLLBARS = 0xFE11 +AFX_IDS_COLOR_BTNFACE = 0xFE12 +AFX_IDS_COLOR_BTNSHADOW = 0xFE13 +AFX_IDS_COLOR_BTNTEXT = 0xFE14 +AFX_IDS_COLOR_BTNHIGHLIGHT = 0xFE15 +AFX_IDS_COLOR_DISABLEDTEXT = 0xFE16 +AFX_IDS_COLOR_HIGHLIGHT = 0xFE17 +AFX_IDS_COLOR_HIGHLIGHTTEXT = 0xFE18 +AFX_IDS_REGULAR = 0xFE19 +AFX_IDS_BOLD = 0xFE1A +AFX_IDS_ITALIC = 0xFE1B +AFX_IDS_BOLDITALIC = 0xFE1C +AFX_IDS_SAMPLETEXT = 0xFE1D +AFX_IDS_DISPLAYSTRING_FONT = 0xFE1E +AFX_IDS_DISPLAYSTRING_COLOR = 0xFE1F +AFX_IDS_DISPLAYSTRING_PICTURE = 0xFE20 +AFX_IDS_PICTUREFILTER = 0xFE21 +AFX_IDS_PICTYPE_UNKNOWN = 0xFE22 +AFX_IDS_PICTYPE_NONE = 0xFE23 +AFX_IDS_PICTYPE_BITMAP = 0xFE24 +AFX_IDS_PICTYPE_METAFILE = 0xFE25 +AFX_IDS_PICTYPE_ICON = 0xFE26 +AFX_IDS_COLOR_PPG = 0xFE28 +AFX_IDS_COLOR_PPG_CAPTION = 0xFE29 +AFX_IDS_FONT_PPG = 0xFE2A +AFX_IDS_FONT_PPG_CAPTION = 0xFE2B +AFX_IDS_PICTURE_PPG = 0xFE2C +AFX_IDS_PICTURE_PPG_CAPTION = 0xFE2D +AFX_IDS_PICTUREBROWSETITLE = 0xFE30 +AFX_IDS_BORDERSTYLE_0 = 0xFE31 +AFX_IDS_BORDERSTYLE_1 = 0xFE32 +AFX_IDS_VERB_EDIT = 0xFE40 +AFX_IDS_VERB_PROPERTIES = 0xFE41 +AFX_IDP_PICTURECANTOPEN = 0xFE83 +AFX_IDP_PICTURECANTLOAD = 0xFE84 +AFX_IDP_PICTURETOOLARGE = 0xFE85 +AFX_IDP_PICTUREREADFAILED = 0xFE86 +AFX_IDP_E_ILLEGALFUNCTIONCALL = 0xFEA0 +AFX_IDP_E_OVERFLOW = 0xFEA1 +AFX_IDP_E_OUTOFMEMORY = 0xFEA2 +AFX_IDP_E_DIVISIONBYZERO = 0xFEA3 +AFX_IDP_E_OUTOFSTRINGSPACE = 0xFEA4 +AFX_IDP_E_OUTOFSTACKSPACE = 0xFEA5 +AFX_IDP_E_BADFILENAMEORNUMBER = 0xFEA6 +AFX_IDP_E_FILENOTFOUND = 0xFEA7 +AFX_IDP_E_BADFILEMODE = 0xFEA8 +AFX_IDP_E_FILEALREADYOPEN = 0xFEA9 +AFX_IDP_E_DEVICEIOERROR = 0xFEAA +AFX_IDP_E_FILEALREADYEXISTS = 0xFEAB +AFX_IDP_E_BADRECORDLENGTH = 0xFEAC +AFX_IDP_E_DISKFULL = 0xFEAD +AFX_IDP_E_BADRECORDNUMBER = 0xFEAE +AFX_IDP_E_BADFILENAME = 0xFEAF +AFX_IDP_E_TOOMANYFILES = 0xFEB0 +AFX_IDP_E_DEVICEUNAVAILABLE = 0xFEB1 +AFX_IDP_E_PERMISSIONDENIED = 0xFEB2 +AFX_IDP_E_DISKNOTREADY = 0xFEB3 +AFX_IDP_E_PATHFILEACCESSERROR = 0xFEB4 +AFX_IDP_E_PATHNOTFOUND = 0xFEB5 +AFX_IDP_E_INVALIDPATTERNSTRING = 0xFEB6 +AFX_IDP_E_INVALIDUSEOFNULL = 0xFEB7 +AFX_IDP_E_INVALIDFILEFORMAT = 0xFEB8 +AFX_IDP_E_INVALIDPROPERTYVALUE = 0xFEB9 +AFX_IDP_E_INVALIDPROPERTYARRAYINDEX = 0xFEBA +AFX_IDP_E_SETNOTSUPPORTEDATRUNTIME = 0xFEBB +AFX_IDP_E_SETNOTSUPPORTED = 0xFEBC +AFX_IDP_E_NEEDPROPERTYARRAYINDEX = 0xFEBD +AFX_IDP_E_SETNOTPERMITTED = 0xFEBE +AFX_IDP_E_GETNOTSUPPORTEDATRUNTIME = 0xFEBF +AFX_IDP_E_GETNOTSUPPORTED = 0xFEC0 +AFX_IDP_E_PROPERTYNOTFOUND = 0xFEC1 +AFX_IDP_E_INVALIDCLIPBOARDFORMAT = 0xFEC2 +AFX_IDP_E_INVALIDPICTURE = 0xFEC3 +AFX_IDP_E_PRINTERERROR = 0xFEC4 +AFX_IDP_E_CANTSAVEFILETOTEMP = 0xFEC5 +AFX_IDP_E_SEARCHTEXTNOTFOUND = 0xFEC6 +AFX_IDP_E_REPLACEMENTSTOOLONG = 0xFEC7 diff --git a/MLPY/Lib/site-packages/win32/lib/commctrl.py b/MLPY/Lib/site-packages/win32/lib/commctrl.py new file mode 100644 index 0000000000000000000000000000000000000000..26641e8452a88aa8c90c42f42f0a953ace72a234 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/commctrl.py @@ -0,0 +1,1551 @@ +# Generated by h2py from COMMCTRL.H +WM_USER = 1024 +ICC_LISTVIEW_CLASSES = 1 # listview, header +ICC_TREEVIEW_CLASSES = 2 # treeview, tooltips +ICC_BAR_CLASSES = 4 # toolbar, statusbar, trackbar, tooltips +ICC_TAB_CLASSES = 8 # tab, tooltips +ICC_UPDOWN_CLASS = 16 # updown +ICC_PROGRESS_CLASS = 32 # progress +ICC_HOTKEY_CLASS = 64 # hotkey +ICC_ANIMATE_CLASS = 128 # animate +ICC_WIN95_CLASSES = 255 +ICC_DATE_CLASSES = 256 # month picker, date picker, time picker, updown +ICC_USEREX_CLASSES = 512 # comboex +ICC_COOL_CLASSES = 1024 # rebar (coolbar) control +ICC_INTERNET_CLASSES = 2048 +ICC_PAGESCROLLER_CLASS = 4096 # page scroller +ICC_NATIVEFNTCTL_CLASS = 8192 # native font control +ODT_HEADER = 100 +ODT_TAB = 101 +ODT_LISTVIEW = 102 +PY_0U = 0 +NM_FIRST = PY_0U # generic to all controls +NM_LAST = PY_0U - 99 +LVN_FIRST = PY_0U - 100 # listview +LVN_LAST = PY_0U - 199 +HDN_FIRST = PY_0U - 300 # header +HDN_LAST = PY_0U - 399 +TVN_FIRST = PY_0U - 400 # treeview +TVN_LAST = PY_0U - 499 +TTN_FIRST = PY_0U - 520 # tooltips +TTN_LAST = PY_0U - 549 +TCN_FIRST = PY_0U - 550 # tab control +TCN_LAST = PY_0U - 580 +CDN_FIRST = PY_0U - 601 # common dialog (new) +CDN_LAST = PY_0U - 699 +TBN_FIRST = PY_0U - 700 # toolbar +TBN_LAST = PY_0U - 720 +UDN_FIRST = PY_0U - 721 # updown +UDN_LAST = PY_0U - 740 +MCN_FIRST = PY_0U - 750 # monthcal +MCN_LAST = PY_0U - 759 +DTN_FIRST = PY_0U - 760 # datetimepick +DTN_LAST = PY_0U - 799 +CBEN_FIRST = PY_0U - 800 # combo box ex +CBEN_LAST = PY_0U - 830 +RBN_FIRST = PY_0U - 831 # rebar +RBN_LAST = PY_0U - 859 +IPN_FIRST = PY_0U - 860 # internet address +IPN_LAST = PY_0U - 879 # internet address +SBN_FIRST = PY_0U - 880 # status bar +SBN_LAST = PY_0U - 899 +PGN_FIRST = PY_0U - 900 # Pager Control +PGN_LAST = PY_0U - 950 +LVM_FIRST = 4096 # ListView messages +TV_FIRST = 4352 # TreeView messages +HDM_FIRST = 4608 # Header messages +TCM_FIRST = 4864 # Tab control messages +PGM_FIRST = 5120 # Pager control messages +CCM_FIRST = 8192 # Common control shared messages +CCM_SETBKCOLOR = CCM_FIRST + 1 # lParam is bkColor +CCM_SETCOLORSCHEME = CCM_FIRST + 2 # lParam is color scheme +CCM_GETCOLORSCHEME = CCM_FIRST + 3 # fills in COLORSCHEME pointed to by lParam +CCM_GETDROPTARGET = CCM_FIRST + 4 +CCM_SETUNICODEFORMAT = CCM_FIRST + 5 +CCM_GETUNICODEFORMAT = CCM_FIRST + 6 +INFOTIPSIZE = 1024 +NM_OUTOFMEMORY = NM_FIRST - 1 +NM_CLICK = NM_FIRST - 2 # uses NMCLICK struct +NM_DBLCLK = NM_FIRST - 3 +NM_RETURN = NM_FIRST - 4 +NM_RCLICK = NM_FIRST - 5 # uses NMCLICK struct +NM_RDBLCLK = NM_FIRST - 6 +NM_SETFOCUS = NM_FIRST - 7 +NM_KILLFOCUS = NM_FIRST - 8 +NM_CUSTOMDRAW = NM_FIRST - 12 +NM_HOVER = NM_FIRST - 13 +NM_NCHITTEST = NM_FIRST - 14 # uses NMMOUSE struct +NM_KEYDOWN = NM_FIRST - 15 # uses NMKEY struct +NM_RELEASEDCAPTURE = NM_FIRST - 16 +NM_SETCURSOR = NM_FIRST - 17 # uses NMMOUSE struct +NM_CHAR = NM_FIRST - 18 # uses NMCHAR struct +MSGF_COMMCTRL_BEGINDRAG = 16896 +MSGF_COMMCTRL_SIZEHEADER = 16897 +MSGF_COMMCTRL_DRAGSELECT = 16898 +MSGF_COMMCTRL_TOOLBARCUST = 16899 +CDRF_DODEFAULT = 0 +CDRF_NEWFONT = 2 +CDRF_SKIPDEFAULT = 4 +CDRF_NOTIFYPOSTPAINT = 16 +CDRF_NOTIFYITEMDRAW = 32 +CDRF_NOTIFYSUBITEMDRAW = 32 # flags are the same, we can distinguish by context +CDRF_NOTIFYPOSTERASE = 64 +CDDS_PREPAINT = 1 +CDDS_POSTPAINT = 2 +CDDS_PREERASE = 3 +CDDS_POSTERASE = 4 +CDDS_ITEM = 65536 +CDDS_ITEMPREPAINT = CDDS_ITEM | CDDS_PREPAINT +CDDS_ITEMPOSTPAINT = CDDS_ITEM | CDDS_POSTPAINT +CDDS_ITEMPREERASE = CDDS_ITEM | CDDS_PREERASE +CDDS_ITEMPOSTERASE = CDDS_ITEM | CDDS_POSTERASE +CDDS_SUBITEM = 131072 +CDIS_SELECTED = 1 +CDIS_GRAYED = 2 +CDIS_DISABLED = 4 +CDIS_CHECKED = 8 +CDIS_FOCUS = 16 +CDIS_DEFAULT = 32 +CDIS_HOT = 64 +CDIS_MARKED = 128 +CDIS_INDETERMINATE = 256 +CLR_NONE = -1 # 0xFFFFFFFFL +CLR_DEFAULT = -16777216 # 0xFF000000L +ILC_MASK = 1 +ILC_COLOR = 0 +ILC_COLORDDB = 254 +ILC_COLOR4 = 4 +ILC_COLOR8 = 8 +ILC_COLOR16 = 16 +ILC_COLOR24 = 24 +ILC_COLOR32 = 32 +ILC_PALETTE = 2048 # (not implemented) +ILD_NORMAL = 0 +ILD_TRANSPARENT = 1 +ILD_MASK = 16 +ILD_IMAGE = 32 +ILD_ROP = 64 +ILD_BLEND25 = 2 +ILD_BLEND50 = 4 +ILD_OVERLAYMASK = 3840 +ILD_SELECTED = ILD_BLEND50 +ILD_FOCUS = ILD_BLEND25 +ILD_BLEND = ILD_BLEND50 +CLR_HILIGHT = CLR_DEFAULT +ILCF_MOVE = 0 +ILCF_SWAP = 1 +WC_HEADERA = "SysHeader32" +WC_HEADER = WC_HEADERA +HDS_HORZ = 0 +HDS_BUTTONS = 2 +HDS_HOTTRACK = 4 +HDS_HIDDEN = 8 +HDS_DRAGDROP = 64 +HDS_FULLDRAG = 128 +HDI_WIDTH = 1 +HDI_HEIGHT = HDI_WIDTH +HDI_TEXT = 2 +HDI_FORMAT = 4 +HDI_LPARAM = 8 +HDI_BITMAP = 16 +HDI_IMAGE = 32 +HDI_DI_SETITEM = 64 +HDI_ORDER = 128 +HDF_LEFT = 0 +HDF_RIGHT = 1 +HDF_CENTER = 2 +HDF_JUSTIFYMASK = 3 +HDF_RTLREADING = 4 +HDF_OWNERDRAW = 32768 +HDF_STRING = 16384 +HDF_BITMAP = 8192 +HDF_BITMAP_ON_RIGHT = 4096 +HDF_IMAGE = 2048 +HDM_GETITEMCOUNT = HDM_FIRST + 0 +HDM_INSERTITEMA = HDM_FIRST + 1 +HDM_INSERTITEMW = HDM_FIRST + 10 +HDM_INSERTITEM = HDM_INSERTITEMA +HDM_DELETEITEM = HDM_FIRST + 2 +HDM_GETITEMA = HDM_FIRST + 3 +HDM_GETITEMW = HDM_FIRST + 11 +HDM_GETITEM = HDM_GETITEMA +HDM_SETITEMA = HDM_FIRST + 4 +HDM_SETITEMW = HDM_FIRST + 12 +HDM_SETITEM = HDM_SETITEMA +HDM_LAYOUT = HDM_FIRST + 5 +HHT_NOWHERE = 1 +HHT_ONHEADER = 2 +HHT_ONDIVIDER = 4 +HHT_ONDIVOPEN = 8 +HHT_ABOVE = 256 +HHT_BELOW = 512 +HHT_TORIGHT = 1024 +HHT_TOLEFT = 2048 +HDM_HITTEST = HDM_FIRST + 6 +HDM_GETITEMRECT = HDM_FIRST + 7 +HDM_SETIMAGELIST = HDM_FIRST + 8 +HDM_GETIMAGELIST = HDM_FIRST + 9 +HDM_ORDERTOINDEX = HDM_FIRST + 15 +HDM_CREATEDRAGIMAGE = HDM_FIRST + 16 # wparam = which item (by index) +HDM_GETORDERARRAY = HDM_FIRST + 17 +HDM_SETORDERARRAY = HDM_FIRST + 18 +HDM_SETHOTDIVIDER = HDM_FIRST + 19 +HDM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +HDM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +HDN_ITEMCHANGINGA = HDN_FIRST - 0 +HDN_ITEMCHANGINGW = HDN_FIRST - 20 +HDN_ITEMCHANGEDA = HDN_FIRST - 1 +HDN_ITEMCHANGEDW = HDN_FIRST - 21 +HDN_ITEMCLICKA = HDN_FIRST - 2 +HDN_ITEMCLICKW = HDN_FIRST - 22 +HDN_ITEMDBLCLICKA = HDN_FIRST - 3 +HDN_ITEMDBLCLICKW = HDN_FIRST - 23 +HDN_DIVIDERDBLCLICKA = HDN_FIRST - 5 +HDN_DIVIDERDBLCLICKW = HDN_FIRST - 25 +HDN_BEGINTRACKA = HDN_FIRST - 6 +HDN_BEGINTRACKW = HDN_FIRST - 26 +HDN_ENDTRACKA = HDN_FIRST - 7 +HDN_ENDTRACKW = HDN_FIRST - 27 +HDN_TRACKA = HDN_FIRST - 8 +HDN_TRACKW = HDN_FIRST - 28 +HDN_GETDISPINFOA = HDN_FIRST - 9 +HDN_GETDISPINFOW = HDN_FIRST - 29 +HDN_BEGINDRAG = HDN_FIRST - 10 +HDN_ENDDRAG = HDN_FIRST - 11 +HDN_ITEMCHANGING = HDN_ITEMCHANGINGA +HDN_ITEMCHANGED = HDN_ITEMCHANGEDA +HDN_ITEMCLICK = HDN_ITEMCLICKA +HDN_ITEMDBLCLICK = HDN_ITEMDBLCLICKA +HDN_DIVIDERDBLCLICK = HDN_DIVIDERDBLCLICKA +HDN_BEGINTRACK = HDN_BEGINTRACKA +HDN_ENDTRACK = HDN_ENDTRACKA +HDN_TRACK = HDN_TRACKA +HDN_GETDISPINFO = HDN_GETDISPINFOA +TOOLBARCLASSNAMEA = "ToolbarWindow32" +TOOLBARCLASSNAME = TOOLBARCLASSNAMEA +CMB_MASKED = 2 +TBSTATE_CHECKED = 1 +TBSTATE_PRESSED = 2 +TBSTATE_ENABLED = 4 +TBSTATE_HIDDEN = 8 +TBSTATE_INDETERMINATE = 16 +TBSTATE_WRAP = 32 +TBSTATE_ELLIPSES = 64 +TBSTATE_MARKED = 128 +TBSTYLE_BUTTON = 0 +TBSTYLE_SEP = 1 +TBSTYLE_CHECK = 2 +TBSTYLE_GROUP = 4 +TBSTYLE_CHECKGROUP = TBSTYLE_GROUP | TBSTYLE_CHECK +TBSTYLE_DROPDOWN = 8 +TBSTYLE_AUTOSIZE = 16 # automatically calculate the cx of the button +TBSTYLE_NOPREFIX = 32 # if this button should not have accel prefix +TBSTYLE_TOOLTIPS = 256 +TBSTYLE_WRAPABLE = 512 +TBSTYLE_ALTDRAG = 1024 +TBSTYLE_FLAT = 2048 +TBSTYLE_LIST = 4096 +TBSTYLE_CUSTOMERASE = 8192 +TBSTYLE_REGISTERDROP = 16384 +TBSTYLE_TRANSPARENT = 32768 +TBSTYLE_EX_DRAWDDARROWS = 1 +BTNS_BUTTON = TBSTYLE_BUTTON +BTNS_SEP = TBSTYLE_SEP # 0x0001 +BTNS_CHECK = TBSTYLE_CHECK # 0x0002 +BTNS_GROUP = TBSTYLE_GROUP # 0x0004 +BTNS_CHECKGROUP = TBSTYLE_CHECKGROUP # (TBSTYLE_GROUP | TBSTYLE_CHECK) +BTNS_DROPDOWN = TBSTYLE_DROPDOWN # 0x0008 +BTNS_AUTOSIZE = TBSTYLE_AUTOSIZE # 0x0010; automatically calculate the cx of the button +BTNS_NOPREFIX = TBSTYLE_NOPREFIX # 0x0020; this button should not have accel prefix +BTNS_SHOWTEXT = ( + 64 # 0x0040 // ignored unless TBSTYLE_EX_MIXEDBUTTONS is set +) +BTNS_WHOLEDROPDOWN = ( + 128 # 0x0080 // draw drop-down arrow, but without split arrow section +) +TBCDRF_NOEDGES = 65536 # Don't draw button edges +TBCDRF_HILITEHOTTRACK = 131072 # Use color of the button bk when hottracked +TBCDRF_NOOFFSET = 262144 # Don't offset button if pressed +TBCDRF_NOMARK = 524288 # Don't draw default highlight of image/text for TBSTATE_MARKED +TBCDRF_NOETCHEDEFFECT = 1048576 # Don't draw etched effect for disabled items +TB_ENABLEBUTTON = WM_USER + 1 +TB_CHECKBUTTON = WM_USER + 2 +TB_PRESSBUTTON = WM_USER + 3 +TB_HIDEBUTTON = WM_USER + 4 +TB_INDETERMINATE = WM_USER + 5 +TB_MARKBUTTON = WM_USER + 6 +TB_ISBUTTONENABLED = WM_USER + 9 +TB_ISBUTTONCHECKED = WM_USER + 10 +TB_ISBUTTONPRESSED = WM_USER + 11 +TB_ISBUTTONHIDDEN = WM_USER + 12 +TB_ISBUTTONINDETERMINATE = WM_USER + 13 +TB_ISBUTTONHIGHLIGHTED = WM_USER + 14 +TB_SETSTATE = WM_USER + 17 +TB_GETSTATE = WM_USER + 18 +TB_ADDBITMAP = WM_USER + 19 +HINST_COMMCTRL = -1 +IDB_STD_SMALL_COLOR = 0 +IDB_STD_LARGE_COLOR = 1 +IDB_VIEW_SMALL_COLOR = 4 +IDB_VIEW_LARGE_COLOR = 5 +IDB_HIST_SMALL_COLOR = 8 +IDB_HIST_LARGE_COLOR = 9 +STD_CUT = 0 +STD_COPY = 1 +STD_PASTE = 2 +STD_UNDO = 3 +STD_REDOW = 4 +STD_DELETE = 5 +STD_FILENEW = 6 +STD_FILEOPEN = 7 +STD_FILESAVE = 8 +STD_PRINTPRE = 9 +STD_PROPERTIES = 10 +STD_HELP = 11 +STD_FIND = 12 +STD_REPLACE = 13 +STD_PRINT = 14 +VIEW_LARGEICONS = 0 +VIEW_SMALLICONS = 1 +VIEW_LIST = 2 +VIEW_DETAILS = 3 +VIEW_SORTNAME = 4 +VIEW_SORTSIZE = 5 +VIEW_SORTDATE = 6 +VIEW_SORTTYPE = 7 +VIEW_PARENTFOLDER = 8 +VIEW_NETCONNECT = 9 +VIEW_NETDISCONNECT = 10 +VIEW_NEWFOLDER = 11 +VIEW_VIEWMENU = 12 +HIST_BACK = 0 +HIST_FORWARD = 1 +HIST_FAVORITES = 2 +HIST_ADDTOFAVORITES = 3 +HIST_VIEWTREE = 4 +TB_ADDBUTTONSA = WM_USER + 20 +TB_INSERTBUTTONA = WM_USER + 21 +TB_ADDBUTTONS = WM_USER + 20 +TB_INSERTBUTTON = WM_USER + 21 +TB_DELETEBUTTON = WM_USER + 22 +TB_GETBUTTON = WM_USER + 23 +TB_BUTTONCOUNT = WM_USER + 24 +TB_COMMANDTOINDEX = WM_USER + 25 +TB_SAVERESTOREA = WM_USER + 26 +TB_SAVERESTOREW = WM_USER + 76 +TB_CUSTOMIZE = WM_USER + 27 +TB_ADDSTRINGA = WM_USER + 28 +TB_ADDSTRINGW = WM_USER + 77 +TB_GETITEMRECT = WM_USER + 29 +TB_BUTTONSTRUCTSIZE = WM_USER + 30 +TB_SETBUTTONSIZE = WM_USER + 31 +TB_SETBITMAPSIZE = WM_USER + 32 +TB_AUTOSIZE = WM_USER + 33 +TB_GETTOOLTIPS = WM_USER + 35 +TB_SETTOOLTIPS = WM_USER + 36 +TB_SETPARENT = WM_USER + 37 +TB_SETROWS = WM_USER + 39 +TB_GETROWS = WM_USER + 40 +TB_SETCMDID = WM_USER + 42 +TB_CHANGEBITMAP = WM_USER + 43 +TB_GETBITMAP = WM_USER + 44 +TB_GETBUTTONTEXTA = WM_USER + 45 +TB_GETBUTTONTEXTW = WM_USER + 75 +TB_REPLACEBITMAP = WM_USER + 46 +TB_SETINDENT = WM_USER + 47 +TB_SETIMAGELIST = WM_USER + 48 +TB_GETIMAGELIST = WM_USER + 49 +TB_LOADIMAGES = WM_USER + 50 +TB_GETRECT = WM_USER + 51 # wParam is the Cmd instead of index +TB_SETHOTIMAGELIST = WM_USER + 52 +TB_GETHOTIMAGELIST = WM_USER + 53 +TB_SETDISABLEDIMAGELIST = WM_USER + 54 +TB_GETDISABLEDIMAGELIST = WM_USER + 55 +TB_SETSTYLE = WM_USER + 56 +TB_GETSTYLE = WM_USER + 57 +TB_GETBUTTONSIZE = WM_USER + 58 +TB_SETBUTTONWIDTH = WM_USER + 59 +TB_SETMAXTEXTROWS = WM_USER + 60 +TB_GETTEXTROWS = WM_USER + 61 +TB_GETBUTTONTEXT = TB_GETBUTTONTEXTA +TB_SAVERESTORE = TB_SAVERESTOREA +TB_ADDSTRING = TB_ADDSTRINGA +TB_GETOBJECT = WM_USER + 62 # wParam == IID, lParam void **ppv +TB_GETHOTITEM = WM_USER + 71 +TB_SETHOTITEM = WM_USER + 72 # wParam == iHotItem +TB_SETANCHORHIGHLIGHT = WM_USER + 73 # wParam == TRUE/FALSE +TB_GETANCHORHIGHLIGHT = WM_USER + 74 +TB_MAPACCELERATORA = WM_USER + 78 # wParam == ch, lParam int * pidBtn +TBIMHT_AFTER = 1 # TRUE = insert After iButton, otherwise before +TBIMHT_BACKGROUND = 2 # TRUE iff missed buttons completely +TB_GETINSERTMARK = WM_USER + 79 # lParam == LPTBINSERTMARK +TB_SETINSERTMARK = WM_USER + 80 # lParam == LPTBINSERTMARK +TB_INSERTMARKHITTEST = WM_USER + 81 # wParam == LPPOINT lParam == LPTBINSERTMARK +TB_MOVEBUTTON = WM_USER + 82 +TB_GETMAXSIZE = WM_USER + 83 # lParam == LPSIZE +TB_SETEXTENDEDSTYLE = WM_USER + 84 # For TBSTYLE_EX_* +TB_GETEXTENDEDSTYLE = WM_USER + 85 # For TBSTYLE_EX_* +TB_GETPADDING = WM_USER + 86 +TB_SETPADDING = WM_USER + 87 +TB_SETINSERTMARKCOLOR = WM_USER + 88 +TB_GETINSERTMARKCOLOR = WM_USER + 89 +TB_SETCOLORSCHEME = CCM_SETCOLORSCHEME # lParam is color scheme +TB_GETCOLORSCHEME = CCM_GETCOLORSCHEME # fills in COLORSCHEME pointed to by lParam +TB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TB_MAPACCELERATORW = WM_USER + 90 # wParam == ch, lParam int * pidBtn +TB_MAPACCELERATOR = TB_MAPACCELERATORA +TBBF_LARGE = 1 +TB_GETBITMAPFLAGS = WM_USER + 41 +TBIF_IMAGE = 1 +TBIF_TEXT = 2 +TBIF_STATE = 4 +TBIF_STYLE = 8 +TBIF_LPARAM = 16 +TBIF_COMMAND = 32 +TBIF_SIZE = 64 +TB_GETBUTTONINFOW = WM_USER + 63 +TB_SETBUTTONINFOW = WM_USER + 64 +TB_GETBUTTONINFOA = WM_USER + 65 +TB_SETBUTTONINFOA = WM_USER + 66 +TB_INSERTBUTTONW = WM_USER + 67 +TB_ADDBUTTONSW = WM_USER + 68 +TB_HITTEST = WM_USER + 69 +TB_SETDRAWTEXTFLAGS = WM_USER + 70 # wParam == mask lParam == bit values +TBN_GETBUTTONINFOA = TBN_FIRST - 0 +TBN_GETBUTTONINFOW = TBN_FIRST - 20 +TBN_BEGINDRAG = TBN_FIRST - 1 +TBN_ENDDRAG = TBN_FIRST - 2 +TBN_BEGINADJUST = TBN_FIRST - 3 +TBN_ENDADJUST = TBN_FIRST - 4 +TBN_RESET = TBN_FIRST - 5 +TBN_QUERYINSERT = TBN_FIRST - 6 +TBN_QUERYDELETE = TBN_FIRST - 7 +TBN_TOOLBARCHANGE = TBN_FIRST - 8 +TBN_CUSTHELP = TBN_FIRST - 9 +TBN_DROPDOWN = TBN_FIRST - 10 +TBN_GETOBJECT = TBN_FIRST - 12 +HICF_OTHER = 0 +HICF_MOUSE = 1 # Triggered by mouse +HICF_ARROWKEYS = 2 # Triggered by arrow keys +HICF_ACCELERATOR = 4 # Triggered by accelerator +HICF_DUPACCEL = 8 # This accelerator is not unique +HICF_ENTERING = 16 # idOld is invalid +HICF_LEAVING = 32 # idNew is invalid +HICF_RESELECT = 64 # hot item reselected +TBN_HOTITEMCHANGE = TBN_FIRST - 13 +TBN_DRAGOUT = ( + TBN_FIRST - 14 +) # this is sent when the user clicks down on a button then drags off the button +TBN_DELETINGBUTTON = TBN_FIRST - 15 # uses TBNOTIFY +TBN_GETDISPINFOA = ( + TBN_FIRST - 16 +) # This is sent when the toolbar needs some display information +TBN_GETDISPINFOW = ( + TBN_FIRST - 17 +) # This is sent when the toolbar needs some display information +TBN_GETINFOTIPA = TBN_FIRST - 18 +TBN_GETINFOTIPW = TBN_FIRST - 19 +TBN_GETINFOTIP = TBN_GETINFOTIPA +TBNF_IMAGE = 1 +TBNF_TEXT = 2 +TBNF_DI_SETITEM = 268435456 +TBN_GETDISPINFO = TBN_GETDISPINFOA +TBDDRET_DEFAULT = 0 +TBDDRET_NODEFAULT = 1 +TBDDRET_TREATPRESSED = 2 # Treat as a standard press button +TBN_GETBUTTONINFO = TBN_GETBUTTONINFOA +REBARCLASSNAMEA = "ReBarWindow32" +REBARCLASSNAME = REBARCLASSNAMEA +RBIM_IMAGELIST = 1 +RBS_TOOLTIPS = 256 +RBS_VARHEIGHT = 512 +RBS_BANDBORDERS = 1024 +RBS_FIXEDORDER = 2048 +RBS_REGISTERDROP = 4096 +RBS_AUTOSIZE = 8192 +RBS_VERTICALGRIPPER = ( + 16384 # this always has the vertical gripper (default for horizontal mode) +) +RBS_DBLCLKTOGGLE = 32768 +RBBS_BREAK = 1 # break to new line +RBBS_FIXEDSIZE = 2 # band can't be sized +RBBS_CHILDEDGE = 4 # edge around top & bottom of child window +RBBS_HIDDEN = 8 # don't show +RBBS_NOVERT = 16 # don't show when vertical +RBBS_FIXEDBMP = 32 # bitmap doesn't move during band resize +RBBS_VARIABLEHEIGHT = 64 # allow autosizing of this child vertically +RBBS_GRIPPERALWAYS = 128 # always show the gripper +RBBS_NOGRIPPER = 256 # never show the gripper +RBBIM_STYLE = 1 +RBBIM_COLORS = 2 +RBBIM_TEXT = 4 +RBBIM_IMAGE = 8 +RBBIM_CHILD = 16 +RBBIM_CHILDSIZE = 32 +RBBIM_SIZE = 64 +RBBIM_BACKGROUND = 128 +RBBIM_ID = 256 +RBBIM_IDEALSIZE = 512 +RBBIM_LPARAM = 1024 +RB_INSERTBANDA = WM_USER + 1 +RB_DELETEBAND = WM_USER + 2 +RB_GETBARINFO = WM_USER + 3 +RB_SETBARINFO = WM_USER + 4 +RB_SETBANDINFOA = WM_USER + 6 +RB_SETPARENT = WM_USER + 7 +RB_HITTEST = WM_USER + 8 +RB_GETRECT = WM_USER + 9 +RB_INSERTBANDW = WM_USER + 10 +RB_SETBANDINFOW = WM_USER + 11 +RB_GETBANDCOUNT = WM_USER + 12 +RB_GETROWCOUNT = WM_USER + 13 +RB_GETROWHEIGHT = WM_USER + 14 +RB_IDTOINDEX = WM_USER + 16 # wParam == id +RB_GETTOOLTIPS = WM_USER + 17 +RB_SETTOOLTIPS = WM_USER + 18 +RB_SETBKCOLOR = WM_USER + 19 # sets the default BK color +RB_GETBKCOLOR = WM_USER + 20 # defaults to CLR_NONE +RB_SETTEXTCOLOR = WM_USER + 21 +RB_GETTEXTCOLOR = WM_USER + 22 # defaults to 0x00000000 +RB_SIZETORECT = ( + WM_USER + 23 +) # resize the rebar/break bands and such to this rect (lparam) +RB_SETCOLORSCHEME = CCM_SETCOLORSCHEME # lParam is color scheme +RB_GETCOLORSCHEME = CCM_GETCOLORSCHEME # fills in COLORSCHEME pointed to by lParam +RB_INSERTBAND = RB_INSERTBANDA +RB_SETBANDINFO = RB_SETBANDINFOA +RB_BEGINDRAG = WM_USER + 24 +RB_ENDDRAG = WM_USER + 25 +RB_DRAGMOVE = WM_USER + 26 +RB_GETBARHEIGHT = WM_USER + 27 +RB_GETBANDINFOW = WM_USER + 28 +RB_GETBANDINFOA = WM_USER + 29 +RB_GETBANDINFO = RB_GETBANDINFOA +RB_MINIMIZEBAND = WM_USER + 30 +RB_MAXIMIZEBAND = WM_USER + 31 +RB_GETDROPTARGET = CCM_GETDROPTARGET +RB_GETBANDBORDERS = ( + WM_USER + 34 +) # returns in lparam = lprc the amount of edges added to band wparam +RB_SHOWBAND = WM_USER + 35 # show/hide band +RB_SETPALETTE = WM_USER + 37 +RB_GETPALETTE = WM_USER + 38 +RB_MOVEBAND = WM_USER + 39 +RB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +RB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +RBN_HEIGHTCHANGE = RBN_FIRST - 0 +RBN_GETOBJECT = RBN_FIRST - 1 +RBN_LAYOUTCHANGED = RBN_FIRST - 2 +RBN_AUTOSIZE = RBN_FIRST - 3 +RBN_BEGINDRAG = RBN_FIRST - 4 +RBN_ENDDRAG = RBN_FIRST - 5 +RBN_DELETINGBAND = RBN_FIRST - 6 # Uses NMREBAR +RBN_DELETEDBAND = RBN_FIRST - 7 # Uses NMREBAR +RBN_CHILDSIZE = RBN_FIRST - 8 +RBNM_ID = 1 +RBNM_STYLE = 2 +RBNM_LPARAM = 4 +RBHT_NOWHERE = 1 +RBHT_CAPTION = 2 +RBHT_CLIENT = 3 +RBHT_GRABBER = 4 +TOOLTIPS_CLASSA = "tooltips_class32" +TOOLTIPS_CLASS = TOOLTIPS_CLASSA +TTS_ALWAYSTIP = 1 +TTS_NOPREFIX = 2 +TTF_IDISHWND = 1 +TTF_CENTERTIP = 2 +TTF_RTLREADING = 4 +TTF_SUBCLASS = 16 +TTF_TRACK = 32 +TTF_ABSOLUTE = 128 +TTF_TRANSPARENT = 256 +TTF_DI_SETITEM = 32768 # valid only on the TTN_NEEDTEXT callback +TTDT_AUTOMATIC = 0 +TTDT_RESHOW = 1 +TTDT_AUTOPOP = 2 +TTDT_INITIAL = 3 +TTM_ACTIVATE = WM_USER + 1 +TTM_SETDELAYTIME = WM_USER + 3 +TTM_ADDTOOLA = WM_USER + 4 +TTM_ADDTOOLW = WM_USER + 50 +TTM_DELTOOLA = WM_USER + 5 +TTM_DELTOOLW = WM_USER + 51 +TTM_NEWTOOLRECTA = WM_USER + 6 +TTM_NEWTOOLRECTW = WM_USER + 52 +TTM_RELAYEVENT = WM_USER + 7 +TTM_GETTOOLINFOA = WM_USER + 8 +TTM_GETTOOLINFOW = WM_USER + 53 +TTM_SETTOOLINFOA = WM_USER + 9 +TTM_SETTOOLINFOW = WM_USER + 54 +TTM_HITTESTA = WM_USER + 10 +TTM_HITTESTW = WM_USER + 55 +TTM_GETTEXTA = WM_USER + 11 +TTM_GETTEXTW = WM_USER + 56 +TTM_UPDATETIPTEXTA = WM_USER + 12 +TTM_UPDATETIPTEXTW = WM_USER + 57 +TTM_GETTOOLCOUNT = WM_USER + 13 +TTM_ENUMTOOLSA = WM_USER + 14 +TTM_ENUMTOOLSW = WM_USER + 58 +TTM_GETCURRENTTOOLA = WM_USER + 15 +TTM_GETCURRENTTOOLW = WM_USER + 59 +TTM_WINDOWFROMPOINT = WM_USER + 16 +TTM_TRACKACTIVATE = WM_USER + 17 # wParam = TRUE/FALSE start end lparam = LPTOOLINFO +TTM_TRACKPOSITION = WM_USER + 18 # lParam = dwPos +TTM_SETTIPBKCOLOR = WM_USER + 19 +TTM_SETTIPTEXTCOLOR = WM_USER + 20 +TTM_GETDELAYTIME = WM_USER + 21 +TTM_GETTIPBKCOLOR = WM_USER + 22 +TTM_GETTIPTEXTCOLOR = WM_USER + 23 +TTM_SETMAXTIPWIDTH = WM_USER + 24 +TTM_GETMAXTIPWIDTH = WM_USER + 25 +TTM_SETMARGIN = WM_USER + 26 # lParam = lprc +TTM_GETMARGIN = WM_USER + 27 # lParam = lprc +TTM_POP = WM_USER + 28 +TTM_UPDATE = WM_USER + 29 +TTM_ADDTOOL = TTM_ADDTOOLA +TTM_DELTOOL = TTM_DELTOOLA +TTM_NEWTOOLRECT = TTM_NEWTOOLRECTA +TTM_GETTOOLINFO = TTM_GETTOOLINFOA +TTM_SETTOOLINFO = TTM_SETTOOLINFOA +TTM_HITTEST = TTM_HITTESTA +TTM_GETTEXT = TTM_GETTEXTA +TTM_UPDATETIPTEXT = TTM_UPDATETIPTEXTA +TTM_ENUMTOOLS = TTM_ENUMTOOLSA +TTM_GETCURRENTTOOL = TTM_GETCURRENTTOOLA +TTN_GETDISPINFOA = TTN_FIRST - 0 +TTN_GETDISPINFOW = TTN_FIRST - 10 +TTN_SHOW = TTN_FIRST - 1 +TTN_POP = TTN_FIRST - 2 +TTN_GETDISPINFO = TTN_GETDISPINFOA +TTN_NEEDTEXT = TTN_GETDISPINFO +TTN_NEEDTEXTA = TTN_GETDISPINFOA +TTN_NEEDTEXTW = TTN_GETDISPINFOW +SBARS_SIZEGRIP = 256 +SBARS_TOOLTIPS = 2048 +STATUSCLASSNAMEA = "msctls_statusbar32" +STATUSCLASSNAME = STATUSCLASSNAMEA +SB_SETTEXTA = WM_USER + 1 +SB_SETTEXTW = WM_USER + 11 +SB_GETTEXTA = WM_USER + 2 +SB_GETTEXTW = WM_USER + 13 +SB_GETTEXTLENGTHA = WM_USER + 3 +SB_GETTEXTLENGTHW = WM_USER + 12 +SB_GETTEXT = SB_GETTEXTA +SB_SETTEXT = SB_SETTEXTA +SB_GETTEXTLENGTH = SB_GETTEXTLENGTHA +SB_SETPARTS = WM_USER + 4 +SB_GETPARTS = WM_USER + 6 +SB_GETBORDERS = WM_USER + 7 +SB_SETMINHEIGHT = WM_USER + 8 +SB_SIMPLE = WM_USER + 9 +SB_GETRECT = WM_USER + 10 +SB_ISSIMPLE = WM_USER + 14 +SB_SETICON = WM_USER + 15 +SB_SETTIPTEXTA = WM_USER + 16 +SB_SETTIPTEXTW = WM_USER + 17 +SB_GETTIPTEXTA = WM_USER + 18 +SB_GETTIPTEXTW = WM_USER + 19 +SB_GETICON = WM_USER + 20 +SB_SETTIPTEXT = SB_SETTIPTEXTA +SB_GETTIPTEXT = SB_GETTIPTEXTA +SB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +SB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +SBT_OWNERDRAW = 4096 +SBT_NOBORDERS = 256 +SBT_POPOUT = 512 +SBT_RTLREADING = 1024 +SBT_NOTABPARSING = 2048 +SBT_TOOLTIPS = 2048 +SB_SETBKCOLOR = CCM_SETBKCOLOR # lParam = bkColor +SBN_SIMPLEMODECHANGE = SBN_FIRST - 0 +TRACKBAR_CLASSA = "msctls_trackbar32" +TRACKBAR_CLASS = TRACKBAR_CLASSA +TBS_AUTOTICKS = 1 +TBS_VERT = 2 +TBS_HORZ = 0 +TBS_TOP = 4 +TBS_BOTTOM = 0 +TBS_LEFT = 4 +TBS_RIGHT = 0 +TBS_BOTH = 8 +TBS_NOTICKS = 16 +TBS_ENABLESELRANGE = 32 +TBS_FIXEDLENGTH = 64 +TBS_NOTHUMB = 128 +TBS_TOOLTIPS = 256 +TBM_GETPOS = WM_USER +TBM_GETRANGEMIN = WM_USER + 1 +TBM_GETRANGEMAX = WM_USER + 2 +TBM_GETTIC = WM_USER + 3 +TBM_SETTIC = WM_USER + 4 +TBM_SETPOS = WM_USER + 5 +TBM_SETRANGE = WM_USER + 6 +TBM_SETRANGEMIN = WM_USER + 7 +TBM_SETRANGEMAX = WM_USER + 8 +TBM_CLEARTICS = WM_USER + 9 +TBM_SETSEL = WM_USER + 10 +TBM_SETSELSTART = WM_USER + 11 +TBM_SETSELEND = WM_USER + 12 +TBM_GETPTICS = WM_USER + 14 +TBM_GETTICPOS = WM_USER + 15 +TBM_GETNUMTICS = WM_USER + 16 +TBM_GETSELSTART = WM_USER + 17 +TBM_GETSELEND = WM_USER + 18 +TBM_CLEARSEL = WM_USER + 19 +TBM_SETTICFREQ = WM_USER + 20 +TBM_SETPAGESIZE = WM_USER + 21 +TBM_GETPAGESIZE = WM_USER + 22 +TBM_SETLINESIZE = WM_USER + 23 +TBM_GETLINESIZE = WM_USER + 24 +TBM_GETTHUMBRECT = WM_USER + 25 +TBM_GETCHANNELRECT = WM_USER + 26 +TBM_SETTHUMBLENGTH = WM_USER + 27 +TBM_GETTHUMBLENGTH = WM_USER + 28 +TBM_SETTOOLTIPS = WM_USER + 29 +TBM_GETTOOLTIPS = WM_USER + 30 +TBM_SETTIPSIDE = WM_USER + 31 +TBTS_TOP = 0 +TBTS_LEFT = 1 +TBTS_BOTTOM = 2 +TBTS_RIGHT = 3 +TBM_SETBUDDY = WM_USER + 32 # wparam = BOOL fLeft; (or right) +TBM_GETBUDDY = WM_USER + 33 # wparam = BOOL fLeft; (or right) +TBM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TBM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TB_LINEUP = 0 +TB_LINEDOWN = 1 +TB_PAGEUP = 2 +TB_PAGEDOWN = 3 +TB_THUMBPOSITION = 4 +TB_THUMBTRACK = 5 +TB_TOP = 6 +TB_BOTTOM = 7 +TB_ENDTRACK = 8 +TBCD_TICS = 1 +TBCD_THUMB = 2 +TBCD_CHANNEL = 3 +DL_BEGINDRAG = WM_USER + 133 +DL_DRAGGING = WM_USER + 134 +DL_DROPPED = WM_USER + 135 +DL_CANCELDRAG = WM_USER + 136 +DL_CURSORSET = 0 +DL_STOPCURSOR = 1 +DL_COPYCURSOR = 2 +DL_MOVECURSOR = 3 +DRAGLISTMSGSTRING = "commctrl_DragListMsg" +UPDOWN_CLASSA = "msctls_updown32" +UPDOWN_CLASS = UPDOWN_CLASSA +UD_MAXVAL = 32767 +UD_MINVAL = -UD_MAXVAL +UDS_WRAP = 1 +UDS_SETBUDDYINT = 2 +UDS_ALIGNRIGHT = 4 +UDS_ALIGNLEFT = 8 +UDS_AUTOBUDDY = 16 +UDS_ARROWKEYS = 32 +UDS_HORZ = 64 +UDS_NOTHOUSANDS = 128 +UDS_HOTTRACK = 256 +UDM_SETRANGE = WM_USER + 101 +UDM_GETRANGE = WM_USER + 102 +UDM_SETPOS = WM_USER + 103 +UDM_GETPOS = WM_USER + 104 +UDM_SETBUDDY = WM_USER + 105 +UDM_GETBUDDY = WM_USER + 106 +UDM_SETACCEL = WM_USER + 107 +UDM_GETACCEL = WM_USER + 108 +UDM_SETBASE = WM_USER + 109 +UDM_GETBASE = WM_USER + 110 +UDM_SETRANGE32 = WM_USER + 111 +UDM_GETRANGE32 = WM_USER + 112 # wParam & lParam are LPINT +UDM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +UDM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +UDN_DELTAPOS = UDN_FIRST - 1 +PROGRESS_CLASSA = "msctls_progress32" +PROGRESS_CLASS = PROGRESS_CLASSA +PBS_SMOOTH = 1 +PBS_VERTICAL = 4 +PBM_SETRANGE = WM_USER + 1 +PBM_SETPOS = WM_USER + 2 +PBM_DELTAPOS = WM_USER + 3 +PBM_SETSTEP = WM_USER + 4 +PBM_STEPIT = WM_USER + 5 +PBM_SETRANGE32 = WM_USER + 6 # lParam = high, wParam = low +PBM_GETRANGE = ( + WM_USER + 7 +) # wParam = return (TRUE ? low : high). lParam = PPBRANGE or NULL +PBM_GETPOS = WM_USER + 8 +PBM_SETBARCOLOR = WM_USER + 9 # lParam = bar color +PBM_SETBKCOLOR = CCM_SETBKCOLOR # lParam = bkColor +HOTKEYF_SHIFT = 1 +HOTKEYF_CONTROL = 2 +HOTKEYF_ALT = 4 +HOTKEYF_EXT = 8 +HKCOMB_NONE = 1 +HKCOMB_S = 2 +HKCOMB_C = 4 +HKCOMB_A = 8 +HKCOMB_SC = 16 +HKCOMB_SA = 32 +HKCOMB_CA = 64 +HKCOMB_SCA = 128 +HKM_SETHOTKEY = WM_USER + 1 +HKM_GETHOTKEY = WM_USER + 2 +HKM_SETRULES = WM_USER + 3 +HOTKEY_CLASSA = "msctls_hotkey32" +HOTKEY_CLASS = HOTKEY_CLASSA +CCS_TOP = 0x00000001 +CCS_NOMOVEY = 0x00000002 +CCS_BOTTOM = 0x00000003 +CCS_NORESIZE = 0x00000004 +CCS_NOPARENTALIGN = 0x00000008 +CCS_ADJUSTABLE = 0x00000020 +CCS_NODIVIDER = 0x00000040 +CCS_VERT = 0x00000080 +CCS_LEFT = CCS_VERT | CCS_TOP +CCS_RIGHT = CCS_VERT | CCS_BOTTOM +CCS_NOMOVEX = CCS_VERT | CCS_NOMOVEY +WC_LISTVIEWA = "SysListView32" +WC_LISTVIEW = WC_LISTVIEWA +LVS_ICON = 0 +LVS_REPORT = 1 +LVS_SMALLICON = 2 +LVS_LIST = 3 +LVS_TYPEMASK = 3 +LVS_SINGLESEL = 4 +LVS_SHOWSELALWAYS = 8 +LVS_SORTASCENDING = 16 +LVS_SORTDESCENDING = 32 +LVS_SHAREIMAGELISTS = 64 +LVS_NOLABELWRAP = 128 +LVS_AUTOARRANGE = 256 +LVS_EDITLABELS = 512 +LVS_OWNERDATA = 4096 +LVS_NOSCROLL = 8192 +LVS_TYPESTYLEMASK = 64512 +LVS_ALIGNTOP = 0 +LVS_ALIGNLEFT = 2048 +LVS_ALIGNMASK = 3072 +LVS_OWNERDRAWFIXED = 1024 +LVS_NOCOLUMNHEADER = 16384 +LVS_NOSORTHEADER = 32768 +LVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +LVM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +LVM_GETBKCOLOR = LVM_FIRST + 0 +LVM_SETBKCOLOR = LVM_FIRST + 1 +LVM_GETIMAGELIST = LVM_FIRST + 2 +LVSIL_NORMAL = 0 +LVSIL_SMALL = 1 +LVSIL_STATE = 2 +LVM_SETIMAGELIST = LVM_FIRST + 3 +LVM_GETITEMCOUNT = LVM_FIRST + 4 +LVIF_TEXT = 1 +LVIF_IMAGE = 2 +LVIF_PARAM = 4 +LVIF_STATE = 8 +LVIF_INDENT = 16 +LVIF_NORECOMPUTE = 2048 +LVIS_FOCUSED = 1 +LVIS_SELECTED = 2 +LVIS_CUT = 4 +LVIS_DROPHILITED = 8 +LVIS_ACTIVATING = 32 +LVIS_OVERLAYMASK = 3840 +LVIS_STATEIMAGEMASK = 61440 +I_INDENTCALLBACK = -1 +LPSTR_TEXTCALLBACKA = -1 +LPSTR_TEXTCALLBACK = LPSTR_TEXTCALLBACKA +I_IMAGECALLBACK = -1 +LVM_GETITEMA = LVM_FIRST + 5 +LVM_GETITEMW = LVM_FIRST + 75 +LVM_GETITEM = LVM_GETITEMA +LVM_SETITEMA = LVM_FIRST + 6 +LVM_SETITEMW = LVM_FIRST + 76 +LVM_SETITEM = LVM_SETITEMA +LVM_INSERTITEMA = LVM_FIRST + 7 +LVM_INSERTITEMW = LVM_FIRST + 77 +LVM_INSERTITEM = LVM_INSERTITEMA +LVM_DELETEITEM = LVM_FIRST + 8 +LVM_DELETEALLITEMS = LVM_FIRST + 9 +LVM_GETCALLBACKMASK = LVM_FIRST + 10 +LVM_SETCALLBACKMASK = LVM_FIRST + 11 +LVNI_ALL = 0 +LVNI_FOCUSED = 1 +LVNI_SELECTED = 2 +LVNI_CUT = 4 +LVNI_DROPHILITED = 8 +LVNI_ABOVE = 256 +LVNI_BELOW = 512 +LVNI_TOLEFT = 1024 +LVNI_TORIGHT = 2048 +LVM_GETNEXTITEM = LVM_FIRST + 12 +LVFI_PARAM = 1 +LVFI_STRING = 2 +LVFI_PARTIAL = 8 +LVFI_WRAP = 32 +LVFI_NEARESTXY = 64 +LVM_FINDITEMA = LVM_FIRST + 13 +LVM_FINDITEMW = LVM_FIRST + 83 +LVM_FINDITEM = LVM_FINDITEMA +LVIR_BOUNDS = 0 +LVIR_ICON = 1 +LVIR_LABEL = 2 +LVIR_SELECTBOUNDS = 3 +LVM_GETITEMRECT = LVM_FIRST + 14 +LVM_SETITEMPOSITION = LVM_FIRST + 15 +LVM_GETITEMPOSITION = LVM_FIRST + 16 +LVM_GETSTRINGWIDTHA = LVM_FIRST + 17 +LVM_GETSTRINGWIDTHW = LVM_FIRST + 87 +LVM_GETSTRINGWIDTH = LVM_GETSTRINGWIDTHA +LVHT_NOWHERE = 1 +LVHT_ONITEMICON = 2 +LVHT_ONITEMLABEL = 4 +LVHT_ONITEMSTATEICON = 8 +LVHT_ONITEM = LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON +LVHT_ABOVE = 8 +LVHT_BELOW = 16 +LVHT_TORIGHT = 32 +LVHT_TOLEFT = 64 +LVM_HITTEST = LVM_FIRST + 18 +LVM_ENSUREVISIBLE = LVM_FIRST + 19 +LVM_SCROLL = LVM_FIRST + 20 +LVM_REDRAWITEMS = LVM_FIRST + 21 +LVA_DEFAULT = 0 +LVA_ALIGNLEFT = 1 +LVA_ALIGNTOP = 2 +LVA_SNAPTOGRID = 5 +LVM_ARRANGE = LVM_FIRST + 22 +LVM_EDITLABELA = LVM_FIRST + 23 +LVM_EDITLABELW = LVM_FIRST + 118 +LVM_EDITLABEL = LVM_EDITLABELA +LVM_GETEDITCONTROL = LVM_FIRST + 24 +LVCF_FMT = 1 +LVCF_WIDTH = 2 +LVCF_TEXT = 4 +LVCF_SUBITEM = 8 +LVCF_IMAGE = 16 +LVCF_ORDER = 32 +LVCFMT_LEFT = 0 +LVCFMT_RIGHT = 1 +LVCFMT_CENTER = 2 +LVCFMT_JUSTIFYMASK = 3 +LVCFMT_IMAGE = 2048 +LVCFMT_BITMAP_ON_RIGHT = 4096 +LVCFMT_COL_HAS_IMAGES = 32768 +LVM_GETCOLUMNA = LVM_FIRST + 25 +LVM_GETCOLUMNW = LVM_FIRST + 95 +LVM_GETCOLUMN = LVM_GETCOLUMNA +LVM_SETCOLUMNA = LVM_FIRST + 26 +LVM_SETCOLUMNW = LVM_FIRST + 96 +LVM_SETCOLUMN = LVM_SETCOLUMNA +LVM_INSERTCOLUMNA = LVM_FIRST + 27 +LVM_INSERTCOLUMNW = LVM_FIRST + 97 +LVM_INSERTCOLUMN = LVM_INSERTCOLUMNA +LVM_DELETECOLUMN = LVM_FIRST + 28 +LVM_GETCOLUMNWIDTH = LVM_FIRST + 29 +LVSCW_AUTOSIZE = -1 +LVSCW_AUTOSIZE_USEHEADER = -2 +LVM_SETCOLUMNWIDTH = LVM_FIRST + 30 +LVM_GETHEADER = LVM_FIRST + 31 +LVM_CREATEDRAGIMAGE = LVM_FIRST + 33 +LVM_GETVIEWRECT = LVM_FIRST + 34 +LVM_GETTEXTCOLOR = LVM_FIRST + 35 +LVM_SETTEXTCOLOR = LVM_FIRST + 36 +LVM_GETTEXTBKCOLOR = LVM_FIRST + 37 +LVM_SETTEXTBKCOLOR = LVM_FIRST + 38 +LVM_GETTOPINDEX = LVM_FIRST + 39 +LVM_GETCOUNTPERPAGE = LVM_FIRST + 40 +LVM_GETORIGIN = LVM_FIRST + 41 +LVM_UPDATE = LVM_FIRST + 42 +LVM_SETITEMSTATE = LVM_FIRST + 43 +LVM_GETITEMSTATE = LVM_FIRST + 44 +LVM_GETITEMTEXTA = LVM_FIRST + 45 +LVM_GETITEMTEXTW = LVM_FIRST + 115 +LVM_GETITEMTEXT = LVM_GETITEMTEXTA +LVM_SETITEMTEXTA = LVM_FIRST + 46 +LVM_SETITEMTEXTW = LVM_FIRST + 116 +LVM_SETITEMTEXT = LVM_SETITEMTEXTA +LVSICF_NOINVALIDATEALL = 1 +LVSICF_NOSCROLL = 2 +LVM_SETITEMCOUNT = LVM_FIRST + 47 +LVM_SORTITEMS = LVM_FIRST + 48 +LVM_SETITEMPOSITION32 = LVM_FIRST + 49 +LVM_GETSELECTEDCOUNT = LVM_FIRST + 50 +LVM_GETITEMSPACING = LVM_FIRST + 51 +LVM_GETISEARCHSTRINGA = LVM_FIRST + 52 +LVM_GETISEARCHSTRINGW = LVM_FIRST + 117 +LVM_GETISEARCHSTRING = LVM_GETISEARCHSTRINGA +LVM_SETICONSPACING = LVM_FIRST + 53 +LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54 # optional wParam == mask +LVM_GETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 55 +LVS_EX_GRIDLINES = 1 +LVS_EX_SUBITEMIMAGES = 2 +LVS_EX_CHECKBOXES = 4 +LVS_EX_TRACKSELECT = 8 +LVS_EX_HEADERDRAGDROP = 16 +LVS_EX_FULLROWSELECT = 32 # applies to report mode only +LVS_EX_ONECLICKACTIVATE = 64 +LVS_EX_TWOCLICKACTIVATE = 128 +LVS_EX_FLATSB = 256 +LVS_EX_REGIONAL = 512 +LVS_EX_INFOTIP = 1024 # listview does InfoTips for you +LVS_EX_UNDERLINEHOT = 2048 +LVS_EX_UNDERLINECOLD = 4096 +LVS_EX_MULTIWORKAREAS = 8192 +LVM_GETSUBITEMRECT = LVM_FIRST + 56 +LVM_SUBITEMHITTEST = LVM_FIRST + 57 +LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58 +LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59 +LVM_SETHOTITEM = LVM_FIRST + 60 +LVM_GETHOTITEM = LVM_FIRST + 61 +LVM_SETHOTCURSOR = LVM_FIRST + 62 +LVM_GETHOTCURSOR = LVM_FIRST + 63 +LVM_APPROXIMATEVIEWRECT = LVM_FIRST + 64 +LV_MAX_WORKAREAS = 16 +LVM_SETWORKAREAS = LVM_FIRST + 65 +LVM_GETWORKAREAS = LVM_FIRST + 70 +LVM_GETNUMBEROFWORKAREAS = LVM_FIRST + 73 +LVM_GETSELECTIONMARK = LVM_FIRST + 66 +LVM_SETSELECTIONMARK = LVM_FIRST + 67 +LVM_SETHOVERTIME = LVM_FIRST + 71 +LVM_GETHOVERTIME = LVM_FIRST + 72 +LVM_SETTOOLTIPS = LVM_FIRST + 74 +LVM_GETTOOLTIPS = LVM_FIRST + 78 +LVBKIF_SOURCE_NONE = 0 +LVBKIF_SOURCE_HBITMAP = 1 +LVBKIF_SOURCE_URL = 2 +LVBKIF_SOURCE_MASK = 3 +LVBKIF_STYLE_NORMAL = 0 +LVBKIF_STYLE_TILE = 16 +LVBKIF_STYLE_MASK = 16 +LVM_SETBKIMAGEA = LVM_FIRST + 68 +LVM_SETBKIMAGEW = LVM_FIRST + 138 +LVM_GETBKIMAGEA = LVM_FIRST + 69 +LVM_GETBKIMAGEW = LVM_FIRST + 139 +LVKF_ALT = 1 +LVKF_CONTROL = 2 +LVKF_SHIFT = 4 +LVN_ITEMCHANGING = LVN_FIRST - 0 +LVN_ITEMCHANGED = LVN_FIRST - 1 +LVN_INSERTITEM = LVN_FIRST - 2 +LVN_DELETEITEM = LVN_FIRST - 3 +LVN_DELETEALLITEMS = LVN_FIRST - 4 +LVN_BEGINLABELEDITA = LVN_FIRST - 5 +LVN_BEGINLABELEDITW = LVN_FIRST - 75 +LVN_ENDLABELEDITA = LVN_FIRST - 6 +LVN_ENDLABELEDITW = LVN_FIRST - 76 +LVN_COLUMNCLICK = LVN_FIRST - 8 +LVN_BEGINDRAG = LVN_FIRST - 9 +LVN_BEGINRDRAG = LVN_FIRST - 11 +LVN_ODCACHEHINT = LVN_FIRST - 13 +LVN_ODFINDITEMA = LVN_FIRST - 52 +LVN_ODFINDITEMW = LVN_FIRST - 79 +LVN_ITEMACTIVATE = LVN_FIRST - 14 +LVN_ODSTATECHANGED = LVN_FIRST - 15 +LVN_ODFINDITEM = LVN_ODFINDITEMA +LVN_HOTTRACK = LVN_FIRST - 21 +LVN_GETDISPINFOA = LVN_FIRST - 50 +LVN_GETDISPINFOW = LVN_FIRST - 77 +LVN_SETDISPINFOA = LVN_FIRST - 51 +LVN_SETDISPINFOW = LVN_FIRST - 78 +LVN_BEGINLABELEDIT = LVN_BEGINLABELEDITA +LVN_ENDLABELEDIT = LVN_ENDLABELEDITA +LVN_GETDISPINFO = LVN_GETDISPINFOA +LVN_SETDISPINFO = LVN_SETDISPINFOA +LVIF_DI_SETITEM = 4096 +LVN_KEYDOWN = LVN_FIRST - 55 +LVN_MARQUEEBEGIN = LVN_FIRST - 56 +LVGIT_UNFOLDED = 1 +LVN_GETINFOTIPA = LVN_FIRST - 57 +LVN_GETINFOTIPW = LVN_FIRST - 58 +LVN_GETINFOTIP = LVN_GETINFOTIPA +WC_TREEVIEWA = "SysTreeView32" +WC_TREEVIEW = WC_TREEVIEWA +TVS_HASBUTTONS = 1 +TVS_HASLINES = 2 +TVS_LINESATROOT = 4 +TVS_EDITLABELS = 8 +TVS_DISABLEDRAGDROP = 16 +TVS_SHOWSELALWAYS = 32 +TVS_RTLREADING = 64 +TVS_NOTOOLTIPS = 128 +TVS_CHECKBOXES = 256 +TVS_TRACKSELECT = 512 +TVS_SINGLEEXPAND = 1024 +TVS_INFOTIP = 2048 +TVS_FULLROWSELECT = 4096 +TVS_NOSCROLL = 8192 +TVS_NONEVENHEIGHT = 16384 +TVIF_TEXT = 1 +TVIF_IMAGE = 2 +TVIF_PARAM = 4 +TVIF_STATE = 8 +TVIF_HANDLE = 16 +TVIF_SELECTEDIMAGE = 32 +TVIF_CHILDREN = 64 +TVIF_INTEGRAL = 128 +TVIS_SELECTED = 2 +TVIS_CUT = 4 +TVIS_DROPHILITED = 8 +TVIS_BOLD = 16 +TVIS_EXPANDED = 32 +TVIS_EXPANDEDONCE = 64 +TVIS_EXPANDPARTIAL = 128 +TVIS_OVERLAYMASK = 3840 +TVIS_STATEIMAGEMASK = 61440 +TVIS_USERMASK = 61440 +I_CHILDRENCALLBACK = -1 +TVI_ROOT = -65536 +TVI_FIRST = -65535 +TVI_LAST = -65534 +TVI_SORT = -65533 +TVM_INSERTITEMA = TV_FIRST + 0 +TVM_INSERTITEMW = TV_FIRST + 50 +TVM_INSERTITEM = TVM_INSERTITEMA +TVM_DELETEITEM = TV_FIRST + 1 +TVM_EXPAND = TV_FIRST + 2 +TVE_COLLAPSE = 1 +TVE_EXPAND = 2 +TVE_TOGGLE = 3 +TVE_EXPANDPARTIAL = 16384 +TVE_COLLAPSERESET = 32768 +TVM_GETITEMRECT = TV_FIRST + 4 +TVM_GETCOUNT = TV_FIRST + 5 +TVM_GETINDENT = TV_FIRST + 6 +TVM_SETINDENT = TV_FIRST + 7 +TVM_GETIMAGELIST = TV_FIRST + 8 +TVSIL_NORMAL = 0 +TVSIL_STATE = 2 +TVM_SETIMAGELIST = TV_FIRST + 9 +TVM_GETNEXTITEM = TV_FIRST + 10 +TVGN_ROOT = 0 +TVGN_NEXT = 1 +TVGN_PREVIOUS = 2 +TVGN_PARENT = 3 +TVGN_CHILD = 4 +TVGN_FIRSTVISIBLE = 5 +TVGN_NEXTVISIBLE = 6 +TVGN_PREVIOUSVISIBLE = 7 +TVGN_DROPHILITE = 8 +TVGN_CARET = 9 +TVGN_LASTVISIBLE = 10 +TVM_SELECTITEM = TV_FIRST + 11 +TVM_GETITEMA = TV_FIRST + 12 +TVM_GETITEMW = TV_FIRST + 62 +TVM_GETITEM = TVM_GETITEMA +TVM_SETITEMA = TV_FIRST + 13 +TVM_SETITEMW = TV_FIRST + 63 +TVM_SETITEM = TVM_SETITEMA +TVM_EDITLABELA = TV_FIRST + 14 +TVM_EDITLABELW = TV_FIRST + 65 +TVM_EDITLABEL = TVM_EDITLABELA +TVM_GETEDITCONTROL = TV_FIRST + 15 +TVM_GETVISIBLECOUNT = TV_FIRST + 16 +TVM_HITTEST = TV_FIRST + 17 +TVHT_NOWHERE = 1 +TVHT_ONITEMICON = 2 +TVHT_ONITEMLABEL = 4 +TVHT_ONITEMINDENT = 8 +TVHT_ONITEMBUTTON = 16 +TVHT_ONITEMRIGHT = 32 +TVHT_ONITEMSTATEICON = 64 +TVHT_ABOVE = 256 +TVHT_BELOW = 512 +TVHT_TORIGHT = 1024 +TVHT_TOLEFT = 2048 +TVHT_ONITEM = TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMSTATEICON +TVM_CREATEDRAGIMAGE = TV_FIRST + 18 +TVM_SORTCHILDREN = TV_FIRST + 19 +TVM_ENSUREVISIBLE = TV_FIRST + 20 +TVM_SORTCHILDRENCB = TV_FIRST + 21 +TVM_ENDEDITLABELNOW = TV_FIRST + 22 +TVM_GETISEARCHSTRINGA = TV_FIRST + 23 +TVM_GETISEARCHSTRINGW = TV_FIRST + 64 +TVM_GETISEARCHSTRING = TVM_GETISEARCHSTRINGA +TVM_SETTOOLTIPS = TV_FIRST + 24 +TVM_GETTOOLTIPS = TV_FIRST + 25 +TVM_SETINSERTMARK = TV_FIRST + 26 +TVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TVM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TVM_SETITEMHEIGHT = TV_FIRST + 27 +TVM_GETITEMHEIGHT = TV_FIRST + 28 +TVM_SETBKCOLOR = TV_FIRST + 29 +TVM_SETTEXTCOLOR = TV_FIRST + 30 +TVM_GETBKCOLOR = TV_FIRST + 31 +TVM_GETTEXTCOLOR = TV_FIRST + 32 +TVM_SETSCROLLTIME = TV_FIRST + 33 +TVM_GETSCROLLTIME = TV_FIRST + 34 +TVM_SETINSERTMARKCOLOR = TV_FIRST + 37 +TVM_GETINSERTMARKCOLOR = TV_FIRST + 38 +TVN_SELCHANGINGA = TVN_FIRST - 1 +TVN_SELCHANGINGW = TVN_FIRST - 50 +TVN_SELCHANGEDA = TVN_FIRST - 2 +TVN_SELCHANGEDW = TVN_FIRST - 51 +TVC_UNKNOWN = 0 +TVC_BYMOUSE = 1 +TVC_BYKEYBOARD = 2 +TVN_GETDISPINFOA = TVN_FIRST - 3 +TVN_GETDISPINFOW = TVN_FIRST - 52 +TVN_SETDISPINFOA = TVN_FIRST - 4 +TVN_SETDISPINFOW = TVN_FIRST - 53 +TVIF_DI_SETITEM = 4096 +TVN_ITEMEXPANDINGA = TVN_FIRST - 5 +TVN_ITEMEXPANDINGW = TVN_FIRST - 54 +TVN_ITEMEXPANDEDA = TVN_FIRST - 6 +TVN_ITEMEXPANDEDW = TVN_FIRST - 55 +TVN_BEGINDRAGA = TVN_FIRST - 7 +TVN_BEGINDRAGW = TVN_FIRST - 56 +TVN_BEGINRDRAGA = TVN_FIRST - 8 +TVN_BEGINRDRAGW = TVN_FIRST - 57 +TVN_DELETEITEMA = TVN_FIRST - 9 +TVN_DELETEITEMW = TVN_FIRST - 58 +TVN_BEGINLABELEDITA = TVN_FIRST - 10 +TVN_BEGINLABELEDITW = TVN_FIRST - 59 +TVN_ENDLABELEDITA = TVN_FIRST - 11 +TVN_ENDLABELEDITW = TVN_FIRST - 60 +TVN_KEYDOWN = TVN_FIRST - 12 +TVN_GETINFOTIPA = TVN_FIRST - 13 +TVN_GETINFOTIPW = TVN_FIRST - 14 +TVN_SINGLEEXPAND = TVN_FIRST - 15 +TVN_SELCHANGING = TVN_SELCHANGINGA +TVN_SELCHANGED = TVN_SELCHANGEDA +TVN_GETDISPINFO = TVN_GETDISPINFOA +TVN_SETDISPINFO = TVN_SETDISPINFOA +TVN_ITEMEXPANDING = TVN_ITEMEXPANDINGA +TVN_ITEMEXPANDED = TVN_ITEMEXPANDEDA +TVN_BEGINDRAG = TVN_BEGINDRAGA +TVN_BEGINRDRAG = TVN_BEGINRDRAGA +TVN_DELETEITEM = TVN_DELETEITEMA +TVN_BEGINLABELEDIT = TVN_BEGINLABELEDITA +TVN_ENDLABELEDIT = TVN_ENDLABELEDITA +TVN_GETINFOTIP = TVN_GETINFOTIPA +TVCDRF_NOIMAGES = 65536 +WC_COMBOBOXEXA = "ComboBoxEx32" +WC_COMBOBOXEX = WC_COMBOBOXEXA +CBEIF_TEXT = 1 +CBEIF_IMAGE = 2 +CBEIF_SELECTEDIMAGE = 4 +CBEIF_OVERLAY = 8 +CBEIF_INDENT = 16 +CBEIF_LPARAM = 32 +CBEIF_DI_SETITEM = 268435456 +CBEM_INSERTITEMA = WM_USER + 1 +CBEM_SETIMAGELIST = WM_USER + 2 +CBEM_GETIMAGELIST = WM_USER + 3 +CBEM_GETITEMA = WM_USER + 4 +CBEM_SETITEMA = WM_USER + 5 +# CBEM_DELETEITEM = CB_DELETESTRING +CBEM_GETCOMBOCONTROL = WM_USER + 6 +CBEM_GETEDITCONTROL = WM_USER + 7 +CBEM_SETEXSTYLE = WM_USER + 8 # use SETEXTENDEDSTYLE instead +CBEM_SETEXTENDEDSTYLE = WM_USER + 14 # lparam == new style, wParam (optional) == mask +CBEM_GETEXSTYLE = WM_USER + 9 # use GETEXTENDEDSTYLE instead +CBEM_GETEXTENDEDSTYLE = WM_USER + 9 +CBEM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +CBEM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +CBEM_HASEDITCHANGED = WM_USER + 10 +CBEM_INSERTITEMW = WM_USER + 11 +CBEM_SETITEMW = WM_USER + 12 +CBEM_GETITEMW = WM_USER + 13 +CBEM_INSERTITEM = CBEM_INSERTITEMA +CBEM_SETITEM = CBEM_SETITEMA +CBEM_GETITEM = CBEM_GETITEMA +CBES_EX_NOEDITIMAGE = 1 +CBES_EX_NOEDITIMAGEINDENT = 2 +CBES_EX_PATHWORDBREAKPROC = 4 +CBES_EX_NOSIZELIMIT = 8 +CBES_EX_CASESENSITIVE = 16 +CBEN_GETDISPINFO = CBEN_FIRST - 0 +CBEN_GETDISPINFOA = CBEN_FIRST - 0 +CBEN_INSERTITEM = CBEN_FIRST - 1 +CBEN_DELETEITEM = CBEN_FIRST - 2 +CBEN_BEGINEDIT = CBEN_FIRST - 4 +CBEN_ENDEDITA = CBEN_FIRST - 5 +CBEN_ENDEDITW = CBEN_FIRST - 6 +CBEN_GETDISPINFOW = CBEN_FIRST - 7 +CBEN_DRAGBEGINA = CBEN_FIRST - 8 +CBEN_DRAGBEGINW = CBEN_FIRST - 9 +CBEN_DRAGBEGIN = CBEN_DRAGBEGINA +CBEN_ENDEDIT = CBEN_ENDEDITA +CBENF_KILLFOCUS = 1 +CBENF_RETURN = 2 +CBENF_ESCAPE = 3 +CBENF_DROPDOWN = 4 +CBEMAXSTRLEN = 260 +WC_TABCONTROLA = "SysTabControl32" +WC_TABCONTROL = WC_TABCONTROLA +TCS_SCROLLOPPOSITE = 1 # assumes multiline tab +TCS_BOTTOM = 2 +TCS_RIGHT = 2 +TCS_MULTISELECT = 4 # allow multi-select in button mode +TCS_FLATBUTTONS = 8 +TCS_FORCEICONLEFT = 16 +TCS_FORCELABELLEFT = 32 +TCS_HOTTRACK = 64 +TCS_VERTICAL = 128 +TCS_TABS = 0 +TCS_BUTTONS = 256 +TCS_SINGLELINE = 0 +TCS_MULTILINE = 512 +TCS_RIGHTJUSTIFY = 0 +TCS_FIXEDWIDTH = 1024 +TCS_RAGGEDRIGHT = 2048 +TCS_FOCUSONBUTTONDOWN = 4096 +TCS_OWNERDRAWFIXED = 8192 +TCS_TOOLTIPS = 16384 +TCS_FOCUSNEVER = 32768 +TCS_EX_FLATSEPARATORS = 1 +TCS_EX_REGISTERDROP = 2 +TCM_GETIMAGELIST = TCM_FIRST + 2 +TCM_SETIMAGELIST = TCM_FIRST + 3 +TCM_GETITEMCOUNT = TCM_FIRST + 4 +TCIF_TEXT = 1 +TCIF_IMAGE = 2 +TCIF_RTLREADING = 4 +TCIF_PARAM = 8 +TCIF_STATE = 16 +TCIS_BUTTONPRESSED = 1 +TCIS_HIGHLIGHTED = 2 +TCM_GETITEMA = TCM_FIRST + 5 +TCM_GETITEMW = TCM_FIRST + 60 +TCM_GETITEM = TCM_GETITEMA +TCM_SETITEMA = TCM_FIRST + 6 +TCM_SETITEMW = TCM_FIRST + 61 +TCM_SETITEM = TCM_SETITEMA +TCM_INSERTITEMA = TCM_FIRST + 7 +TCM_INSERTITEMW = TCM_FIRST + 62 +TCM_INSERTITEM = TCM_INSERTITEMA +TCM_DELETEITEM = TCM_FIRST + 8 +TCM_DELETEALLITEMS = TCM_FIRST + 9 +TCM_GETITEMRECT = TCM_FIRST + 10 +TCM_GETCURSEL = TCM_FIRST + 11 +TCM_SETCURSEL = TCM_FIRST + 12 +TCHT_NOWHERE = 1 +TCHT_ONITEMICON = 2 +TCHT_ONITEMLABEL = 4 +TCHT_ONITEM = TCHT_ONITEMICON | TCHT_ONITEMLABEL +TCM_HITTEST = TCM_FIRST + 13 +TCM_SETITEMEXTRA = TCM_FIRST + 14 +TCM_ADJUSTRECT = TCM_FIRST + 40 +TCM_SETITEMSIZE = TCM_FIRST + 41 +TCM_REMOVEIMAGE = TCM_FIRST + 42 +TCM_SETPADDING = TCM_FIRST + 43 +TCM_GETROWCOUNT = TCM_FIRST + 44 +TCM_GETTOOLTIPS = TCM_FIRST + 45 +TCM_SETTOOLTIPS = TCM_FIRST + 46 +TCM_GETCURFOCUS = TCM_FIRST + 47 +TCM_SETCURFOCUS = TCM_FIRST + 48 +TCM_SETMINTABWIDTH = TCM_FIRST + 49 +TCM_DESELECTALL = TCM_FIRST + 50 +TCM_HIGHLIGHTITEM = TCM_FIRST + 51 +TCM_SETEXTENDEDSTYLE = TCM_FIRST + 52 # optional wParam == mask +TCM_GETEXTENDEDSTYLE = TCM_FIRST + 53 +TCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TCN_KEYDOWN = TCN_FIRST - 0 +ANIMATE_CLASSA = "SysAnimate32" +ANIMATE_CLASS = ANIMATE_CLASSA +ACS_CENTER = 1 +ACS_TRANSPARENT = 2 +ACS_AUTOPLAY = 4 +ACS_TIMER = 8 # don't use threads... use timers +ACM_OPENA = WM_USER + 100 +ACM_OPENW = WM_USER + 103 +ACM_OPEN = ACM_OPENA +ACM_PLAY = WM_USER + 101 +ACM_STOP = WM_USER + 102 +ACN_START = 1 +ACN_STOP = 2 +MONTHCAL_CLASSA = "SysMonthCal32" +MONTHCAL_CLASS = MONTHCAL_CLASSA +MCM_FIRST = 4096 +MCM_GETCURSEL = MCM_FIRST + 1 +MCM_SETCURSEL = MCM_FIRST + 2 +MCM_GETMAXSELCOUNT = MCM_FIRST + 3 +MCM_SETMAXSELCOUNT = MCM_FIRST + 4 +MCM_GETSELRANGE = MCM_FIRST + 5 +MCM_SETSELRANGE = MCM_FIRST + 6 +MCM_GETMONTHRANGE = MCM_FIRST + 7 +MCM_SETDAYSTATE = MCM_FIRST + 8 +MCM_GETMINREQRECT = MCM_FIRST + 9 +MCM_SETCOLOR = MCM_FIRST + 10 +MCM_GETCOLOR = MCM_FIRST + 11 +MCSC_BACKGROUND = 0 # the background color (between months) +MCSC_TEXT = 1 # the dates +MCSC_TITLEBK = 2 # background of the title +MCSC_TITLETEXT = 3 +MCSC_MONTHBK = 4 # background within the month cal +MCSC_TRAILINGTEXT = 5 # the text color of header & trailing days +MCM_SETTODAY = MCM_FIRST + 12 +MCM_GETTODAY = MCM_FIRST + 13 +MCM_HITTEST = MCM_FIRST + 14 +MCHT_TITLE = 65536 +MCHT_CALENDAR = 131072 +MCHT_TODAYLINK = 196608 +MCHT_NEXT = 16777216 # these indicate that hitting +MCHT_PREV = 33554432 # here will go to the next/prev month +MCHT_NOWHERE = 0 +MCHT_TITLEBK = MCHT_TITLE +MCHT_TITLEMONTH = MCHT_TITLE | 1 +MCHT_TITLEYEAR = MCHT_TITLE | 2 +MCHT_TITLEBTNNEXT = MCHT_TITLE | MCHT_NEXT | 3 +MCHT_TITLEBTNPREV = MCHT_TITLE | MCHT_PREV | 3 +MCHT_CALENDARBK = MCHT_CALENDAR +MCHT_CALENDARDATE = MCHT_CALENDAR | 1 +MCHT_CALENDARDATENEXT = MCHT_CALENDARDATE | MCHT_NEXT +MCHT_CALENDARDATEPREV = MCHT_CALENDARDATE | MCHT_PREV +MCHT_CALENDARDAY = MCHT_CALENDAR | 2 +MCHT_CALENDARWEEKNUM = MCHT_CALENDAR | 3 +MCM_SETFIRSTDAYOFWEEK = MCM_FIRST + 15 +MCM_GETFIRSTDAYOFWEEK = MCM_FIRST + 16 +MCM_GETRANGE = MCM_FIRST + 17 +MCM_SETRANGE = MCM_FIRST + 18 +MCM_GETMONTHDELTA = MCM_FIRST + 19 +MCM_SETMONTHDELTA = MCM_FIRST + 20 +MCM_GETMAXTODAYWIDTH = MCM_FIRST + 21 +MCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +MCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +MCN_SELCHANGE = MCN_FIRST + 1 +MCN_GETDAYSTATE = MCN_FIRST + 3 +MCN_SELECT = MCN_FIRST + 4 +MCS_DAYSTATE = 1 +MCS_MULTISELECT = 2 +MCS_WEEKNUMBERS = 4 +MCS_NOTODAYCIRCLE = 8 +MCS_NOTODAY = 8 +GMR_VISIBLE = 0 # visible portion of display +GMR_DAYSTATE = 1 # above plus the grayed out parts of +DATETIMEPICK_CLASSA = "SysDateTimePick32" +DATETIMEPICK_CLASS = DATETIMEPICK_CLASSA +DTM_FIRST = 4096 +DTM_GETSYSTEMTIME = DTM_FIRST + 1 +DTM_SETSYSTEMTIME = DTM_FIRST + 2 +DTM_GETRANGE = DTM_FIRST + 3 +DTM_SETRANGE = DTM_FIRST + 4 +DTM_SETFORMATA = DTM_FIRST + 5 +DTM_SETFORMATW = DTM_FIRST + 50 +DTM_SETFORMAT = DTM_SETFORMATA +DTM_SETMCCOLOR = DTM_FIRST + 6 +DTM_GETMCCOLOR = DTM_FIRST + 7 +DTM_GETMONTHCAL = DTM_FIRST + 8 +DTM_SETMCFONT = DTM_FIRST + 9 +DTM_GETMCFONT = DTM_FIRST + 10 +DTS_UPDOWN = 1 # use UPDOWN instead of MONTHCAL +DTS_SHOWNONE = 2 # allow a NONE selection +DTS_SHORTDATEFORMAT = ( + 0 # use the short date format (app must forward WM_WININICHANGE messages) +) +DTS_LONGDATEFORMAT = ( + 4 # use the long date format (app must forward WM_WININICHANGE messages) +) +DTS_TIMEFORMAT = 9 # use the time format (app must forward WM_WININICHANGE messages) +DTS_APPCANPARSE = 16 # allow user entered strings (app MUST respond to DTN_USERSTRING) +DTS_RIGHTALIGN = 32 # right-align popup instead of left-align it +DTN_DATETIMECHANGE = DTN_FIRST + 1 # the systemtime has changed +DTN_USERSTRINGA = DTN_FIRST + 2 # the user has entered a string +DTN_USERSTRINGW = DTN_FIRST + 15 +DTN_USERSTRING = DTN_USERSTRINGW +DTN_WMKEYDOWNA = DTN_FIRST + 3 # modify keydown on app format field (X) +DTN_WMKEYDOWNW = DTN_FIRST + 16 +DTN_WMKEYDOWN = DTN_WMKEYDOWNA +DTN_FORMATA = DTN_FIRST + 4 # query display for app format field (X) +DTN_FORMATW = DTN_FIRST + 17 +DTN_FORMAT = DTN_FORMATA +DTN_FORMATQUERYA = DTN_FIRST + 5 # query formatting info for app format field (X) +DTN_FORMATQUERYW = DTN_FIRST + 18 +DTN_FORMATQUERY = DTN_FORMATQUERYA +DTN_DROPDOWN = DTN_FIRST + 6 # MonthCal has dropped down +DTN_CLOSEUP = DTN_FIRST + 7 # MonthCal is popping up +GDTR_MIN = 1 +GDTR_MAX = 2 +GDT_ERROR = -1 +GDT_VALID = 0 +GDT_NONE = 1 +IPM_CLEARADDRESS = WM_USER + 100 # no parameters +IPM_SETADDRESS = WM_USER + 101 # lparam = TCP/IP address +IPM_GETADDRESS = ( + WM_USER + 102 +) # lresult = # of non black fields. lparam = LPDWORD for TCP/IP address +IPM_SETRANGE = WM_USER + 103 # wparam = field, lparam = range +IPM_SETFOCUS = WM_USER + 104 # wparam = field +IPM_ISBLANK = WM_USER + 105 # no parameters +WC_IPADDRESSA = "SysIPAddress32" +WC_IPADDRESS = WC_IPADDRESSA +IPN_FIELDCHANGED = IPN_FIRST - 0 +WC_PAGESCROLLERA = "SysPager" +WC_PAGESCROLLER = WC_PAGESCROLLERA +PGS_VERT = 0 +PGS_HORZ = 1 +PGS_AUTOSCROLL = 2 +PGS_DRAGNDROP = 4 +PGF_INVISIBLE = 0 # Scroll button is not visible +PGF_NORMAL = 1 # Scroll button is in normal state +PGF_GRAYED = 2 # Scroll button is in grayed state +PGF_DEPRESSED = 4 # Scroll button is in depressed state +PGF_HOT = 8 # Scroll button is in hot state +PGB_TOPORLEFT = 0 +PGB_BOTTOMORRIGHT = 1 +PGM_SETCHILD = PGM_FIRST + 1 # lParam == hwnd +PGM_RECALCSIZE = PGM_FIRST + 2 +PGM_FORWARDMOUSE = PGM_FIRST + 3 +PGM_SETBKCOLOR = PGM_FIRST + 4 +PGM_GETBKCOLOR = PGM_FIRST + 5 +PGM_SETBORDER = PGM_FIRST + 6 +PGM_GETBORDER = PGM_FIRST + 7 +PGM_SETPOS = PGM_FIRST + 8 +PGM_GETPOS = PGM_FIRST + 9 +PGM_SETBUTTONSIZE = PGM_FIRST + 10 +PGM_GETBUTTONSIZE = PGM_FIRST + 11 +PGM_GETBUTTONSTATE = PGM_FIRST + 12 +PGM_GETDROPTARGET = CCM_GETDROPTARGET +PGN_SCROLL = PGN_FIRST - 1 +PGF_SCROLLUP = 1 +PGF_SCROLLDOWN = 2 +PGF_SCROLLLEFT = 4 +PGF_SCROLLRIGHT = 8 +PGK_SHIFT = 1 +PGK_CONTROL = 2 +PGK_MENU = 4 +PGN_CALCSIZE = PGN_FIRST - 2 +PGF_CALCWIDTH = 1 +PGF_CALCHEIGHT = 2 +WC_NATIVEFONTCTLA = "NativeFontCtl" +WC_NATIVEFONTCTL = WC_NATIVEFONTCTLA +NFS_EDIT = 1 +NFS_STATIC = 2 +NFS_LISTCOMBO = 4 +NFS_BUTTON = 8 +NFS_ALL = 16 +WM_MOUSEHOVER = 673 +WM_MOUSELEAVE = 675 +TME_HOVER = 1 +TME_LEAVE = 2 +TME_QUERY = 1073741824 +TME_CANCEL = -2147483648 +HOVER_DEFAULT = -1 +WSB_PROP_CYVSCROLL = 0x00000001 +WSB_PROP_CXHSCROLL = 0x00000002 +WSB_PROP_CYHSCROLL = 0x00000004 +WSB_PROP_CXVSCROLL = 0x00000008 +WSB_PROP_CXHTHUMB = 0x00000010 +WSB_PROP_CYVTHUMB = 0x00000020 +WSB_PROP_VBKGCOLOR = 0x00000040 +WSB_PROP_HBKGCOLOR = 0x00000080 +WSB_PROP_VSTYLE = 0x00000100 +WSB_PROP_HSTYLE = 0x00000200 +WSB_PROP_WINSTYLE = 0x00000400 +WSB_PROP_PALETTE = 0x00000800 +WSB_PROP_MASK = 0x00000FFF +FSB_FLAT_MODE = 2 +FSB_ENCARTA_MODE = 1 +FSB_REGULAR_MODE = 0 + + +def INDEXTOOVERLAYMASK(i): + return i << 8 + + +def INDEXTOSTATEIMAGEMASK(i): + return i << 12 diff --git a/MLPY/Lib/site-packages/win32/lib/dbi.py b/MLPY/Lib/site-packages/win32/lib/dbi.py new file mode 100644 index 0000000000000000000000000000000000000000..c33d6721ea913180077e33af80e270a872978c8c --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/dbi.py @@ -0,0 +1,27 @@ +""" +Skeleton replacement for removed dbi module. +Use of objects created by this module should be replaced with native Python objects. +Dates are now returned as datetime.datetime objects, but will still accept PyTime +objects also. +Raw data for binary fields should be passed as buffer objects for Python 2.x, +and memoryview objects in Py3k. +""" + +import warnings + +warnings.warn( + "dbi module is obsolete, code should now use native python datetime and buffer/memoryview objects", + DeprecationWarning, +) + +import datetime + +dbDate = dbiDate = datetime.datetime + +try: + dbRaw = dbiRaw = buffer +except NameError: + dbRaw = dbiRaw = memoryview + +# type names are still exported by odbc module +from odbc import * diff --git a/MLPY/Lib/site-packages/win32/lib/mmsystem.py b/MLPY/Lib/site-packages/win32/lib/mmsystem.py new file mode 100644 index 0000000000000000000000000000000000000000..4d36b5efcf74e297817970591fea05816fb84ff8 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/mmsystem.py @@ -0,0 +1,954 @@ +# Generated by h2py from d:/msdev/include/mmsystem.h +MAXPNAMELEN = 32 +MAXERRORLENGTH = 256 +MAX_JOYSTICKOEMVXDNAME = 260 +MM_MICROSOFT = 1 +MM_MIDI_MAPPER = 1 +MM_WAVE_MAPPER = 2 +MM_SNDBLST_MIDIOUT = 3 +MM_SNDBLST_MIDIIN = 4 +MM_SNDBLST_SYNTH = 5 +MM_SNDBLST_WAVEOUT = 6 +MM_SNDBLST_WAVEIN = 7 +MM_ADLIB = 9 +MM_MPU401_MIDIOUT = 10 +MM_MPU401_MIDIIN = 11 +MM_PC_JOYSTICK = 12 +TIME_MS = 0x0001 +TIME_SAMPLES = 0x0002 +TIME_BYTES = 0x0004 +TIME_SMPTE = 0x0008 +TIME_MIDI = 0x0010 +TIME_TICKS = 0x0020 +MM_JOY1MOVE = 0x3A0 +MM_JOY2MOVE = 0x3A1 +MM_JOY1ZMOVE = 0x3A2 +MM_JOY2ZMOVE = 0x3A3 +MM_JOY1BUTTONDOWN = 0x3B5 +MM_JOY2BUTTONDOWN = 0x3B6 +MM_JOY1BUTTONUP = 0x3B7 +MM_JOY2BUTTONUP = 0x3B8 +MM_MCINOTIFY = 0x3B9 +MM_WOM_OPEN = 0x3BB +MM_WOM_CLOSE = 0x3BC +MM_WOM_DONE = 0x3BD +MM_WIM_OPEN = 0x3BE +MM_WIM_CLOSE = 0x3BF +MM_WIM_DATA = 0x3C0 +MM_MIM_OPEN = 0x3C1 +MM_MIM_CLOSE = 0x3C2 +MM_MIM_DATA = 0x3C3 +MM_MIM_LONGDATA = 0x3C4 +MM_MIM_ERROR = 0x3C5 +MM_MIM_LONGERROR = 0x3C6 +MM_MOM_OPEN = 0x3C7 +MM_MOM_CLOSE = 0x3C8 +MM_MOM_DONE = 0x3C9 +MM_STREAM_OPEN = 0x3D4 +MM_STREAM_CLOSE = 0x3D5 +MM_STREAM_DONE = 0x3D6 +MM_STREAM_ERROR = 0x3D7 +MM_MOM_POSITIONCB = 0x3CA +MM_MIM_MOREDATA = 0x3CC +MM_MIXM_LINE_CHANGE = 0x3D0 +MM_MIXM_CONTROL_CHANGE = 0x3D1 +MMSYSERR_BASE = 0 +WAVERR_BASE = 32 +MIDIERR_BASE = 64 +TIMERR_BASE = 96 +JOYERR_BASE = 160 +MCIERR_BASE = 256 +MIXERR_BASE = 1024 +MCI_STRING_OFFSET = 512 +MCI_VD_OFFSET = 1024 +MCI_CD_OFFSET = 1088 +MCI_WAVE_OFFSET = 1152 +MCI_SEQ_OFFSET = 1216 +MMSYSERR_NOERROR = 0 +MMSYSERR_ERROR = MMSYSERR_BASE + 1 +MMSYSERR_BADDEVICEID = MMSYSERR_BASE + 2 +MMSYSERR_NOTENABLED = MMSYSERR_BASE + 3 +MMSYSERR_ALLOCATED = MMSYSERR_BASE + 4 +MMSYSERR_INVALHANDLE = MMSYSERR_BASE + 5 +MMSYSERR_NODRIVER = MMSYSERR_BASE + 6 +MMSYSERR_NOMEM = MMSYSERR_BASE + 7 +MMSYSERR_NOTSUPPORTED = MMSYSERR_BASE + 8 +MMSYSERR_BADERRNUM = MMSYSERR_BASE + 9 +MMSYSERR_INVALFLAG = MMSYSERR_BASE + 10 +MMSYSERR_INVALPARAM = MMSYSERR_BASE + 11 +MMSYSERR_HANDLEBUSY = MMSYSERR_BASE + 12 +MMSYSERR_INVALIDALIAS = MMSYSERR_BASE + 13 +MMSYSERR_BADDB = MMSYSERR_BASE + 14 +MMSYSERR_KEYNOTFOUND = MMSYSERR_BASE + 15 +MMSYSERR_READERROR = MMSYSERR_BASE + 16 +MMSYSERR_WRITEERROR = MMSYSERR_BASE + 17 +MMSYSERR_DELETEERROR = MMSYSERR_BASE + 18 +MMSYSERR_VALNOTFOUND = MMSYSERR_BASE + 19 +MMSYSERR_NODRIVERCB = MMSYSERR_BASE + 20 +MMSYSERR_LASTERROR = MMSYSERR_BASE + 20 +DRV_LOAD = 0x0001 +DRV_ENABLE = 0x0002 +DRV_OPEN = 0x0003 +DRV_CLOSE = 0x0004 +DRV_DISABLE = 0x0005 +DRV_FREE = 0x0006 +DRV_CONFIGURE = 0x0007 +DRV_QUERYCONFIGURE = 0x0008 +DRV_INSTALL = 0x0009 +DRV_REMOVE = 0x000A +DRV_EXITSESSION = 0x000B +DRV_POWER = 0x000F +DRV_RESERVED = 0x0800 +DRV_USER = 0x4000 +DRVCNF_CANCEL = 0x0000 +DRVCNF_OK = 0x0001 +DRVCNF_RESTART = 0x0002 +DRV_CANCEL = DRVCNF_CANCEL +DRV_OK = DRVCNF_OK +DRV_RESTART = DRVCNF_RESTART +DRV_MCI_FIRST = DRV_RESERVED +DRV_MCI_LAST = DRV_RESERVED + 0xFFF +CALLBACK_TYPEMASK = 0x00070000 +CALLBACK_NULL = 0x00000000 +CALLBACK_WINDOW = 0x00010000 +CALLBACK_TASK = 0x00020000 +CALLBACK_FUNCTION = 0x00030000 +CALLBACK_THREAD = CALLBACK_TASK +CALLBACK_EVENT = 0x00050000 +SND_SYNC = 0x0000 +SND_ASYNC = 0x0001 +SND_NODEFAULT = 0x0002 +SND_MEMORY = 0x0004 +SND_LOOP = 0x0008 +SND_NOSTOP = 0x0010 +SND_NOWAIT = 0x00002000 +SND_ALIAS = 0x00010000 +SND_ALIAS_ID = 0x00110000 +SND_FILENAME = 0x00020000 +SND_RESOURCE = 0x00040004 +SND_PURGE = 0x0040 +SND_APPLICATION = 0x0080 +SND_ALIAS_START = 0 +WAVERR_BADFORMAT = WAVERR_BASE + 0 +WAVERR_STILLPLAYING = WAVERR_BASE + 1 +WAVERR_UNPREPARED = WAVERR_BASE + 2 +WAVERR_SYNC = WAVERR_BASE + 3 +WAVERR_LASTERROR = WAVERR_BASE + 3 +WOM_OPEN = MM_WOM_OPEN +WOM_CLOSE = MM_WOM_CLOSE +WOM_DONE = MM_WOM_DONE +WIM_OPEN = MM_WIM_OPEN +WIM_CLOSE = MM_WIM_CLOSE +WIM_DATA = MM_WIM_DATA +WAVE_MAPPER = -1 # 0xFFFFFFFF +WAVE_FORMAT_QUERY = 0x0001 +WAVE_ALLOWSYNC = 0x0002 +WAVE_MAPPED = 0x0004 +WAVE_FORMAT_DIRECT = 0x0008 +WAVE_FORMAT_DIRECT_QUERY = WAVE_FORMAT_QUERY | WAVE_FORMAT_DIRECT +WHDR_DONE = 0x00000001 +WHDR_PREPARED = 0x00000002 +WHDR_BEGINLOOP = 0x00000004 +WHDR_ENDLOOP = 0x00000008 +WHDR_INQUEUE = 0x00000010 +WAVECAPS_PITCH = 0x0001 +WAVECAPS_PLAYBACKRATE = 0x0002 +WAVECAPS_VOLUME = 0x0004 +WAVECAPS_LRVOLUME = 0x0008 +WAVECAPS_SYNC = 0x0010 +WAVECAPS_SAMPLEACCURATE = 0x0020 +WAVECAPS_DIRECTSOUND = 0x0040 +WAVE_INVALIDFORMAT = 0x00000000 +WAVE_FORMAT_1M08 = 0x00000001 +WAVE_FORMAT_1S08 = 0x00000002 +WAVE_FORMAT_1M16 = 0x00000004 +WAVE_FORMAT_1S16 = 0x00000008 +WAVE_FORMAT_2M08 = 0x00000010 +WAVE_FORMAT_2S08 = 0x00000020 +WAVE_FORMAT_2M16 = 0x00000040 +WAVE_FORMAT_2S16 = 0x00000080 +WAVE_FORMAT_4M08 = 0x00000100 +WAVE_FORMAT_4S08 = 0x00000200 +WAVE_FORMAT_4M16 = 0x00000400 +WAVE_FORMAT_4S16 = 0x00000800 +WAVE_FORMAT_PCM = 1 +WAVE_FORMAT_IEEE_FLOAT = 3 +MIDIERR_UNPREPARED = MIDIERR_BASE + 0 +MIDIERR_STILLPLAYING = MIDIERR_BASE + 1 +MIDIERR_NOMAP = MIDIERR_BASE + 2 +MIDIERR_NOTREADY = MIDIERR_BASE + 3 +MIDIERR_NODEVICE = MIDIERR_BASE + 4 +MIDIERR_INVALIDSETUP = MIDIERR_BASE + 5 +MIDIERR_BADOPENMODE = MIDIERR_BASE + 6 +MIDIERR_DONT_CONTINUE = MIDIERR_BASE + 7 +MIDIERR_LASTERROR = MIDIERR_BASE + 7 +MIDIPATCHSIZE = 128 +MIM_OPEN = MM_MIM_OPEN +MIM_CLOSE = MM_MIM_CLOSE +MIM_DATA = MM_MIM_DATA +MIM_LONGDATA = MM_MIM_LONGDATA +MIM_ERROR = MM_MIM_ERROR +MIM_LONGERROR = MM_MIM_LONGERROR +MOM_OPEN = MM_MOM_OPEN +MOM_CLOSE = MM_MOM_CLOSE +MOM_DONE = MM_MOM_DONE +MIM_MOREDATA = MM_MIM_MOREDATA +MOM_POSITIONCB = MM_MOM_POSITIONCB +MIDI_IO_STATUS = 0x00000020 +MIDI_CACHE_ALL = 1 +MIDI_CACHE_BESTFIT = 2 +MIDI_CACHE_QUERY = 3 +MIDI_UNCACHE = 4 +MOD_MIDIPORT = 1 +MOD_SYNTH = 2 +MOD_SQSYNTH = 3 +MOD_FMSYNTH = 4 +MOD_MAPPER = 5 +MIDICAPS_VOLUME = 0x0001 +MIDICAPS_LRVOLUME = 0x0002 +MIDICAPS_CACHE = 0x0004 +MIDICAPS_STREAM = 0x0008 +MHDR_DONE = 0x00000001 +MHDR_PREPARED = 0x00000002 +MHDR_INQUEUE = 0x00000004 +MHDR_ISSTRM = 0x00000008 +MEVT_F_SHORT = 0x00000000 +MEVT_F_LONG = -2147483648 # 0x80000000 +MEVT_F_CALLBACK = 0x40000000 + + +def MEVT_EVENTTYPE(x): + return (BYTE)(((x) >> 24) & 0xFF) + + +def MEVT_EVENTPARM(x): + return (DWORD)((x) & 0x00FFFFFF) + + +MIDISTRM_ERROR = -2 +MIDIPROP_SET = -2147483648 # 0x80000000 +MIDIPROP_GET = 0x40000000 +MIDIPROP_TIMEDIV = 0x00000001 +MIDIPROP_TEMPO = 0x00000002 +AUXCAPS_CDAUDIO = 1 +AUXCAPS_AUXIN = 2 +AUXCAPS_VOLUME = 0x0001 +AUXCAPS_LRVOLUME = 0x0002 +MIXER_SHORT_NAME_CHARS = 16 +MIXER_LONG_NAME_CHARS = 64 +MIXERR_INVALLINE = MIXERR_BASE + 0 +MIXERR_INVALCONTROL = MIXERR_BASE + 1 +MIXERR_INVALVALUE = MIXERR_BASE + 2 +MIXERR_LASTERROR = MIXERR_BASE + 2 +MIXER_OBJECTF_HANDLE = -2147483648 # 0x80000000 +MIXER_OBJECTF_MIXER = 0x00000000 +MIXER_OBJECTF_HMIXER = MIXER_OBJECTF_HANDLE | MIXER_OBJECTF_MIXER +MIXER_OBJECTF_WAVEOUT = 0x10000000 +MIXER_OBJECTF_HWAVEOUT = MIXER_OBJECTF_HANDLE | MIXER_OBJECTF_WAVEOUT +MIXER_OBJECTF_WAVEIN = 0x20000000 +MIXER_OBJECTF_HWAVEIN = MIXER_OBJECTF_HANDLE | MIXER_OBJECTF_WAVEIN +MIXER_OBJECTF_MIDIOUT = 0x30000000 +MIXER_OBJECTF_HMIDIOUT = MIXER_OBJECTF_HANDLE | MIXER_OBJECTF_MIDIOUT +MIXER_OBJECTF_MIDIIN = 0x40000000 +MIXER_OBJECTF_HMIDIIN = MIXER_OBJECTF_HANDLE | MIXER_OBJECTF_MIDIIN +MIXER_OBJECTF_AUX = 0x50000000 +MIXERLINE_LINEF_ACTIVE = 0x00000001 +MIXERLINE_LINEF_DISCONNECTED = 0x00008000 +MIXERLINE_LINEF_SOURCE = -2147483648 # 0x80000000 +MIXERLINE_COMPONENTTYPE_DST_FIRST = 0x00000000 +MIXERLINE_COMPONENTTYPE_DST_UNDEFINED = MIXERLINE_COMPONENTTYPE_DST_FIRST + 0 +MIXERLINE_COMPONENTTYPE_DST_DIGITAL = MIXERLINE_COMPONENTTYPE_DST_FIRST + 1 +MIXERLINE_COMPONENTTYPE_DST_LINE = MIXERLINE_COMPONENTTYPE_DST_FIRST + 2 +MIXERLINE_COMPONENTTYPE_DST_MONITOR = MIXERLINE_COMPONENTTYPE_DST_FIRST + 3 +MIXERLINE_COMPONENTTYPE_DST_SPEAKERS = MIXERLINE_COMPONENTTYPE_DST_FIRST + 4 +MIXERLINE_COMPONENTTYPE_DST_HEADPHONES = MIXERLINE_COMPONENTTYPE_DST_FIRST + 5 +MIXERLINE_COMPONENTTYPE_DST_TELEPHONE = MIXERLINE_COMPONENTTYPE_DST_FIRST + 6 +MIXERLINE_COMPONENTTYPE_DST_WAVEIN = MIXERLINE_COMPONENTTYPE_DST_FIRST + 7 +MIXERLINE_COMPONENTTYPE_DST_VOICEIN = MIXERLINE_COMPONENTTYPE_DST_FIRST + 8 +MIXERLINE_COMPONENTTYPE_DST_LAST = MIXERLINE_COMPONENTTYPE_DST_FIRST + 8 +MIXERLINE_COMPONENTTYPE_SRC_FIRST = 0x00001000 +MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 0 +MIXERLINE_COMPONENTTYPE_SRC_DIGITAL = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 1 +MIXERLINE_COMPONENTTYPE_SRC_LINE = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2 +MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3 +MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 4 +MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 5 +MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 6 +MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 7 +MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 8 +MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 9 +MIXERLINE_COMPONENTTYPE_SRC_ANALOG = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 10 +MIXERLINE_COMPONENTTYPE_SRC_LAST = MIXERLINE_COMPONENTTYPE_SRC_FIRST + 10 +MIXERLINE_TARGETTYPE_UNDEFINED = 0 +MIXERLINE_TARGETTYPE_WAVEOUT = 1 +MIXERLINE_TARGETTYPE_WAVEIN = 2 +MIXERLINE_TARGETTYPE_MIDIOUT = 3 +MIXERLINE_TARGETTYPE_MIDIIN = 4 +MIXERLINE_TARGETTYPE_AUX = 5 +MIXER_GETLINEINFOF_DESTINATION = 0x00000000 +MIXER_GETLINEINFOF_SOURCE = 0x00000001 +MIXER_GETLINEINFOF_LINEID = 0x00000002 +MIXER_GETLINEINFOF_COMPONENTTYPE = 0x00000003 +MIXER_GETLINEINFOF_TARGETTYPE = 0x00000004 +MIXER_GETLINEINFOF_QUERYMASK = 0x0000000F +MIXERCONTROL_CONTROLF_UNIFORM = 0x00000001 +MIXERCONTROL_CONTROLF_MULTIPLE = 0x00000002 +MIXERCONTROL_CONTROLF_DISABLED = -2147483648 # 0x80000000 +MIXERCONTROL_CT_CLASS_MASK = -268435456 # 0xF0000000 +MIXERCONTROL_CT_CLASS_CUSTOM = 0x00000000 +MIXERCONTROL_CT_CLASS_METER = 0x10000000 +MIXERCONTROL_CT_CLASS_SWITCH = 0x20000000 +MIXERCONTROL_CT_CLASS_NUMBER = 0x30000000 +MIXERCONTROL_CT_CLASS_SLIDER = 0x40000000 +MIXERCONTROL_CT_CLASS_FADER = 0x50000000 +MIXERCONTROL_CT_CLASS_TIME = 0x60000000 +MIXERCONTROL_CT_CLASS_LIST = 0x70000000 +MIXERCONTROL_CT_SUBCLASS_MASK = 0x0F000000 +MIXERCONTROL_CT_SC_SWITCH_BOOLEAN = 0x00000000 +MIXERCONTROL_CT_SC_SWITCH_BUTTON = 0x01000000 +MIXERCONTROL_CT_SC_METER_POLLED = 0x00000000 +MIXERCONTROL_CT_SC_TIME_MICROSECS = 0x00000000 +MIXERCONTROL_CT_SC_TIME_MILLISECS = 0x01000000 +MIXERCONTROL_CT_SC_LIST_SINGLE = 0x00000000 +MIXERCONTROL_CT_SC_LIST_MULTIPLE = 0x01000000 +MIXERCONTROL_CT_UNITS_MASK = 0x00FF0000 +MIXERCONTROL_CT_UNITS_CUSTOM = 0x00000000 +MIXERCONTROL_CT_UNITS_BOOLEAN = 0x00010000 +MIXERCONTROL_CT_UNITS_SIGNED = 0x00020000 +MIXERCONTROL_CT_UNITS_UNSIGNED = 0x00030000 +MIXERCONTROL_CT_UNITS_DECIBELS = 0x00040000 +MIXERCONTROL_CT_UNITS_PERCENT = 0x00050000 +MIXERCONTROL_CONTROLTYPE_CUSTOM = ( + MIXERCONTROL_CT_CLASS_CUSTOM | MIXERCONTROL_CT_UNITS_CUSTOM +) +MIXERCONTROL_CONTROLTYPE_BOOLEANMETER = ( + MIXERCONTROL_CT_CLASS_METER + | MIXERCONTROL_CT_SC_METER_POLLED + | MIXERCONTROL_CT_UNITS_BOOLEAN +) +MIXERCONTROL_CONTROLTYPE_SIGNEDMETER = ( + MIXERCONTROL_CT_CLASS_METER + | MIXERCONTROL_CT_SC_METER_POLLED + | MIXERCONTROL_CT_UNITS_SIGNED +) +MIXERCONTROL_CONTROLTYPE_PEAKMETER = MIXERCONTROL_CONTROLTYPE_SIGNEDMETER + 1 +MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER = ( + MIXERCONTROL_CT_CLASS_METER + | MIXERCONTROL_CT_SC_METER_POLLED + | MIXERCONTROL_CT_UNITS_UNSIGNED +) +MIXERCONTROL_CONTROLTYPE_BOOLEAN = ( + MIXERCONTROL_CT_CLASS_SWITCH + | MIXERCONTROL_CT_SC_SWITCH_BOOLEAN + | MIXERCONTROL_CT_UNITS_BOOLEAN +) +MIXERCONTROL_CONTROLTYPE_ONOFF = MIXERCONTROL_CONTROLTYPE_BOOLEAN + 1 +MIXERCONTROL_CONTROLTYPE_MUTE = MIXERCONTROL_CONTROLTYPE_BOOLEAN + 2 +MIXERCONTROL_CONTROLTYPE_MONO = MIXERCONTROL_CONTROLTYPE_BOOLEAN + 3 +MIXERCONTROL_CONTROLTYPE_LOUDNESS = MIXERCONTROL_CONTROLTYPE_BOOLEAN + 4 +MIXERCONTROL_CONTROLTYPE_STEREOENH = MIXERCONTROL_CONTROLTYPE_BOOLEAN + 5 +MIXERCONTROL_CONTROLTYPE_BUTTON = ( + MIXERCONTROL_CT_CLASS_SWITCH + | MIXERCONTROL_CT_SC_SWITCH_BUTTON + | MIXERCONTROL_CT_UNITS_BOOLEAN +) +MIXERCONTROL_CONTROLTYPE_DECIBELS = ( + MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_DECIBELS +) +MIXERCONTROL_CONTROLTYPE_SIGNED = ( + MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_SIGNED +) +MIXERCONTROL_CONTROLTYPE_UNSIGNED = ( + MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_UNSIGNED +) +MIXERCONTROL_CONTROLTYPE_PERCENT = ( + MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_PERCENT +) +MIXERCONTROL_CONTROLTYPE_SLIDER = ( + MIXERCONTROL_CT_CLASS_SLIDER | MIXERCONTROL_CT_UNITS_SIGNED +) +MIXERCONTROL_CONTROLTYPE_PAN = MIXERCONTROL_CONTROLTYPE_SLIDER + 1 +MIXERCONTROL_CONTROLTYPE_QSOUNDPAN = MIXERCONTROL_CONTROLTYPE_SLIDER + 2 +MIXERCONTROL_CONTROLTYPE_FADER = ( + MIXERCONTROL_CT_CLASS_FADER | MIXERCONTROL_CT_UNITS_UNSIGNED +) +MIXERCONTROL_CONTROLTYPE_VOLUME = MIXERCONTROL_CONTROLTYPE_FADER + 1 +MIXERCONTROL_CONTROLTYPE_BASS = MIXERCONTROL_CONTROLTYPE_FADER + 2 +MIXERCONTROL_CONTROLTYPE_TREBLE = MIXERCONTROL_CONTROLTYPE_FADER + 3 +MIXERCONTROL_CONTROLTYPE_EQUALIZER = MIXERCONTROL_CONTROLTYPE_FADER + 4 +MIXERCONTROL_CONTROLTYPE_SINGLESELECT = ( + MIXERCONTROL_CT_CLASS_LIST + | MIXERCONTROL_CT_SC_LIST_SINGLE + | MIXERCONTROL_CT_UNITS_BOOLEAN +) +MIXERCONTROL_CONTROLTYPE_MUX = MIXERCONTROL_CONTROLTYPE_SINGLESELECT + 1 +MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT = ( + MIXERCONTROL_CT_CLASS_LIST + | MIXERCONTROL_CT_SC_LIST_MULTIPLE + | MIXERCONTROL_CT_UNITS_BOOLEAN +) +MIXERCONTROL_CONTROLTYPE_MIXER = MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT + 1 +MIXERCONTROL_CONTROLTYPE_MICROTIME = ( + MIXERCONTROL_CT_CLASS_TIME + | MIXERCONTROL_CT_SC_TIME_MICROSECS + | MIXERCONTROL_CT_UNITS_UNSIGNED +) +MIXERCONTROL_CONTROLTYPE_MILLITIME = ( + MIXERCONTROL_CT_CLASS_TIME + | MIXERCONTROL_CT_SC_TIME_MILLISECS + | MIXERCONTROL_CT_UNITS_UNSIGNED +) +MIXER_GETLINECONTROLSF_ALL = 0x00000000 +MIXER_GETLINECONTROLSF_ONEBYID = 0x00000001 +MIXER_GETLINECONTROLSF_ONEBYTYPE = 0x00000002 +MIXER_GETLINECONTROLSF_QUERYMASK = 0x0000000F +MIXER_GETCONTROLDETAILSF_VALUE = 0x00000000 +MIXER_GETCONTROLDETAILSF_LISTTEXT = 0x00000001 +MIXER_GETCONTROLDETAILSF_QUERYMASK = 0x0000000F +MIXER_SETCONTROLDETAILSF_VALUE = 0x00000000 +MIXER_SETCONTROLDETAILSF_CUSTOM = 0x00000001 +MIXER_SETCONTROLDETAILSF_QUERYMASK = 0x0000000F +TIMERR_NOERROR = 0 +TIMERR_NOCANDO = TIMERR_BASE + 1 +TIMERR_STRUCT = TIMERR_BASE + 33 +TIME_ONESHOT = 0x0000 +TIME_PERIODIC = 0x0001 +TIME_CALLBACK_FUNCTION = 0x0000 +TIME_CALLBACK_EVENT_SET = 0x0010 +TIME_CALLBACK_EVENT_PULSE = 0x0020 +JOYERR_NOERROR = 0 +JOYERR_PARMS = JOYERR_BASE + 5 +JOYERR_NOCANDO = JOYERR_BASE + 6 +JOYERR_UNPLUGGED = JOYERR_BASE + 7 +JOY_BUTTON1 = 0x0001 +JOY_BUTTON2 = 0x0002 +JOY_BUTTON3 = 0x0004 +JOY_BUTTON4 = 0x0008 +JOY_BUTTON1CHG = 0x0100 +JOY_BUTTON2CHG = 0x0200 +JOY_BUTTON3CHG = 0x0400 +JOY_BUTTON4CHG = 0x0800 +JOY_BUTTON5 = 0x00000010 +JOY_BUTTON6 = 0x00000020 +JOY_BUTTON7 = 0x00000040 +JOY_BUTTON8 = 0x00000080 +JOY_BUTTON9 = 0x00000100 +JOY_BUTTON10 = 0x00000200 +JOY_BUTTON11 = 0x00000400 +JOY_BUTTON12 = 0x00000800 +JOY_BUTTON13 = 0x00001000 +JOY_BUTTON14 = 0x00002000 +JOY_BUTTON15 = 0x00004000 +JOY_BUTTON16 = 0x00008000 +JOY_BUTTON17 = 0x00010000 +JOY_BUTTON18 = 0x00020000 +JOY_BUTTON19 = 0x00040000 +JOY_BUTTON20 = 0x00080000 +JOY_BUTTON21 = 0x00100000 +JOY_BUTTON22 = 0x00200000 +JOY_BUTTON23 = 0x00400000 +JOY_BUTTON24 = 0x00800000 +JOY_BUTTON25 = 0x01000000 +JOY_BUTTON26 = 0x02000000 +JOY_BUTTON27 = 0x04000000 +JOY_BUTTON28 = 0x08000000 +JOY_BUTTON29 = 0x10000000 +JOY_BUTTON30 = 0x20000000 +JOY_BUTTON31 = 0x40000000 +JOY_BUTTON32 = -2147483648 # 0x80000000 +JOY_POVFORWARD = 0 +JOY_POVRIGHT = 9000 +JOY_POVBACKWARD = 18000 +JOY_POVLEFT = 27000 +JOY_RETURNX = 0x00000001 +JOY_RETURNY = 0x00000002 +JOY_RETURNZ = 0x00000004 +JOY_RETURNR = 0x00000008 +JOY_RETURNU = 0x00000010 +JOY_RETURNV = 0x00000020 +JOY_RETURNPOV = 0x00000040 +JOY_RETURNBUTTONS = 0x00000080 +JOY_RETURNRAWDATA = 0x00000100 +JOY_RETURNPOVCTS = 0x00000200 +JOY_RETURNCENTERED = 0x00000400 +JOY_USEDEADZONE = 0x00000800 +JOY_RETURNALL = ( + JOY_RETURNX + | JOY_RETURNY + | JOY_RETURNZ + | JOY_RETURNR + | JOY_RETURNU + | JOY_RETURNV + | JOY_RETURNPOV + | JOY_RETURNBUTTONS +) +JOY_CAL_READALWAYS = 0x00010000 +JOY_CAL_READXYONLY = 0x00020000 +JOY_CAL_READ3 = 0x00040000 +JOY_CAL_READ4 = 0x00080000 +JOY_CAL_READXONLY = 0x00100000 +JOY_CAL_READYONLY = 0x00200000 +JOY_CAL_READ5 = 0x00400000 +JOY_CAL_READ6 = 0x00800000 +JOY_CAL_READZONLY = 0x01000000 +JOY_CAL_READRONLY = 0x02000000 +JOY_CAL_READUONLY = 0x04000000 +JOY_CAL_READVONLY = 0x08000000 +JOYSTICKID1 = 0 +JOYSTICKID2 = 1 +JOYCAPS_HASZ = 0x0001 +JOYCAPS_HASR = 0x0002 +JOYCAPS_HASU = 0x0004 +JOYCAPS_HASV = 0x0008 +JOYCAPS_HASPOV = 0x0010 +JOYCAPS_POV4DIR = 0x0020 +JOYCAPS_POVCTS = 0x0040 +MMIOERR_BASE = 256 +MMIOERR_FILENOTFOUND = MMIOERR_BASE + 1 +MMIOERR_OUTOFMEMORY = MMIOERR_BASE + 2 +MMIOERR_CANNOTOPEN = MMIOERR_BASE + 3 +MMIOERR_CANNOTCLOSE = MMIOERR_BASE + 4 +MMIOERR_CANNOTREAD = MMIOERR_BASE + 5 +MMIOERR_CANNOTWRITE = MMIOERR_BASE + 6 +MMIOERR_CANNOTSEEK = MMIOERR_BASE + 7 +MMIOERR_CANNOTEXPAND = MMIOERR_BASE + 8 +MMIOERR_CHUNKNOTFOUND = MMIOERR_BASE + 9 +MMIOERR_UNBUFFERED = MMIOERR_BASE + 10 +MMIOERR_PATHNOTFOUND = MMIOERR_BASE + 11 +MMIOERR_ACCESSDENIED = MMIOERR_BASE + 12 +MMIOERR_SHARINGVIOLATION = MMIOERR_BASE + 13 +MMIOERR_NETWORKERROR = MMIOERR_BASE + 14 +MMIOERR_TOOMANYOPENFILES = MMIOERR_BASE + 15 +MMIOERR_INVALIDFILE = MMIOERR_BASE + 16 +CFSEPCHAR = ord("+") +MMIO_RWMODE = 0x00000003 +MMIO_SHAREMODE = 0x00000070 +MMIO_CREATE = 0x00001000 +MMIO_PARSE = 0x00000100 +MMIO_DELETE = 0x00000200 +MMIO_EXIST = 0x00004000 +MMIO_ALLOCBUF = 0x00010000 +MMIO_GETTEMP = 0x00020000 +MMIO_DIRTY = 0x10000000 +MMIO_READ = 0x00000000 +MMIO_WRITE = 0x00000001 +MMIO_READWRITE = 0x00000002 +MMIO_COMPAT = 0x00000000 +MMIO_EXCLUSIVE = 0x00000010 +MMIO_DENYWRITE = 0x00000020 +MMIO_DENYREAD = 0x00000030 +MMIO_DENYNONE = 0x00000040 +MMIO_FHOPEN = 0x0010 +MMIO_EMPTYBUF = 0x0010 +MMIO_TOUPPER = 0x0010 +MMIO_INSTALLPROC = 0x00010000 +MMIO_GLOBALPROC = 0x10000000 +MMIO_REMOVEPROC = 0x00020000 +MMIO_UNICODEPROC = 0x01000000 +MMIO_FINDPROC = 0x00040000 +MMIO_FINDCHUNK = 0x0010 +MMIO_FINDRIFF = 0x0020 +MMIO_FINDLIST = 0x0040 +MMIO_CREATERIFF = 0x0020 +MMIO_CREATELIST = 0x0040 +MMIOM_READ = MMIO_READ +MMIOM_WRITE = MMIO_WRITE +MMIOM_SEEK = 2 +MMIOM_OPEN = 3 +MMIOM_CLOSE = 4 +MMIOM_WRITEFLUSH = 5 +MMIOM_RENAME = 6 +MMIOM_USER = 0x8000 +SEEK_SET = 0 +SEEK_CUR = 1 +SEEK_END = 2 +MMIO_DEFAULTBUFFER = 8192 +MCIERR_INVALID_DEVICE_ID = MCIERR_BASE + 1 +MCIERR_UNRECOGNIZED_KEYWORD = MCIERR_BASE + 3 +MCIERR_UNRECOGNIZED_COMMAND = MCIERR_BASE + 5 +MCIERR_HARDWARE = MCIERR_BASE + 6 +MCIERR_INVALID_DEVICE_NAME = MCIERR_BASE + 7 +MCIERR_OUT_OF_MEMORY = MCIERR_BASE + 8 +MCIERR_DEVICE_OPEN = MCIERR_BASE + 9 +MCIERR_CANNOT_LOAD_DRIVER = MCIERR_BASE + 10 +MCIERR_MISSING_COMMAND_STRING = MCIERR_BASE + 11 +MCIERR_PARAM_OVERFLOW = MCIERR_BASE + 12 +MCIERR_MISSING_STRING_ARGUMENT = MCIERR_BASE + 13 +MCIERR_BAD_INTEGER = MCIERR_BASE + 14 +MCIERR_PARSER_INTERNAL = MCIERR_BASE + 15 +MCIERR_DRIVER_INTERNAL = MCIERR_BASE + 16 +MCIERR_MISSING_PARAMETER = MCIERR_BASE + 17 +MCIERR_UNSUPPORTED_FUNCTION = MCIERR_BASE + 18 +MCIERR_FILE_NOT_FOUND = MCIERR_BASE + 19 +MCIERR_DEVICE_NOT_READY = MCIERR_BASE + 20 +MCIERR_INTERNAL = MCIERR_BASE + 21 +MCIERR_DRIVER = MCIERR_BASE + 22 +MCIERR_CANNOT_USE_ALL = MCIERR_BASE + 23 +MCIERR_MULTIPLE = MCIERR_BASE + 24 +MCIERR_EXTENSION_NOT_FOUND = MCIERR_BASE + 25 +MCIERR_OUTOFRANGE = MCIERR_BASE + 26 +MCIERR_FLAGS_NOT_COMPATIBLE = MCIERR_BASE + 28 +MCIERR_FILE_NOT_SAVED = MCIERR_BASE + 30 +MCIERR_DEVICE_TYPE_REQUIRED = MCIERR_BASE + 31 +MCIERR_DEVICE_LOCKED = MCIERR_BASE + 32 +MCIERR_DUPLICATE_ALIAS = MCIERR_BASE + 33 +MCIERR_BAD_CONSTANT = MCIERR_BASE + 34 +MCIERR_MUST_USE_SHAREABLE = MCIERR_BASE + 35 +MCIERR_MISSING_DEVICE_NAME = MCIERR_BASE + 36 +MCIERR_BAD_TIME_FORMAT = MCIERR_BASE + 37 +MCIERR_NO_CLOSING_QUOTE = MCIERR_BASE + 38 +MCIERR_DUPLICATE_FLAGS = MCIERR_BASE + 39 +MCIERR_INVALID_FILE = MCIERR_BASE + 40 +MCIERR_NULL_PARAMETER_BLOCK = MCIERR_BASE + 41 +MCIERR_UNNAMED_RESOURCE = MCIERR_BASE + 42 +MCIERR_NEW_REQUIRES_ALIAS = MCIERR_BASE + 43 +MCIERR_NOTIFY_ON_AUTO_OPEN = MCIERR_BASE + 44 +MCIERR_NO_ELEMENT_ALLOWED = MCIERR_BASE + 45 +MCIERR_NONAPPLICABLE_FUNCTION = MCIERR_BASE + 46 +MCIERR_ILLEGAL_FOR_AUTO_OPEN = MCIERR_BASE + 47 +MCIERR_FILENAME_REQUIRED = MCIERR_BASE + 48 +MCIERR_EXTRA_CHARACTERS = MCIERR_BASE + 49 +MCIERR_DEVICE_NOT_INSTALLED = MCIERR_BASE + 50 +MCIERR_GET_CD = MCIERR_BASE + 51 +MCIERR_SET_CD = MCIERR_BASE + 52 +MCIERR_SET_DRIVE = MCIERR_BASE + 53 +MCIERR_DEVICE_LENGTH = MCIERR_BASE + 54 +MCIERR_DEVICE_ORD_LENGTH = MCIERR_BASE + 55 +MCIERR_NO_INTEGER = MCIERR_BASE + 56 +MCIERR_WAVE_OUTPUTSINUSE = MCIERR_BASE + 64 +MCIERR_WAVE_SETOUTPUTINUSE = MCIERR_BASE + 65 +MCIERR_WAVE_INPUTSINUSE = MCIERR_BASE + 66 +MCIERR_WAVE_SETINPUTINUSE = MCIERR_BASE + 67 +MCIERR_WAVE_OUTPUTUNSPECIFIED = MCIERR_BASE + 68 +MCIERR_WAVE_INPUTUNSPECIFIED = MCIERR_BASE + 69 +MCIERR_WAVE_OUTPUTSUNSUITABLE = MCIERR_BASE + 70 +MCIERR_WAVE_SETOUTPUTUNSUITABLE = MCIERR_BASE + 71 +MCIERR_WAVE_INPUTSUNSUITABLE = MCIERR_BASE + 72 +MCIERR_WAVE_SETINPUTUNSUITABLE = MCIERR_BASE + 73 +MCIERR_SEQ_DIV_INCOMPATIBLE = MCIERR_BASE + 80 +MCIERR_SEQ_PORT_INUSE = MCIERR_BASE + 81 +MCIERR_SEQ_PORT_NONEXISTENT = MCIERR_BASE + 82 +MCIERR_SEQ_PORT_MAPNODEVICE = MCIERR_BASE + 83 +MCIERR_SEQ_PORT_MISCERROR = MCIERR_BASE + 84 +MCIERR_SEQ_TIMER = MCIERR_BASE + 85 +MCIERR_SEQ_PORTUNSPECIFIED = MCIERR_BASE + 86 +MCIERR_SEQ_NOMIDIPRESENT = MCIERR_BASE + 87 +MCIERR_NO_WINDOW = MCIERR_BASE + 90 +MCIERR_CREATEWINDOW = MCIERR_BASE + 91 +MCIERR_FILE_READ = MCIERR_BASE + 92 +MCIERR_FILE_WRITE = MCIERR_BASE + 93 +MCIERR_NO_IDENTITY = MCIERR_BASE + 94 +MCIERR_CUSTOM_DRIVER_BASE = MCIERR_BASE + 256 +MCI_FIRST = DRV_MCI_FIRST +MCI_OPEN = 0x0803 +MCI_CLOSE = 0x0804 +MCI_ESCAPE = 0x0805 +MCI_PLAY = 0x0806 +MCI_SEEK = 0x0807 +MCI_STOP = 0x0808 +MCI_PAUSE = 0x0809 +MCI_INFO = 0x080A +MCI_GETDEVCAPS = 0x080B +MCI_SPIN = 0x080C +MCI_SET = 0x080D +MCI_STEP = 0x080E +MCI_RECORD = 0x080F +MCI_SYSINFO = 0x0810 +MCI_BREAK = 0x0811 +MCI_SAVE = 0x0813 +MCI_STATUS = 0x0814 +MCI_CUE = 0x0830 +MCI_REALIZE = 0x0840 +MCI_WINDOW = 0x0841 +MCI_PUT = 0x0842 +MCI_WHERE = 0x0843 +MCI_FREEZE = 0x0844 +MCI_UNFREEZE = 0x0845 +MCI_LOAD = 0x0850 +MCI_CUT = 0x0851 +MCI_COPY = 0x0852 +MCI_PASTE = 0x0853 +MCI_UPDATE = 0x0854 +MCI_RESUME = 0x0855 +MCI_DELETE = 0x0856 +MCI_USER_MESSAGES = DRV_MCI_FIRST + 0x400 +MCI_LAST = 0x0FFF +MCI_DEVTYPE_VCR = 513 +MCI_DEVTYPE_VIDEODISC = 514 +MCI_DEVTYPE_OVERLAY = 515 +MCI_DEVTYPE_CD_AUDIO = 516 +MCI_DEVTYPE_DAT = 517 +MCI_DEVTYPE_SCANNER = 518 +MCI_DEVTYPE_ANIMATION = 519 +MCI_DEVTYPE_DIGITAL_VIDEO = 520 +MCI_DEVTYPE_OTHER = 521 +MCI_DEVTYPE_WAVEFORM_AUDIO = 522 +MCI_DEVTYPE_SEQUENCER = 523 +MCI_DEVTYPE_FIRST = MCI_DEVTYPE_VCR +MCI_DEVTYPE_LAST = MCI_DEVTYPE_SEQUENCER +MCI_DEVTYPE_FIRST_USER = 0x1000 +MCI_MODE_NOT_READY = MCI_STRING_OFFSET + 12 +MCI_MODE_STOP = MCI_STRING_OFFSET + 13 +MCI_MODE_PLAY = MCI_STRING_OFFSET + 14 +MCI_MODE_RECORD = MCI_STRING_OFFSET + 15 +MCI_MODE_SEEK = MCI_STRING_OFFSET + 16 +MCI_MODE_PAUSE = MCI_STRING_OFFSET + 17 +MCI_MODE_OPEN = MCI_STRING_OFFSET + 18 +MCI_FORMAT_MILLISECONDS = 0 +MCI_FORMAT_HMS = 1 +MCI_FORMAT_MSF = 2 +MCI_FORMAT_FRAMES = 3 +MCI_FORMAT_SMPTE_24 = 4 +MCI_FORMAT_SMPTE_25 = 5 +MCI_FORMAT_SMPTE_30 = 6 +MCI_FORMAT_SMPTE_30DROP = 7 +MCI_FORMAT_BYTES = 8 +MCI_FORMAT_SAMPLES = 9 +MCI_FORMAT_TMSF = 10 + + +def MCI_MSF_MINUTE(msf): + return (BYTE)(msf) + + +def MCI_MSF_SECOND(msf): + return (BYTE)(((WORD)(msf)) >> 8) + + +def MCI_MSF_FRAME(msf): + return (BYTE)((msf) >> 16) + + +def MCI_TMSF_TRACK(tmsf): + return (BYTE)(tmsf) + + +def MCI_TMSF_MINUTE(tmsf): + return (BYTE)(((WORD)(tmsf)) >> 8) + + +def MCI_TMSF_SECOND(tmsf): + return (BYTE)((tmsf) >> 16) + + +def MCI_TMSF_FRAME(tmsf): + return (BYTE)((tmsf) >> 24) + + +def MCI_HMS_HOUR(hms): + return (BYTE)(hms) + + +def MCI_HMS_MINUTE(hms): + return (BYTE)(((WORD)(hms)) >> 8) + + +def MCI_HMS_SECOND(hms): + return (BYTE)((hms) >> 16) + + +MCI_NOTIFY_SUCCESSFUL = 0x0001 +MCI_NOTIFY_SUPERSEDED = 0x0002 +MCI_NOTIFY_ABORTED = 0x0004 +MCI_NOTIFY_FAILURE = 0x0008 +MCI_NOTIFY = 0x00000001 +MCI_WAIT = 0x00000002 +MCI_FROM = 0x00000004 +MCI_TO = 0x00000008 +MCI_TRACK = 0x00000010 +MCI_OPEN_SHAREABLE = 0x00000100 +MCI_OPEN_ELEMENT = 0x00000200 +MCI_OPEN_ALIAS = 0x00000400 +MCI_OPEN_ELEMENT_ID = 0x00000800 +MCI_OPEN_TYPE_ID = 0x00001000 +MCI_OPEN_TYPE = 0x00002000 +MCI_SEEK_TO_START = 0x00000100 +MCI_SEEK_TO_END = 0x00000200 +MCI_STATUS_ITEM = 0x00000100 +MCI_STATUS_START = 0x00000200 +MCI_STATUS_LENGTH = 0x00000001 +MCI_STATUS_POSITION = 0x00000002 +MCI_STATUS_NUMBER_OF_TRACKS = 0x00000003 +MCI_STATUS_MODE = 0x00000004 +MCI_STATUS_MEDIA_PRESENT = 0x00000005 +MCI_STATUS_TIME_FORMAT = 0x00000006 +MCI_STATUS_READY = 0x00000007 +MCI_STATUS_CURRENT_TRACK = 0x00000008 +MCI_INFO_PRODUCT = 0x00000100 +MCI_INFO_FILE = 0x00000200 +MCI_INFO_MEDIA_UPC = 0x00000400 +MCI_INFO_MEDIA_IDENTITY = 0x00000800 +MCI_INFO_NAME = 0x00001000 +MCI_INFO_COPYRIGHT = 0x00002000 +MCI_GETDEVCAPS_ITEM = 0x00000100 +MCI_GETDEVCAPS_CAN_RECORD = 0x00000001 +MCI_GETDEVCAPS_HAS_AUDIO = 0x00000002 +MCI_GETDEVCAPS_HAS_VIDEO = 0x00000003 +MCI_GETDEVCAPS_DEVICE_TYPE = 0x00000004 +MCI_GETDEVCAPS_USES_FILES = 0x00000005 +MCI_GETDEVCAPS_COMPOUND_DEVICE = 0x00000006 +MCI_GETDEVCAPS_CAN_EJECT = 0x00000007 +MCI_GETDEVCAPS_CAN_PLAY = 0x00000008 +MCI_GETDEVCAPS_CAN_SAVE = 0x00000009 +MCI_SYSINFO_QUANTITY = 0x00000100 +MCI_SYSINFO_OPEN = 0x00000200 +MCI_SYSINFO_NAME = 0x00000400 +MCI_SYSINFO_INSTALLNAME = 0x00000800 +MCI_SET_DOOR_OPEN = 0x00000100 +MCI_SET_DOOR_CLOSED = 0x00000200 +MCI_SET_TIME_FORMAT = 0x00000400 +MCI_SET_AUDIO = 0x00000800 +MCI_SET_VIDEO = 0x00001000 +MCI_SET_ON = 0x00002000 +MCI_SET_OFF = 0x00004000 +MCI_SET_AUDIO_ALL = 0x00000000 +MCI_SET_AUDIO_LEFT = 0x00000001 +MCI_SET_AUDIO_RIGHT = 0x00000002 +MCI_BREAK_KEY = 0x00000100 +MCI_BREAK_HWND = 0x00000200 +MCI_BREAK_OFF = 0x00000400 +MCI_RECORD_INSERT = 0x00000100 +MCI_RECORD_OVERWRITE = 0x00000200 +MCI_SAVE_FILE = 0x00000100 +MCI_LOAD_FILE = 0x00000100 +MCI_VD_MODE_PARK = MCI_VD_OFFSET + 1 +MCI_VD_MEDIA_CLV = MCI_VD_OFFSET + 2 +MCI_VD_MEDIA_CAV = MCI_VD_OFFSET + 3 +MCI_VD_MEDIA_OTHER = MCI_VD_OFFSET + 4 +MCI_VD_FORMAT_TRACK = 0x4001 +MCI_VD_PLAY_REVERSE = 0x00010000 +MCI_VD_PLAY_FAST = 0x00020000 +MCI_VD_PLAY_SPEED = 0x00040000 +MCI_VD_PLAY_SCAN = 0x00080000 +MCI_VD_PLAY_SLOW = 0x00100000 +MCI_VD_SEEK_REVERSE = 0x00010000 +MCI_VD_STATUS_SPEED = 0x00004002 +MCI_VD_STATUS_FORWARD = 0x00004003 +MCI_VD_STATUS_MEDIA_TYPE = 0x00004004 +MCI_VD_STATUS_SIDE = 0x00004005 +MCI_VD_STATUS_DISC_SIZE = 0x00004006 +MCI_VD_GETDEVCAPS_CLV = 0x00010000 +MCI_VD_GETDEVCAPS_CAV = 0x00020000 +MCI_VD_SPIN_UP = 0x00010000 +MCI_VD_SPIN_DOWN = 0x00020000 +MCI_VD_GETDEVCAPS_CAN_REVERSE = 0x00004002 +MCI_VD_GETDEVCAPS_FAST_RATE = 0x00004003 +MCI_VD_GETDEVCAPS_SLOW_RATE = 0x00004004 +MCI_VD_GETDEVCAPS_NORMAL_RATE = 0x00004005 +MCI_VD_STEP_FRAMES = 0x00010000 +MCI_VD_STEP_REVERSE = 0x00020000 +MCI_VD_ESCAPE_STRING = 0x00000100 +MCI_CDA_STATUS_TYPE_TRACK = 0x00004001 +MCI_CDA_TRACK_AUDIO = MCI_CD_OFFSET + 0 +MCI_CDA_TRACK_OTHER = MCI_CD_OFFSET + 1 +MCI_WAVE_PCM = MCI_WAVE_OFFSET + 0 +MCI_WAVE_MAPPER = MCI_WAVE_OFFSET + 1 +MCI_WAVE_OPEN_BUFFER = 0x00010000 +MCI_WAVE_SET_FORMATTAG = 0x00010000 +MCI_WAVE_SET_CHANNELS = 0x00020000 +MCI_WAVE_SET_SAMPLESPERSEC = 0x00040000 +MCI_WAVE_SET_AVGBYTESPERSEC = 0x00080000 +MCI_WAVE_SET_BLOCKALIGN = 0x00100000 +MCI_WAVE_SET_BITSPERSAMPLE = 0x00200000 +MCI_WAVE_INPUT = 0x00400000 +MCI_WAVE_OUTPUT = 0x00800000 +MCI_WAVE_STATUS_FORMATTAG = 0x00004001 +MCI_WAVE_STATUS_CHANNELS = 0x00004002 +MCI_WAVE_STATUS_SAMPLESPERSEC = 0x00004003 +MCI_WAVE_STATUS_AVGBYTESPERSEC = 0x00004004 +MCI_WAVE_STATUS_BLOCKALIGN = 0x00004005 +MCI_WAVE_STATUS_BITSPERSAMPLE = 0x00004006 +MCI_WAVE_STATUS_LEVEL = 0x00004007 +MCI_WAVE_SET_ANYINPUT = 0x04000000 +MCI_WAVE_SET_ANYOUTPUT = 0x08000000 +MCI_WAVE_GETDEVCAPS_INPUTS = 0x00004001 +MCI_WAVE_GETDEVCAPS_OUTPUTS = 0x00004002 +MCI_SEQ_DIV_PPQN = 0 + MCI_SEQ_OFFSET +MCI_SEQ_DIV_SMPTE_24 = 1 + MCI_SEQ_OFFSET +MCI_SEQ_DIV_SMPTE_25 = 2 + MCI_SEQ_OFFSET +MCI_SEQ_DIV_SMPTE_30DROP = 3 + MCI_SEQ_OFFSET +MCI_SEQ_DIV_SMPTE_30 = 4 + MCI_SEQ_OFFSET +MCI_SEQ_FORMAT_SONGPTR = 0x4001 +MCI_SEQ_FILE = 0x4002 +MCI_SEQ_MIDI = 0x4003 +MCI_SEQ_SMPTE = 0x4004 +MCI_SEQ_NONE = 65533 +MCI_SEQ_MAPPER = 65535 +MCI_SEQ_STATUS_TEMPO = 0x00004002 +MCI_SEQ_STATUS_PORT = 0x00004003 +MCI_SEQ_STATUS_SLAVE = 0x00004007 +MCI_SEQ_STATUS_MASTER = 0x00004008 +MCI_SEQ_STATUS_OFFSET = 0x00004009 +MCI_SEQ_STATUS_DIVTYPE = 0x0000400A +MCI_SEQ_STATUS_NAME = 0x0000400B +MCI_SEQ_STATUS_COPYRIGHT = 0x0000400C +MCI_SEQ_SET_TEMPO = 0x00010000 +MCI_SEQ_SET_PORT = 0x00020000 +MCI_SEQ_SET_SLAVE = 0x00040000 +MCI_SEQ_SET_MASTER = 0x00080000 +MCI_SEQ_SET_OFFSET = 0x01000000 +MCI_ANIM_OPEN_WS = 0x00010000 +MCI_ANIM_OPEN_PARENT = 0x00020000 +MCI_ANIM_OPEN_NOSTATIC = 0x00040000 +MCI_ANIM_PLAY_SPEED = 0x00010000 +MCI_ANIM_PLAY_REVERSE = 0x00020000 +MCI_ANIM_PLAY_FAST = 0x00040000 +MCI_ANIM_PLAY_SLOW = 0x00080000 +MCI_ANIM_PLAY_SCAN = 0x00100000 +MCI_ANIM_STEP_REVERSE = 0x00010000 +MCI_ANIM_STEP_FRAMES = 0x00020000 +MCI_ANIM_STATUS_SPEED = 0x00004001 +MCI_ANIM_STATUS_FORWARD = 0x00004002 +MCI_ANIM_STATUS_HWND = 0x00004003 +MCI_ANIM_STATUS_HPAL = 0x00004004 +MCI_ANIM_STATUS_STRETCH = 0x00004005 +MCI_ANIM_INFO_TEXT = 0x00010000 +MCI_ANIM_GETDEVCAPS_CAN_REVERSE = 0x00004001 +MCI_ANIM_GETDEVCAPS_FAST_RATE = 0x00004002 +MCI_ANIM_GETDEVCAPS_SLOW_RATE = 0x00004003 +MCI_ANIM_GETDEVCAPS_NORMAL_RATE = 0x00004004 +MCI_ANIM_GETDEVCAPS_PALETTES = 0x00004006 +MCI_ANIM_GETDEVCAPS_CAN_STRETCH = 0x00004007 +MCI_ANIM_GETDEVCAPS_MAX_WINDOWS = 0x00004008 +MCI_ANIM_REALIZE_NORM = 0x00010000 +MCI_ANIM_REALIZE_BKGD = 0x00020000 +MCI_ANIM_WINDOW_HWND = 0x00010000 +MCI_ANIM_WINDOW_STATE = 0x00040000 +MCI_ANIM_WINDOW_TEXT = 0x00080000 +MCI_ANIM_WINDOW_ENABLE_STRETCH = 0x00100000 +MCI_ANIM_WINDOW_DISABLE_STRETCH = 0x00200000 +MCI_ANIM_WINDOW_DEFAULT = 0x00000000 +MCI_ANIM_RECT = 0x00010000 +MCI_ANIM_PUT_SOURCE = 0x00020000 +MCI_ANIM_PUT_DESTINATION = 0x00040000 +MCI_ANIM_WHERE_SOURCE = 0x00020000 +MCI_ANIM_WHERE_DESTINATION = 0x00040000 +MCI_ANIM_UPDATE_HDC = 0x00020000 +MCI_OVLY_OPEN_WS = 0x00010000 +MCI_OVLY_OPEN_PARENT = 0x00020000 +MCI_OVLY_STATUS_HWND = 0x00004001 +MCI_OVLY_STATUS_STRETCH = 0x00004002 +MCI_OVLY_INFO_TEXT = 0x00010000 +MCI_OVLY_GETDEVCAPS_CAN_STRETCH = 0x00004001 +MCI_OVLY_GETDEVCAPS_CAN_FREEZE = 0x00004002 +MCI_OVLY_GETDEVCAPS_MAX_WINDOWS = 0x00004003 +MCI_OVLY_WINDOW_HWND = 0x00010000 +MCI_OVLY_WINDOW_STATE = 0x00040000 +MCI_OVLY_WINDOW_TEXT = 0x00080000 +MCI_OVLY_WINDOW_ENABLE_STRETCH = 0x00100000 +MCI_OVLY_WINDOW_DISABLE_STRETCH = 0x00200000 +MCI_OVLY_WINDOW_DEFAULT = 0x00000000 +MCI_OVLY_RECT = 0x00010000 +MCI_OVLY_PUT_SOURCE = 0x00020000 +MCI_OVLY_PUT_DESTINATION = 0x00040000 +MCI_OVLY_PUT_FRAME = 0x00080000 +MCI_OVLY_PUT_VIDEO = 0x00100000 +MCI_OVLY_WHERE_SOURCE = 0x00020000 +MCI_OVLY_WHERE_DESTINATION = 0x00040000 +MCI_OVLY_WHERE_FRAME = 0x00080000 +MCI_OVLY_WHERE_VIDEO = 0x00100000 +SELECTDIB = 41 + + +def DIBINDEX(n): + return MAKELONG((n), 0x10FF) diff --git a/MLPY/Lib/site-packages/win32/lib/netbios.py b/MLPY/Lib/site-packages/win32/lib/netbios.py new file mode 100644 index 0000000000000000000000000000000000000000..dca4dee67929b1ba720bee2025b28fe660b7fa6c --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/netbios.py @@ -0,0 +1,304 @@ +import struct +import sys + +import win32wnet + +# Constants generated by h2py from nb30.h +NCBNAMSZ = 16 +MAX_LANA = 254 +NAME_FLAGS_MASK = 0x87 +GROUP_NAME = 0x80 +UNIQUE_NAME = 0x00 +REGISTERING = 0x00 +REGISTERED = 0x04 +DEREGISTERED = 0x05 +DUPLICATE = 0x06 +DUPLICATE_DEREG = 0x07 +LISTEN_OUTSTANDING = 0x01 +CALL_PENDING = 0x02 +SESSION_ESTABLISHED = 0x03 +HANGUP_PENDING = 0x04 +HANGUP_COMPLETE = 0x05 +SESSION_ABORTED = 0x06 +ALL_TRANSPORTS = "M\0\0\0" +MS_NBF = "MNBF" +NCBCALL = 0x10 +NCBLISTEN = 0x11 +NCBHANGUP = 0x12 +NCBSEND = 0x14 +NCBRECV = 0x15 +NCBRECVANY = 0x16 +NCBCHAINSEND = 0x17 +NCBDGSEND = 0x20 +NCBDGRECV = 0x21 +NCBDGSENDBC = 0x22 +NCBDGRECVBC = 0x23 +NCBADDNAME = 0x30 +NCBDELNAME = 0x31 +NCBRESET = 0x32 +NCBASTAT = 0x33 +NCBSSTAT = 0x34 +NCBCANCEL = 0x35 +NCBADDGRNAME = 0x36 +NCBENUM = 0x37 +NCBUNLINK = 0x70 +NCBSENDNA = 0x71 +NCBCHAINSENDNA = 0x72 +NCBLANSTALERT = 0x73 +NCBACTION = 0x77 +NCBFINDNAME = 0x78 +NCBTRACE = 0x79 +ASYNCH = 0x80 +NRC_GOODRET = 0x00 +NRC_BUFLEN = 0x01 +NRC_ILLCMD = 0x03 +NRC_CMDTMO = 0x05 +NRC_INCOMP = 0x06 +NRC_BADDR = 0x07 +NRC_SNUMOUT = 0x08 +NRC_NORES = 0x09 +NRC_SCLOSED = 0x0A +NRC_CMDCAN = 0x0B +NRC_DUPNAME = 0x0D +NRC_NAMTFUL = 0x0E +NRC_ACTSES = 0x0F +NRC_LOCTFUL = 0x11 +NRC_REMTFUL = 0x12 +NRC_ILLNN = 0x13 +NRC_NOCALL = 0x14 +NRC_NOWILD = 0x15 +NRC_INUSE = 0x16 +NRC_NAMERR = 0x17 +NRC_SABORT = 0x18 +NRC_NAMCONF = 0x19 +NRC_IFBUSY = 0x21 +NRC_TOOMANY = 0x22 +NRC_BRIDGE = 0x23 +NRC_CANOCCR = 0x24 +NRC_CANCEL = 0x26 +NRC_DUPENV = 0x30 +NRC_ENVNOTDEF = 0x34 +NRC_OSRESNOTAV = 0x35 +NRC_MAXAPPS = 0x36 +NRC_NOSAPS = 0x37 +NRC_NORESOURCES = 0x38 +NRC_INVADDRESS = 0x39 +NRC_INVDDID = 0x3B +NRC_LOCKFAIL = 0x3C +NRC_OPENERR = 0x3F +NRC_SYSTEM = 0x40 +NRC_PENDING = 0xFF + + +UCHAR = "B" +WORD = "H" +DWORD = "I" +USHORT = "H" +ULONG = "I" + +ADAPTER_STATUS_ITEMS = [ + ("6s", "adapter_address"), + (UCHAR, "rev_major"), + (UCHAR, "reserved0"), + (UCHAR, "adapter_type"), + (UCHAR, "rev_minor"), + (WORD, "duration"), + (WORD, "frmr_recv"), + (WORD, "frmr_xmit"), + (WORD, "iframe_recv_err"), + (WORD, "xmit_aborts"), + (DWORD, "xmit_success"), + (DWORD, "recv_success"), + (WORD, "iframe_xmit_err"), + (WORD, "recv_buff_unavail"), + (WORD, "t1_timeouts"), + (WORD, "ti_timeouts"), + (DWORD, "reserved1"), + (WORD, "free_ncbs"), + (WORD, "max_cfg_ncbs"), + (WORD, "max_ncbs"), + (WORD, "xmit_buf_unavail"), + (WORD, "max_dgram_size"), + (WORD, "pending_sess"), + (WORD, "max_cfg_sess"), + (WORD, "max_sess"), + (WORD, "max_sess_pkt_size"), + (WORD, "name_count"), +] + +NAME_BUFFER_ITEMS = [ + (str(NCBNAMSZ) + "s", "name"), + (UCHAR, "name_num"), + (UCHAR, "name_flags"), +] + +SESSION_HEADER_ITEMS = [ + (UCHAR, "sess_name"), + (UCHAR, "num_sess"), + (UCHAR, "rcv_dg_outstanding"), + (UCHAR, "rcv_any_outstanding"), +] + +SESSION_BUFFER_ITEMS = [ + (UCHAR, "lsn"), + (UCHAR, "state"), + (str(NCBNAMSZ) + "s", "local_name"), + (str(NCBNAMSZ) + "s", "remote_name"), + (UCHAR, "rcvs_outstanding"), + (UCHAR, "sends_outstanding"), +] + +LANA_ENUM_ITEMS = [ + ("B", "length"), # Number of valid entries in lana[] + (str(MAX_LANA + 1) + "s", "lana"), +] + +FIND_NAME_HEADER_ITEMS = [ + (WORD, "node_count"), + (UCHAR, "reserved"), + (UCHAR, "unique_group"), +] + +FIND_NAME_BUFFER_ITEMS = [ + (UCHAR, "length"), + (UCHAR, "access_control"), + (UCHAR, "frame_control"), + ("6s", "destination_addr"), + ("6s", "source_addr"), + ("18s", "routing_info"), +] + +ACTION_HEADER_ITEMS = [ + (ULONG, "transport_id"), + (USHORT, "action_code"), + (USHORT, "reserved"), +] + +del UCHAR, WORD, DWORD, USHORT, ULONG + +NCB = win32wnet.NCB + + +def Netbios(ncb): + ob = ncb.Buffer + is_ours = hasattr(ob, "_pack") + if is_ours: + ob._pack() + try: + return win32wnet.Netbios(ncb) + finally: + if is_ours: + ob._unpack() + + +class NCBStruct: + def __init__(self, items): + self._format = "".join([item[0] for item in items]) + self._items = items + self._buffer_ = win32wnet.NCBBuffer(struct.calcsize(self._format)) + + for format, name in self._items: + if len(format) == 1: + if format == "c": + val = "\0" + else: + val = 0 + else: + l = int(format[:-1]) + val = "\0" * l + self.__dict__[name] = val + + def _pack(self): + vals = [] + for format, name in self._items: + try: + vals.append(self.__dict__[name]) + except KeyError: + vals.append(None) + + self._buffer_[:] = struct.pack(*(self._format,) + tuple(vals)) + + def _unpack(self): + items = struct.unpack(self._format, self._buffer_) + assert len(items) == len(self._items), "unexpected number of items to unpack!" + for (format, name), val in zip(self._items, items): + self.__dict__[name] = val + + def __setattr__(self, attr, val): + if attr not in self.__dict__ and attr[0] != "_": + for format, attr_name in self._items: + if attr == attr_name: + break + else: + raise AttributeError(attr) + self.__dict__[attr] = val + + +def ADAPTER_STATUS(): + return NCBStruct(ADAPTER_STATUS_ITEMS) + + +def NAME_BUFFER(): + return NCBStruct(NAME_BUFFER_ITEMS) + + +def SESSION_HEADER(): + return NCBStruct(SESSION_HEADER_ITEMS) + + +def SESSION_BUFFER(): + return NCBStruct(SESSION_BUFFER_ITEMS) + + +def LANA_ENUM(): + return NCBStruct(LANA_ENUM_ITEMS) + + +def FIND_NAME_HEADER(): + return NCBStruct(FIND_NAME_HEADER_ITEMS) + + +def FIND_NAME_BUFFER(): + return NCBStruct(FIND_NAME_BUFFER_ITEMS) + + +def ACTION_HEADER(): + return NCBStruct(ACTION_HEADER_ITEMS) + + +def byte_to_int(b): + """Given an element in a binary buffer, return its integer value""" + if sys.version_info >= (3, 0): + # a byte is already an int in py3k + return b + return ord(b) # its a char from a string in py2k. + + +if __name__ == "__main__": + # code ported from "HOWTO: Get the MAC Address for an Ethernet Adapter" + # MS KB ID: Q118623 + ncb = NCB() + ncb.Command = NCBENUM + la_enum = LANA_ENUM() + ncb.Buffer = la_enum + rc = Netbios(ncb) + if rc != 0: + raise RuntimeError("Unexpected result %d" % (rc,)) + for i in range(la_enum.length): + ncb.Reset() + ncb.Command = NCBRESET + ncb.Lana_num = byte_to_int(la_enum.lana[i]) + rc = Netbios(ncb) + if rc != 0: + raise RuntimeError("Unexpected result %d" % (rc,)) + ncb.Reset() + ncb.Command = NCBASTAT + ncb.Lana_num = byte_to_int(la_enum.lana[i]) + ncb.Callname = "* ".encode("ascii") # ensure bytes on py2x and 3k + adapter = ADAPTER_STATUS() + ncb.Buffer = adapter + Netbios(ncb) + print("Adapter address:", end=" ") + for ch in adapter.adapter_address: + print("%02x" % (byte_to_int(ch),), end=" ") + print() diff --git a/MLPY/Lib/site-packages/win32/lib/ntsecuritycon.py b/MLPY/Lib/site-packages/win32/lib/ntsecuritycon.py new file mode 100644 index 0000000000000000000000000000000000000000..4d5b2ed58a96748dc3bf30d3bec97fddc674332d --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/ntsecuritycon.py @@ -0,0 +1,731 @@ +# Hacked from winnt.h + +DELETE = 65536 +READ_CONTROL = 131072 +WRITE_DAC = 262144 +WRITE_OWNER = 524288 +SYNCHRONIZE = 1048576 +STANDARD_RIGHTS_REQUIRED = 983040 +STANDARD_RIGHTS_READ = READ_CONTROL +STANDARD_RIGHTS_WRITE = READ_CONTROL +STANDARD_RIGHTS_EXECUTE = READ_CONTROL +STANDARD_RIGHTS_ALL = 2031616 +SPECIFIC_RIGHTS_ALL = 65535 +ACCESS_SYSTEM_SECURITY = 16777216 +MAXIMUM_ALLOWED = 33554432 +GENERIC_READ = -2147483648 +GENERIC_WRITE = 1073741824 +GENERIC_EXECUTE = 536870912 +GENERIC_ALL = 268435456 + +# file security permissions +FILE_READ_DATA = 1 +FILE_LIST_DIRECTORY = 1 +FILE_WRITE_DATA = 2 +FILE_ADD_FILE = 2 +FILE_APPEND_DATA = 4 +FILE_ADD_SUBDIRECTORY = 4 +FILE_CREATE_PIPE_INSTANCE = 4 +FILE_READ_EA = 8 +FILE_WRITE_EA = 16 +FILE_EXECUTE = 32 +FILE_TRAVERSE = 32 +FILE_DELETE_CHILD = 64 +FILE_READ_ATTRIBUTES = 128 +FILE_WRITE_ATTRIBUTES = 256 +FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 511 +FILE_GENERIC_READ = ( + STANDARD_RIGHTS_READ + | FILE_READ_DATA + | FILE_READ_ATTRIBUTES + | FILE_READ_EA + | SYNCHRONIZE +) +FILE_GENERIC_WRITE = ( + STANDARD_RIGHTS_WRITE + | FILE_WRITE_DATA + | FILE_WRITE_ATTRIBUTES + | FILE_WRITE_EA + | FILE_APPEND_DATA + | SYNCHRONIZE +) +FILE_GENERIC_EXECUTE = ( + STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE +) + + +SECURITY_NULL_SID_AUTHORITY = (0, 0, 0, 0, 0, 0) +SECURITY_WORLD_SID_AUTHORITY = (0, 0, 0, 0, 0, 1) +SECURITY_LOCAL_SID_AUTHORITY = (0, 0, 0, 0, 0, 2) +SECURITY_CREATOR_SID_AUTHORITY = (0, 0, 0, 0, 0, 3) +SECURITY_NON_UNIQUE_AUTHORITY = (0, 0, 0, 0, 0, 4) +SECURITY_RESOURCE_MANAGER_AUTHORITY = (0, 0, 0, 0, 0, 9) + +SECURITY_NULL_RID = 0 +SECURITY_WORLD_RID = 0 +SECURITY_LOCAL_RID = 0x00000000 + +SECURITY_CREATOR_OWNER_RID = 0 +SECURITY_CREATOR_GROUP_RID = 1 + +SECURITY_CREATOR_OWNER_SERVER_RID = 2 +SECURITY_CREATOR_GROUP_SERVER_RID = 3 +SECURITY_CREATOR_OWNER_RIGHTS_RID = 4 + +# NT well-known SIDs +SECURITY_NT_AUTHORITY = (0, 0, 0, 0, 0, 5) + +SECURITY_DIALUP_RID = 1 +SECURITY_NETWORK_RID = 2 +SECURITY_BATCH_RID = 3 +SECURITY_INTERACTIVE_RID = 4 +SECURITY_SERVICE_RID = 6 +SECURITY_ANONYMOUS_LOGON_RID = 7 +SECURITY_PROXY_RID = 8 +SECURITY_SERVER_LOGON_RID = 9 + +SECURITY_LOGON_IDS_RID = 5 +SECURITY_LOGON_IDS_RID_COUNT = 3 + +SECURITY_LOCAL_SYSTEM_RID = 18 + +SECURITY_NT_NON_UNIQUE = 21 + +SECURITY_BUILTIN_DOMAIN_RID = 32 + +# well-known domain relative sub-authority values (RIDs)... +DOMAIN_USER_RID_ADMIN = 500 +DOMAIN_USER_RID_GUEST = 501 +DOMAIN_USER_RID_KRBTGT = 502 +DOMAIN_USER_RID_MAX = 999 + +# well-known groups ... +DOMAIN_GROUP_RID_ADMINS = 512 +DOMAIN_GROUP_RID_USERS = 513 +DOMAIN_GROUP_RID_GUESTS = 514 +DOMAIN_GROUP_RID_COMPUTERS = 515 +DOMAIN_GROUP_RID_CONTROLLERS = 516 +DOMAIN_GROUP_RID_CERT_ADMINS = 517 +DOMAIN_GROUP_RID_SCHEMA_ADMINS = 518 +DOMAIN_GROUP_RID_ENTERPRISE_ADMINS = 519 +DOMAIN_GROUP_RID_POLICY_ADMINS = 520 +DOMAIN_GROUP_RID_READONLY_CONTROLLERS = 521 + +# well-known aliases ... +DOMAIN_ALIAS_RID_ADMINS = 544 +DOMAIN_ALIAS_RID_USERS = 545 +DOMAIN_ALIAS_RID_GUESTS = 546 +DOMAIN_ALIAS_RID_POWER_USERS = 547 +DOMAIN_ALIAS_RID_ACCOUNT_OPS = 548 +DOMAIN_ALIAS_RID_SYSTEM_OPS = 549 +DOMAIN_ALIAS_RID_PRINT_OPS = 550 +DOMAIN_ALIAS_RID_BACKUP_OPS = 551 +DOMAIN_ALIAS_RID_REPLICATOR = 552 +DOMAIN_ALIAS_RID_RAS_SERVERS = 553 +DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 554 +DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 555 +DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 556 +DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 557 +DOMAIN_ALIAS_RID_MONITORING_USERS = 558 +DOMAIN_ALIAS_RID_LOGGING_USERS = 559 +DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 560 +DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 561 +DOMAIN_ALIAS_RID_DCOM_USERS = 562 +DOMAIN_ALIAS_RID_IUSERS = 568 +DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 569 +DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 571 +DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 572 +DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 573 + +SECURITY_MANDATORY_LABEL_AUTHORITY = (0, 0, 0, 0, 0, 16) +SECURITY_MANDATORY_UNTRUSTED_RID = 0x00000000 +SECURITY_MANDATORY_LOW_RID = 0x00001000 +SECURITY_MANDATORY_MEDIUM_RID = 0x00002000 +SECURITY_MANDATORY_HIGH_RID = 0x00003000 +SECURITY_MANDATORY_SYSTEM_RID = 0x00004000 +SECURITY_MANDATORY_PROTECTED_PROCESS_RID = 0x00005000 +SECURITY_MANDATORY_MAXIMUM_USER_RID = SECURITY_MANDATORY_SYSTEM_RID + +SYSTEM_LUID = (999, 0) +ANONYMOUS_LOGON_LUID = (998, 0) +LOCALSERVICE_LUID = (997, 0) +NETWORKSERVICE_LUID = (996, 0) +IUSER_LUID = (995, 0) + +# Group attributes + +SE_GROUP_MANDATORY = 1 +SE_GROUP_ENABLED_BY_DEFAULT = 2 +SE_GROUP_ENABLED = 4 +SE_GROUP_OWNER = 8 +SE_GROUP_USE_FOR_DENY_ONLY = 16 +SE_GROUP_INTEGRITY = 32 +SE_GROUP_INTEGRITY_ENABLED = 64 +SE_GROUP_RESOURCE = 536870912 +SE_GROUP_LOGON_ID = -1073741824 + + +# User attributes +# (None yet defined.) + +# ACE types +ACCESS_MIN_MS_ACE_TYPE = 0 +ACCESS_ALLOWED_ACE_TYPE = 0 +ACCESS_DENIED_ACE_TYPE = 1 +SYSTEM_AUDIT_ACE_TYPE = 2 +SYSTEM_ALARM_ACE_TYPE = 3 +ACCESS_MAX_MS_V2_ACE_TYPE = 3 +ACCESS_ALLOWED_COMPOUND_ACE_TYPE = 4 +ACCESS_MAX_MS_V3_ACE_TYPE = 4 +ACCESS_MIN_MS_OBJECT_ACE_TYPE = 5 +ACCESS_ALLOWED_OBJECT_ACE_TYPE = 5 +ACCESS_DENIED_OBJECT_ACE_TYPE = 6 +SYSTEM_AUDIT_OBJECT_ACE_TYPE = 7 +SYSTEM_ALARM_OBJECT_ACE_TYPE = 8 +ACCESS_MAX_MS_OBJECT_ACE_TYPE = 8 +ACCESS_MAX_MS_V4_ACE_TYPE = 8 +ACCESS_MAX_MS_ACE_TYPE = 8 +ACCESS_ALLOWED_CALLBACK_ACE_TYPE = 9 +ACCESS_DENIED_CALLBACK_ACE_TYPE = 10 +ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE = 11 +ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE = 12 +SYSTEM_AUDIT_CALLBACK_ACE_TYPE = 13 +SYSTEM_ALARM_CALLBACK_ACE_TYPE = 14 +SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE = 15 +SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE = 16 +SYSTEM_MANDATORY_LABEL_ACE_TYPE = 17 +ACCESS_MAX_MS_V5_ACE_TYPE = 17 + +# The following are the inherit flags that go into the AceFlags field +# of an Ace header. + +OBJECT_INHERIT_ACE = 1 +CONTAINER_INHERIT_ACE = 2 +NO_PROPAGATE_INHERIT_ACE = 4 +INHERIT_ONLY_ACE = 8 +VALID_INHERIT_FLAGS = 15 + + +SUCCESSFUL_ACCESS_ACE_FLAG = 64 +FAILED_ACCESS_ACE_FLAG = 128 + +SE_OWNER_DEFAULTED = 1 +SE_GROUP_DEFAULTED = 2 +SE_DACL_PRESENT = 4 +SE_DACL_DEFAULTED = 8 +SE_SACL_PRESENT = 16 +SE_SACL_DEFAULTED = 32 +SE_SELF_RELATIVE = 32768 + + +SE_PRIVILEGE_ENABLED_BY_DEFAULT = 1 +SE_PRIVILEGE_ENABLED = 2 +SE_PRIVILEGE_USED_FOR_ACCESS = -2147483648 + +PRIVILEGE_SET_ALL_NECESSARY = 1 + +# NT Defined Privileges + +SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" +SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" +SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" +SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" +SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege" +SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" +SE_TCB_NAME = "SeTcbPrivilege" +SE_SECURITY_NAME = "SeSecurityPrivilege" +SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" +SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" +SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" +SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" +SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" +SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" +SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" +SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" +SE_BACKUP_NAME = "SeBackupPrivilege" +SE_RESTORE_NAME = "SeRestorePrivilege" +SE_SHUTDOWN_NAME = "SeShutdownPrivilege" +SE_DEBUG_NAME = "SeDebugPrivilege" +SE_AUDIT_NAME = "SeAuditPrivilege" +SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" +SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" +SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege" + + +# Enum SECURITY_IMPERSONATION_LEVEL: +SecurityAnonymous = 0 +SecurityIdentification = 1 +SecurityImpersonation = 2 +SecurityDelegation = 3 + +SECURITY_MAX_IMPERSONATION_LEVEL = SecurityDelegation + +DEFAULT_IMPERSONATION_LEVEL = SecurityImpersonation + +TOKEN_ASSIGN_PRIMARY = 1 +TOKEN_DUPLICATE = 2 +TOKEN_IMPERSONATE = 4 +TOKEN_QUERY = 8 +TOKEN_QUERY_SOURCE = 16 +TOKEN_ADJUST_PRIVILEGES = 32 +TOKEN_ADJUST_GROUPS = 64 +TOKEN_ADJUST_DEFAULT = 128 + +TOKEN_ALL_ACCESS = ( + STANDARD_RIGHTS_REQUIRED + | TOKEN_ASSIGN_PRIMARY + | TOKEN_DUPLICATE + | TOKEN_IMPERSONATE + | TOKEN_QUERY + | TOKEN_QUERY_SOURCE + | TOKEN_ADJUST_PRIVILEGES + | TOKEN_ADJUST_GROUPS + | TOKEN_ADJUST_DEFAULT +) + + +TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY + + +TOKEN_WRITE = ( + STANDARD_RIGHTS_WRITE + | TOKEN_ADJUST_PRIVILEGES + | TOKEN_ADJUST_GROUPS + | TOKEN_ADJUST_DEFAULT +) + +TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE + +SidTypeUser = 1 +SidTypeGroup = 2 +SidTypeDomain = 3 +SidTypeAlias = 4 +SidTypeWellKnownGroup = 5 +SidTypeDeletedAccount = 6 +SidTypeInvalid = 7 +SidTypeUnknown = 8 +SidTypeComputer = 9 +SidTypeLabel = 10 + +# Token types +TokenPrimary = 1 +TokenImpersonation = 2 + +# TOKEN_INFORMATION_CLASS, used with Get/SetTokenInformation +TokenUser = 1 +TokenGroups = 2 +TokenPrivileges = 3 +TokenOwner = 4 +TokenPrimaryGroup = 5 +TokenDefaultDacl = 6 +TokenSource = 7 +TokenType = 8 +TokenImpersonationLevel = 9 +TokenStatistics = 10 +TokenRestrictedSids = 11 +TokenSessionId = 12 +TokenGroupsAndPrivileges = 13 +TokenSessionReference = 14 +TokenSandBoxInert = 15 +TokenAuditPolicy = 16 +TokenOrigin = 17 +TokenElevationType = 18 +TokenLinkedToken = 19 +TokenElevation = 20 +TokenHasRestrictions = 21 +TokenAccessInformation = 22 +TokenVirtualizationAllowed = 23 +TokenVirtualizationEnabled = 24 +TokenIntegrityLevel = 25 +TokenUIAccess = 26 +TokenMandatoryPolicy = 27 +TokenLogonSid = 28 + +# DirectoryService related constants. +# Generated by h2py from NtDsAPI.h +DS_BEHAVIOR_WIN2000 = 0 +DS_BEHAVIOR_WIN2003_WITH_MIXED_DOMAINS = 1 +DS_BEHAVIOR_WIN2003 = 2 +DS_SYNCED_EVENT_NAME = "NTDSInitialSyncsCompleted" +ACTRL_DS_OPEN = 0x00000000 +ACTRL_DS_CREATE_CHILD = 0x00000001 +ACTRL_DS_DELETE_CHILD = 0x00000002 +ACTRL_DS_LIST = 0x00000004 +ACTRL_DS_SELF = 0x00000008 +ACTRL_DS_READ_PROP = 0x00000010 +ACTRL_DS_WRITE_PROP = 0x00000020 +ACTRL_DS_DELETE_TREE = 0x00000040 +ACTRL_DS_LIST_OBJECT = 0x00000080 +ACTRL_DS_CONTROL_ACCESS = 0x00000100 +NTDSAPI_BIND_ALLOW_DELEGATION = 0x00000001 +DS_REPSYNC_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPSYNC_WRITEABLE = 0x00000002 +DS_REPSYNC_PERIODIC = 0x00000004 +DS_REPSYNC_INTERSITE_MESSAGING = 0x00000008 +DS_REPSYNC_ALL_SOURCES = 0x00000010 +DS_REPSYNC_FULL = 0x00000020 +DS_REPSYNC_URGENT = 0x00000040 +DS_REPSYNC_NO_DISCARD = 0x00000080 +DS_REPSYNC_FORCE = 0x00000100 +DS_REPSYNC_ADD_REFERENCE = 0x00000200 +DS_REPSYNC_NEVER_COMPLETED = 0x00000400 +DS_REPSYNC_TWO_WAY = 0x00000800 +DS_REPSYNC_NEVER_NOTIFY = 0x00001000 +DS_REPSYNC_INITIAL = 0x00002000 +DS_REPSYNC_USE_COMPRESSION = 0x00004000 +DS_REPSYNC_ABANDONED = 0x00008000 +DS_REPSYNC_INITIAL_IN_PROGRESS = 0x00010000 +DS_REPSYNC_PARTIAL_ATTRIBUTE_SET = 0x00020000 +DS_REPSYNC_REQUEUE = 0x00040000 +DS_REPSYNC_NOTIFICATION = 0x00080000 +DS_REPSYNC_ASYNCHRONOUS_REPLICA = 0x00100000 +DS_REPSYNC_CRITICAL = 0x00200000 +DS_REPSYNC_FULL_IN_PROGRESS = 0x00400000 +DS_REPSYNC_PREEMPTED = 0x00800000 +DS_REPADD_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPADD_WRITEABLE = 0x00000002 +DS_REPADD_INITIAL = 0x00000004 +DS_REPADD_PERIODIC = 0x00000008 +DS_REPADD_INTERSITE_MESSAGING = 0x00000010 +DS_REPADD_ASYNCHRONOUS_REPLICA = 0x00000020 +DS_REPADD_DISABLE_NOTIFICATION = 0x00000040 +DS_REPADD_DISABLE_PERIODIC = 0x00000080 +DS_REPADD_USE_COMPRESSION = 0x00000100 +DS_REPADD_NEVER_NOTIFY = 0x00000200 +DS_REPADD_TWO_WAY = 0x00000400 +DS_REPADD_CRITICAL = 0x00000800 +DS_REPDEL_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPDEL_WRITEABLE = 0x00000002 +DS_REPDEL_INTERSITE_MESSAGING = 0x00000004 +DS_REPDEL_IGNORE_ERRORS = 0x00000008 +DS_REPDEL_LOCAL_ONLY = 0x00000010 +DS_REPDEL_NO_SOURCE = 0x00000020 +DS_REPDEL_REF_OK = 0x00000040 +DS_REPMOD_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPMOD_WRITEABLE = 0x00000002 +DS_REPMOD_UPDATE_FLAGS = 0x00000001 +DS_REPMOD_UPDATE_ADDRESS = 0x00000002 +DS_REPMOD_UPDATE_SCHEDULE = 0x00000004 +DS_REPMOD_UPDATE_RESULT = 0x00000008 +DS_REPMOD_UPDATE_TRANSPORT = 0x00000010 +DS_REPUPD_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPUPD_WRITEABLE = 0x00000002 +DS_REPUPD_ADD_REFERENCE = 0x00000004 +DS_REPUPD_DELETE_REFERENCE = 0x00000008 +DS_INSTANCETYPE_IS_NC_HEAD = 0x00000001 +DS_INSTANCETYPE_NC_IS_WRITEABLE = 0x00000004 +DS_INSTANCETYPE_NC_COMING = 0x00000010 +DS_INSTANCETYPE_NC_GOING = 0x00000020 +NTDSDSA_OPT_IS_GC = 1 << 0 +NTDSDSA_OPT_DISABLE_INBOUND_REPL = 1 << 1 +NTDSDSA_OPT_DISABLE_OUTBOUND_REPL = 1 << 2 +NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE = 1 << 3 +NTDSCONN_OPT_IS_GENERATED = 1 << 0 +NTDSCONN_OPT_TWOWAY_SYNC = 1 << 1 +NTDSCONN_OPT_OVERRIDE_NOTIFY_DEFAULT = 1 << 2 +NTDSCONN_OPT_USE_NOTIFY = 1 << 3 +NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSION = 1 << 4 +NTDSCONN_OPT_USER_OWNED_SCHEDULE = 1 << 5 +NTDSCONN_KCC_NO_REASON = 0 +NTDSCONN_KCC_GC_TOPOLOGY = 1 << 0 +NTDSCONN_KCC_RING_TOPOLOGY = 1 << 1 +NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY = 1 << 2 +NTDSCONN_KCC_STALE_SERVERS_TOPOLOGY = 1 << 3 +NTDSCONN_KCC_OSCILLATING_CONNECTION_TOPOLOGY = 1 << 4 +NTDSCONN_KCC_INTERSITE_GC_TOPOLOGY = 1 << 5 +NTDSCONN_KCC_INTERSITE_TOPOLOGY = 1 << 6 +NTDSCONN_KCC_SERVER_FAILOVER_TOPOLOGY = 1 << 7 +NTDSCONN_KCC_SITE_FAILOVER_TOPOLOGY = 1 << 8 +NTDSCONN_KCC_REDUNDANT_SERVER_TOPOLOGY = 1 << 9 +FRSCONN_PRIORITY_MASK = 0x70000000 +FRSCONN_MAX_PRIORITY = 0x8 +NTDSCONN_OPT_IGNORE_SCHEDULE_MASK = -2147483648 + +NTDSSETTINGS_OPT_IS_AUTO_TOPOLOGY_DISABLED = 1 << 0 +NTDSSETTINGS_OPT_IS_TOPL_CLEANUP_DISABLED = 1 << 1 +NTDSSETTINGS_OPT_IS_TOPL_MIN_HOPS_DISABLED = 1 << 2 +NTDSSETTINGS_OPT_IS_TOPL_DETECT_STALE_DISABLED = 1 << 3 +NTDSSETTINGS_OPT_IS_INTER_SITE_AUTO_TOPOLOGY_DISABLED = 1 << 4 +NTDSSETTINGS_OPT_IS_GROUP_CACHING_ENABLED = 1 << 5 +NTDSSETTINGS_OPT_FORCE_KCC_WHISTLER_BEHAVIOR = 1 << 6 +NTDSSETTINGS_OPT_FORCE_KCC_W2K_ELECTION = 1 << 7 +NTDSSETTINGS_OPT_IS_RAND_BH_SELECTION_DISABLED = 1 << 8 +NTDSSETTINGS_OPT_IS_SCHEDULE_HASHING_ENABLED = 1 << 9 +NTDSSETTINGS_OPT_IS_REDUNDANT_SERVER_TOPOLOGY_ENABLED = 1 << 10 +NTDSSETTINGS_DEFAULT_SERVER_REDUNDANCY = 2 +NTDSTRANSPORT_OPT_IGNORE_SCHEDULES = 1 << 0 +NTDSTRANSPORT_OPT_BRIDGES_REQUIRED = 1 << 1 +NTDSSITECONN_OPT_USE_NOTIFY = 1 << 0 +NTDSSITECONN_OPT_TWOWAY_SYNC = 1 << 1 +NTDSSITECONN_OPT_DISABLE_COMPRESSION = 1 << 2 +NTDSSITELINK_OPT_USE_NOTIFY = 1 << 0 +NTDSSITELINK_OPT_TWOWAY_SYNC = 1 << 1 +NTDSSITELINK_OPT_DISABLE_COMPRESSION = 1 << 2 +GUID_USERS_CONTAINER_A = "a9d1ca15768811d1aded00c04fd8d5cd" +GUID_COMPUTRS_CONTAINER_A = "aa312825768811d1aded00c04fd8d5cd" +GUID_SYSTEMS_CONTAINER_A = "ab1d30f3768811d1aded00c04fd8d5cd" +GUID_DOMAIN_CONTROLLERS_CONTAINER_A = "a361b2ffffd211d1aa4b00c04fd7d83a" +GUID_INFRASTRUCTURE_CONTAINER_A = "2fbac1870ade11d297c400c04fd8d5cd" +GUID_DELETED_OBJECTS_CONTAINER_A = "18e2ea80684f11d2b9aa00c04f79f805" +GUID_LOSTANDFOUND_CONTAINER_A = "ab8153b7768811d1aded00c04fd8d5cd" +GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER_A = "22b70c67d56e4efb91e9300fca3dc1aa" +GUID_PROGRAM_DATA_CONTAINER_A = "09460c08ae1e4a4ea0f64aee7daa1e5a" +GUID_MICROSOFT_PROGRAM_DATA_CONTAINER_A = "f4be92a4c777485e878e9421d53087db" +GUID_NTDS_QUOTAS_CONTAINER_A = "6227f0af1fc2410d8e3bb10615bb5b0f" +GUID_USERS_CONTAINER_BYTE = ( + "\xa9\xd1\xca\x15\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +) +GUID_COMPUTRS_CONTAINER_BYTE = ( + "\xaa\x31\x28\x25\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +) +GUID_SYSTEMS_CONTAINER_BYTE = ( + "\xab\x1d\x30\xf3\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +) +GUID_DOMAIN_CONTROLLERS_CONTAINER_BYTE = ( + "\xa3\x61\xb2\xff\xff\xd2\x11\xd1\xaa\x4b\x00\xc0\x4f\xd7\xd8\x3a" +) +GUID_INFRASTRUCTURE_CONTAINER_BYTE = ( + "\x2f\xba\xc1\x87\x0a\xde\x11\xd2\x97\xc4\x00\xc0\x4f\xd8\xd5\xcd" +) +GUID_DELETED_OBJECTS_CONTAINER_BYTE = ( + "\x18\xe2\xea\x80\x68\x4f\x11\xd2\xb9\xaa\x00\xc0\x4f\x79\xf8\x05" +) +GUID_LOSTANDFOUND_CONTAINER_BYTE = ( + "\xab\x81\x53\xb7\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +) +GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER_BYTE = ( + "\x22\xb7\x0c\x67\xd5\x6e\x4e\xfb\x91\xe9\x30\x0f\xca\x3d\xc1\xaa" +) +GUID_PROGRAM_DATA_CONTAINER_BYTE = ( + "\x09\x46\x0c\x08\xae\x1e\x4a\x4e\xa0\xf6\x4a\xee\x7d\xaa\x1e\x5a" +) +GUID_MICROSOFT_PROGRAM_DATA_CONTAINER_BYTE = ( + "\xf4\xbe\x92\xa4\xc7\x77\x48\x5e\x87\x8e\x94\x21\xd5\x30\x87\xdb" +) +GUID_NTDS_QUOTAS_CONTAINER_BYTE = ( + "\x62\x27\xf0\xaf\x1f\xc2\x41\x0d\x8e\x3b\xb1\x06\x15\xbb\x5b\x0f" +) +DS_REPSYNCALL_NO_OPTIONS = 0x00000000 +DS_REPSYNCALL_ABORT_IF_SERVER_UNAVAILABLE = 0x00000001 +DS_REPSYNCALL_SYNC_ADJACENT_SERVERS_ONLY = 0x00000002 +DS_REPSYNCALL_ID_SERVERS_BY_DN = 0x00000004 +DS_REPSYNCALL_DO_NOT_SYNC = 0x00000008 +DS_REPSYNCALL_SKIP_INITIAL_CHECK = 0x00000010 +DS_REPSYNCALL_PUSH_CHANGES_OUTWARD = 0x00000020 +DS_REPSYNCALL_CROSS_SITE_BOUNDARIES = 0x00000040 +DS_LIST_DSA_OBJECT_FOR_SERVER = 0 +DS_LIST_DNS_HOST_NAME_FOR_SERVER = 1 +DS_LIST_ACCOUNT_OBJECT_FOR_SERVER = 2 +DS_ROLE_SCHEMA_OWNER = 0 +DS_ROLE_DOMAIN_OWNER = 1 +DS_ROLE_PDC_OWNER = 2 +DS_ROLE_RID_OWNER = 3 +DS_ROLE_INFRASTRUCTURE_OWNER = 4 +DS_SCHEMA_GUID_NOT_FOUND = 0 +DS_SCHEMA_GUID_ATTR = 1 +DS_SCHEMA_GUID_ATTR_SET = 2 +DS_SCHEMA_GUID_CLASS = 3 +DS_SCHEMA_GUID_CONTROL_RIGHT = 4 +DS_KCC_FLAG_ASYNC_OP = 1 << 0 +DS_KCC_FLAG_DAMPED = 1 << 1 +DS_EXIST_ADVISORY_MODE = 0x1 +DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS = 0x00000001 +DS_REPL_NBR_WRITEABLE = 0x00000010 +DS_REPL_NBR_SYNC_ON_STARTUP = 0x00000020 +DS_REPL_NBR_DO_SCHEDULED_SYNCS = 0x00000040 +DS_REPL_NBR_USE_ASYNC_INTERSITE_TRANSPORT = 0x00000080 +DS_REPL_NBR_TWO_WAY_SYNC = 0x00000200 +DS_REPL_NBR_RETURN_OBJECT_PARENTS = 0x00000800 +DS_REPL_NBR_FULL_SYNC_IN_PROGRESS = 0x00010000 +DS_REPL_NBR_FULL_SYNC_NEXT_PACKET = 0x00020000 +DS_REPL_NBR_NEVER_SYNCED = 0x00200000 +DS_REPL_NBR_PREEMPTED = 0x01000000 +DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS = 0x04000000 +DS_REPL_NBR_DISABLE_SCHEDULED_SYNC = 0x08000000 +DS_REPL_NBR_COMPRESS_CHANGES = 0x10000000 +DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS = 0x20000000 +DS_REPL_NBR_PARTIAL_ATTRIBUTE_SET = 0x40000000 +DS_REPL_NBR_MODIFIABLE_MASK = ( + DS_REPL_NBR_SYNC_ON_STARTUP + | DS_REPL_NBR_DO_SCHEDULED_SYNCS + | DS_REPL_NBR_TWO_WAY_SYNC + | DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS + | DS_REPL_NBR_DISABLE_SCHEDULED_SYNC + | DS_REPL_NBR_COMPRESS_CHANGES + | DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS +) + +# from enum DS_NAME_FORMAT +DS_UNKNOWN_NAME = 0 +DS_FQDN_1779_NAME = 1 +DS_NT4_ACCOUNT_NAME = 2 +DS_DISPLAY_NAME = 3 +DS_UNIQUE_ID_NAME = 6 +DS_CANONICAL_NAME = 7 +DS_USER_PRINCIPAL_NAME = 8 +DS_CANONICAL_NAME_EX = 9 +DS_SERVICE_PRINCIPAL_NAME = 10 +DS_SID_OR_SID_HISTORY_NAME = 11 +DS_DNS_DOMAIN_NAME = 12 + +DS_DOMAIN_SIMPLE_NAME = DS_USER_PRINCIPAL_NAME +DS_ENTERPRISE_SIMPLE_NAME = DS_USER_PRINCIPAL_NAME + +# from enum DS_NAME_FLAGS +DS_NAME_NO_FLAGS = 0x0 +DS_NAME_FLAG_SYNTACTICAL_ONLY = 0x1 +DS_NAME_FLAG_EVAL_AT_DC = 0x2 +DS_NAME_FLAG_GCVERIFY = 0x4 +DS_NAME_FLAG_TRUST_REFERRAL = 0x8 + +# from enum DS_NAME_ERROR +DS_NAME_NO_ERROR = 0 +DS_NAME_ERROR_RESOLVING = 1 +DS_NAME_ERROR_NOT_FOUND = 2 +DS_NAME_ERROR_NOT_UNIQUE = 3 +DS_NAME_ERROR_NO_MAPPING = 4 +DS_NAME_ERROR_DOMAIN_ONLY = 5 +DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 6 +DS_NAME_ERROR_TRUST_REFERRAL = 7 + + +# from enum DS_SPN_NAME_TYPE +DS_SPN_DNS_HOST = 0 +DS_SPN_DN_HOST = 1 +DS_SPN_NB_HOST = 2 +DS_SPN_DOMAIN = 3 +DS_SPN_NB_DOMAIN = 4 +DS_SPN_SERVICE = 5 + +# from enum DS_SPN_WRITE_OP +DS_SPN_ADD_SPN_OP = 0 +DS_SPN_REPLACE_SPN_OP = 1 +DS_SPN_DELETE_SPN_OP = 2 + +# Generated by h2py from DsGetDC.h +DS_FORCE_REDISCOVERY = 0x00000001 +DS_DIRECTORY_SERVICE_REQUIRED = 0x00000010 +DS_DIRECTORY_SERVICE_PREFERRED = 0x00000020 +DS_GC_SERVER_REQUIRED = 0x00000040 +DS_PDC_REQUIRED = 0x00000080 +DS_BACKGROUND_ONLY = 0x00000100 +DS_IP_REQUIRED = 0x00000200 +DS_KDC_REQUIRED = 0x00000400 +DS_TIMESERV_REQUIRED = 0x00000800 +DS_WRITABLE_REQUIRED = 0x00001000 +DS_GOOD_TIMESERV_PREFERRED = 0x00002000 +DS_AVOID_SELF = 0x00004000 +DS_ONLY_LDAP_NEEDED = 0x00008000 +DS_IS_FLAT_NAME = 0x00010000 +DS_IS_DNS_NAME = 0x00020000 +DS_RETURN_DNS_NAME = 0x40000000 +DS_RETURN_FLAT_NAME = -2147483648 +DSGETDC_VALID_FLAGS = ( + DS_FORCE_REDISCOVERY + | DS_DIRECTORY_SERVICE_REQUIRED + | DS_DIRECTORY_SERVICE_PREFERRED + | DS_GC_SERVER_REQUIRED + | DS_PDC_REQUIRED + | DS_BACKGROUND_ONLY + | DS_IP_REQUIRED + | DS_KDC_REQUIRED + | DS_TIMESERV_REQUIRED + | DS_WRITABLE_REQUIRED + | DS_GOOD_TIMESERV_PREFERRED + | DS_AVOID_SELF + | DS_ONLY_LDAP_NEEDED + | DS_IS_FLAT_NAME + | DS_IS_DNS_NAME + | DS_RETURN_FLAT_NAME + | DS_RETURN_DNS_NAME +) +DS_INET_ADDRESS = 1 +DS_NETBIOS_ADDRESS = 2 +DS_PDC_FLAG = 0x00000001 +DS_GC_FLAG = 0x00000004 +DS_LDAP_FLAG = 0x00000008 +DS_DS_FLAG = 0x00000010 +DS_KDC_FLAG = 0x00000020 +DS_TIMESERV_FLAG = 0x00000040 +DS_CLOSEST_FLAG = 0x00000080 +DS_WRITABLE_FLAG = 0x00000100 +DS_GOOD_TIMESERV_FLAG = 0x00000200 +DS_NDNC_FLAG = 0x00000400 +DS_PING_FLAGS = 0x0000FFFF +DS_DNS_CONTROLLER_FLAG = 0x20000000 +DS_DNS_DOMAIN_FLAG = 0x40000000 +DS_DNS_FOREST_FLAG = -2147483648 +DS_DOMAIN_IN_FOREST = 0x0001 +DS_DOMAIN_DIRECT_OUTBOUND = 0x0002 +DS_DOMAIN_TREE_ROOT = 0x0004 +DS_DOMAIN_PRIMARY = 0x0008 +DS_DOMAIN_NATIVE_MODE = 0x0010 +DS_DOMAIN_DIRECT_INBOUND = 0x0020 +DS_DOMAIN_VALID_FLAGS = ( + DS_DOMAIN_IN_FOREST + | DS_DOMAIN_DIRECT_OUTBOUND + | DS_DOMAIN_TREE_ROOT + | DS_DOMAIN_PRIMARY + | DS_DOMAIN_NATIVE_MODE + | DS_DOMAIN_DIRECT_INBOUND +) +DS_GFTI_UPDATE_TDO = 0x1 +DS_GFTI_VALID_FLAGS = 0x1 +DS_ONLY_DO_SITE_NAME = 0x01 +DS_NOTIFY_AFTER_SITE_RECORDS = 0x02 +DS_OPEN_VALID_OPTION_FLAGS = DS_ONLY_DO_SITE_NAME | DS_NOTIFY_AFTER_SITE_RECORDS +DS_OPEN_VALID_FLAGS = ( + DS_FORCE_REDISCOVERY + | DS_ONLY_LDAP_NEEDED + | DS_KDC_REQUIRED + | DS_PDC_REQUIRED + | DS_GC_SERVER_REQUIRED + | DS_WRITABLE_REQUIRED +) + +## from aclui.h +# SI_OBJECT_INFO.dwFlags +SI_EDIT_PERMS = 0x00000000 +SI_EDIT_OWNER = 0x00000001 +SI_EDIT_AUDITS = 0x00000002 +SI_CONTAINER = 0x00000004 +SI_READONLY = 0x00000008 +SI_ADVANCED = 0x00000010 +SI_RESET = 0x00000020 +SI_OWNER_READONLY = 0x00000040 +SI_EDIT_PROPERTIES = 0x00000080 +SI_OWNER_RECURSE = 0x00000100 +SI_NO_ACL_PROTECT = 0x00000200 +SI_NO_TREE_APPLY = 0x00000400 +SI_PAGE_TITLE = 0x00000800 +SI_SERVER_IS_DC = 0x00001000 +SI_RESET_DACL_TREE = 0x00004000 +SI_RESET_SACL_TREE = 0x00008000 +SI_OBJECT_GUID = 0x00010000 +SI_EDIT_EFFECTIVE = 0x00020000 +SI_RESET_DACL = 0x00040000 +SI_RESET_SACL = 0x00080000 +SI_RESET_OWNER = 0x00100000 +SI_NO_ADDITIONAL_PERMISSION = 0x00200000 +SI_MAY_WRITE = 0x10000000 +SI_EDIT_ALL = SI_EDIT_PERMS | SI_EDIT_OWNER | SI_EDIT_AUDITS +SI_AUDITS_ELEVATION_REQUIRED = 0x02000000 +SI_VIEW_ONLY = 0x00400000 +SI_OWNER_ELEVATION_REQUIRED = 0x04000000 +SI_PERMS_ELEVATION_REQUIRED = 0x01000000 + +# SI_ACCESS.dwFlags +SI_ACCESS_SPECIFIC = 0x00010000 +SI_ACCESS_GENERAL = 0x00020000 +SI_ACCESS_CONTAINER = 0x00040000 +SI_ACCESS_PROPERTY = 0x00080000 + +# SI_PAGE_TYPE enum +SI_PAGE_PERM = 0 +SI_PAGE_ADVPERM = 1 +SI_PAGE_AUDIT = 2 +SI_PAGE_OWNER = 3 +SI_PAGE_EFFECTIVE = 4 + +CFSTR_ACLUI_SID_INFO_LIST = "CFSTR_ACLUI_SID_INFO_LIST" +PSPCB_SI_INITDIALOG = 1025 ## WM_USER+1 diff --git a/MLPY/Lib/site-packages/win32/lib/pywin32_bootstrap.py b/MLPY/Lib/site-packages/win32/lib/pywin32_bootstrap.py new file mode 100644 index 0000000000000000000000000000000000000000..fbc4f7be4a8f110ae88606e0cba6449b90045a74 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/pywin32_bootstrap.py @@ -0,0 +1,29 @@ +# Imported by pywin32.pth to bootstrap the pywin32 environment in "portable" +# environments or any other case where the post-install script isn't run. +# +# In short, there's a directory installed by pywin32 named 'pywin32_system32' +# with some important DLLs which need to be found by Python when some pywin32 +# modules are imported. +# If Python has `os.add_dll_directory()`, we need to call it with this path. +# Otherwise, we add this path to PATH. + + +try: + import pywin32_system32 +except ImportError: # Python ≥3.6: replace ImportError with ModuleNotFoundError + pass +else: + import os + + # We're guaranteed only that __path__: Iterable[str] + # https://docs.python.org/3/reference/import.html#__path__ + for path in pywin32_system32.__path__: + if os.path.isdir(path): + if hasattr(os, "add_dll_directory"): + os.add_dll_directory(path) + # This is to ensure the pywin32 path is in the beginning to find the + # pywin32 DLLs first and prevent other PATH entries to shadow them + elif not os.environ["PATH"].startswith(path): + os.environ["PATH"] = os.environ["PATH"].replace(os.pathsep + path, "") + os.environ["PATH"] = path + os.pathsep + os.environ["PATH"] + break diff --git a/MLPY/Lib/site-packages/win32/lib/pywin32_testutil.py b/MLPY/Lib/site-packages/win32/lib/pywin32_testutil.py new file mode 100644 index 0000000000000000000000000000000000000000..41566a8eb24d0bf1e0f583fa10bdc06a4a284ec3 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/pywin32_testutil.py @@ -0,0 +1,327 @@ +# Utilities for the pywin32 tests +import gc +import os +import site +import sys +import unittest + +import winerror + +## +## General purpose utilities for the test suite. +## + + +# The test suite has lots of string constants containing binary data, but +# the strings are used in various "bytes" contexts. +def str2bytes(sval): + if sys.version_info < (3, 0) and isinstance(sval, str): + sval = sval.decode("latin1") + return sval.encode("latin1") + + +# Sometimes we want to pass a string that should explicitly be treated as +# a memory blob. +def str2memory(sval): + if sys.version_info < (3, 0): + return buffer(sval) + # py3k. + return memoryview(sval.encode("latin1")) + + +# Sometimes we want to pass an object that exposes its memory +def ob2memory(ob): + if sys.version_info < (3, 0): + return buffer(ob) + # py3k. + return memoryview(ob) + + +## +## unittest related stuff +## + + +# This is a specialized TestCase adaptor which wraps a real test. +class LeakTestCase(unittest.TestCase): + """An 'adaptor' which takes another test. In debug builds we execute the + test once to remove one-off side-effects, then capture the total + reference count, then execute the test a few times. If the total + refcount at the end is greater than we first captured, we have a leak! + + In release builds the test is executed just once, as normal. + + Generally used automatically by the test runner - you can safely + ignore this. + """ + + def __init__(self, real_test): + unittest.TestCase.__init__(self) + self.real_test = real_test + self.num_test_cases = 1 + self.num_leak_iters = 2 # seems to be enough! + if hasattr(sys, "gettotalrefcount"): + self.num_test_cases = self.num_test_cases + self.num_leak_iters + + def countTestCases(self): + return self.num_test_cases + + def __call__(self, result=None): + # For the COM suite's sake, always ensure we don't leak + # gateways/interfaces + from pythoncom import _GetGatewayCount, _GetInterfaceCount + + gc.collect() + ni = _GetInterfaceCount() + ng = _GetGatewayCount() + self.real_test(result) + # Failed - no point checking anything else + if result.shouldStop or not result.wasSuccessful(): + return + self._do_leak_tests(result) + gc.collect() + lost_i = _GetInterfaceCount() - ni + lost_g = _GetGatewayCount() - ng + if lost_i or lost_g: + msg = "%d interface objects and %d gateway objects leaked" % ( + lost_i, + lost_g, + ) + exc = AssertionError(msg) + result.addFailure(self.real_test, (exc.__class__, exc, None)) + + def runTest(self): + assert 0, "not used" + + def _do_leak_tests(self, result=None): + try: + gtrc = sys.gettotalrefcount + except AttributeError: + return # can't do leak tests in this build + # Assume already called once, to prime any caches etc + gc.collect() + trc = gtrc() + for i in range(self.num_leak_iters): + self.real_test(result) + if result.shouldStop: + break + del i # created after we remembered the refcount! + # int division here means one or 2 stray references won't force + # failure, but one per loop + gc.collect() + lost = (gtrc() - trc) // self.num_leak_iters + if lost < 0: + msg = "LeakTest: %s appeared to gain %d references!!" % ( + self.real_test, + -lost, + ) + result.addFailure(self.real_test, (AssertionError, msg, None)) + if lost > 0: + msg = "LeakTest: %s lost %d references" % (self.real_test, lost) + exc = AssertionError(msg) + result.addFailure(self.real_test, (exc.__class__, exc, None)) + + +class TestLoader(unittest.TestLoader): + def loadTestsFromTestCase(self, testCaseClass): + """Return a suite of all tests cases contained in testCaseClass""" + leak_tests = [] + for name in self.getTestCaseNames(testCaseClass): + real_test = testCaseClass(name) + leak_test = self._getTestWrapper(real_test) + leak_tests.append(leak_test) + return self.suiteClass(leak_tests) + + def fixupTestsForLeakTests(self, test): + if isinstance(test, unittest.TestSuite): + test._tests = [self.fixupTestsForLeakTests(t) for t in test._tests] + return test + else: + # just a normal test case. + return self._getTestWrapper(test) + + def _getTestWrapper(self, test): + # one or 2 tests in the COM test suite set this... + no_leak_tests = getattr(test, "no_leak_tests", False) + if no_leak_tests: + print("Test says it doesn't want leak tests!") + return test + return LeakTestCase(test) + + def loadTestsFromModule(self, mod): + if hasattr(mod, "suite"): + tests = mod.suite() + else: + tests = unittest.TestLoader.loadTestsFromModule(self, mod) + return self.fixupTestsForLeakTests(tests) + + def loadTestsFromName(self, name, module=None): + test = unittest.TestLoader.loadTestsFromName(self, name, module) + if isinstance(test, unittest.TestSuite): + pass # hmmm? print "Don't wrap suites yet!", test._tests + elif isinstance(test, unittest.TestCase): + test = self._getTestWrapper(test) + else: + print("XXX - what is", test) + return test + + +# Lots of classes necessary to support one simple feature: we want a 3rd +# test result state - "SKIPPED" - to indicate that the test wasn't able +# to be executed for various reasons. Inspired by bzr's tests, but it +# has other concepts, such as "Expected Failure", which we don't bother +# with. + +# win32 error codes that probably mean we need to be elevated (ie, if we +# aren't elevated, we treat these error codes as 'skipped') +non_admin_error_codes = [ + winerror.ERROR_ACCESS_DENIED, + winerror.ERROR_PRIVILEGE_NOT_HELD, +] + +_is_admin = None + + +def check_is_admin(): + global _is_admin + if _is_admin is None: + import pythoncom + from win32com.shell.shell import IsUserAnAdmin + + try: + _is_admin = IsUserAnAdmin() + except pythoncom.com_error as exc: + if exc.hresult != winerror.E_NOTIMPL: + raise + # not impl on this platform - must be old - assume is admin + _is_admin = True + return _is_admin + + +# Find a test "fixture" (eg, binary test file) expected to be very close to +# the test being run. +# If the tests are being run from the "installed" version, then these fixtures +# probably don't exist - the test is "skipped". +# But it's fatal if we think we might be running from a pywin32 source tree. +def find_test_fixture(basename, extra_dir="."): + # look for the test file in various places + candidates = [ + os.path.dirname(sys.argv[0]), + extra_dir, + ".", + ] + for candidate in candidates: + fname = os.path.join(candidate, basename) + if os.path.isfile(fname): + return fname + else: + # Can't find it - see if this is expected or not. + # This module is typically always in the installed dir, so use argv[0] + this_file = os.path.normcase(os.path.abspath(sys.argv[0])) + dirs_to_check = site.getsitepackages()[:] + if site.USER_SITE: + dirs_to_check.append(site.USER_SITE) + + for d in dirs_to_check: + d = os.path.normcase(d) + if os.path.commonprefix([this_file, d]) == d: + # looks like we are in an installed Python, so skip the text. + raise TestSkipped(f"Can't find test fixture '{fname}'") + # Looks like we are running from source, so this is fatal. + raise RuntimeError(f"Can't find test fixture '{fname}'") + + +# If this exception is raised by a test, the test is reported as a 'skip' +class TestSkipped(Exception): + pass + + +# This appears to have been "upgraded" to non-private in 3.11 +try: + TextTestResult = unittest._TextTestResult +except AttributeError: + TextTestResult = unittest.TextTestResult + + +# The 'TestResult' subclass that records the failures and has the special +# handling for the TestSkipped exception. +class TestResult(TextTestResult): + def __init__(self, *args, **kw): + super(TestResult, self).__init__(*args, **kw) + self.skips = {} # count of skips for each reason. + + def addError(self, test, err): + """Called when an error has occurred. 'err' is a tuple of values as + returned by sys.exc_info(). + """ + # translate a couple of 'well-known' exceptions into 'skipped' + import pywintypes + + exc_val = err[1] + # translate ERROR_ACCESS_DENIED for non-admin users to be skipped. + # (access denied errors for an admin user aren't expected.) + if ( + isinstance(exc_val, pywintypes.error) + and exc_val.winerror in non_admin_error_codes + and not check_is_admin() + ): + exc_val = TestSkipped(exc_val) + # and COM errors due to objects not being registered (the com test + # suite will attempt to catch this and handle it itself if the user + # is admin) + elif isinstance(exc_val, pywintypes.com_error) and exc_val.hresult in [ + winerror.CO_E_CLASSSTRING, + winerror.REGDB_E_CLASSNOTREG, + winerror.TYPE_E_LIBNOTREGISTERED, + ]: + exc_val = TestSkipped(exc_val) + # NotImplemented generally means the platform doesn't support the + # functionality. + elif isinstance(exc_val, NotImplementedError): + exc_val = TestSkipped(NotImplementedError) + + if isinstance(exc_val, TestSkipped): + reason = exc_val.args[0] + # if the reason itself is another exception, get its args. + try: + reason = tuple(reason.args) + except (AttributeError, TypeError): + pass + self.skips.setdefault(reason, 0) + self.skips[reason] += 1 + if self.showAll: + self.stream.writeln("SKIP (%s)" % (reason,)) + elif self.dots: + self.stream.write("S") + self.stream.flush() + return + super(TestResult, self).addError(test, err) + + def printErrors(self): + super(TestResult, self).printErrors() + for reason, num_skipped in self.skips.items(): + self.stream.writeln("SKIPPED: %d tests - %s" % (num_skipped, reason)) + + +# TestRunner subclass necessary just to get our TestResult hooked up. +class TestRunner(unittest.TextTestRunner): + def _makeResult(self): + return TestResult(self.stream, self.descriptions, self.verbosity) + + +# TestProgream subclass necessary just to get our TestRunner hooked up, +# which is necessary to get our TestResult hooked up *sob* +class TestProgram(unittest.TestProgram): + def runTests(self): + # clobber existing runner - *sob* - it shouldn't be this hard + self.testRunner = TestRunner(verbosity=self.verbosity) + unittest.TestProgram.runTests(self) + + +# A convenient entry-point - if used, 'SKIPPED' exceptions will be supressed. +def testmain(*args, **kw): + new_kw = kw.copy() + if "testLoader" not in new_kw: + new_kw["testLoader"] = TestLoader() + program_class = new_kw.get("testProgram", TestProgram) + program_class(*args, **new_kw) diff --git a/MLPY/Lib/site-packages/win32/lib/pywintypes.py b/MLPY/Lib/site-packages/win32/lib/pywintypes.py new file mode 100644 index 0000000000000000000000000000000000000000..115c4f82f75968698b2f670cc31c2b1f38fc91eb --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/pywintypes.py @@ -0,0 +1,126 @@ +# Magic utility that "redirects" to pywintypesxx.dll +import importlib.machinery +import importlib.util +import os +import sys + + +def __import_pywin32_system_module__(modname, globs): + # This has been through a number of iterations. The problem: how to + # locate pywintypesXX.dll when it may be in a number of places, and how + # to avoid ever loading it twice. This problem is compounded by the + # fact that the "right" way to do this requires win32api, but this + # itself requires pywintypesXX. + # And the killer problem is that someone may have done 'import win32api' + # before this code is called. In that case Windows will have already + # loaded pywintypesXX as part of loading win32api - but by the time + # we get here, we may locate a different one. This appears to work, but + # then starts raising bizarre TypeErrors complaining that something + # is not a pywintypes type when it clearly is! + + # So in what we hope is the last major iteration of this, we now + # rely on a _win32sysloader module, implemented in C but not relying + # on pywintypesXX.dll. It then can check if the DLL we are looking for + # lib is already loaded. + # See if this is a debug build. + suffix = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else "" + filename = "%s%d%d%s.dll" % ( + modname, + sys.version_info[0], + sys.version_info[1], + suffix, + ) + if hasattr(sys, "frozen"): + # If we are running from a frozen program (py2exe, McMillan, freeze) + # then we try and load the DLL from our sys.path + # XXX - This path may also benefit from _win32sysloader? However, + # MarkH has never seen the DLL load problem with py2exe programs... + for look in sys.path: + # If the sys.path entry is a (presumably) .zip file, use the + # directory + if os.path.isfile(look): + look = os.path.dirname(look) + found = os.path.join(look, filename) + if os.path.isfile(found): + break + else: + raise ImportError( + "Module '%s' isn't in frozen sys.path %s" % (modname, sys.path) + ) + else: + # First see if it already in our process - if so, we must use that. + import _win32sysloader + + found = _win32sysloader.GetModuleFilename(filename) + if found is None: + # We ask Windows to load it next. This is in an attempt to + # get the exact same module loaded should pywintypes be imported + # first (which is how we are here) or if, eg, win32api was imported + # first thereby implicitly loading the DLL. + + # Sadly though, it doesn't quite work - if pywintypesxx.dll + # is in system32 *and* the executable's directory, on XP SP2, an + # import of win32api will cause Windows to load pywintypes + # from system32, where LoadLibrary for that name will + # load the one in the exe's dir. + # That shouldn't really matter though, so long as we only ever + # get one loaded. + found = _win32sysloader.LoadModule(filename) + if found is None: + # Windows can't find it - which although isn't relevent here, + # means that we *must* be the first win32 import, as an attempt + # to import win32api etc would fail when Windows attempts to + # locate the DLL. + # This is most likely to happen for "non-admin" installs, where + # we can't put the files anywhere else on the global path. + + # If there is a version in our Python directory, use that + if os.path.isfile(os.path.join(sys.prefix, filename)): + found = os.path.join(sys.prefix, filename) + if found is None: + # Not in the Python directory? Maybe we were installed via + # easy_install... + if os.path.isfile(os.path.join(os.path.dirname(__file__), filename)): + found = os.path.join(os.path.dirname(__file__), filename) + + # There are 2 site-packages directories - one "global" and one "user". + # We could be in either, or both (but with different versions!). Factors include + # virtualenvs, post-install script being run or not, `setup.py install` flags, etc. + + # In a worst-case, it means, say 'python -c "import win32api"' + # will not work but 'python -c "import pywintypes, win32api"' will, + # but it's better than nothing. + + # We use the same logic as pywin32_bootstrap to find potential location for the dll + # Simply import pywin32_system32 and look in the paths in pywin32_system32.__path__ + + if found is None: + import pywin32_system32 + + for path in pywin32_system32.__path__: + maybe = os.path.join(path, filename) + if os.path.isfile(maybe): + found = maybe + break + + if found is None: + # give up in disgust. + raise ImportError("No system module '%s' (%s)" % (modname, filename)) + # After importing the module, sys.modules is updated to the DLL we just + # loaded - which isn't what we want. So we update sys.modules to refer to + # this module, and update our globals from it. + old_mod = sys.modules[modname] + # Load the DLL. + loader = importlib.machinery.ExtensionFileLoader(modname, found) + spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=found) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + + # Check the sys.modules[] behaviour we describe above is true... + assert sys.modules[modname] is mod + # as above - re-reset to the *old* module object then update globs. + sys.modules[modname] = old_mod + globs.update(mod.__dict__) + + +__import_pywin32_system_module__("pywintypes", globals()) diff --git a/MLPY/Lib/site-packages/win32/lib/rasutil.py b/MLPY/Lib/site-packages/win32/lib/rasutil.py new file mode 100644 index 0000000000000000000000000000000000000000..fb71b4fc53d0b39d54f7cab0ad3dd4d4e275c092 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/rasutil.py @@ -0,0 +1,40 @@ +import win32ras + +stateStrings = { + win32ras.RASCS_OpenPort: "OpenPort", + win32ras.RASCS_PortOpened: "PortOpened", + win32ras.RASCS_ConnectDevice: "ConnectDevice", + win32ras.RASCS_DeviceConnected: "DeviceConnected", + win32ras.RASCS_AllDevicesConnected: "AllDevicesConnected", + win32ras.RASCS_Authenticate: "Authenticate", + win32ras.RASCS_AuthNotify: "AuthNotify", + win32ras.RASCS_AuthRetry: "AuthRetry", + win32ras.RASCS_AuthCallback: "AuthCallback", + win32ras.RASCS_AuthChangePassword: "AuthChangePassword", + win32ras.RASCS_AuthProject: "AuthProject", + win32ras.RASCS_AuthLinkSpeed: "AuthLinkSpeed", + win32ras.RASCS_AuthAck: "AuthAck", + win32ras.RASCS_ReAuthenticate: "ReAuthenticate", + win32ras.RASCS_Authenticated: "Authenticated", + win32ras.RASCS_PrepareForCallback: "PrepareForCallback", + win32ras.RASCS_WaitForModemReset: "WaitForModemReset", + win32ras.RASCS_WaitForCallback: "WaitForCallback", + win32ras.RASCS_Projected: "Projected", + win32ras.RASCS_StartAuthentication: "StartAuthentication", + win32ras.RASCS_CallbackComplete: "CallbackComplete", + win32ras.RASCS_LogonNetwork: "LogonNetwork", + win32ras.RASCS_Interactive: "Interactive", + win32ras.RASCS_RetryAuthentication: "RetryAuthentication", + win32ras.RASCS_CallbackSetByCaller: "CallbackSetByCaller", + win32ras.RASCS_PasswordExpired: "PasswordExpired", + win32ras.RASCS_Connected: "Connected", + win32ras.RASCS_Disconnected: "Disconnected", +} + + +def TestCallback(hras, msg, state, error, exterror): + print("Callback called with ", hras, msg, stateStrings[state], error, exterror) + + +def test(rasName="_ Divert Off"): + return win32ras.Dial(None, None, (rasName,), TestCallback) diff --git a/MLPY/Lib/site-packages/win32/lib/regcheck.py b/MLPY/Lib/site-packages/win32/lib/regcheck.py new file mode 100644 index 0000000000000000000000000000000000000000..c07b77b7a684e47ab2e416c36d9d580494aabf78 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/regcheck.py @@ -0,0 +1,162 @@ +# This module is very old and useless in this day and age! It will be +# removed in a few years (ie, 2009 or so...) + +import warnings + +warnings.warn( + "The regcheck module has been pending deprecation since build 210", + category=PendingDeprecationWarning, +) + +import os +import sys + +import regutil +import win32api +import win32con + + +def CheckRegisteredExe(exename): + try: + os.stat( + win32api.RegQueryValue( + regutil.GetRootKey(), regutil.GetAppPathsKey() + "\\" + exename + ) + ) + # except SystemError: + except (os.error, win32api.error): + print("Registration of %s - Not registered correctly" % exename) + + +def CheckPathString(pathString): + for path in pathString.split(";"): + if not os.path.isdir(path): + return "'%s' is not a valid directory!" % path + return None + + +def CheckPythonPaths(verbose): + if verbose: + print("Python Paths:") + # Check the core path + if verbose: + print("\tCore Path:", end=" ") + try: + appPath = win32api.RegQueryValue( + regutil.GetRootKey(), regutil.BuildDefaultPythonKey() + "\\PythonPath" + ) + except win32api.error as exc: + print("** does not exist - ", exc.strerror) + problem = CheckPathString(appPath) + if problem: + print(problem) + else: + if verbose: + print(appPath) + + key = win32api.RegOpenKey( + regutil.GetRootKey(), + regutil.BuildDefaultPythonKey() + "\\PythonPath", + 0, + win32con.KEY_READ, + ) + try: + keyNo = 0 + while 1: + try: + appName = win32api.RegEnumKey(key, keyNo) + appPath = win32api.RegQueryValue(key, appName) + if verbose: + print("\t" + appName + ":", end=" ") + if appPath: + problem = CheckPathString(appPath) + if problem: + print(problem) + else: + if verbose: + print(appPath) + else: + if verbose: + print("(empty)") + keyNo = keyNo + 1 + except win32api.error: + break + finally: + win32api.RegCloseKey(key) + + +def CheckHelpFiles(verbose): + if verbose: + print("Help Files:") + try: + key = win32api.RegOpenKey( + regutil.GetRootKey(), + regutil.BuildDefaultPythonKey() + "\\Help", + 0, + win32con.KEY_READ, + ) + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + return + + try: + keyNo = 0 + while 1: + try: + helpDesc = win32api.RegEnumKey(key, keyNo) + helpFile = win32api.RegQueryValue(key, helpDesc) + if verbose: + print("\t" + helpDesc + ":", end=" ") + # query the os section. + try: + os.stat(helpFile) + if verbose: + print(helpFile) + except os.error: + print("** Help file %s does not exist" % helpFile) + keyNo = keyNo + 1 + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_NO_MORE_ITEMS: + raise + break + finally: + win32api.RegCloseKey(key) + + +def CheckRegisteredModules(verbose): + # Check out all registered modules. + k = regutil.BuildDefaultPythonKey() + "\\Modules" + try: + keyhandle = win32api.RegOpenKey(regutil.GetRootKey(), k) + print("WARNING: 'Modules' registry entry is deprectated and evil!") + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + return + + +def CheckRegistry(verbose=0): + # check the registered modules + if verbose and "pythonpath" in os.environ: + print("Warning - PythonPath in environment - please check it!") + # Check out all paths on sys.path + + CheckPythonPaths(verbose) + CheckHelpFiles(verbose) + CheckRegisteredModules(verbose) + CheckRegisteredExe("Python.exe") + + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "-q": + verbose = 0 + else: + verbose = 1 + CheckRegistry(verbose) diff --git a/MLPY/Lib/site-packages/win32/lib/regutil.py b/MLPY/Lib/site-packages/win32/lib/regutil.py new file mode 100644 index 0000000000000000000000000000000000000000..1abdd551a91f85b68574a7b77e5a18c6fcb607c9 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/regutil.py @@ -0,0 +1,397 @@ +# Some registry helpers. +import os +import sys + +import win32api +import win32con + +error = "Registry utility error" + +# A .py file has a CLSID associated with it (why? - dunno!) +CLSIDPyFile = "{b51df050-06ae-11cf-ad3b-524153480001}" + +RegistryIDPyFile = "Python.File" # The registry "file type" of a .py file +RegistryIDPycFile = "Python.CompiledFile" # The registry "file type" of a .pyc file + + +def BuildDefaultPythonKey(): + """Builds a string containing the path to the current registry key. + + The Python registry key contains the Python version. This function + uses the version of the DLL used by the current process to get the + registry key currently in use. + """ + return "Software\\Python\\PythonCore\\" + sys.winver + + +def GetRootKey(): + """Retrieves the Registry root in use by Python.""" + keyname = BuildDefaultPythonKey() + try: + k = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, keyname) + k.close() + return win32con.HKEY_CURRENT_USER + except win32api.error: + return win32con.HKEY_LOCAL_MACHINE + + +def GetRegistryDefaultValue(subkey, rootkey=None): + """A helper to return the default value for a key in the registry.""" + if rootkey is None: + rootkey = GetRootKey() + return win32api.RegQueryValue(rootkey, subkey) + + +def SetRegistryDefaultValue(subKey, value, rootkey=None): + """A helper to set the default value for a key in the registry""" + if rootkey is None: + rootkey = GetRootKey() + if type(value) == str: + typeId = win32con.REG_SZ + elif type(value) == int: + typeId = win32con.REG_DWORD + else: + raise TypeError("Value must be string or integer - was passed " + repr(value)) + + win32api.RegSetValue(rootkey, subKey, typeId, value) + + +def GetAppPathsKey(): + return "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths" + + +def RegisterPythonExe(exeFullPath, exeAlias=None, exeAppPath=None): + """Register a .exe file that uses Python. + + Registers the .exe with the OS. This allows the specified .exe to + be run from the command-line or start button without using the full path, + and also to setup application specific path (ie, os.environ['PATH']). + + Currently the exeAppPath is not supported, so this function is general + purpose, and not specific to Python at all. Later, exeAppPath may provide + a reasonable default that is used. + + exeFullPath -- The full path to the .exe + exeAlias = None -- An alias for the exe - if none, the base portion + of the filename is used. + exeAppPath -- Not supported. + """ + # Note - Dont work on win32s (but we dont care anymore!) + if exeAppPath: + raise error("Do not support exeAppPath argument currently") + if exeAlias is None: + exeAlias = os.path.basename(exeFullPath) + win32api.RegSetValue( + GetRootKey(), GetAppPathsKey() + "\\" + exeAlias, win32con.REG_SZ, exeFullPath + ) + + +def GetRegisteredExe(exeAlias): + """Get a registered .exe""" + return win32api.RegQueryValue(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias) + + +def UnregisterPythonExe(exeAlias): + """Unregister a .exe file that uses Python.""" + try: + win32api.RegDeleteKey(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias) + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + return + + +def RegisterNamedPath(name, path): + """Register a named path - ie, a named PythonPath entry.""" + keyStr = BuildDefaultPythonKey() + "\\PythonPath" + if name: + keyStr = keyStr + "\\" + name + win32api.RegSetValue(GetRootKey(), keyStr, win32con.REG_SZ, path) + + +def UnregisterNamedPath(name): + """Unregister a named path - ie, a named PythonPath entry.""" + keyStr = BuildDefaultPythonKey() + "\\PythonPath\\" + name + try: + win32api.RegDeleteKey(GetRootKey(), keyStr) + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + return + + +def GetRegisteredNamedPath(name): + """Get a registered named path, or None if it doesnt exist.""" + keyStr = BuildDefaultPythonKey() + "\\PythonPath" + if name: + keyStr = keyStr + "\\" + name + try: + return win32api.RegQueryValue(GetRootKey(), keyStr) + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + return None + + +def RegisterModule(modName, modPath): + """Register an explicit module in the registry. This forces the Python import + mechanism to locate this module directly, without a sys.path search. Thus + a registered module need not appear in sys.path at all. + + modName -- The name of the module, as used by import. + modPath -- The full path and file name of the module. + """ + try: + import os + + os.stat(modPath) + except os.error: + print("Warning: Registering non-existant module %s" % modPath) + win32api.RegSetValue( + GetRootKey(), + BuildDefaultPythonKey() + "\\Modules\\%s" % modName, + win32con.REG_SZ, + modPath, + ) + + +def UnregisterModule(modName): + """Unregister an explicit module in the registry. + + modName -- The name of the module, as used by import. + """ + try: + win32api.RegDeleteKey( + GetRootKey(), BuildDefaultPythonKey() + "\\Modules\\%s" % modName + ) + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + + +def GetRegisteredHelpFile(helpDesc): + """Given a description, return the registered entry.""" + try: + return GetRegistryDefaultValue(BuildDefaultPythonKey() + "\\Help\\" + helpDesc) + except win32api.error: + try: + return GetRegistryDefaultValue( + BuildDefaultPythonKey() + "\\Help\\" + helpDesc, + win32con.HKEY_CURRENT_USER, + ) + except win32api.error: + pass + return None + + +def RegisterHelpFile(helpFile, helpPath, helpDesc=None, bCheckFile=1): + """Register a help file in the registry. + + Note that this used to support writing to the Windows Help + key, however this is no longer done, as it seems to be incompatible. + + helpFile -- the base name of the help file. + helpPath -- the path to the help file + helpDesc -- A description for the help file. If None, the helpFile param is used. + bCheckFile -- A flag indicating if the file existence should be checked. + """ + if helpDesc is None: + helpDesc = helpFile + fullHelpFile = os.path.join(helpPath, helpFile) + try: + if bCheckFile: + os.stat(fullHelpFile) + except os.error: + raise ValueError("Help file does not exist") + # Now register with Python itself. + win32api.RegSetValue( + GetRootKey(), + BuildDefaultPythonKey() + "\\Help\\%s" % helpDesc, + win32con.REG_SZ, + fullHelpFile, + ) + + +def UnregisterHelpFile(helpFile, helpDesc=None): + """Unregister a help file in the registry. + + helpFile -- the base name of the help file. + helpDesc -- A description for the help file. If None, the helpFile param is used. + """ + key = win32api.RegOpenKey( + win32con.HKEY_LOCAL_MACHINE, + "Software\\Microsoft\\Windows\\Help", + 0, + win32con.KEY_ALL_ACCESS, + ) + try: + try: + win32api.RegDeleteValue(key, helpFile) + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + finally: + win32api.RegCloseKey(key) + + # Now de-register with Python itself. + if helpDesc is None: + helpDesc = helpFile + try: + win32api.RegDeleteKey( + GetRootKey(), BuildDefaultPythonKey() + "\\Help\\%s" % helpDesc + ) + except win32api.error as exc: + import winerror + + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + + +def RegisterCoreDLL(coredllName=None): + """Registers the core DLL in the registry. + + If no params are passed, the name of the Python DLL used in + the current process is used and registered. + """ + if coredllName is None: + coredllName = win32api.GetModuleFileName(sys.dllhandle) + # must exist! + else: + try: + os.stat(coredllName) + except os.error: + print("Warning: Registering non-existant core DLL %s" % coredllName) + + hKey = win32api.RegCreateKey(GetRootKey(), BuildDefaultPythonKey()) + try: + win32api.RegSetValue(hKey, "Dll", win32con.REG_SZ, coredllName) + finally: + win32api.RegCloseKey(hKey) + # Lastly, setup the current version to point to me. + win32api.RegSetValue( + GetRootKey(), + "Software\\Python\\PythonCore\\CurrentVersion", + win32con.REG_SZ, + sys.winver, + ) + + +def RegisterFileExtensions(defPyIcon, defPycIcon, runCommand): + """Register the core Python file extensions. + + defPyIcon -- The default icon to use for .py files, in 'fname,offset' format. + defPycIcon -- The default icon to use for .pyc files, in 'fname,offset' format. + runCommand -- The command line to use for running .py files + """ + # Register the file extensions. + pythonFileId = RegistryIDPyFile + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, ".py", win32con.REG_SZ, pythonFileId + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, pythonFileId, win32con.REG_SZ, "Python File" + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + "%s\\CLSID" % pythonFileId, + win32con.REG_SZ, + CLSIDPyFile, + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + "%s\\DefaultIcon" % pythonFileId, + win32con.REG_SZ, + defPyIcon, + ) + base = "%s\\Shell" % RegistryIDPyFile + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, base + "\\Open", win32con.REG_SZ, "Run" + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + base + "\\Open\\Command", + win32con.REG_SZ, + runCommand, + ) + + # Register the .PYC. + pythonFileId = RegistryIDPycFile + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, ".pyc", win32con.REG_SZ, pythonFileId + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + pythonFileId, + win32con.REG_SZ, + "Compiled Python File", + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + "%s\\DefaultIcon" % pythonFileId, + win32con.REG_SZ, + defPycIcon, + ) + base = "%s\\Shell" % pythonFileId + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, base + "\\Open", win32con.REG_SZ, "Run" + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + base + "\\Open\\Command", + win32con.REG_SZ, + runCommand, + ) + + +def RegisterShellCommand(shellCommand, exeCommand, shellUserCommand=None): + # Last param for "Open" - for a .py file to be executed by the command line + # or shell execute (eg, just entering "foo.py"), the Command must be "Open", + # but you may associate a different name for the right-click menu. + # In our case, normally we have "Open=Run" + base = "%s\\Shell" % RegistryIDPyFile + if shellUserCommand: + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + base + "\\%s" % (shellCommand), + win32con.REG_SZ, + shellUserCommand, + ) + + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + base + "\\%s\\Command" % (shellCommand), + win32con.REG_SZ, + exeCommand, + ) + + +def RegisterDDECommand(shellCommand, ddeApp, ddeTopic, ddeCommand): + base = "%s\\Shell" % RegistryIDPyFile + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + base + "\\%s\\ddeexec" % (shellCommand), + win32con.REG_SZ, + ddeCommand, + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + base + "\\%s\\ddeexec\\Application" % (shellCommand), + win32con.REG_SZ, + ddeApp, + ) + win32api.RegSetValue( + win32con.HKEY_CLASSES_ROOT, + base + "\\%s\\ddeexec\\Topic" % (shellCommand), + win32con.REG_SZ, + ddeTopic, + ) diff --git a/MLPY/Lib/site-packages/win32/lib/sspi.py b/MLPY/Lib/site-packages/win32/lib/sspi.py new file mode 100644 index 0000000000000000000000000000000000000000..22c0e4a0eb0592fbb0dbb61eb79f19de0ae2b34a --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/sspi.py @@ -0,0 +1,412 @@ +""" +Helper classes for SSPI authentication via the win32security module. + +SSPI authentication involves a token-exchange "dance", the exact details +of which depends on the authentication provider used. There are also +a number of complex flags and constants that need to be used - in most +cases, there are reasonable defaults. + +These classes attempt to hide these details from you until you really need +to know. They are not designed to handle all cases, just the common ones. +If you need finer control than offered here, just use the win32security +functions directly. +""" +# Based on Roger Upole's sspi demos. +# $Id$ +import sspicon +import win32security + +error = win32security.error + + +class _BaseAuth(object): + def __init__(self): + self.reset() + + def reset(self): + """Reset everything to an unauthorized state""" + self.ctxt = None + self.authenticated = False + self.initiator_name = None + self.service_name = None + + # The next seq_num for an encrypt/sign operation + self.next_seq_num = 0 + + def _get_next_seq_num(self): + """Get the next sequence number for a transmission. Default + implementation is to increment a counter + """ + ret = self.next_seq_num + self.next_seq_num = self.next_seq_num + 1 + return ret + + def encrypt(self, data): + """Encrypt a string, returning a tuple of (encrypted_data, trailer). + These can be passed to decrypt to get back the original string. + """ + pkg_size_info = self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES) + trailersize = pkg_size_info["SecurityTrailer"] + + encbuf = win32security.PySecBufferDescType() + encbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + encbuf.append( + win32security.PySecBufferType(trailersize, sspicon.SECBUFFER_TOKEN) + ) + encbuf[0].Buffer = data + self.ctxt.EncryptMessage(0, encbuf, self._get_next_seq_num()) + return encbuf[0].Buffer, encbuf[1].Buffer + + def decrypt(self, data, trailer): + """Decrypt a previously encrypted string, returning the orignal data""" + encbuf = win32security.PySecBufferDescType() + encbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + encbuf.append( + win32security.PySecBufferType(len(trailer), sspicon.SECBUFFER_TOKEN) + ) + encbuf[0].Buffer = data + encbuf[1].Buffer = trailer + self.ctxt.DecryptMessage(encbuf, self._get_next_seq_num()) + return encbuf[0].Buffer + + def sign(self, data): + """sign a string suitable for transmission, returning the signature. + Passing the data and signature to verify will determine if the data + is unchanged. + """ + pkg_size_info = self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES) + sigsize = pkg_size_info["MaxSignature"] + sigbuf = win32security.PySecBufferDescType() + sigbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + sigbuf.append(win32security.PySecBufferType(sigsize, sspicon.SECBUFFER_TOKEN)) + sigbuf[0].Buffer = data + + self.ctxt.MakeSignature(0, sigbuf, self._get_next_seq_num()) + return sigbuf[1].Buffer + + def verify(self, data, sig): + """Verifies data and its signature. If verification fails, an sspi.error + will be raised. + """ + sigbuf = win32security.PySecBufferDescType() + sigbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + sigbuf.append(win32security.PySecBufferType(len(sig), sspicon.SECBUFFER_TOKEN)) + + sigbuf[0].Buffer = data + sigbuf[1].Buffer = sig + self.ctxt.VerifySignature(sigbuf, self._get_next_seq_num()) + + def unwrap(self, token): + """ + GSSAPI's unwrap with SSPI. + https://docs.microsoft.com/en-us/windows/win32/secauthn/sspi-kerberos-interoperability-with-gssapi + + Usable mainly with Kerberos SSPI package, but this is not enforced. + + Return the clear text, and a boolean that is True if the token was encrypted. + """ + buffer = win32security.PySecBufferDescType() + # This buffer will contain a "stream", which is the token coming from the other side + buffer.append( + win32security.PySecBufferType(len(token), sspicon.SECBUFFER_STREAM) + ) + buffer[0].Buffer = token + + # This buffer will receive the clear, or just unwrapped text if no encryption was used. + # Will be resized by the lib. + buffer.append(win32security.PySecBufferType(0, sspicon.SECBUFFER_DATA)) + + pfQOP = self.ctxt.DecryptMessage(buffer, self._get_next_seq_num()) + + r = buffer[1].Buffer + return r, not (pfQOP == sspicon.SECQOP_WRAP_NO_ENCRYPT) + + def wrap(self, msg, encrypt=False): + """ + GSSAPI's wrap with SSPI. + https://docs.microsoft.com/en-us/windows/win32/secauthn/sspi-kerberos-interoperability-with-gssapi + + Usable mainly with Kerberos SSPI package, but this is not enforced. + + Wrap a message to be sent to the other side. Encrypted if encrypt is True. + """ + + size_info = self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES) + trailer_size = size_info["SecurityTrailer"] + block_size = size_info["BlockSize"] + + buffer = win32security.PySecBufferDescType() + + # This buffer will contain unencrypted data to wrap, and maybe encrypt. + buffer.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA)) + buffer[0].Buffer = msg + + # Will receive the token that forms the beginning of the msg + buffer.append( + win32security.PySecBufferType(trailer_size, sspicon.SECBUFFER_TOKEN) + ) + + # The trailer is needed in case of block encryption + buffer.append( + win32security.PySecBufferType(block_size, sspicon.SECBUFFER_PADDING) + ) + + fQOP = 0 if encrypt else sspicon.SECQOP_WRAP_NO_ENCRYPT + self.ctxt.EncryptMessage(fQOP, buffer, self._get_next_seq_num()) + + # Sec token, then data, then padding + r = buffer[1].Buffer + buffer[0].Buffer + buffer[2].Buffer + return r + + def _amend_ctx_name(self): + """Adds initiator and service names in the security context for ease of use""" + if not self.authenticated: + raise ValueError("Sec context is not completely authenticated") + + try: + names = self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_NATIVE_NAMES) + except error: + # The SSP doesn't provide these attributes. + pass + else: + self.initiator_name, self.service_name = names + + +class ClientAuth(_BaseAuth): + """Manages the client side of an SSPI authentication handshake""" + + def __init__( + self, + pkg_name, # Name of the package to used. + client_name=None, # User for whom credentials are used. + auth_info=None, # or a tuple of (username, domain, password) + targetspn=None, # Target security context provider name. + scflags=None, # security context flags + datarep=sspicon.SECURITY_NETWORK_DREP, + ): + if scflags is None: + scflags = ( + sspicon.ISC_REQ_INTEGRITY + | sspicon.ISC_REQ_SEQUENCE_DETECT + | sspicon.ISC_REQ_REPLAY_DETECT + | sspicon.ISC_REQ_CONFIDENTIALITY + ) + self.scflags = scflags + self.datarep = datarep + self.targetspn = targetspn + self.pkg_info = win32security.QuerySecurityPackageInfo(pkg_name) + ( + self.credentials, + self.credentials_expiry, + ) = win32security.AcquireCredentialsHandle( + client_name, + self.pkg_info["Name"], + sspicon.SECPKG_CRED_OUTBOUND, + None, + auth_info, + ) + _BaseAuth.__init__(self) + + def authorize(self, sec_buffer_in): + """Perform *one* step of the client authentication process. Pass None for the first round""" + if ( + sec_buffer_in is not None + and type(sec_buffer_in) != win32security.PySecBufferDescType + ): + # User passed us the raw data - wrap it into a SecBufferDesc + sec_buffer_new = win32security.PySecBufferDescType() + tokenbuf = win32security.PySecBufferType( + self.pkg_info["MaxToken"], sspicon.SECBUFFER_TOKEN + ) + tokenbuf.Buffer = sec_buffer_in + sec_buffer_new.append(tokenbuf) + sec_buffer_in = sec_buffer_new + sec_buffer_out = win32security.PySecBufferDescType() + tokenbuf = win32security.PySecBufferType( + self.pkg_info["MaxToken"], sspicon.SECBUFFER_TOKEN + ) + sec_buffer_out.append(tokenbuf) + ## input context handle should be NULL on first call + ctxtin = self.ctxt + if self.ctxt is None: + self.ctxt = win32security.PyCtxtHandleType() + err, attr, exp = win32security.InitializeSecurityContext( + self.credentials, + ctxtin, + self.targetspn, + self.scflags, + self.datarep, + sec_buffer_in, + self.ctxt, + sec_buffer_out, + ) + # Stash these away incase someone needs to know the state from the + # final call. + self.ctxt_attr = attr + self.ctxt_expiry = exp + + if err in (sspicon.SEC_I_COMPLETE_NEEDED, sspicon.SEC_I_COMPLETE_AND_CONTINUE): + self.ctxt.CompleteAuthToken(sec_buffer_out) + + self.authenticated = err == 0 + if self.authenticated: + self._amend_ctx_name() + + return err, sec_buffer_out + + +class ServerAuth(_BaseAuth): + """Manages the server side of an SSPI authentication handshake""" + + def __init__( + self, pkg_name, spn=None, scflags=None, datarep=sspicon.SECURITY_NETWORK_DREP + ): + self.spn = spn + self.datarep = datarep + + if scflags is None: + scflags = ( + sspicon.ASC_REQ_INTEGRITY + | sspicon.ASC_REQ_SEQUENCE_DETECT + | sspicon.ASC_REQ_REPLAY_DETECT + | sspicon.ASC_REQ_CONFIDENTIALITY + ) + # Should we default to sspicon.KerbAddExtraCredentialsMessage + # if pkg_name=='Kerberos'? + self.scflags = scflags + + self.pkg_info = win32security.QuerySecurityPackageInfo(pkg_name) + + ( + self.credentials, + self.credentials_expiry, + ) = win32security.AcquireCredentialsHandle( + spn, self.pkg_info["Name"], sspicon.SECPKG_CRED_INBOUND, None, None + ) + _BaseAuth.__init__(self) + + def authorize(self, sec_buffer_in): + """Perform *one* step of the server authentication process.""" + if ( + sec_buffer_in is not None + and type(sec_buffer_in) != win32security.PySecBufferDescType + ): + # User passed us the raw data - wrap it into a SecBufferDesc + sec_buffer_new = win32security.PySecBufferDescType() + tokenbuf = win32security.PySecBufferType( + self.pkg_info["MaxToken"], sspicon.SECBUFFER_TOKEN + ) + tokenbuf.Buffer = sec_buffer_in + sec_buffer_new.append(tokenbuf) + sec_buffer_in = sec_buffer_new + + sec_buffer_out = win32security.PySecBufferDescType() + tokenbuf = win32security.PySecBufferType( + self.pkg_info["MaxToken"], sspicon.SECBUFFER_TOKEN + ) + sec_buffer_out.append(tokenbuf) + ## input context handle is None initially, then handle returned from last call thereafter + ctxtin = self.ctxt + if self.ctxt is None: + self.ctxt = win32security.PyCtxtHandleType() + err, attr, exp = win32security.AcceptSecurityContext( + self.credentials, + ctxtin, + sec_buffer_in, + self.scflags, + self.datarep, + self.ctxt, + sec_buffer_out, + ) + + # Stash these away incase someone needs to know the state from the + # final call. + self.ctxt_attr = attr + self.ctxt_expiry = exp + + if err in (sspicon.SEC_I_COMPLETE_NEEDED, sspicon.SEC_I_COMPLETE_AND_CONTINUE): + self.ctxt.CompleteAuthToken(sec_buffer_out) + + self.authenticated = err == 0 + if self.authenticated: + self._amend_ctx_name() + + return err, sec_buffer_out + + +if __name__ == "__main__": + # This is the security package (the security support provider / the security backend) + # we want to use for this example. + ssp = "Kerberos" # or "NTLM" or "Negotiate" which enable negotiation between + # Kerberos (prefered) and NTLM (if not supported on the other side). + + flags = ( + sspicon.ISC_REQ_MUTUAL_AUTH + | sspicon.ISC_REQ_INTEGRITY # mutual authentication + | sspicon.ISC_REQ_SEQUENCE_DETECT # check for integrity + | sspicon.ISC_REQ_CONFIDENTIALITY # enable out-of-order messages + | sspicon.ISC_REQ_REPLAY_DETECT # request confidentiality # request replay detection + ) + + # Get our identity, mandatory for the Kerberos case *for this example* + # Kerberos cannot be used if we don't tell it the target we want + # to authenticate to. + cred_handle, exp = win32security.AcquireCredentialsHandle( + None, ssp, sspicon.SECPKG_CRED_INBOUND, None, None + ) + cred = cred_handle.QueryCredentialsAttributes(sspicon.SECPKG_CRED_ATTR_NAMES) + print("We are:", cred) + + # Setup the 2 contexts. In real life, only one is needed: the other one is + # created in the process we want to communicate with. + sspiclient = ClientAuth(ssp, scflags=flags, targetspn=cred) + sspiserver = ServerAuth(ssp, scflags=flags) + + print( + "SSP : %s (%s)" % (sspiclient.pkg_info["Name"], sspiclient.pkg_info["Comment"]) + ) + + # Perform the authentication dance, each loop exchanging more information + # on the way to completing authentication. + sec_buffer = None + client_step = 0 + server_step = 0 + while not (sspiclient.authenticated) or len(sec_buffer[0].Buffer): + client_step += 1 + err, sec_buffer = sspiclient.authorize(sec_buffer) + print("Client step %s" % client_step) + if sspiserver.authenticated and len(sec_buffer[0].Buffer) == 0: + break + + server_step += 1 + err, sec_buffer = sspiserver.authorize(sec_buffer) + print("Server step %s" % server_step) + + # Authentication process is finished. + print("Initiator name from the service side:", sspiserver.initiator_name) + print("Service name from the client side: ", sspiclient.service_name) + + data = "hello".encode("ascii") # py3k-friendly + + # Simple signature, not compatible with GSSAPI. + sig = sspiclient.sign(data) + sspiserver.verify(data, sig) + + # Encryption + encrypted, sig = sspiclient.encrypt(data) + decrypted = sspiserver.decrypt(encrypted, sig) + assert decrypted == data + + # GSSAPI wrapping, no encryption (NTLM always encrypts) + wrapped = sspiclient.wrap(data) + unwrapped, was_encrypted = sspiserver.unwrap(wrapped) + print("encrypted ?", was_encrypted) + assert data == unwrapped + + # GSSAPI wrapping, with encryption + wrapped = sspiserver.wrap(data, encrypt=True) + unwrapped, was_encrypted = sspiclient.unwrap(wrapped) + print("encrypted ?", was_encrypted) + assert data == unwrapped + + print("cool!") diff --git a/MLPY/Lib/site-packages/win32/lib/sspicon.py b/MLPY/Lib/site-packages/win32/lib/sspicon.py new file mode 100644 index 0000000000000000000000000000000000000000..12f7482d8678bbe7bbfba465bab5704d26c2372f --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/sspicon.py @@ -0,0 +1,477 @@ +# Generated by h2py from c:\microsoft sdk\include\sspi.h +ISSP_LEVEL = 32 +ISSP_MODE = 1 + + +def SEC_SUCCESS(Status): + return (Status) >= 0 + + +SECPKG_FLAG_INTEGRITY = 1 +SECPKG_FLAG_PRIVACY = 2 +SECPKG_FLAG_TOKEN_ONLY = 4 +SECPKG_FLAG_DATAGRAM = 8 +SECPKG_FLAG_CONNECTION = 16 +SECPKG_FLAG_MULTI_REQUIRED = 32 +SECPKG_FLAG_CLIENT_ONLY = 64 +SECPKG_FLAG_EXTENDED_ERROR = 128 +SECPKG_FLAG_IMPERSONATION = 256 +SECPKG_FLAG_ACCEPT_WIN32_NAME = 512 +SECPKG_FLAG_STREAM = 1024 +SECPKG_FLAG_NEGOTIABLE = 2048 +SECPKG_FLAG_GSS_COMPATIBLE = 4096 +SECPKG_FLAG_LOGON = 8192 +SECPKG_FLAG_ASCII_BUFFERS = 16384 +SECPKG_FLAG_FRAGMENT = 32768 +SECPKG_FLAG_MUTUAL_AUTH = 65536 +SECPKG_FLAG_DELEGATION = 131072 +SECPKG_FLAG_READONLY_WITH_CHECKSUM = 262144 +SECPKG_ID_NONE = 65535 + +SECBUFFER_VERSION = 0 +SECBUFFER_EMPTY = 0 +SECBUFFER_DATA = 1 +SECBUFFER_TOKEN = 2 +SECBUFFER_PKG_PARAMS = 3 +SECBUFFER_MISSING = 4 +SECBUFFER_EXTRA = 5 +SECBUFFER_STREAM_TRAILER = 6 +SECBUFFER_STREAM_HEADER = 7 +SECBUFFER_NEGOTIATION_INFO = 8 +SECBUFFER_PADDING = 9 +SECBUFFER_STREAM = 10 +SECBUFFER_MECHLIST = 11 +SECBUFFER_MECHLIST_SIGNATURE = 12 +SECBUFFER_TARGET = 13 +SECBUFFER_CHANNEL_BINDINGS = 14 +SECBUFFER_ATTRMASK = -268435456 +SECBUFFER_READONLY = -2147483648 +SECBUFFER_READONLY_WITH_CHECKSUM = 268435456 +SECBUFFER_RESERVED = 1610612736 + +SECURITY_NATIVE_DREP = 16 +SECURITY_NETWORK_DREP = 0 + +SECPKG_CRED_INBOUND = 1 +SECPKG_CRED_OUTBOUND = 2 +SECPKG_CRED_BOTH = 3 +SECPKG_CRED_DEFAULT = 4 +SECPKG_CRED_RESERVED = -268435456 + +ISC_REQ_DELEGATE = 1 +ISC_REQ_MUTUAL_AUTH = 2 +ISC_REQ_REPLAY_DETECT = 4 +ISC_REQ_SEQUENCE_DETECT = 8 +ISC_REQ_CONFIDENTIALITY = 16 +ISC_REQ_USE_SESSION_KEY = 32 +ISC_REQ_PROMPT_FOR_CREDS = 64 +ISC_REQ_USE_SUPPLIED_CREDS = 128 +ISC_REQ_ALLOCATE_MEMORY = 256 +ISC_REQ_USE_DCE_STYLE = 512 +ISC_REQ_DATAGRAM = 1024 +ISC_REQ_CONNECTION = 2048 +ISC_REQ_CALL_LEVEL = 4096 +ISC_REQ_FRAGMENT_SUPPLIED = 8192 +ISC_REQ_EXTENDED_ERROR = 16384 +ISC_REQ_STREAM = 32768 +ISC_REQ_INTEGRITY = 65536 +ISC_REQ_IDENTIFY = 131072 +ISC_REQ_NULL_SESSION = 262144 +ISC_REQ_MANUAL_CRED_VALIDATION = 524288 +ISC_REQ_RESERVED1 = 1048576 +ISC_REQ_FRAGMENT_TO_FIT = 2097152 +ISC_REQ_HTTP = 0x10000000 +ISC_RET_DELEGATE = 1 +ISC_RET_MUTUAL_AUTH = 2 +ISC_RET_REPLAY_DETECT = 4 +ISC_RET_SEQUENCE_DETECT = 8 +ISC_RET_CONFIDENTIALITY = 16 +ISC_RET_USE_SESSION_KEY = 32 +ISC_RET_USED_COLLECTED_CREDS = 64 +ISC_RET_USED_SUPPLIED_CREDS = 128 +ISC_RET_ALLOCATED_MEMORY = 256 +ISC_RET_USED_DCE_STYLE = 512 +ISC_RET_DATAGRAM = 1024 +ISC_RET_CONNECTION = 2048 +ISC_RET_INTERMEDIATE_RETURN = 4096 +ISC_RET_CALL_LEVEL = 8192 +ISC_RET_EXTENDED_ERROR = 16384 +ISC_RET_STREAM = 32768 +ISC_RET_INTEGRITY = 65536 +ISC_RET_IDENTIFY = 131072 +ISC_RET_NULL_SESSION = 262144 +ISC_RET_MANUAL_CRED_VALIDATION = 524288 +ISC_RET_RESERVED1 = 1048576 +ISC_RET_FRAGMENT_ONLY = 2097152 + +ASC_REQ_DELEGATE = 1 +ASC_REQ_MUTUAL_AUTH = 2 +ASC_REQ_REPLAY_DETECT = 4 +ASC_REQ_SEQUENCE_DETECT = 8 +ASC_REQ_CONFIDENTIALITY = 16 +ASC_REQ_USE_SESSION_KEY = 32 +ASC_REQ_ALLOCATE_MEMORY = 256 +ASC_REQ_USE_DCE_STYLE = 512 +ASC_REQ_DATAGRAM = 1024 +ASC_REQ_CONNECTION = 2048 +ASC_REQ_CALL_LEVEL = 4096 +ASC_REQ_EXTENDED_ERROR = 32768 +ASC_REQ_STREAM = 65536 +ASC_REQ_INTEGRITY = 131072 +ASC_REQ_LICENSING = 262144 +ASC_REQ_IDENTIFY = 524288 +ASC_REQ_ALLOW_NULL_SESSION = 1048576 +ASC_REQ_ALLOW_NON_USER_LOGONS = 2097152 +ASC_REQ_ALLOW_CONTEXT_REPLAY = 4194304 +ASC_REQ_FRAGMENT_TO_FIT = 8388608 +ASC_REQ_FRAGMENT_SUPPLIED = 8192 +ASC_REQ_NO_TOKEN = 16777216 +ASC_RET_DELEGATE = 1 +ASC_RET_MUTUAL_AUTH = 2 +ASC_RET_REPLAY_DETECT = 4 +ASC_RET_SEQUENCE_DETECT = 8 +ASC_RET_CONFIDENTIALITY = 16 +ASC_RET_USE_SESSION_KEY = 32 +ASC_RET_ALLOCATED_MEMORY = 256 +ASC_RET_USED_DCE_STYLE = 512 +ASC_RET_DATAGRAM = 1024 +ASC_RET_CONNECTION = 2048 +ASC_RET_CALL_LEVEL = 8192 +ASC_RET_THIRD_LEG_FAILED = 16384 +ASC_RET_EXTENDED_ERROR = 32768 +ASC_RET_STREAM = 65536 +ASC_RET_INTEGRITY = 131072 +ASC_RET_LICENSING = 262144 +ASC_RET_IDENTIFY = 524288 +ASC_RET_NULL_SESSION = 1048576 +ASC_RET_ALLOW_NON_USER_LOGONS = 2097152 +ASC_RET_ALLOW_CONTEXT_REPLAY = 4194304 +ASC_RET_FRAGMENT_ONLY = 8388608 + +SECPKG_CRED_ATTR_NAMES = 1 +SECPKG_ATTR_SIZES = 0 +SECPKG_ATTR_NAMES = 1 +SECPKG_ATTR_LIFESPAN = 2 +SECPKG_ATTR_DCE_INFO = 3 +SECPKG_ATTR_STREAM_SIZES = 4 +SECPKG_ATTR_KEY_INFO = 5 +SECPKG_ATTR_AUTHORITY = 6 +SECPKG_ATTR_PROTO_INFO = 7 +SECPKG_ATTR_PASSWORD_EXPIRY = 8 +SECPKG_ATTR_SESSION_KEY = 9 +SECPKG_ATTR_PACKAGE_INFO = 10 +SECPKG_ATTR_USER_FLAGS = 11 +SECPKG_ATTR_NEGOTIATION_INFO = 12 +SECPKG_ATTR_NATIVE_NAMES = 13 +SECPKG_ATTR_FLAGS = 14 +SECPKG_ATTR_USE_VALIDATED = 15 +SECPKG_ATTR_CREDENTIAL_NAME = 16 +SECPKG_ATTR_TARGET_INFORMATION = 17 +SECPKG_ATTR_ACCESS_TOKEN = 18 +SECPKG_ATTR_TARGET = 19 +SECPKG_ATTR_AUTHENTICATION_ID = 20 + +## attributes from schannel.h +SECPKG_ATTR_REMOTE_CERT_CONTEXT = 83 +SECPKG_ATTR_LOCAL_CERT_CONTEXT = 84 +SECPKG_ATTR_ROOT_STORE = 85 +SECPKG_ATTR_SUPPORTED_ALGS = 86 +SECPKG_ATTR_CIPHER_STRENGTHS = 87 +SECPKG_ATTR_SUPPORTED_PROTOCOLS = 88 +SECPKG_ATTR_ISSUER_LIST_EX = 89 +SECPKG_ATTR_CONNECTION_INFO = 90 +SECPKG_ATTR_EAP_KEY_BLOCK = 91 +SECPKG_ATTR_MAPPED_CRED_ATTR = 92 +SECPKG_ATTR_SESSION_INFO = 93 +SECPKG_ATTR_APP_DATA = 94 + +SECPKG_NEGOTIATION_COMPLETE = 0 +SECPKG_NEGOTIATION_OPTIMISTIC = 1 +SECPKG_NEGOTIATION_IN_PROGRESS = 2 +SECPKG_NEGOTIATION_DIRECT = 3 +SECPKG_NEGOTIATION_TRY_MULTICRED = 4 +SECPKG_CONTEXT_EXPORT_RESET_NEW = 1 +SECPKG_CONTEXT_EXPORT_DELETE_OLD = 2 +SECQOP_WRAP_NO_ENCRYPT = -2147483647 +SECURITY_ENTRYPOINT_ANSIW = "InitSecurityInterfaceW" +SECURITY_ENTRYPOINT_ANSIA = "InitSecurityInterfaceA" +SECURITY_ENTRYPOINT16 = "INITSECURITYINTERFACEA" +SECURITY_ENTRYPOINT = SECURITY_ENTRYPOINT16 +SECURITY_ENTRYPOINT_ANSI = SECURITY_ENTRYPOINT16 +SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION = 1 +SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2 = 2 +SASL_OPTION_SEND_SIZE = 1 +SASL_OPTION_RECV_SIZE = 2 +SASL_OPTION_AUTHZ_STRING = 3 +SASL_OPTION_AUTHZ_PROCESSING = 4 +SEC_WINNT_AUTH_IDENTITY_ANSI = 1 +SEC_WINNT_AUTH_IDENTITY_UNICODE = 2 +SEC_WINNT_AUTH_IDENTITY_VERSION = 512 +SEC_WINNT_AUTH_IDENTITY_MARSHALLED = 4 +SEC_WINNT_AUTH_IDENTITY_ONLY = 8 +SECPKG_OPTIONS_TYPE_UNKNOWN = 0 +SECPKG_OPTIONS_TYPE_LSA = 1 +SECPKG_OPTIONS_TYPE_SSPI = 2 +SECPKG_OPTIONS_PERMANENT = 1 + +SEC_E_INSUFFICIENT_MEMORY = -2146893056 +SEC_E_INVALID_HANDLE = -2146893055 +SEC_E_UNSUPPORTED_FUNCTION = -2146893054 +SEC_E_TARGET_UNKNOWN = -2146893053 +SEC_E_INTERNAL_ERROR = -2146893052 +SEC_E_SECPKG_NOT_FOUND = -2146893051 +SEC_E_NOT_OWNER = -2146893050 +SEC_E_CANNOT_INSTALL = -2146893049 +SEC_E_INVALID_TOKEN = -2146893048 +SEC_E_CANNOT_PACK = -2146893047 +SEC_E_QOP_NOT_SUPPORTED = -2146893046 +SEC_E_NO_IMPERSONATION = -2146893045 +SEC_E_LOGON_DENIED = -2146893044 +SEC_E_UNKNOWN_CREDENTIALS = -2146893043 +SEC_E_NO_CREDENTIALS = -2146893042 +SEC_E_MESSAGE_ALTERED = -2146893041 +SEC_E_OUT_OF_SEQUENCE = -2146893040 +SEC_E_NO_AUTHENTICATING_AUTHORITY = -2146893039 +SEC_I_CONTINUE_NEEDED = 590610 +SEC_I_COMPLETE_NEEDED = 590611 +SEC_I_COMPLETE_AND_CONTINUE = 590612 +SEC_I_LOCAL_LOGON = 590613 +SEC_E_BAD_PKGID = -2146893034 +SEC_E_CONTEXT_EXPIRED = -2146893033 +SEC_I_CONTEXT_EXPIRED = 590615 +SEC_E_INCOMPLETE_MESSAGE = -2146893032 +SEC_E_INCOMPLETE_CREDENTIALS = -2146893024 +SEC_E_BUFFER_TOO_SMALL = -2146893023 +SEC_I_INCOMPLETE_CREDENTIALS = 590624 +SEC_I_RENEGOTIATE = 590625 +SEC_E_WRONG_PRINCIPAL = -2146893022 +SEC_I_NO_LSA_CONTEXT = 590627 +SEC_E_TIME_SKEW = -2146893020 +SEC_E_UNTRUSTED_ROOT = -2146893019 +SEC_E_ILLEGAL_MESSAGE = -2146893018 +SEC_E_CERT_UNKNOWN = -2146893017 +SEC_E_CERT_EXPIRED = -2146893016 +SEC_E_ENCRYPT_FAILURE = -2146893015 +SEC_E_DECRYPT_FAILURE = -2146893008 +SEC_E_ALGORITHM_MISMATCH = -2146893007 +SEC_E_SECURITY_QOS_FAILED = -2146893006 +SEC_E_UNFINISHED_CONTEXT_DELETED = -2146893005 +SEC_E_NO_TGT_REPLY = -2146893004 +SEC_E_NO_IP_ADDRESSES = -2146893003 +SEC_E_WRONG_CREDENTIAL_HANDLE = -2146893002 +SEC_E_CRYPTO_SYSTEM_INVALID = -2146893001 +SEC_E_MAX_REFERRALS_EXCEEDED = -2146893000 +SEC_E_MUST_BE_KDC = -2146892999 +SEC_E_STRONG_CRYPTO_NOT_SUPPORTED = -2146892998 +SEC_E_TOO_MANY_PRINCIPALS = -2146892997 +SEC_E_NO_PA_DATA = -2146892996 +SEC_E_PKINIT_NAME_MISMATCH = -2146892995 +SEC_E_SMARTCARD_LOGON_REQUIRED = -2146892994 +SEC_E_SHUTDOWN_IN_PROGRESS = -2146892993 +SEC_E_KDC_INVALID_REQUEST = -2146892992 +SEC_E_KDC_UNABLE_TO_REFER = -2146892991 +SEC_E_KDC_UNKNOWN_ETYPE = -2146892990 +SEC_E_UNSUPPORTED_PREAUTH = -2146892989 +SEC_E_DELEGATION_REQUIRED = -2146892987 +SEC_E_BAD_BINDINGS = -2146892986 +SEC_E_MULTIPLE_ACCOUNTS = -2146892985 +SEC_E_NO_KERB_KEY = -2146892984 + +ERROR_IPSEC_QM_POLICY_EXISTS = 13000 +ERROR_IPSEC_QM_POLICY_NOT_FOUND = 13001 +ERROR_IPSEC_QM_POLICY_IN_USE = 13002 +ERROR_IPSEC_MM_POLICY_EXISTS = 13003 +ERROR_IPSEC_MM_POLICY_NOT_FOUND = 13004 +ERROR_IPSEC_MM_POLICY_IN_USE = 13005 +ERROR_IPSEC_MM_FILTER_EXISTS = 13006 +ERROR_IPSEC_MM_FILTER_NOT_FOUND = 13007 +ERROR_IPSEC_TRANSPORT_FILTER_EXISTS = 13008 +ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND = 13009 +ERROR_IPSEC_MM_AUTH_EXISTS = 13010 +ERROR_IPSEC_MM_AUTH_NOT_FOUND = 13011 +ERROR_IPSEC_MM_AUTH_IN_USE = 13012 +ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND = 13013 +ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND = 13014 +ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND = 13015 +ERROR_IPSEC_TUNNEL_FILTER_EXISTS = 13016 +ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND = 13017 +ERROR_IPSEC_MM_FILTER_PENDING_DELETION = 13018 +ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION = 13019 +ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION = 13020 +ERROR_IPSEC_MM_POLICY_PENDING_DELETION = 13021 +ERROR_IPSEC_MM_AUTH_PENDING_DELETION = 13022 +ERROR_IPSEC_QM_POLICY_PENDING_DELETION = 13023 +WARNING_IPSEC_MM_POLICY_PRUNED = 13024 +WARNING_IPSEC_QM_POLICY_PRUNED = 13025 +ERROR_IPSEC_IKE_NEG_STATUS_BEGIN = 13800 +ERROR_IPSEC_IKE_AUTH_FAIL = 13801 +ERROR_IPSEC_IKE_ATTRIB_FAIL = 13802 +ERROR_IPSEC_IKE_NEGOTIATION_PENDING = 13803 +ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR = 13804 +ERROR_IPSEC_IKE_TIMED_OUT = 13805 +ERROR_IPSEC_IKE_NO_CERT = 13806 +ERROR_IPSEC_IKE_SA_DELETED = 13807 +ERROR_IPSEC_IKE_SA_REAPED = 13808 +ERROR_IPSEC_IKE_MM_ACQUIRE_DROP = 13809 +ERROR_IPSEC_IKE_QM_ACQUIRE_DROP = 13810 +ERROR_IPSEC_IKE_QUEUE_DROP_MM = 13811 +ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM = 13812 +ERROR_IPSEC_IKE_DROP_NO_RESPONSE = 13813 +ERROR_IPSEC_IKE_MM_DELAY_DROP = 13814 +ERROR_IPSEC_IKE_QM_DELAY_DROP = 13815 +ERROR_IPSEC_IKE_ERROR = 13816 +ERROR_IPSEC_IKE_CRL_FAILED = 13817 +ERROR_IPSEC_IKE_INVALID_KEY_USAGE = 13818 +ERROR_IPSEC_IKE_INVALID_CERT_TYPE = 13819 +ERROR_IPSEC_IKE_NO_PRIVATE_KEY = 13820 +ERROR_IPSEC_IKE_DH_FAIL = 13822 +ERROR_IPSEC_IKE_INVALID_HEADER = 13824 +ERROR_IPSEC_IKE_NO_POLICY = 13825 +ERROR_IPSEC_IKE_INVALID_SIGNATURE = 13826 +ERROR_IPSEC_IKE_KERBEROS_ERROR = 13827 +ERROR_IPSEC_IKE_NO_PUBLIC_KEY = 13828 +ERROR_IPSEC_IKE_PROCESS_ERR = 13829 +ERROR_IPSEC_IKE_PROCESS_ERR_SA = 13830 +ERROR_IPSEC_IKE_PROCESS_ERR_PROP = 13831 +ERROR_IPSEC_IKE_PROCESS_ERR_TRANS = 13832 +ERROR_IPSEC_IKE_PROCESS_ERR_KE = 13833 +ERROR_IPSEC_IKE_PROCESS_ERR_ID = 13834 +ERROR_IPSEC_IKE_PROCESS_ERR_CERT = 13835 +ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ = 13836 +ERROR_IPSEC_IKE_PROCESS_ERR_HASH = 13837 +ERROR_IPSEC_IKE_PROCESS_ERR_SIG = 13838 +ERROR_IPSEC_IKE_PROCESS_ERR_NONCE = 13839 +ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY = 13840 +ERROR_IPSEC_IKE_PROCESS_ERR_DELETE = 13841 +ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR = 13842 +ERROR_IPSEC_IKE_INVALID_PAYLOAD = 13843 +ERROR_IPSEC_IKE_LOAD_SOFT_SA = 13844 +ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN = 13845 +ERROR_IPSEC_IKE_INVALID_COOKIE = 13846 +ERROR_IPSEC_IKE_NO_PEER_CERT = 13847 +ERROR_IPSEC_IKE_PEER_CRL_FAILED = 13848 +ERROR_IPSEC_IKE_POLICY_CHANGE = 13849 +ERROR_IPSEC_IKE_NO_MM_POLICY = 13850 +ERROR_IPSEC_IKE_NOTCBPRIV = 13851 +ERROR_IPSEC_IKE_SECLOADFAIL = 13852 +ERROR_IPSEC_IKE_FAILSSPINIT = 13853 +ERROR_IPSEC_IKE_FAILQUERYSSP = 13854 +ERROR_IPSEC_IKE_SRVACQFAIL = 13855 +ERROR_IPSEC_IKE_SRVQUERYCRED = 13856 +ERROR_IPSEC_IKE_GETSPIFAIL = 13857 +ERROR_IPSEC_IKE_INVALID_FILTER = 13858 +ERROR_IPSEC_IKE_OUT_OF_MEMORY = 13859 +ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED = 13860 +ERROR_IPSEC_IKE_INVALID_POLICY = 13861 +ERROR_IPSEC_IKE_UNKNOWN_DOI = 13862 +ERROR_IPSEC_IKE_INVALID_SITUATION = 13863 +ERROR_IPSEC_IKE_DH_FAILURE = 13864 +ERROR_IPSEC_IKE_INVALID_GROUP = 13865 +ERROR_IPSEC_IKE_ENCRYPT = 13866 +ERROR_IPSEC_IKE_DECRYPT = 13867 +ERROR_IPSEC_IKE_POLICY_MATCH = 13868 +ERROR_IPSEC_IKE_UNSUPPORTED_ID = 13869 +ERROR_IPSEC_IKE_INVALID_HASH = 13870 +ERROR_IPSEC_IKE_INVALID_HASH_ALG = 13871 +ERROR_IPSEC_IKE_INVALID_HASH_SIZE = 13872 +ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG = 13873 +ERROR_IPSEC_IKE_INVALID_AUTH_ALG = 13874 +ERROR_IPSEC_IKE_INVALID_SIG = 13875 +ERROR_IPSEC_IKE_LOAD_FAILED = 13876 +ERROR_IPSEC_IKE_RPC_DELETE = 13877 +ERROR_IPSEC_IKE_BENIGN_REINIT = 13878 +ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY = 13879 +ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN = 13881 +ERROR_IPSEC_IKE_MM_LIMIT = 13882 +ERROR_IPSEC_IKE_NEGOTIATION_DISABLED = 13883 +ERROR_IPSEC_IKE_NEG_STATUS_END = 13884 +CRYPT_E_MSG_ERROR = -2146889727 +CRYPT_E_UNKNOWN_ALGO = -2146889726 +CRYPT_E_OID_FORMAT = -2146889725 +CRYPT_E_INVALID_MSG_TYPE = -2146889724 +CRYPT_E_UNEXPECTED_ENCODING = -2146889723 +CRYPT_E_AUTH_ATTR_MISSING = -2146889722 +CRYPT_E_HASH_VALUE = -2146889721 +CRYPT_E_INVALID_INDEX = -2146889720 +CRYPT_E_ALREADY_DECRYPTED = -2146889719 +CRYPT_E_NOT_DECRYPTED = -2146889718 +CRYPT_E_RECIPIENT_NOT_FOUND = -2146889717 +CRYPT_E_CONTROL_TYPE = -2146889716 +CRYPT_E_ISSUER_SERIALNUMBER = -2146889715 +CRYPT_E_SIGNER_NOT_FOUND = -2146889714 +CRYPT_E_ATTRIBUTES_MISSING = -2146889713 +CRYPT_E_STREAM_MSG_NOT_READY = -2146889712 +CRYPT_E_STREAM_INSUFFICIENT_DATA = -2146889711 +CRYPT_I_NEW_PROTECTION_REQUIRED = 593938 +CRYPT_E_BAD_LEN = -2146885631 +CRYPT_E_BAD_ENCODE = -2146885630 +CRYPT_E_FILE_ERROR = -2146885629 +CRYPT_E_NOT_FOUND = -2146885628 +CRYPT_E_EXISTS = -2146885627 +CRYPT_E_NO_PROVIDER = -2146885626 +CRYPT_E_SELF_SIGNED = -2146885625 +CRYPT_E_DELETED_PREV = -2146885624 +CRYPT_E_NO_MATCH = -2146885623 +CRYPT_E_UNEXPECTED_MSG_TYPE = -2146885622 +CRYPT_E_NO_KEY_PROPERTY = -2146885621 +CRYPT_E_NO_DECRYPT_CERT = -2146885620 +CRYPT_E_BAD_MSG = -2146885619 +CRYPT_E_NO_SIGNER = -2146885618 +CRYPT_E_PENDING_CLOSE = -2146885617 +CRYPT_E_REVOKED = -2146885616 +CRYPT_E_NO_REVOCATION_DLL = -2146885615 +CRYPT_E_NO_REVOCATION_CHECK = -2146885614 +CRYPT_E_REVOCATION_OFFLINE = -2146885613 +CRYPT_E_NOT_IN_REVOCATION_DATABASE = -2146885612 +CRYPT_E_INVALID_NUMERIC_STRING = -2146885600 +CRYPT_E_INVALID_PRINTABLE_STRING = -2146885599 +CRYPT_E_INVALID_IA5_STRING = -2146885598 +CRYPT_E_INVALID_X500_STRING = -2146885597 +CRYPT_E_NOT_CHAR_STRING = -2146885596 +CRYPT_E_FILERESIZED = -2146885595 +CRYPT_E_SECURITY_SETTINGS = -2146885594 +CRYPT_E_NO_VERIFY_USAGE_DLL = -2146885593 +CRYPT_E_NO_VERIFY_USAGE_CHECK = -2146885592 +CRYPT_E_VERIFY_USAGE_OFFLINE = -2146885591 +CRYPT_E_NOT_IN_CTL = -2146885590 +CRYPT_E_NO_TRUSTED_SIGNER = -2146885589 +CRYPT_E_MISSING_PUBKEY_PARA = -2146885588 +CRYPT_E_OSS_ERROR = -2146881536 + +## Kerberos message types for LsaCallAuthenticationPackage (from ntsecapi.h) +KerbDebugRequestMessage = 0 +KerbQueryTicketCacheMessage = 1 +KerbChangeMachinePasswordMessage = 2 +KerbVerifyPacMessage = 3 +KerbRetrieveTicketMessage = 4 +KerbUpdateAddressesMessage = 5 +KerbPurgeTicketCacheMessage = 6 +KerbChangePasswordMessage = 7 +KerbRetrieveEncodedTicketMessage = 8 +KerbDecryptDataMessage = 9 +KerbAddBindingCacheEntryMessage = 10 +KerbSetPasswordMessage = 11 +KerbSetPasswordExMessage = 12 +KerbVerifyCredentialsMessage = 13 +KerbQueryTicketCacheExMessage = 14 +KerbPurgeTicketCacheExMessage = 15 +KerbRefreshSmartcardCredentialsMessage = 16 +KerbAddExtraCredentialsMessage = 17 +KerbQuerySupplementalCredentialsMessage = 18 + +## messages used with msv1_0 from ntsecapi.h +MsV1_0Lm20ChallengeRequest = 0 +MsV1_0Lm20GetChallengeResponse = 1 +MsV1_0EnumerateUsers = 2 +MsV1_0GetUserInfo = 3 +MsV1_0ReLogonUsers = 4 +MsV1_0ChangePassword = 5 +MsV1_0ChangeCachedPassword = 6 +MsV1_0GenericPassthrough = 7 +MsV1_0CacheLogon = 8 +MsV1_0SubAuth = 9 +MsV1_0DeriveCredential = 10 +MsV1_0CacheLookup = 11 +MsV1_0SetProcessOption = 12 + +SEC_E_OK = 0 diff --git a/MLPY/Lib/site-packages/win32/lib/win2kras.py b/MLPY/Lib/site-packages/win32/lib/win2kras.py new file mode 100644 index 0000000000000000000000000000000000000000..f1c18b3acaf56decfd3373e34bc902e0c226108c --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win2kras.py @@ -0,0 +1,7 @@ +# win2kras used to be an extension module with wrapped the "new" RAS functions +# in Windows 2000, so win32ras could still be used on NT/etc. +# I think in 2021 we can be confident pywin32 is not used on earlier OSs, so +# that functionality is now in win32ras. +# +# This exists just to avoid breaking old scripts. +from win32ras import * diff --git a/MLPY/Lib/site-packages/win32/lib/win32con.py b/MLPY/Lib/site-packages/win32/lib/win32con.py new file mode 100644 index 0000000000000000000000000000000000000000..9916ba4aba373567d4cac1f95121c9c603f107b5 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32con.py @@ -0,0 +1,5083 @@ +# Generated by h2py from commdlg.h (plus modifications 4jan98) +WINVER = 1280 +WM_USER = 1024 +PY_0U = 0 +OFN_READONLY = 1 +OFN_OVERWRITEPROMPT = 2 +OFN_HIDEREADONLY = 4 +OFN_NOCHANGEDIR = 8 +OFN_SHOWHELP = 16 +OFN_ENABLEHOOK = 32 +OFN_ENABLETEMPLATE = 64 +OFN_ENABLETEMPLATEHANDLE = 128 +OFN_NOVALIDATE = 256 +OFN_ALLOWMULTISELECT = 512 +OFN_EXTENSIONDIFFERENT = 1024 +OFN_PATHMUSTEXIST = 2048 +OFN_FILEMUSTEXIST = 4096 +OFN_CREATEPROMPT = 8192 +OFN_SHAREAWARE = 16384 +OFN_NOREADONLYRETURN = 32768 +OFN_NOTESTFILECREATE = 65536 +OFN_NONETWORKBUTTON = 131072 +OFN_NOLONGNAMES = 262144 +OFN_EXPLORER = 524288 # new look commdlg +OFN_NODEREFERENCELINKS = 1048576 +OFN_LONGNAMES = 2097152 # force long names for 3.x modules +OFN_ENABLEINCLUDENOTIFY = 4194304 # send include message to callback +OFN_ENABLESIZING = 8388608 +OFN_DONTADDTORECENT = 33554432 +OFN_FORCESHOWHIDDEN = 268435456 # Show All files including System and hidden files +OFN_EX_NOPLACESBAR = 1 +OFN_SHAREFALLTHROUGH = 2 +OFN_SHARENOWARN = 1 +OFN_SHAREWARN = 0 +CDN_FIRST = PY_0U - 601 +CDN_LAST = PY_0U - 699 +CDN_INITDONE = CDN_FIRST - 0 +CDN_SELCHANGE = CDN_FIRST - 1 +CDN_FOLDERCHANGE = CDN_FIRST - 2 +CDN_SHAREVIOLATION = CDN_FIRST - 3 +CDN_HELP = CDN_FIRST - 4 +CDN_FILEOK = CDN_FIRST - 5 +CDN_TYPECHANGE = CDN_FIRST - 6 +CDN_INCLUDEITEM = CDN_FIRST - 7 +CDM_FIRST = WM_USER + 100 +CDM_LAST = WM_USER + 200 +CDM_GETSPEC = CDM_FIRST + 0 +CDM_GETFILEPATH = CDM_FIRST + 1 +CDM_GETFOLDERPATH = CDM_FIRST + 2 +CDM_GETFOLDERIDLIST = CDM_FIRST + 3 +CDM_SETCONTROLTEXT = CDM_FIRST + 4 +CDM_HIDECONTROL = CDM_FIRST + 5 +CDM_SETDEFEXT = CDM_FIRST + 6 +CC_RGBINIT = 1 +CC_FULLOPEN = 2 +CC_PREVENTFULLOPEN = 4 +CC_SHOWHELP = 8 +CC_ENABLEHOOK = 16 +CC_ENABLETEMPLATE = 32 +CC_ENABLETEMPLATEHANDLE = 64 +CC_SOLIDCOLOR = 128 +CC_ANYCOLOR = 256 +FR_DOWN = 1 +FR_WHOLEWORD = 2 +FR_MATCHCASE = 4 +FR_FINDNEXT = 8 +FR_REPLACE = 16 +FR_REPLACEALL = 32 +FR_DIALOGTERM = 64 +FR_SHOWHELP = 128 +FR_ENABLEHOOK = 256 +FR_ENABLETEMPLATE = 512 +FR_NOUPDOWN = 1024 +FR_NOMATCHCASE = 2048 +FR_NOWHOLEWORD = 4096 +FR_ENABLETEMPLATEHANDLE = 8192 +FR_HIDEUPDOWN = 16384 +FR_HIDEMATCHCASE = 32768 +FR_HIDEWHOLEWORD = 65536 +CF_SCREENFONTS = 1 +CF_PRINTERFONTS = 2 +CF_BOTH = CF_SCREENFONTS | CF_PRINTERFONTS +CF_SHOWHELP = 4 +CF_ENABLEHOOK = 8 +CF_ENABLETEMPLATE = 16 +CF_ENABLETEMPLATEHANDLE = 32 +CF_INITTOLOGFONTSTRUCT = 64 +CF_USESTYLE = 128 +CF_EFFECTS = 256 +CF_APPLY = 512 +CF_ANSIONLY = 1024 +CF_SCRIPTSONLY = CF_ANSIONLY +CF_NOVECTORFONTS = 2048 +CF_NOOEMFONTS = CF_NOVECTORFONTS +CF_NOSIMULATIONS = 4096 +CF_LIMITSIZE = 8192 +CF_FIXEDPITCHONLY = 16384 +CF_WYSIWYG = 32768 # must also have CF_SCREENFONTS & CF_PRINTERFONTS +CF_FORCEFONTEXIST = 65536 +CF_SCALABLEONLY = 131072 +CF_TTONLY = 262144 +CF_NOFACESEL = 524288 +CF_NOSTYLESEL = 1048576 +CF_NOSIZESEL = 2097152 +CF_SELECTSCRIPT = 4194304 +CF_NOSCRIPTSEL = 8388608 +CF_NOVERTFONTS = 16777216 +SIMULATED_FONTTYPE = 32768 +PRINTER_FONTTYPE = 16384 +SCREEN_FONTTYPE = 8192 +BOLD_FONTTYPE = 256 +ITALIC_FONTTYPE = 512 +REGULAR_FONTTYPE = 1024 +OPENTYPE_FONTTYPE = 65536 +TYPE1_FONTTYPE = 131072 +DSIG_FONTTYPE = 262144 +WM_CHOOSEFONT_GETLOGFONT = WM_USER + 1 +WM_CHOOSEFONT_SETLOGFONT = WM_USER + 101 +WM_CHOOSEFONT_SETFLAGS = WM_USER + 102 +LBSELCHSTRINGA = "commdlg_LBSelChangedNotify" +SHAREVISTRINGA = "commdlg_ShareViolation" +FILEOKSTRINGA = "commdlg_FileNameOK" +COLOROKSTRINGA = "commdlg_ColorOK" +SETRGBSTRINGA = "commdlg_SetRGBColor" +HELPMSGSTRINGA = "commdlg_help" +FINDMSGSTRINGA = "commdlg_FindReplace" +LBSELCHSTRING = LBSELCHSTRINGA +SHAREVISTRING = SHAREVISTRINGA +FILEOKSTRING = FILEOKSTRINGA +COLOROKSTRING = COLOROKSTRINGA +SETRGBSTRING = SETRGBSTRINGA +HELPMSGSTRING = HELPMSGSTRINGA +FINDMSGSTRING = FINDMSGSTRINGA +CD_LBSELNOITEMS = -1 +CD_LBSELCHANGE = 0 +CD_LBSELSUB = 1 +CD_LBSELADD = 2 +PD_ALLPAGES = 0 +PD_SELECTION = 1 +PD_PAGENUMS = 2 +PD_NOSELECTION = 4 +PD_NOPAGENUMS = 8 +PD_COLLATE = 16 +PD_PRINTTOFILE = 32 +PD_PRINTSETUP = 64 +PD_NOWARNING = 128 +PD_RETURNDC = 256 +PD_RETURNIC = 512 +PD_RETURNDEFAULT = 1024 +PD_SHOWHELP = 2048 +PD_ENABLEPRINTHOOK = 4096 +PD_ENABLESETUPHOOK = 8192 +PD_ENABLEPRINTTEMPLATE = 16384 +PD_ENABLESETUPTEMPLATE = 32768 +PD_ENABLEPRINTTEMPLATEHANDLE = 65536 +PD_ENABLESETUPTEMPLATEHANDLE = 131072 +PD_USEDEVMODECOPIES = 262144 +PD_DISABLEPRINTTOFILE = 524288 +PD_HIDEPRINTTOFILE = 1048576 +PD_NONETWORKBUTTON = 2097152 +DN_DEFAULTPRN = 1 +WM_PSD_PAGESETUPDLG = WM_USER +WM_PSD_FULLPAGERECT = WM_USER + 1 +WM_PSD_MINMARGINRECT = WM_USER + 2 +WM_PSD_MARGINRECT = WM_USER + 3 +WM_PSD_GREEKTEXTRECT = WM_USER + 4 +WM_PSD_ENVSTAMPRECT = WM_USER + 5 +WM_PSD_YAFULLPAGERECT = WM_USER + 6 +PSD_DEFAULTMINMARGINS = 0 # default (printer's) +PSD_INWININIINTLMEASURE = 0 # 1st of 4 possible +PSD_MINMARGINS = 1 # use caller's +PSD_MARGINS = 2 # use caller's +PSD_INTHOUSANDTHSOFINCHES = 4 # 2nd of 4 possible +PSD_INHUNDREDTHSOFMILLIMETERS = 8 # 3rd of 4 possible +PSD_DISABLEMARGINS = 16 +PSD_DISABLEPRINTER = 32 +PSD_NOWARNING = 128 # must be same as PD_* +PSD_DISABLEORIENTATION = 256 +PSD_RETURNDEFAULT = 1024 # must be same as PD_* +PSD_DISABLEPAPER = 512 +PSD_SHOWHELP = 2048 # must be same as PD_* +PSD_ENABLEPAGESETUPHOOK = 8192 # must be same as PD_* +PSD_ENABLEPAGESETUPTEMPLATE = 32768 # must be same as PD_* +PSD_ENABLEPAGESETUPTEMPLATEHANDLE = 131072 # must be same as PD_* +PSD_ENABLEPAGEPAINTHOOK = 262144 +PSD_DISABLEPAGEPAINTING = 524288 +PSD_NONETWORKBUTTON = 2097152 # must be same as PD_* + +# Generated by h2py from winreg.h +HKEY_CLASSES_ROOT = -2147483648 +HKEY_CURRENT_USER = -2147483647 +HKEY_LOCAL_MACHINE = -2147483646 +HKEY_USERS = -2147483645 +HKEY_PERFORMANCE_DATA = -2147483644 +HKEY_CURRENT_CONFIG = -2147483643 +HKEY_DYN_DATA = -2147483642 +HKEY_PERFORMANCE_TEXT = -2147483568 # ?? 4Jan98 +HKEY_PERFORMANCE_NLSTEXT = -2147483552 # ?? 4Jan98 + +# Generated by h2py from winuser.h +HWND_BROADCAST = 65535 +HWND_DESKTOP = 0 +HWND_TOP = 0 +HWND_BOTTOM = 1 +HWND_TOPMOST = -1 +HWND_NOTOPMOST = -2 +HWND_MESSAGE = -3 + +# winuser.h line 4601 +SM_CXSCREEN = 0 +SM_CYSCREEN = 1 +SM_CXVSCROLL = 2 +SM_CYHSCROLL = 3 +SM_CYCAPTION = 4 +SM_CXBORDER = 5 +SM_CYBORDER = 6 +SM_CXDLGFRAME = 7 +SM_CYDLGFRAME = 8 +SM_CYVTHUMB = 9 +SM_CXHTHUMB = 10 +SM_CXICON = 11 +SM_CYICON = 12 +SM_CXCURSOR = 13 +SM_CYCURSOR = 14 +SM_CYMENU = 15 +SM_CXFULLSCREEN = 16 +SM_CYFULLSCREEN = 17 +SM_CYKANJIWINDOW = 18 +SM_MOUSEPRESENT = 19 +SM_CYVSCROLL = 20 +SM_CXHSCROLL = 21 +SM_DEBUG = 22 +SM_SWAPBUTTON = 23 +SM_RESERVED1 = 24 +SM_RESERVED2 = 25 +SM_RESERVED3 = 26 +SM_RESERVED4 = 27 +SM_CXMIN = 28 +SM_CYMIN = 29 +SM_CXSIZE = 30 +SM_CYSIZE = 31 +SM_CXFRAME = 32 +SM_CYFRAME = 33 +SM_CXMINTRACK = 34 +SM_CYMINTRACK = 35 +SM_CXDOUBLECLK = 36 +SM_CYDOUBLECLK = 37 +SM_CXICONSPACING = 38 +SM_CYICONSPACING = 39 +SM_MENUDROPALIGNMENT = 40 +SM_PENWINDOWS = 41 +SM_DBCSENABLED = 42 +SM_CMOUSEBUTTONS = 43 +SM_CXFIXEDFRAME = SM_CXDLGFRAME +SM_CYFIXEDFRAME = SM_CYDLGFRAME +SM_CXSIZEFRAME = SM_CXFRAME +SM_CYSIZEFRAME = SM_CYFRAME +SM_SECURE = 44 +SM_CXEDGE = 45 +SM_CYEDGE = 46 +SM_CXMINSPACING = 47 +SM_CYMINSPACING = 48 +SM_CXSMICON = 49 +SM_CYSMICON = 50 +SM_CYSMCAPTION = 51 +SM_CXSMSIZE = 52 +SM_CYSMSIZE = 53 +SM_CXMENUSIZE = 54 +SM_CYMENUSIZE = 55 +SM_ARRANGE = 56 +SM_CXMINIMIZED = 57 +SM_CYMINIMIZED = 58 +SM_CXMAXTRACK = 59 +SM_CYMAXTRACK = 60 +SM_CXMAXIMIZED = 61 +SM_CYMAXIMIZED = 62 +SM_NETWORK = 63 +SM_CLEANBOOT = 67 +SM_CXDRAG = 68 +SM_CYDRAG = 69 +SM_SHOWSOUNDS = 70 +SM_CXMENUCHECK = 71 +SM_CYMENUCHECK = 72 +SM_SLOWMACHINE = 73 +SM_MIDEASTENABLED = 74 +SM_MOUSEWHEELPRESENT = 75 +SM_XVIRTUALSCREEN = 76 +SM_YVIRTUALSCREEN = 77 +SM_CXVIRTUALSCREEN = 78 +SM_CYVIRTUALSCREEN = 79 +SM_CMONITORS = 80 +SM_SAMEDISPLAYFORMAT = 81 +SM_CMETRICS = 83 +MNC_IGNORE = 0 +MNC_CLOSE = 1 +MNC_EXECUTE = 2 +MNC_SELECT = 3 +MNS_NOCHECK = -2147483648 +MNS_MODELESS = 1073741824 +MNS_DRAGDROP = 536870912 +MNS_AUTODISMISS = 268435456 +MNS_NOTIFYBYPOS = 134217728 +MNS_CHECKORBMP = 67108864 +MIM_MAXHEIGHT = 1 +MIM_BACKGROUND = 2 +MIM_HELPID = 4 +MIM_MENUDATA = 8 +MIM_STYLE = 16 +MIM_APPLYTOSUBMENUS = -2147483648 +MND_CONTINUE = 0 +MND_ENDMENU = 1 +MNGOF_GAP = 3 +MNGO_NOINTERFACE = 0 +MNGO_NOERROR = 1 +MIIM_STATE = 1 +MIIM_ID = 2 +MIIM_SUBMENU = 4 +MIIM_CHECKMARKS = 8 +MIIM_TYPE = 16 +MIIM_DATA = 32 +MIIM_STRING = 64 +MIIM_BITMAP = 128 +MIIM_FTYPE = 256 +HBMMENU_CALLBACK = -1 +HBMMENU_SYSTEM = 1 +HBMMENU_MBAR_RESTORE = 2 +HBMMENU_MBAR_MINIMIZE = 3 +HBMMENU_MBAR_CLOSE = 5 +HBMMENU_MBAR_CLOSE_D = 6 +HBMMENU_MBAR_MINIMIZE_D = 7 +HBMMENU_POPUP_CLOSE = 8 +HBMMENU_POPUP_RESTORE = 9 +HBMMENU_POPUP_MAXIMIZE = 10 +HBMMENU_POPUP_MINIMIZE = 11 +GMDI_USEDISABLED = 1 +GMDI_GOINTOPOPUPS = 2 +TPM_LEFTBUTTON = 0 +TPM_RIGHTBUTTON = 2 +TPM_LEFTALIGN = 0 +TPM_CENTERALIGN = 4 +TPM_RIGHTALIGN = 8 +TPM_TOPALIGN = 0 +TPM_VCENTERALIGN = 16 +TPM_BOTTOMALIGN = 32 +TPM_HORIZONTAL = 0 +TPM_VERTICAL = 64 +TPM_NONOTIFY = 128 +TPM_RETURNCMD = 256 +TPM_RECURSE = 1 +DOF_EXECUTABLE = 32769 +DOF_DOCUMENT = 32770 +DOF_DIRECTORY = 32771 +DOF_MULTIPLE = 32772 +DOF_PROGMAN = 1 +DOF_SHELLDATA = 2 +DO_DROPFILE = 1162627398 +DO_PRINTFILE = 1414419024 +DT_TOP = 0 +DT_LEFT = 0 +DT_CENTER = 1 +DT_RIGHT = 2 +DT_VCENTER = 4 +DT_BOTTOM = 8 +DT_WORDBREAK = 16 +DT_SINGLELINE = 32 +DT_EXPANDTABS = 64 +DT_TABSTOP = 128 +DT_NOCLIP = 256 +DT_EXTERNALLEADING = 512 +DT_CALCRECT = 1024 +DT_NOPREFIX = 2048 +DT_INTERNAL = 4096 +DT_EDITCONTROL = 8192 +DT_PATH_ELLIPSIS = 16384 +DT_END_ELLIPSIS = 32768 +DT_MODIFYSTRING = 65536 +DT_RTLREADING = 131072 +DT_WORD_ELLIPSIS = 262144 +DST_COMPLEX = 0 +DST_TEXT = 1 +DST_PREFIXTEXT = 2 +DST_ICON = 3 +DST_BITMAP = 4 +DSS_NORMAL = 0 +DSS_UNION = 16 +DSS_DISABLED = 32 +DSS_MONO = 128 +DSS_RIGHT = 32768 +DCX_WINDOW = 1 +DCX_CACHE = 2 +DCX_NORESETATTRS = 4 +DCX_CLIPCHILDREN = 8 +DCX_CLIPSIBLINGS = 16 +DCX_PARENTCLIP = 32 +DCX_EXCLUDERGN = 64 +DCX_INTERSECTRGN = 128 +DCX_EXCLUDEUPDATE = 256 +DCX_INTERSECTUPDATE = 512 +DCX_LOCKWINDOWUPDATE = 1024 +DCX_VALIDATE = 2097152 +CUDR_NORMAL = 0 +CUDR_NOSNAPTOGRID = 1 +CUDR_NORESOLVEPOSITIONS = 2 +CUDR_NOCLOSEGAPS = 4 +CUDR_NEGATIVECOORDS = 8 +CUDR_NOPRIMARY = 16 +RDW_INVALIDATE = 1 +RDW_INTERNALPAINT = 2 +RDW_ERASE = 4 +RDW_VALIDATE = 8 +RDW_NOINTERNALPAINT = 16 +RDW_NOERASE = 32 +RDW_NOCHILDREN = 64 +RDW_ALLCHILDREN = 128 +RDW_UPDATENOW = 256 +RDW_ERASENOW = 512 +RDW_FRAME = 1024 +RDW_NOFRAME = 2048 +SW_SCROLLCHILDREN = 1 +SW_INVALIDATE = 2 +SW_ERASE = 4 +SW_SMOOTHSCROLL = 16 # Use smooth scrolling +ESB_ENABLE_BOTH = 0 +ESB_DISABLE_BOTH = 3 +ESB_DISABLE_LEFT = 1 +ESB_DISABLE_RIGHT = 2 +ESB_DISABLE_UP = 1 +ESB_DISABLE_DOWN = 2 +ESB_DISABLE_LTUP = ESB_DISABLE_LEFT +ESB_DISABLE_RTDN = ESB_DISABLE_RIGHT +HELPINFO_WINDOW = 1 +HELPINFO_MENUITEM = 2 +MB_OK = 0 +MB_OKCANCEL = 1 +MB_ABORTRETRYIGNORE = 2 +MB_YESNOCANCEL = 3 +MB_YESNO = 4 +MB_RETRYCANCEL = 5 +MB_ICONHAND = 16 +MB_ICONQUESTION = 32 +MB_ICONEXCLAMATION = 48 +MB_ICONASTERISK = 64 +MB_ICONWARNING = MB_ICONEXCLAMATION +MB_ICONERROR = MB_ICONHAND +MB_ICONINFORMATION = MB_ICONASTERISK +MB_ICONSTOP = MB_ICONHAND +MB_DEFBUTTON1 = 0 +MB_DEFBUTTON2 = 256 +MB_DEFBUTTON3 = 512 +MB_DEFBUTTON4 = 768 +MB_APPLMODAL = 0 +MB_SYSTEMMODAL = 4096 +MB_TASKMODAL = 8192 +MB_HELP = 16384 +MB_NOFOCUS = 32768 +MB_SETFOREGROUND = 65536 +MB_DEFAULT_DESKTOP_ONLY = 131072 +MB_TOPMOST = 262144 +MB_RIGHT = 524288 +MB_RTLREADING = 1048576 +MB_SERVICE_NOTIFICATION = 2097152 +MB_TYPEMASK = 15 +MB_USERICON = 128 +MB_ICONMASK = 240 +MB_DEFMASK = 3840 +MB_MODEMASK = 12288 +MB_MISCMASK = 49152 +# winuser.h line 6373 +CWP_ALL = 0 +CWP_SKIPINVISIBLE = 1 +CWP_SKIPDISABLED = 2 +CWP_SKIPTRANSPARENT = 4 +CTLCOLOR_MSGBOX = 0 +CTLCOLOR_EDIT = 1 +CTLCOLOR_LISTBOX = 2 +CTLCOLOR_BTN = 3 +CTLCOLOR_DLG = 4 +CTLCOLOR_SCROLLBAR = 5 +CTLCOLOR_STATIC = 6 +CTLCOLOR_MAX = 7 +COLOR_SCROLLBAR = 0 +COLOR_BACKGROUND = 1 +COLOR_ACTIVECAPTION = 2 +COLOR_INACTIVECAPTION = 3 +COLOR_MENU = 4 +COLOR_WINDOW = 5 +COLOR_WINDOWFRAME = 6 +COLOR_MENUTEXT = 7 +COLOR_WINDOWTEXT = 8 +COLOR_CAPTIONTEXT = 9 +COLOR_ACTIVEBORDER = 10 +COLOR_INACTIVEBORDER = 11 +COLOR_APPWORKSPACE = 12 +COLOR_HIGHLIGHT = 13 +COLOR_HIGHLIGHTTEXT = 14 +COLOR_BTNFACE = 15 +COLOR_BTNSHADOW = 16 +COLOR_GRAYTEXT = 17 +COLOR_BTNTEXT = 18 +COLOR_INACTIVECAPTIONTEXT = 19 +COLOR_BTNHIGHLIGHT = 20 +COLOR_3DDKSHADOW = 21 +COLOR_3DLIGHT = 22 +COLOR_INFOTEXT = 23 +COLOR_INFOBK = 24 +COLOR_HOTLIGHT = 26 +COLOR_GRADIENTACTIVECAPTION = 27 +COLOR_GRADIENTINACTIVECAPTION = 28 +COLOR_DESKTOP = COLOR_BACKGROUND +COLOR_3DFACE = COLOR_BTNFACE +COLOR_3DSHADOW = COLOR_BTNSHADOW +COLOR_3DHIGHLIGHT = COLOR_BTNHIGHLIGHT +COLOR_3DHILIGHT = COLOR_BTNHIGHLIGHT +COLOR_BTNHILIGHT = COLOR_BTNHIGHLIGHT +GW_HWNDFIRST = 0 +GW_HWNDLAST = 1 +GW_HWNDNEXT = 2 +GW_HWNDPREV = 3 +GW_OWNER = 4 +GW_CHILD = 5 +GW_ENABLEDPOPUP = 6 +GW_MAX = 6 +MF_INSERT = 0 +MF_CHANGE = 128 +MF_APPEND = 256 +MF_DELETE = 512 +MF_REMOVE = 4096 +MF_BYCOMMAND = 0 +MF_BYPOSITION = 1024 +MF_SEPARATOR = 2048 +MF_ENABLED = 0 +MF_GRAYED = 1 +MF_DISABLED = 2 +MF_UNCHECKED = 0 +MF_CHECKED = 8 +MF_USECHECKBITMAPS = 512 +MF_STRING = 0 +MF_BITMAP = 4 +MF_OWNERDRAW = 256 +MF_POPUP = 16 +MF_MENUBARBREAK = 32 +MF_MENUBREAK = 64 +MF_UNHILITE = 0 +MF_HILITE = 128 +MF_DEFAULT = 4096 +MF_SYSMENU = 8192 +MF_HELP = 16384 +MF_RIGHTJUSTIFY = 16384 +MF_MOUSESELECT = 32768 +MF_END = 128 +MFT_STRING = MF_STRING +MFT_BITMAP = MF_BITMAP +MFT_MENUBARBREAK = MF_MENUBARBREAK +MFT_MENUBREAK = MF_MENUBREAK +MFT_OWNERDRAW = MF_OWNERDRAW +MFT_RADIOCHECK = 512 +MFT_SEPARATOR = MF_SEPARATOR +MFT_RIGHTORDER = 8192 +MFT_RIGHTJUSTIFY = MF_RIGHTJUSTIFY +MFS_GRAYED = 3 +MFS_DISABLED = MFS_GRAYED +MFS_CHECKED = MF_CHECKED +MFS_HILITE = MF_HILITE +MFS_ENABLED = MF_ENABLED +MFS_UNCHECKED = MF_UNCHECKED +MFS_UNHILITE = MF_UNHILITE +MFS_DEFAULT = MF_DEFAULT +MFS_MASK = 4235 +MFS_HOTTRACKDRAWN = 268435456 +MFS_CACHEDBMP = 536870912 +MFS_BOTTOMGAPDROP = 1073741824 +MFS_TOPGAPDROP = -2147483648 +MFS_GAPDROP = -1073741824 +SC_SIZE = 61440 +SC_MOVE = 61456 +SC_MINIMIZE = 61472 +SC_MAXIMIZE = 61488 +SC_NEXTWINDOW = 61504 +SC_PREVWINDOW = 61520 +SC_CLOSE = 61536 +SC_VSCROLL = 61552 +SC_HSCROLL = 61568 +SC_MOUSEMENU = 61584 +SC_KEYMENU = 61696 +SC_ARRANGE = 61712 +SC_RESTORE = 61728 +SC_TASKLIST = 61744 +SC_SCREENSAVE = 61760 +SC_HOTKEY = 61776 +SC_DEFAULT = 61792 +SC_MONITORPOWER = 61808 +SC_CONTEXTHELP = 61824 +SC_SEPARATOR = 61455 +SC_ICON = SC_MINIMIZE +SC_ZOOM = SC_MAXIMIZE +IDC_ARROW = 32512 +IDC_IBEAM = 32513 +IDC_WAIT = 32514 +IDC_CROSS = 32515 +IDC_UPARROW = 32516 +IDC_SIZE = 32640 # OBSOLETE: use IDC_SIZEALL +IDC_ICON = 32641 # OBSOLETE: use IDC_ARROW +IDC_SIZENWSE = 32642 +IDC_SIZENESW = 32643 +IDC_SIZEWE = 32644 +IDC_SIZENS = 32645 +IDC_SIZEALL = 32646 +IDC_NO = 32648 +IDC_HAND = 32649 +IDC_APPSTARTING = 32650 +IDC_HELP = 32651 +IMAGE_BITMAP = 0 +IMAGE_ICON = 1 +IMAGE_CURSOR = 2 +IMAGE_ENHMETAFILE = 3 +LR_DEFAULTCOLOR = 0 +LR_MONOCHROME = 1 +LR_COLOR = 2 +LR_COPYRETURNORG = 4 +LR_COPYDELETEORG = 8 +LR_LOADFROMFILE = 16 +LR_LOADTRANSPARENT = 32 +LR_DEFAULTSIZE = 64 +LR_LOADREALSIZE = 128 +LR_LOADMAP3DCOLORS = 4096 +LR_CREATEDIBSECTION = 8192 +LR_COPYFROMRESOURCE = 16384 +LR_SHARED = 32768 +DI_MASK = 1 +DI_IMAGE = 2 +DI_NORMAL = 3 +DI_COMPAT = 4 +DI_DEFAULTSIZE = 8 +RES_ICON = 1 +RES_CURSOR = 2 +OBM_CLOSE = 32754 +OBM_UPARROW = 32753 +OBM_DNARROW = 32752 +OBM_RGARROW = 32751 +OBM_LFARROW = 32750 +OBM_REDUCE = 32749 +OBM_ZOOM = 32748 +OBM_RESTORE = 32747 +OBM_REDUCED = 32746 +OBM_ZOOMD = 32745 +OBM_RESTORED = 32744 +OBM_UPARROWD = 32743 +OBM_DNARROWD = 32742 +OBM_RGARROWD = 32741 +OBM_LFARROWD = 32740 +OBM_MNARROW = 32739 +OBM_COMBO = 32738 +OBM_UPARROWI = 32737 +OBM_DNARROWI = 32736 +OBM_RGARROWI = 32735 +OBM_LFARROWI = 32734 +OBM_OLD_CLOSE = 32767 +OBM_SIZE = 32766 +OBM_OLD_UPARROW = 32765 +OBM_OLD_DNARROW = 32764 +OBM_OLD_RGARROW = 32763 +OBM_OLD_LFARROW = 32762 +OBM_BTSIZE = 32761 +OBM_CHECK = 32760 +OBM_CHECKBOXES = 32759 +OBM_BTNCORNERS = 32758 +OBM_OLD_REDUCE = 32757 +OBM_OLD_ZOOM = 32756 +OBM_OLD_RESTORE = 32755 +OCR_NORMAL = 32512 +OCR_IBEAM = 32513 +OCR_WAIT = 32514 +OCR_CROSS = 32515 +OCR_UP = 32516 +OCR_SIZE = 32640 +OCR_ICON = 32641 +OCR_SIZENWSE = 32642 +OCR_SIZENESW = 32643 +OCR_SIZEWE = 32644 +OCR_SIZENS = 32645 +OCR_SIZEALL = 32646 +OCR_ICOCUR = 32647 +OCR_NO = 32648 +OCR_HAND = 32649 +OCR_APPSTARTING = 32650 +# winuser.h line 7455 +OIC_SAMPLE = 32512 +OIC_HAND = 32513 +OIC_QUES = 32514 +OIC_BANG = 32515 +OIC_NOTE = 32516 +OIC_WINLOGO = 32517 +OIC_WARNING = OIC_BANG +OIC_ERROR = OIC_HAND +OIC_INFORMATION = OIC_NOTE +ORD_LANGDRIVER = 1 +IDI_APPLICATION = 32512 +IDI_HAND = 32513 +IDI_QUESTION = 32514 +IDI_EXCLAMATION = 32515 +IDI_ASTERISK = 32516 +IDI_WINLOGO = 32517 +IDI_WARNING = IDI_EXCLAMATION +IDI_ERROR = IDI_HAND +IDI_INFORMATION = IDI_ASTERISK +IDOK = 1 +IDCANCEL = 2 +IDABORT = 3 +IDRETRY = 4 +IDIGNORE = 5 +IDYES = 6 +IDNO = 7 +IDCLOSE = 8 +IDHELP = 9 +ES_LEFT = 0 +ES_CENTER = 1 +ES_RIGHT = 2 +ES_MULTILINE = 4 +ES_UPPERCASE = 8 +ES_LOWERCASE = 16 +ES_PASSWORD = 32 +ES_AUTOVSCROLL = 64 +ES_AUTOHSCROLL = 128 +ES_NOHIDESEL = 256 +ES_OEMCONVERT = 1024 +ES_READONLY = 2048 +ES_WANTRETURN = 4096 +ES_NUMBER = 8192 +EN_SETFOCUS = 256 +EN_KILLFOCUS = 512 +EN_CHANGE = 768 +EN_UPDATE = 1024 +EN_ERRSPACE = 1280 +EN_MAXTEXT = 1281 +EN_HSCROLL = 1537 +EN_VSCROLL = 1538 +EC_LEFTMARGIN = 1 +EC_RIGHTMARGIN = 2 +EC_USEFONTINFO = 65535 +EMSIS_COMPOSITIONSTRING = 1 +EIMES_GETCOMPSTRATONCE = 1 +EIMES_CANCELCOMPSTRINFOCUS = 2 +EIMES_COMPLETECOMPSTRKILLFOCUS = 4 +EM_GETSEL = 176 +EM_SETSEL = 177 +EM_GETRECT = 178 +EM_SETRECT = 179 +EM_SETRECTNP = 180 +EM_SCROLL = 181 +EM_LINESCROLL = 182 +EM_SCROLLCARET = 183 +EM_GETMODIFY = 184 +EM_SETMODIFY = 185 +EM_GETLINECOUNT = 186 +EM_LINEINDEX = 187 +EM_SETHANDLE = 188 +EM_GETHANDLE = 189 +EM_GETTHUMB = 190 +EM_LINELENGTH = 193 +EM_REPLACESEL = 194 +EM_GETLINE = 196 +EM_LIMITTEXT = 197 +EM_CANUNDO = 198 +EM_UNDO = 199 +EM_FMTLINES = 200 +EM_LINEFROMCHAR = 201 +EM_SETTABSTOPS = 203 +EM_SETPASSWORDCHAR = 204 +EM_EMPTYUNDOBUFFER = 205 +EM_GETFIRSTVISIBLELINE = 206 +EM_SETREADONLY = 207 +EM_SETWORDBREAKPROC = 208 +EM_GETWORDBREAKPROC = 209 +EM_GETPASSWORDCHAR = 210 +EM_SETMARGINS = 211 +EM_GETMARGINS = 212 +EM_SETLIMITTEXT = EM_LIMITTEXT +EM_GETLIMITTEXT = 213 +EM_POSFROMCHAR = 214 +EM_CHARFROMPOS = 215 +EM_SETIMESTATUS = 216 +EM_GETIMESTATUS = 217 +WB_LEFT = 0 +WB_RIGHT = 1 +WB_ISDELIMITER = 2 +BS_PUSHBUTTON = 0 +BS_DEFPUSHBUTTON = 1 +BS_CHECKBOX = 2 +BS_AUTOCHECKBOX = 3 +BS_RADIOBUTTON = 4 +BS_3STATE = 5 +BS_AUTO3STATE = 6 +BS_GROUPBOX = 7 +BS_USERBUTTON = 8 +BS_AUTORADIOBUTTON = 9 +BS_OWNERDRAW = 11 +BS_LEFTTEXT = 32 +BS_TEXT = 0 +BS_ICON = 64 +BS_BITMAP = 128 +BS_LEFT = 256 +BS_RIGHT = 512 +BS_CENTER = 768 +BS_TOP = 1024 +BS_BOTTOM = 2048 +BS_VCENTER = 3072 +BS_PUSHLIKE = 4096 +BS_MULTILINE = 8192 +BS_NOTIFY = 16384 +BS_FLAT = 32768 +BS_RIGHTBUTTON = BS_LEFTTEXT +BN_CLICKED = 0 +BN_PAINT = 1 +BN_HILITE = 2 +BN_UNHILITE = 3 +BN_DISABLE = 4 +BN_DOUBLECLICKED = 5 +BN_PUSHED = BN_HILITE +BN_UNPUSHED = BN_UNHILITE +BN_DBLCLK = BN_DOUBLECLICKED +BN_SETFOCUS = 6 +BN_KILLFOCUS = 7 +BM_GETCHECK = 240 +BM_SETCHECK = 241 +BM_GETSTATE = 242 +BM_SETSTATE = 243 +BM_SETSTYLE = 244 +BM_CLICK = 245 +BM_GETIMAGE = 246 +BM_SETIMAGE = 247 +BST_UNCHECKED = 0 +BST_CHECKED = 1 +BST_INDETERMINATE = 2 +BST_PUSHED = 4 +BST_FOCUS = 8 +SS_LEFT = 0 +SS_CENTER = 1 +SS_RIGHT = 2 +SS_ICON = 3 +SS_BLACKRECT = 4 +SS_GRAYRECT = 5 +SS_WHITERECT = 6 +SS_BLACKFRAME = 7 +SS_GRAYFRAME = 8 +SS_WHITEFRAME = 9 +SS_USERITEM = 10 +SS_SIMPLE = 11 +SS_LEFTNOWORDWRAP = 12 +SS_BITMAP = 14 +SS_OWNERDRAW = 13 +SS_ENHMETAFILE = 15 +SS_ETCHEDHORZ = 16 +SS_ETCHEDVERT = 17 +SS_ETCHEDFRAME = 18 +SS_TYPEMASK = 31 +SS_NOPREFIX = 128 +SS_NOTIFY = 256 +SS_CENTERIMAGE = 512 +SS_RIGHTJUST = 1024 +SS_REALSIZEIMAGE = 2048 +SS_SUNKEN = 4096 +SS_ENDELLIPSIS = 16384 +SS_PATHELLIPSIS = 32768 +SS_WORDELLIPSIS = 49152 +SS_ELLIPSISMASK = 49152 +STM_SETICON = 368 +STM_GETICON = 369 +STM_SETIMAGE = 370 +STM_GETIMAGE = 371 +STN_CLICKED = 0 +STN_DBLCLK = 1 +STN_ENABLE = 2 +STN_DISABLE = 3 +STM_MSGMAX = 372 +DWL_MSGRESULT = 0 +DWL_DLGPROC = 4 +DWL_USER = 8 +DDL_READWRITE = 0 +DDL_READONLY = 1 +DDL_HIDDEN = 2 +DDL_SYSTEM = 4 +DDL_DIRECTORY = 16 +DDL_ARCHIVE = 32 +DDL_POSTMSGS = 8192 +DDL_DRIVES = 16384 +DDL_EXCLUSIVE = 32768 + +# from winuser.h line 153 +RT_CURSOR = 1 +RT_BITMAP = 2 +RT_ICON = 3 +RT_MENU = 4 +RT_DIALOG = 5 +RT_STRING = 6 +RT_FONTDIR = 7 +RT_FONT = 8 +RT_ACCELERATOR = 9 +RT_RCDATA = 10 +RT_MESSAGETABLE = 11 +DIFFERENCE = 11 +RT_GROUP_CURSOR = RT_CURSOR + DIFFERENCE +RT_GROUP_ICON = RT_ICON + DIFFERENCE +RT_VERSION = 16 +RT_DLGINCLUDE = 17 +RT_PLUGPLAY = 19 +RT_VXD = 20 +RT_ANICURSOR = 21 +RT_ANIICON = 22 +RT_HTML = 23 +# from winuser.h line 218 +SB_HORZ = 0 +SB_VERT = 1 +SB_CTL = 2 +SB_BOTH = 3 +SB_LINEUP = 0 +SB_LINELEFT = 0 +SB_LINEDOWN = 1 +SB_LINERIGHT = 1 +SB_PAGEUP = 2 +SB_PAGELEFT = 2 +SB_PAGEDOWN = 3 +SB_PAGERIGHT = 3 +SB_THUMBPOSITION = 4 +SB_THUMBTRACK = 5 +SB_TOP = 6 +SB_LEFT = 6 +SB_BOTTOM = 7 +SB_RIGHT = 7 +SB_ENDSCROLL = 8 +SW_HIDE = 0 +SW_SHOWNORMAL = 1 +SW_NORMAL = 1 +SW_SHOWMINIMIZED = 2 +SW_SHOWMAXIMIZED = 3 +SW_MAXIMIZE = 3 +SW_SHOWNOACTIVATE = 4 +SW_SHOW = 5 +SW_MINIMIZE = 6 +SW_SHOWMINNOACTIVE = 7 +SW_SHOWNA = 8 +SW_RESTORE = 9 +SW_SHOWDEFAULT = 10 +SW_FORCEMINIMIZE = 11 +SW_MAX = 11 +HIDE_WINDOW = 0 +SHOW_OPENWINDOW = 1 +SHOW_ICONWINDOW = 2 +SHOW_FULLSCREEN = 3 +SHOW_OPENNOACTIVATE = 4 +SW_PARENTCLOSING = 1 +SW_OTHERZOOM = 2 +SW_PARENTOPENING = 3 +SW_OTHERUNZOOM = 4 +AW_HOR_POSITIVE = 1 +AW_HOR_NEGATIVE = 2 +AW_VER_POSITIVE = 4 +AW_VER_NEGATIVE = 8 +AW_CENTER = 16 +AW_HIDE = 65536 +AW_ACTIVATE = 131072 +AW_SLIDE = 262144 +AW_BLEND = 524288 +KF_EXTENDED = 256 +KF_DLGMODE = 2048 +KF_MENUMODE = 4096 +KF_ALTDOWN = 8192 +KF_REPEAT = 16384 +KF_UP = 32768 +VK_LBUTTON = 1 +VK_RBUTTON = 2 +VK_CANCEL = 3 +VK_MBUTTON = 4 +VK_BACK = 8 +VK_TAB = 9 +VK_CLEAR = 12 +VK_RETURN = 13 +VK_SHIFT = 16 +VK_CONTROL = 17 +VK_MENU = 18 +VK_PAUSE = 19 +VK_CAPITAL = 20 +VK_KANA = 21 +VK_HANGEUL = 21 # old name - should be here for compatibility +VK_HANGUL = 21 +VK_JUNJA = 23 +VK_FINAL = 24 +VK_HANJA = 25 +VK_KANJI = 25 +VK_ESCAPE = 27 +VK_CONVERT = 28 +VK_NONCONVERT = 29 +VK_ACCEPT = 30 +VK_MODECHANGE = 31 +VK_SPACE = 32 +VK_PRIOR = 33 +VK_NEXT = 34 +VK_END = 35 +VK_HOME = 36 +VK_LEFT = 37 +VK_UP = 38 +VK_RIGHT = 39 +VK_DOWN = 40 +VK_SELECT = 41 +VK_PRINT = 42 +VK_EXECUTE = 43 +VK_SNAPSHOT = 44 +VK_INSERT = 45 +VK_DELETE = 46 +VK_HELP = 47 +VK_LWIN = 91 +VK_RWIN = 92 +VK_APPS = 93 +VK_NUMPAD0 = 96 +VK_NUMPAD1 = 97 +VK_NUMPAD2 = 98 +VK_NUMPAD3 = 99 +VK_NUMPAD4 = 100 +VK_NUMPAD5 = 101 +VK_NUMPAD6 = 102 +VK_NUMPAD7 = 103 +VK_NUMPAD8 = 104 +VK_NUMPAD9 = 105 +VK_MULTIPLY = 106 +VK_ADD = 107 +VK_SEPARATOR = 108 +VK_SUBTRACT = 109 +VK_DECIMAL = 110 +VK_DIVIDE = 111 +VK_F1 = 112 +VK_F2 = 113 +VK_F3 = 114 +VK_F4 = 115 +VK_F5 = 116 +VK_F6 = 117 +VK_F7 = 118 +VK_F8 = 119 +VK_F9 = 120 +VK_F10 = 121 +VK_F11 = 122 +VK_F12 = 123 +VK_F13 = 124 +VK_F14 = 125 +VK_F15 = 126 +VK_F16 = 127 +VK_F17 = 128 +VK_F18 = 129 +VK_F19 = 130 +VK_F20 = 131 +VK_F21 = 132 +VK_F22 = 133 +VK_F23 = 134 +VK_F24 = 135 +VK_NUMLOCK = 144 +VK_SCROLL = 145 +VK_LSHIFT = 160 +VK_RSHIFT = 161 +VK_LCONTROL = 162 +VK_RCONTROL = 163 +VK_LMENU = 164 +VK_RMENU = 165 +VK_PROCESSKEY = 229 +VK_ATTN = 246 +VK_CRSEL = 247 +VK_EXSEL = 248 +VK_EREOF = 249 +VK_PLAY = 250 +VK_ZOOM = 251 +VK_NONAME = 252 +VK_PA1 = 253 +VK_OEM_CLEAR = 254 +# multi-media related "keys" +MOUSEEVENTF_XDOWN = 0x0080 +MOUSEEVENTF_XUP = 0x0100 +MOUSEEVENTF_WHEEL = 0x0800 +VK_XBUTTON1 = 0x05 +VK_XBUTTON2 = 0x06 +VK_VOLUME_MUTE = 0xAD +VK_VOLUME_DOWN = 0xAE +VK_VOLUME_UP = 0xAF +VK_MEDIA_NEXT_TRACK = 0xB0 +VK_MEDIA_PREV_TRACK = 0xB1 +VK_MEDIA_PLAY_PAUSE = 0xB3 +VK_BROWSER_BACK = 0xA6 +VK_BROWSER_FORWARD = 0xA7 +WH_MIN = -1 +WH_MSGFILTER = -1 +WH_JOURNALRECORD = 0 +WH_JOURNALPLAYBACK = 1 +WH_KEYBOARD = 2 +WH_GETMESSAGE = 3 +WH_CALLWNDPROC = 4 +WH_CBT = 5 +WH_SYSMSGFILTER = 6 +WH_MOUSE = 7 +WH_HARDWARE = 8 +WH_DEBUG = 9 +WH_SHELL = 10 +WH_FOREGROUNDIDLE = 11 +WH_CALLWNDPROCRET = 12 +WH_KEYBOARD_LL = 13 +WH_MOUSE_LL = 14 +WH_MAX = 14 +WH_MINHOOK = WH_MIN +WH_MAXHOOK = WH_MAX +HC_ACTION = 0 +HC_GETNEXT = 1 +HC_SKIP = 2 +HC_NOREMOVE = 3 +HC_NOREM = HC_NOREMOVE +HC_SYSMODALON = 4 +HC_SYSMODALOFF = 5 +HCBT_MOVESIZE = 0 +HCBT_MINMAX = 1 +HCBT_QS = 2 +HCBT_CREATEWND = 3 +HCBT_DESTROYWND = 4 +HCBT_ACTIVATE = 5 +HCBT_CLICKSKIPPED = 6 +HCBT_KEYSKIPPED = 7 +HCBT_SYSCOMMAND = 8 +HCBT_SETFOCUS = 9 +MSGF_DIALOGBOX = 0 +MSGF_MESSAGEBOX = 1 +MSGF_MENU = 2 +# MSGF_MOVE = 3 +# MSGF_SIZE = 4 +MSGF_SCROLLBAR = 5 +MSGF_NEXTWINDOW = 6 +# MSGF_MAINLOOP = 8 +MSGF_MAX = 8 +MSGF_USER = 4096 +HSHELL_WINDOWCREATED = 1 +HSHELL_WINDOWDESTROYED = 2 +HSHELL_ACTIVATESHELLWINDOW = 3 +HSHELL_WINDOWACTIVATED = 4 +HSHELL_GETMINRECT = 5 +HSHELL_REDRAW = 6 +HSHELL_TASKMAN = 7 +HSHELL_LANGUAGE = 8 +HSHELL_ACCESSIBILITYSTATE = 11 +ACCESS_STICKYKEYS = 1 +ACCESS_FILTERKEYS = 2 +ACCESS_MOUSEKEYS = 3 +# winuser.h line 624 +LLKHF_EXTENDED = 1 +LLKHF_INJECTED = 16 +LLKHF_ALTDOWN = 32 +LLKHF_UP = 128 +LLKHF_LOWER_IL_INJECTED = 2 +LLMHF_INJECTED = 1 +LLMHF_LOWER_IL_INJECTED = 2 +# line 692 +HKL_PREV = 0 +HKL_NEXT = 1 +KLF_ACTIVATE = 1 +KLF_SUBSTITUTE_OK = 2 +KLF_UNLOADPREVIOUS = 4 +KLF_REORDER = 8 +KLF_REPLACELANG = 16 +KLF_NOTELLSHELL = 128 +KLF_SETFORPROCESS = 256 +KL_NAMELENGTH = 9 +DESKTOP_READOBJECTS = 1 +DESKTOP_CREATEWINDOW = 2 +DESKTOP_CREATEMENU = 4 +DESKTOP_HOOKCONTROL = 8 +DESKTOP_JOURNALRECORD = 16 +DESKTOP_JOURNALPLAYBACK = 32 +DESKTOP_ENUMERATE = 64 +DESKTOP_WRITEOBJECTS = 128 +DESKTOP_SWITCHDESKTOP = 256 +DF_ALLOWOTHERACCOUNTHOOK = 1 +WINSTA_ENUMDESKTOPS = 1 +WINSTA_READATTRIBUTES = 2 +WINSTA_ACCESSCLIPBOARD = 4 +WINSTA_CREATEDESKTOP = 8 +WINSTA_WRITEATTRIBUTES = 16 +WINSTA_ACCESSGLOBALATOMS = 32 +WINSTA_EXITWINDOWS = 64 +WINSTA_ENUMERATE = 256 +WINSTA_READSCREEN = 512 +WSF_VISIBLE = 1 +UOI_FLAGS = 1 +UOI_NAME = 2 +UOI_TYPE = 3 +UOI_USER_SID = 4 +GWL_WNDPROC = -4 +GWL_HINSTANCE = -6 +GWL_HWNDPARENT = -8 +GWL_STYLE = -16 +GWL_EXSTYLE = -20 +GWL_USERDATA = -21 +GWL_ID = -12 +GCL_MENUNAME = -8 +GCL_HBRBACKGROUND = -10 +GCL_HCURSOR = -12 +GCL_HICON = -14 +GCL_HMODULE = -16 +GCL_CBWNDEXTRA = -18 +GCL_CBCLSEXTRA = -20 +GCL_WNDPROC = -24 +GCL_STYLE = -26 +GCW_ATOM = -32 +GCL_HICONSM = -34 +# line 1291 +WM_NULL = 0 +WM_CREATE = 1 +WM_DESTROY = 2 +WM_MOVE = 3 +WM_SIZE = 5 +WM_ACTIVATE = 6 +WA_INACTIVE = 0 +WA_ACTIVE = 1 +WA_CLICKACTIVE = 2 +WM_SETFOCUS = 7 +WM_KILLFOCUS = 8 +WM_ENABLE = 10 +WM_SETREDRAW = 11 +WM_SETTEXT = 12 +WM_GETTEXT = 13 +WM_GETTEXTLENGTH = 14 +WM_PAINT = 15 +WM_CLOSE = 16 +WM_QUERYENDSESSION = 17 +WM_QUIT = 18 +WM_QUERYOPEN = 19 +WM_ERASEBKGND = 20 +WM_SYSCOLORCHANGE = 21 +WM_ENDSESSION = 22 +WM_SHOWWINDOW = 24 +WM_WININICHANGE = 26 +WM_SETTINGCHANGE = WM_WININICHANGE +WM_DEVMODECHANGE = 27 +WM_ACTIVATEAPP = 28 +WM_FONTCHANGE = 29 +WM_TIMECHANGE = 30 +WM_CANCELMODE = 31 +WM_SETCURSOR = 32 +WM_MOUSEACTIVATE = 33 +WM_CHILDACTIVATE = 34 +WM_QUEUESYNC = 35 +WM_GETMINMAXINFO = 36 +WM_PAINTICON = 38 +WM_ICONERASEBKGND = 39 +WM_NEXTDLGCTL = 40 +WM_SPOOLERSTATUS = 42 +WM_DRAWITEM = 43 +WM_MEASUREITEM = 44 +WM_DELETEITEM = 45 +WM_VKEYTOITEM = 46 +WM_CHARTOITEM = 47 +WM_SETFONT = 48 +WM_GETFONT = 49 +WM_SETHOTKEY = 50 +WM_GETHOTKEY = 51 +WM_QUERYDRAGICON = 55 +WM_COMPAREITEM = 57 +WM_GETOBJECT = 61 +WM_COMPACTING = 65 +WM_COMMNOTIFY = 68 +WM_WINDOWPOSCHANGING = 70 +WM_WINDOWPOSCHANGED = 71 +WM_POWER = 72 +PWR_OK = 1 +PWR_FAIL = -1 +PWR_SUSPENDREQUEST = 1 +PWR_SUSPENDRESUME = 2 +PWR_CRITICALRESUME = 3 +WM_COPYDATA = 74 +WM_CANCELJOURNAL = 75 +WM_NOTIFY = 78 +WM_INPUTLANGCHANGEREQUEST = 80 +WM_INPUTLANGCHANGE = 81 +WM_TCARD = 82 +WM_HELP = 83 +WM_USERCHANGED = 84 +WM_NOTIFYFORMAT = 85 +NFR_ANSI = 1 +NFR_UNICODE = 2 +NF_QUERY = 3 +NF_REQUERY = 4 +WM_CONTEXTMENU = 123 +WM_STYLECHANGING = 124 +WM_STYLECHANGED = 125 +WM_DISPLAYCHANGE = 126 +WM_GETICON = 127 +WM_SETICON = 128 +WM_NCCREATE = 129 +WM_NCDESTROY = 130 +WM_NCCALCSIZE = 131 +WM_NCHITTEST = 132 +WM_NCPAINT = 133 +WM_NCACTIVATE = 134 +WM_GETDLGCODE = 135 +WM_SYNCPAINT = 136 +WM_NCMOUSEMOVE = 160 +WM_NCLBUTTONDOWN = 161 +WM_NCLBUTTONUP = 162 +WM_NCLBUTTONDBLCLK = 163 +WM_NCRBUTTONDOWN = 164 +WM_NCRBUTTONUP = 165 +WM_NCRBUTTONDBLCLK = 166 +WM_NCMBUTTONDOWN = 167 +WM_NCMBUTTONUP = 168 +WM_NCMBUTTONDBLCLK = 169 +WM_KEYFIRST = 256 +WM_KEYDOWN = 256 +WM_KEYUP = 257 +WM_CHAR = 258 +WM_DEADCHAR = 259 +WM_SYSKEYDOWN = 260 +WM_SYSKEYUP = 261 +WM_SYSCHAR = 262 +WM_SYSDEADCHAR = 263 +WM_KEYLAST = 264 +WM_IME_STARTCOMPOSITION = 269 +WM_IME_ENDCOMPOSITION = 270 +WM_IME_COMPOSITION = 271 +WM_IME_KEYLAST = 271 +WM_INITDIALOG = 272 +WM_COMMAND = 273 +WM_SYSCOMMAND = 274 +WM_TIMER = 275 +WM_HSCROLL = 276 +WM_VSCROLL = 277 +WM_INITMENU = 278 +WM_INITMENUPOPUP = 279 +WM_MENUSELECT = 287 +WM_MENUCHAR = 288 +WM_ENTERIDLE = 289 +WM_MENURBUTTONUP = 290 +WM_MENUDRAG = 291 +WM_MENUGETOBJECT = 292 +WM_UNINITMENUPOPUP = 293 +WM_MENUCOMMAND = 294 +WM_CTLCOLORMSGBOX = 306 +WM_CTLCOLOREDIT = 307 +WM_CTLCOLORLISTBOX = 308 +WM_CTLCOLORBTN = 309 +WM_CTLCOLORDLG = 310 +WM_CTLCOLORSCROLLBAR = 311 +WM_CTLCOLORSTATIC = 312 +WM_MOUSEFIRST = 512 +WM_MOUSEMOVE = 512 +WM_LBUTTONDOWN = 513 +WM_LBUTTONUP = 514 +WM_LBUTTONDBLCLK = 515 +WM_RBUTTONDOWN = 516 +WM_RBUTTONUP = 517 +WM_RBUTTONDBLCLK = 518 +WM_MBUTTONDOWN = 519 +WM_MBUTTONUP = 520 +WM_MBUTTONDBLCLK = 521 +WM_MOUSEWHEEL = 522 +WM_MOUSELAST = 522 +WHEEL_DELTA = 120 # Value for rolling one detent +WHEEL_PAGESCROLL = -1 # Scroll one page +WM_PARENTNOTIFY = 528 +MENULOOP_WINDOW = 0 +MENULOOP_POPUP = 1 +WM_ENTERMENULOOP = 529 +WM_EXITMENULOOP = 530 +WM_NEXTMENU = 531 +WM_SIZING = 532 +WM_CAPTURECHANGED = 533 +WM_MOVING = 534 +WM_POWERBROADCAST = 536 +PBT_APMQUERYSUSPEND = 0 +PBT_APMQUERYSTANDBY = 1 +PBT_APMQUERYSUSPENDFAILED = 2 +PBT_APMQUERYSTANDBYFAILED = 3 +PBT_APMSUSPEND = 4 +PBT_APMSTANDBY = 5 +PBT_APMRESUMECRITICAL = 6 +PBT_APMRESUMESUSPEND = 7 +PBT_APMRESUMESTANDBY = 8 +PBTF_APMRESUMEFROMFAILURE = 1 +PBT_APMBATTERYLOW = 9 +PBT_APMPOWERSTATUSCHANGE = 10 +PBT_APMOEMEVENT = 11 +PBT_APMRESUMEAUTOMATIC = 18 +WM_DEVICECHANGE = 537 +WM_MDICREATE = 544 +WM_MDIDESTROY = 545 +WM_MDIACTIVATE = 546 +WM_MDIRESTORE = 547 +WM_MDINEXT = 548 +WM_MDIMAXIMIZE = 549 +WM_MDITILE = 550 +WM_MDICASCADE = 551 +WM_MDIICONARRANGE = 552 +WM_MDIGETACTIVE = 553 +WM_MDISETMENU = 560 +WM_ENTERSIZEMOVE = 561 +WM_EXITSIZEMOVE = 562 +WM_DROPFILES = 563 +WM_MDIREFRESHMENU = 564 +WM_IME_SETCONTEXT = 641 +WM_IME_NOTIFY = 642 +WM_IME_CONTROL = 643 +WM_IME_COMPOSITIONFULL = 644 +WM_IME_SELECT = 645 +WM_IME_CHAR = 646 +WM_IME_REQUEST = 648 +WM_IME_KEYDOWN = 656 +WM_IME_KEYUP = 657 +WM_MOUSEHOVER = 673 +WM_MOUSELEAVE = 675 +WM_CUT = 768 +WM_COPY = 769 +WM_PASTE = 770 +WM_CLEAR = 771 +WM_UNDO = 772 +WM_RENDERFORMAT = 773 +WM_RENDERALLFORMATS = 774 +WM_DESTROYCLIPBOARD = 775 +WM_DRAWCLIPBOARD = 776 +WM_PAINTCLIPBOARD = 777 +WM_VSCROLLCLIPBOARD = 778 +WM_SIZECLIPBOARD = 779 +WM_ASKCBFORMATNAME = 780 +WM_CHANGECBCHAIN = 781 +WM_HSCROLLCLIPBOARD = 782 +WM_QUERYNEWPALETTE = 783 +WM_PALETTEISCHANGING = 784 +WM_PALETTECHANGED = 785 +WM_HOTKEY = 786 +WM_PRINT = 791 +WM_PRINTCLIENT = 792 +WM_HANDHELDFIRST = 856 +WM_HANDHELDLAST = 863 +WM_AFXFIRST = 864 +WM_AFXLAST = 895 +WM_PENWINFIRST = 896 +WM_PENWINLAST = 911 +WM_APP = 32768 +WMSZ_LEFT = 1 +WMSZ_RIGHT = 2 +WMSZ_TOP = 3 +WMSZ_TOPLEFT = 4 +WMSZ_TOPRIGHT = 5 +WMSZ_BOTTOM = 6 +WMSZ_BOTTOMLEFT = 7 +WMSZ_BOTTOMRIGHT = 8 +# ST_BEGINSWP = 0 +# ST_ENDSWP = 1 +HTERROR = -2 +HTTRANSPARENT = -1 +HTNOWHERE = 0 +HTCLIENT = 1 +HTCAPTION = 2 +HTSYSMENU = 3 +HTGROWBOX = 4 +HTSIZE = HTGROWBOX +HTMENU = 5 +HTHSCROLL = 6 +HTVSCROLL = 7 +HTMINBUTTON = 8 +HTMAXBUTTON = 9 +HTLEFT = 10 +HTRIGHT = 11 +HTTOP = 12 +HTTOPLEFT = 13 +HTTOPRIGHT = 14 +HTBOTTOM = 15 +HTBOTTOMLEFT = 16 +HTBOTTOMRIGHT = 17 +HTBORDER = 18 +HTREDUCE = HTMINBUTTON +HTZOOM = HTMAXBUTTON +HTSIZEFIRST = HTLEFT +HTSIZELAST = HTBOTTOMRIGHT +HTOBJECT = 19 +HTCLOSE = 20 +HTHELP = 21 +SMTO_NORMAL = 0 +SMTO_BLOCK = 1 +SMTO_ABORTIFHUNG = 2 +SMTO_NOTIMEOUTIFNOTHUNG = 8 +MA_ACTIVATE = 1 +MA_ACTIVATEANDEAT = 2 +MA_NOACTIVATE = 3 +MA_NOACTIVATEANDEAT = 4 +ICON_SMALL = 0 +ICON_BIG = 1 +SIZE_RESTORED = 0 +SIZE_MINIMIZED = 1 +SIZE_MAXIMIZED = 2 +SIZE_MAXSHOW = 3 +SIZE_MAXHIDE = 4 +SIZENORMAL = SIZE_RESTORED +SIZEICONIC = SIZE_MINIMIZED +SIZEFULLSCREEN = SIZE_MAXIMIZED +SIZEZOOMSHOW = SIZE_MAXSHOW +SIZEZOOMHIDE = SIZE_MAXHIDE +WVR_ALIGNTOP = 16 +WVR_ALIGNLEFT = 32 +WVR_ALIGNBOTTOM = 64 +WVR_ALIGNRIGHT = 128 +WVR_HREDRAW = 256 +WVR_VREDRAW = 512 +WVR_REDRAW = WVR_HREDRAW | WVR_VREDRAW +WVR_VALIDRECTS = 1024 +MK_LBUTTON = 1 +MK_RBUTTON = 2 +MK_SHIFT = 4 +MK_CONTROL = 8 +MK_MBUTTON = 16 +TME_HOVER = 1 +TME_LEAVE = 2 +TME_QUERY = 1073741824 +TME_CANCEL = -2147483648 +HOVER_DEFAULT = -1 +WS_OVERLAPPED = 0 +WS_POPUP = -2147483648 +WS_CHILD = 1073741824 +WS_MINIMIZE = 536870912 +WS_VISIBLE = 268435456 +WS_DISABLED = 134217728 +WS_CLIPSIBLINGS = 67108864 +WS_CLIPCHILDREN = 33554432 +WS_MAXIMIZE = 16777216 +WS_CAPTION = 12582912 +WS_BORDER = 8388608 +WS_DLGFRAME = 4194304 +WS_VSCROLL = 2097152 +WS_HSCROLL = 1048576 +WS_SYSMENU = 524288 +WS_THICKFRAME = 262144 +WS_GROUP = 131072 +WS_TABSTOP = 65536 +WS_MINIMIZEBOX = 131072 +WS_MAXIMIZEBOX = 65536 +WS_TILED = WS_OVERLAPPED +WS_ICONIC = WS_MINIMIZE +WS_SIZEBOX = WS_THICKFRAME +WS_OVERLAPPEDWINDOW = ( + WS_OVERLAPPED + | WS_CAPTION + | WS_SYSMENU + | WS_THICKFRAME + | WS_MINIMIZEBOX + | WS_MAXIMIZEBOX +) +WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU +WS_CHILDWINDOW = WS_CHILD +WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW +WS_EX_DLGMODALFRAME = 1 +WS_EX_NOPARENTNOTIFY = 4 +WS_EX_TOPMOST = 8 +WS_EX_ACCEPTFILES = 16 +WS_EX_TRANSPARENT = 32 +WS_EX_MDICHILD = 64 +WS_EX_TOOLWINDOW = 128 +WS_EX_WINDOWEDGE = 256 +WS_EX_CLIENTEDGE = 512 +WS_EX_CONTEXTHELP = 1024 +WS_EX_RIGHT = 4096 +WS_EX_LEFT = 0 +WS_EX_RTLREADING = 8192 +WS_EX_LTRREADING = 0 +WS_EX_LEFTSCROLLBAR = 16384 +WS_EX_RIGHTSCROLLBAR = 0 +WS_EX_CONTROLPARENT = 65536 +WS_EX_STATICEDGE = 131072 +WS_EX_APPWINDOW = 262144 +WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE +WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST +WS_EX_LAYERED = 0x00080000 +WS_EX_NOINHERITLAYOUT = 0x00100000 +WS_EX_LAYOUTRTL = 0x00400000 +WS_EX_COMPOSITED = 0x02000000 +WS_EX_NOACTIVATE = 0x08000000 + +CS_VREDRAW = 1 +CS_HREDRAW = 2 +# CS_KEYCVTWINDOW = 0x0004 +CS_DBLCLKS = 8 +CS_OWNDC = 32 +CS_CLASSDC = 64 +CS_PARENTDC = 128 +# CS_NOKEYCVT = 0x0100 +CS_NOCLOSE = 512 +CS_SAVEBITS = 2048 +CS_BYTEALIGNCLIENT = 4096 +CS_BYTEALIGNWINDOW = 8192 +CS_GLOBALCLASS = 16384 +CS_IME = 65536 +PRF_CHECKVISIBLE = 1 +PRF_NONCLIENT = 2 +PRF_CLIENT = 4 +PRF_ERASEBKGND = 8 +PRF_CHILDREN = 16 +PRF_OWNED = 32 +BDR_RAISEDOUTER = 1 +BDR_SUNKENOUTER = 2 +BDR_RAISEDINNER = 4 +BDR_SUNKENINNER = 8 +BDR_OUTER = 3 +BDR_INNER = 12 +# BDR_RAISED = 0x0005 +# BDR_SUNKEN = 0x000a +EDGE_RAISED = BDR_RAISEDOUTER | BDR_RAISEDINNER +EDGE_SUNKEN = BDR_SUNKENOUTER | BDR_SUNKENINNER +EDGE_ETCHED = BDR_SUNKENOUTER | BDR_RAISEDINNER +EDGE_BUMP = BDR_RAISEDOUTER | BDR_SUNKENINNER + +# winuser.h line 2879 +ISMEX_NOSEND = 0 +ISMEX_SEND = 1 +ISMEX_NOTIFY = 2 +ISMEX_CALLBACK = 4 +ISMEX_REPLIED = 8 +CW_USEDEFAULT = -2147483648 +FLASHW_STOP = 0 +FLASHW_CAPTION = 1 +FLASHW_TRAY = 2 +FLASHW_ALL = FLASHW_CAPTION | FLASHW_TRAY +FLASHW_TIMER = 4 +FLASHW_TIMERNOFG = 12 + +# winuser.h line 7963 +DS_ABSALIGN = 1 +DS_SYSMODAL = 2 +DS_LOCALEDIT = 32 +DS_SETFONT = 64 +DS_MODALFRAME = 128 +DS_NOIDLEMSG = 256 +DS_SETFOREGROUND = 512 +DS_3DLOOK = 4 +DS_FIXEDSYS = 8 +DS_NOFAILCREATE = 16 +DS_CONTROL = 1024 +DS_CENTER = 2048 +DS_CENTERMOUSE = 4096 +DS_CONTEXTHELP = 8192 +DM_GETDEFID = WM_USER + 0 +DM_SETDEFID = WM_USER + 1 +DM_REPOSITION = WM_USER + 2 +# PSM_PAGEINFO = (WM_USER+100) +# PSM_SHEETINFO = (WM_USER+101) +# PSI_SETACTIVE = 0x0001 +# PSI_KILLACTIVE = 0x0002 +# PSI_APPLY = 0x0003 +# PSI_RESET = 0x0004 +# PSI_HASHELP = 0x0005 +# PSI_HELP = 0x0006 +# PSI_CHANGED = 0x0001 +# PSI_GUISTART = 0x0002 +# PSI_REBOOT = 0x0003 +# PSI_GETSIBLINGS = 0x0004 +DC_HASDEFID = 21323 +DLGC_WANTARROWS = 1 +DLGC_WANTTAB = 2 +DLGC_WANTALLKEYS = 4 +DLGC_WANTMESSAGE = 4 +DLGC_HASSETSEL = 8 +DLGC_DEFPUSHBUTTON = 16 +DLGC_UNDEFPUSHBUTTON = 32 +DLGC_RADIOBUTTON = 64 +DLGC_WANTCHARS = 128 +DLGC_STATIC = 256 +DLGC_BUTTON = 8192 +LB_CTLCODE = 0 +LB_OKAY = 0 +LB_ERR = -1 +LB_ERRSPACE = -2 +LBN_ERRSPACE = -2 +LBN_SELCHANGE = 1 +LBN_DBLCLK = 2 +LBN_SELCANCEL = 3 +LBN_SETFOCUS = 4 +LBN_KILLFOCUS = 5 +LB_ADDSTRING = 384 +LB_INSERTSTRING = 385 +LB_DELETESTRING = 386 +LB_SELITEMRANGEEX = 387 +LB_RESETCONTENT = 388 +LB_SETSEL = 389 +LB_SETCURSEL = 390 +LB_GETSEL = 391 +LB_GETCURSEL = 392 +LB_GETTEXT = 393 +LB_GETTEXTLEN = 394 +LB_GETCOUNT = 395 +LB_SELECTSTRING = 396 +LB_DIR = 397 +LB_GETTOPINDEX = 398 +LB_FINDSTRING = 399 +LB_GETSELCOUNT = 400 +LB_GETSELITEMS = 401 +LB_SETTABSTOPS = 402 +LB_GETHORIZONTALEXTENT = 403 +LB_SETHORIZONTALEXTENT = 404 +LB_SETCOLUMNWIDTH = 405 +LB_ADDFILE = 406 +LB_SETTOPINDEX = 407 +LB_GETITEMRECT = 408 +LB_GETITEMDATA = 409 +LB_SETITEMDATA = 410 +LB_SELITEMRANGE = 411 +LB_SETANCHORINDEX = 412 +LB_GETANCHORINDEX = 413 +LB_SETCARETINDEX = 414 +LB_GETCARETINDEX = 415 +LB_SETITEMHEIGHT = 416 +LB_GETITEMHEIGHT = 417 +LB_FINDSTRINGEXACT = 418 +LB_SETLOCALE = 421 +LB_GETLOCALE = 422 +LB_SETCOUNT = 423 +LB_INITSTORAGE = 424 +LB_ITEMFROMPOINT = 425 +LB_MSGMAX = 432 +LBS_NOTIFY = 1 +LBS_SORT = 2 +LBS_NOREDRAW = 4 +LBS_MULTIPLESEL = 8 +LBS_OWNERDRAWFIXED = 16 +LBS_OWNERDRAWVARIABLE = 32 +LBS_HASSTRINGS = 64 +LBS_USETABSTOPS = 128 +LBS_NOINTEGRALHEIGHT = 256 +LBS_MULTICOLUMN = 512 +LBS_WANTKEYBOARDINPUT = 1024 +LBS_EXTENDEDSEL = 2048 +LBS_DISABLENOSCROLL = 4096 +LBS_NODATA = 8192 +LBS_NOSEL = 16384 +LBS_STANDARD = LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER +CB_OKAY = 0 +CB_ERR = -1 +CB_ERRSPACE = -2 +CBN_ERRSPACE = -1 +CBN_SELCHANGE = 1 +CBN_DBLCLK = 2 +CBN_SETFOCUS = 3 +CBN_KILLFOCUS = 4 +CBN_EDITCHANGE = 5 +CBN_EDITUPDATE = 6 +CBN_DROPDOWN = 7 +CBN_CLOSEUP = 8 +CBN_SELENDOK = 9 +CBN_SELENDCANCEL = 10 +CBS_SIMPLE = 1 +CBS_DROPDOWN = 2 +CBS_DROPDOWNLIST = 3 +CBS_OWNERDRAWFIXED = 16 +CBS_OWNERDRAWVARIABLE = 32 +CBS_AUTOHSCROLL = 64 +CBS_OEMCONVERT = 128 +CBS_SORT = 256 +CBS_HASSTRINGS = 512 +CBS_NOINTEGRALHEIGHT = 1024 +CBS_DISABLENOSCROLL = 2048 +CBS_UPPERCASE = 8192 +CBS_LOWERCASE = 16384 +CB_GETEDITSEL = 320 +CB_LIMITTEXT = 321 +CB_SETEDITSEL = 322 +CB_ADDSTRING = 323 +CB_DELETESTRING = 324 +CB_DIR = 325 +CB_GETCOUNT = 326 +CB_GETCURSEL = 327 +CB_GETLBTEXT = 328 +CB_GETLBTEXTLEN = 329 +CB_INSERTSTRING = 330 +CB_RESETCONTENT = 331 +CB_FINDSTRING = 332 +CB_SELECTSTRING = 333 +CB_SETCURSEL = 334 +CB_SHOWDROPDOWN = 335 +CB_GETITEMDATA = 336 +CB_SETITEMDATA = 337 +CB_GETDROPPEDCONTROLRECT = 338 +CB_SETITEMHEIGHT = 339 +CB_GETITEMHEIGHT = 340 +CB_SETEXTENDEDUI = 341 +CB_GETEXTENDEDUI = 342 +CB_GETDROPPEDSTATE = 343 +CB_FINDSTRINGEXACT = 344 +CB_SETLOCALE = 345 +CB_GETLOCALE = 346 +CB_GETTOPINDEX = 347 +CB_SETTOPINDEX = 348 +CB_GETHORIZONTALEXTENT = 349 +CB_SETHORIZONTALEXTENT = 350 +CB_GETDROPPEDWIDTH = 351 +CB_SETDROPPEDWIDTH = 352 +CB_INITSTORAGE = 353 +CB_MSGMAX = 354 +SBS_HORZ = 0 +SBS_VERT = 1 +SBS_TOPALIGN = 2 +SBS_LEFTALIGN = 2 +SBS_BOTTOMALIGN = 4 +SBS_RIGHTALIGN = 4 +SBS_SIZEBOXTOPLEFTALIGN = 2 +SBS_SIZEBOXBOTTOMRIGHTALIGN = 4 +SBS_SIZEBOX = 8 +SBS_SIZEGRIP = 16 +SBM_SETPOS = 224 +SBM_GETPOS = 225 +SBM_SETRANGE = 226 +SBM_SETRANGEREDRAW = 230 +SBM_GETRANGE = 227 +SBM_ENABLE_ARROWS = 228 +SBM_SETSCROLLINFO = 233 +SBM_GETSCROLLINFO = 234 +SIF_RANGE = 1 +SIF_PAGE = 2 +SIF_POS = 4 +SIF_DISABLENOSCROLL = 8 +SIF_TRACKPOS = 16 +SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS +MDIS_ALLCHILDSTYLES = 1 +MDITILE_VERTICAL = 0 +MDITILE_HORIZONTAL = 1 +MDITILE_SKIPDISABLED = 2 +MDITILE_ZORDER = 4 + +IMC_GETCANDIDATEPOS = 7 +IMC_SETCANDIDATEPOS = 8 +IMC_GETCOMPOSITIONFONT = 9 +IMC_SETCOMPOSITIONFONT = 10 +IMC_GETCOMPOSITIONWINDOW = 11 +IMC_SETCOMPOSITIONWINDOW = 12 +IMC_GETSTATUSWINDOWPOS = 15 +IMC_SETSTATUSWINDOWPOS = 16 +IMC_CLOSESTATUSWINDOW = 33 +IMC_OPENSTATUSWINDOW = 34 +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +DELETE = 65536 +READ_CONTROL = 131072 +WRITE_DAC = 262144 +WRITE_OWNER = 524288 +SYNCHRONIZE = 1048576 +STANDARD_RIGHTS_REQUIRED = 983040 +STANDARD_RIGHTS_READ = READ_CONTROL +STANDARD_RIGHTS_WRITE = READ_CONTROL +STANDARD_RIGHTS_EXECUTE = READ_CONTROL +STANDARD_RIGHTS_ALL = 2031616 +SPECIFIC_RIGHTS_ALL = 65535 +ACCESS_SYSTEM_SECURITY = 16777216 +MAXIMUM_ALLOWED = 33554432 +GENERIC_READ = -2147483648 +GENERIC_WRITE = 1073741824 +GENERIC_EXECUTE = 536870912 +GENERIC_ALL = 268435456 + +SERVICE_KERNEL_DRIVER = 1 +SERVICE_FILE_SYSTEM_DRIVER = 2 +SERVICE_ADAPTER = 4 +SERVICE_RECOGNIZER_DRIVER = 8 +SERVICE_DRIVER = ( + SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER +) +SERVICE_WIN32_OWN_PROCESS = 16 +SERVICE_WIN32_SHARE_PROCESS = 32 +SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS +SERVICE_INTERACTIVE_PROCESS = 256 +SERVICE_TYPE_ALL = ( + SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS +) +SERVICE_BOOT_START = 0 +SERVICE_SYSTEM_START = 1 +SERVICE_AUTO_START = 2 +SERVICE_DEMAND_START = 3 +SERVICE_DISABLED = 4 +SERVICE_ERROR_IGNORE = 0 +SERVICE_ERROR_NORMAL = 1 +SERVICE_ERROR_SEVERE = 2 +SERVICE_ERROR_CRITICAL = 3 +TAPE_ERASE_SHORT = 0 +TAPE_ERASE_LONG = 1 +TAPE_LOAD = 0 +TAPE_UNLOAD = 1 +TAPE_TENSION = 2 +TAPE_LOCK = 3 +TAPE_UNLOCK = 4 +TAPE_FORMAT = 5 +TAPE_SETMARKS = 0 +TAPE_FILEMARKS = 1 +TAPE_SHORT_FILEMARKS = 2 +TAPE_LONG_FILEMARKS = 3 +TAPE_ABSOLUTE_POSITION = 0 +TAPE_LOGICAL_POSITION = 1 +TAPE_PSEUDO_LOGICAL_POSITION = 2 +TAPE_REWIND = 0 +TAPE_ABSOLUTE_BLOCK = 1 +TAPE_LOGICAL_BLOCK = 2 +TAPE_PSEUDO_LOGICAL_BLOCK = 3 +TAPE_SPACE_END_OF_DATA = 4 +TAPE_SPACE_RELATIVE_BLOCKS = 5 +TAPE_SPACE_FILEMARKS = 6 +TAPE_SPACE_SEQUENTIAL_FMKS = 7 +TAPE_SPACE_SETMARKS = 8 +TAPE_SPACE_SEQUENTIAL_SMKS = 9 +TAPE_DRIVE_FIXED = 1 +TAPE_DRIVE_SELECT = 2 +TAPE_DRIVE_INITIATOR = 4 +TAPE_DRIVE_ERASE_SHORT = 16 +TAPE_DRIVE_ERASE_LONG = 32 +TAPE_DRIVE_ERASE_BOP_ONLY = 64 +TAPE_DRIVE_ERASE_IMMEDIATE = 128 +TAPE_DRIVE_TAPE_CAPACITY = 256 +TAPE_DRIVE_TAPE_REMAINING = 512 +TAPE_DRIVE_FIXED_BLOCK = 1024 +TAPE_DRIVE_VARIABLE_BLOCK = 2048 +TAPE_DRIVE_WRITE_PROTECT = 4096 +TAPE_DRIVE_EOT_WZ_SIZE = 8192 +TAPE_DRIVE_ECC = 65536 +TAPE_DRIVE_COMPRESSION = 131072 +TAPE_DRIVE_PADDING = 262144 +TAPE_DRIVE_REPORT_SMKS = 524288 +TAPE_DRIVE_GET_ABSOLUTE_BLK = 1048576 +TAPE_DRIVE_GET_LOGICAL_BLK = 2097152 +TAPE_DRIVE_SET_EOT_WZ_SIZE = 4194304 +TAPE_DRIVE_LOAD_UNLOAD = -2147483647 +TAPE_DRIVE_TENSION = -2147483646 +TAPE_DRIVE_LOCK_UNLOCK = -2147483644 +TAPE_DRIVE_REWIND_IMMEDIATE = -2147483640 +TAPE_DRIVE_SET_BLOCK_SIZE = -2147483632 +TAPE_DRIVE_LOAD_UNLD_IMMED = -2147483616 +TAPE_DRIVE_TENSION_IMMED = -2147483584 +TAPE_DRIVE_LOCK_UNLK_IMMED = -2147483520 +TAPE_DRIVE_SET_ECC = -2147483392 +TAPE_DRIVE_SET_COMPRESSION = -2147483136 +TAPE_DRIVE_SET_PADDING = -2147482624 +TAPE_DRIVE_SET_REPORT_SMKS = -2147481600 +TAPE_DRIVE_ABSOLUTE_BLK = -2147479552 +TAPE_DRIVE_ABS_BLK_IMMED = -2147475456 +TAPE_DRIVE_LOGICAL_BLK = -2147467264 +TAPE_DRIVE_LOG_BLK_IMMED = -2147450880 +TAPE_DRIVE_END_OF_DATA = -2147418112 +TAPE_DRIVE_RELATIVE_BLKS = -2147352576 +TAPE_DRIVE_FILEMARKS = -2147221504 +TAPE_DRIVE_SEQUENTIAL_FMKS = -2146959360 +TAPE_DRIVE_SETMARKS = -2146435072 +TAPE_DRIVE_SEQUENTIAL_SMKS = -2145386496 +TAPE_DRIVE_REVERSE_POSITION = -2143289344 +TAPE_DRIVE_SPACE_IMMEDIATE = -2139095040 +TAPE_DRIVE_WRITE_SETMARKS = -2130706432 +TAPE_DRIVE_WRITE_FILEMARKS = -2113929216 +TAPE_DRIVE_WRITE_SHORT_FMKS = -2080374784 +TAPE_DRIVE_WRITE_LONG_FMKS = -2013265920 +TAPE_DRIVE_WRITE_MARK_IMMED = -1879048192 +TAPE_DRIVE_FORMAT = -1610612736 +TAPE_DRIVE_FORMAT_IMMEDIATE = -1073741824 +TAPE_FIXED_PARTITIONS = 0 +TAPE_SELECT_PARTITIONS = 1 +TAPE_INITIATOR_PARTITIONS = 2 +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. + +APPLICATION_ERROR_MASK = 536870912 +ERROR_SEVERITY_SUCCESS = 0 +ERROR_SEVERITY_INFORMATIONAL = 1073741824 +ERROR_SEVERITY_WARNING = -2147483648 +ERROR_SEVERITY_ERROR = -1073741824 +MINCHAR = 128 +MAXCHAR = 127 +MINSHORT = 32768 +MAXSHORT = 32767 +MINLONG = -2147483648 +MAXLONG = 2147483647 +MAXBYTE = 255 +MAXWORD = 65535 +MAXDWORD = -1 +LANG_NEUTRAL = 0 +LANG_BULGARIAN = 2 +LANG_CHINESE = 4 +LANG_CROATIAN = 26 +LANG_CZECH = 5 +LANG_DANISH = 6 +LANG_DUTCH = 19 +LANG_ENGLISH = 9 +LANG_FINNISH = 11 +LANG_FRENCH = 12 +LANG_GERMAN = 7 +LANG_GREEK = 8 +LANG_HUNGARIAN = 14 +LANG_ICELANDIC = 15 +LANG_ITALIAN = 16 +LANG_JAPANESE = 17 +LANG_KOREAN = 18 +LANG_NORWEGIAN = 20 +LANG_POLISH = 21 +LANG_PORTUGUESE = 22 +LANG_ROMANIAN = 24 +LANG_RUSSIAN = 25 +LANG_SLOVAK = 27 +LANG_SLOVENIAN = 36 +LANG_SPANISH = 10 +LANG_SWEDISH = 29 +LANG_TURKISH = 31 +SUBLANG_NEUTRAL = 0 +SUBLANG_DEFAULT = 1 +SUBLANG_SYS_DEFAULT = 2 +SUBLANG_CHINESE_TRADITIONAL = 1 +SUBLANG_CHINESE_SIMPLIFIED = 2 +SUBLANG_CHINESE_HONGKONG = 3 +SUBLANG_CHINESE_SINGAPORE = 4 +SUBLANG_DUTCH = 1 +SUBLANG_DUTCH_BELGIAN = 2 +SUBLANG_ENGLISH_US = 1 +SUBLANG_ENGLISH_UK = 2 +SUBLANG_ENGLISH_AUS = 3 +SUBLANG_ENGLISH_CAN = 4 +SUBLANG_ENGLISH_NZ = 5 +SUBLANG_ENGLISH_EIRE = 6 +SUBLANG_FRENCH = 1 +SUBLANG_FRENCH_BELGIAN = 2 +SUBLANG_FRENCH_CANADIAN = 3 +SUBLANG_FRENCH_SWISS = 4 +SUBLANG_GERMAN = 1 +SUBLANG_GERMAN_SWISS = 2 +SUBLANG_GERMAN_AUSTRIAN = 3 +SUBLANG_ITALIAN = 1 +SUBLANG_ITALIAN_SWISS = 2 +SUBLANG_NORWEGIAN_BOKMAL = 1 +SUBLANG_NORWEGIAN_NYNORSK = 2 +SUBLANG_PORTUGUESE = 2 +SUBLANG_PORTUGUESE_BRAZILIAN = 1 +SUBLANG_SPANISH = 1 +SUBLANG_SPANISH_MEXICAN = 2 +SUBLANG_SPANISH_MODERN = 3 +SORT_DEFAULT = 0 +SORT_JAPANESE_XJIS = 0 +SORT_JAPANESE_UNICODE = 1 +SORT_CHINESE_BIG5 = 0 +SORT_CHINESE_UNICODE = 1 +SORT_KOREAN_KSC = 0 +SORT_KOREAN_UNICODE = 1 + + +def PRIMARYLANGID(lgid): + return (lgid) & 1023 + + +def SUBLANGID(lgid): + return (lgid) >> 10 + + +NLS_VALID_LOCALE_MASK = 1048575 +CONTEXT_PORTABLE_32BIT = 1048576 +CONTEXT_ALPHA = 131072 +CONTEXT_CONTROL = CONTEXT_ALPHA | 1 +CONTEXT_FLOATING_POINT = CONTEXT_ALPHA | 2 +CONTEXT_INTEGER = CONTEXT_ALPHA | 4 +CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER +SIZE_OF_80387_REGISTERS = 80 +CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER +CONTEXT_CONTROL = 1 +CONTEXT_FLOATING_POINT = 2 +CONTEXT_INTEGER = 4 +CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER +PROCESS_TERMINATE = 1 +PROCESS_CREATE_THREAD = 2 +PROCESS_VM_OPERATION = 8 +PROCESS_VM_READ = 16 +PROCESS_VM_WRITE = 32 +PROCESS_DUP_HANDLE = 64 +PROCESS_CREATE_PROCESS = 128 +PROCESS_SET_QUOTA = 256 +PROCESS_SET_INFORMATION = 512 +PROCESS_QUERY_INFORMATION = 1024 +PROCESS_SUSPEND_RESUME = 2048 +PROCESS_QUERY_LIMITED_INFORMATION = 4096 +PROCESS_SET_LIMITED_INFORMATION = 8192 +PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 4095 +THREAD_TERMINATE = 1 +THREAD_SUSPEND_RESUME = 2 +THREAD_GET_CONTEXT = 8 +THREAD_SET_CONTEXT = 16 +THREAD_SET_INFORMATION = 32 +THREAD_QUERY_INFORMATION = 64 +THREAD_SET_THREAD_TOKEN = 128 +THREAD_IMPERSONATE = 256 +THREAD_DIRECT_IMPERSONATION = 512 +THREAD_SET_LIMITED_INFORMATION = 1024 +THREAD_QUERY_LIMITED_INFORMATION = 2048 +THREAD_RESUME = 4096 +TLS_MINIMUM_AVAILABLE = 64 +EVENT_MODIFY_STATE = 2 +MUTANT_QUERY_STATE = 1 +SEMAPHORE_MODIFY_STATE = 2 +TIME_ZONE_ID_UNKNOWN = 0 +TIME_ZONE_ID_STANDARD = 1 +TIME_ZONE_ID_DAYLIGHT = 2 +PROCESSOR_INTEL_386 = 386 +PROCESSOR_INTEL_486 = 486 +PROCESSOR_INTEL_PENTIUM = 586 +PROCESSOR_INTEL_860 = 860 +PROCESSOR_MIPS_R2000 = 2000 +PROCESSOR_MIPS_R3000 = 3000 +PROCESSOR_MIPS_R4000 = 4000 +PROCESSOR_ALPHA_21064 = 21064 +PROCESSOR_PPC_601 = 601 +PROCESSOR_PPC_603 = 603 +PROCESSOR_PPC_604 = 604 +PROCESSOR_PPC_620 = 620 +SECTION_QUERY = 1 +SECTION_MAP_WRITE = 2 +SECTION_MAP_READ = 4 +SECTION_MAP_EXECUTE = 8 +SECTION_EXTEND_SIZE = 16 +PAGE_NOACCESS = 1 +PAGE_READONLY = 2 +PAGE_READWRITE = 4 +PAGE_WRITECOPY = 8 +PAGE_EXECUTE = 16 +PAGE_EXECUTE_READ = 32 +PAGE_EXECUTE_READWRITE = 64 +PAGE_EXECUTE_WRITECOPY = 128 +PAGE_GUARD = 256 +PAGE_NOCACHE = 512 +MEM_COMMIT = 4096 +MEM_RESERVE = 8192 +MEM_DECOMMIT = 16384 +MEM_RELEASE = 32768 +MEM_FREE = 65536 +MEM_PRIVATE = 131072 +MEM_MAPPED = 262144 +MEM_TOP_DOWN = 1048576 + +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +SEC_FILE = 8388608 +SEC_IMAGE = 16777216 +SEC_RESERVE = 67108864 +SEC_COMMIT = 134217728 +SEC_NOCACHE = 268435456 +MEM_IMAGE = SEC_IMAGE +FILE_SHARE_READ = 1 +FILE_SHARE_WRITE = 2 +FILE_SHARE_DELETE = 4 +FILE_ATTRIBUTE_READONLY = 1 +FILE_ATTRIBUTE_HIDDEN = 2 +FILE_ATTRIBUTE_SYSTEM = 4 +FILE_ATTRIBUTE_DIRECTORY = 16 +FILE_ATTRIBUTE_ARCHIVE = 32 +FILE_ATTRIBUTE_DEVICE = 64 +FILE_ATTRIBUTE_NORMAL = 128 +FILE_ATTRIBUTE_TEMPORARY = 256 +FILE_ATTRIBUTE_SPARSE_FILE = 512 +FILE_ATTRIBUTE_REPARSE_POINT = 1024 +FILE_ATTRIBUTE_COMPRESSED = 2048 +FILE_ATTRIBUTE_OFFLINE = 4096 +FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192 +FILE_ATTRIBUTE_ENCRYPTED = 16384 +FILE_ATTRIBUTE_VIRTUAL = 65536 +# These FILE_ATTRIBUTE_* flags are apparently old definitions from Windows 95 +# and conflict with current values above - but they live on for b/w compat... +FILE_ATTRIBUTE_ATOMIC_WRITE = 512 +FILE_ATTRIBUTE_XACTION_WRITE = 1024 + +FILE_NOTIFY_CHANGE_FILE_NAME = 1 +FILE_NOTIFY_CHANGE_DIR_NAME = 2 +FILE_NOTIFY_CHANGE_ATTRIBUTES = 4 +FILE_NOTIFY_CHANGE_SIZE = 8 +FILE_NOTIFY_CHANGE_LAST_WRITE = 16 +FILE_NOTIFY_CHANGE_SECURITY = 256 +FILE_CASE_SENSITIVE_SEARCH = 1 +FILE_CASE_PRESERVED_NAMES = 2 +FILE_UNICODE_ON_DISK = 4 +FILE_PERSISTENT_ACLS = 8 +FILE_FILE_COMPRESSION = 16 +FILE_NAMED_STREAMS = 262144 +FILE_PERSISTENT_ACLS = 0x00000008 +FILE_READ_ONLY_VOLUME = 0x00080000 +FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000 +FILE_SUPPORTS_ENCRYPTION = 0x00020000 +FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000 +FILE_SUPPORTS_HARD_LINKS = 0x00400000 +FILE_SUPPORTS_OBJECT_IDS = 0x00010000 +FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000 +FILE_SUPPORTS_REPARSE_POINTS = 0x00000080 +FILE_SUPPORTS_SPARSE_FILES = 0x00000040 +FILE_SUPPORTS_TRANSACTIONS = 0x00200000 +FILE_SUPPORTS_USN_JOURNAL = 0x02000000 +FILE_UNICODE_ON_DISK = 0x00000004 +FILE_VOLUME_IS_COMPRESSED = 0x00008000 +FILE_VOLUME_QUOTAS = 0x00000020 +FILE_VOLUME_IS_COMPRESSED = 32768 +IO_COMPLETION_MODIFY_STATE = 2 +DUPLICATE_CLOSE_SOURCE = 1 +DUPLICATE_SAME_ACCESS = 2 +SID_MAX_SUB_AUTHORITIES = 15 +SECURITY_NULL_RID = 0 +SECURITY_WORLD_RID = 0 +SECURITY_LOCAL_RID = 0x00000000 +SECURITY_CREATOR_OWNER_RID = 0 +SECURITY_CREATOR_GROUP_RID = 1 +SECURITY_DIALUP_RID = 1 +SECURITY_NETWORK_RID = 2 +SECURITY_BATCH_RID = 3 +SECURITY_INTERACTIVE_RID = 4 +SECURITY_SERVICE_RID = 6 +SECURITY_ANONYMOUS_LOGON_RID = 7 +SECURITY_LOGON_IDS_RID = 5 +SECURITY_LOGON_IDS_RID_COUNT = 3 +SECURITY_LOCAL_SYSTEM_RID = 18 +SECURITY_NT_NON_UNIQUE = 21 +SECURITY_BUILTIN_DOMAIN_RID = 32 +DOMAIN_USER_RID_ADMIN = 500 +DOMAIN_USER_RID_GUEST = 501 +DOMAIN_GROUP_RID_ADMINS = 512 +DOMAIN_GROUP_RID_USERS = 513 +DOMAIN_GROUP_RID_GUESTS = 514 +DOMAIN_ALIAS_RID_ADMINS = 544 +DOMAIN_ALIAS_RID_USERS = 545 +DOMAIN_ALIAS_RID_GUESTS = 546 +DOMAIN_ALIAS_RID_POWER_USERS = 547 +DOMAIN_ALIAS_RID_ACCOUNT_OPS = 548 +DOMAIN_ALIAS_RID_SYSTEM_OPS = 549 +DOMAIN_ALIAS_RID_PRINT_OPS = 550 +DOMAIN_ALIAS_RID_BACKUP_OPS = 551 +DOMAIN_ALIAS_RID_REPLICATOR = 552 +SE_GROUP_MANDATORY = 1 +SE_GROUP_ENABLED_BY_DEFAULT = 2 +SE_GROUP_ENABLED = 4 +SE_GROUP_OWNER = 8 +SE_GROUP_LOGON_ID = -1073741824 +ACL_REVISION = 2 +ACL_REVISION1 = 1 +ACL_REVISION2 = 2 +ACCESS_ALLOWED_ACE_TYPE = 0 +ACCESS_DENIED_ACE_TYPE = 1 +SYSTEM_AUDIT_ACE_TYPE = 2 +SYSTEM_ALARM_ACE_TYPE = 3 +OBJECT_INHERIT_ACE = 1 +CONTAINER_INHERIT_ACE = 2 +NO_PROPAGATE_INHERIT_ACE = 4 +INHERIT_ONLY_ACE = 8 +VALID_INHERIT_FLAGS = 15 +SUCCESSFUL_ACCESS_ACE_FLAG = 64 +FAILED_ACCESS_ACE_FLAG = 128 +SECURITY_DESCRIPTOR_REVISION = 1 +SECURITY_DESCRIPTOR_REVISION1 = 1 +SECURITY_DESCRIPTOR_MIN_LENGTH = 20 +SE_OWNER_DEFAULTED = 1 +SE_GROUP_DEFAULTED = 2 +SE_DACL_PRESENT = 4 +SE_DACL_DEFAULTED = 8 +SE_SACL_PRESENT = 16 +SE_SACL_DEFAULTED = 32 +SE_SELF_RELATIVE = 32768 +SE_PRIVILEGE_ENABLED_BY_DEFAULT = 1 +SE_PRIVILEGE_ENABLED = 2 +SE_PRIVILEGE_USED_FOR_ACCESS = -2147483648 +PRIVILEGE_SET_ALL_NECESSARY = 1 +SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" +SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" +SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" +SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" +SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege" +SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" +SE_TCB_NAME = "SeTcbPrivilege" +SE_SECURITY_NAME = "SeSecurityPrivilege" +SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" +SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" +SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" +SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" +SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" +SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" +SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" +SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" +SE_BACKUP_NAME = "SeBackupPrivilege" +SE_RESTORE_NAME = "SeRestorePrivilege" +SE_SHUTDOWN_NAME = "SeShutdownPrivilege" +SE_DEBUG_NAME = "SeDebugPrivilege" +SE_AUDIT_NAME = "SeAuditPrivilege" +SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" +SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" +SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege" + +TOKEN_ASSIGN_PRIMARY = 1 +TOKEN_DUPLICATE = 2 +TOKEN_IMPERSONATE = 4 +TOKEN_QUERY = 8 +TOKEN_QUERY_SOURCE = 16 +TOKEN_ADJUST_PRIVILEGES = 32 +TOKEN_ADJUST_GROUPS = 64 +TOKEN_ADJUST_DEFAULT = 128 +TOKEN_ADJUST_SESSIONID = 256 +TOKEN_ALL_ACCESS = ( + STANDARD_RIGHTS_REQUIRED + | TOKEN_ASSIGN_PRIMARY + | TOKEN_DUPLICATE + | TOKEN_IMPERSONATE + | TOKEN_QUERY + | TOKEN_QUERY_SOURCE + | TOKEN_ADJUST_PRIVILEGES + | TOKEN_ADJUST_GROUPS + | TOKEN_ADJUST_DEFAULT + | TOKEN_ADJUST_SESSIONID +) +TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY +TOKEN_WRITE = ( + STANDARD_RIGHTS_WRITE + | TOKEN_ADJUST_PRIVILEGES + | TOKEN_ADJUST_GROUPS + | TOKEN_ADJUST_DEFAULT +) +TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE +TOKEN_SOURCE_LENGTH = 8 + +KEY_QUERY_VALUE = 1 +KEY_SET_VALUE = 2 +KEY_CREATE_SUB_KEY = 4 +KEY_ENUMERATE_SUB_KEYS = 8 +KEY_NOTIFY = 16 +KEY_CREATE_LINK = 32 +KEY_WOW64_32KEY = 512 +KEY_WOW64_64KEY = 256 +KEY_WOW64_RES = 768 +KEY_READ = ( + STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY +) & (~SYNCHRONIZE) +KEY_WRITE = (STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & ( + ~SYNCHRONIZE +) +KEY_EXECUTE = (KEY_READ) & (~SYNCHRONIZE) +KEY_ALL_ACCESS = ( + STANDARD_RIGHTS_ALL + | KEY_QUERY_VALUE + | KEY_SET_VALUE + | KEY_CREATE_SUB_KEY + | KEY_ENUMERATE_SUB_KEYS + | KEY_NOTIFY + | KEY_CREATE_LINK +) & (~SYNCHRONIZE) +REG_NOTIFY_CHANGE_ATTRIBUTES = 2 +REG_NOTIFY_CHANGE_SECURITY = 8 +REG_RESOURCE_REQUIREMENTS_LIST = 10 +REG_NONE = 0 # No value type +REG_SZ = 1 # Unicode nul terminated string +REG_EXPAND_SZ = 2 # Unicode nul terminated string +# (with environment variable references) +REG_BINARY = 3 # Free form binary +REG_DWORD = 4 # 32-bit number +REG_DWORD_LITTLE_ENDIAN = 4 # 32-bit number (same as REG_DWORD) +REG_DWORD_BIG_ENDIAN = 5 # 32-bit number +REG_LINK = 6 # Symbolic Link (unicode) +REG_MULTI_SZ = 7 # Multiple Unicode strings +REG_RESOURCE_LIST = 8 # Resource list in the resource map +REG_FULL_RESOURCE_DESCRIPTOR = 9 # Resource list in the hardware description +REG_RESOURCE_REQUIREMENTS_LIST = 10 +REG_QWORD = 11 # 64-bit number +REG_QWORD_LITTLE_ENDIAN = 11 # 64-bit number (same as REG_QWORD) + + +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +# Included from string.h +_NLSCMPERROR = 2147483647 +NULL = 0 +HEAP_NO_SERIALIZE = 1 +HEAP_GROWABLE = 2 +HEAP_GENERATE_EXCEPTIONS = 4 +HEAP_ZERO_MEMORY = 8 +HEAP_REALLOC_IN_PLACE_ONLY = 16 +HEAP_TAIL_CHECKING_ENABLED = 32 +HEAP_FREE_CHECKING_ENABLED = 64 +HEAP_DISABLE_COALESCE_ON_FREE = 128 +IS_TEXT_UNICODE_ASCII16 = 1 +IS_TEXT_UNICODE_REVERSE_ASCII16 = 16 +IS_TEXT_UNICODE_STATISTICS = 2 +IS_TEXT_UNICODE_REVERSE_STATISTICS = 32 +IS_TEXT_UNICODE_CONTROLS = 4 +IS_TEXT_UNICODE_REVERSE_CONTROLS = 64 +IS_TEXT_UNICODE_SIGNATURE = 8 +IS_TEXT_UNICODE_REVERSE_SIGNATURE = 128 +IS_TEXT_UNICODE_ILLEGAL_CHARS = 256 +IS_TEXT_UNICODE_ODD_LENGTH = 512 +IS_TEXT_UNICODE_DBCS_LEADBYTE = 1024 +IS_TEXT_UNICODE_NULL_BYTES = 4096 +IS_TEXT_UNICODE_UNICODE_MASK = 15 +IS_TEXT_UNICODE_REVERSE_MASK = 240 +IS_TEXT_UNICODE_NOT_UNICODE_MASK = 3840 +IS_TEXT_UNICODE_NOT_ASCII_MASK = 61440 +COMPRESSION_FORMAT_NONE = 0 +COMPRESSION_FORMAT_DEFAULT = 1 +COMPRESSION_FORMAT_LZNT1 = 2 +COMPRESSION_ENGINE_STANDARD = 0 +COMPRESSION_ENGINE_MAXIMUM = 256 +MESSAGE_RESOURCE_UNICODE = 1 +RTL_CRITSECT_TYPE = 0 +RTL_RESOURCE_TYPE = 1 +DLL_PROCESS_ATTACH = 1 +DLL_THREAD_ATTACH = 2 +DLL_THREAD_DETACH = 3 +DLL_PROCESS_DETACH = 0 +EVENTLOG_SEQUENTIAL_READ = 0x0001 +EVENTLOG_SEEK_READ = 0x0002 +EVENTLOG_FORWARDS_READ = 0x0004 +EVENTLOG_BACKWARDS_READ = 0x0008 +EVENTLOG_SUCCESS = 0x0000 +EVENTLOG_ERROR_TYPE = 1 +EVENTLOG_WARNING_TYPE = 2 +EVENTLOG_INFORMATION_TYPE = 4 +EVENTLOG_AUDIT_SUCCESS = 8 +EVENTLOG_AUDIT_FAILURE = 16 +EVENTLOG_START_PAIRED_EVENT = 1 +EVENTLOG_END_PAIRED_EVENT = 2 +EVENTLOG_END_ALL_PAIRED_EVENTS = 4 +EVENTLOG_PAIRED_EVENT_ACTIVE = 8 +EVENTLOG_PAIRED_EVENT_INACTIVE = 16 +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +OWNER_SECURITY_INFORMATION = 0x00000001 +GROUP_SECURITY_INFORMATION = 0x00000002 +DACL_SECURITY_INFORMATION = 0x00000004 +SACL_SECURITY_INFORMATION = 0x00000008 +IMAGE_SIZEOF_FILE_HEADER = 20 +IMAGE_FILE_MACHINE_UNKNOWN = 0 +IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 +IMAGE_SIZEOF_ROM_OPTIONAL_HEADER = 56 +IMAGE_SIZEOF_STD_OPTIONAL_HEADER = 28 +IMAGE_SIZEOF_NT_OPTIONAL_HEADER = 224 +IMAGE_NT_OPTIONAL_HDR_MAGIC = 267 +IMAGE_ROM_OPTIONAL_HDR_MAGIC = 263 +IMAGE_SIZEOF_SHORT_NAME = 8 +IMAGE_SIZEOF_SECTION_HEADER = 40 +IMAGE_SIZEOF_SYMBOL = 18 +IMAGE_SYM_CLASS_NULL = 0 +IMAGE_SYM_CLASS_AUTOMATIC = 1 +IMAGE_SYM_CLASS_EXTERNAL = 2 +IMAGE_SYM_CLASS_STATIC = 3 +IMAGE_SYM_CLASS_REGISTER = 4 +IMAGE_SYM_CLASS_EXTERNAL_DEF = 5 +IMAGE_SYM_CLASS_LABEL = 6 +IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7 +IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8 +IMAGE_SYM_CLASS_ARGUMENT = 9 +IMAGE_SYM_CLASS_STRUCT_TAG = 10 +IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11 +IMAGE_SYM_CLASS_UNION_TAG = 12 +IMAGE_SYM_CLASS_TYPE_DEFINITION = 13 +IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14 +IMAGE_SYM_CLASS_ENUM_TAG = 15 +IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16 +IMAGE_SYM_CLASS_REGISTER_PARAM = 17 +IMAGE_SYM_CLASS_BIT_FIELD = 18 +IMAGE_SYM_CLASS_BLOCK = 100 +IMAGE_SYM_CLASS_FUNCTION = 101 +IMAGE_SYM_CLASS_END_OF_STRUCT = 102 +IMAGE_SYM_CLASS_FILE = 103 +IMAGE_SYM_CLASS_SECTION = 104 +IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105 +N_BTMASK = 15 +N_TMASK = 48 +N_TMASK1 = 192 +N_TMASK2 = 240 +N_BTSHFT = 4 +N_TSHIFT = 2 +IMAGE_SIZEOF_AUX_SYMBOL = 18 +IMAGE_COMDAT_SELECT_NODUPLICATES = 1 +IMAGE_COMDAT_SELECT_ANY = 2 +IMAGE_COMDAT_SELECT_SAME_SIZE = 3 +IMAGE_COMDAT_SELECT_EXACT_MATCH = 4 +IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5 +IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1 +IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2 +IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 +IMAGE_SIZEOF_RELOCATION = 10 +IMAGE_REL_I386_SECTION = 10 +IMAGE_REL_I386_SECREL = 11 +IMAGE_REL_MIPS_REFHALF = 1 +IMAGE_REL_MIPS_REFWORD = 2 +IMAGE_REL_MIPS_JMPADDR = 3 +IMAGE_REL_MIPS_REFHI = 4 +IMAGE_REL_MIPS_REFLO = 5 +IMAGE_REL_MIPS_GPREL = 6 +IMAGE_REL_MIPS_LITERAL = 7 +IMAGE_REL_MIPS_SECTION = 10 +IMAGE_REL_MIPS_SECREL = 11 +IMAGE_REL_MIPS_REFWORDNB = 34 +IMAGE_REL_MIPS_PAIR = 37 +IMAGE_REL_ALPHA_ABSOLUTE = 0 +IMAGE_REL_ALPHA_REFLONG = 1 +IMAGE_REL_ALPHA_REFQUAD = 2 +IMAGE_REL_ALPHA_GPREL32 = 3 +IMAGE_REL_ALPHA_LITERAL = 4 +IMAGE_REL_ALPHA_LITUSE = 5 +IMAGE_REL_ALPHA_GPDISP = 6 +IMAGE_REL_ALPHA_BRADDR = 7 +IMAGE_REL_ALPHA_HINT = 8 +IMAGE_REL_ALPHA_INLINE_REFLONG = 9 +IMAGE_REL_ALPHA_REFHI = 10 +IMAGE_REL_ALPHA_REFLO = 11 +IMAGE_REL_ALPHA_PAIR = 12 +IMAGE_REL_ALPHA_MATCH = 13 +IMAGE_REL_ALPHA_SECTION = 14 +IMAGE_REL_ALPHA_SECREL = 15 +IMAGE_REL_ALPHA_REFLONGNB = 16 +IMAGE_SIZEOF_BASE_RELOCATION = 8 +IMAGE_REL_BASED_ABSOLUTE = 0 +IMAGE_REL_BASED_HIGH = 1 +IMAGE_REL_BASED_LOW = 2 +IMAGE_REL_BASED_HIGHLOW = 3 +IMAGE_REL_BASED_HIGHADJ = 4 +IMAGE_REL_BASED_MIPS_JMPADDR = 5 +IMAGE_SIZEOF_LINENUMBER = 6 +IMAGE_ARCHIVE_START_SIZE = 8 +IMAGE_ARCHIVE_START = "!\n" +IMAGE_ARCHIVE_END = "`\n" +IMAGE_ARCHIVE_PAD = "\n" +IMAGE_ARCHIVE_LINKER_MEMBER = "/ " +IMAGE_ARCHIVE_LONGNAMES_MEMBER = "// " +IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR = 60 +IMAGE_ORDINAL_FLAG = -2147483648 + + +def IMAGE_SNAP_BY_ORDINAL(Ordinal): + return (Ordinal & IMAGE_ORDINAL_FLAG) != 0 + + +def IMAGE_ORDINAL(Ordinal): + return Ordinal & 65535 + + +IMAGE_RESOURCE_NAME_IS_STRING = -2147483648 +IMAGE_RESOURCE_DATA_IS_DIRECTORY = -2147483648 +IMAGE_DEBUG_TYPE_UNKNOWN = 0 +IMAGE_DEBUG_TYPE_COFF = 1 +IMAGE_DEBUG_TYPE_CODEVIEW = 2 +IMAGE_DEBUG_TYPE_FPO = 3 +IMAGE_DEBUG_TYPE_MISC = 4 +IMAGE_DEBUG_TYPE_EXCEPTION = 5 +IMAGE_DEBUG_TYPE_FIXUP = 6 +IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7 +IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8 +FRAME_FPO = 0 +FRAME_TRAP = 1 +FRAME_TSS = 2 +SIZEOF_RFPO_DATA = 16 +IMAGE_DEBUG_MISC_EXENAME = 1 +IMAGE_SEPARATE_DEBUG_SIGNATURE = 18756 +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +NEWFRAME = 1 +ABORTDOC = 2 +NEXTBAND = 3 +SETCOLORTABLE = 4 +GETCOLORTABLE = 5 +FLUSHOUTPUT = 6 +DRAFTMODE = 7 +QUERYESCSUPPORT = 8 +SETABORTPROC = 9 +STARTDOC = 10 +ENDDOC = 11 +GETPHYSPAGESIZE = 12 +GETPRINTINGOFFSET = 13 +GETSCALINGFACTOR = 14 +MFCOMMENT = 15 +GETPENWIDTH = 16 +SETCOPYCOUNT = 17 +SELECTPAPERSOURCE = 18 +DEVICEDATA = 19 +PASSTHROUGH = 19 +GETTECHNOLGY = 20 +GETTECHNOLOGY = 20 +SETLINECAP = 21 +SETLINEJOIN = 22 +SETMITERLIMIT = 23 +BANDINFO = 24 +DRAWPATTERNRECT = 25 +GETVECTORPENSIZE = 26 +GETVECTORBRUSHSIZE = 27 +ENABLEDUPLEX = 28 +GETSETPAPERBINS = 29 +GETSETPRINTORIENT = 30 +ENUMPAPERBINS = 31 +SETDIBSCALING = 32 +EPSPRINTING = 33 +ENUMPAPERMETRICS = 34 +GETSETPAPERMETRICS = 35 +POSTSCRIPT_DATA = 37 +POSTSCRIPT_IGNORE = 38 +MOUSETRAILS = 39 +GETDEVICEUNITS = 42 +GETEXTENDEDTEXTMETRICS = 256 +GETEXTENTTABLE = 257 +GETPAIRKERNTABLE = 258 +GETTRACKKERNTABLE = 259 +EXTTEXTOUT = 512 +GETFACENAME = 513 +DOWNLOADFACE = 514 +ENABLERELATIVEWIDTHS = 768 +ENABLEPAIRKERNING = 769 +SETKERNTRACK = 770 +SETALLJUSTVALUES = 771 +SETCHARSET = 772 +STRETCHBLT = 2048 +GETSETSCREENPARAMS = 3072 +BEGIN_PATH = 4096 +CLIP_TO_PATH = 4097 +END_PATH = 4098 +EXT_DEVICE_CAPS = 4099 +RESTORE_CTM = 4100 +SAVE_CTM = 4101 +SET_ARC_DIRECTION = 4102 +SET_BACKGROUND_COLOR = 4103 +SET_POLY_MODE = 4104 +SET_SCREEN_ANGLE = 4105 +SET_SPREAD = 4106 +TRANSFORM_CTM = 4107 +SET_CLIP_BOX = 4108 +SET_BOUNDS = 4109 +SET_MIRROR_MODE = 4110 +OPENCHANNEL = 4110 +DOWNLOADHEADER = 4111 +CLOSECHANNEL = 4112 +POSTSCRIPT_PASSTHROUGH = 4115 +ENCAPSULATED_POSTSCRIPT = 4116 +SP_NOTREPORTED = 16384 +SP_ERROR = -1 +SP_APPABORT = -2 +SP_USERABORT = -3 +SP_OUTOFDISK = -4 +SP_OUTOFMEMORY = -5 +PR_JOBSTATUS = 0 + +## GDI object types +OBJ_PEN = 1 +OBJ_BRUSH = 2 +OBJ_DC = 3 +OBJ_METADC = 4 +OBJ_PAL = 5 +OBJ_FONT = 6 +OBJ_BITMAP = 7 +OBJ_REGION = 8 +OBJ_METAFILE = 9 +OBJ_MEMDC = 10 +OBJ_EXTPEN = 11 +OBJ_ENHMETADC = 12 +OBJ_ENHMETAFILE = 13 +OBJ_COLORSPACE = 14 + +MWT_IDENTITY = 1 +MWT_LEFTMULTIPLY = 2 +MWT_RIGHTMULTIPLY = 3 +MWT_MIN = MWT_IDENTITY +MWT_MAX = MWT_RIGHTMULTIPLY +BI_RGB = 0 +BI_RLE8 = 1 +BI_RLE4 = 2 +BI_BITFIELDS = 3 +TMPF_FIXED_PITCH = 1 +TMPF_VECTOR = 2 +TMPF_DEVICE = 8 +TMPF_TRUETYPE = 4 +NTM_REGULAR = 64 +NTM_BOLD = 32 +NTM_ITALIC = 1 +LF_FACESIZE = 32 +LF_FULLFACESIZE = 64 +OUT_DEFAULT_PRECIS = 0 +OUT_STRING_PRECIS = 1 +OUT_CHARACTER_PRECIS = 2 +OUT_STROKE_PRECIS = 3 +OUT_TT_PRECIS = 4 +OUT_DEVICE_PRECIS = 5 +OUT_RASTER_PRECIS = 6 +OUT_TT_ONLY_PRECIS = 7 +OUT_OUTLINE_PRECIS = 8 +CLIP_DEFAULT_PRECIS = 0 +CLIP_CHARACTER_PRECIS = 1 +CLIP_STROKE_PRECIS = 2 +CLIP_MASK = 15 +CLIP_LH_ANGLES = 1 << 4 +CLIP_TT_ALWAYS = 2 << 4 +CLIP_EMBEDDED = 8 << 4 +DEFAULT_QUALITY = 0 +DRAFT_QUALITY = 1 +PROOF_QUALITY = 2 +NONANTIALIASED_QUALITY = 3 +ANTIALIASED_QUALITY = 4 +CLEARTYPE_QUALITY = 5 +CLEARTYPE_NATURAL_QUALITY = 6 +DEFAULT_PITCH = 0 +FIXED_PITCH = 1 +VARIABLE_PITCH = 2 +ANSI_CHARSET = 0 +DEFAULT_CHARSET = 1 +SYMBOL_CHARSET = 2 +SHIFTJIS_CHARSET = 128 +HANGEUL_CHARSET = 129 +CHINESEBIG5_CHARSET = 136 +OEM_CHARSET = 255 +JOHAB_CHARSET = 130 +HEBREW_CHARSET = 177 +ARABIC_CHARSET = 178 +GREEK_CHARSET = 161 +TURKISH_CHARSET = 162 +VIETNAMESE_CHARSET = 163 +THAI_CHARSET = 222 +EASTEUROPE_CHARSET = 238 +RUSSIAN_CHARSET = 204 +MAC_CHARSET = 77 +BALTIC_CHARSET = 186 +FF_DONTCARE = 0 << 4 +FF_ROMAN = 1 << 4 +FF_SWISS = 2 << 4 +FF_MODERN = 3 << 4 +FF_SCRIPT = 4 << 4 +FF_DECORATIVE = 5 << 4 +FW_DONTCARE = 0 +FW_THIN = 100 +FW_EXTRALIGHT = 200 +FW_LIGHT = 300 +FW_NORMAL = 400 +FW_MEDIUM = 500 +FW_SEMIBOLD = 600 +FW_BOLD = 700 +FW_EXTRABOLD = 800 +FW_HEAVY = 900 +FW_ULTRALIGHT = FW_EXTRALIGHT +FW_REGULAR = FW_NORMAL +FW_DEMIBOLD = FW_SEMIBOLD +FW_ULTRABOLD = FW_EXTRABOLD +FW_BLACK = FW_HEAVY +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +BS_SOLID = 0 +BS_NULL = 1 +BS_HOLLOW = BS_NULL +BS_HATCHED = 2 +BS_PATTERN = 3 +BS_INDEXED = 4 +BS_DIBPATTERN = 5 +BS_DIBPATTERNPT = 6 +BS_PATTERN8X8 = 7 +BS_DIBPATTERN8X8 = 8 +HS_HORIZONTAL = 0 +HS_VERTICAL = 1 +HS_FDIAGONAL = 2 +HS_BDIAGONAL = 3 +HS_CROSS = 4 +HS_DIAGCROSS = 5 +HS_FDIAGONAL1 = 6 +HS_BDIAGONAL1 = 7 +HS_SOLID = 8 +HS_DENSE1 = 9 +HS_DENSE2 = 10 +HS_DENSE3 = 11 +HS_DENSE4 = 12 +HS_DENSE5 = 13 +HS_DENSE6 = 14 +HS_DENSE7 = 15 +HS_DENSE8 = 16 +HS_NOSHADE = 17 +HS_HALFTONE = 18 +HS_SOLIDCLR = 19 +HS_DITHEREDCLR = 20 +HS_SOLIDTEXTCLR = 21 +HS_DITHEREDTEXTCLR = 22 +HS_SOLIDBKCLR = 23 +HS_DITHEREDBKCLR = 24 +HS_API_MAX = 25 +PS_SOLID = 0 +PS_DASH = 1 +PS_DOT = 2 +PS_DASHDOT = 3 +PS_DASHDOTDOT = 4 +PS_NULL = 5 +PS_INSIDEFRAME = 6 +PS_USERSTYLE = 7 +PS_ALTERNATE = 8 +PS_STYLE_MASK = 15 +PS_ENDCAP_ROUND = 0 +PS_ENDCAP_SQUARE = 256 +PS_ENDCAP_FLAT = 512 +PS_ENDCAP_MASK = 3840 +PS_JOIN_ROUND = 0 +PS_JOIN_BEVEL = 4096 +PS_JOIN_MITER = 8192 +PS_JOIN_MASK = 61440 +PS_COSMETIC = 0 +PS_GEOMETRIC = 65536 +PS_TYPE_MASK = 983040 +AD_COUNTERCLOCKWISE = 1 +AD_CLOCKWISE = 2 +DRIVERVERSION = 0 +TECHNOLOGY = 2 +HORZSIZE = 4 +VERTSIZE = 6 +HORZRES = 8 +VERTRES = 10 +BITSPIXEL = 12 +PLANES = 14 +NUMBRUSHES = 16 +NUMPENS = 18 +NUMMARKERS = 20 +NUMFONTS = 22 +NUMCOLORS = 24 +PDEVICESIZE = 26 +CURVECAPS = 28 +LINECAPS = 30 +POLYGONALCAPS = 32 +TEXTCAPS = 34 +CLIPCAPS = 36 +RASTERCAPS = 38 +ASPECTX = 40 +ASPECTY = 42 +ASPECTXY = 44 +LOGPIXELSX = 88 +LOGPIXELSY = 90 +SIZEPALETTE = 104 +NUMRESERVED = 106 +COLORRES = 108 + +PHYSICALWIDTH = 110 +PHYSICALHEIGHT = 111 +PHYSICALOFFSETX = 112 +PHYSICALOFFSETY = 113 +SCALINGFACTORX = 114 +SCALINGFACTORY = 115 +VREFRESH = 116 +DESKTOPVERTRES = 117 +DESKTOPHORZRES = 118 +BLTALIGNMENT = 119 +SHADEBLENDCAPS = 120 +COLORMGMTCAPS = 121 + +DT_PLOTTER = 0 +DT_RASDISPLAY = 1 +DT_RASPRINTER = 2 +DT_RASCAMERA = 3 +DT_CHARSTREAM = 4 +DT_METAFILE = 5 +DT_DISPFILE = 6 +CC_NONE = 0 +CC_CIRCLES = 1 +CC_PIE = 2 +CC_CHORD = 4 +CC_ELLIPSES = 8 +CC_WIDE = 16 +CC_STYLED = 32 +CC_WIDESTYLED = 64 +CC_INTERIORS = 128 +CC_ROUNDRECT = 256 +LC_NONE = 0 +LC_POLYLINE = 2 +LC_MARKER = 4 +LC_POLYMARKER = 8 +LC_WIDE = 16 +LC_STYLED = 32 +LC_WIDESTYLED = 64 +LC_INTERIORS = 128 +PC_NONE = 0 +PC_POLYGON = 1 +PC_RECTANGLE = 2 +PC_WINDPOLYGON = 4 +PC_TRAPEZOID = 4 +PC_SCANLINE = 8 +PC_WIDE = 16 +PC_STYLED = 32 +PC_WIDESTYLED = 64 +PC_INTERIORS = 128 +CP_NONE = 0 +CP_RECTANGLE = 1 +CP_REGION = 2 +TC_OP_CHARACTER = 1 +TC_OP_STROKE = 2 +TC_CP_STROKE = 4 +TC_CR_90 = 8 +TC_CR_ANY = 16 +TC_SF_X_YINDEP = 32 +TC_SA_DOUBLE = 64 +TC_SA_INTEGER = 128 +TC_SA_CONTIN = 256 +TC_EA_DOUBLE = 512 +TC_IA_ABLE = 1024 +TC_UA_ABLE = 2048 +TC_SO_ABLE = 4096 +TC_RA_ABLE = 8192 +TC_VA_ABLE = 16384 +TC_RESERVED = 32768 +TC_SCROLLBLT = 65536 +RC_BITBLT = 1 +RC_BANDING = 2 +RC_SCALING = 4 +RC_BITMAP64 = 8 +RC_GDI20_OUTPUT = 16 +RC_GDI20_STATE = 32 +RC_SAVEBITMAP = 64 +RC_DI_BITMAP = 128 +RC_PALETTE = 256 +RC_DIBTODEV = 512 +RC_BIGFONT = 1024 +RC_STRETCHBLT = 2048 +RC_FLOODFILL = 4096 +RC_STRETCHDIB = 8192 +RC_OP_DX_OUTPUT = 16384 +RC_DEVBITS = 32768 +DIB_RGB_COLORS = 0 +DIB_PAL_COLORS = 1 +DIB_PAL_INDICES = 2 +DIB_PAL_PHYSINDICES = 2 +DIB_PAL_LOGINDICES = 4 +SYSPAL_ERROR = 0 +SYSPAL_STATIC = 1 +SYSPAL_NOSTATIC = 2 +CBM_CREATEDIB = 2 +CBM_INIT = 4 +FLOODFILLBORDER = 0 +FLOODFILLSURFACE = 1 +CCHDEVICENAME = 32 +CCHFORMNAME = 32 +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. + +# DEVMODE.dmFields +DM_SPECVERSION = 800 +DM_ORIENTATION = 1 +DM_PAPERSIZE = 2 +DM_PAPERLENGTH = 4 +DM_PAPERWIDTH = 8 +DM_SCALE = 16 +DM_POSITION = 32 +DM_NUP = 64 +DM_DISPLAYORIENTATION = 128 +DM_COPIES = 256 +DM_DEFAULTSOURCE = 512 +DM_PRINTQUALITY = 1024 +DM_COLOR = 2048 +DM_DUPLEX = 4096 +DM_YRESOLUTION = 8192 +DM_TTOPTION = 16384 +DM_COLLATE = 32768 +DM_FORMNAME = 65536 +DM_LOGPIXELS = 131072 +DM_BITSPERPEL = 262144 +DM_PELSWIDTH = 524288 +DM_PELSHEIGHT = 1048576 +DM_DISPLAYFLAGS = 2097152 +DM_DISPLAYFREQUENCY = 4194304 +DM_ICMMETHOD = 8388608 +DM_ICMINTENT = 16777216 +DM_MEDIATYPE = 33554432 +DM_DITHERTYPE = 67108864 +DM_PANNINGWIDTH = 134217728 +DM_PANNINGHEIGHT = 268435456 +DM_DISPLAYFIXEDOUTPUT = 536870912 + +# DEVMODE.dmOrientation +DMORIENT_PORTRAIT = 1 +DMORIENT_LANDSCAPE = 2 + +# DEVMODE.dmDisplayOrientation +DMDO_DEFAULT = 0 +DMDO_90 = 1 +DMDO_180 = 2 +DMDO_270 = 3 + +# DEVMODE.dmDisplayFixedOutput +DMDFO_DEFAULT = 0 +DMDFO_STRETCH = 1 +DMDFO_CENTER = 2 + +# DEVMODE.dmPaperSize +DMPAPER_LETTER = 1 +DMPAPER_LETTERSMALL = 2 +DMPAPER_TABLOID = 3 +DMPAPER_LEDGER = 4 +DMPAPER_LEGAL = 5 +DMPAPER_STATEMENT = 6 +DMPAPER_EXECUTIVE = 7 +DMPAPER_A3 = 8 +DMPAPER_A4 = 9 +DMPAPER_A4SMALL = 10 +DMPAPER_A5 = 11 +DMPAPER_B4 = 12 +DMPAPER_B5 = 13 +DMPAPER_FOLIO = 14 +DMPAPER_QUARTO = 15 +DMPAPER_10X14 = 16 +DMPAPER_11X17 = 17 +DMPAPER_NOTE = 18 +DMPAPER_ENV_9 = 19 +DMPAPER_ENV_10 = 20 +DMPAPER_ENV_11 = 21 +DMPAPER_ENV_12 = 22 +DMPAPER_ENV_14 = 23 +DMPAPER_CSHEET = 24 +DMPAPER_DSHEET = 25 +DMPAPER_ESHEET = 26 +DMPAPER_ENV_DL = 27 +DMPAPER_ENV_C5 = 28 +DMPAPER_ENV_C3 = 29 +DMPAPER_ENV_C4 = 30 +DMPAPER_ENV_C6 = 31 +DMPAPER_ENV_C65 = 32 +DMPAPER_ENV_B4 = 33 +DMPAPER_ENV_B5 = 34 +DMPAPER_ENV_B6 = 35 +DMPAPER_ENV_ITALY = 36 +DMPAPER_ENV_MONARCH = 37 +DMPAPER_ENV_PERSONAL = 38 +DMPAPER_FANFOLD_US = 39 +DMPAPER_FANFOLD_STD_GERMAN = 40 +DMPAPER_FANFOLD_LGL_GERMAN = 41 +DMPAPER_ISO_B4 = 42 +DMPAPER_JAPANESE_POSTCARD = 43 +DMPAPER_9X11 = 44 +DMPAPER_10X11 = 45 +DMPAPER_15X11 = 46 +DMPAPER_ENV_INVITE = 47 +DMPAPER_RESERVED_48 = 48 +DMPAPER_RESERVED_49 = 49 +DMPAPER_LETTER_EXTRA = 50 +DMPAPER_LEGAL_EXTRA = 51 +DMPAPER_TABLOID_EXTRA = 52 +DMPAPER_A4_EXTRA = 53 +DMPAPER_LETTER_TRANSVERSE = 54 +DMPAPER_A4_TRANSVERSE = 55 +DMPAPER_LETTER_EXTRA_TRANSVERSE = 56 +DMPAPER_A_PLUS = 57 +DMPAPER_B_PLUS = 58 +DMPAPER_LETTER_PLUS = 59 +DMPAPER_A4_PLUS = 60 +DMPAPER_A5_TRANSVERSE = 61 +DMPAPER_B5_TRANSVERSE = 62 +DMPAPER_A3_EXTRA = 63 +DMPAPER_A5_EXTRA = 64 +DMPAPER_B5_EXTRA = 65 +DMPAPER_A2 = 66 +DMPAPER_A3_TRANSVERSE = 67 +DMPAPER_A3_EXTRA_TRANSVERSE = 68 +DMPAPER_DBL_JAPANESE_POSTCARD = 69 +DMPAPER_A6 = 70 +DMPAPER_JENV_KAKU2 = 71 +DMPAPER_JENV_KAKU3 = 72 +DMPAPER_JENV_CHOU3 = 73 +DMPAPER_JENV_CHOU4 = 74 +DMPAPER_LETTER_ROTATED = 75 +DMPAPER_A3_ROTATED = 76 +DMPAPER_A4_ROTATED = 77 +DMPAPER_A5_ROTATED = 78 +DMPAPER_B4_JIS_ROTATED = 79 +DMPAPER_B5_JIS_ROTATED = 80 +DMPAPER_JAPANESE_POSTCARD_ROTATED = 81 +DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED = 82 +DMPAPER_A6_ROTATED = 83 +DMPAPER_JENV_KAKU2_ROTATED = 84 +DMPAPER_JENV_KAKU3_ROTATED = 85 +DMPAPER_JENV_CHOU3_ROTATED = 86 +DMPAPER_JENV_CHOU4_ROTATED = 87 +DMPAPER_B6_JIS = 88 +DMPAPER_B6_JIS_ROTATED = 89 +DMPAPER_12X11 = 90 +DMPAPER_JENV_YOU4 = 91 +DMPAPER_JENV_YOU4_ROTATED = 92 +DMPAPER_P16K = 93 +DMPAPER_P32K = 94 +DMPAPER_P32KBIG = 95 +DMPAPER_PENV_1 = 96 +DMPAPER_PENV_2 = 97 +DMPAPER_PENV_3 = 98 +DMPAPER_PENV_4 = 99 +DMPAPER_PENV_5 = 100 +DMPAPER_PENV_6 = 101 +DMPAPER_PENV_7 = 102 +DMPAPER_PENV_8 = 103 +DMPAPER_PENV_9 = 104 +DMPAPER_PENV_10 = 105 +DMPAPER_P16K_ROTATED = 106 +DMPAPER_P32K_ROTATED = 107 +DMPAPER_P32KBIG_ROTATED = 108 +DMPAPER_PENV_1_ROTATED = 109 +DMPAPER_PENV_2_ROTATED = 110 +DMPAPER_PENV_3_ROTATED = 111 +DMPAPER_PENV_4_ROTATED = 112 +DMPAPER_PENV_5_ROTATED = 113 +DMPAPER_PENV_6_ROTATED = 114 +DMPAPER_PENV_7_ROTATED = 115 +DMPAPER_PENV_8_ROTATED = 116 +DMPAPER_PENV_9_ROTATED = 117 +DMPAPER_PENV_10_ROTATED = 118 +DMPAPER_LAST = DMPAPER_PENV_10_ROTATED +DMPAPER_USER = 256 + +# DEVMODE.dmDefaultSource +DMBIN_UPPER = 1 +DMBIN_ONLYONE = 1 +DMBIN_LOWER = 2 +DMBIN_MIDDLE = 3 +DMBIN_MANUAL = 4 +DMBIN_ENVELOPE = 5 +DMBIN_ENVMANUAL = 6 +DMBIN_AUTO = 7 +DMBIN_TRACTOR = 8 +DMBIN_SMALLFMT = 9 +DMBIN_LARGEFMT = 10 +DMBIN_LARGECAPACITY = 11 +DMBIN_CASSETTE = 14 +DMBIN_FORMSOURCE = 15 +DMBIN_LAST = DMBIN_FORMSOURCE +DMBIN_USER = 256 + +# DEVMODE.dmPrintQuality +DMRES_DRAFT = -1 +DMRES_LOW = -2 +DMRES_MEDIUM = -3 +DMRES_HIGH = -4 + +# DEVMODE.dmColor +DMCOLOR_MONOCHROME = 1 +DMCOLOR_COLOR = 2 + +# DEVMODE.dmDuplex +DMDUP_SIMPLEX = 1 +DMDUP_VERTICAL = 2 +DMDUP_HORIZONTAL = 3 + +# DEVMODE.dmTTOption +DMTT_BITMAP = 1 +DMTT_DOWNLOAD = 2 +DMTT_SUBDEV = 3 +DMTT_DOWNLOAD_OUTLINE = 4 + +# DEVMODE.dmCollate +DMCOLLATE_FALSE = 0 +DMCOLLATE_TRUE = 1 + +# DEVMODE.dmDisplayFlags +DM_GRAYSCALE = 1 +DM_INTERLACED = 2 + +# DEVMODE.dmICMMethod +DMICMMETHOD_NONE = 1 +DMICMMETHOD_SYSTEM = 2 +DMICMMETHOD_DRIVER = 3 +DMICMMETHOD_DEVICE = 4 +DMICMMETHOD_USER = 256 + +# DEVMODE.dmICMIntent +DMICM_SATURATE = 1 +DMICM_CONTRAST = 2 +DMICM_COLORIMETRIC = 3 +DMICM_ABS_COLORIMETRIC = 4 +DMICM_USER = 256 + +# DEVMODE.dmMediaType +DMMEDIA_STANDARD = 1 +DMMEDIA_TRANSPARENCY = 2 +DMMEDIA_GLOSSY = 3 +DMMEDIA_USER = 256 + +# DEVMODE.dmDitherType +DMDITHER_NONE = 1 +DMDITHER_COARSE = 2 +DMDITHER_FINE = 3 +DMDITHER_LINEART = 4 +DMDITHER_ERRORDIFFUSION = 5 +DMDITHER_RESERVED6 = 6 +DMDITHER_RESERVED7 = 7 +DMDITHER_RESERVED8 = 8 +DMDITHER_RESERVED9 = 9 +DMDITHER_GRAYSCALE = 10 +DMDITHER_USER = 256 + +# DEVMODE.dmNup +DMNUP_SYSTEM = 1 +DMNUP_ONEUP = 2 + +# used with ExtEscape +FEATURESETTING_NUP = 0 +FEATURESETTING_OUTPUT = 1 +FEATURESETTING_PSLEVEL = 2 +FEATURESETTING_CUSTPAPER = 3 +FEATURESETTING_MIRROR = 4 +FEATURESETTING_NEGATIVE = 5 +FEATURESETTING_PROTOCOL = 6 +FEATURESETTING_PRIVATE_BEGIN = 0x1000 +FEATURESETTING_PRIVATE_END = 0x1FFF + +RDH_RECTANGLES = 1 +GGO_METRICS = 0 +GGO_BITMAP = 1 +GGO_NATIVE = 2 +TT_POLYGON_TYPE = 24 +TT_PRIM_LINE = 1 +TT_PRIM_QSPLINE = 2 +TT_AVAILABLE = 1 +TT_ENABLED = 2 +DM_UPDATE = 1 +DM_COPY = 2 +DM_PROMPT = 4 +DM_MODIFY = 8 +DM_IN_BUFFER = DM_MODIFY +DM_IN_PROMPT = DM_PROMPT +DM_OUT_BUFFER = DM_COPY +DM_OUT_DEFAULT = DM_UPDATE + +# DISPLAY_DEVICE.StateFlags +DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = 1 +DISPLAY_DEVICE_MULTI_DRIVER = 2 +DISPLAY_DEVICE_PRIMARY_DEVICE = 4 +DISPLAY_DEVICE_MIRRORING_DRIVER = 8 +DISPLAY_DEVICE_VGA_COMPATIBLE = 16 +DISPLAY_DEVICE_REMOVABLE = 32 +DISPLAY_DEVICE_MODESPRUNED = 134217728 +DISPLAY_DEVICE_REMOTE = 67108864 +DISPLAY_DEVICE_DISCONNECT = 33554432 + +# DeviceCapabilities types +DC_FIELDS = 1 +DC_PAPERS = 2 +DC_PAPERSIZE = 3 +DC_MINEXTENT = 4 +DC_MAXEXTENT = 5 +DC_BINS = 6 +DC_DUPLEX = 7 +DC_SIZE = 8 +DC_EXTRA = 9 +DC_VERSION = 10 +DC_DRIVER = 11 +DC_BINNAMES = 12 +DC_ENUMRESOLUTIONS = 13 +DC_FILEDEPENDENCIES = 14 +DC_TRUETYPE = 15 +DC_PAPERNAMES = 16 +DC_ORIENTATION = 17 +DC_COPIES = 18 +DC_BINADJUST = 19 +DC_EMF_COMPLIANT = 20 +DC_DATATYPE_PRODUCED = 21 +DC_COLLATE = 22 +DC_MANUFACTURER = 23 +DC_MODEL = 24 +DC_PERSONALITY = 25 +DC_PRINTRATE = 26 +DC_PRINTRATEUNIT = 27 +DC_PRINTERMEM = 28 +DC_MEDIAREADY = 29 +DC_STAPLE = 30 +DC_PRINTRATEPPM = 31 +DC_COLORDEVICE = 32 +DC_NUP = 33 +DC_MEDIATYPENAMES = 34 +DC_MEDIATYPES = 35 + +PRINTRATEUNIT_PPM = 1 +PRINTRATEUNIT_CPS = 2 +PRINTRATEUNIT_LPM = 3 +PRINTRATEUNIT_IPM = 4 + +# TrueType constants +DCTT_BITMAP = 1 +DCTT_DOWNLOAD = 2 +DCTT_SUBDEV = 4 +DCTT_DOWNLOAD_OUTLINE = 8 + +DCBA_FACEUPNONE = 0 +DCBA_FACEUPCENTER = 1 +DCBA_FACEUPLEFT = 2 +DCBA_FACEUPRIGHT = 3 +DCBA_FACEDOWNNONE = 256 +DCBA_FACEDOWNCENTER = 257 +DCBA_FACEDOWNLEFT = 258 +DCBA_FACEDOWNRIGHT = 259 + +CA_NEGATIVE = 1 +CA_LOG_FILTER = 2 +ILLUMINANT_DEVICE_DEFAULT = 0 +ILLUMINANT_A = 1 +ILLUMINANT_B = 2 +ILLUMINANT_C = 3 +ILLUMINANT_D50 = 4 +ILLUMINANT_D55 = 5 +ILLUMINANT_D65 = 6 +ILLUMINANT_D75 = 7 +ILLUMINANT_F2 = 8 +ILLUMINANT_MAX_INDEX = ILLUMINANT_F2 +ILLUMINANT_TUNGSTEN = ILLUMINANT_A +ILLUMINANT_DAYLIGHT = ILLUMINANT_C +ILLUMINANT_FLUORESCENT = ILLUMINANT_F2 +ILLUMINANT_NTSC = ILLUMINANT_C + +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +FONTMAPPER_MAX = 10 +ENHMETA_SIGNATURE = 1179469088 +ENHMETA_STOCK_OBJECT = -2147483648 +EMR_HEADER = 1 +EMR_POLYBEZIER = 2 +EMR_POLYGON = 3 +EMR_POLYLINE = 4 +EMR_POLYBEZIERTO = 5 +EMR_POLYLINETO = 6 +EMR_POLYPOLYLINE = 7 +EMR_POLYPOLYGON = 8 +EMR_SETWINDOWEXTEX = 9 +EMR_SETWINDOWORGEX = 10 +EMR_SETVIEWPORTEXTEX = 11 +EMR_SETVIEWPORTORGEX = 12 +EMR_SETBRUSHORGEX = 13 +EMR_EOF = 14 +EMR_SETPIXELV = 15 +EMR_SETMAPPERFLAGS = 16 +EMR_SETMAPMODE = 17 +EMR_SETBKMODE = 18 +EMR_SETPOLYFILLMODE = 19 +EMR_SETROP2 = 20 +EMR_SETSTRETCHBLTMODE = 21 +EMR_SETTEXTALIGN = 22 +EMR_SETCOLORADJUSTMENT = 23 +EMR_SETTEXTCOLOR = 24 +EMR_SETBKCOLOR = 25 +EMR_OFFSETCLIPRGN = 26 +EMR_MOVETOEX = 27 +EMR_SETMETARGN = 28 +EMR_EXCLUDECLIPRECT = 29 +EMR_INTERSECTCLIPRECT = 30 +EMR_SCALEVIEWPORTEXTEX = 31 +EMR_SCALEWINDOWEXTEX = 32 +EMR_SAVEDC = 33 +EMR_RESTOREDC = 34 +EMR_SETWORLDTRANSFORM = 35 +EMR_MODIFYWORLDTRANSFORM = 36 +EMR_SELECTOBJECT = 37 +EMR_CREATEPEN = 38 +EMR_CREATEBRUSHINDIRECT = 39 +EMR_DELETEOBJECT = 40 +EMR_ANGLEARC = 41 +EMR_ELLIPSE = 42 +EMR_RECTANGLE = 43 +EMR_ROUNDRECT = 44 +EMR_ARC = 45 +EMR_CHORD = 46 +EMR_PIE = 47 +EMR_SELECTPALETTE = 48 +EMR_CREATEPALETTE = 49 +EMR_SETPALETTEENTRIES = 50 +EMR_RESIZEPALETTE = 51 +EMR_REALIZEPALETTE = 52 +EMR_EXTFLOODFILL = 53 +EMR_LINETO = 54 +EMR_ARCTO = 55 +EMR_POLYDRAW = 56 +EMR_SETARCDIRECTION = 57 +EMR_SETMITERLIMIT = 58 +EMR_BEGINPATH = 59 +EMR_ENDPATH = 60 +EMR_CLOSEFIGURE = 61 +EMR_FILLPATH = 62 +EMR_STROKEANDFILLPATH = 63 +EMR_STROKEPATH = 64 +EMR_FLATTENPATH = 65 +EMR_WIDENPATH = 66 +EMR_SELECTCLIPPATH = 67 +EMR_ABORTPATH = 68 +EMR_GDICOMMENT = 70 +EMR_FILLRGN = 71 +EMR_FRAMERGN = 72 +EMR_INVERTRGN = 73 +EMR_PAINTRGN = 74 +EMR_EXTSELECTCLIPRGN = 75 +EMR_BITBLT = 76 +EMR_STRETCHBLT = 77 +EMR_MASKBLT = 78 +EMR_PLGBLT = 79 +EMR_SETDIBITSTODEVICE = 80 +EMR_STRETCHDIBITS = 81 +EMR_EXTCREATEFONTINDIRECTW = 82 +EMR_EXTTEXTOUTA = 83 +EMR_EXTTEXTOUTW = 84 +EMR_POLYBEZIER16 = 85 +EMR_POLYGON16 = 86 +EMR_POLYLINE16 = 87 +EMR_POLYBEZIERTO16 = 88 +EMR_POLYLINETO16 = 89 +EMR_POLYPOLYLINE16 = 90 +EMR_POLYPOLYGON16 = 91 +EMR_POLYDRAW16 = 92 +EMR_CREATEMONOBRUSH = 93 +EMR_CREATEDIBPATTERNBRUSHPT = 94 +EMR_EXTCREATEPEN = 95 +EMR_POLYTEXTOUTA = 96 +EMR_POLYTEXTOUTW = 97 +EMR_MIN = 1 +EMR_MAX = 97 +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +PANOSE_COUNT = 10 +PAN_FAMILYTYPE_INDEX = 0 +PAN_SERIFSTYLE_INDEX = 1 +PAN_WEIGHT_INDEX = 2 +PAN_PROPORTION_INDEX = 3 +PAN_CONTRAST_INDEX = 4 +PAN_STROKEVARIATION_INDEX = 5 +PAN_ARMSTYLE_INDEX = 6 +PAN_LETTERFORM_INDEX = 7 +PAN_MIDLINE_INDEX = 8 +PAN_XHEIGHT_INDEX = 9 +PAN_CULTURE_LATIN = 0 +PAN_ANY = 0 +PAN_NO_FIT = 1 +PAN_FAMILY_TEXT_DISPLAY = 2 +PAN_FAMILY_SCRIPT = 3 +PAN_FAMILY_DECORATIVE = 4 +PAN_FAMILY_PICTORIAL = 5 +PAN_SERIF_COVE = 2 +PAN_SERIF_OBTUSE_COVE = 3 +PAN_SERIF_SQUARE_COVE = 4 +PAN_SERIF_OBTUSE_SQUARE_COVE = 5 +PAN_SERIF_SQUARE = 6 +PAN_SERIF_THIN = 7 +PAN_SERIF_BONE = 8 +PAN_SERIF_EXAGGERATED = 9 +PAN_SERIF_TRIANGLE = 10 +PAN_SERIF_NORMAL_SANS = 11 +PAN_SERIF_OBTUSE_SANS = 12 +PAN_SERIF_PERP_SANS = 13 +PAN_SERIF_FLARED = 14 +PAN_SERIF_ROUNDED = 15 +PAN_WEIGHT_VERY_LIGHT = 2 +PAN_WEIGHT_LIGHT = 3 +PAN_WEIGHT_THIN = 4 +PAN_WEIGHT_BOOK = 5 +PAN_WEIGHT_MEDIUM = 6 +PAN_WEIGHT_DEMI = 7 +PAN_WEIGHT_BOLD = 8 +PAN_WEIGHT_HEAVY = 9 +PAN_WEIGHT_BLACK = 10 +PAN_WEIGHT_NORD = 11 +PAN_PROP_OLD_STYLE = 2 +PAN_PROP_MODERN = 3 +PAN_PROP_EVEN_WIDTH = 4 +PAN_PROP_EXPANDED = 5 +PAN_PROP_CONDENSED = 6 +PAN_PROP_VERY_EXPANDED = 7 +PAN_PROP_VERY_CONDENSED = 8 +PAN_PROP_MONOSPACED = 9 +PAN_CONTRAST_NONE = 2 +PAN_CONTRAST_VERY_LOW = 3 +PAN_CONTRAST_LOW = 4 +PAN_CONTRAST_MEDIUM_LOW = 5 +PAN_CONTRAST_MEDIUM = 6 +PAN_CONTRAST_MEDIUM_HIGH = 7 +PAN_CONTRAST_HIGH = 8 +PAN_CONTRAST_VERY_HIGH = 9 +PAN_STROKE_GRADUAL_DIAG = 2 +PAN_STROKE_GRADUAL_TRAN = 3 +PAN_STROKE_GRADUAL_VERT = 4 +PAN_STROKE_GRADUAL_HORZ = 5 +PAN_STROKE_RAPID_VERT = 6 +PAN_STROKE_RAPID_HORZ = 7 +PAN_STROKE_INSTANT_VERT = 8 +PAN_STRAIGHT_ARMS_HORZ = 2 +PAN_STRAIGHT_ARMS_WEDGE = 3 +PAN_STRAIGHT_ARMS_VERT = 4 +PAN_STRAIGHT_ARMS_SINGLE_SERIF = 5 +PAN_STRAIGHT_ARMS_DOUBLE_SERIF = 6 +PAN_BENT_ARMS_HORZ = 7 +PAN_BENT_ARMS_WEDGE = 8 +PAN_BENT_ARMS_VERT = 9 +PAN_BENT_ARMS_SINGLE_SERIF = 10 +PAN_BENT_ARMS_DOUBLE_SERIF = 11 +PAN_LETT_NORMAL_CONTACT = 2 +PAN_LETT_NORMAL_WEIGHTED = 3 +PAN_LETT_NORMAL_BOXED = 4 +PAN_LETT_NORMAL_FLATTENED = 5 +PAN_LETT_NORMAL_ROUNDED = 6 +PAN_LETT_NORMAL_OFF_CENTER = 7 +PAN_LETT_NORMAL_SQUARE = 8 +PAN_LETT_OBLIQUE_CONTACT = 9 +PAN_LETT_OBLIQUE_WEIGHTED = 10 +PAN_LETT_OBLIQUE_BOXED = 11 +PAN_LETT_OBLIQUE_FLATTENED = 12 +PAN_LETT_OBLIQUE_ROUNDED = 13 +PAN_LETT_OBLIQUE_OFF_CENTER = 14 +PAN_LETT_OBLIQUE_SQUARE = 15 +PAN_MIDLINE_STANDARD_TRIMMED = 2 +PAN_MIDLINE_STANDARD_POINTED = 3 +PAN_MIDLINE_STANDARD_SERIFED = 4 +PAN_MIDLINE_HIGH_TRIMMED = 5 +PAN_MIDLINE_HIGH_POINTED = 6 +PAN_MIDLINE_HIGH_SERIFED = 7 +PAN_MIDLINE_CONSTANT_TRIMMED = 8 +PAN_MIDLINE_CONSTANT_POINTED = 9 +PAN_MIDLINE_CONSTANT_SERIFED = 10 +PAN_MIDLINE_LOW_TRIMMED = 11 +PAN_MIDLINE_LOW_POINTED = 12 +PAN_MIDLINE_LOW_SERIFED = 13 +PAN_XHEIGHT_CONSTANT_SMALL = 2 +PAN_XHEIGHT_CONSTANT_STD = 3 +PAN_XHEIGHT_CONSTANT_LARGE = 4 +PAN_XHEIGHT_DUCKING_SMALL = 5 +PAN_XHEIGHT_DUCKING_STD = 6 +PAN_XHEIGHT_DUCKING_LARGE = 7 +ELF_VENDOR_SIZE = 4 +ELF_VERSION = 0 +ELF_CULTURE_LATIN = 0 +RASTER_FONTTYPE = 1 +DEVICE_FONTTYPE = 2 +TRUETYPE_FONTTYPE = 4 + + +def PALETTEINDEX(i): + return 16777216 | (i) + + +PC_RESERVED = 1 +PC_EXPLICIT = 2 +PC_NOCOLLAPSE = 4 + + +def GetRValue(rgb): + return rgb & 0xFF + + +def GetGValue(rgb): + return (rgb >> 8) & 0xFF + + +def GetBValue(rgb): + return (rgb >> 16) & 0xFF + + +TRANSPARENT = 1 +OPAQUE = 2 +BKMODE_LAST = 2 +GM_COMPATIBLE = 1 +GM_ADVANCED = 2 +GM_LAST = 2 +PT_CLOSEFIGURE = 1 +PT_LINETO = 2 +PT_BEZIERTO = 4 +PT_MOVETO = 6 +MM_TEXT = 1 +MM_LOMETRIC = 2 +MM_HIMETRIC = 3 +MM_LOENGLISH = 4 +MM_HIENGLISH = 5 +MM_TWIPS = 6 +MM_ISOTROPIC = 7 +MM_ANISOTROPIC = 8 +MM_MIN = MM_TEXT +MM_MAX = MM_ANISOTROPIC +MM_MAX_FIXEDSCALE = MM_TWIPS +ABSOLUTE = 1 +RELATIVE = 2 +WHITE_BRUSH = 0 +LTGRAY_BRUSH = 1 +GRAY_BRUSH = 2 +DKGRAY_BRUSH = 3 +BLACK_BRUSH = 4 +NULL_BRUSH = 5 +HOLLOW_BRUSH = NULL_BRUSH +WHITE_PEN = 6 +BLACK_PEN = 7 +NULL_PEN = 8 +OEM_FIXED_FONT = 10 +ANSI_FIXED_FONT = 11 +ANSI_VAR_FONT = 12 +SYSTEM_FONT = 13 +DEVICE_DEFAULT_FONT = 14 +DEFAULT_PALETTE = 15 +SYSTEM_FIXED_FONT = 16 +STOCK_LAST = 16 +CLR_INVALID = -1 + +DC_BRUSH = 18 +DC_PEN = 19 + +# Exception/Status codes from winuser.h and winnt.h +STATUS_WAIT_0 = 0 +STATUS_ABANDONED_WAIT_0 = 128 +STATUS_USER_APC = 192 +STATUS_TIMEOUT = 258 +STATUS_PENDING = 259 +STATUS_SEGMENT_NOTIFICATION = 1073741829 +STATUS_GUARD_PAGE_VIOLATION = -2147483647 +STATUS_DATATYPE_MISALIGNMENT = -2147483646 +STATUS_BREAKPOINT = -2147483645 +STATUS_SINGLE_STEP = -2147483644 +STATUS_ACCESS_VIOLATION = -1073741819 +STATUS_IN_PAGE_ERROR = -1073741818 +STATUS_INVALID_HANDLE = -1073741816 +STATUS_NO_MEMORY = -1073741801 +STATUS_ILLEGAL_INSTRUCTION = -1073741795 +STATUS_NONCONTINUABLE_EXCEPTION = -1073741787 +STATUS_INVALID_DISPOSITION = -1073741786 +STATUS_ARRAY_BOUNDS_EXCEEDED = -1073741684 +STATUS_FLOAT_DENORMAL_OPERAND = -1073741683 +STATUS_FLOAT_DIVIDE_BY_ZERO = -1073741682 +STATUS_FLOAT_INEXACT_RESULT = -1073741681 +STATUS_FLOAT_INVALID_OPERATION = -1073741680 +STATUS_FLOAT_OVERFLOW = -1073741679 +STATUS_FLOAT_STACK_CHECK = -1073741678 +STATUS_FLOAT_UNDERFLOW = -1073741677 +STATUS_INTEGER_DIVIDE_BY_ZERO = -1073741676 +STATUS_INTEGER_OVERFLOW = -1073741675 +STATUS_PRIVILEGED_INSTRUCTION = -1073741674 +STATUS_STACK_OVERFLOW = -1073741571 +STATUS_CONTROL_C_EXIT = -1073741510 + + +WAIT_FAILED = -1 +WAIT_OBJECT_0 = STATUS_WAIT_0 + 0 + +WAIT_ABANDONED = STATUS_ABANDONED_WAIT_0 + 0 +WAIT_ABANDONED_0 = STATUS_ABANDONED_WAIT_0 + 0 + +WAIT_TIMEOUT = STATUS_TIMEOUT +WAIT_IO_COMPLETION = STATUS_USER_APC +STILL_ACTIVE = STATUS_PENDING +EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION +EXCEPTION_DATATYPE_MISALIGNMENT = STATUS_DATATYPE_MISALIGNMENT +EXCEPTION_BREAKPOINT = STATUS_BREAKPOINT +EXCEPTION_SINGLE_STEP = STATUS_SINGLE_STEP +EXCEPTION_ARRAY_BOUNDS_EXCEEDED = STATUS_ARRAY_BOUNDS_EXCEEDED +EXCEPTION_FLT_DENORMAL_OPERAND = STATUS_FLOAT_DENORMAL_OPERAND +EXCEPTION_FLT_DIVIDE_BY_ZERO = STATUS_FLOAT_DIVIDE_BY_ZERO +EXCEPTION_FLT_INEXACT_RESULT = STATUS_FLOAT_INEXACT_RESULT +EXCEPTION_FLT_INVALID_OPERATION = STATUS_FLOAT_INVALID_OPERATION +EXCEPTION_FLT_OVERFLOW = STATUS_FLOAT_OVERFLOW +EXCEPTION_FLT_STACK_CHECK = STATUS_FLOAT_STACK_CHECK +EXCEPTION_FLT_UNDERFLOW = STATUS_FLOAT_UNDERFLOW +EXCEPTION_INT_DIVIDE_BY_ZERO = STATUS_INTEGER_DIVIDE_BY_ZERO +EXCEPTION_INT_OVERFLOW = STATUS_INTEGER_OVERFLOW +EXCEPTION_PRIV_INSTRUCTION = STATUS_PRIVILEGED_INSTRUCTION +EXCEPTION_IN_PAGE_ERROR = STATUS_IN_PAGE_ERROR +EXCEPTION_ILLEGAL_INSTRUCTION = STATUS_ILLEGAL_INSTRUCTION +EXCEPTION_NONCONTINUABLE_EXCEPTION = STATUS_NONCONTINUABLE_EXCEPTION +EXCEPTION_STACK_OVERFLOW = STATUS_STACK_OVERFLOW +EXCEPTION_INVALID_DISPOSITION = STATUS_INVALID_DISPOSITION +EXCEPTION_GUARD_PAGE = STATUS_GUARD_PAGE_VIOLATION +EXCEPTION_INVALID_HANDLE = STATUS_INVALID_HANDLE +CONTROL_C_EXIT = STATUS_CONTROL_C_EXIT + +# winuser.h line 8594 +# constants used with SystemParametersInfo +SPI_GETBEEP = 1 +SPI_SETBEEP = 2 +SPI_GETMOUSE = 3 +SPI_SETMOUSE = 4 +SPI_GETBORDER = 5 +SPI_SETBORDER = 6 +SPI_GETKEYBOARDSPEED = 10 +SPI_SETKEYBOARDSPEED = 11 +SPI_LANGDRIVER = 12 +SPI_ICONHORIZONTALSPACING = 13 +SPI_GETSCREENSAVETIMEOUT = 14 +SPI_SETSCREENSAVETIMEOUT = 15 +SPI_GETSCREENSAVEACTIVE = 16 +SPI_SETSCREENSAVEACTIVE = 17 +SPI_GETGRIDGRANULARITY = 18 +SPI_SETGRIDGRANULARITY = 19 +SPI_SETDESKWALLPAPER = 20 +SPI_SETDESKPATTERN = 21 +SPI_GETKEYBOARDDELAY = 22 +SPI_SETKEYBOARDDELAY = 23 +SPI_ICONVERTICALSPACING = 24 +SPI_GETICONTITLEWRAP = 25 +SPI_SETICONTITLEWRAP = 26 +SPI_GETMENUDROPALIGNMENT = 27 +SPI_SETMENUDROPALIGNMENT = 28 +SPI_SETDOUBLECLKWIDTH = 29 +SPI_SETDOUBLECLKHEIGHT = 30 +SPI_GETICONTITLELOGFONT = 31 +SPI_SETDOUBLECLICKTIME = 32 +SPI_SETMOUSEBUTTONSWAP = 33 +SPI_SETICONTITLELOGFONT = 34 +SPI_GETFASTTASKSWITCH = 35 +SPI_SETFASTTASKSWITCH = 36 +SPI_SETDRAGFULLWINDOWS = 37 +SPI_GETDRAGFULLWINDOWS = 38 +SPI_GETNONCLIENTMETRICS = 41 +SPI_SETNONCLIENTMETRICS = 42 +SPI_GETMINIMIZEDMETRICS = 43 +SPI_SETMINIMIZEDMETRICS = 44 +SPI_GETICONMETRICS = 45 +SPI_SETICONMETRICS = 46 +SPI_SETWORKAREA = 47 +SPI_GETWORKAREA = 48 +SPI_SETPENWINDOWS = 49 +SPI_GETFILTERKEYS = 50 +SPI_SETFILTERKEYS = 51 +SPI_GETTOGGLEKEYS = 52 +SPI_SETTOGGLEKEYS = 53 +SPI_GETMOUSEKEYS = 54 +SPI_SETMOUSEKEYS = 55 +SPI_GETSHOWSOUNDS = 56 +SPI_SETSHOWSOUNDS = 57 +SPI_GETSTICKYKEYS = 58 +SPI_SETSTICKYKEYS = 59 +SPI_GETACCESSTIMEOUT = 60 +SPI_SETACCESSTIMEOUT = 61 +SPI_GETSERIALKEYS = 62 +SPI_SETSERIALKEYS = 63 +SPI_GETSOUNDSENTRY = 64 +SPI_SETSOUNDSENTRY = 65 +SPI_GETHIGHCONTRAST = 66 +SPI_SETHIGHCONTRAST = 67 +SPI_GETKEYBOARDPREF = 68 +SPI_SETKEYBOARDPREF = 69 +SPI_GETSCREENREADER = 70 +SPI_SETSCREENREADER = 71 +SPI_GETANIMATION = 72 +SPI_SETANIMATION = 73 +SPI_GETFONTSMOOTHING = 74 +SPI_SETFONTSMOOTHING = 75 +SPI_SETDRAGWIDTH = 76 +SPI_SETDRAGHEIGHT = 77 +SPI_SETHANDHELD = 78 +SPI_GETLOWPOWERTIMEOUT = 79 +SPI_GETPOWEROFFTIMEOUT = 80 +SPI_SETLOWPOWERTIMEOUT = 81 +SPI_SETPOWEROFFTIMEOUT = 82 +SPI_GETLOWPOWERACTIVE = 83 +SPI_GETPOWEROFFACTIVE = 84 +SPI_SETLOWPOWERACTIVE = 85 +SPI_SETPOWEROFFACTIVE = 86 +SPI_SETCURSORS = 87 +SPI_SETICONS = 88 +SPI_GETDEFAULTINPUTLANG = 89 +SPI_SETDEFAULTINPUTLANG = 90 +SPI_SETLANGTOGGLE = 91 +SPI_GETWINDOWSEXTENSION = 92 +SPI_SETMOUSETRAILS = 93 +SPI_GETMOUSETRAILS = 94 +SPI_GETSNAPTODEFBUTTON = 95 +SPI_SETSNAPTODEFBUTTON = 96 +SPI_SETSCREENSAVERRUNNING = 97 +SPI_SCREENSAVERRUNNING = SPI_SETSCREENSAVERRUNNING +SPI_GETMOUSEHOVERWIDTH = 98 +SPI_SETMOUSEHOVERWIDTH = 99 +SPI_GETMOUSEHOVERHEIGHT = 100 +SPI_SETMOUSEHOVERHEIGHT = 101 +SPI_GETMOUSEHOVERTIME = 102 +SPI_SETMOUSEHOVERTIME = 103 +SPI_GETWHEELSCROLLLINES = 104 +SPI_SETWHEELSCROLLLINES = 105 +SPI_GETMENUSHOWDELAY = 106 +SPI_SETMENUSHOWDELAY = 107 + +SPI_GETSHOWIMEUI = 110 +SPI_SETSHOWIMEUI = 111 +SPI_GETMOUSESPEED = 112 +SPI_SETMOUSESPEED = 113 +SPI_GETSCREENSAVERRUNNING = 114 +SPI_GETDESKWALLPAPER = 115 + +SPI_GETACTIVEWINDOWTRACKING = 4096 +SPI_SETACTIVEWINDOWTRACKING = 4097 +SPI_GETMENUANIMATION = 4098 +SPI_SETMENUANIMATION = 4099 +SPI_GETCOMBOBOXANIMATION = 4100 +SPI_SETCOMBOBOXANIMATION = 4101 +SPI_GETLISTBOXSMOOTHSCROLLING = 4102 +SPI_SETLISTBOXSMOOTHSCROLLING = 4103 +SPI_GETGRADIENTCAPTIONS = 4104 +SPI_SETGRADIENTCAPTIONS = 4105 +SPI_GETKEYBOARDCUES = 4106 +SPI_SETKEYBOARDCUES = 4107 +SPI_GETMENUUNDERLINES = 4106 +SPI_SETMENUUNDERLINES = 4107 +SPI_GETACTIVEWNDTRKZORDER = 4108 +SPI_SETACTIVEWNDTRKZORDER = 4109 +SPI_GETHOTTRACKING = 4110 +SPI_SETHOTTRACKING = 4111 + +SPI_GETMENUFADE = 4114 +SPI_SETMENUFADE = 4115 +SPI_GETSELECTIONFADE = 4116 +SPI_SETSELECTIONFADE = 4117 +SPI_GETTOOLTIPANIMATION = 4118 +SPI_SETTOOLTIPANIMATION = 4119 +SPI_GETTOOLTIPFADE = 4120 +SPI_SETTOOLTIPFADE = 4121 +SPI_GETCURSORSHADOW = 4122 +SPI_SETCURSORSHADOW = 4123 +SPI_GETMOUSESONAR = 4124 +SPI_SETMOUSESONAR = 4125 +SPI_GETMOUSECLICKLOCK = 4126 +SPI_SETMOUSECLICKLOCK = 4127 +SPI_GETMOUSEVANISH = 4128 +SPI_SETMOUSEVANISH = 4129 +SPI_GETFLATMENU = 4130 +SPI_SETFLATMENU = 4131 +SPI_GETDROPSHADOW = 4132 +SPI_SETDROPSHADOW = 4133 +SPI_GETBLOCKSENDINPUTRESETS = 4134 +SPI_SETBLOCKSENDINPUTRESETS = 4135 +SPI_GETUIEFFECTS = 4158 +SPI_SETUIEFFECTS = 4159 + +SPI_GETFOREGROUNDLOCKTIMEOUT = 8192 +SPI_SETFOREGROUNDLOCKTIMEOUT = 8193 +SPI_GETACTIVEWNDTRKTIMEOUT = 8194 +SPI_SETACTIVEWNDTRKTIMEOUT = 8195 +SPI_GETFOREGROUNDFLASHCOUNT = 8196 +SPI_SETFOREGROUNDFLASHCOUNT = 8197 +SPI_GETCARETWIDTH = 8198 +SPI_SETCARETWIDTH = 8199 +SPI_GETMOUSECLICKLOCKTIME = 8200 +SPI_SETMOUSECLICKLOCKTIME = 8201 +SPI_GETFONTSMOOTHINGTYPE = 8202 +SPI_SETFONTSMOOTHINGTYPE = 8203 +SPI_GETFONTSMOOTHINGCONTRAST = 8204 +SPI_SETFONTSMOOTHINGCONTRAST = 8205 +SPI_GETFOCUSBORDERWIDTH = 8206 +SPI_SETFOCUSBORDERWIDTH = 8207 +SPI_GETFOCUSBORDERHEIGHT = 8208 +SPI_SETFOCUSBORDERHEIGHT = 8209 +SPI_GETFONTSMOOTHINGORIENTATION = 8210 +SPI_SETFONTSMOOTHINGORIENTATION = 8211 + +# fWinIni flags for SystemParametersInfo +SPIF_UPDATEINIFILE = 1 +SPIF_SENDWININICHANGE = 2 +SPIF_SENDCHANGE = SPIF_SENDWININICHANGE + +# used with SystemParametersInfo and SPI_GETFONTSMOOTHINGTYPE/SPI_SETFONTSMOOTHINGTYPE +FE_FONTSMOOTHINGSTANDARD = 1 +FE_FONTSMOOTHINGCLEARTYPE = 2 +FE_FONTSMOOTHINGDOCKING = 32768 + +METRICS_USEDEFAULT = -1 +ARW_BOTTOMLEFT = 0 +ARW_BOTTOMRIGHT = 1 +ARW_TOPLEFT = 2 +ARW_TOPRIGHT = 3 +ARW_STARTMASK = 3 +ARW_STARTRIGHT = 1 +ARW_STARTTOP = 2 +ARW_LEFT = 0 +ARW_RIGHT = 0 +ARW_UP = 4 +ARW_DOWN = 4 +ARW_HIDE = 8 +# ARW_VALID = 0x000F +SERKF_SERIALKEYSON = 1 +SERKF_AVAILABLE = 2 +SERKF_INDICATOR = 4 +HCF_HIGHCONTRASTON = 1 +HCF_AVAILABLE = 2 +HCF_HOTKEYACTIVE = 4 +HCF_CONFIRMHOTKEY = 8 +HCF_HOTKEYSOUND = 16 +HCF_INDICATOR = 32 +HCF_HOTKEYAVAILABLE = 64 +CDS_UPDATEREGISTRY = 1 +CDS_TEST = 2 +CDS_FULLSCREEN = 4 +CDS_GLOBAL = 8 +CDS_SET_PRIMARY = 16 +CDS_RESET = 1073741824 +CDS_SETRECT = 536870912 +CDS_NORESET = 268435456 + +# return values from ChangeDisplaySettings and ChangeDisplaySettingsEx +DISP_CHANGE_SUCCESSFUL = 0 +DISP_CHANGE_RESTART = 1 +DISP_CHANGE_FAILED = -1 +DISP_CHANGE_BADMODE = -2 +DISP_CHANGE_NOTUPDATED = -3 +DISP_CHANGE_BADFLAGS = -4 +DISP_CHANGE_BADPARAM = -5 +DISP_CHANGE_BADDUALVIEW = -6 + +ENUM_CURRENT_SETTINGS = -1 +ENUM_REGISTRY_SETTINGS = -2 +FKF_FILTERKEYSON = 1 +FKF_AVAILABLE = 2 +FKF_HOTKEYACTIVE = 4 +FKF_CONFIRMHOTKEY = 8 +FKF_HOTKEYSOUND = 16 +FKF_INDICATOR = 32 +FKF_CLICKON = 64 +SKF_STICKYKEYSON = 1 +SKF_AVAILABLE = 2 +SKF_HOTKEYACTIVE = 4 +SKF_CONFIRMHOTKEY = 8 +SKF_HOTKEYSOUND = 16 +SKF_INDICATOR = 32 +SKF_AUDIBLEFEEDBACK = 64 +SKF_TRISTATE = 128 +SKF_TWOKEYSOFF = 256 +SKF_LALTLATCHED = 268435456 +SKF_LCTLLATCHED = 67108864 +SKF_LSHIFTLATCHED = 16777216 +SKF_RALTLATCHED = 536870912 +SKF_RCTLLATCHED = 134217728 +SKF_RSHIFTLATCHED = 33554432 +SKF_LWINLATCHED = 1073741824 +SKF_RWINLATCHED = -2147483648 +SKF_LALTLOCKED = 1048576 +SKF_LCTLLOCKED = 262144 +SKF_LSHIFTLOCKED = 65536 +SKF_RALTLOCKED = 2097152 +SKF_RCTLLOCKED = 524288 +SKF_RSHIFTLOCKED = 131072 +SKF_LWINLOCKED = 4194304 +SKF_RWINLOCKED = 8388608 +MKF_MOUSEKEYSON = 1 +MKF_AVAILABLE = 2 +MKF_HOTKEYACTIVE = 4 +MKF_CONFIRMHOTKEY = 8 +MKF_HOTKEYSOUND = 16 +MKF_INDICATOR = 32 +MKF_MODIFIERS = 64 +MKF_REPLACENUMBERS = 128 +MKF_LEFTBUTTONSEL = 268435456 +MKF_RIGHTBUTTONSEL = 536870912 +MKF_LEFTBUTTONDOWN = 16777216 +MKF_RIGHTBUTTONDOWN = 33554432 +MKF_MOUSEMODE = -2147483648 +ATF_TIMEOUTON = 1 +ATF_ONOFFFEEDBACK = 2 +SSGF_NONE = 0 +SSGF_DISPLAY = 3 +SSTF_NONE = 0 +SSTF_CHARS = 1 +SSTF_BORDER = 2 +SSTF_DISPLAY = 3 +SSWF_NONE = 0 +SSWF_TITLE = 1 +SSWF_WINDOW = 2 +SSWF_DISPLAY = 3 +SSWF_CUSTOM = 4 +SSF_SOUNDSENTRYON = 1 +SSF_AVAILABLE = 2 +SSF_INDICATOR = 4 +TKF_TOGGLEKEYSON = 1 +TKF_AVAILABLE = 2 +TKF_HOTKEYACTIVE = 4 +TKF_CONFIRMHOTKEY = 8 +TKF_HOTKEYSOUND = 16 +TKF_INDICATOR = 32 +SLE_ERROR = 1 +SLE_MINORERROR = 2 +SLE_WARNING = 3 +MONITOR_DEFAULTTONULL = 0 +MONITOR_DEFAULTTOPRIMARY = 1 +MONITOR_DEFAULTTONEAREST = 2 +MONITORINFOF_PRIMARY = 1 +CCHDEVICENAME = 32 +CHILDID_SELF = 0 +INDEXID_OBJECT = 0 +INDEXID_CONTAINER = 0 +OBJID_WINDOW = 0 +OBJID_SYSMENU = -1 +OBJID_TITLEBAR = -2 +OBJID_MENU = -3 +OBJID_CLIENT = -4 +OBJID_VSCROLL = -5 +OBJID_HSCROLL = -6 +OBJID_SIZEGRIP = -7 +OBJID_CARET = -8 +OBJID_CURSOR = -9 +OBJID_ALERT = -10 +OBJID_SOUND = -11 +EVENT_MIN = 1 +EVENT_MAX = 2147483647 +EVENT_SYSTEM_SOUND = 1 +EVENT_SYSTEM_ALERT = 2 +EVENT_SYSTEM_FOREGROUND = 3 +EVENT_SYSTEM_MENUSTART = 4 +EVENT_SYSTEM_MENUEND = 5 +EVENT_SYSTEM_MENUPOPUPSTART = 6 +EVENT_SYSTEM_MENUPOPUPEND = 7 +EVENT_SYSTEM_CAPTURESTART = 8 +EVENT_SYSTEM_CAPTUREEND = 9 +EVENT_SYSTEM_MOVESIZESTART = 10 +EVENT_SYSTEM_MOVESIZEEND = 11 +EVENT_SYSTEM_CONTEXTHELPSTART = 12 +EVENT_SYSTEM_CONTEXTHELPEND = 13 +EVENT_SYSTEM_DRAGDROPSTART = 14 +EVENT_SYSTEM_DRAGDROPEND = 15 +EVENT_SYSTEM_DIALOGSTART = 16 +EVENT_SYSTEM_DIALOGEND = 17 +EVENT_SYSTEM_SCROLLINGSTART = 18 +EVENT_SYSTEM_SCROLLINGEND = 19 +EVENT_SYSTEM_SWITCHSTART = 20 +EVENT_SYSTEM_SWITCHEND = 21 +EVENT_SYSTEM_MINIMIZESTART = 22 +EVENT_SYSTEM_MINIMIZEEND = 23 +EVENT_OBJECT_CREATE = 32768 +EVENT_OBJECT_DESTROY = 32769 +EVENT_OBJECT_SHOW = 32770 +EVENT_OBJECT_HIDE = 32771 +EVENT_OBJECT_REORDER = 32772 +EVENT_OBJECT_FOCUS = 32773 +EVENT_OBJECT_SELECTION = 32774 +EVENT_OBJECT_SELECTIONADD = 32775 +EVENT_OBJECT_SELECTIONREMOVE = 32776 +EVENT_OBJECT_SELECTIONWITHIN = 32777 +EVENT_OBJECT_STATECHANGE = 32778 +EVENT_OBJECT_LOCATIONCHANGE = 32779 +EVENT_OBJECT_NAMECHANGE = 32780 +EVENT_OBJECT_DESCRIPTIONCHANGE = 32781 +EVENT_OBJECT_VALUECHANGE = 32782 +EVENT_OBJECT_PARENTCHANGE = 32783 +EVENT_OBJECT_HELPCHANGE = 32784 +EVENT_OBJECT_DEFACTIONCHANGE = 32785 +EVENT_OBJECT_ACCELERATORCHANGE = 32786 +SOUND_SYSTEM_STARTUP = 1 +SOUND_SYSTEM_SHUTDOWN = 2 +SOUND_SYSTEM_BEEP = 3 +SOUND_SYSTEM_ERROR = 4 +SOUND_SYSTEM_QUESTION = 5 +SOUND_SYSTEM_WARNING = 6 +SOUND_SYSTEM_INFORMATION = 7 +SOUND_SYSTEM_MAXIMIZE = 8 +SOUND_SYSTEM_MINIMIZE = 9 +SOUND_SYSTEM_RESTOREUP = 10 +SOUND_SYSTEM_RESTOREDOWN = 11 +SOUND_SYSTEM_APPSTART = 12 +SOUND_SYSTEM_FAULT = 13 +SOUND_SYSTEM_APPEND = 14 +SOUND_SYSTEM_MENUCOMMAND = 15 +SOUND_SYSTEM_MENUPOPUP = 16 +CSOUND_SYSTEM = 16 +ALERT_SYSTEM_INFORMATIONAL = 1 +ALERT_SYSTEM_WARNING = 2 +ALERT_SYSTEM_ERROR = 3 +ALERT_SYSTEM_QUERY = 4 +ALERT_SYSTEM_CRITICAL = 5 +CALERT_SYSTEM = 6 +WINEVENT_OUTOFCONTEXT = 0 +WINEVENT_SKIPOWNTHREAD = 1 +WINEVENT_SKIPOWNPROCESS = 2 +WINEVENT_INCONTEXT = 4 +GUI_CARETBLINKING = 1 +GUI_INMOVESIZE = 2 +GUI_INMENUMODE = 4 +GUI_SYSTEMMENUMODE = 8 +GUI_POPUPMENUMODE = 16 +STATE_SYSTEM_UNAVAILABLE = 1 +STATE_SYSTEM_SELECTED = 2 +STATE_SYSTEM_FOCUSED = 4 +STATE_SYSTEM_PRESSED = 8 +STATE_SYSTEM_CHECKED = 16 +STATE_SYSTEM_MIXED = 32 +STATE_SYSTEM_READONLY = 64 +STATE_SYSTEM_HOTTRACKED = 128 +STATE_SYSTEM_DEFAULT = 256 +STATE_SYSTEM_EXPANDED = 512 +STATE_SYSTEM_COLLAPSED = 1024 +STATE_SYSTEM_BUSY = 2048 +STATE_SYSTEM_FLOATING = 4096 +STATE_SYSTEM_MARQUEED = 8192 +STATE_SYSTEM_ANIMATED = 16384 +STATE_SYSTEM_INVISIBLE = 32768 +STATE_SYSTEM_OFFSCREEN = 65536 +STATE_SYSTEM_SIZEABLE = 131072 +STATE_SYSTEM_MOVEABLE = 262144 +STATE_SYSTEM_SELFVOICING = 524288 +STATE_SYSTEM_FOCUSABLE = 1048576 +STATE_SYSTEM_SELECTABLE = 2097152 +STATE_SYSTEM_LINKED = 4194304 +STATE_SYSTEM_TRAVERSED = 8388608 +STATE_SYSTEM_MULTISELECTABLE = 16777216 +STATE_SYSTEM_EXTSELECTABLE = 33554432 +STATE_SYSTEM_ALERT_LOW = 67108864 +STATE_SYSTEM_ALERT_MEDIUM = 134217728 +STATE_SYSTEM_ALERT_HIGH = 268435456 +STATE_SYSTEM_VALID = 536870911 +CCHILDREN_TITLEBAR = 5 +CCHILDREN_SCROLLBAR = 5 +CURSOR_SHOWING = 1 +WS_ACTIVECAPTION = 1 +GA_MIC = 1 +GA_PARENT = 1 +GA_ROOT = 2 +GA_ROOTOWNER = 3 +GA_MAC = 4 + +# winuser.h line 1979 +BF_LEFT = 1 +BF_TOP = 2 +BF_RIGHT = 4 +BF_BOTTOM = 8 +BF_TOPLEFT = BF_TOP | BF_LEFT +BF_TOPRIGHT = BF_TOP | BF_RIGHT +BF_BOTTOMLEFT = BF_BOTTOM | BF_LEFT +BF_BOTTOMRIGHT = BF_BOTTOM | BF_RIGHT +BF_RECT = BF_LEFT | BF_TOP | BF_RIGHT | BF_BOTTOM +BF_DIAGONAL = 16 +BF_DIAGONAL_ENDTOPRIGHT = BF_DIAGONAL | BF_TOP | BF_RIGHT +BF_DIAGONAL_ENDTOPLEFT = BF_DIAGONAL | BF_TOP | BF_LEFT +BF_DIAGONAL_ENDBOTTOMLEFT = BF_DIAGONAL | BF_BOTTOM | BF_LEFT +BF_DIAGONAL_ENDBOTTOMRIGHT = BF_DIAGONAL | BF_BOTTOM | BF_RIGHT +BF_MIDDLE = 2048 +BF_SOFT = 4096 +BF_ADJUST = 8192 +BF_FLAT = 16384 +BF_MONO = 32768 +DFC_CAPTION = 1 +DFC_MENU = 2 +DFC_SCROLL = 3 +DFC_BUTTON = 4 +DFC_POPUPMENU = 5 +DFCS_CAPTIONCLOSE = 0 +DFCS_CAPTIONMIN = 1 +DFCS_CAPTIONMAX = 2 +DFCS_CAPTIONRESTORE = 3 +DFCS_CAPTIONHELP = 4 +DFCS_MENUARROW = 0 +DFCS_MENUCHECK = 1 +DFCS_MENUBULLET = 2 +DFCS_MENUARROWRIGHT = 4 +DFCS_SCROLLUP = 0 +DFCS_SCROLLDOWN = 1 +DFCS_SCROLLLEFT = 2 +DFCS_SCROLLRIGHT = 3 +DFCS_SCROLLCOMBOBOX = 5 +DFCS_SCROLLSIZEGRIP = 8 +DFCS_SCROLLSIZEGRIPRIGHT = 16 +DFCS_BUTTONCHECK = 0 +DFCS_BUTTONRADIOIMAGE = 1 +DFCS_BUTTONRADIOMASK = 2 +DFCS_BUTTONRADIO = 4 +DFCS_BUTTON3STATE = 8 +DFCS_BUTTONPUSH = 16 +DFCS_INACTIVE = 256 +DFCS_PUSHED = 512 +DFCS_CHECKED = 1024 +DFCS_TRANSPARENT = 2048 +DFCS_HOT = 4096 +DFCS_ADJUSTRECT = 8192 +DFCS_FLAT = 16384 +DFCS_MONO = 32768 +DC_ACTIVE = 1 +DC_SMALLCAP = 2 +DC_ICON = 4 +DC_TEXT = 8 +DC_INBUTTON = 16 +DC_GRADIENT = 32 +IDANI_OPEN = 1 +IDANI_CLOSE = 2 +IDANI_CAPTION = 3 +CF_TEXT = 1 +CF_BITMAP = 2 +CF_METAFILEPICT = 3 +CF_SYLK = 4 +CF_DIF = 5 +CF_TIFF = 6 +CF_OEMTEXT = 7 +CF_DIB = 8 +CF_PALETTE = 9 +CF_PENDATA = 10 +CF_RIFF = 11 +CF_WAVE = 12 +CF_UNICODETEXT = 13 +CF_ENHMETAFILE = 14 +CF_HDROP = 15 +CF_LOCALE = 16 +CF_DIBV5 = 17 +CF_MAX = 18 +CF_OWNERDISPLAY = 128 +CF_DSPTEXT = 129 +CF_DSPBITMAP = 130 +CF_DSPMETAFILEPICT = 131 +CF_DSPENHMETAFILE = 142 +CF_PRIVATEFIRST = 512 +CF_PRIVATELAST = 767 +CF_GDIOBJFIRST = 768 +CF_GDIOBJLAST = 1023 +FVIRTKEY = 1 +FNOINVERT = 2 +FSHIFT = 4 +FCONTROL = 8 +FALT = 16 +WPF_SETMINPOSITION = 1 +WPF_RESTORETOMAXIMIZED = 2 +ODT_MENU = 1 +ODT_LISTBOX = 2 +ODT_COMBOBOX = 3 +ODT_BUTTON = 4 +ODT_STATIC = 5 +ODA_DRAWENTIRE = 1 +ODA_SELECT = 2 +ODA_FOCUS = 4 +ODS_SELECTED = 1 +ODS_GRAYED = 2 +ODS_DISABLED = 4 +ODS_CHECKED = 8 +ODS_FOCUS = 16 +ODS_DEFAULT = 32 +ODS_COMBOBOXEDIT = 4096 +ODS_HOTLIGHT = 64 +ODS_INACTIVE = 128 +PM_NOREMOVE = 0 +PM_REMOVE = 1 +PM_NOYIELD = 2 +MOD_ALT = 1 +MOD_CONTROL = 2 +MOD_SHIFT = 4 +MOD_WIN = 8 +IDHOT_SNAPWINDOW = -1 +IDHOT_SNAPDESKTOP = -2 +# EW_RESTARTWINDOWS = 0x0042 +# EW_REBOOTSYSTEM = 0x0043 +# EW_EXITANDEXECAPP = 0x0044 +ENDSESSION_LOGOFF = -2147483648 +EWX_LOGOFF = 0 +EWX_SHUTDOWN = 1 +EWX_REBOOT = 2 +EWX_FORCE = 4 +EWX_POWEROFF = 8 +EWX_FORCEIFHUNG = 16 +BSM_ALLCOMPONENTS = 0 +BSM_VXDS = 1 +BSM_NETDRIVER = 2 +BSM_INSTALLABLEDRIVERS = 4 +BSM_APPLICATIONS = 8 +BSM_ALLDESKTOPS = 16 +BSF_QUERY = 1 +BSF_IGNORECURRENTTASK = 2 +BSF_FLUSHDISK = 4 +BSF_NOHANG = 8 +BSF_POSTMESSAGE = 16 +BSF_FORCEIFHUNG = 32 +BSF_NOTIMEOUTIFNOTHUNG = 64 +BROADCAST_QUERY_DENY = 1112363332 # Return this value to deny a query. + +DBWF_LPARAMPOINTER = 32768 + +# winuser.h line 3232 +SWP_NOSIZE = 1 +SWP_NOMOVE = 2 +SWP_NOZORDER = 4 +SWP_NOREDRAW = 8 +SWP_NOACTIVATE = 16 +SWP_FRAMECHANGED = 32 +SWP_SHOWWINDOW = 64 +SWP_HIDEWINDOW = 128 +SWP_NOCOPYBITS = 256 +SWP_NOOWNERZORDER = 512 +SWP_NOSENDCHANGING = 1024 +SWP_DRAWFRAME = SWP_FRAMECHANGED +SWP_NOREPOSITION = SWP_NOOWNERZORDER +SWP_DEFERERASE = 8192 +SWP_ASYNCWINDOWPOS = 16384 + +DLGWINDOWEXTRA = 30 +# winuser.h line 4249 +KEYEVENTF_EXTENDEDKEY = 1 +KEYEVENTF_KEYUP = 2 +# if(_WIN32_WINNT >= 0x0500) +KEYEVENTF_UNICODE = 4 +KEYEVENTF_SCANCODE = 8 +# endif /* _WIN32_WINNT >= 0x0500 */ +MOUSEEVENTF_MOVE = 1 +MOUSEEVENTF_LEFTDOWN = 2 +MOUSEEVENTF_LEFTUP = 4 +MOUSEEVENTF_RIGHTDOWN = 8 +MOUSEEVENTF_RIGHTUP = 16 +MOUSEEVENTF_MIDDLEDOWN = 32 +MOUSEEVENTF_MIDDLEUP = 64 +MOUSEEVENTF_XDOWN = 128 +MOUSEEVENTF_XUP = 256 +MOUSEEVENTF_WHEEL = 2048 +# if (_WIN32_WINNT >= 0x0600) +MOUSEEVENTF_HWHEEL = 4096 +# endif +# if(WINVER >= 0x0600) +MOUSEEVENTF_MOVE_NOCOALESCE = 8192 +# endif /* WINVER >= 0x0600 */ +MOUSEEVENTF_VIRTUALDESK = 16384 +MOUSEEVENTF_ABSOLUTE = 32768 +INPUT_MOUSE = 0 +INPUT_KEYBOARD = 1 +INPUT_HARDWARE = 2 +MWMO_WAITALL = 1 +MWMO_ALERTABLE = 2 +MWMO_INPUTAVAILABLE = 4 +QS_KEY = 1 +QS_MOUSEMOVE = 2 +QS_MOUSEBUTTON = 4 +QS_POSTMESSAGE = 8 +QS_TIMER = 16 +QS_PAINT = 32 +QS_SENDMESSAGE = 64 +QS_HOTKEY = 128 +QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON +QS_INPUT = QS_MOUSE | QS_KEY +QS_ALLEVENTS = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY +QS_ALLINPUT = ( + QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE +) + + +IMN_CLOSESTATUSWINDOW = 1 +IMN_OPENSTATUSWINDOW = 2 +IMN_CHANGECANDIDATE = 3 +IMN_CLOSECANDIDATE = 4 +IMN_OPENCANDIDATE = 5 +IMN_SETCONVERSIONMODE = 6 +IMN_SETSENTENCEMODE = 7 +IMN_SETOPENSTATUS = 8 +IMN_SETCANDIDATEPOS = 9 +IMN_SETCOMPOSITIONFONT = 10 +IMN_SETCOMPOSITIONWINDOW = 11 +IMN_SETSTATUSWINDOWPOS = 12 +IMN_GUIDELINE = 13 +IMN_PRIVATE = 14 + +# winuser.h line 8518 +HELP_CONTEXT = 1 +HELP_QUIT = 2 +HELP_INDEX = 3 +HELP_CONTENTS = 3 +HELP_HELPONHELP = 4 +HELP_SETINDEX = 5 +HELP_SETCONTENTS = 5 +HELP_CONTEXTPOPUP = 8 +HELP_FORCEFILE = 9 +HELP_KEY = 257 +HELP_COMMAND = 258 +HELP_PARTIALKEY = 261 +HELP_MULTIKEY = 513 +HELP_SETWINPOS = 515 +HELP_CONTEXTMENU = 10 +HELP_FINDER = 11 +HELP_WM_HELP = 12 +HELP_SETPOPUP_POS = 13 +HELP_TCARD = 32768 +HELP_TCARD_DATA = 16 +HELP_TCARD_OTHER_CALLER = 17 +IDH_NO_HELP = 28440 +IDH_MISSING_CONTEXT = 28441 # Control doesn't have matching help context +IDH_GENERIC_HELP_BUTTON = 28442 # Property sheet help button +IDH_OK = 28443 +IDH_CANCEL = 28444 +IDH_HELP = 28445 +GR_GDIOBJECTS = 0 # Count of GDI objects +GR_USEROBJECTS = 1 # Count of USER objects +# Generated by h2py from \msvcnt\include\wingdi.h +# manually added (missed by generation some how! +SRCCOPY = 13369376 # dest = source +SRCPAINT = 15597702 # dest = source OR dest +SRCAND = 8913094 # dest = source AND dest +SRCINVERT = 6684742 # dest = source XOR dest +SRCERASE = 4457256 # dest = source AND (NOT dest ) +NOTSRCCOPY = 3342344 # dest = (NOT source) +NOTSRCERASE = 1114278 # dest = (NOT src) AND (NOT dest) +MERGECOPY = 12583114 # dest = (source AND pattern) +MERGEPAINT = 12255782 # dest = (NOT source) OR dest +PATCOPY = 15728673 # dest = pattern +PATPAINT = 16452105 # dest = DPSnoo +PATINVERT = 5898313 # dest = pattern XOR dest +DSTINVERT = 5570569 # dest = (NOT dest) +BLACKNESS = 66 # dest = BLACK +WHITENESS = 16711778 # dest = WHITE + +# hacked and split manually by mhammond. +R2_BLACK = 1 +R2_NOTMERGEPEN = 2 +R2_MASKNOTPEN = 3 +R2_NOTCOPYPEN = 4 +R2_MASKPENNOT = 5 +R2_NOT = 6 +R2_XORPEN = 7 +R2_NOTMASKPEN = 8 +R2_MASKPEN = 9 +R2_NOTXORPEN = 10 +R2_NOP = 11 +R2_MERGENOTPEN = 12 +R2_COPYPEN = 13 +R2_MERGEPENNOT = 14 +R2_MERGEPEN = 15 +R2_WHITE = 16 +R2_LAST = 16 +GDI_ERROR = -1 +ERROR = 0 +NULLREGION = 1 +SIMPLEREGION = 2 +COMPLEXREGION = 3 +RGN_ERROR = ERROR +RGN_AND = 1 +RGN_OR = 2 +RGN_XOR = 3 +RGN_DIFF = 4 +RGN_COPY = 5 +RGN_MIN = RGN_AND +RGN_MAX = RGN_COPY + +## Stretching modes used with Get/SetStretchBltMode +BLACKONWHITE = 1 +WHITEONBLACK = 2 +COLORONCOLOR = 3 +HALFTONE = 4 +MAXSTRETCHBLTMODE = 4 +STRETCH_ANDSCANS = BLACKONWHITE +STRETCH_ORSCANS = WHITEONBLACK +STRETCH_DELETESCANS = COLORONCOLOR +STRETCH_HALFTONE = HALFTONE + +ALTERNATE = 1 +WINDING = 2 +POLYFILL_LAST = 2 + +## flags used with SetLayout +LAYOUT_RTL = 1 +LAYOUT_BTT = 2 +LAYOUT_VBH = 4 +LAYOUT_ORIENTATIONMASK = LAYOUT_RTL | LAYOUT_BTT | LAYOUT_VBH +LAYOUT_BITMAPORIENTATIONPRESERVED = 8 + +TA_NOUPDATECP = 0 +TA_UPDATECP = 1 +TA_LEFT = 0 +TA_RIGHT = 2 +TA_CENTER = 6 +TA_TOP = 0 +TA_BOTTOM = 8 +TA_BASELINE = 24 +TA_MASK = TA_BASELINE + TA_CENTER + TA_UPDATECP +VTA_BASELINE = TA_BASELINE +VTA_LEFT = TA_BOTTOM +VTA_RIGHT = TA_TOP +VTA_CENTER = TA_CENTER +VTA_BOTTOM = TA_RIGHT +VTA_TOP = TA_LEFT +ETO_GRAYED = 1 +ETO_OPAQUE = 2 +ETO_CLIPPED = 4 +ASPECT_FILTERING = 1 +DCB_RESET = 1 +DCB_ACCUMULATE = 2 +DCB_DIRTY = DCB_ACCUMULATE +DCB_SET = DCB_RESET | DCB_ACCUMULATE +DCB_ENABLE = 4 +DCB_DISABLE = 8 +META_SETBKCOLOR = 513 +META_SETBKMODE = 258 +META_SETMAPMODE = 259 +META_SETROP2 = 260 +META_SETRELABS = 261 +META_SETPOLYFILLMODE = 262 +META_SETSTRETCHBLTMODE = 263 +META_SETTEXTCHAREXTRA = 264 +META_SETTEXTCOLOR = 521 +META_SETTEXTJUSTIFICATION = 522 +META_SETWINDOWORG = 523 +META_SETWINDOWEXT = 524 +META_SETVIEWPORTORG = 525 +META_SETVIEWPORTEXT = 526 +META_OFFSETWINDOWORG = 527 +META_SCALEWINDOWEXT = 1040 +META_OFFSETVIEWPORTORG = 529 +META_SCALEVIEWPORTEXT = 1042 +META_LINETO = 531 +META_MOVETO = 532 +META_EXCLUDECLIPRECT = 1045 +META_INTERSECTCLIPRECT = 1046 +META_ARC = 2071 +META_ELLIPSE = 1048 +META_FLOODFILL = 1049 +META_PIE = 2074 +META_RECTANGLE = 1051 +META_ROUNDRECT = 1564 +META_PATBLT = 1565 +META_SAVEDC = 30 +META_SETPIXEL = 1055 +META_OFFSETCLIPRGN = 544 +META_TEXTOUT = 1313 +META_BITBLT = 2338 +META_STRETCHBLT = 2851 +META_POLYGON = 804 +META_POLYLINE = 805 +META_ESCAPE = 1574 +META_RESTOREDC = 295 +META_FILLREGION = 552 +META_FRAMEREGION = 1065 +META_INVERTREGION = 298 +META_PAINTREGION = 299 +META_SELECTCLIPREGION = 300 +META_SELECTOBJECT = 301 +META_SETTEXTALIGN = 302 +META_CHORD = 2096 +META_SETMAPPERFLAGS = 561 +META_EXTTEXTOUT = 2610 +META_SETDIBTODEV = 3379 +META_SELECTPALETTE = 564 +META_REALIZEPALETTE = 53 +META_ANIMATEPALETTE = 1078 +META_SETPALENTRIES = 55 +META_POLYPOLYGON = 1336 +META_RESIZEPALETTE = 313 +META_DIBBITBLT = 2368 +META_DIBSTRETCHBLT = 2881 +META_DIBCREATEPATTERNBRUSH = 322 +META_STRETCHDIB = 3907 +META_EXTFLOODFILL = 1352 +META_DELETEOBJECT = 496 +META_CREATEPALETTE = 247 +META_CREATEPATTERNBRUSH = 505 +META_CREATEPENINDIRECT = 762 +META_CREATEFONTINDIRECT = 763 +META_CREATEBRUSHINDIRECT = 764 +META_CREATEREGION = 1791 +FILE_BEGIN = 0 +FILE_CURRENT = 1 +FILE_END = 2 +FILE_FLAG_WRITE_THROUGH = -2147483648 +FILE_FLAG_OVERLAPPED = 1073741824 +FILE_FLAG_NO_BUFFERING = 536870912 +FILE_FLAG_RANDOM_ACCESS = 268435456 +FILE_FLAG_SEQUENTIAL_SCAN = 134217728 +FILE_FLAG_DELETE_ON_CLOSE = 67108864 +FILE_FLAG_BACKUP_SEMANTICS = 33554432 +FILE_FLAG_POSIX_SEMANTICS = 16777216 +CREATE_NEW = 1 +CREATE_ALWAYS = 2 +OPEN_EXISTING = 3 +OPEN_ALWAYS = 4 +TRUNCATE_EXISTING = 5 +PIPE_ACCESS_INBOUND = 1 +PIPE_ACCESS_OUTBOUND = 2 +PIPE_ACCESS_DUPLEX = 3 +PIPE_CLIENT_END = 0 +PIPE_SERVER_END = 1 +PIPE_WAIT = 0 +PIPE_NOWAIT = 1 +PIPE_READMODE_BYTE = 0 +PIPE_READMODE_MESSAGE = 2 +PIPE_TYPE_BYTE = 0 +PIPE_TYPE_MESSAGE = 4 +PIPE_UNLIMITED_INSTANCES = 255 +SECURITY_CONTEXT_TRACKING = 262144 +SECURITY_EFFECTIVE_ONLY = 524288 +SECURITY_SQOS_PRESENT = 1048576 +SECURITY_VALID_SQOS_FLAGS = 2031616 +DTR_CONTROL_DISABLE = 0 +DTR_CONTROL_ENABLE = 1 +DTR_CONTROL_HANDSHAKE = 2 +RTS_CONTROL_DISABLE = 0 +RTS_CONTROL_ENABLE = 1 +RTS_CONTROL_HANDSHAKE = 2 +RTS_CONTROL_TOGGLE = 3 +GMEM_FIXED = 0 +GMEM_MOVEABLE = 2 +GMEM_NOCOMPACT = 16 +GMEM_NODISCARD = 32 +GMEM_ZEROINIT = 64 +GMEM_MODIFY = 128 +GMEM_DISCARDABLE = 256 +GMEM_NOT_BANKED = 4096 +GMEM_SHARE = 8192 +GMEM_DDESHARE = 8192 +GMEM_NOTIFY = 16384 +GMEM_LOWER = GMEM_NOT_BANKED +GMEM_VALID_FLAGS = 32626 +GMEM_INVALID_HANDLE = 32768 +GHND = GMEM_MOVEABLE | GMEM_ZEROINIT +GPTR = GMEM_FIXED | GMEM_ZEROINIT +GMEM_DISCARDED = 16384 +GMEM_LOCKCOUNT = 255 +LMEM_FIXED = 0 +LMEM_MOVEABLE = 2 +LMEM_NOCOMPACT = 16 +LMEM_NODISCARD = 32 +LMEM_ZEROINIT = 64 +LMEM_MODIFY = 128 +LMEM_DISCARDABLE = 3840 +LMEM_VALID_FLAGS = 3954 +LMEM_INVALID_HANDLE = 32768 +LHND = LMEM_MOVEABLE | LMEM_ZEROINIT +LPTR = LMEM_FIXED | LMEM_ZEROINIT +NONZEROLHND = LMEM_MOVEABLE +NONZEROLPTR = LMEM_FIXED +LMEM_DISCARDED = 16384 +LMEM_LOCKCOUNT = 255 +DEBUG_PROCESS = 1 +DEBUG_ONLY_THIS_PROCESS = 2 +CREATE_SUSPENDED = 4 +DETACHED_PROCESS = 8 +CREATE_NEW_CONSOLE = 16 +NORMAL_PRIORITY_CLASS = 32 +IDLE_PRIORITY_CLASS = 64 +HIGH_PRIORITY_CLASS = 128 +REALTIME_PRIORITY_CLASS = 256 +CREATE_NEW_PROCESS_GROUP = 512 +CREATE_UNICODE_ENVIRONMENT = 1024 +CREATE_SEPARATE_WOW_VDM = 2048 +CREATE_SHARED_WOW_VDM = 4096 +CREATE_DEFAULT_ERROR_MODE = 67108864 +CREATE_NO_WINDOW = 134217728 +PROFILE_USER = 268435456 +PROFILE_KERNEL = 536870912 +PROFILE_SERVER = 1073741824 +THREAD_BASE_PRIORITY_LOWRT = 15 +THREAD_BASE_PRIORITY_MAX = 2 +THREAD_BASE_PRIORITY_MIN = -2 +THREAD_BASE_PRIORITY_IDLE = -15 +THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN +THREAD_PRIORITY_BELOW_NORMAL = THREAD_PRIORITY_LOWEST + 1 +THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX +THREAD_PRIORITY_ABOVE_NORMAL = THREAD_PRIORITY_HIGHEST - 1 +THREAD_PRIORITY_ERROR_RETURN = MAXLONG +THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT +THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE +THREAD_PRIORITY_NORMAL = 0 +THREAD_MODE_BACKGROUND_BEGIN = 0x00010000 +THREAD_MODE_BACKGROUND_END = 0x00020000 + +EXCEPTION_DEBUG_EVENT = 1 +CREATE_THREAD_DEBUG_EVENT = 2 +CREATE_PROCESS_DEBUG_EVENT = 3 +EXIT_THREAD_DEBUG_EVENT = 4 +EXIT_PROCESS_DEBUG_EVENT = 5 +LOAD_DLL_DEBUG_EVENT = 6 +UNLOAD_DLL_DEBUG_EVENT = 7 +OUTPUT_DEBUG_STRING_EVENT = 8 +RIP_EVENT = 9 +DRIVE_UNKNOWN = 0 +DRIVE_NO_ROOT_DIR = 1 +DRIVE_REMOVABLE = 2 +DRIVE_FIXED = 3 +DRIVE_REMOTE = 4 +DRIVE_CDROM = 5 +DRIVE_RAMDISK = 6 +FILE_TYPE_UNKNOWN = 0 +FILE_TYPE_DISK = 1 +FILE_TYPE_CHAR = 2 +FILE_TYPE_PIPE = 3 +FILE_TYPE_REMOTE = 32768 +NOPARITY = 0 +ODDPARITY = 1 +EVENPARITY = 2 +MARKPARITY = 3 +SPACEPARITY = 4 +ONESTOPBIT = 0 +ONE5STOPBITS = 1 +TWOSTOPBITS = 2 +CBR_110 = 110 +CBR_300 = 300 +CBR_600 = 600 +CBR_1200 = 1200 +CBR_2400 = 2400 +CBR_4800 = 4800 +CBR_9600 = 9600 +CBR_14400 = 14400 +CBR_19200 = 19200 +CBR_38400 = 38400 +CBR_56000 = 56000 +CBR_57600 = 57600 +CBR_115200 = 115200 +CBR_128000 = 128000 +CBR_256000 = 256000 +S_QUEUEEMPTY = 0 +S_THRESHOLD = 1 +S_ALLTHRESHOLD = 2 +S_NORMAL = 0 +S_LEGATO = 1 +S_STACCATO = 2 +NMPWAIT_WAIT_FOREVER = -1 +NMPWAIT_NOWAIT = 1 +NMPWAIT_USE_DEFAULT_WAIT = 0 +OF_READ = 0 +OF_WRITE = 1 +OF_READWRITE = 2 +OF_SHARE_COMPAT = 0 +OF_SHARE_EXCLUSIVE = 16 +OF_SHARE_DENY_WRITE = 32 +OF_SHARE_DENY_READ = 48 +OF_SHARE_DENY_NONE = 64 +OF_PARSE = 256 +OF_DELETE = 512 +OF_VERIFY = 1024 +OF_CANCEL = 2048 +OF_CREATE = 4096 +OF_PROMPT = 8192 +OF_EXIST = 16384 +OF_REOPEN = 32768 +OFS_MAXPATHNAME = 128 +MAXINTATOM = 49152 + +# winbase.h +PROCESS_HEAP_REGION = 1 +PROCESS_HEAP_UNCOMMITTED_RANGE = 2 +PROCESS_HEAP_ENTRY_BUSY = 4 +PROCESS_HEAP_ENTRY_MOVEABLE = 16 +PROCESS_HEAP_ENTRY_DDESHARE = 32 +SCS_32BIT_BINARY = 0 +SCS_DOS_BINARY = 1 +SCS_WOW_BINARY = 2 +SCS_PIF_BINARY = 3 +SCS_POSIX_BINARY = 4 +SCS_OS216_BINARY = 5 +SEM_FAILCRITICALERRORS = 1 +SEM_NOGPFAULTERRORBOX = 2 +SEM_NOALIGNMENTFAULTEXCEPT = 4 +SEM_NOOPENFILEERRORBOX = 32768 +LOCKFILE_FAIL_IMMEDIATELY = 1 +LOCKFILE_EXCLUSIVE_LOCK = 2 +HANDLE_FLAG_INHERIT = 1 +HANDLE_FLAG_PROTECT_FROM_CLOSE = 2 +HINSTANCE_ERROR = 32 +GET_TAPE_MEDIA_INFORMATION = 0 +GET_TAPE_DRIVE_INFORMATION = 1 +SET_TAPE_MEDIA_INFORMATION = 0 +SET_TAPE_DRIVE_INFORMATION = 1 +FORMAT_MESSAGE_ALLOCATE_BUFFER = 256 +FORMAT_MESSAGE_IGNORE_INSERTS = 512 +FORMAT_MESSAGE_FROM_STRING = 1024 +FORMAT_MESSAGE_FROM_HMODULE = 2048 +FORMAT_MESSAGE_FROM_SYSTEM = 4096 +FORMAT_MESSAGE_ARGUMENT_ARRAY = 8192 +FORMAT_MESSAGE_MAX_WIDTH_MASK = 255 +BACKUP_INVALID = 0 +BACKUP_DATA = 1 +BACKUP_EA_DATA = 2 +BACKUP_SECURITY_DATA = 3 +BACKUP_ALTERNATE_DATA = 4 +BACKUP_LINK = 5 +BACKUP_PROPERTY_DATA = 6 +BACKUP_OBJECT_ID = 7 +BACKUP_REPARSE_DATA = 8 +BACKUP_SPARSE_BLOCK = 9 + +STREAM_NORMAL_ATTRIBUTE = 0 +STREAM_MODIFIED_WHEN_READ = 1 +STREAM_CONTAINS_SECURITY = 2 +STREAM_CONTAINS_PROPERTIES = 4 +STARTF_USESHOWWINDOW = 1 +STARTF_USESIZE = 2 +STARTF_USEPOSITION = 4 +STARTF_USECOUNTCHARS = 8 +STARTF_USEFILLATTRIBUTE = 16 +STARTF_FORCEONFEEDBACK = 64 +STARTF_FORCEOFFFEEDBACK = 128 +STARTF_USESTDHANDLES = 256 +STARTF_USEHOTKEY = 512 +SHUTDOWN_NORETRY = 1 +DONT_RESOLVE_DLL_REFERENCES = 1 +LOAD_LIBRARY_AS_DATAFILE = 2 +LOAD_WITH_ALTERED_SEARCH_PATH = 8 +DDD_RAW_TARGET_PATH = 1 +DDD_REMOVE_DEFINITION = 2 +DDD_EXACT_MATCH_ON_REMOVE = 4 +MOVEFILE_REPLACE_EXISTING = 1 +MOVEFILE_COPY_ALLOWED = 2 +MOVEFILE_DELAY_UNTIL_REBOOT = 4 +MAX_COMPUTERNAME_LENGTH = 15 +LOGON32_LOGON_INTERACTIVE = 2 +LOGON32_LOGON_NETWORK = 3 +LOGON32_LOGON_BATCH = 4 +LOGON32_LOGON_SERVICE = 5 +LOGON32_LOGON_UNLOCK = 7 +LOGON32_LOGON_NETWORK_CLEARTEXT = 8 +LOGON32_LOGON_NEW_CREDENTIALS = 9 +LOGON32_PROVIDER_DEFAULT = 0 +LOGON32_PROVIDER_WINNT35 = 1 +LOGON32_PROVIDER_WINNT40 = 2 +LOGON32_PROVIDER_WINNT50 = 3 +VER_PLATFORM_WIN32s = 0 +VER_PLATFORM_WIN32_WINDOWS = 1 +VER_PLATFORM_WIN32_NT = 2 +TC_NORMAL = 0 +TC_HARDERR = 1 +TC_GP_TRAP = 2 +TC_SIGNAL = 3 +AC_LINE_OFFLINE = 0 +AC_LINE_ONLINE = 1 +AC_LINE_BACKUP_POWER = 2 +AC_LINE_UNKNOWN = 255 +BATTERY_FLAG_HIGH = 1 +BATTERY_FLAG_LOW = 2 +BATTERY_FLAG_CRITICAL = 4 +BATTERY_FLAG_CHARGING = 8 +BATTERY_FLAG_NO_BATTERY = 128 +BATTERY_FLAG_UNKNOWN = 255 +BATTERY_PERCENTAGE_UNKNOWN = 255 +BATTERY_LIFE_UNKNOWN = -1 + +# Generated by h2py from d:\msdev\include\richedit.h +cchTextLimitDefault = 32767 +WM_CONTEXTMENU = 123 +WM_PRINTCLIENT = 792 +EN_MSGFILTER = 1792 +EN_REQUESTRESIZE = 1793 +EN_SELCHANGE = 1794 +EN_DROPFILES = 1795 +EN_PROTECTED = 1796 +EN_CORRECTTEXT = 1797 +EN_STOPNOUNDO = 1798 +EN_IMECHANGE = 1799 +EN_SAVECLIPBOARD = 1800 +EN_OLEOPFAILED = 1801 +ENM_NONE = 0 +ENM_CHANGE = 1 +ENM_UPDATE = 2 +ENM_SCROLL = 4 +ENM_KEYEVENTS = 65536 +ENM_MOUSEEVENTS = 131072 +ENM_REQUESTRESIZE = 262144 +ENM_SELCHANGE = 524288 +ENM_DROPFILES = 1048576 +ENM_PROTECTED = 2097152 +ENM_CORRECTTEXT = 4194304 +ENM_IMECHANGE = 8388608 +ES_SAVESEL = 32768 +ES_SUNKEN = 16384 +ES_DISABLENOSCROLL = 8192 +ES_SELECTIONBAR = 16777216 +ES_EX_NOCALLOLEINIT = 16777216 +ES_VERTICAL = 4194304 +ES_NOIME = 524288 +ES_SELFIME = 262144 +ECO_AUTOWORDSELECTION = 1 +ECO_AUTOVSCROLL = 64 +ECO_AUTOHSCROLL = 128 +ECO_NOHIDESEL = 256 +ECO_READONLY = 2048 +ECO_WANTRETURN = 4096 +ECO_SAVESEL = 32768 +ECO_SELECTIONBAR = 16777216 +ECO_VERTICAL = 4194304 +ECOOP_SET = 1 +ECOOP_OR = 2 +ECOOP_AND = 3 +ECOOP_XOR = 4 +WB_CLASSIFY = 3 +WB_MOVEWORDLEFT = 4 +WB_MOVEWORDRIGHT = 5 +WB_LEFTBREAK = 6 +WB_RIGHTBREAK = 7 +WB_MOVEWORDPREV = 4 +WB_MOVEWORDNEXT = 5 +WB_PREVBREAK = 6 +WB_NEXTBREAK = 7 +PC_FOLLOWING = 1 +PC_LEADING = 2 +PC_OVERFLOW = 3 +PC_DELIMITER = 4 +WBF_WORDWRAP = 16 +WBF_WORDBREAK = 32 +WBF_OVERFLOW = 64 +WBF_LEVEL1 = 128 +WBF_LEVEL2 = 256 +WBF_CUSTOM = 512 +CFM_BOLD = 1 +CFM_ITALIC = 2 +CFM_UNDERLINE = 4 +CFM_STRIKEOUT = 8 +CFM_PROTECTED = 16 +CFM_SIZE = -2147483648 +CFM_COLOR = 1073741824 +CFM_FACE = 536870912 +CFM_OFFSET = 268435456 +CFM_CHARSET = 134217728 +CFE_BOLD = 1 +CFE_ITALIC = 2 +CFE_UNDERLINE = 4 +CFE_STRIKEOUT = 8 +CFE_PROTECTED = 16 +CFE_AUTOCOLOR = 1073741824 +yHeightCharPtsMost = 1638 +SCF_SELECTION = 1 +SCF_WORD = 2 +SF_TEXT = 1 +SF_RTF = 2 +SF_RTFNOOBJS = 3 +SF_TEXTIZED = 4 +SFF_SELECTION = 32768 +SFF_PLAINRTF = 16384 +MAX_TAB_STOPS = 32 +lDefaultTab = 720 +PFM_STARTINDENT = 1 +PFM_RIGHTINDENT = 2 +PFM_OFFSET = 4 +PFM_ALIGNMENT = 8 +PFM_TABSTOPS = 16 +PFM_NUMBERING = 32 +PFM_OFFSETINDENT = -2147483648 +PFN_BULLET = 1 +PFA_LEFT = 1 +PFA_RIGHT = 2 +PFA_CENTER = 3 +WM_NOTIFY = 78 +SEL_EMPTY = 0 +SEL_TEXT = 1 +SEL_OBJECT = 2 +SEL_MULTICHAR = 4 +SEL_MULTIOBJECT = 8 +OLEOP_DOVERB = 1 +CF_RTF = "Rich Text Format" +CF_RTFNOOBJS = "Rich Text Format Without Objects" +CF_RETEXTOBJ = "RichEdit Text and Objects" + +# From wincon.h +RIGHT_ALT_PRESSED = 1 # the right alt key is pressed. +LEFT_ALT_PRESSED = 2 # the left alt key is pressed. +RIGHT_CTRL_PRESSED = 4 # the right ctrl key is pressed. +LEFT_CTRL_PRESSED = 8 # the left ctrl key is pressed. +SHIFT_PRESSED = 16 # the shift key is pressed. +NUMLOCK_ON = 32 # the numlock light is on. +SCROLLLOCK_ON = 64 # the scrolllock light is on. +CAPSLOCK_ON = 128 # the capslock light is on. +ENHANCED_KEY = 256 # the key is enhanced. +NLS_DBCSCHAR = 65536 # DBCS for JPN: SBCS/DBCS mode. +NLS_ALPHANUMERIC = 0 # DBCS for JPN: Alphanumeric mode. +NLS_KATAKANA = 131072 # DBCS for JPN: Katakana mode. +NLS_HIRAGANA = 262144 # DBCS for JPN: Hiragana mode. +NLS_ROMAN = 4194304 # DBCS for JPN: Roman/Noroman mode. +NLS_IME_CONVERSION = 8388608 # DBCS for JPN: IME conversion. +NLS_IME_DISABLE = 536870912 # DBCS for JPN: IME enable/disable. + +FROM_LEFT_1ST_BUTTON_PRESSED = 1 +RIGHTMOST_BUTTON_PRESSED = 2 +FROM_LEFT_2ND_BUTTON_PRESSED = 4 +FROM_LEFT_3RD_BUTTON_PRESSED = 8 +FROM_LEFT_4TH_BUTTON_PRESSED = 16 + +CTRL_C_EVENT = 0 +CTRL_BREAK_EVENT = 1 +CTRL_CLOSE_EVENT = 2 +CTRL_LOGOFF_EVENT = 5 +CTRL_SHUTDOWN_EVENT = 6 + +MOUSE_MOVED = 1 +DOUBLE_CLICK = 2 +MOUSE_WHEELED = 4 + +# property sheet window messages from prsht.h +PSM_SETCURSEL = WM_USER + 101 +PSM_REMOVEPAGE = WM_USER + 102 +PSM_ADDPAGE = WM_USER + 103 +PSM_CHANGED = WM_USER + 104 +PSM_RESTARTWINDOWS = WM_USER + 105 +PSM_REBOOTSYSTEM = WM_USER + 106 +PSM_CANCELTOCLOSE = WM_USER + 107 +PSM_QUERYSIBLINGS = WM_USER + 108 +PSM_UNCHANGED = WM_USER + 109 +PSM_APPLY = WM_USER + 110 +PSM_SETTITLEA = WM_USER + 111 +PSM_SETTITLEW = WM_USER + 120 +PSM_SETWIZBUTTONS = WM_USER + 112 +PSM_PRESSBUTTON = WM_USER + 113 +PSM_SETCURSELID = WM_USER + 114 +PSM_SETFINISHTEXTA = WM_USER + 115 +PSM_SETFINISHTEXTW = WM_USER + 121 +PSM_GETTABCONTROL = WM_USER + 116 +PSM_ISDIALOGMESSAGE = WM_USER + 117 +PSM_GETCURRENTPAGEHWND = WM_USER + 118 +PSM_INSERTPAGE = WM_USER + 119 +PSM_SETHEADERTITLEA = WM_USER + 125 +PSM_SETHEADERTITLEW = WM_USER + 126 +PSM_SETHEADERSUBTITLEA = WM_USER + 127 +PSM_SETHEADERSUBTITLEW = WM_USER + 128 +PSM_HWNDTOINDEX = WM_USER + 129 +PSM_INDEXTOHWND = WM_USER + 130 +PSM_PAGETOINDEX = WM_USER + 131 +PSM_INDEXTOPAGE = WM_USER + 132 +PSM_IDTOINDEX = WM_USER + 133 +PSM_INDEXTOID = WM_USER + 134 +PSM_GETRESULT = WM_USER + 135 +PSM_RECALCPAGESIZES = WM_USER + 136 + +# GetUserNameEx/GetComputerNameEx +NameUnknown = 0 +NameFullyQualifiedDN = 1 +NameSamCompatible = 2 +NameDisplay = 3 +NameUniqueId = 6 +NameCanonical = 7 +NameUserPrincipal = 8 +NameCanonicalEx = 9 +NameServicePrincipal = 10 +NameDnsDomain = 12 + +ComputerNameNetBIOS = 0 +ComputerNameDnsHostname = 1 +ComputerNameDnsDomain = 2 +ComputerNameDnsFullyQualified = 3 +ComputerNamePhysicalNetBIOS = 4 +ComputerNamePhysicalDnsHostname = 5 +ComputerNamePhysicalDnsDomain = 6 +ComputerNamePhysicalDnsFullyQualified = 7 + +LWA_COLORKEY = 0x00000001 +LWA_ALPHA = 0x00000002 +ULW_COLORKEY = 0x00000001 +ULW_ALPHA = 0x00000002 +ULW_OPAQUE = 0x00000004 + +# WinDef.h +TRUE = 1 +FALSE = 0 +MAX_PATH = 260 +# WinGDI.h +AC_SRC_OVER = 0 +AC_SRC_ALPHA = 1 +GRADIENT_FILL_RECT_H = 0 +GRADIENT_FILL_RECT_V = 1 +GRADIENT_FILL_TRIANGLE = 2 +GRADIENT_FILL_OP_FLAG = 255 + +## flags used with Get/SetSystemFileCacheSize +MM_WORKING_SET_MAX_HARD_ENABLE = 1 +MM_WORKING_SET_MAX_HARD_DISABLE = 2 +MM_WORKING_SET_MIN_HARD_ENABLE = 4 +MM_WORKING_SET_MIN_HARD_DISABLE = 8 + +## Flags for GetFinalPathNameByHandle +VOLUME_NAME_DOS = 0 +VOLUME_NAME_GUID = 1 +VOLUME_NAME_NT = 2 +VOLUME_NAME_NONE = 4 +FILE_NAME_NORMALIZED = 0 +FILE_NAME_OPENED = 8 + +DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000 +DEVICE_NOTIFY_SERVICE_HANDLE = 0x00000001 + +# From Dbt.h +# Generated by h2py from Dbt.h +WM_DEVICECHANGE = 0x0219 +BSF_QUERY = 0x00000001 +BSF_IGNORECURRENTTASK = 0x00000002 +BSF_FLUSHDISK = 0x00000004 +BSF_NOHANG = 0x00000008 +BSF_POSTMESSAGE = 0x00000010 +BSF_FORCEIFHUNG = 0x00000020 +BSF_NOTIMEOUTIFNOTHUNG = 0x00000040 +BSF_MSGSRV32ISOK = -2147483648 +BSF_MSGSRV32ISOK_BIT = 31 +BSM_ALLCOMPONENTS = 0x00000000 +BSM_VXDS = 0x00000001 +BSM_NETDRIVER = 0x00000002 +BSM_INSTALLABLEDRIVERS = 0x00000004 +BSM_APPLICATIONS = 0x00000008 +DBT_APPYBEGIN = 0x0000 +DBT_APPYEND = 0x0001 +DBT_DEVNODES_CHANGED = 0x0007 +DBT_QUERYCHANGECONFIG = 0x0017 +DBT_CONFIGCHANGED = 0x0018 +DBT_CONFIGCHANGECANCELED = 0x0019 +DBT_MONITORCHANGE = 0x001B +DBT_SHELLLOGGEDON = 0x0020 +DBT_CONFIGMGAPI32 = 0x0022 +DBT_VXDINITCOMPLETE = 0x0023 +DBT_VOLLOCKQUERYLOCK = 0x8041 +DBT_VOLLOCKLOCKTAKEN = 0x8042 +DBT_VOLLOCKLOCKFAILED = 0x8043 +DBT_VOLLOCKQUERYUNLOCK = 0x8044 +DBT_VOLLOCKLOCKRELEASED = 0x8045 +DBT_VOLLOCKUNLOCKFAILED = 0x8046 +LOCKP_ALLOW_WRITES = 0x01 +LOCKP_FAIL_WRITES = 0x00 +LOCKP_FAIL_MEM_MAPPING = 0x02 +LOCKP_ALLOW_MEM_MAPPING = 0x00 +LOCKP_USER_MASK = 0x03 +LOCKP_LOCK_FOR_FORMAT = 0x04 +LOCKF_LOGICAL_LOCK = 0x00 +LOCKF_PHYSICAL_LOCK = 0x01 +DBT_NO_DISK_SPACE = 0x0047 +DBT_LOW_DISK_SPACE = 0x0048 +DBT_CONFIGMGPRIVATE = 0x7FFF +DBT_DEVICEARRIVAL = 0x8000 +DBT_DEVICEQUERYREMOVE = 0x8001 +DBT_DEVICEQUERYREMOVEFAILED = 0x8002 +DBT_DEVICEREMOVEPENDING = 0x8003 +DBT_DEVICEREMOVECOMPLETE = 0x8004 +DBT_DEVICETYPESPECIFIC = 0x8005 +DBT_CUSTOMEVENT = 0x8006 +DBT_DEVTYP_OEM = 0x00000000 +DBT_DEVTYP_DEVNODE = 0x00000001 +DBT_DEVTYP_VOLUME = 0x00000002 +DBT_DEVTYP_PORT = 0x00000003 +DBT_DEVTYP_NET = 0x00000004 +DBT_DEVTYP_DEVICEINTERFACE = 0x00000005 +DBT_DEVTYP_HANDLE = 0x00000006 +DBTF_MEDIA = 0x0001 +DBTF_NET = 0x0002 +DBTF_RESOURCE = 0x00000001 +DBTF_XPORT = 0x00000002 +DBTF_SLOWNET = 0x00000004 +DBT_VPOWERDAPI = 0x8100 +DBT_USERDEFINED = 0xFFFF diff --git a/MLPY/Lib/site-packages/win32/lib/win32cryptcon.py b/MLPY/Lib/site-packages/win32/lib/win32cryptcon.py new file mode 100644 index 0000000000000000000000000000000000000000..8d71996a08d5df3b7cd031971843452b89ce5124 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32cryptcon.py @@ -0,0 +1,1925 @@ +# Generated by h2py from WinCrypt.h +def GET_ALG_CLASS(x): + return x & (7 << 13) + + +def GET_ALG_TYPE(x): + return x & (15 << 9) + + +def GET_ALG_SID(x): + return x & (511) + + +ALG_CLASS_ANY = 0 +ALG_CLASS_SIGNATURE = 1 << 13 +ALG_CLASS_MSG_ENCRYPT = 2 << 13 +ALG_CLASS_DATA_ENCRYPT = 3 << 13 +ALG_CLASS_HASH = 4 << 13 +ALG_CLASS_KEY_EXCHANGE = 5 << 13 +ALG_CLASS_ALL = 7 << 13 +ALG_TYPE_ANY = 0 +ALG_TYPE_DSS = 1 << 9 +ALG_TYPE_RSA = 2 << 9 +ALG_TYPE_BLOCK = 3 << 9 +ALG_TYPE_STREAM = 4 << 9 +ALG_TYPE_DH = 5 << 9 +ALG_TYPE_SECURECHANNEL = 6 << 9 +ALG_SID_ANY = 0 +ALG_SID_RSA_ANY = 0 +ALG_SID_RSA_PKCS = 1 +ALG_SID_RSA_MSATWORK = 2 +ALG_SID_RSA_ENTRUST = 3 +ALG_SID_RSA_PGP = 4 +ALG_SID_DSS_ANY = 0 +ALG_SID_DSS_PKCS = 1 +ALG_SID_DSS_DMS = 2 +ALG_SID_DES = 1 +ALG_SID_3DES = 3 +ALG_SID_DESX = 4 +ALG_SID_IDEA = 5 +ALG_SID_CAST = 6 +ALG_SID_SAFERSK64 = 7 +ALG_SID_SAFERSK128 = 8 +ALG_SID_3DES_112 = 9 +ALG_SID_CYLINK_MEK = 12 +ALG_SID_RC5 = 13 +ALG_SID_AES_128 = 14 +ALG_SID_AES_192 = 15 +ALG_SID_AES_256 = 16 +ALG_SID_AES = 17 +ALG_SID_SKIPJACK = 10 +ALG_SID_TEK = 11 +CRYPT_MODE_CBCI = 6 +CRYPT_MODE_CFBP = 7 +CRYPT_MODE_OFBP = 8 +CRYPT_MODE_CBCOFM = 9 +CRYPT_MODE_CBCOFMI = 10 +ALG_SID_RC2 = 2 +ALG_SID_RC4 = 1 +ALG_SID_SEAL = 2 +ALG_SID_DH_SANDF = 1 +ALG_SID_DH_EPHEM = 2 +ALG_SID_AGREED_KEY_ANY = 3 +ALG_SID_KEA = 4 +ALG_SID_MD2 = 1 +ALG_SID_MD4 = 2 +ALG_SID_MD5 = 3 +ALG_SID_SHA = 4 +ALG_SID_SHA1 = 4 +ALG_SID_MAC = 5 +ALG_SID_RIPEMD = 6 +ALG_SID_RIPEMD160 = 7 +ALG_SID_SSL3SHAMD5 = 8 +ALG_SID_HMAC = 9 +ALG_SID_TLS1PRF = 10 +ALG_SID_HASH_REPLACE_OWF = 11 +ALG_SID_SHA_256 = 12 +ALG_SID_SHA_384 = 13 +ALG_SID_SHA_512 = 14 +ALG_SID_SSL3_MASTER = 1 +ALG_SID_SCHANNEL_MASTER_HASH = 2 +ALG_SID_SCHANNEL_MAC_KEY = 3 +ALG_SID_PCT1_MASTER = 4 +ALG_SID_SSL2_MASTER = 5 +ALG_SID_TLS1_MASTER = 6 +ALG_SID_SCHANNEL_ENC_KEY = 7 +ALG_SID_EXAMPLE = 80 +CALG_MD2 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD2 +CALG_MD4 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4 +CALG_MD5 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5 +CALG_SHA = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA +CALG_SHA1 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1 +CALG_MAC = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MAC +CALG_RSA_SIGN = ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY +CALG_DSS_SIGN = ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY +CALG_NO_SIGN = ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | ALG_SID_ANY +CALG_RSA_KEYX = ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | ALG_SID_RSA_ANY +CALG_DES = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_DES +CALG_3DES_112 = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES_112 +CALG_3DES = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES +CALG_DESX = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_DESX +CALG_RC2 = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_RC2 +CALG_RC4 = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_RC4 +CALG_SEAL = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_SEAL +CALG_DH_SF = ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_SANDF +CALG_DH_EPHEM = ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_EPHEM +CALG_AGREEDKEY_ANY = ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_AGREED_KEY_ANY +CALG_KEA_KEYX = ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_KEA +CALG_HUGHES_MD5 = ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_MD5 +CALG_SKIPJACK = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_SKIPJACK +CALG_TEK = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_TEK +CALG_CYLINK_MEK = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_CYLINK_MEK +CALG_SSL3_SHAMD5 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5 +CALG_SSL3_MASTER = ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SSL3_MASTER +CALG_SCHANNEL_MASTER_HASH = ( + ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_MASTER_HASH +) +CALG_SCHANNEL_MAC_KEY = ( + ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_MAC_KEY +) +CALG_SCHANNEL_ENC_KEY = ( + ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_ENC_KEY +) +CALG_PCT1_MASTER = ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_PCT1_MASTER +CALG_SSL2_MASTER = ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SSL2_MASTER +CALG_TLS1_MASTER = ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_TLS1_MASTER +CALG_RC5 = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_RC5 +CALG_HMAC = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC +CALG_TLS1PRF = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_TLS1PRF +CALG_HASH_REPLACE_OWF = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HASH_REPLACE_OWF +CALG_AES_128 = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_128 +CALG_AES_192 = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_192 +CALG_AES_256 = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_256 +CALG_AES = ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES +CALG_SHA_256 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256 +CALG_SHA_384 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384 +CALG_SHA_512 = ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512 +CRYPT_VERIFYCONTEXT = -268435456 +CRYPT_NEWKEYSET = 0x00000008 +CRYPT_DELETEKEYSET = 0x00000010 +CRYPT_MACHINE_KEYSET = 0x00000020 +CRYPT_SILENT = 0x00000040 +CRYPT_EXPORTABLE = 0x00000001 +CRYPT_USER_PROTECTED = 0x00000002 +CRYPT_CREATE_SALT = 0x00000004 +CRYPT_UPDATE_KEY = 0x00000008 +CRYPT_NO_SALT = 0x00000010 +CRYPT_PREGEN = 0x00000040 +CRYPT_RECIPIENT = 0x00000010 +CRYPT_INITIATOR = 0x00000040 +CRYPT_ONLINE = 0x00000080 +CRYPT_SF = 0x00000100 +CRYPT_CREATE_IV = 0x00000200 +CRYPT_KEK = 0x00000400 +CRYPT_DATA_KEY = 0x00000800 +CRYPT_VOLATILE = 0x00001000 +CRYPT_SGCKEY = 0x00002000 +CRYPT_ARCHIVABLE = 0x00004000 +RSA1024BIT_KEY = 0x04000000 +CRYPT_SERVER = 0x00000400 +KEY_LENGTH_MASK = -65536 +CRYPT_Y_ONLY = 0x00000001 +CRYPT_SSL2_FALLBACK = 0x00000002 +CRYPT_DESTROYKEY = 0x00000004 +CRYPT_OAEP = 0x00000040 +CRYPT_BLOB_VER3 = 0x00000080 +CRYPT_IPSEC_HMAC_KEY = 0x00000100 +CRYPT_DECRYPT_RSA_NO_PADDING_CHECK = 0x00000020 +CRYPT_SECRETDIGEST = 0x00000001 +CRYPT_OWF_REPL_LM_HASH = 0x00000001 +CRYPT_LITTLE_ENDIAN = 0x00000001 +CRYPT_NOHASHOID = 0x00000001 +CRYPT_TYPE2_FORMAT = 0x00000002 +CRYPT_X931_FORMAT = 0x00000004 +CRYPT_MACHINE_DEFAULT = 0x00000001 +CRYPT_USER_DEFAULT = 0x00000002 +CRYPT_DELETE_DEFAULT = 0x00000004 +SIMPLEBLOB = 0x1 +PUBLICKEYBLOB = 0x6 +PRIVATEKEYBLOB = 0x7 +PLAINTEXTKEYBLOB = 0x8 +OPAQUEKEYBLOB = 0x9 +PUBLICKEYBLOBEX = 0xA +SYMMETRICWRAPKEYBLOB = 0xB +AT_KEYEXCHANGE = 1 +AT_SIGNATURE = 2 +CRYPT_USERDATA = 1 +KP_IV = 1 +KP_SALT = 2 +KP_PADDING = 3 +KP_MODE = 4 +KP_MODE_BITS = 5 +KP_PERMISSIONS = 6 +KP_ALGID = 7 +KP_BLOCKLEN = 8 +KP_KEYLEN = 9 +KP_SALT_EX = 10 +KP_P = 11 +KP_G = 12 +KP_Q = 13 +KP_X = 14 +KP_Y = 15 +KP_RA = 16 +KP_RB = 17 +KP_INFO = 18 +KP_EFFECTIVE_KEYLEN = 19 +KP_SCHANNEL_ALG = 20 +KP_CLIENT_RANDOM = 21 +KP_SERVER_RANDOM = 22 +KP_RP = 23 +KP_PRECOMP_MD5 = 24 +KP_PRECOMP_SHA = 25 +KP_CERTIFICATE = 26 +KP_CLEAR_KEY = 27 +KP_PUB_EX_LEN = 28 +KP_PUB_EX_VAL = 29 +KP_KEYVAL = 30 +KP_ADMIN_PIN = 31 +KP_KEYEXCHANGE_PIN = 32 +KP_SIGNATURE_PIN = 33 +KP_PREHASH = 34 +KP_ROUNDS = 35 +KP_OAEP_PARAMS = 36 +KP_CMS_KEY_INFO = 37 +KP_CMS_DH_KEY_INFO = 38 +KP_PUB_PARAMS = 39 +KP_VERIFY_PARAMS = 40 +KP_HIGHEST_VERSION = 41 +KP_GET_USE_COUNT = 42 +PKCS5_PADDING = 1 +RANDOM_PADDING = 2 +ZERO_PADDING = 3 +CRYPT_MODE_CBC = 1 +CRYPT_MODE_ECB = 2 +CRYPT_MODE_OFB = 3 +CRYPT_MODE_CFB = 4 +CRYPT_MODE_CTS = 5 +CRYPT_ENCRYPT = 0x0001 +CRYPT_DECRYPT = 0x0002 +CRYPT_EXPORT = 0x0004 +CRYPT_READ = 0x0008 +CRYPT_WRITE = 0x0010 +CRYPT_MAC = 0x0020 +CRYPT_EXPORT_KEY = 0x0040 +CRYPT_IMPORT_KEY = 0x0080 +CRYPT_ARCHIVE = 0x0100 +HP_ALGID = 0x0001 +HP_HASHVAL = 0x0002 +HP_HASHSIZE = 0x0004 +HP_HMAC_INFO = 0x0005 +HP_TLS1PRF_LABEL = 0x0006 +HP_TLS1PRF_SEED = 0x0007 + +CRYPT_FAILED = 0 +CRYPT_SUCCEED = 1 + + +def RCRYPT_SUCCEEDED(rt): + return (rt) == CRYPT_SUCCEED + + +def RCRYPT_FAILED(rt): + return (rt) == CRYPT_FAILED + + +PP_ENUMALGS = 1 +PP_ENUMCONTAINERS = 2 +PP_IMPTYPE = 3 +PP_NAME = 4 +PP_VERSION = 5 +PP_CONTAINER = 6 +PP_CHANGE_PASSWORD = 7 +PP_KEYSET_SEC_DESCR = 8 +PP_CERTCHAIN = 9 +PP_KEY_TYPE_SUBTYPE = 10 +PP_PROVTYPE = 16 +PP_KEYSTORAGE = 17 +PP_APPLI_CERT = 18 +PP_SYM_KEYSIZE = 19 +PP_SESSION_KEYSIZE = 20 +PP_UI_PROMPT = 21 +PP_ENUMALGS_EX = 22 +PP_ENUMMANDROOTS = 25 +PP_ENUMELECTROOTS = 26 +PP_KEYSET_TYPE = 27 +PP_ADMIN_PIN = 31 +PP_KEYEXCHANGE_PIN = 32 +PP_SIGNATURE_PIN = 33 +PP_SIG_KEYSIZE_INC = 34 +PP_KEYX_KEYSIZE_INC = 35 +PP_UNIQUE_CONTAINER = 36 +PP_SGC_INFO = 37 +PP_USE_HARDWARE_RNG = 38 +PP_KEYSPEC = 39 +PP_ENUMEX_SIGNING_PROT = 40 +PP_CRYPT_COUNT_KEY_USE = 41 +CRYPT_FIRST = 1 +CRYPT_NEXT = 2 +CRYPT_SGC_ENUM = 4 +CRYPT_IMPL_HARDWARE = 1 +CRYPT_IMPL_SOFTWARE = 2 +CRYPT_IMPL_MIXED = 3 +CRYPT_IMPL_UNKNOWN = 4 +CRYPT_IMPL_REMOVABLE = 8 +CRYPT_SEC_DESCR = 0x00000001 +CRYPT_PSTORE = 0x00000002 +CRYPT_UI_PROMPT = 0x00000004 +CRYPT_FLAG_PCT1 = 0x0001 +CRYPT_FLAG_SSL2 = 0x0002 +CRYPT_FLAG_SSL3 = 0x0004 +CRYPT_FLAG_TLS1 = 0x0008 +CRYPT_FLAG_IPSEC = 0x0010 +CRYPT_FLAG_SIGNING = 0x0020 +CRYPT_SGC = 0x0001 +CRYPT_FASTSGC = 0x0002 +PP_CLIENT_HWND = 1 +PP_CONTEXT_INFO = 11 +PP_KEYEXCHANGE_KEYSIZE = 12 +PP_SIGNATURE_KEYSIZE = 13 +PP_KEYEXCHANGE_ALG = 14 +PP_SIGNATURE_ALG = 15 +PP_DELETEKEY = 24 +PROV_RSA_FULL = 1 +PROV_RSA_SIG = 2 +PROV_DSS = 3 +PROV_FORTEZZA = 4 +PROV_MS_EXCHANGE = 5 +PROV_SSL = 6 +PROV_RSA_SCHANNEL = 12 +PROV_DSS_DH = 13 +PROV_EC_ECDSA_SIG = 14 +PROV_EC_ECNRA_SIG = 15 +PROV_EC_ECDSA_FULL = 16 +PROV_EC_ECNRA_FULL = 17 +PROV_DH_SCHANNEL = 18 +PROV_SPYRUS_LYNKS = 20 +PROV_RNG = 21 +PROV_INTEL_SEC = 22 +PROV_REPLACE_OWF = 23 +PROV_RSA_AES = 24 +MS_DEF_PROV_A = "Microsoft Base Cryptographic Provider v1.0" +MS_DEF_PROV = MS_DEF_PROV_A +MS_ENHANCED_PROV_A = "Microsoft Enhanced Cryptographic Provider v1.0" +MS_ENHANCED_PROV = MS_ENHANCED_PROV_A +MS_STRONG_PROV_A = "Microsoft Strong Cryptographic Provider" +MS_STRONG_PROV = MS_STRONG_PROV_A +MS_DEF_RSA_SIG_PROV_A = "Microsoft RSA Signature Cryptographic Provider" +MS_DEF_RSA_SIG_PROV = MS_DEF_RSA_SIG_PROV_A +MS_DEF_RSA_SCHANNEL_PROV_A = "Microsoft RSA SChannel Cryptographic Provider" +MS_DEF_RSA_SCHANNEL_PROV = MS_DEF_RSA_SCHANNEL_PROV_A +MS_DEF_DSS_PROV_A = "Microsoft Base DSS Cryptographic Provider" +MS_DEF_DSS_PROV = MS_DEF_DSS_PROV_A +MS_DEF_DSS_DH_PROV_A = "Microsoft Base DSS and Diffie-Hellman Cryptographic Provider" +MS_DEF_DSS_DH_PROV = MS_DEF_DSS_DH_PROV_A +MS_ENH_DSS_DH_PROV_A = ( + "Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider" +) +MS_ENH_DSS_DH_PROV = MS_ENH_DSS_DH_PROV_A +MS_DEF_DH_SCHANNEL_PROV_A = "Microsoft DH SChannel Cryptographic Provider" +MS_DEF_DH_SCHANNEL_PROV = MS_DEF_DH_SCHANNEL_PROV_A +MS_SCARD_PROV_A = "Microsoft Base Smart Card Crypto Provider" +MS_SCARD_PROV = MS_SCARD_PROV_A +MS_ENH_RSA_AES_PROV_A = "Microsoft Enhanced RSA and AES Cryptographic Provider" +MS_ENH_RSA_AES_PROV = MS_ENH_RSA_AES_PROV_A +MAXUIDLEN = 64 +EXPO_OFFLOAD_REG_VALUE = "ExpoOffload" +EXPO_OFFLOAD_FUNC_NAME = "OffloadModExpo" +szKEY_CRYPTOAPI_PRIVATE_KEY_OPTIONS = "Software\\Policies\\Microsoft\\Cryptography" +szFORCE_KEY_PROTECTION = "ForceKeyProtection" +dwFORCE_KEY_PROTECTION_DISABLED = 0x0 +dwFORCE_KEY_PROTECTION_USER_SELECT = 0x1 +dwFORCE_KEY_PROTECTION_HIGH = 0x2 +szKEY_CACHE_ENABLED = "CachePrivateKeys" +szKEY_CACHE_SECONDS = "PrivateKeyLifetimeSeconds" +CUR_BLOB_VERSION = 2 +SCHANNEL_MAC_KEY = 0x00000000 +SCHANNEL_ENC_KEY = 0x00000001 +INTERNATIONAL_USAGE = 0x00000001 +szOID_RSA = "1.2.840.113549" +szOID_PKCS = "1.2.840.113549.1" +szOID_RSA_HASH = "1.2.840.113549.2" +szOID_RSA_ENCRYPT = "1.2.840.113549.3" +szOID_PKCS_1 = "1.2.840.113549.1.1" +szOID_PKCS_2 = "1.2.840.113549.1.2" +szOID_PKCS_3 = "1.2.840.113549.1.3" +szOID_PKCS_4 = "1.2.840.113549.1.4" +szOID_PKCS_5 = "1.2.840.113549.1.5" +szOID_PKCS_6 = "1.2.840.113549.1.6" +szOID_PKCS_7 = "1.2.840.113549.1.7" +szOID_PKCS_8 = "1.2.840.113549.1.8" +szOID_PKCS_9 = "1.2.840.113549.1.9" +szOID_PKCS_10 = "1.2.840.113549.1.10" +szOID_PKCS_12 = "1.2.840.113549.1.12" +szOID_RSA_RSA = "1.2.840.113549.1.1.1" +szOID_RSA_MD2RSA = "1.2.840.113549.1.1.2" +szOID_RSA_MD4RSA = "1.2.840.113549.1.1.3" +szOID_RSA_MD5RSA = "1.2.840.113549.1.1.4" +szOID_RSA_SHA1RSA = "1.2.840.113549.1.1.5" +szOID_RSA_SETOAEP_RSA = "1.2.840.113549.1.1.6" +szOID_RSA_DH = "1.2.840.113549.1.3.1" +szOID_RSA_data = "1.2.840.113549.1.7.1" +szOID_RSA_signedData = "1.2.840.113549.1.7.2" +szOID_RSA_envelopedData = "1.2.840.113549.1.7.3" +szOID_RSA_signEnvData = "1.2.840.113549.1.7.4" +szOID_RSA_digestedData = "1.2.840.113549.1.7.5" +szOID_RSA_hashedData = "1.2.840.113549.1.7.5" +szOID_RSA_encryptedData = "1.2.840.113549.1.7.6" +szOID_RSA_emailAddr = "1.2.840.113549.1.9.1" +szOID_RSA_unstructName = "1.2.840.113549.1.9.2" +szOID_RSA_contentType = "1.2.840.113549.1.9.3" +szOID_RSA_messageDigest = "1.2.840.113549.1.9.4" +szOID_RSA_signingTime = "1.2.840.113549.1.9.5" +szOID_RSA_counterSign = "1.2.840.113549.1.9.6" +szOID_RSA_challengePwd = "1.2.840.113549.1.9.7" +szOID_RSA_unstructAddr = "1.2.840.113549.1.9.8" +szOID_RSA_extCertAttrs = "1.2.840.113549.1.9.9" +szOID_RSA_certExtensions = "1.2.840.113549.1.9.14" +szOID_RSA_SMIMECapabilities = "1.2.840.113549.1.9.15" +szOID_RSA_preferSignedData = "1.2.840.113549.1.9.15.1" +szOID_RSA_SMIMEalg = "1.2.840.113549.1.9.16.3" +szOID_RSA_SMIMEalgESDH = "1.2.840.113549.1.9.16.3.5" +szOID_RSA_SMIMEalgCMS3DESwrap = "1.2.840.113549.1.9.16.3.6" +szOID_RSA_SMIMEalgCMSRC2wrap = "1.2.840.113549.1.9.16.3.7" +szOID_RSA_MD2 = "1.2.840.113549.2.2" +szOID_RSA_MD4 = "1.2.840.113549.2.4" +szOID_RSA_MD5 = "1.2.840.113549.2.5" +szOID_RSA_RC2CBC = "1.2.840.113549.3.2" +szOID_RSA_RC4 = "1.2.840.113549.3.4" +szOID_RSA_DES_EDE3_CBC = "1.2.840.113549.3.7" +szOID_RSA_RC5_CBCPad = "1.2.840.113549.3.9" +szOID_ANSI_X942 = "1.2.840.10046" +szOID_ANSI_X942_DH = "1.2.840.10046.2.1" +szOID_X957 = "1.2.840.10040" +szOID_X957_DSA = "1.2.840.10040.4.1" +szOID_X957_SHA1DSA = "1.2.840.10040.4.3" +szOID_DS = "2.5" +szOID_DSALG = "2.5.8" +szOID_DSALG_CRPT = "2.5.8.1" +szOID_DSALG_HASH = "2.5.8.2" +szOID_DSALG_SIGN = "2.5.8.3" +szOID_DSALG_RSA = "2.5.8.1.1" +szOID_OIW = "1.3.14" +szOID_OIWSEC = "1.3.14.3.2" +szOID_OIWSEC_md4RSA = "1.3.14.3.2.2" +szOID_OIWSEC_md5RSA = "1.3.14.3.2.3" +szOID_OIWSEC_md4RSA2 = "1.3.14.3.2.4" +szOID_OIWSEC_desECB = "1.3.14.3.2.6" +szOID_OIWSEC_desCBC = "1.3.14.3.2.7" +szOID_OIWSEC_desOFB = "1.3.14.3.2.8" +szOID_OIWSEC_desCFB = "1.3.14.3.2.9" +szOID_OIWSEC_desMAC = "1.3.14.3.2.10" +szOID_OIWSEC_rsaSign = "1.3.14.3.2.11" +szOID_OIWSEC_dsa = "1.3.14.3.2.12" +szOID_OIWSEC_shaDSA = "1.3.14.3.2.13" +szOID_OIWSEC_mdc2RSA = "1.3.14.3.2.14" +szOID_OIWSEC_shaRSA = "1.3.14.3.2.15" +szOID_OIWSEC_dhCommMod = "1.3.14.3.2.16" +szOID_OIWSEC_desEDE = "1.3.14.3.2.17" +szOID_OIWSEC_sha = "1.3.14.3.2.18" +szOID_OIWSEC_mdc2 = "1.3.14.3.2.19" +szOID_OIWSEC_dsaComm = "1.3.14.3.2.20" +szOID_OIWSEC_dsaCommSHA = "1.3.14.3.2.21" +szOID_OIWSEC_rsaXchg = "1.3.14.3.2.22" +szOID_OIWSEC_keyHashSeal = "1.3.14.3.2.23" +szOID_OIWSEC_md2RSASign = "1.3.14.3.2.24" +szOID_OIWSEC_md5RSASign = "1.3.14.3.2.25" +szOID_OIWSEC_sha1 = "1.3.14.3.2.26" +szOID_OIWSEC_dsaSHA1 = "1.3.14.3.2.27" +szOID_OIWSEC_dsaCommSHA1 = "1.3.14.3.2.28" +szOID_OIWSEC_sha1RSASign = "1.3.14.3.2.29" +szOID_OIWDIR = "1.3.14.7.2" +szOID_OIWDIR_CRPT = "1.3.14.7.2.1" +szOID_OIWDIR_HASH = "1.3.14.7.2.2" +szOID_OIWDIR_SIGN = "1.3.14.7.2.3" +szOID_OIWDIR_md2 = "1.3.14.7.2.2.1" +szOID_OIWDIR_md2RSA = "1.3.14.7.2.3.1" +szOID_INFOSEC = "2.16.840.1.101.2.1" +szOID_INFOSEC_sdnsSignature = "2.16.840.1.101.2.1.1.1" +szOID_INFOSEC_mosaicSignature = "2.16.840.1.101.2.1.1.2" +szOID_INFOSEC_sdnsConfidentiality = "2.16.840.1.101.2.1.1.3" +szOID_INFOSEC_mosaicConfidentiality = "2.16.840.1.101.2.1.1.4" +szOID_INFOSEC_sdnsIntegrity = "2.16.840.1.101.2.1.1.5" +szOID_INFOSEC_mosaicIntegrity = "2.16.840.1.101.2.1.1.6" +szOID_INFOSEC_sdnsTokenProtection = "2.16.840.1.101.2.1.1.7" +szOID_INFOSEC_mosaicTokenProtection = "2.16.840.1.101.2.1.1.8" +szOID_INFOSEC_sdnsKeyManagement = "2.16.840.1.101.2.1.1.9" +szOID_INFOSEC_mosaicKeyManagement = "2.16.840.1.101.2.1.1.10" +szOID_INFOSEC_sdnsKMandSig = "2.16.840.1.101.2.1.1.11" +szOID_INFOSEC_mosaicKMandSig = "2.16.840.1.101.2.1.1.12" +szOID_INFOSEC_SuiteASignature = "2.16.840.1.101.2.1.1.13" +szOID_INFOSEC_SuiteAConfidentiality = "2.16.840.1.101.2.1.1.14" +szOID_INFOSEC_SuiteAIntegrity = "2.16.840.1.101.2.1.1.15" +szOID_INFOSEC_SuiteATokenProtection = "2.16.840.1.101.2.1.1.16" +szOID_INFOSEC_SuiteAKeyManagement = "2.16.840.1.101.2.1.1.17" +szOID_INFOSEC_SuiteAKMandSig = "2.16.840.1.101.2.1.1.18" +szOID_INFOSEC_mosaicUpdatedSig = "2.16.840.1.101.2.1.1.19" +szOID_INFOSEC_mosaicKMandUpdSig = "2.16.840.1.101.2.1.1.20" +szOID_INFOSEC_mosaicUpdatedInteg = "2.16.840.1.101.2.1.1.21" +szOID_COMMON_NAME = "2.5.4.3" +szOID_SUR_NAME = "2.5.4.4" +szOID_DEVICE_SERIAL_NUMBER = "2.5.4.5" +szOID_COUNTRY_NAME = "2.5.4.6" +szOID_LOCALITY_NAME = "2.5.4.7" +szOID_STATE_OR_PROVINCE_NAME = "2.5.4.8" +szOID_STREET_ADDRESS = "2.5.4.9" +szOID_ORGANIZATION_NAME = "2.5.4.10" +szOID_ORGANIZATIONAL_UNIT_NAME = "2.5.4.11" +szOID_TITLE = "2.5.4.12" +szOID_DESCRIPTION = "2.5.4.13" +szOID_SEARCH_GUIDE = "2.5.4.14" +szOID_BUSINESS_CATEGORY = "2.5.4.15" +szOID_POSTAL_ADDRESS = "2.5.4.16" +szOID_POSTAL_CODE = "2.5.4.17" +szOID_POST_OFFICE_BOX = "2.5.4.18" +szOID_PHYSICAL_DELIVERY_OFFICE_NAME = "2.5.4.19" +szOID_TELEPHONE_NUMBER = "2.5.4.20" +szOID_TELEX_NUMBER = "2.5.4.21" +szOID_TELETEXT_TERMINAL_IDENTIFIER = "2.5.4.22" +szOID_FACSIMILE_TELEPHONE_NUMBER = "2.5.4.23" +szOID_X21_ADDRESS = "2.5.4.24" +szOID_INTERNATIONAL_ISDN_NUMBER = "2.5.4.25" +szOID_REGISTERED_ADDRESS = "2.5.4.26" +szOID_DESTINATION_INDICATOR = "2.5.4.27" +szOID_PREFERRED_DELIVERY_METHOD = "2.5.4.28" +szOID_PRESENTATION_ADDRESS = "2.5.4.29" +szOID_SUPPORTED_APPLICATION_CONTEXT = "2.5.4.30" +szOID_MEMBER = "2.5.4.31" +szOID_OWNER = "2.5.4.32" +szOID_ROLE_OCCUPANT = "2.5.4.33" +szOID_SEE_ALSO = "2.5.4.34" +szOID_USER_PASSWORD = "2.5.4.35" +szOID_USER_CERTIFICATE = "2.5.4.36" +szOID_CA_CERTIFICATE = "2.5.4.37" +szOID_AUTHORITY_REVOCATION_LIST = "2.5.4.38" +szOID_CERTIFICATE_REVOCATION_LIST = "2.5.4.39" +szOID_CROSS_CERTIFICATE_PAIR = "2.5.4.40" +szOID_GIVEN_NAME = "2.5.4.42" +szOID_INITIALS = "2.5.4.43" +szOID_DN_QUALIFIER = "2.5.4.46" +szOID_DOMAIN_COMPONENT = "0.9.2342.19200300.100.1.25" +szOID_PKCS_12_FRIENDLY_NAME_ATTR = "1.2.840.113549.1.9.20" +szOID_PKCS_12_LOCAL_KEY_ID = "1.2.840.113549.1.9.21" +szOID_PKCS_12_KEY_PROVIDER_NAME_ATTR = "1.3.6.1.4.1.311.17.1" +szOID_LOCAL_MACHINE_KEYSET = "1.3.6.1.4.1.311.17.2" +szOID_KEYID_RDN = "1.3.6.1.4.1.311.10.7.1" +CERT_RDN_ANY_TYPE = 0 +CERT_RDN_ENCODED_BLOB = 1 +CERT_RDN_OCTET_STRING = 2 +CERT_RDN_NUMERIC_STRING = 3 +CERT_RDN_PRINTABLE_STRING = 4 +CERT_RDN_TELETEX_STRING = 5 +CERT_RDN_T61_STRING = 5 +CERT_RDN_VIDEOTEX_STRING = 6 +CERT_RDN_IA5_STRING = 7 +CERT_RDN_GRAPHIC_STRING = 8 +CERT_RDN_VISIBLE_STRING = 9 +CERT_RDN_ISO646_STRING = 9 +CERT_RDN_GENERAL_STRING = 10 +CERT_RDN_UNIVERSAL_STRING = 11 +CERT_RDN_INT4_STRING = 11 +CERT_RDN_BMP_STRING = 12 +CERT_RDN_UNICODE_STRING = 12 +CERT_RDN_UTF8_STRING = 13 +CERT_RDN_TYPE_MASK = 0x000000FF +CERT_RDN_FLAGS_MASK = -16777216 +CERT_RDN_ENABLE_T61_UNICODE_FLAG = -2147483648 +CERT_RDN_ENABLE_UTF8_UNICODE_FLAG = 0x20000000 +CERT_RDN_DISABLE_CHECK_TYPE_FLAG = 0x40000000 +CERT_RDN_DISABLE_IE4_UTF8_FLAG = 0x01000000 +CERT_RSA_PUBLIC_KEY_OBJID = szOID_RSA_RSA +CERT_DEFAULT_OID_PUBLIC_KEY_SIGN = szOID_RSA_RSA +CERT_DEFAULT_OID_PUBLIC_KEY_XCHG = szOID_RSA_RSA +CERT_V1 = 0 +CERT_V2 = 1 +CERT_V3 = 2 +CERT_INFO_VERSION_FLAG = 1 +CERT_INFO_SERIAL_NUMBER_FLAG = 2 +CERT_INFO_SIGNATURE_ALGORITHM_FLAG = 3 +CERT_INFO_ISSUER_FLAG = 4 +CERT_INFO_NOT_BEFORE_FLAG = 5 +CERT_INFO_NOT_AFTER_FLAG = 6 +CERT_INFO_SUBJECT_FLAG = 7 +CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG = 8 +CERT_INFO_ISSUER_UNIQUE_ID_FLAG = 9 +CERT_INFO_SUBJECT_UNIQUE_ID_FLAG = 10 +CERT_INFO_EXTENSION_FLAG = 11 +CRL_V1 = 0 +CRL_V2 = 1 +CERT_REQUEST_V1 = 0 +CERT_KEYGEN_REQUEST_V1 = 0 +CTL_V1 = 0 +CERT_ENCODING_TYPE_MASK = 0x0000FFFF +CMSG_ENCODING_TYPE_MASK = -65536 + + +def GET_CERT_ENCODING_TYPE(X): + return X & CERT_ENCODING_TYPE_MASK + + +def GET_CMSG_ENCODING_TYPE(X): + return X & CMSG_ENCODING_TYPE_MASK + + +CRYPT_ASN_ENCODING = 0x00000001 +CRYPT_NDR_ENCODING = 0x00000002 +X509_ASN_ENCODING = 0x00000001 +X509_NDR_ENCODING = 0x00000002 +PKCS_7_ASN_ENCODING = 0x00010000 +PKCS_7_NDR_ENCODING = 0x00020000 +CRYPT_FORMAT_STR_MULTI_LINE = 0x0001 +CRYPT_FORMAT_STR_NO_HEX = 0x0010 +CRYPT_FORMAT_SIMPLE = 0x0001 +CRYPT_FORMAT_X509 = 0x0002 +CRYPT_FORMAT_OID = 0x0004 +CRYPT_FORMAT_RDN_SEMICOLON = 0x0100 +CRYPT_FORMAT_RDN_CRLF = 0x0200 +CRYPT_FORMAT_RDN_UNQUOTE = 0x0400 +CRYPT_FORMAT_RDN_REVERSE = 0x0800 +CRYPT_FORMAT_COMMA = 0x1000 +CRYPT_FORMAT_SEMICOLON = CRYPT_FORMAT_RDN_SEMICOLON +CRYPT_FORMAT_CRLF = CRYPT_FORMAT_RDN_CRLF +CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG = 0x8 +CRYPT_ENCODE_ALLOC_FLAG = 0x8000 +CRYPT_UNICODE_NAME_ENCODE_ENABLE_T61_UNICODE_FLAG = CERT_RDN_ENABLE_T61_UNICODE_FLAG +CRYPT_UNICODE_NAME_ENCODE_ENABLE_UTF8_UNICODE_FLAG = CERT_RDN_ENABLE_UTF8_UNICODE_FLAG +CRYPT_UNICODE_NAME_ENCODE_DISABLE_CHECK_TYPE_FLAG = CERT_RDN_DISABLE_CHECK_TYPE_FLAG +CRYPT_SORTED_CTL_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG = 0x10000 +CRYPT_DECODE_NOCOPY_FLAG = 0x1 +CRYPT_DECODE_TO_BE_SIGNED_FLAG = 0x2 +CRYPT_DECODE_SHARE_OID_STRING_FLAG = 0x4 +CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG = 0x8 +CRYPT_DECODE_ALLOC_FLAG = 0x8000 +CRYPT_UNICODE_NAME_DECODE_DISABLE_IE4_UTF8_FLAG = CERT_RDN_DISABLE_IE4_UTF8_FLAG + +CRYPT_ENCODE_DECODE_NONE = 0 +X509_CERT = 1 +X509_CERT_TO_BE_SIGNED = 2 +X509_CERT_CRL_TO_BE_SIGNED = 3 +X509_CERT_REQUEST_TO_BE_SIGNED = 4 +X509_EXTENSIONS = 5 +X509_NAME_VALUE = 6 +X509_NAME = 7 +X509_PUBLIC_KEY_INFO = 8 +X509_AUTHORITY_KEY_ID = 9 +X509_KEY_ATTRIBUTES = 10 +X509_KEY_USAGE_RESTRICTION = 11 +X509_ALTERNATE_NAME = 12 +X509_BASIC_CONSTRAINTS = 13 +X509_KEY_USAGE = 14 +X509_BASIC_CONSTRAINTS2 = 15 +X509_CERT_POLICIES = 16 +PKCS_UTC_TIME = 17 +PKCS_TIME_REQUEST = 18 +RSA_CSP_PUBLICKEYBLOB = 19 +X509_UNICODE_NAME = 20 +X509_KEYGEN_REQUEST_TO_BE_SIGNED = 21 +PKCS_ATTRIBUTE = 22 +PKCS_CONTENT_INFO_SEQUENCE_OF_ANY = 23 +X509_UNICODE_NAME_VALUE = 24 +X509_ANY_STRING = X509_NAME_VALUE +X509_UNICODE_ANY_STRING = X509_UNICODE_NAME_VALUE +X509_OCTET_STRING = 25 +X509_BITS = 26 +X509_INTEGER = 27 +X509_MULTI_BYTE_INTEGER = 28 +X509_ENUMERATED = 29 +X509_CHOICE_OF_TIME = 30 +X509_AUTHORITY_KEY_ID2 = 31 +X509_AUTHORITY_INFO_ACCESS = 32 +X509_SUBJECT_INFO_ACCESS = X509_AUTHORITY_INFO_ACCESS +X509_CRL_REASON_CODE = X509_ENUMERATED +PKCS_CONTENT_INFO = 33 +X509_SEQUENCE_OF_ANY = 34 +X509_CRL_DIST_POINTS = 35 +X509_ENHANCED_KEY_USAGE = 36 +PKCS_CTL = 37 +X509_MULTI_BYTE_UINT = 38 +X509_DSS_PUBLICKEY = X509_MULTI_BYTE_UINT +X509_DSS_PARAMETERS = 39 +X509_DSS_SIGNATURE = 40 +PKCS_RC2_CBC_PARAMETERS = 41 +PKCS_SMIME_CAPABILITIES = 42 +X509_QC_STATEMENTS_EXT = 42 +PKCS_RSA_PRIVATE_KEY = 43 +PKCS_PRIVATE_KEY_INFO = 44 +PKCS_ENCRYPTED_PRIVATE_KEY_INFO = 45 +X509_PKIX_POLICY_QUALIFIER_USERNOTICE = 46 +X509_DH_PUBLICKEY = X509_MULTI_BYTE_UINT +X509_DH_PARAMETERS = 47 +PKCS_ATTRIBUTES = 48 +PKCS_SORTED_CTL = 49 +X509_ECC_SIGNATURE = 47 +X942_DH_PARAMETERS = 50 +X509_BITS_WITHOUT_TRAILING_ZEROES = 51 +X942_OTHER_INFO = 52 +X509_CERT_PAIR = 53 +X509_ISSUING_DIST_POINT = 54 +X509_NAME_CONSTRAINTS = 55 +X509_POLICY_MAPPINGS = 56 +X509_POLICY_CONSTRAINTS = 57 +X509_CROSS_CERT_DIST_POINTS = 58 +CMC_DATA = 59 +CMC_RESPONSE = 60 +CMC_STATUS = 61 +CMC_ADD_EXTENSIONS = 62 +CMC_ADD_ATTRIBUTES = 63 +X509_CERTIFICATE_TEMPLATE = 64 +OCSP_SIGNED_REQUEST = 65 +OCSP_REQUEST = 66 +OCSP_RESPONSE = 67 +OCSP_BASIC_SIGNED_RESPONSE = 68 +OCSP_BASIC_RESPONSE = 69 +X509_LOGOTYPE_EXT = 70 +X509_BIOMETRIC_EXT = 71 +CNG_RSA_PUBLIC_KEY_BLOB = 72 +X509_OBJECT_IDENTIFIER = 73 +X509_ALGORITHM_IDENTIFIER = 74 +PKCS_RSA_SSA_PSS_PARAMETERS = 75 +PKCS_RSAES_OAEP_PARAMETERS = 76 +ECC_CMS_SHARED_INFO = 77 +TIMESTAMP_REQUEST = 78 +TIMESTAMP_RESPONSE = 79 +TIMESTAMP_INFO = 80 +X509_CERT_BUNDLE = 81 +PKCS7_SIGNER_INFO = 500 +CMS_SIGNER_INFO = 501 + +szOID_AUTHORITY_KEY_IDENTIFIER = "2.5.29.1" +szOID_KEY_ATTRIBUTES = "2.5.29.2" +szOID_CERT_POLICIES_95 = "2.5.29.3" +szOID_KEY_USAGE_RESTRICTION = "2.5.29.4" +szOID_SUBJECT_ALT_NAME = "2.5.29.7" +szOID_ISSUER_ALT_NAME = "2.5.29.8" +szOID_BASIC_CONSTRAINTS = "2.5.29.10" +szOID_KEY_USAGE = "2.5.29.15" +szOID_PRIVATEKEY_USAGE_PERIOD = "2.5.29.16" +szOID_BASIC_CONSTRAINTS2 = "2.5.29.19" +szOID_CERT_POLICIES = "2.5.29.32" +szOID_ANY_CERT_POLICY = "2.5.29.32.0" +szOID_AUTHORITY_KEY_IDENTIFIER2 = "2.5.29.35" +szOID_SUBJECT_KEY_IDENTIFIER = "2.5.29.14" +szOID_SUBJECT_ALT_NAME2 = "2.5.29.17" +szOID_ISSUER_ALT_NAME2 = "2.5.29.18" +szOID_CRL_REASON_CODE = "2.5.29.21" +szOID_REASON_CODE_HOLD = "2.5.29.23" +szOID_CRL_DIST_POINTS = "2.5.29.31" +szOID_ENHANCED_KEY_USAGE = "2.5.29.37" +szOID_CRL_NUMBER = "2.5.29.20" +szOID_DELTA_CRL_INDICATOR = "2.5.29.27" +szOID_ISSUING_DIST_POINT = "2.5.29.28" +szOID_FRESHEST_CRL = "2.5.29.46" +szOID_NAME_CONSTRAINTS = "2.5.29.30" +szOID_POLICY_MAPPINGS = "2.5.29.33" +szOID_LEGACY_POLICY_MAPPINGS = "2.5.29.5" +szOID_POLICY_CONSTRAINTS = "2.5.29.36" +szOID_RENEWAL_CERTIFICATE = "1.3.6.1.4.1.311.13.1" +szOID_ENROLLMENT_NAME_VALUE_PAIR = "1.3.6.1.4.1.311.13.2.1" +szOID_ENROLLMENT_CSP_PROVIDER = "1.3.6.1.4.1.311.13.2.2" +szOID_OS_VERSION = "1.3.6.1.4.1.311.13.2.3" +szOID_ENROLLMENT_AGENT = "1.3.6.1.4.1.311.20.2.1" +szOID_PKIX = "1.3.6.1.5.5.7" +szOID_PKIX_PE = "1.3.6.1.5.5.7.1" +szOID_AUTHORITY_INFO_ACCESS = "1.3.6.1.5.5.7.1.1" +szOID_CERT_EXTENSIONS = "1.3.6.1.4.1.311.2.1.14" +szOID_NEXT_UPDATE_LOCATION = "1.3.6.1.4.1.311.10.2" +szOID_REMOVE_CERTIFICATE = "1.3.6.1.4.1.311.10.8.1" +szOID_CROSS_CERT_DIST_POINTS = "1.3.6.1.4.1.311.10.9.1" +szOID_CTL = "1.3.6.1.4.1.311.10.1" +szOID_SORTED_CTL = "1.3.6.1.4.1.311.10.1.1" +szOID_SERIALIZED = "1.3.6.1.4.1.311.10.3.3.1" +szOID_NT_PRINCIPAL_NAME = "1.3.6.1.4.1.311.20.2.3" +szOID_PRODUCT_UPDATE = "1.3.6.1.4.1.311.31.1" +szOID_ANY_APPLICATION_POLICY = "1.3.6.1.4.1.311.10.12.1" +szOID_AUTO_ENROLL_CTL_USAGE = "1.3.6.1.4.1.311.20.1" +szOID_ENROLL_CERTTYPE_EXTENSION = "1.3.6.1.4.1.311.20.2" +szOID_CERT_MANIFOLD = "1.3.6.1.4.1.311.20.3" +szOID_CERTSRV_CA_VERSION = "1.3.6.1.4.1.311.21.1" +szOID_CERTSRV_PREVIOUS_CERT_HASH = "1.3.6.1.4.1.311.21.2" +szOID_CRL_VIRTUAL_BASE = "1.3.6.1.4.1.311.21.3" +szOID_CRL_NEXT_PUBLISH = "1.3.6.1.4.1.311.21.4" +szOID_KP_CA_EXCHANGE = "1.3.6.1.4.1.311.21.5" +szOID_KP_KEY_RECOVERY_AGENT = "1.3.6.1.4.1.311.21.6" +szOID_CERTIFICATE_TEMPLATE = "1.3.6.1.4.1.311.21.7" +szOID_ENTERPRISE_OID_ROOT = "1.3.6.1.4.1.311.21.8" +szOID_RDN_DUMMY_SIGNER = "1.3.6.1.4.1.311.21.9" +szOID_APPLICATION_CERT_POLICIES = "1.3.6.1.4.1.311.21.10" +szOID_APPLICATION_POLICY_MAPPINGS = "1.3.6.1.4.1.311.21.11" +szOID_APPLICATION_POLICY_CONSTRAINTS = "1.3.6.1.4.1.311.21.12" +szOID_ARCHIVED_KEY_ATTR = "1.3.6.1.4.1.311.21.13" +szOID_CRL_SELF_CDP = "1.3.6.1.4.1.311.21.14" +szOID_REQUIRE_CERT_CHAIN_POLICY = "1.3.6.1.4.1.311.21.15" +szOID_ARCHIVED_KEY_CERT_HASH = "1.3.6.1.4.1.311.21.16" +szOID_ISSUED_CERT_HASH = "1.3.6.1.4.1.311.21.17" +szOID_DS_EMAIL_REPLICATION = "1.3.6.1.4.1.311.21.19" +szOID_REQUEST_CLIENT_INFO = "1.3.6.1.4.1.311.21.20" +szOID_ENCRYPTED_KEY_HASH = "1.3.6.1.4.1.311.21.21" +szOID_CERTSRV_CROSSCA_VERSION = "1.3.6.1.4.1.311.21.22" +szOID_NTDS_REPLICATION = "1.3.6.1.4.1.311.25.1" +szOID_SUBJECT_DIR_ATTRS = "2.5.29.9" +szOID_PKIX_KP = "1.3.6.1.5.5.7.3" +szOID_PKIX_KP_SERVER_AUTH = "1.3.6.1.5.5.7.3.1" +szOID_PKIX_KP_CLIENT_AUTH = "1.3.6.1.5.5.7.3.2" +szOID_PKIX_KP_CODE_SIGNING = "1.3.6.1.5.5.7.3.3" +szOID_PKIX_KP_EMAIL_PROTECTION = "1.3.6.1.5.5.7.3.4" +szOID_PKIX_KP_IPSEC_END_SYSTEM = "1.3.6.1.5.5.7.3.5" +szOID_PKIX_KP_IPSEC_TUNNEL = "1.3.6.1.5.5.7.3.6" +szOID_PKIX_KP_IPSEC_USER = "1.3.6.1.5.5.7.3.7" +szOID_PKIX_KP_TIMESTAMP_SIGNING = "1.3.6.1.5.5.7.3.8" +szOID_IPSEC_KP_IKE_INTERMEDIATE = "1.3.6.1.5.5.8.2.2" +szOID_KP_CTL_USAGE_SIGNING = "1.3.6.1.4.1.311.10.3.1" +szOID_KP_TIME_STAMP_SIGNING = "1.3.6.1.4.1.311.10.3.2" +szOID_SERVER_GATED_CRYPTO = "1.3.6.1.4.1.311.10.3.3" +szOID_SGC_NETSCAPE = "2.16.840.1.113730.4.1" +szOID_KP_EFS = "1.3.6.1.4.1.311.10.3.4" +szOID_EFS_RECOVERY = "1.3.6.1.4.1.311.10.3.4.1" +szOID_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.5" +szOID_NT5_CRYPTO = "1.3.6.1.4.1.311.10.3.6" +szOID_OEM_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.7" +szOID_EMBEDDED_NT_CRYPTO = "1.3.6.1.4.1.311.10.3.8" +szOID_ROOT_LIST_SIGNER = "1.3.6.1.4.1.311.10.3.9" +szOID_KP_QUALIFIED_SUBORDINATION = "1.3.6.1.4.1.311.10.3.10" +szOID_KP_KEY_RECOVERY = "1.3.6.1.4.1.311.10.3.11" +szOID_KP_DOCUMENT_SIGNING = "1.3.6.1.4.1.311.10.3.12" +szOID_KP_LIFETIME_SIGNING = "1.3.6.1.4.1.311.10.3.13" +szOID_KP_MOBILE_DEVICE_SOFTWARE = "1.3.6.1.4.1.311.10.3.14" +szOID_DRM = "1.3.6.1.4.1.311.10.5.1" +szOID_DRM_INDIVIDUALIZATION = "1.3.6.1.4.1.311.10.5.2" +szOID_LICENSES = "1.3.6.1.4.1.311.10.6.1" +szOID_LICENSE_SERVER = "1.3.6.1.4.1.311.10.6.2" +szOID_KP_SMARTCARD_LOGON = "1.3.6.1.4.1.311.20.2.2" +szOID_YESNO_TRUST_ATTR = "1.3.6.1.4.1.311.10.4.1" +szOID_PKIX_POLICY_QUALIFIER_CPS = "1.3.6.1.5.5.7.2.1" +szOID_PKIX_POLICY_QUALIFIER_USERNOTICE = "1.3.6.1.5.5.7.2.2" +szOID_CERT_POLICIES_95_QUALIFIER1 = "2.16.840.1.113733.1.7.1.1" +CERT_UNICODE_RDN_ERR_INDEX_MASK = 0x3FF +CERT_UNICODE_RDN_ERR_INDEX_SHIFT = 22 +CERT_UNICODE_ATTR_ERR_INDEX_MASK = 0x003F +CERT_UNICODE_ATTR_ERR_INDEX_SHIFT = 16 +CERT_UNICODE_VALUE_ERR_INDEX_MASK = 0x0000FFFF +CERT_UNICODE_VALUE_ERR_INDEX_SHIFT = 0 +CERT_DIGITAL_SIGNATURE_KEY_USAGE = 0x80 +CERT_NON_REPUDIATION_KEY_USAGE = 0x40 +CERT_KEY_ENCIPHERMENT_KEY_USAGE = 0x20 +CERT_DATA_ENCIPHERMENT_KEY_USAGE = 0x10 +CERT_KEY_AGREEMENT_KEY_USAGE = 0x08 +CERT_KEY_CERT_SIGN_KEY_USAGE = 0x04 +CERT_OFFLINE_CRL_SIGN_KEY_USAGE = 0x02 +CERT_CRL_SIGN_KEY_USAGE = 0x02 +CERT_ENCIPHER_ONLY_KEY_USAGE = 0x01 +CERT_DECIPHER_ONLY_KEY_USAGE = 0x80 +CERT_ALT_NAME_OTHER_NAME = 1 +CERT_ALT_NAME_RFC822_NAME = 2 +CERT_ALT_NAME_DNS_NAME = 3 +CERT_ALT_NAME_X400_ADDRESS = 4 +CERT_ALT_NAME_DIRECTORY_NAME = 5 +CERT_ALT_NAME_EDI_PARTY_NAME = 6 +CERT_ALT_NAME_URL = 7 +CERT_ALT_NAME_IP_ADDRESS = 8 +CERT_ALT_NAME_REGISTERED_ID = 9 +CERT_ALT_NAME_ENTRY_ERR_INDEX_MASK = 0xFF +CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT = 16 +CERT_ALT_NAME_VALUE_ERR_INDEX_MASK = 0x0000FFFF +CERT_ALT_NAME_VALUE_ERR_INDEX_SHIFT = 0 +CERT_CA_SUBJECT_FLAG = 0x80 +CERT_END_ENTITY_SUBJECT_FLAG = 0x40 +szOID_PKIX_ACC_DESCR = "1.3.6.1.5.5.7.48" +szOID_PKIX_OCSP = "1.3.6.1.5.5.7.48.1" +szOID_PKIX_CA_ISSUERS = "1.3.6.1.5.5.7.48.2" +CRL_REASON_UNSPECIFIED = 0 +CRL_REASON_KEY_COMPROMISE = 1 +CRL_REASON_CA_COMPROMISE = 2 +CRL_REASON_AFFILIATION_CHANGED = 3 +CRL_REASON_SUPERSEDED = 4 +CRL_REASON_CESSATION_OF_OPERATION = 5 +CRL_REASON_CERTIFICATE_HOLD = 6 +CRL_REASON_REMOVE_FROM_CRL = 8 +CRL_DIST_POINT_NO_NAME = 0 +CRL_DIST_POINT_FULL_NAME = 1 +CRL_DIST_POINT_ISSUER_RDN_NAME = 2 +CRL_REASON_UNUSED_FLAG = 0x80 +CRL_REASON_KEY_COMPROMISE_FLAG = 0x40 +CRL_REASON_CA_COMPROMISE_FLAG = 0x20 +CRL_REASON_AFFILIATION_CHANGED_FLAG = 0x10 +CRL_REASON_SUPERSEDED_FLAG = 0x08 +CRL_REASON_CESSATION_OF_OPERATION_FLAG = 0x04 +CRL_REASON_CERTIFICATE_HOLD_FLAG = 0x02 +CRL_DIST_POINT_ERR_INDEX_MASK = 0x7F +CRL_DIST_POINT_ERR_INDEX_SHIFT = 24 + +CRL_DIST_POINT_ERR_CRL_ISSUER_BIT = -2147483648 + +CROSS_CERT_DIST_POINT_ERR_INDEX_MASK = 0xFF +CROSS_CERT_DIST_POINT_ERR_INDEX_SHIFT = 24 + +CERT_EXCLUDED_SUBTREE_BIT = -2147483648 + +SORTED_CTL_EXT_FLAGS_OFFSET = 0 * 4 +SORTED_CTL_EXT_COUNT_OFFSET = 1 * 4 +SORTED_CTL_EXT_MAX_COLLISION_OFFSET = 2 * 4 +SORTED_CTL_EXT_HASH_BUCKET_OFFSET = 3 * 4 +SORTED_CTL_EXT_HASHED_SUBJECT_IDENTIFIER_FLAG = 0x1 +CERT_DSS_R_LEN = 20 +CERT_DSS_S_LEN = 20 +CERT_DSS_SIGNATURE_LEN = CERT_DSS_R_LEN + CERT_DSS_S_LEN +CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN = 2 + 2 * (2 + 20 + 1) +CRYPT_X942_COUNTER_BYTE_LENGTH = 4 +CRYPT_X942_KEY_LENGTH_BYTE_LENGTH = 4 +CRYPT_X942_PUB_INFO_BYTE_LENGTH = 512 / 8 +CRYPT_RC2_40BIT_VERSION = 160 +CRYPT_RC2_56BIT_VERSION = 52 +CRYPT_RC2_64BIT_VERSION = 120 +CRYPT_RC2_128BIT_VERSION = 58 +szOID_VERISIGN_PRIVATE_6_9 = "2.16.840.1.113733.1.6.9" +szOID_VERISIGN_ONSITE_JURISDICTION_HASH = "2.16.840.1.113733.1.6.11" +szOID_VERISIGN_BITSTRING_6_13 = "2.16.840.1.113733.1.6.13" +szOID_VERISIGN_ISS_STRONG_CRYPTO = "2.16.840.1.113733.1.8.1" +szOID_NETSCAPE = "2.16.840.1.113730" +szOID_NETSCAPE_CERT_EXTENSION = "2.16.840.1.113730.1" +szOID_NETSCAPE_CERT_TYPE = "2.16.840.1.113730.1.1" +szOID_NETSCAPE_BASE_URL = "2.16.840.1.113730.1.2" +szOID_NETSCAPE_REVOCATION_URL = "2.16.840.1.113730.1.3" +szOID_NETSCAPE_CA_REVOCATION_URL = "2.16.840.1.113730.1.4" +szOID_NETSCAPE_CERT_RENEWAL_URL = "2.16.840.1.113730.1.7" +szOID_NETSCAPE_CA_POLICY_URL = "2.16.840.1.113730.1.8" +szOID_NETSCAPE_SSL_SERVER_NAME = "2.16.840.1.113730.1.12" +szOID_NETSCAPE_COMMENT = "2.16.840.1.113730.1.13" +szOID_NETSCAPE_DATA_TYPE = "2.16.840.1.113730.2" +szOID_NETSCAPE_CERT_SEQUENCE = "2.16.840.1.113730.2.5" +NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE = 0x80 +NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE = 0x40 +NETSCAPE_SMIME_CERT_TYPE = 0x20 +NETSCAPE_SIGN_CERT_TYPE = 0x10 +NETSCAPE_SSL_CA_CERT_TYPE = 0x04 +NETSCAPE_SMIME_CA_CERT_TYPE = 0x02 +NETSCAPE_SIGN_CA_CERT_TYPE = 0x01 +szOID_CT_PKI_DATA = "1.3.6.1.5.5.7.12.2" +szOID_CT_PKI_RESPONSE = "1.3.6.1.5.5.7.12.3" +szOID_PKIX_NO_SIGNATURE = "1.3.6.1.5.5.7.6.2" +szOID_CMC = "1.3.6.1.5.5.7.7" +szOID_CMC_STATUS_INFO = "1.3.6.1.5.5.7.7.1" +szOID_CMC_IDENTIFICATION = "1.3.6.1.5.5.7.7.2" +szOID_CMC_IDENTITY_PROOF = "1.3.6.1.5.5.7.7.3" +szOID_CMC_DATA_RETURN = "1.3.6.1.5.5.7.7.4" +szOID_CMC_TRANSACTION_ID = "1.3.6.1.5.5.7.7.5" +szOID_CMC_SENDER_NONCE = "1.3.6.1.5.5.7.7.6" +szOID_CMC_RECIPIENT_NONCE = "1.3.6.1.5.5.7.7.7" +szOID_CMC_ADD_EXTENSIONS = "1.3.6.1.5.5.7.7.8" +szOID_CMC_ENCRYPTED_POP = "1.3.6.1.5.5.7.7.9" +szOID_CMC_DECRYPTED_POP = "1.3.6.1.5.5.7.7.10" +szOID_CMC_LRA_POP_WITNESS = "1.3.6.1.5.5.7.7.11" +szOID_CMC_GET_CERT = "1.3.6.1.5.5.7.7.15" +szOID_CMC_GET_CRL = "1.3.6.1.5.5.7.7.16" +szOID_CMC_REVOKE_REQUEST = "1.3.6.1.5.5.7.7.17" +szOID_CMC_REG_INFO = "1.3.6.1.5.5.7.7.18" +szOID_CMC_RESPONSE_INFO = "1.3.6.1.5.5.7.7.19" +szOID_CMC_QUERY_PENDING = "1.3.6.1.5.5.7.7.21" +szOID_CMC_ID_POP_LINK_RANDOM = "1.3.6.1.5.5.7.7.22" +szOID_CMC_ID_POP_LINK_WITNESS = "1.3.6.1.5.5.7.7.23" +szOID_CMC_ID_CONFIRM_CERT_ACCEPTANCE = "1.3.6.1.5.5.7.7.24" +szOID_CMC_ADD_ATTRIBUTES = "1.3.6.1.4.1.311.10.10.1" +CMC_TAGGED_CERT_REQUEST_CHOICE = 1 +CMC_OTHER_INFO_NO_CHOICE = 0 +CMC_OTHER_INFO_FAIL_CHOICE = 1 +CMC_OTHER_INFO_PEND_CHOICE = 2 +CMC_STATUS_SUCCESS = 0 +CMC_STATUS_FAILED = 2 +CMC_STATUS_PENDING = 3 +CMC_STATUS_NO_SUPPORT = 4 +CMC_STATUS_CONFIRM_REQUIRED = 5 +CMC_FAIL_BAD_ALG = 0 +CMC_FAIL_BAD_MESSAGE_CHECK = 1 +CMC_FAIL_BAD_REQUEST = 2 +CMC_FAIL_BAD_TIME = 3 +CMC_FAIL_BAD_CERT_ID = 4 +CMC_FAIL_UNSUPORTED_EXT = 5 +CMC_FAIL_MUST_ARCHIVE_KEYS = 6 +CMC_FAIL_BAD_IDENTITY = 7 +CMC_FAIL_POP_REQUIRED = 8 +CMC_FAIL_POP_FAILED = 9 +CMC_FAIL_NO_KEY_REUSE = 10 +CMC_FAIL_INTERNAL_CA_ERROR = 11 +CMC_FAIL_TRY_LATER = 12 +CRYPT_OID_ENCODE_OBJECT_FUNC = "CryptDllEncodeObject" +CRYPT_OID_DECODE_OBJECT_FUNC = "CryptDllDecodeObject" +CRYPT_OID_ENCODE_OBJECT_EX_FUNC = "CryptDllEncodeObjectEx" +CRYPT_OID_DECODE_OBJECT_EX_FUNC = "CryptDllDecodeObjectEx" +CRYPT_OID_CREATE_COM_OBJECT_FUNC = "CryptDllCreateCOMObject" +CRYPT_OID_VERIFY_REVOCATION_FUNC = "CertDllVerifyRevocation" +CRYPT_OID_VERIFY_CTL_USAGE_FUNC = "CertDllVerifyCTLUsage" +CRYPT_OID_FORMAT_OBJECT_FUNC = "CryptDllFormatObject" +CRYPT_OID_FIND_OID_INFO_FUNC = "CryptDllFindOIDInfo" +CRYPT_OID_FIND_LOCALIZED_NAME_FUNC = "CryptDllFindLocalizedName" + +CRYPT_OID_REGPATH = "Software\\Microsoft\\Cryptography\\OID" +CRYPT_OID_REG_ENCODING_TYPE_PREFIX = "EncodingType " +CRYPT_OID_REG_DLL_VALUE_NAME = "Dll" +CRYPT_OID_REG_FUNC_NAME_VALUE_NAME = "FuncName" +CRYPT_OID_REG_FUNC_NAME_VALUE_NAME_A = "FuncName" +CRYPT_OID_REG_FLAGS_VALUE_NAME = "CryptFlags" +CRYPT_DEFAULT_OID = "DEFAULT" +CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG = 1 +CRYPT_GET_INSTALLED_OID_FUNC_FLAG = 0x1 +CRYPT_REGISTER_FIRST_INDEX = 0 +CRYPT_REGISTER_LAST_INDEX = -1 +CRYPT_MATCH_ANY_ENCODING_TYPE = -1 +CRYPT_HASH_ALG_OID_GROUP_ID = 1 +CRYPT_ENCRYPT_ALG_OID_GROUP_ID = 2 +CRYPT_PUBKEY_ALG_OID_GROUP_ID = 3 +CRYPT_SIGN_ALG_OID_GROUP_ID = 4 +CRYPT_RDN_ATTR_OID_GROUP_ID = 5 +CRYPT_EXT_OR_ATTR_OID_GROUP_ID = 6 +CRYPT_ENHKEY_USAGE_OID_GROUP_ID = 7 +CRYPT_POLICY_OID_GROUP_ID = 8 +CRYPT_TEMPLATE_OID_GROUP_ID = 9 +CRYPT_LAST_OID_GROUP_ID = 9 +CRYPT_FIRST_ALG_OID_GROUP_ID = CRYPT_HASH_ALG_OID_GROUP_ID +CRYPT_LAST_ALG_OID_GROUP_ID = CRYPT_SIGN_ALG_OID_GROUP_ID +CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG = 0x1 +CRYPT_OID_USE_PUBKEY_PARA_FOR_PKCS7_FLAG = 0x2 +CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG = 0x4 +CRYPT_OID_INFO_OID_KEY = 1 +CRYPT_OID_INFO_NAME_KEY = 2 +CRYPT_OID_INFO_ALGID_KEY = 3 +CRYPT_OID_INFO_SIGN_KEY = 4 +CRYPT_INSTALL_OID_INFO_BEFORE_FLAG = 1 +CRYPT_LOCALIZED_NAME_ENCODING_TYPE = 0 +CRYPT_LOCALIZED_NAME_OID = "LocalizedNames" +szOID_PKCS_7_DATA = "1.2.840.113549.1.7.1" +szOID_PKCS_7_SIGNED = "1.2.840.113549.1.7.2" +szOID_PKCS_7_ENVELOPED = "1.2.840.113549.1.7.3" +szOID_PKCS_7_SIGNEDANDENVELOPED = "1.2.840.113549.1.7.4" +szOID_PKCS_7_DIGESTED = "1.2.840.113549.1.7.5" +szOID_PKCS_7_ENCRYPTED = "1.2.840.113549.1.7.6" +szOID_PKCS_9_CONTENT_TYPE = "1.2.840.113549.1.9.3" +szOID_PKCS_9_MESSAGE_DIGEST = "1.2.840.113549.1.9.4" +CMSG_DATA = 1 +CMSG_SIGNED = 2 +CMSG_ENVELOPED = 3 +CMSG_SIGNED_AND_ENVELOPED = 4 +CMSG_HASHED = 5 +CMSG_ENCRYPTED = 6 + +CMSG_ALL_FLAGS = -1 +CMSG_DATA_FLAG = 1 << CMSG_DATA +CMSG_SIGNED_FLAG = 1 << CMSG_SIGNED +CMSG_ENVELOPED_FLAG = 1 << CMSG_ENVELOPED +CMSG_SIGNED_AND_ENVELOPED_FLAG = 1 << CMSG_SIGNED_AND_ENVELOPED +CMSG_HASHED_FLAG = 1 << CMSG_HASHED +CMSG_ENCRYPTED_FLAG = 1 << CMSG_ENCRYPTED +CERT_ID_ISSUER_SERIAL_NUMBER = 1 +CERT_ID_KEY_IDENTIFIER = 2 +CERT_ID_SHA1_HASH = 3 +CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE = 1 +CMSG_KEY_AGREE_STATIC_KEY_CHOICE = 2 +CMSG_MAIL_LIST_HANDLE_KEY_CHOICE = 1 +CMSG_KEY_TRANS_RECIPIENT = 1 +CMSG_KEY_AGREE_RECIPIENT = 2 +CMSG_MAIL_LIST_RECIPIENT = 3 +CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG = -2147483648 +CMSG_RC4_NO_SALT_FLAG = 0x40000000 +CMSG_INDEFINITE_LENGTH = -1 +CMSG_BARE_CONTENT_FLAG = 0x00000001 +CMSG_LENGTH_ONLY_FLAG = 0x00000002 +CMSG_DETACHED_FLAG = 0x00000004 +CMSG_AUTHENTICATED_ATTRIBUTES_FLAG = 0x00000008 +CMSG_CONTENTS_OCTETS_FLAG = 0x00000010 +CMSG_MAX_LENGTH_FLAG = 0x00000020 +CMSG_CMS_ENCAPSULATED_CONTENT_FLAG = 0x00000040 +CMSG_CRYPT_RELEASE_CONTEXT_FLAG = 0x00008000 +CMSG_TYPE_PARAM = 1 +CMSG_CONTENT_PARAM = 2 +CMSG_BARE_CONTENT_PARAM = 3 +CMSG_INNER_CONTENT_TYPE_PARAM = 4 +CMSG_SIGNER_COUNT_PARAM = 5 +CMSG_SIGNER_INFO_PARAM = 6 +CMSG_SIGNER_CERT_INFO_PARAM = 7 +CMSG_SIGNER_HASH_ALGORITHM_PARAM = 8 +CMSG_SIGNER_AUTH_ATTR_PARAM = 9 +CMSG_SIGNER_UNAUTH_ATTR_PARAM = 10 +CMSG_CERT_COUNT_PARAM = 11 +CMSG_CERT_PARAM = 12 +CMSG_CRL_COUNT_PARAM = 13 +CMSG_CRL_PARAM = 14 +CMSG_ENVELOPE_ALGORITHM_PARAM = 15 +CMSG_RECIPIENT_COUNT_PARAM = 17 +CMSG_RECIPIENT_INDEX_PARAM = 18 +CMSG_RECIPIENT_INFO_PARAM = 19 +CMSG_HASH_ALGORITHM_PARAM = 20 +CMSG_HASH_DATA_PARAM = 21 +CMSG_COMPUTED_HASH_PARAM = 22 +CMSG_ENCRYPT_PARAM = 26 +CMSG_ENCRYPTED_DIGEST = 27 +CMSG_ENCODED_SIGNER = 28 +CMSG_ENCODED_MESSAGE = 29 +CMSG_VERSION_PARAM = 30 +CMSG_ATTR_CERT_COUNT_PARAM = 31 +CMSG_ATTR_CERT_PARAM = 32 +CMSG_CMS_RECIPIENT_COUNT_PARAM = 33 +CMSG_CMS_RECIPIENT_INDEX_PARAM = 34 +CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM = 35 +CMSG_CMS_RECIPIENT_INFO_PARAM = 36 +CMSG_UNPROTECTED_ATTR_PARAM = 37 +CMSG_SIGNER_CERT_ID_PARAM = 38 +CMSG_CMS_SIGNER_INFO_PARAM = 39 +CMSG_SIGNED_DATA_V1 = 1 +CMSG_SIGNED_DATA_V3 = 3 +CMSG_SIGNED_DATA_PKCS_1_5_VERSION = CMSG_SIGNED_DATA_V1 +CMSG_SIGNED_DATA_CMS_VERSION = CMSG_SIGNED_DATA_V3 +CMSG_SIGNER_INFO_V1 = 1 +CMSG_SIGNER_INFO_V3 = 3 +CMSG_SIGNER_INFO_PKCS_1_5_VERSION = CMSG_SIGNER_INFO_V1 +CMSG_SIGNER_INFO_CMS_VERSION = CMSG_SIGNER_INFO_V3 +CMSG_HASHED_DATA_V0 = 0 +CMSG_HASHED_DATA_V2 = 2 +CMSG_HASHED_DATA_PKCS_1_5_VERSION = CMSG_HASHED_DATA_V0 +CMSG_HASHED_DATA_CMS_VERSION = CMSG_HASHED_DATA_V2 +CMSG_ENVELOPED_DATA_V0 = 0 +CMSG_ENVELOPED_DATA_V2 = 2 +CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION = CMSG_ENVELOPED_DATA_V0 +CMSG_ENVELOPED_DATA_CMS_VERSION = CMSG_ENVELOPED_DATA_V2 +CMSG_KEY_AGREE_ORIGINATOR_CERT = 1 +CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY = 2 +CMSG_ENVELOPED_RECIPIENT_V0 = 0 +CMSG_ENVELOPED_RECIPIENT_V2 = 2 +CMSG_ENVELOPED_RECIPIENT_V3 = 3 +CMSG_ENVELOPED_RECIPIENT_V4 = 4 +CMSG_KEY_TRANS_PKCS_1_5_VERSION = CMSG_ENVELOPED_RECIPIENT_V0 +CMSG_KEY_TRANS_CMS_VERSION = CMSG_ENVELOPED_RECIPIENT_V2 +CMSG_KEY_AGREE_VERSION = CMSG_ENVELOPED_RECIPIENT_V3 +CMSG_MAIL_LIST_VERSION = CMSG_ENVELOPED_RECIPIENT_V4 +CMSG_CTRL_VERIFY_SIGNATURE = 1 +CMSG_CTRL_DECRYPT = 2 +CMSG_CTRL_VERIFY_HASH = 5 +CMSG_CTRL_ADD_SIGNER = 6 +CMSG_CTRL_DEL_SIGNER = 7 +CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR = 8 +CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR = 9 +CMSG_CTRL_ADD_CERT = 10 +CMSG_CTRL_DEL_CERT = 11 +CMSG_CTRL_ADD_CRL = 12 +CMSG_CTRL_DEL_CRL = 13 +CMSG_CTRL_ADD_ATTR_CERT = 14 +CMSG_CTRL_DEL_ATTR_CERT = 15 +CMSG_CTRL_KEY_TRANS_DECRYPT = 16 +CMSG_CTRL_KEY_AGREE_DECRYPT = 17 +CMSG_CTRL_MAIL_LIST_DECRYPT = 18 +CMSG_CTRL_VERIFY_SIGNATURE_EX = 19 +CMSG_CTRL_ADD_CMS_SIGNER_INFO = 20 +CMSG_VERIFY_SIGNER_PUBKEY = 1 +CMSG_VERIFY_SIGNER_CERT = 2 +CMSG_VERIFY_SIGNER_CHAIN = 3 +CMSG_VERIFY_SIGNER_NULL = 4 +CMSG_OID_GEN_ENCRYPT_KEY_FUNC = "CryptMsgDllGenEncryptKey" +CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC = "CryptMsgDllExportEncryptKey" +CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC = "CryptMsgDllImportEncryptKey" +CMSG_CONTENT_ENCRYPT_PAD_ENCODED_LEN_FLAG = 0x00000001 +CMSG_DEFAULT_INSTALLABLE_FUNC_OID = 1 +CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG = 0x00008000 +CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC = "CryptMsgDllGenContentEncryptKey" +CMSG_KEY_TRANS_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_OID_EXPORT_KEY_TRANS_FUNC = "CryptMsgDllExportKeyTrans" +CMSG_KEY_AGREE_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_KEY_AGREE_ENCRYPT_FREE_MATERIAL_FLAG = 0x00000002 +CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_ALG_FLAG = 0x00000004 +CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_PARA_FLAG = 0x00000008 +CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_BITS_FLAG = 0x00000010 +CMSG_OID_EXPORT_KEY_AGREE_FUNC = "CryptMsgDllExportKeyAgree" +CMSG_MAIL_LIST_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_OID_EXPORT_MAIL_LIST_FUNC = "CryptMsgDllExportMailList" +CMSG_OID_IMPORT_KEY_TRANS_FUNC = "CryptMsgDllImportKeyTrans" +CMSG_OID_IMPORT_KEY_AGREE_FUNC = "CryptMsgDllImportKeyAgree" +CMSG_OID_IMPORT_MAIL_LIST_FUNC = "CryptMsgDllImportMailList" + +# Certificate property id's used with CertGetCertificateContextProperty +CERT_KEY_PROV_HANDLE_PROP_ID = 1 +CERT_KEY_PROV_INFO_PROP_ID = 2 +CERT_SHA1_HASH_PROP_ID = 3 +CERT_MD5_HASH_PROP_ID = 4 +CERT_HASH_PROP_ID = CERT_SHA1_HASH_PROP_ID +CERT_KEY_CONTEXT_PROP_ID = 5 +CERT_KEY_SPEC_PROP_ID = 6 +CERT_IE30_RESERVED_PROP_ID = 7 +CERT_PUBKEY_HASH_RESERVED_PROP_ID = 8 +CERT_ENHKEY_USAGE_PROP_ID = 9 +CERT_CTL_USAGE_PROP_ID = CERT_ENHKEY_USAGE_PROP_ID +CERT_NEXT_UPDATE_LOCATION_PROP_ID = 10 +CERT_FRIENDLY_NAME_PROP_ID = 11 +CERT_PVK_FILE_PROP_ID = 12 +CERT_DESCRIPTION_PROP_ID = 13 +CERT_ACCESS_STATE_PROP_ID = 14 +CERT_SIGNATURE_HASH_PROP_ID = 15 +CERT_SMART_CARD_DATA_PROP_ID = 16 +CERT_EFS_PROP_ID = 17 +CERT_FORTEZZA_DATA_PROP_ID = 18 +CERT_ARCHIVED_PROP_ID = 19 +CERT_KEY_IDENTIFIER_PROP_ID = 20 +CERT_AUTO_ENROLL_PROP_ID = 21 +CERT_PUBKEY_ALG_PARA_PROP_ID = 22 +CERT_CROSS_CERT_DIST_POINTS_PROP_ID = 23 +CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID = 24 +CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID = 25 +CERT_ENROLLMENT_PROP_ID = 26 +CERT_DATE_STAMP_PROP_ID = 27 +CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID = 28 +CERT_SUBJECT_NAME_MD5_HASH_PROP_ID = 29 +CERT_EXTENDED_ERROR_INFO_PROP_ID = 30 +CERT_RENEWAL_PROP_ID = 64 +CERT_ARCHIVED_KEY_HASH_PROP_ID = 65 +CERT_AUTO_ENROLL_RETRY_PROP_ID = 66 +CERT_AIA_URL_RETRIEVED_PROP_ID = 67 +CERT_AUTHORITY_INFO_ACCESS_PROP_ID = 68 +CERT_BACKED_UP_PROP_ID = 69 +CERT_OCSP_RESPONSE_PROP_ID = 70 +CERT_REQUEST_ORIGINATOR_PROP_ID = 71 +CERT_SOURCE_LOCATION_PROP_ID = 72 +CERT_SOURCE_URL_PROP_ID = 73 +CERT_NEW_KEY_PROP_ID = 74 +CERT_OCSP_CACHE_PREFIX_PROP_ID = 75 +CERT_SMART_CARD_ROOT_INFO_PROP_ID = 76 +CERT_NO_AUTO_EXPIRE_CHECK_PROP_ID = 77 +CERT_NCRYPT_KEY_HANDLE_PROP_ID = 78 +CERT_HCRYPTPROV_OR_NCRYPT_KEY_HANDLE_PROP_ID = 79 +CERT_SUBJECT_INFO_ACCESS_PROP_ID = 80 +CERT_CA_OCSP_AUTHORITY_INFO_ACCESS_PROP_ID = 81 +CERT_CA_DISABLE_CRL_PROP_ID = 82 +CERT_ROOT_PROGRAM_CERT_POLICIES_PROP_ID = 83 +CERT_ROOT_PROGRAM_NAME_CONSTRAINTS_PROP_ID = 84 +CERT_SUBJECT_OCSP_AUTHORITY_INFO_ACCESS_PROP_ID = 85 +CERT_SUBJECT_DISABLE_CRL_PROP_ID = 86 +CERT_CEP_PROP_ID = 87 +CERT_SIGN_HASH_CNG_ALG_PROP_ID = 89 +CERT_SCARD_PIN_ID_PROP_ID = 90 +CERT_SCARD_PIN_INFO_PROP_ID = 91 +CERT_FIRST_RESERVED_PROP_ID = 92 +CERT_LAST_RESERVED_PROP_ID = 0x00007FFF +CERT_FIRST_USER_PROP_ID = 0x00008000 +CERT_LAST_USER_PROP_ID = 0x0000FFFF + +szOID_CERT_PROP_ID_PREFIX = "1.3.6.1.4.1.311.10.11." +szOID_CERT_KEY_IDENTIFIER_PROP_ID = "1.3.6.1.4.1.311.10.11.20" +szOID_CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID = "1.3.6.1.4.1.311.10.11.28" +szOID_CERT_SUBJECT_NAME_MD5_HASH_PROP_ID = "1.3.6.1.4.1.311.10.11.29" +CERT_ACCESS_STATE_WRITE_PERSIST_FLAG = 0x1 +CERT_ACCESS_STATE_SYSTEM_STORE_FLAG = 0x2 +CERT_ACCESS_STATE_LM_SYSTEM_STORE_FLAG = 0x4 +CERT_SET_KEY_PROV_HANDLE_PROP_ID = 0x00000001 +CERT_SET_KEY_CONTEXT_PROP_ID = 0x00000001 +sz_CERT_STORE_PROV_MEMORY = "Memory" +sz_CERT_STORE_PROV_FILENAME_W = "File" +sz_CERT_STORE_PROV_FILENAME = sz_CERT_STORE_PROV_FILENAME_W +sz_CERT_STORE_PROV_SYSTEM_W = "System" +sz_CERT_STORE_PROV_SYSTEM = sz_CERT_STORE_PROV_SYSTEM_W +sz_CERT_STORE_PROV_PKCS7 = "PKCS7" +sz_CERT_STORE_PROV_SERIALIZED = "Serialized" +sz_CERT_STORE_PROV_COLLECTION = "Collection" +sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W = "SystemRegistry" +sz_CERT_STORE_PROV_SYSTEM_REGISTRY = sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W +sz_CERT_STORE_PROV_PHYSICAL_W = "Physical" +sz_CERT_STORE_PROV_PHYSICAL = sz_CERT_STORE_PROV_PHYSICAL_W +sz_CERT_STORE_PROV_SMART_CARD_W = "SmartCard" +sz_CERT_STORE_PROV_SMART_CARD = sz_CERT_STORE_PROV_SMART_CARD_W +sz_CERT_STORE_PROV_LDAP_W = "Ldap" +sz_CERT_STORE_PROV_LDAP = sz_CERT_STORE_PROV_LDAP_W +CERT_STORE_SIGNATURE_FLAG = 0x00000001 +CERT_STORE_TIME_VALIDITY_FLAG = 0x00000002 +CERT_STORE_REVOCATION_FLAG = 0x00000004 +CERT_STORE_NO_CRL_FLAG = 0x00010000 +CERT_STORE_NO_ISSUER_FLAG = 0x00020000 +CERT_STORE_BASE_CRL_FLAG = 0x00000100 +CERT_STORE_DELTA_CRL_FLAG = 0x00000200 +CERT_STORE_NO_CRYPT_RELEASE_FLAG = 0x00000001 +CERT_STORE_SET_LOCALIZED_NAME_FLAG = 0x00000002 +CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004 +CERT_STORE_DELETE_FLAG = 0x00000010 +CERT_STORE_UNSAFE_PHYSICAL_FLAG = 0x00000020 +CERT_STORE_SHARE_STORE_FLAG = 0x00000040 +CERT_STORE_SHARE_CONTEXT_FLAG = 0x00000080 +CERT_STORE_MANIFOLD_FLAG = 0x00000100 +CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200 +CERT_STORE_UPDATE_KEYID_FLAG = 0x00000400 +CERT_STORE_BACKUP_RESTORE_FLAG = 0x00000800 +CERT_STORE_READONLY_FLAG = 0x00008000 +CERT_STORE_OPEN_EXISTING_FLAG = 0x00004000 +CERT_STORE_CREATE_NEW_FLAG = 0x00002000 +CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000 +CERT_SYSTEM_STORE_MASK = -65536 +CERT_SYSTEM_STORE_RELOCATE_FLAG = -2147483648 +CERT_SYSTEM_STORE_UNPROTECTED_FLAG = 0x40000000 +CERT_SYSTEM_STORE_LOCATION_MASK = 0x00FF0000 +CERT_SYSTEM_STORE_LOCATION_SHIFT = 16 +CERT_SYSTEM_STORE_CURRENT_USER_ID = 1 +CERT_SYSTEM_STORE_LOCAL_MACHINE_ID = 2 +CERT_SYSTEM_STORE_CURRENT_SERVICE_ID = 4 +CERT_SYSTEM_STORE_SERVICES_ID = 5 +CERT_SYSTEM_STORE_USERS_ID = 6 +CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY_ID = 7 +CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY_ID = 8 +CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID = 9 +CERT_SYSTEM_STORE_CURRENT_USER = ( + CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +) +CERT_SYSTEM_STORE_LOCAL_MACHINE = ( + CERT_SYSTEM_STORE_LOCAL_MACHINE_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +) +CERT_SYSTEM_STORE_CURRENT_SERVICE = ( + CERT_SYSTEM_STORE_CURRENT_SERVICE_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +) +CERT_SYSTEM_STORE_SERVICES = ( + CERT_SYSTEM_STORE_SERVICES_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +) +CERT_SYSTEM_STORE_USERS = CERT_SYSTEM_STORE_USERS_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY = ( + CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +) +CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY = ( + CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +) +CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE = ( + CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT +) +CERT_PROT_ROOT_DISABLE_CURRENT_USER_FLAG = 0x1 +CERT_PROT_ROOT_INHIBIT_ADD_AT_INIT_FLAG = 0x2 +CERT_PROT_ROOT_INHIBIT_PURGE_LM_FLAG = 0x4 +CERT_PROT_ROOT_DISABLE_LM_AUTH_FLAG = 0x8 +CERT_PROT_ROOT_ONLY_LM_GPT_FLAG = 0x8 +CERT_PROT_ROOT_DISABLE_NT_AUTH_REQUIRED_FLAG = 0x10 +CERT_PROT_ROOT_DISABLE_NOT_DEFINED_NAME_CONSTRAINT_FLAG = 0x20 +CERT_TRUST_PUB_ALLOW_TRUST_MASK = 0x00000003 +CERT_TRUST_PUB_ALLOW_END_USER_TRUST = 0x00000000 +CERT_TRUST_PUB_ALLOW_MACHINE_ADMIN_TRUST = 0x00000001 +CERT_TRUST_PUB_ALLOW_ENTERPRISE_ADMIN_TRUST = 0x00000002 +CERT_TRUST_PUB_CHECK_PUBLISHER_REV_FLAG = 0x00000100 +CERT_TRUST_PUB_CHECK_TIMESTAMP_REV_FLAG = 0x00000200 + +CERT_AUTH_ROOT_AUTO_UPDATE_LOCAL_MACHINE_REGPATH = ( + r"Software\Microsoft\SystemCertificates\AuthRoot\AutoUpdate" +) +CERT_AUTH_ROOT_AUTO_UPDATE_DISABLE_UNTRUSTED_ROOT_LOGGING_FLAG = 0x1 +CERT_AUTH_ROOT_AUTO_UPDATE_DISABLE_PARTIAL_CHAIN_LOGGING_FLAG = 0x2 +CERT_AUTH_ROOT_AUTO_UPDATE_ROOT_DIR_URL_VALUE_NAME = "RootDirUrl" +CERT_AUTH_ROOT_AUTO_UPDATE_SYNC_DELTA_TIME_VALUE_NAME = "SyncDeltaTime" +CERT_AUTH_ROOT_AUTO_UPDATE_FLAGS_VALUE_NAME = "Flags" +CERT_AUTH_ROOT_CTL_FILENAME = "authroot.stl" +CERT_AUTH_ROOT_CTL_FILENAME_A = "authroot.stl" +CERT_AUTH_ROOT_CAB_FILENAME = "authrootstl.cab" +CERT_AUTH_ROOT_SEQ_FILENAME = "authrootseq.txt" +CERT_AUTH_ROOT_CERT_EXT = ".crt" + +CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH = ( + r"Software\Policies\Microsoft\SystemCertificates" +) +CERT_EFSBLOB_REGPATH = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH + r"\EFS" +CERT_EFSBLOB_VALUE_NAME = "EFSBlob" +CERT_PROT_ROOT_FLAGS_REGPATH = ( + CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH + r"\Root\ProtectedRoots" +) +CERT_PROT_ROOT_FLAGS_VALUE_NAME = "Flags" +CERT_TRUST_PUB_SAFER_GROUP_POLICY_REGPATH = ( + CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH + r"\TrustedPublisher\Safer" +) +CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH = r"Software\Microsoft\SystemCertificates" +CERT_TRUST_PUB_SAFER_LOCAL_MACHINE_REGPATH = ( + CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH + r"\TrustedPublisher\Safer" +) +CERT_TRUST_PUB_AUTHENTICODE_FLAGS_VALUE_NAME = "AuthenticodeFlags" +CERT_OCM_SUBCOMPONENTS_LOCAL_MACHINE_REGPATH = ( + r"SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OC Manager\Subcomponents" +) +CERT_OCM_SUBCOMPONENTS_ROOT_AUTO_UPDATE_VALUE_NAME = r"RootAutoUpdate" +CERT_DISABLE_ROOT_AUTO_UPDATE_REGPATH = ( + CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH + r"\AuthRoot" +) +CERT_DISABLE_ROOT_AUTO_UPDATE_VALUE_NAME = "DisableRootAutoUpdate" +CERT_AUTH_ROOT_AUTO_UPDATE_LOCAL_MACHINE_REGPATH = ( + CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH + r"\AuthRoot\AutoUpdate" +) + +CERT_REGISTRY_STORE_REMOTE_FLAG = 0x10000 +CERT_REGISTRY_STORE_SERIALIZED_FLAG = 0x20000 +CERT_REGISTRY_STORE_CLIENT_GPT_FLAG = -2147483648 +CERT_REGISTRY_STORE_LM_GPT_FLAG = 0x01000000 +CERT_REGISTRY_STORE_ROAMING_FLAG = 0x40000 +CERT_REGISTRY_STORE_MY_IE_DIRTY_FLAG = 0x80000 +CERT_IE_DIRTY_FLAGS_REGPATH = r"Software\Microsoft\Cryptography\IEDirtyFlags" + +CERT_FILE_STORE_COMMIT_ENABLE_FLAG = 0x10000 +CERT_LDAP_STORE_SIGN_FLAG = 0x10000 +CERT_LDAP_STORE_AREC_EXCLUSIVE_FLAG = 0x20000 +CERT_LDAP_STORE_OPENED_FLAG = 0x40000 +CERT_LDAP_STORE_UNBIND_FLAG = 0x80000 +CRYPT_OID_OPEN_STORE_PROV_FUNC = "CertDllOpenStoreProv" + +CERT_STORE_PROV_EXTERNAL_FLAG = 0x1 +CERT_STORE_PROV_DELETED_FLAG = 0x2 +CERT_STORE_PROV_NO_PERSIST_FLAG = 0x4 +CERT_STORE_PROV_SYSTEM_STORE_FLAG = 0x8 +CERT_STORE_PROV_LM_SYSTEM_STORE_FLAG = 0x10 +CERT_STORE_PROV_CLOSE_FUNC = 0 +CERT_STORE_PROV_READ_CERT_FUNC = 1 +CERT_STORE_PROV_WRITE_CERT_FUNC = 2 +CERT_STORE_PROV_DELETE_CERT_FUNC = 3 +CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC = 4 +CERT_STORE_PROV_READ_CRL_FUNC = 5 +CERT_STORE_PROV_WRITE_CRL_FUNC = 6 +CERT_STORE_PROV_DELETE_CRL_FUNC = 7 +CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC = 8 +CERT_STORE_PROV_READ_CTL_FUNC = 9 +CERT_STORE_PROV_WRITE_CTL_FUNC = 10 +CERT_STORE_PROV_DELETE_CTL_FUNC = 11 +CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC = 12 +CERT_STORE_PROV_CONTROL_FUNC = 13 +CERT_STORE_PROV_FIND_CERT_FUNC = 14 +CERT_STORE_PROV_FREE_FIND_CERT_FUNC = 15 +CERT_STORE_PROV_GET_CERT_PROPERTY_FUNC = 16 +CERT_STORE_PROV_FIND_CRL_FUNC = 17 +CERT_STORE_PROV_FREE_FIND_CRL_FUNC = 18 +CERT_STORE_PROV_GET_CRL_PROPERTY_FUNC = 19 +CERT_STORE_PROV_FIND_CTL_FUNC = 20 +CERT_STORE_PROV_FREE_FIND_CTL_FUNC = 21 +CERT_STORE_PROV_GET_CTL_PROPERTY_FUNC = 22 +CERT_STORE_PROV_WRITE_ADD_FLAG = 0x1 +CERT_STORE_SAVE_AS_STORE = 1 +CERT_STORE_SAVE_AS_PKCS7 = 2 +CERT_STORE_SAVE_TO_FILE = 1 +CERT_STORE_SAVE_TO_MEMORY = 2 +CERT_STORE_SAVE_TO_FILENAME_A = 3 +CERT_STORE_SAVE_TO_FILENAME_W = 4 +CERT_STORE_SAVE_TO_FILENAME = CERT_STORE_SAVE_TO_FILENAME_W +CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001 +CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002 +CERT_COMPARE_MASK = 0xFFFF +CERT_COMPARE_SHIFT = 16 +CERT_COMPARE_ANY = 0 +CERT_COMPARE_SHA1_HASH = 1 +CERT_COMPARE_NAME = 2 +CERT_COMPARE_ATTR = 3 +CERT_COMPARE_MD5_HASH = 4 +CERT_COMPARE_PROPERTY = 5 +CERT_COMPARE_PUBLIC_KEY = 6 +CERT_COMPARE_HASH = CERT_COMPARE_SHA1_HASH +CERT_COMPARE_NAME_STR_A = 7 +CERT_COMPARE_NAME_STR_W = 8 +CERT_COMPARE_KEY_SPEC = 9 +CERT_COMPARE_ENHKEY_USAGE = 10 +CERT_COMPARE_CTL_USAGE = CERT_COMPARE_ENHKEY_USAGE +CERT_COMPARE_SUBJECT_CERT = 11 +CERT_COMPARE_ISSUER_OF = 12 +CERT_COMPARE_EXISTING = 13 +CERT_COMPARE_SIGNATURE_HASH = 14 +CERT_COMPARE_KEY_IDENTIFIER = 15 +CERT_COMPARE_CERT_ID = 16 +CERT_COMPARE_CROSS_CERT_DIST_POINTS = 17 +CERT_COMPARE_PUBKEY_MD5_HASH = 18 +CERT_FIND_ANY = CERT_COMPARE_ANY << CERT_COMPARE_SHIFT +CERT_FIND_SHA1_HASH = CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT +CERT_FIND_MD5_HASH = CERT_COMPARE_MD5_HASH << CERT_COMPARE_SHIFT +CERT_FIND_SIGNATURE_HASH = CERT_COMPARE_SIGNATURE_HASH << CERT_COMPARE_SHIFT +CERT_FIND_KEY_IDENTIFIER = CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT +CERT_FIND_HASH = CERT_FIND_SHA1_HASH +CERT_FIND_PROPERTY = CERT_COMPARE_PROPERTY << CERT_COMPARE_SHIFT +CERT_FIND_PUBLIC_KEY = CERT_COMPARE_PUBLIC_KEY << CERT_COMPARE_SHIFT +CERT_FIND_SUBJECT_NAME = ( + CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG +) +CERT_FIND_SUBJECT_ATTR = ( + CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG +) +CERT_FIND_ISSUER_NAME = CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG +CERT_FIND_ISSUER_ATTR = CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG +CERT_FIND_SUBJECT_STR_A = ( + CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG +) +CERT_FIND_SUBJECT_STR_W = ( + CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG +) +CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W +CERT_FIND_ISSUER_STR_A = ( + CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG +) +CERT_FIND_ISSUER_STR_W = ( + CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG +) +CERT_FIND_ISSUER_STR = CERT_FIND_ISSUER_STR_W +CERT_FIND_KEY_SPEC = CERT_COMPARE_KEY_SPEC << CERT_COMPARE_SHIFT +CERT_FIND_ENHKEY_USAGE = CERT_COMPARE_ENHKEY_USAGE << CERT_COMPARE_SHIFT +CERT_FIND_CTL_USAGE = CERT_FIND_ENHKEY_USAGE +CERT_FIND_SUBJECT_CERT = CERT_COMPARE_SUBJECT_CERT << CERT_COMPARE_SHIFT +CERT_FIND_ISSUER_OF = CERT_COMPARE_ISSUER_OF << CERT_COMPARE_SHIFT +CERT_FIND_EXISTING = CERT_COMPARE_EXISTING << CERT_COMPARE_SHIFT +CERT_FIND_CERT_ID = CERT_COMPARE_CERT_ID << CERT_COMPARE_SHIFT +CERT_FIND_CROSS_CERT_DIST_POINTS = ( + CERT_COMPARE_CROSS_CERT_DIST_POINTS << CERT_COMPARE_SHIFT +) +CERT_FIND_PUBKEY_MD5_HASH = CERT_COMPARE_PUBKEY_MD5_HASH << CERT_COMPARE_SHIFT +CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG = 0x1 +CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = 0x2 +CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = 0x4 +CERT_FIND_NO_ENHKEY_USAGE_FLAG = 0x8 +CERT_FIND_OR_ENHKEY_USAGE_FLAG = 0x10 +CERT_FIND_VALID_ENHKEY_USAGE_FLAG = 0x20 +CERT_FIND_OPTIONAL_CTL_USAGE_FLAG = CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG +CERT_FIND_EXT_ONLY_CTL_USAGE_FLAG = CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG +CERT_FIND_PROP_ONLY_CTL_USAGE_FLAG = CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG +CERT_FIND_NO_CTL_USAGE_FLAG = CERT_FIND_NO_ENHKEY_USAGE_FLAG +CERT_FIND_OR_CTL_USAGE_FLAG = CERT_FIND_OR_ENHKEY_USAGE_FLAG +CERT_FIND_VALID_CTL_USAGE_FLAG = CERT_FIND_VALID_ENHKEY_USAGE_FLAG +CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG = -2147483648 +CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG = 0x40000000 +CTL_ENTRY_FROM_PROP_CHAIN_FLAG = 0x1 +CRL_FIND_ANY = 0 +CRL_FIND_ISSUED_BY = 1 +CRL_FIND_EXISTING = 2 +CRL_FIND_ISSUED_FOR = 3 +CRL_FIND_ISSUED_BY_AKI_FLAG = 0x1 +CRL_FIND_ISSUED_BY_SIGNATURE_FLAG = 0x2 +CRL_FIND_ISSUED_BY_DELTA_FLAG = 0x4 +CRL_FIND_ISSUED_BY_BASE_FLAG = 0x8 +CERT_STORE_ADD_NEW = 1 +CERT_STORE_ADD_USE_EXISTING = 2 +CERT_STORE_ADD_REPLACE_EXISTING = 3 +CERT_STORE_ADD_ALWAYS = 4 +CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES = 5 +CERT_STORE_ADD_NEWER = 6 +CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES = 7 +CERT_STORE_CERTIFICATE_CONTEXT = 1 +CERT_STORE_CRL_CONTEXT = 2 +CERT_STORE_CTL_CONTEXT = 3 + +CERT_STORE_ALL_CONTEXT_FLAG = -1 +CERT_STORE_CERTIFICATE_CONTEXT_FLAG = 1 << CERT_STORE_CERTIFICATE_CONTEXT +CERT_STORE_CRL_CONTEXT_FLAG = 1 << CERT_STORE_CRL_CONTEXT +CERT_STORE_CTL_CONTEXT_FLAG = 1 << CERT_STORE_CTL_CONTEXT +CTL_ANY_SUBJECT_TYPE = 1 +CTL_CERT_SUBJECT_TYPE = 2 +CTL_FIND_ANY = 0 +CTL_FIND_SHA1_HASH = 1 +CTL_FIND_MD5_HASH = 2 +CTL_FIND_USAGE = 3 +CTL_FIND_SUBJECT = 4 +CTL_FIND_EXISTING = 5 +CTL_FIND_NO_LIST_ID_CBDATA = -1 +CTL_FIND_SAME_USAGE_FLAG = 0x1 +CERT_STORE_CTRL_RESYNC = 1 +CERT_STORE_CTRL_NOTIFY_CHANGE = 2 +CERT_STORE_CTRL_COMMIT = 3 +CERT_STORE_CTRL_AUTO_RESYNC = 4 +CERT_STORE_CTRL_CANCEL_NOTIFY = 5 +CERT_STORE_CTRL_INHIBIT_DUPLICATE_HANDLE_FLAG = 0x1 +CERT_STORE_CTRL_COMMIT_FORCE_FLAG = 0x1 +CERT_STORE_CTRL_COMMIT_CLEAR_FLAG = 0x2 +CERT_STORE_LOCALIZED_NAME_PROP_ID = 0x1000 +CERT_CREATE_CONTEXT_NOCOPY_FLAG = 0x1 +CERT_CREATE_CONTEXT_SORTED_FLAG = 0x2 +CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG = 0x4 +CERT_CREATE_CONTEXT_NO_ENTRY_FLAG = 0x8 + +CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG = 0x1 +CERT_PHYSICAL_STORE_OPEN_DISABLE_FLAG = 0x2 +CERT_PHYSICAL_STORE_REMOTE_OPEN_DISABLE_FLAG = 0x4 +CERT_PHYSICAL_STORE_INSERT_COMPUTER_NAME_ENABLE_FLAG = 0x8 +CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG = 0x1 + +# Names of physical cert stores +CERT_PHYSICAL_STORE_DEFAULT_NAME = ".Default" +CERT_PHYSICAL_STORE_GROUP_POLICY_NAME = ".GroupPolicy" +CERT_PHYSICAL_STORE_LOCAL_MACHINE_NAME = ".LocalMachine" +CERT_PHYSICAL_STORE_DS_USER_CERTIFICATE_NAME = ".UserCertificate" +CERT_PHYSICAL_STORE_LOCAL_MACHINE_GROUP_POLICY_NAME = ".LocalMachineGroupPolicy" +CERT_PHYSICAL_STORE_ENTERPRISE_NAME = ".Enterprise" +CERT_PHYSICAL_STORE_AUTH_ROOT_NAME = ".AuthRoot" +CERT_PHYSICAL_STORE_SMART_CARD_NAME = ".SmartCard" + +CRYPT_OID_OPEN_SYSTEM_STORE_PROV_FUNC = "CertDllOpenSystemStoreProv" +CRYPT_OID_REGISTER_SYSTEM_STORE_FUNC = "CertDllRegisterSystemStore" +CRYPT_OID_UNREGISTER_SYSTEM_STORE_FUNC = "CertDllUnregisterSystemStore" +CRYPT_OID_ENUM_SYSTEM_STORE_FUNC = "CertDllEnumSystemStore" +CRYPT_OID_REGISTER_PHYSICAL_STORE_FUNC = "CertDllRegisterPhysicalStore" +CRYPT_OID_UNREGISTER_PHYSICAL_STORE_FUNC = "CertDllUnregisterPhysicalStore" +CRYPT_OID_ENUM_PHYSICAL_STORE_FUNC = "CertDllEnumPhysicalStore" +CRYPT_OID_SYSTEM_STORE_LOCATION_VALUE_NAME = "SystemStoreLocation" + +CMSG_TRUSTED_SIGNER_FLAG = 0x1 +CMSG_SIGNER_ONLY_FLAG = 0x2 +CMSG_USE_SIGNER_INDEX_FLAG = 0x4 +CMSG_CMS_ENCAPSULATED_CTL_FLAG = 0x00008000 +CMSG_ENCODE_SORTED_CTL_FLAG = 0x1 +CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG = 0x2 +CERT_VERIFY_INHIBIT_CTL_UPDATE_FLAG = 0x1 +CERT_VERIFY_TRUSTED_SIGNERS_FLAG = 0x2 +CERT_VERIFY_NO_TIME_CHECK_FLAG = 0x4 +CERT_VERIFY_ALLOW_MORE_USAGE_FLAG = 0x8 +CERT_VERIFY_UPDATED_CTL_FLAG = 0x1 +CERT_CONTEXT_REVOCATION_TYPE = 1 +CERT_VERIFY_REV_CHAIN_FLAG = 0x00000001 +CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION = 0x00000002 +CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG = 0x00000004 +CERT_UNICODE_IS_RDN_ATTRS_FLAG = 0x1 +CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG = 0x2 +CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB = 1 +CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT = 2 +CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL = 3 +CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY = 1 +CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT = 2 +CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN = 3 +CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL = 4 +CRYPT_DEFAULT_CONTEXT_AUTO_RELEASE_FLAG = 0x00000001 +CRYPT_DEFAULT_CONTEXT_PROCESS_FLAG = 0x00000002 +CRYPT_DEFAULT_CONTEXT_CERT_SIGN_OID = 1 +CRYPT_DEFAULT_CONTEXT_MULTI_CERT_SIGN_OID = 2 +CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC = "CryptDllExportPublicKeyInfoEx" +CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC = "CryptDllImportPublicKeyInfoEx" +CRYPT_ACQUIRE_CACHE_FLAG = 0x00000001 +CRYPT_ACQUIRE_USE_PROV_INFO_FLAG = 0x00000002 +CRYPT_ACQUIRE_COMPARE_KEY_FLAG = 0x00000004 +CRYPT_ACQUIRE_SILENT_FLAG = 0x00000040 +CRYPT_FIND_USER_KEYSET_FLAG = 0x00000001 +CRYPT_FIND_MACHINE_KEYSET_FLAG = 0x00000002 +CRYPT_FIND_SILENT_KEYSET_FLAG = 0x00000040 +CRYPT_OID_IMPORT_PRIVATE_KEY_INFO_FUNC = "CryptDllImportPrivateKeyInfoEx" +CRYPT_OID_EXPORT_PRIVATE_KEY_INFO_FUNC = "CryptDllExportPrivateKeyInfoEx" +CRYPT_DELETE_KEYSET = CRYPT_DELETEKEYSET +CERT_SIMPLE_NAME_STR = 1 +CERT_OID_NAME_STR = 2 +CERT_X500_NAME_STR = 3 +CERT_NAME_STR_SEMICOLON_FLAG = 0x40000000 +CERT_NAME_STR_NO_PLUS_FLAG = 0x20000000 +CERT_NAME_STR_NO_QUOTING_FLAG = 0x10000000 +CERT_NAME_STR_CRLF_FLAG = 0x08000000 +CERT_NAME_STR_COMMA_FLAG = 0x04000000 +CERT_NAME_STR_REVERSE_FLAG = 0x02000000 +CERT_NAME_STR_DISABLE_IE4_UTF8_FLAG = 0x00010000 +CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG = 0x00020000 +CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG = 0x00040000 +CERT_NAME_EMAIL_TYPE = 1 +CERT_NAME_RDN_TYPE = 2 +CERT_NAME_ATTR_TYPE = 3 +CERT_NAME_SIMPLE_DISPLAY_TYPE = 4 +CERT_NAME_FRIENDLY_DISPLAY_TYPE = 5 +CERT_NAME_DNS_TYPE = 6 +CERT_NAME_URL_TYPE = 7 +CERT_NAME_UPN_TYPE = 8 +CERT_NAME_ISSUER_FLAG = 0x1 +CERT_NAME_DISABLE_IE4_UTF8_FLAG = 0x00010000 +CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG = 0x00000001 +CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG = 0x00000002 +CRYPT_MESSAGE_KEYID_SIGNER_FLAG = 0x00000004 +CRYPT_MESSAGE_SILENT_KEYSET_FLAG = 0x00000040 +CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG = 0x4 +CERT_QUERY_OBJECT_FILE = 0x00000001 +CERT_QUERY_OBJECT_BLOB = 0x00000002 +CERT_QUERY_CONTENT_CERT = 1 +CERT_QUERY_CONTENT_CTL = 2 +CERT_QUERY_CONTENT_CRL = 3 +CERT_QUERY_CONTENT_SERIALIZED_STORE = 4 +CERT_QUERY_CONTENT_SERIALIZED_CERT = 5 +CERT_QUERY_CONTENT_SERIALIZED_CTL = 6 +CERT_QUERY_CONTENT_SERIALIZED_CRL = 7 +CERT_QUERY_CONTENT_PKCS7_SIGNED = 8 +CERT_QUERY_CONTENT_PKCS7_UNSIGNED = 9 +CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED = 10 +CERT_QUERY_CONTENT_PKCS10 = 11 +CERT_QUERY_CONTENT_PFX = 12 +CERT_QUERY_CONTENT_CERT_PAIR = 13 +CERT_QUERY_CONTENT_FLAG_CERT = 1 << CERT_QUERY_CONTENT_CERT +CERT_QUERY_CONTENT_FLAG_CTL = 1 << CERT_QUERY_CONTENT_CTL +CERT_QUERY_CONTENT_FLAG_CRL = 1 << CERT_QUERY_CONTENT_CRL +CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE = 1 << CERT_QUERY_CONTENT_SERIALIZED_STORE +CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT = 1 << CERT_QUERY_CONTENT_SERIALIZED_CERT +CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL = 1 << CERT_QUERY_CONTENT_SERIALIZED_CTL +CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL = 1 << CERT_QUERY_CONTENT_SERIALIZED_CRL +CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED = 1 << CERT_QUERY_CONTENT_PKCS7_SIGNED +CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED = 1 << CERT_QUERY_CONTENT_PKCS7_UNSIGNED +CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = 1 << CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED +CERT_QUERY_CONTENT_FLAG_PKCS10 = 1 << CERT_QUERY_CONTENT_PKCS10 +CERT_QUERY_CONTENT_FLAG_PFX = 1 << CERT_QUERY_CONTENT_PFX +CERT_QUERY_CONTENT_FLAG_CERT_PAIR = 1 << CERT_QUERY_CONTENT_CERT_PAIR +CERT_QUERY_CONTENT_FLAG_ALL = ( + CERT_QUERY_CONTENT_FLAG_CERT + | CERT_QUERY_CONTENT_FLAG_CTL + | CERT_QUERY_CONTENT_FLAG_CRL + | CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE + | CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT + | CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL + | CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL + | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED + | CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED + | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED + | CERT_QUERY_CONTENT_FLAG_PKCS10 + | CERT_QUERY_CONTENT_FLAG_PFX + | CERT_QUERY_CONTENT_FLAG_CERT_PAIR +) +CERT_QUERY_FORMAT_BINARY = 1 +CERT_QUERY_FORMAT_BASE64_ENCODED = 2 +CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED = 3 +CERT_QUERY_FORMAT_FLAG_BINARY = 1 << CERT_QUERY_FORMAT_BINARY +CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED = 1 << CERT_QUERY_FORMAT_BASE64_ENCODED +CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED = ( + 1 << CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED +) +CERT_QUERY_FORMAT_FLAG_ALL = ( + CERT_QUERY_FORMAT_FLAG_BINARY + | CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED + | CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED +) + +CREDENTIAL_OID_PASSWORD_CREDENTIALS_A = 1 +CREDENTIAL_OID_PASSWORD_CREDENTIALS_W = 2 +CREDENTIAL_OID_PASSWORD_CREDENTIALS = CREDENTIAL_OID_PASSWORD_CREDENTIALS_W + +SCHEME_OID_RETRIEVE_ENCODED_OBJECT_FUNC = "SchemeDllRetrieveEncodedObject" +SCHEME_OID_RETRIEVE_ENCODED_OBJECTW_FUNC = "SchemeDllRetrieveEncodedObjectW" +CONTEXT_OID_CREATE_OBJECT_CONTEXT_FUNC = "ContextDllCreateObjectContext" +CONTEXT_OID_CERTIFICATE = 1 +CONTEXT_OID_CRL = 2 +CONTEXT_OID_CTL = 3 +CONTEXT_OID_PKCS7 = 4 +CONTEXT_OID_CAPI2_ANY = 5 +CONTEXT_OID_OCSP_RESP = 6 + +CRYPT_RETRIEVE_MULTIPLE_OBJECTS = 0x00000001 +CRYPT_CACHE_ONLY_RETRIEVAL = 0x00000002 +CRYPT_WIRE_ONLY_RETRIEVAL = 0x00000004 +CRYPT_DONT_CACHE_RESULT = 0x00000008 +CRYPT_ASYNC_RETRIEVAL = 0x00000010 +CRYPT_STICKY_CACHE_RETRIEVAL = 0x00001000 +CRYPT_LDAP_SCOPE_BASE_ONLY_RETRIEVAL = 0x00002000 +CRYPT_OFFLINE_CHECK_RETRIEVAL = 0x00004000 +CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE = 0x00008000 +CRYPT_LDAP_SIGN_RETRIEVAL = 0x00010000 +CRYPT_NO_AUTH_RETRIEVAL = 0x00020000 +CRYPT_LDAP_AREC_EXCLUSIVE_RETRIEVAL = 0x00040000 +CRYPT_AIA_RETRIEVAL = 0x00080000 +CRYPT_VERIFY_CONTEXT_SIGNATURE = 0x00000020 +CRYPT_VERIFY_DATA_HASH = 0x00000040 +CRYPT_KEEP_TIME_VALID = 0x00000080 +CRYPT_DONT_VERIFY_SIGNATURE = 0x00000100 +CRYPT_DONT_CHECK_TIME_VALIDITY = 0x00000200 +CRYPT_CHECK_FRESHNESS_TIME_VALIDITY = 0x00000400 +CRYPT_ACCUMULATIVE_TIMEOUT = 0x00000800 +CRYPT_PARAM_ASYNC_RETRIEVAL_COMPLETION = 1 +CRYPT_PARAM_CANCEL_ASYNC_RETRIEVAL = 2 +CRYPT_GET_URL_FROM_PROPERTY = 0x00000001 +CRYPT_GET_URL_FROM_EXTENSION = 0x00000002 +CRYPT_GET_URL_FROM_UNAUTH_ATTRIBUTE = 0x00000004 +CRYPT_GET_URL_FROM_AUTH_ATTRIBUTE = 0x00000008 +URL_OID_GET_OBJECT_URL_FUNC = "UrlDllGetObjectUrl" +TIME_VALID_OID_GET_OBJECT_FUNC = "TimeValidDllGetObject" +TIME_VALID_OID_FLUSH_OBJECT_FUNC = "TimeValidDllFlushObject" + +TIME_VALID_OID_GET_CTL = 1 +TIME_VALID_OID_GET_CRL = 2 +TIME_VALID_OID_GET_CRL_FROM_CERT = 3 +TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CERT = 4 +TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CRL = 5 + +TIME_VALID_OID_FLUSH_CTL = 1 +TIME_VALID_OID_FLUSH_CRL = 2 +TIME_VALID_OID_FLUSH_CRL_FROM_CERT = 3 +TIME_VALID_OID_FLUSH_FRESHEST_CRL_FROM_CERT = 4 +TIME_VALID_OID_FLUSH_FRESHEST_CRL_FROM_CRL = 5 + +CRYPTPROTECT_PROMPT_ON_UNPROTECT = 0x1 +CRYPTPROTECT_PROMPT_ON_PROTECT = 0x2 +CRYPTPROTECT_PROMPT_RESERVED = 0x04 +CRYPTPROTECT_PROMPT_STRONG = 0x08 +CRYPTPROTECT_PROMPT_REQUIRE_STRONG = 0x10 +CRYPTPROTECT_UI_FORBIDDEN = 0x1 +CRYPTPROTECT_LOCAL_MACHINE = 0x4 +CRYPTPROTECT_CRED_SYNC = 0x8 +CRYPTPROTECT_AUDIT = 0x10 +CRYPTPROTECT_NO_RECOVERY = 0x20 +CRYPTPROTECT_VERIFY_PROTECTION = 0x40 +CRYPTPROTECT_CRED_REGENERATE = 0x80 +CRYPTPROTECT_FIRST_RESERVED_FLAGVAL = 0x0FFFFFFF +CRYPTPROTECT_LAST_RESERVED_FLAGVAL = -1 +CRYPTPROTECTMEMORY_BLOCK_SIZE = 16 +CRYPTPROTECTMEMORY_SAME_PROCESS = 0x00 +CRYPTPROTECTMEMORY_CROSS_PROCESS = 0x01 +CRYPTPROTECTMEMORY_SAME_LOGON = 0x02 +CERT_CREATE_SELFSIGN_NO_SIGN = 1 +CERT_CREATE_SELFSIGN_NO_KEY_INFO = 2 +CRYPT_KEYID_MACHINE_FLAG = 0x00000020 +CRYPT_KEYID_ALLOC_FLAG = 0x00008000 +CRYPT_KEYID_DELETE_FLAG = 0x00000010 +CRYPT_KEYID_SET_NEW_FLAG = 0x00002000 +CERT_CHAIN_MAX_AIA_URL_COUNT_IN_CERT_DEFAULT = 5 +CERT_CHAIN_MAX_AIA_URL_RETRIEVAL_COUNT_PER_CHAIN_DEFAULT = 10 +CERT_CHAIN_MAX_AIA_URL_RETRIEVAL_BYTE_COUNT_DEFAULT = 100000 +CERT_CHAIN_MAX_AIA_URL_RETRIEVAL_CERT_COUNT_DEFAULT = 10 +CERT_CHAIN_CACHE_END_CERT = 0x00000001 +CERT_CHAIN_THREAD_STORE_SYNC = 0x00000002 +CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL = 0x00000004 +CERT_CHAIN_USE_LOCAL_MACHINE_STORE = 0x00000008 +CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE = 0x00000010 +CERT_CHAIN_ENABLE_SHARE_STORE = 0x00000020 +CERT_TRUST_NO_ERROR = 0x00000000 +CERT_TRUST_IS_NOT_TIME_VALID = 0x00000001 +CERT_TRUST_IS_NOT_TIME_NESTED = 0x00000002 +CERT_TRUST_IS_REVOKED = 0x00000004 +CERT_TRUST_IS_NOT_SIGNATURE_VALID = 0x00000008 +CERT_TRUST_IS_NOT_VALID_FOR_USAGE = 0x00000010 +CERT_TRUST_IS_UNTRUSTED_ROOT = 0x00000020 +CERT_TRUST_REVOCATION_STATUS_UNKNOWN = 0x00000040 +CERT_TRUST_IS_CYCLIC = 0x00000080 +CERT_TRUST_INVALID_EXTENSION = 0x00000100 +CERT_TRUST_INVALID_POLICY_CONSTRAINTS = 0x00000200 +CERT_TRUST_INVALID_BASIC_CONSTRAINTS = 0x00000400 +CERT_TRUST_INVALID_NAME_CONSTRAINTS = 0x00000800 +CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT = 0x00001000 +CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x00002000 +CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x00004000 +CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT = 0x00008000 +CERT_TRUST_IS_OFFLINE_REVOCATION = 0x01000000 +CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY = 0x02000000 +CERT_TRUST_IS_PARTIAL_CHAIN = 0x00010000 +CERT_TRUST_CTL_IS_NOT_TIME_VALID = 0x00020000 +CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID = 0x00040000 +CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE = 0x00080000 +CERT_TRUST_HAS_EXACT_MATCH_ISSUER = 0x00000001 +CERT_TRUST_HAS_KEY_MATCH_ISSUER = 0x00000002 +CERT_TRUST_HAS_NAME_MATCH_ISSUER = 0x00000004 +CERT_TRUST_IS_SELF_SIGNED = 0x00000008 +CERT_TRUST_HAS_PREFERRED_ISSUER = 0x00000100 +CERT_TRUST_HAS_ISSUANCE_CHAIN_POLICY = 0x00000200 +CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS = 0x00000400 +CERT_TRUST_IS_COMPLEX_CHAIN = 0x00010000 +USAGE_MATCH_TYPE_AND = 0x00000000 +USAGE_MATCH_TYPE_OR = 0x00000001 +CERT_CHAIN_REVOCATION_CHECK_END_CERT = 0x10000000 +CERT_CHAIN_REVOCATION_CHECK_CHAIN = 0x20000000 +CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x40000000 +CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY = -2147483648 +CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT = 0x08000000 +CERT_CHAIN_DISABLE_PASS1_QUALITY_FILTERING = 0x00000040 +CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS = 0x00000080 +CERT_CHAIN_DISABLE_AUTH_ROOT_AUTO_UPDATE = 0x00000100 +CERT_CHAIN_TIMESTAMP_TIME = 0x00000200 +REVOCATION_OID_CRL_REVOCATION = 1 +CERT_CHAIN_FIND_BY_ISSUER = 1 +CERT_CHAIN_FIND_BY_ISSUER_COMPARE_KEY_FLAG = 0x0001 +CERT_CHAIN_FIND_BY_ISSUER_COMPLEX_CHAIN_FLAG = 0x0002 +CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG = 0x0004 +CERT_CHAIN_FIND_BY_ISSUER_LOCAL_MACHINE_FLAG = 0x0008 +CERT_CHAIN_FIND_BY_ISSUER_NO_KEY_FLAG = 0x4000 +CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG = 0x8000 +CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG = 0x00000001 +CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG = 0x00000002 +CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG = 0x00000004 +CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG = 0x00000008 +CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS = ( + CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG + | CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG + | CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG +) +CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG = 0x00000010 +CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG = 0x00000020 +CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG = 0x00000040 +CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG = 0x00000080 +CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG = 0x00000100 +CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG = 0x00000200 +CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG = 0x00000400 +CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG = 0x00000800 +CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS = ( + CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG + | CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG + | CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG + | CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG +) +CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG = 0x00008000 +CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG = 0x00004000 +CRYPT_OID_VERIFY_CERTIFICATE_CHAIN_POLICY_FUNC = "CertDllVerifyCertificateChainPolicy" +AUTHTYPE_CLIENT = 1 +AUTHTYPE_SERVER = 2 +BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_CA_FLAG = -2147483648 +BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_END_ENTITY_FLAG = 0x40000000 +MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG = 0x00010000 +CRYPT_STRING_BASE64HEADER = 0x00000000 +CRYPT_STRING_BASE64 = 0x00000001 +CRYPT_STRING_BINARY = 0x00000002 +CRYPT_STRING_BASE64REQUESTHEADER = 0x00000003 +CRYPT_STRING_HEX = 0x00000004 +CRYPT_STRING_HEXASCII = 0x00000005 +CRYPT_STRING_BASE64_ANY = 0x00000006 +CRYPT_STRING_ANY = 0x00000007 +CRYPT_STRING_HEX_ANY = 0x00000008 +CRYPT_STRING_BASE64X509CRLHEADER = 0x00000009 +CRYPT_STRING_HEXADDR = 0x0000000A +CRYPT_STRING_HEXASCIIADDR = 0x0000000B +CRYPT_STRING_NOCR = -2147483648 +CRYPT_USER_KEYSET = 0x00001000 +PKCS12_IMPORT_RESERVED_MASK = -65536 +REPORT_NO_PRIVATE_KEY = 0x0001 +REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY = 0x0002 +EXPORT_PRIVATE_KEYS = 0x0004 +PKCS12_EXPORT_RESERVED_MASK = -65536 + +# Certificate store provider types used with CertOpenStore +CERT_STORE_PROV_MSG = 1 +CERT_STORE_PROV_MEMORY = 2 +CERT_STORE_PROV_FILE = 3 +CERT_STORE_PROV_REG = 4 +CERT_STORE_PROV_PKCS7 = 5 +CERT_STORE_PROV_SERIALIZED = 6 +CERT_STORE_PROV_FILENAME = 8 +CERT_STORE_PROV_SYSTEM = 10 +CERT_STORE_PROV_COLLECTION = 11 +CERT_STORE_PROV_SYSTEM_REGISTRY = 13 +CERT_STORE_PROV_PHYSICAL = 14 +CERT_STORE_PROV_SMART_CARD = 15 +CERT_STORE_PROV_LDAP = 16 + +URL_OID_CERTIFICATE_ISSUER = 1 +URL_OID_CERTIFICATE_CRL_DIST_POINT = 2 +URL_OID_CTL_ISSUER = 3 +URL_OID_CTL_NEXT_UPDATE = 4 +URL_OID_CRL_ISSUER = 5 +URL_OID_CERTIFICATE_FRESHEST_CRL = 6 +URL_OID_CRL_FRESHEST_CRL = 7 +URL_OID_CROSS_CERT_DIST_POINT = 8 +URL_OID_CERTIFICATE_OCSP = 9 +URL_OID_CERTIFICATE_OCSP_AND_CRL_DIST_POINT = 10 +URL_OID_CERTIFICATE_CRL_DIST_POINT_AND_OCSP = 11 +URL_OID_CROSS_CERT_SUBJECT_INFO_ACCESS = 12 +URL_OID_CERTIFICATE_ONLY_OCSP = 13 diff --git a/MLPY/Lib/site-packages/win32/lib/win32evtlogutil.py b/MLPY/Lib/site-packages/win32/lib/win32evtlogutil.py new file mode 100644 index 0000000000000000000000000000000000000000..78e231c9945278a3ac6f3131ccc8cd8ba8cb0aff --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32evtlogutil.py @@ -0,0 +1,229 @@ +"""Event Log Utilities - helper for win32evtlog.pyd +""" + +import win32api +import win32con +import win32evtlog +import winerror + +error = win32api.error # The error the evtlog module raises. + +langid = win32api.MAKELANGID(win32con.LANG_NEUTRAL, win32con.SUBLANG_NEUTRAL) + + +def AddSourceToRegistry( + appName, + msgDLL=None, + eventLogType="Application", + eventLogFlags=None, + categoryDLL=None, + categoryCount=0, +): + """Add a source of messages to the event log. + + Allows Python program to register a custom source of messages in the + registry. You must also provide the DLL name that has the message table, so the + full message text appears in the event log. + + Note that the win32evtlog.pyd file has a number of string entries with just "%1" + built in, so many Python programs can simply use this DLL. Disadvantages are that + you do not get language translation, and the full text is stored in the event log, + blowing the size of the log up. + """ + + # When an application uses the RegisterEventSource or OpenEventLog + # function to get a handle of an event log, the event logging service + # searches for the specified source name in the registry. You can add a + # new source name to the registry by opening a new registry subkey + # under the Application key and adding registry values to the new + # subkey. + + if msgDLL is None: + msgDLL = win32evtlog.__file__ + # Create a new key for our application + hkey = win32api.RegCreateKey( + win32con.HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s" + % (eventLogType, appName), + ) + + # Add the Event-ID message-file name to the subkey. + win32api.RegSetValueEx( + hkey, + "EventMessageFile", # value name \ + 0, # reserved \ + win32con.REG_EXPAND_SZ, # value type \ + msgDLL, + ) + + # Set the supported types flags and add it to the subkey. + if eventLogFlags is None: + eventLogFlags = ( + win32evtlog.EVENTLOG_ERROR_TYPE + | win32evtlog.EVENTLOG_WARNING_TYPE + | win32evtlog.EVENTLOG_INFORMATION_TYPE + ) + win32api.RegSetValueEx( + hkey, # subkey handle \ + "TypesSupported", # value name \ + 0, # reserved \ + win32con.REG_DWORD, # value type \ + eventLogFlags, + ) + + if categoryCount > 0: + # Optionally, you can specify a message file that contains the categories + if categoryDLL is None: + categoryDLL = win32evtlog.__file__ + win32api.RegSetValueEx( + hkey, # subkey handle \ + "CategoryMessageFile", # value name \ + 0, # reserved \ + win32con.REG_EXPAND_SZ, # value type \ + categoryDLL, + ) + + win32api.RegSetValueEx( + hkey, # subkey handle \ + "CategoryCount", # value name \ + 0, # reserved \ + win32con.REG_DWORD, # value type \ + categoryCount, + ) + win32api.RegCloseKey(hkey) + + +def RemoveSourceFromRegistry(appName, eventLogType="Application"): + """Removes a source of messages from the event log.""" + + # Delete our key + try: + win32api.RegDeleteKey( + win32con.HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s" + % (eventLogType, appName), + ) + except win32api.error as exc: + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + + +def ReportEvent( + appName, + eventID, + eventCategory=0, + eventType=win32evtlog.EVENTLOG_ERROR_TYPE, + strings=None, + data=None, + sid=None, +): + """Report an event for a previously added event source.""" + # Get a handle to the Application event log + hAppLog = win32evtlog.RegisterEventSource(None, appName) + + # Now report the event, which will add this event to the event log */ + win32evtlog.ReportEvent( + hAppLog, # event-log handle \ + eventType, + eventCategory, + eventID, + sid, + strings, + data, + ) + + win32evtlog.DeregisterEventSource(hAppLog) + + +def FormatMessage(eventLogRecord, logType="Application"): + """Given a tuple from ReadEventLog, and optionally where the event + record came from, load the message, and process message inserts. + + Note that this function may raise win32api.error. See also the + function SafeFormatMessage which will return None if the message can + not be processed. + """ + + # From the event log source name, we know the name of the registry + # key to look under for the name of the message DLL that contains + # the messages we need to extract with FormatMessage. So first get + # the event log source name... + keyName = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s" % ( + logType, + eventLogRecord.SourceName, + ) + + # Now open this key and get the EventMessageFile value, which is + # the name of the message DLL. + handle = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, keyName) + try: + dllNames = win32api.RegQueryValueEx(handle, "EventMessageFile")[0].split(";") + # Win2k etc appear to allow multiple DLL names + data = None + for dllName in dllNames: + try: + # Expand environment variable strings in the message DLL path name, + # in case any are there. + dllName = win32api.ExpandEnvironmentStrings(dllName) + + dllHandle = win32api.LoadLibraryEx( + dllName, 0, win32con.LOAD_LIBRARY_AS_DATAFILE + ) + try: + data = win32api.FormatMessageW( + win32con.FORMAT_MESSAGE_FROM_HMODULE, + dllHandle, + eventLogRecord.EventID, + langid, + eventLogRecord.StringInserts, + ) + finally: + win32api.FreeLibrary(dllHandle) + except win32api.error: + pass # Not in this DLL - try the next + if data is not None: + break + finally: + win32api.RegCloseKey(handle) + return data or "" # Don't want "None" ever being returned. + + +def SafeFormatMessage(eventLogRecord, logType=None): + """As for FormatMessage, except returns an error message if + the message can not be processed. + """ + if logType is None: + logType = "Application" + try: + return FormatMessage(eventLogRecord, logType) + except win32api.error: + if eventLogRecord.StringInserts is None: + desc = "" + else: + desc = ", ".join(eventLogRecord.StringInserts) + return ( + "" + % ( + winerror.HRESULT_CODE(eventLogRecord.EventID), + eventLogRecord.SourceName, + desc, + ) + ) + + +def FeedEventLogRecords( + feeder, machineName=None, logName="Application", readFlags=None +): + if readFlags is None: + readFlags = ( + win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ + ) + h = win32evtlog.OpenEventLog(machineName, logName) + try: + while 1: + objects = win32evtlog.ReadEventLog(h, readFlags, 0) + if not objects: + break + map(lambda item, feeder=feeder: feeder(*(item,)), objects) + finally: + win32evtlog.CloseEventLog(h) diff --git a/MLPY/Lib/site-packages/win32/lib/win32gui_struct.py b/MLPY/Lib/site-packages/win32/lib/win32gui_struct.py new file mode 100644 index 0000000000000000000000000000000000000000..86623ae3230dd4e4f5fea208565a0b5cc9b622cb --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32gui_struct.py @@ -0,0 +1,999 @@ +# This is a work in progress - see Demos/win32gui_menu.py + +# win32gui_struct.py - helpers for working with various win32gui structures. +# As win32gui is "light-weight", it does not define objects for all possible +# win32 structures - in general, "buffer" objects are passed around - it is +# the callers responsibility to pack the buffer in the correct format. +# +# This module defines some helpers for the commonly used structures. +# +# In general, each structure has 3 functions: +# +# buffer, extras = PackSTRUCTURE(items, ...) +# item, ... = UnpackSTRUCTURE(buffer) +# buffer, extras = EmtpySTRUCTURE(...) +# +# 'extras' is always items that must be held along with the buffer, as the +# buffer refers to these object's memory. +# For structures that support a 'mask', this mask is hidden from the user - if +# 'None' is passed, the mask flag will not be set, or on return, None will +# be returned for the value if the mask is not set. +# +# NOTE: I considered making these structures look like real classes, and +# support 'attributes' etc - however, ctypes already has a good structure +# mechanism - I think it makes more sense to support ctype structures +# at the win32gui level, then there will be no need for this module at all. +# XXX - the above makes sense in terms of what is built and passed to +# win32gui (ie, the Pack* functions) - but doesn't make as much sense for +# the Unpack* functions, where the aim is user convenience. + +import array +import struct +import sys + +import commctrl +import pywintypes +import win32con +import win32gui + +is64bit = "64 bit" in sys.version + +try: + from collections import namedtuple + + def _MakeResult(names_str, values): + names = names_str.split() + nt = namedtuple(names[0], names[1:]) + return nt(*values) + +except ImportError: + # no namedtuple support - just return the values as a normal tuple. + def _MakeResult(names_str, values): + return values + + +_nmhdr_fmt = "PPi" +if is64bit: + # When the item past the NMHDR gets aligned (eg, when it is a struct) + # we need this many bytes padding. + _nmhdr_align_padding = "xxxx" +else: + _nmhdr_align_padding = "" + +# Encode a string suitable for passing in a win32gui related structure +# If win32gui is built with UNICODE defined (ie, py3k), then functions +# like InsertMenuItem are actually calling InsertMenuItemW etc, so all +# strings will need to be unicode. +if win32gui.UNICODE: + + def _make_text_buffer(text): + # XXX - at this stage win32gui.UNICODE is only True in py3k, + # and in py3k is makes sense to reject bytes. + if not isinstance(text, str): + raise TypeError("MENUITEMINFO text must be unicode") + data = (text + "\0").encode("utf-16le") + return array.array("b", data) + +else: + + def _make_text_buffer(text): + if isinstance(text, str): + text = text.encode("mbcs") + return array.array("b", text + "\0") + + +# make an 'empty' buffer, ready for filling with cch characters. +def _make_empty_text_buffer(cch): + return _make_text_buffer("\0" * cch) + + +if sys.version_info < (3, 0): + + def _make_memory(ob): + return str(buffer(ob)) + + def _make_bytes(sval): + return sval + +else: + + def _make_memory(ob): + return bytes(memoryview(ob)) + + def _make_bytes(sval): + return sval.encode("ascii") + + +# Generic WM_NOTIFY unpacking +def UnpackWMNOTIFY(lparam): + format = "PPi" + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + return _MakeResult("WMNOTIFY hwndFrom idFrom code", struct.unpack(format, buf)) + + +def UnpackNMITEMACTIVATE(lparam): + format = _nmhdr_fmt + _nmhdr_align_padding + if is64bit: + # the struct module doesn't handle this correctly as some of the items + # are actually structs in structs, which get individually aligned. + format = format + "iiiiiiixxxxP" + else: + format = format + "iiiiiiiP" + buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam) + return _MakeResult( + "NMITEMACTIVATE hwndFrom idFrom code iItem iSubItem uNewState uOldState uChanged actionx actiony lParam", + struct.unpack(format, buf), + ) + + +# MENUITEMINFO struct +# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Resources/Menus/MenuReference/MenuStructures/MENUITEMINFO.asp +# We use the struct module to pack and unpack strings as MENUITEMINFO +# structures. We also have special handling for the 'fMask' item in that +# structure to avoid the caller needing to explicitly check validity +# (None is used if the mask excludes/should exclude the value) +_menuiteminfo_fmt = "5i5PiP" + + +def PackMENUITEMINFO( + fType=None, + fState=None, + wID=None, + hSubMenu=None, + hbmpChecked=None, + hbmpUnchecked=None, + dwItemData=None, + text=None, + hbmpItem=None, + dwTypeData=None, +): + # 'extras' are objects the caller must keep a reference to (as their + # memory is used) for the lifetime of the INFO item. + extras = [] + # ack - dwItemData and dwTypeData were confused for a while... + assert ( + dwItemData is None or dwTypeData is None + ), "sorry - these were confused - you probably want dwItemData" + # if we are a long way past 209, then we can nuke the above... + if dwTypeData is not None: + import warnings + + warnings.warn("PackMENUITEMINFO: please use dwItemData instead of dwTypeData") + if dwItemData is None: + dwItemData = dwTypeData or 0 + + fMask = 0 + if fType is None: + fType = 0 + else: + fMask |= win32con.MIIM_FTYPE + if fState is None: + fState = 0 + else: + fMask |= win32con.MIIM_STATE + if wID is None: + wID = 0 + else: + fMask |= win32con.MIIM_ID + if hSubMenu is None: + hSubMenu = 0 + else: + fMask |= win32con.MIIM_SUBMENU + if hbmpChecked is None: + assert hbmpUnchecked is None, "neither or both checkmark bmps must be given" + hbmpChecked = hbmpUnchecked = 0 + else: + assert hbmpUnchecked is not None, "neither or both checkmark bmps must be given" + fMask |= win32con.MIIM_CHECKMARKS + if dwItemData is None: + dwItemData = 0 + else: + fMask |= win32con.MIIM_DATA + if hbmpItem is None: + hbmpItem = 0 + else: + fMask |= win32con.MIIM_BITMAP + if text is not None: + fMask |= win32con.MIIM_STRING + str_buf = _make_text_buffer(text) + cch = len(text) + # We are taking address of strbuf - it must not die until windows + # has finished with our structure. + lptext = str_buf.buffer_info()[0] + extras.append(str_buf) + else: + lptext = 0 + cch = 0 + # Create the struct. + # 'P' format does not accept PyHANDLE's ! + item = struct.pack( + _menuiteminfo_fmt, + struct.calcsize(_menuiteminfo_fmt), # cbSize + fMask, + fType, + fState, + wID, + int(hSubMenu), + int(hbmpChecked), + int(hbmpUnchecked), + dwItemData, + lptext, + cch, + int(hbmpItem), + ) + # Now copy the string to a writable buffer, so that the result + # could be passed to a 'Get' function + return array.array("b", item), extras + + +def UnpackMENUITEMINFO(s): + ( + cb, + fMask, + fType, + fState, + wID, + hSubMenu, + hbmpChecked, + hbmpUnchecked, + dwItemData, + lptext, + cch, + hbmpItem, + ) = struct.unpack(_menuiteminfo_fmt, s) + assert cb == len(s) + if fMask & win32con.MIIM_FTYPE == 0: + fType = None + if fMask & win32con.MIIM_STATE == 0: + fState = None + if fMask & win32con.MIIM_ID == 0: + wID = None + if fMask & win32con.MIIM_SUBMENU == 0: + hSubMenu = None + if fMask & win32con.MIIM_CHECKMARKS == 0: + hbmpChecked = hbmpUnchecked = None + if fMask & win32con.MIIM_DATA == 0: + dwItemData = None + if fMask & win32con.MIIM_BITMAP == 0: + hbmpItem = None + if fMask & win32con.MIIM_STRING: + text = win32gui.PyGetString(lptext, cch) + else: + text = None + return _MakeResult( + "MENUITEMINFO fType fState wID hSubMenu hbmpChecked " + "hbmpUnchecked dwItemData text hbmpItem", + ( + fType, + fState, + wID, + hSubMenu, + hbmpChecked, + hbmpUnchecked, + dwItemData, + text, + hbmpItem, + ), + ) + + +def EmptyMENUITEMINFO(mask=None, text_buf_size=512): + # text_buf_size is number of *characters* - not necessarily no of bytes. + extra = [] + if mask is None: + mask = ( + win32con.MIIM_BITMAP + | win32con.MIIM_CHECKMARKS + | win32con.MIIM_DATA + | win32con.MIIM_FTYPE + | win32con.MIIM_ID + | win32con.MIIM_STATE + | win32con.MIIM_STRING + | win32con.MIIM_SUBMENU + ) + # Note: No MIIM_TYPE - this screws win2k/98. + + if mask & win32con.MIIM_STRING: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + + # Now copy the string to a writable buffer, so that the result + # could be passed to a 'Get' function + buf = struct.pack( + _menuiteminfo_fmt, + struct.calcsize(_menuiteminfo_fmt), # cbSize + mask, + 0, # fType, + 0, # fState, + 0, # wID, + 0, # hSubMenu, + 0, # hbmpChecked, + 0, # hbmpUnchecked, + 0, # dwItemData, + text_addr, + text_buf_size, + 0, # hbmpItem + ) + return array.array("b", buf), extra + + +# MENUINFO struct +_menuinfo_fmt = "iiiiPiP" + + +def PackMENUINFO( + dwStyle=None, + cyMax=None, + hbrBack=None, + dwContextHelpID=None, + dwMenuData=None, + fMask=0, +): + if dwStyle is None: + dwStyle = 0 + else: + fMask |= win32con.MIM_STYLE + if cyMax is None: + cyMax = 0 + else: + fMask |= win32con.MIM_MAXHEIGHT + if hbrBack is None: + hbrBack = 0 + else: + fMask |= win32con.MIM_BACKGROUND + if dwContextHelpID is None: + dwContextHelpID = 0 + else: + fMask |= win32con.MIM_HELPID + if dwMenuData is None: + dwMenuData = 0 + else: + fMask |= win32con.MIM_MENUDATA + # Create the struct. + item = struct.pack( + _menuinfo_fmt, + struct.calcsize(_menuinfo_fmt), # cbSize + fMask, + dwStyle, + cyMax, + hbrBack, + dwContextHelpID, + dwMenuData, + ) + return array.array("b", item) + + +def UnpackMENUINFO(s): + (cb, fMask, dwStyle, cyMax, hbrBack, dwContextHelpID, dwMenuData) = struct.unpack( + _menuinfo_fmt, s + ) + assert cb == len(s) + if fMask & win32con.MIM_STYLE == 0: + dwStyle = None + if fMask & win32con.MIM_MAXHEIGHT == 0: + cyMax = None + if fMask & win32con.MIM_BACKGROUND == 0: + hbrBack = None + if fMask & win32con.MIM_HELPID == 0: + dwContextHelpID = None + if fMask & win32con.MIM_MENUDATA == 0: + dwMenuData = None + return _MakeResult( + "MENUINFO dwStyle cyMax hbrBack dwContextHelpID dwMenuData", + (dwStyle, cyMax, hbrBack, dwContextHelpID, dwMenuData), + ) + + +def EmptyMENUINFO(mask=None): + if mask is None: + mask = ( + win32con.MIM_STYLE + | win32con.MIM_MAXHEIGHT + | win32con.MIM_BACKGROUND + | win32con.MIM_HELPID + | win32con.MIM_MENUDATA + ) + + buf = struct.pack( + _menuinfo_fmt, + struct.calcsize(_menuinfo_fmt), # cbSize + mask, + 0, # dwStyle + 0, # cyMax + 0, # hbrBack, + 0, # dwContextHelpID, + 0, # dwMenuData, + ) + return array.array("b", buf) + + +########################################################################## +# +# Tree View structure support - TVITEM, TVINSERTSTRUCT and TVDISPINFO +# +########################################################################## + +# XXX - Note that the following implementation of TreeView structures is ripped +# XXX - from the SpamBayes project. It may not quite work correctly yet - I +# XXX - intend checking them later - but having them is better than not at all! + +_tvitem_fmt = "iPiiPiiiiP" + + +# Helpers for the ugly win32 structure packing/unpacking +# XXX - Note that functions using _GetMaskAndVal run 3x faster if they are +# 'inlined' into the function - see PackLVITEM. If the profiler points at +# _GetMaskAndVal(), you should nuke it (patches welcome once they have been +# tested) +def _GetMaskAndVal(val, default, mask, flag): + if val is None: + return mask, default + else: + if flag is not None: + mask |= flag + return mask, val + + +def PackTVINSERTSTRUCT(parent, insertAfter, tvitem): + tvitem_buf, extra = PackTVITEM(*tvitem) + tvitem_buf = tvitem_buf.tobytes() + format = "PP%ds" % len(tvitem_buf) + return struct.pack(format, parent, insertAfter, tvitem_buf), extra + + +def PackTVITEM(hitem, state, stateMask, text, image, selimage, citems, param): + extra = [] # objects we must keep references to + mask = 0 + mask, hitem = _GetMaskAndVal(hitem, 0, mask, commctrl.TVIF_HANDLE) + mask, state = _GetMaskAndVal(state, 0, mask, commctrl.TVIF_STATE) + if not mask & commctrl.TVIF_STATE: + stateMask = 0 + mask, text = _GetMaskAndVal(text, None, mask, commctrl.TVIF_TEXT) + mask, image = _GetMaskAndVal(image, 0, mask, commctrl.TVIF_IMAGE) + mask, selimage = _GetMaskAndVal(selimage, 0, mask, commctrl.TVIF_SELECTEDIMAGE) + mask, citems = _GetMaskAndVal(citems, 0, mask, commctrl.TVIF_CHILDREN) + mask, param = _GetMaskAndVal(param, 0, mask, commctrl.TVIF_PARAM) + if text is None: + text_addr = text_len = 0 + else: + text_buffer = _make_text_buffer(text) + text_len = len(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + buf = struct.pack( + _tvitem_fmt, + mask, + hitem, + state, + stateMask, + text_addr, + text_len, # text + image, + selimage, + citems, + param, + ) + return array.array("b", buf), extra + + +# Make a new buffer suitable for querying hitem's attributes. +def EmptyTVITEM(hitem, mask=None, text_buf_size=512): + extra = [] # objects we must keep references to + if mask is None: + mask = ( + commctrl.TVIF_HANDLE + | commctrl.TVIF_STATE + | commctrl.TVIF_TEXT + | commctrl.TVIF_IMAGE + | commctrl.TVIF_SELECTEDIMAGE + | commctrl.TVIF_CHILDREN + | commctrl.TVIF_PARAM + ) + if mask & commctrl.TVIF_TEXT: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + buf = struct.pack( + _tvitem_fmt, mask, hitem, 0, 0, text_addr, text_buf_size, 0, 0, 0, 0 # text + ) + return array.array("b", buf), extra + + +def UnpackTVITEM(buffer): + ( + item_mask, + item_hItem, + item_state, + item_stateMask, + item_textptr, + item_cchText, + item_image, + item_selimage, + item_cChildren, + item_param, + ) = struct.unpack(_tvitem_fmt, buffer) + # ensure only items listed by the mask are valid (except we assume the + # handle is always valid - some notifications (eg, TVN_ENDLABELEDIT) set a + # mask that doesn't include the handle, but the docs explicity say it is.) + if not (item_mask & commctrl.TVIF_TEXT): + item_textptr = item_cchText = None + if not (item_mask & commctrl.TVIF_CHILDREN): + item_cChildren = None + if not (item_mask & commctrl.TVIF_IMAGE): + item_image = None + if not (item_mask & commctrl.TVIF_PARAM): + item_param = None + if not (item_mask & commctrl.TVIF_SELECTEDIMAGE): + item_selimage = None + if not (item_mask & commctrl.TVIF_STATE): + item_state = item_stateMask = None + + if item_textptr: + text = win32gui.PyGetString(item_textptr) + else: + text = None + return _MakeResult( + "TVITEM item_hItem item_state item_stateMask " + "text item_image item_selimage item_cChildren item_param", + ( + item_hItem, + item_state, + item_stateMask, + text, + item_image, + item_selimage, + item_cChildren, + item_param, + ), + ) + + +# Unpack the lparm from a "TVNOTIFY" message +def UnpackTVNOTIFY(lparam): + item_size = struct.calcsize(_tvitem_fmt) + format = _nmhdr_fmt + _nmhdr_align_padding + if is64bit: + format = format + "ixxxx" + else: + format = format + "i" + format = format + "%ds%ds" % (item_size, item_size) + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + hwndFrom, id, code, action, buf_old, buf_new = struct.unpack(format, buf) + item_old = UnpackTVITEM(buf_old) + item_new = UnpackTVITEM(buf_new) + return _MakeResult( + "TVNOTIFY hwndFrom id code action item_old item_new", + (hwndFrom, id, code, action, item_old, item_new), + ) + + +def UnpackTVDISPINFO(lparam): + item_size = struct.calcsize(_tvitem_fmt) + format = "PPi%ds" % (item_size,) + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + hwndFrom, id, code, buf_item = struct.unpack(format, buf) + item = UnpackTVITEM(buf_item) + return _MakeResult("TVDISPINFO hwndFrom id code item", (hwndFrom, id, code, item)) + + +# +# List view items +_lvitem_fmt = "iiiiiPiiPi" + + +def PackLVITEM( + item=None, + subItem=None, + state=None, + stateMask=None, + text=None, + image=None, + param=None, + indent=None, +): + extra = [] # objects we must keep references to + mask = 0 + # _GetMaskAndVal adds quite a bit of overhead to this function. + if item is None: + item = 0 # No mask for item + if subItem is None: + subItem = 0 # No mask for sibItem + if state is None: + state = 0 + stateMask = 0 + else: + mask |= commctrl.LVIF_STATE + if stateMask is None: + stateMask = state + + if image is None: + image = 0 + else: + mask |= commctrl.LVIF_IMAGE + if param is None: + param = 0 + else: + mask |= commctrl.LVIF_PARAM + if indent is None: + indent = 0 + else: + mask |= commctrl.LVIF_INDENT + + if text is None: + text_addr = text_len = 0 + else: + mask |= commctrl.LVIF_TEXT + text_buffer = _make_text_buffer(text) + text_len = len(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + buf = struct.pack( + _lvitem_fmt, + mask, + item, + subItem, + state, + stateMask, + text_addr, + text_len, # text + image, + param, + indent, + ) + return array.array("b", buf), extra + + +def UnpackLVITEM(buffer): + ( + item_mask, + item_item, + item_subItem, + item_state, + item_stateMask, + item_textptr, + item_cchText, + item_image, + item_param, + item_indent, + ) = struct.unpack(_lvitem_fmt, buffer) + # ensure only items listed by the mask are valid + if not (item_mask & commctrl.LVIF_TEXT): + item_textptr = item_cchText = None + if not (item_mask & commctrl.LVIF_IMAGE): + item_image = None + if not (item_mask & commctrl.LVIF_PARAM): + item_param = None + if not (item_mask & commctrl.LVIF_INDENT): + item_indent = None + if not (item_mask & commctrl.LVIF_STATE): + item_state = item_stateMask = None + + if item_textptr: + text = win32gui.PyGetString(item_textptr) + else: + text = None + return _MakeResult( + "LVITEM item_item item_subItem item_state " + "item_stateMask text item_image item_param item_indent", + ( + item_item, + item_subItem, + item_state, + item_stateMask, + text, + item_image, + item_param, + item_indent, + ), + ) + + +# Unpack an "LVNOTIFY" message +def UnpackLVDISPINFO(lparam): + item_size = struct.calcsize(_lvitem_fmt) + format = _nmhdr_fmt + _nmhdr_align_padding + ("%ds" % (item_size,)) + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + hwndFrom, id, code, buf_item = struct.unpack(format, buf) + item = UnpackLVITEM(buf_item) + return _MakeResult("LVDISPINFO hwndFrom id code item", (hwndFrom, id, code, item)) + + +def UnpackLVNOTIFY(lparam): + format = _nmhdr_fmt + _nmhdr_align_padding + "7i" + if is64bit: + format = format + "xxxx" # point needs padding. + format = format + "P" + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + ( + hwndFrom, + id, + code, + item, + subitem, + newstate, + oldstate, + changed, + pt_x, + pt_y, + lparam, + ) = struct.unpack(format, buf) + return _MakeResult( + "UnpackLVNOTIFY hwndFrom id code item subitem " + "newstate oldstate changed pt lparam", + ( + hwndFrom, + id, + code, + item, + subitem, + newstate, + oldstate, + changed, + (pt_x, pt_y), + lparam, + ), + ) + + +# Make a new buffer suitable for querying an items attributes. +def EmptyLVITEM(item, subitem, mask=None, text_buf_size=512): + extra = [] # objects we must keep references to + if mask is None: + mask = ( + commctrl.LVIF_IMAGE + | commctrl.LVIF_INDENT + | commctrl.LVIF_TEXT + | commctrl.LVIF_PARAM + | commctrl.LVIF_STATE + ) + if mask & commctrl.LVIF_TEXT: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + buf = struct.pack( + _lvitem_fmt, + mask, + item, + subitem, + 0, + 0, + text_addr, + text_buf_size, # text + 0, + 0, + 0, + ) + return array.array("b", buf), extra + + +# List view column structure +_lvcolumn_fmt = "iiiPiiii" + + +def PackLVCOLUMN(fmt=None, cx=None, text=None, subItem=None, image=None, order=None): + extra = [] # objects we must keep references to + mask = 0 + mask, fmt = _GetMaskAndVal(fmt, 0, mask, commctrl.LVCF_FMT) + mask, cx = _GetMaskAndVal(cx, 0, mask, commctrl.LVCF_WIDTH) + mask, text = _GetMaskAndVal(text, None, mask, commctrl.LVCF_TEXT) + mask, subItem = _GetMaskAndVal(subItem, 0, mask, commctrl.LVCF_SUBITEM) + mask, image = _GetMaskAndVal(image, 0, mask, commctrl.LVCF_IMAGE) + mask, order = _GetMaskAndVal(order, 0, mask, commctrl.LVCF_ORDER) + if text is None: + text_addr = text_len = 0 + else: + text_buffer = _make_text_buffer(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + text_len = len(text) + buf = struct.pack( + _lvcolumn_fmt, mask, fmt, cx, text_addr, text_len, subItem, image, order # text + ) + return array.array("b", buf), extra + + +def UnpackLVCOLUMN(lparam): + mask, fmt, cx, text_addr, text_size, subItem, image, order = struct.unpack( + _lvcolumn_fmt, lparam + ) + # ensure only items listed by the mask are valid + if not (mask & commctrl.LVCF_FMT): + fmt = None + if not (mask & commctrl.LVCF_WIDTH): + cx = None + if not (mask & commctrl.LVCF_TEXT): + text_addr = text_size = None + if not (mask & commctrl.LVCF_SUBITEM): + subItem = None + if not (mask & commctrl.LVCF_IMAGE): + image = None + if not (mask & commctrl.LVCF_ORDER): + order = None + if text_addr: + text = win32gui.PyGetString(text_addr) + else: + text = None + return _MakeResult( + "LVCOLUMN fmt cx text subItem image order", + (fmt, cx, text, subItem, image, order), + ) + + +# Make a new buffer suitable for querying an items attributes. +def EmptyLVCOLUMN(mask=None, text_buf_size=512): + extra = [] # objects we must keep references to + if mask is None: + mask = ( + commctrl.LVCF_FMT + | commctrl.LVCF_WIDTH + | commctrl.LVCF_TEXT + | commctrl.LVCF_SUBITEM + | commctrl.LVCF_IMAGE + | commctrl.LVCF_ORDER + ) + if mask & commctrl.LVCF_TEXT: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + buf = struct.pack( + _lvcolumn_fmt, mask, 0, 0, text_addr, text_buf_size, 0, 0, 0 # text + ) + return array.array("b", buf), extra + + +# List view hit-test. +def PackLVHITTEST(pt): + format = "iiiii" + buf = struct.pack(format, pt[0], pt[1], 0, 0, 0) + return array.array("b", buf), None + + +def UnpackLVHITTEST(buf): + format = "iiiii" + x, y, flags, item, subitem = struct.unpack(format, buf) + return _MakeResult( + "LVHITTEST pt flags item subitem", ((x, y), flags, item, subitem) + ) + + +def PackHDITEM( + cxy=None, text=None, hbm=None, fmt=None, param=None, image=None, order=None +): + extra = [] # objects we must keep references to + mask = 0 + mask, cxy = _GetMaskAndVal(cxy, 0, mask, commctrl.HDI_HEIGHT) + mask, text = _GetMaskAndVal(text, None, mask, commctrl.LVCF_TEXT) + mask, hbm = _GetMaskAndVal(hbm, 0, mask, commctrl.HDI_BITMAP) + mask, fmt = _GetMaskAndVal(fmt, 0, mask, commctrl.HDI_FORMAT) + mask, param = _GetMaskAndVal(param, 0, mask, commctrl.HDI_LPARAM) + mask, image = _GetMaskAndVal(image, 0, mask, commctrl.HDI_IMAGE) + mask, order = _GetMaskAndVal(order, 0, mask, commctrl.HDI_ORDER) + + if text is None: + text_addr = text_len = 0 + else: + text_buffer = _make_text_buffer(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + text_len = len(text) + + format = "iiPPiiPiiii" + buf = struct.pack( + format, mask, cxy, text_addr, hbm, text_len, fmt, param, image, order, 0, 0 + ) + return array.array("b", buf), extra + + +# Device notification stuff + + +# Generic function for packing a DEV_BROADCAST_* structure - generally used +# by the other PackDEV_BROADCAST_* functions in this module. +def PackDEV_BROADCAST(devicetype, rest_fmt, rest_data, extra_data=_make_bytes("")): + # It seems a requirement is 4 byte alignment, even for the 'BYTE data[1]' + # field (eg, that would make DEV_BROADCAST_HANDLE 41 bytes, but we must + # be 44. + extra_data += _make_bytes("\0" * (4 - len(extra_data) % 4)) + format = "iii" + rest_fmt + full_size = struct.calcsize(format) + len(extra_data) + data = (full_size, devicetype, 0) + rest_data + return struct.pack(format, *data) + extra_data + + +def PackDEV_BROADCAST_HANDLE( + handle, + hdevnotify=0, + guid=_make_bytes("\0" * 16), + name_offset=0, + data=_make_bytes("\0"), +): + return PackDEV_BROADCAST( + win32con.DBT_DEVTYP_HANDLE, + "PP16sl", + (int(handle), int(hdevnotify), _make_memory(guid), name_offset), + data, + ) + + +def PackDEV_BROADCAST_VOLUME(unitmask, flags): + return PackDEV_BROADCAST(win32con.DBT_DEVTYP_VOLUME, "II", (unitmask, flags)) + + +def PackDEV_BROADCAST_DEVICEINTERFACE(classguid, name=""): + if win32gui.UNICODE: + # This really means "is py3k?" - so not accepting bytes is OK + if not isinstance(name, str): + raise TypeError("Must provide unicode for the name") + name = name.encode("utf-16le") + else: + # py2k was passed a unicode object - encode as mbcs. + if isinstance(name, str): + name = name.encode("mbcs") + + # 16 bytes for the IID followed by \0 term'd string. + rest_fmt = "16s%ds" % len(name) + # _make_memory(iid) hoops necessary to get the raw IID bytes. + rest_data = (_make_memory(pywintypes.IID(classguid)), name) + return PackDEV_BROADCAST(win32con.DBT_DEVTYP_DEVICEINTERFACE, rest_fmt, rest_data) + + +# An object returned by UnpackDEV_BROADCAST. +class DEV_BROADCAST_INFO: + def __init__(self, devicetype, **kw): + self.devicetype = devicetype + self.__dict__.update(kw) + + def __str__(self): + return "DEV_BROADCAST_INFO:" + str(self.__dict__) + + +# Support for unpacking the 'lparam' +def UnpackDEV_BROADCAST(lparam): + if lparam == 0: + return None + hdr_format = "iii" + hdr_size = struct.calcsize(hdr_format) + hdr_buf = win32gui.PyGetMemory(lparam, hdr_size) + size, devtype, reserved = struct.unpack("iii", hdr_buf) + # Due to x64 alignment issues, we need to use the full format string over + # the entire buffer. ie, on x64: + # calcsize('iiiP') != calcsize('iii')+calcsize('P') + buf = win32gui.PyGetMemory(lparam, size) + + extra = x = {} + if devtype == win32con.DBT_DEVTYP_HANDLE: + # 2 handles, a GUID, a LONG and possibly an array following... + fmt = hdr_format + "PP16sl" + ( + _, + _, + _, + x["handle"], + x["hdevnotify"], + guid_bytes, + x["nameoffset"], + ) = struct.unpack(fmt, buf[: struct.calcsize(fmt)]) + x["eventguid"] = pywintypes.IID(guid_bytes, True) + elif devtype == win32con.DBT_DEVTYP_DEVICEINTERFACE: + fmt = hdr_format + "16s" + _, _, _, guid_bytes = struct.unpack(fmt, buf[: struct.calcsize(fmt)]) + x["classguid"] = pywintypes.IID(guid_bytes, True) + x["name"] = win32gui.PyGetString(lparam + struct.calcsize(fmt)) + elif devtype == win32con.DBT_DEVTYP_VOLUME: + # int mask and flags + fmt = hdr_format + "II" + _, _, _, x["unitmask"], x["flags"] = struct.unpack( + fmt, buf[: struct.calcsize(fmt)] + ) + else: + raise NotImplementedError("unknown device type %d" % (devtype,)) + return DEV_BROADCAST_INFO(devtype, **extra) diff --git a/MLPY/Lib/site-packages/win32/lib/win32inetcon.py b/MLPY/Lib/site-packages/win32/lib/win32inetcon.py new file mode 100644 index 0000000000000000000000000000000000000000..b6e8e6722cb1429c03c39a3e95d4f1e1ee67cfd5 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32inetcon.py @@ -0,0 +1,1086 @@ +# Generated by h2py from \mssdk\include\WinInet.h + +INTERNET_INVALID_PORT_NUMBER = 0 +INTERNET_DEFAULT_PORT = 0 +INTERNET_DEFAULT_FTP_PORT = 21 +INTERNET_DEFAULT_GOPHER_PORT = 70 +INTERNET_DEFAULT_HTTP_PORT = 80 +INTERNET_DEFAULT_HTTPS_PORT = 443 +INTERNET_DEFAULT_SOCKS_PORT = 1080 +INTERNET_MAX_HOST_NAME_LENGTH = 256 +INTERNET_MAX_USER_NAME_LENGTH = 128 +INTERNET_MAX_PASSWORD_LENGTH = 128 +INTERNET_MAX_PORT_NUMBER_LENGTH = 5 +INTERNET_MAX_PORT_NUMBER_VALUE = 65535 +INTERNET_MAX_PATH_LENGTH = 2048 +INTERNET_MAX_SCHEME_LENGTH = 32 +INTERNET_KEEP_ALIVE_ENABLED = 1 +INTERNET_KEEP_ALIVE_DISABLED = 0 +INTERNET_REQFLAG_FROM_CACHE = 0x00000001 +INTERNET_REQFLAG_ASYNC = 0x00000002 +INTERNET_REQFLAG_VIA_PROXY = 0x00000004 +INTERNET_REQFLAG_NO_HEADERS = 0x00000008 +INTERNET_REQFLAG_PASSIVE = 0x00000010 +INTERNET_REQFLAG_CACHE_WRITE_DISABLED = 0x00000040 +INTERNET_REQFLAG_NET_TIMEOUT = 0x00000080 +INTERNET_FLAG_RELOAD = -2147483648 +INTERNET_FLAG_RAW_DATA = 0x40000000 +INTERNET_FLAG_EXISTING_CONNECT = 0x20000000 +INTERNET_FLAG_ASYNC = 0x10000000 +INTERNET_FLAG_PASSIVE = 0x08000000 +INTERNET_FLAG_NO_CACHE_WRITE = 0x04000000 +INTERNET_FLAG_DONT_CACHE = INTERNET_FLAG_NO_CACHE_WRITE +INTERNET_FLAG_MAKE_PERSISTENT = 0x02000000 +INTERNET_FLAG_FROM_CACHE = 0x01000000 +INTERNET_FLAG_OFFLINE = INTERNET_FLAG_FROM_CACHE +INTERNET_FLAG_SECURE = 0x00800000 +INTERNET_FLAG_KEEP_CONNECTION = 0x00400000 +INTERNET_FLAG_NO_AUTO_REDIRECT = 0x00200000 +INTERNET_FLAG_READ_PREFETCH = 0x00100000 +INTERNET_FLAG_NO_COOKIES = 0x00080000 +INTERNET_FLAG_NO_AUTH = 0x00040000 +INTERNET_FLAG_RESTRICTED_ZONE = 0x00020000 +INTERNET_FLAG_CACHE_IF_NET_FAIL = 0x00010000 +INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP = 0x00008000 +INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS = 0x00004000 +INTERNET_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000 +INTERNET_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000 +INTERNET_FLAG_RESYNCHRONIZE = 0x00000800 +INTERNET_FLAG_HYPERLINK = 0x00000400 +INTERNET_FLAG_NO_UI = 0x00000200 +INTERNET_FLAG_PRAGMA_NOCACHE = 0x00000100 +INTERNET_FLAG_CACHE_ASYNC = 0x00000080 +INTERNET_FLAG_FORMS_SUBMIT = 0x00000040 +INTERNET_FLAG_FWD_BACK = 0x00000020 +INTERNET_FLAG_NEED_FILE = 0x00000010 +INTERNET_FLAG_MUST_CACHE_REQUEST = INTERNET_FLAG_NEED_FILE +SECURITY_INTERNET_MASK = ( + INTERNET_FLAG_IGNORE_CERT_CN_INVALID + | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID + | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS + | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP +) +INTERNET_ERROR_MASK_INSERT_CDROM = 0x1 +INTERNET_ERROR_MASK_COMBINED_SEC_CERT = 0x2 +INTERNET_ERROR_MASK_NEED_MSN_SSPI_PKG = 0x4 +INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY = 0x8 +WININET_API_FLAG_ASYNC = 0x00000001 +WININET_API_FLAG_SYNC = 0x00000004 +WININET_API_FLAG_USE_CONTEXT = 0x00000008 +INTERNET_NO_CALLBACK = 0 +IDSI_FLAG_KEEP_ALIVE = 0x00000001 +IDSI_FLAG_SECURE = 0x00000002 +IDSI_FLAG_PROXY = 0x00000004 +IDSI_FLAG_TUNNEL = 0x00000008 +INTERNET_PER_CONN_FLAGS = 1 +INTERNET_PER_CONN_PROXY_SERVER = 2 +INTERNET_PER_CONN_PROXY_BYPASS = 3 +INTERNET_PER_CONN_AUTOCONFIG_URL = 4 +INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5 +INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6 +INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7 +INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8 +INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9 +PROXY_TYPE_DIRECT = 0x00000001 +PROXY_TYPE_PROXY = 0x00000002 +PROXY_TYPE_AUTO_PROXY_URL = 0x00000004 +PROXY_TYPE_AUTO_DETECT = 0x00000008 +AUTO_PROXY_FLAG_USER_SET = 0x00000001 +AUTO_PROXY_FLAG_ALWAYS_DETECT = 0x00000002 +AUTO_PROXY_FLAG_DETECTION_RUN = 0x00000004 +AUTO_PROXY_FLAG_MIGRATED = 0x00000008 +AUTO_PROXY_FLAG_DONT_CACHE_PROXY_RESULT = 0x00000010 +AUTO_PROXY_FLAG_CACHE_INIT_RUN = 0x00000020 +AUTO_PROXY_FLAG_DETECTION_SUSPECT = 0x00000040 +ISO_FORCE_DISCONNECTED = 0x00000001 +INTERNET_RFC1123_FORMAT = 0 +INTERNET_RFC1123_BUFSIZE = 30 +ICU_ESCAPE = -2147483648 +ICU_ESCAPE_AUTHORITY = 0x00002000 +ICU_REJECT_USERPWD = 0x00004000 +ICU_USERNAME = 0x40000000 +ICU_NO_ENCODE = 0x20000000 +ICU_DECODE = 0x10000000 +ICU_NO_META = 0x08000000 +ICU_ENCODE_SPACES_ONLY = 0x04000000 +ICU_BROWSER_MODE = 0x02000000 +ICU_ENCODE_PERCENT = 0x00001000 +INTERNET_OPEN_TYPE_PRECONFIG = 0 +INTERNET_OPEN_TYPE_DIRECT = 1 +INTERNET_OPEN_TYPE_PROXY = 3 +INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 4 +PRE_CONFIG_INTERNET_ACCESS = INTERNET_OPEN_TYPE_PRECONFIG +LOCAL_INTERNET_ACCESS = INTERNET_OPEN_TYPE_DIRECT +CERN_PROXY_INTERNET_ACCESS = INTERNET_OPEN_TYPE_PROXY +INTERNET_SERVICE_FTP = 1 +INTERNET_SERVICE_GOPHER = 2 +INTERNET_SERVICE_HTTP = 3 +IRF_ASYNC = WININET_API_FLAG_ASYNC +IRF_SYNC = WININET_API_FLAG_SYNC +IRF_USE_CONTEXT = WININET_API_FLAG_USE_CONTEXT +IRF_NO_WAIT = 0x00000008 +ISO_GLOBAL = 0x00000001 +ISO_REGISTRY = 0x00000002 +ISO_VALID_FLAGS = ISO_GLOBAL | ISO_REGISTRY +INTERNET_OPTION_CALLBACK = 1 +INTERNET_OPTION_CONNECT_TIMEOUT = 2 +INTERNET_OPTION_CONNECT_RETRIES = 3 +INTERNET_OPTION_CONNECT_BACKOFF = 4 +INTERNET_OPTION_SEND_TIMEOUT = 5 +INTERNET_OPTION_CONTROL_SEND_TIMEOUT = INTERNET_OPTION_SEND_TIMEOUT +INTERNET_OPTION_RECEIVE_TIMEOUT = 6 +INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT = INTERNET_OPTION_RECEIVE_TIMEOUT +INTERNET_OPTION_DATA_SEND_TIMEOUT = 7 +INTERNET_OPTION_DATA_RECEIVE_TIMEOUT = 8 +INTERNET_OPTION_HANDLE_TYPE = 9 +INTERNET_OPTION_LISTEN_TIMEOUT = 11 +INTERNET_OPTION_READ_BUFFER_SIZE = 12 +INTERNET_OPTION_WRITE_BUFFER_SIZE = 13 +INTERNET_OPTION_ASYNC_ID = 15 +INTERNET_OPTION_ASYNC_PRIORITY = 16 +INTERNET_OPTION_PARENT_HANDLE = 21 +INTERNET_OPTION_KEEP_CONNECTION = 22 +INTERNET_OPTION_REQUEST_FLAGS = 23 +INTERNET_OPTION_EXTENDED_ERROR = 24 +INTERNET_OPTION_OFFLINE_MODE = 26 +INTERNET_OPTION_CACHE_STREAM_HANDLE = 27 +INTERNET_OPTION_USERNAME = 28 +INTERNET_OPTION_PASSWORD = 29 +INTERNET_OPTION_ASYNC = 30 +INTERNET_OPTION_SECURITY_FLAGS = 31 +INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT = 32 +INTERNET_OPTION_DATAFILE_NAME = 33 +INTERNET_OPTION_URL = 34 +INTERNET_OPTION_SECURITY_CERTIFICATE = 35 +INTERNET_OPTION_SECURITY_KEY_BITNESS = 36 +INTERNET_OPTION_REFRESH = 37 +INTERNET_OPTION_PROXY = 38 +INTERNET_OPTION_SETTINGS_CHANGED = 39 +INTERNET_OPTION_VERSION = 40 +INTERNET_OPTION_USER_AGENT = 41 +INTERNET_OPTION_END_BROWSER_SESSION = 42 +INTERNET_OPTION_PROXY_USERNAME = 43 +INTERNET_OPTION_PROXY_PASSWORD = 44 +INTERNET_OPTION_CONTEXT_VALUE = 45 +INTERNET_OPTION_CONNECT_LIMIT = 46 +INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT = 47 +INTERNET_OPTION_POLICY = 48 +INTERNET_OPTION_DISCONNECTED_TIMEOUT = 49 +INTERNET_OPTION_CONNECTED_STATE = 50 +INTERNET_OPTION_IDLE_STATE = 51 +INTERNET_OPTION_OFFLINE_SEMANTICS = 52 +INTERNET_OPTION_SECONDARY_CACHE_KEY = 53 +INTERNET_OPTION_CALLBACK_FILTER = 54 +INTERNET_OPTION_CONNECT_TIME = 55 +INTERNET_OPTION_SEND_THROUGHPUT = 56 +INTERNET_OPTION_RECEIVE_THROUGHPUT = 57 +INTERNET_OPTION_REQUEST_PRIORITY = 58 +INTERNET_OPTION_HTTP_VERSION = 59 +INTERNET_OPTION_RESET_URLCACHE_SESSION = 60 +INTERNET_OPTION_ERROR_MASK = 62 +INTERNET_OPTION_FROM_CACHE_TIMEOUT = 63 +INTERNET_OPTION_BYPASS_EDITED_ENTRY = 64 +INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO = 67 +INTERNET_OPTION_CODEPAGE = 68 +INTERNET_OPTION_CACHE_TIMESTAMPS = 69 +INTERNET_OPTION_DISABLE_AUTODIAL = 70 +INTERNET_OPTION_MAX_CONNS_PER_SERVER = 73 +INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER = 74 +INTERNET_OPTION_PER_CONNECTION_OPTION = 75 +INTERNET_OPTION_DIGEST_AUTH_UNLOAD = 76 +INTERNET_OPTION_IGNORE_OFFLINE = 77 +INTERNET_OPTION_IDENTITY = 78 +INTERNET_OPTION_REMOVE_IDENTITY = 79 +INTERNET_OPTION_ALTER_IDENTITY = 80 +INTERNET_OPTION_SUPPRESS_BEHAVIOR = 81 +INTERNET_OPTION_AUTODIAL_MODE = 82 +INTERNET_OPTION_AUTODIAL_CONNECTION = 83 +INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84 +INTERNET_OPTION_AUTH_FLAGS = 85 +INTERNET_OPTION_COOKIES_3RD_PARTY = 86 +INTERNET_OPTION_DISABLE_PASSPORT_AUTH = 87 +INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY = 88 +INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT = 89 +INTERNET_OPTION_ENABLE_PASSPORT_AUTH = 90 +INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS = 91 +INTERNET_OPTION_ACTIVATE_WORKER_THREADS = 92 +INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS = 93 +INTERNET_OPTION_SOCKET_SEND_BUFFER_LENGTH = 94 +INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95 +INTERNET_FIRST_OPTION = INTERNET_OPTION_CALLBACK +INTERNET_LAST_OPTION = INTERNET_OPTION_PROXY_SETTINGS_CHANGED +INTERNET_PRIORITY_FOREGROUND = 1000 +INTERNET_HANDLE_TYPE_INTERNET = 1 +INTERNET_HANDLE_TYPE_CONNECT_FTP = 2 +INTERNET_HANDLE_TYPE_CONNECT_GOPHER = 3 +INTERNET_HANDLE_TYPE_CONNECT_HTTP = 4 +INTERNET_HANDLE_TYPE_FTP_FIND = 5 +INTERNET_HANDLE_TYPE_FTP_FIND_HTML = 6 +INTERNET_HANDLE_TYPE_FTP_FILE = 7 +INTERNET_HANDLE_TYPE_FTP_FILE_HTML = 8 +INTERNET_HANDLE_TYPE_GOPHER_FIND = 9 +INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML = 10 +INTERNET_HANDLE_TYPE_GOPHER_FILE = 11 +INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML = 12 +INTERNET_HANDLE_TYPE_HTTP_REQUEST = 13 +INTERNET_HANDLE_TYPE_FILE_REQUEST = 14 +AUTH_FLAG_DISABLE_NEGOTIATE = 0x00000001 +AUTH_FLAG_ENABLE_NEGOTIATE = 0x00000002 +SECURITY_FLAG_SECURE = 0x00000001 +SECURITY_FLAG_STRENGTH_WEAK = 0x10000000 +SECURITY_FLAG_STRENGTH_MEDIUM = 0x40000000 +SECURITY_FLAG_STRENGTH_STRONG = 0x20000000 +SECURITY_FLAG_UNKNOWNBIT = -2147483648 +SECURITY_FLAG_FORTEZZA = 0x08000000 +SECURITY_FLAG_NORMALBITNESS = SECURITY_FLAG_STRENGTH_WEAK +SECURITY_FLAG_SSL = 0x00000002 +SECURITY_FLAG_SSL3 = 0x00000004 +SECURITY_FLAG_PCT = 0x00000008 +SECURITY_FLAG_PCT4 = 0x00000010 +SECURITY_FLAG_IETFSSL4 = 0x00000020 +SECURITY_FLAG_40BIT = SECURITY_FLAG_STRENGTH_WEAK +SECURITY_FLAG_128BIT = SECURITY_FLAG_STRENGTH_STRONG +SECURITY_FLAG_56BIT = SECURITY_FLAG_STRENGTH_MEDIUM +SECURITY_FLAG_IGNORE_REVOCATION = 0x00000080 +SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100 +SECURITY_FLAG_IGNORE_WRONG_USAGE = 0x00000200 +SECURITY_FLAG_IGNORE_CERT_CN_INVALID = INTERNET_FLAG_IGNORE_CERT_CN_INVALID +SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = INTERNET_FLAG_IGNORE_CERT_DATE_INVALID +SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE = 0x00000200 +SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS +SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP +SECURITY_SET_MASK = ( + SECURITY_FLAG_IGNORE_REVOCATION + | SECURITY_FLAG_IGNORE_UNKNOWN_CA + | SECURITY_FLAG_IGNORE_CERT_CN_INVALID + | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID + | SECURITY_FLAG_IGNORE_WRONG_USAGE +) +AUTODIAL_MODE_NEVER = 1 +AUTODIAL_MODE_ALWAYS = 2 +AUTODIAL_MODE_NO_NETWORK_PRESENT = 4 +INTERNET_STATUS_RESOLVING_NAME = 10 +INTERNET_STATUS_NAME_RESOLVED = 11 +INTERNET_STATUS_CONNECTING_TO_SERVER = 20 +INTERNET_STATUS_CONNECTED_TO_SERVER = 21 +INTERNET_STATUS_SENDING_REQUEST = 30 +INTERNET_STATUS_REQUEST_SENT = 31 +INTERNET_STATUS_RECEIVING_RESPONSE = 40 +INTERNET_STATUS_RESPONSE_RECEIVED = 41 +INTERNET_STATUS_CTL_RESPONSE_RECEIVED = 42 +INTERNET_STATUS_PREFETCH = 43 +INTERNET_STATUS_CLOSING_CONNECTION = 50 +INTERNET_STATUS_CONNECTION_CLOSED = 51 +INTERNET_STATUS_HANDLE_CREATED = 60 +INTERNET_STATUS_HANDLE_CLOSING = 70 +INTERNET_STATUS_DETECTING_PROXY = 80 +INTERNET_STATUS_REQUEST_COMPLETE = 100 +INTERNET_STATUS_REDIRECT = 110 +INTERNET_STATUS_INTERMEDIATE_RESPONSE = 120 +INTERNET_STATUS_USER_INPUT_REQUIRED = 140 +INTERNET_STATUS_STATE_CHANGE = 200 +INTERNET_STATUS_COOKIE_SENT = 320 +INTERNET_STATUS_COOKIE_RECEIVED = 321 +INTERNET_STATUS_PRIVACY_IMPACTED = 324 +INTERNET_STATUS_P3P_HEADER = 325 +INTERNET_STATUS_P3P_POLICYREF = 326 +INTERNET_STATUS_COOKIE_HISTORY = 327 +INTERNET_STATE_CONNECTED = 0x00000001 +INTERNET_STATE_DISCONNECTED = 0x00000002 +INTERNET_STATE_DISCONNECTED_BY_USER = 0x00000010 +INTERNET_STATE_IDLE = 0x00000100 +INTERNET_STATE_BUSY = 0x00000200 +FTP_TRANSFER_TYPE_UNKNOWN = 0x00000000 +FTP_TRANSFER_TYPE_ASCII = 0x00000001 +FTP_TRANSFER_TYPE_BINARY = 0x00000002 +FTP_TRANSFER_TYPE_MASK = FTP_TRANSFER_TYPE_ASCII | FTP_TRANSFER_TYPE_BINARY +MAX_GOPHER_DISPLAY_TEXT = 128 +MAX_GOPHER_SELECTOR_TEXT = 256 +MAX_GOPHER_HOST_NAME = INTERNET_MAX_HOST_NAME_LENGTH +MAX_GOPHER_LOCATOR_LENGTH = ( + 1 + + MAX_GOPHER_DISPLAY_TEXT + + 1 + + MAX_GOPHER_SELECTOR_TEXT + + 1 + + MAX_GOPHER_HOST_NAME + + 1 + + INTERNET_MAX_PORT_NUMBER_LENGTH + + 1 + + 1 + + 2 +) +GOPHER_TYPE_TEXT_FILE = 0x00000001 +GOPHER_TYPE_DIRECTORY = 0x00000002 +GOPHER_TYPE_CSO = 0x00000004 +GOPHER_TYPE_ERROR = 0x00000008 +GOPHER_TYPE_MAC_BINHEX = 0x00000010 +GOPHER_TYPE_DOS_ARCHIVE = 0x00000020 +GOPHER_TYPE_UNIX_UUENCODED = 0x00000040 +GOPHER_TYPE_INDEX_SERVER = 0x00000080 +GOPHER_TYPE_TELNET = 0x00000100 +GOPHER_TYPE_BINARY = 0x00000200 +GOPHER_TYPE_REDUNDANT = 0x00000400 +GOPHER_TYPE_TN3270 = 0x00000800 +GOPHER_TYPE_GIF = 0x00001000 +GOPHER_TYPE_IMAGE = 0x00002000 +GOPHER_TYPE_BITMAP = 0x00004000 +GOPHER_TYPE_MOVIE = 0x00008000 +GOPHER_TYPE_SOUND = 0x00010000 +GOPHER_TYPE_HTML = 0x00020000 +GOPHER_TYPE_PDF = 0x00040000 +GOPHER_TYPE_CALENDAR = 0x00080000 +GOPHER_TYPE_INLINE = 0x00100000 +GOPHER_TYPE_UNKNOWN = 0x20000000 +GOPHER_TYPE_ASK = 0x40000000 +GOPHER_TYPE_GOPHER_PLUS = -2147483648 +GOPHER_TYPE_FILE_MASK = ( + GOPHER_TYPE_TEXT_FILE + | GOPHER_TYPE_MAC_BINHEX + | GOPHER_TYPE_DOS_ARCHIVE + | GOPHER_TYPE_UNIX_UUENCODED + | GOPHER_TYPE_BINARY + | GOPHER_TYPE_GIF + | GOPHER_TYPE_IMAGE + | GOPHER_TYPE_BITMAP + | GOPHER_TYPE_MOVIE + | GOPHER_TYPE_SOUND + | GOPHER_TYPE_HTML + | GOPHER_TYPE_PDF + | GOPHER_TYPE_CALENDAR + | GOPHER_TYPE_INLINE +) +MAX_GOPHER_CATEGORY_NAME = 128 +MAX_GOPHER_ATTRIBUTE_NAME = 128 +MIN_GOPHER_ATTRIBUTE_LENGTH = 256 +GOPHER_ATTRIBUTE_ID_BASE = -1412641792 +GOPHER_CATEGORY_ID_ALL = GOPHER_ATTRIBUTE_ID_BASE + 1 +GOPHER_CATEGORY_ID_INFO = GOPHER_ATTRIBUTE_ID_BASE + 2 +GOPHER_CATEGORY_ID_ADMIN = GOPHER_ATTRIBUTE_ID_BASE + 3 +GOPHER_CATEGORY_ID_VIEWS = GOPHER_ATTRIBUTE_ID_BASE + 4 +GOPHER_CATEGORY_ID_ABSTRACT = GOPHER_ATTRIBUTE_ID_BASE + 5 +GOPHER_CATEGORY_ID_VERONICA = GOPHER_ATTRIBUTE_ID_BASE + 6 +GOPHER_CATEGORY_ID_ASK = GOPHER_ATTRIBUTE_ID_BASE + 7 +GOPHER_CATEGORY_ID_UNKNOWN = GOPHER_ATTRIBUTE_ID_BASE + 8 +GOPHER_ATTRIBUTE_ID_ALL = GOPHER_ATTRIBUTE_ID_BASE + 9 +GOPHER_ATTRIBUTE_ID_ADMIN = GOPHER_ATTRIBUTE_ID_BASE + 10 +GOPHER_ATTRIBUTE_ID_MOD_DATE = GOPHER_ATTRIBUTE_ID_BASE + 11 +GOPHER_ATTRIBUTE_ID_TTL = GOPHER_ATTRIBUTE_ID_BASE + 12 +GOPHER_ATTRIBUTE_ID_SCORE = GOPHER_ATTRIBUTE_ID_BASE + 13 +GOPHER_ATTRIBUTE_ID_RANGE = GOPHER_ATTRIBUTE_ID_BASE + 14 +GOPHER_ATTRIBUTE_ID_SITE = GOPHER_ATTRIBUTE_ID_BASE + 15 +GOPHER_ATTRIBUTE_ID_ORG = GOPHER_ATTRIBUTE_ID_BASE + 16 +GOPHER_ATTRIBUTE_ID_LOCATION = GOPHER_ATTRIBUTE_ID_BASE + 17 +GOPHER_ATTRIBUTE_ID_GEOG = GOPHER_ATTRIBUTE_ID_BASE + 18 +GOPHER_ATTRIBUTE_ID_TIMEZONE = GOPHER_ATTRIBUTE_ID_BASE + 19 +GOPHER_ATTRIBUTE_ID_PROVIDER = GOPHER_ATTRIBUTE_ID_BASE + 20 +GOPHER_ATTRIBUTE_ID_VERSION = GOPHER_ATTRIBUTE_ID_BASE + 21 +GOPHER_ATTRIBUTE_ID_ABSTRACT = GOPHER_ATTRIBUTE_ID_BASE + 22 +GOPHER_ATTRIBUTE_ID_VIEW = GOPHER_ATTRIBUTE_ID_BASE + 23 +GOPHER_ATTRIBUTE_ID_TREEWALK = GOPHER_ATTRIBUTE_ID_BASE + 24 +GOPHER_ATTRIBUTE_ID_UNKNOWN = GOPHER_ATTRIBUTE_ID_BASE + 25 +HTTP_MAJOR_VERSION = 1 +HTTP_MINOR_VERSION = 0 +HTTP_VERSIONA = "HTTP/1.0" +HTTP_VERSION = HTTP_VERSIONA +HTTP_QUERY_MIME_VERSION = 0 +HTTP_QUERY_CONTENT_TYPE = 1 +HTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2 +HTTP_QUERY_CONTENT_ID = 3 +HTTP_QUERY_CONTENT_DESCRIPTION = 4 +HTTP_QUERY_CONTENT_LENGTH = 5 +HTTP_QUERY_CONTENT_LANGUAGE = 6 +HTTP_QUERY_ALLOW = 7 +HTTP_QUERY_PUBLIC = 8 +HTTP_QUERY_DATE = 9 +HTTP_QUERY_EXPIRES = 10 +HTTP_QUERY_LAST_MODIFIED = 11 +HTTP_QUERY_MESSAGE_ID = 12 +HTTP_QUERY_URI = 13 +HTTP_QUERY_DERIVED_FROM = 14 +HTTP_QUERY_COST = 15 +HTTP_QUERY_LINK = 16 +HTTP_QUERY_PRAGMA = 17 +HTTP_QUERY_VERSION = 18 +HTTP_QUERY_STATUS_CODE = 19 +HTTP_QUERY_STATUS_TEXT = 20 +HTTP_QUERY_RAW_HEADERS = 21 +HTTP_QUERY_RAW_HEADERS_CRLF = 22 +HTTP_QUERY_CONNECTION = 23 +HTTP_QUERY_ACCEPT = 24 +HTTP_QUERY_ACCEPT_CHARSET = 25 +HTTP_QUERY_ACCEPT_ENCODING = 26 +HTTP_QUERY_ACCEPT_LANGUAGE = 27 +HTTP_QUERY_AUTHORIZATION = 28 +HTTP_QUERY_CONTENT_ENCODING = 29 +HTTP_QUERY_FORWARDED = 30 +HTTP_QUERY_FROM = 31 +HTTP_QUERY_IF_MODIFIED_SINCE = 32 +HTTP_QUERY_LOCATION = 33 +HTTP_QUERY_ORIG_URI = 34 +HTTP_QUERY_REFERER = 35 +HTTP_QUERY_RETRY_AFTER = 36 +HTTP_QUERY_SERVER = 37 +HTTP_QUERY_TITLE = 38 +HTTP_QUERY_USER_AGENT = 39 +HTTP_QUERY_WWW_AUTHENTICATE = 40 +HTTP_QUERY_PROXY_AUTHENTICATE = 41 +HTTP_QUERY_ACCEPT_RANGES = 42 +HTTP_QUERY_SET_COOKIE = 43 +HTTP_QUERY_COOKIE = 44 +HTTP_QUERY_REQUEST_METHOD = 45 +HTTP_QUERY_REFRESH = 46 +HTTP_QUERY_CONTENT_DISPOSITION = 47 +HTTP_QUERY_AGE = 48 +HTTP_QUERY_CACHE_CONTROL = 49 +HTTP_QUERY_CONTENT_BASE = 50 +HTTP_QUERY_CONTENT_LOCATION = 51 +HTTP_QUERY_CONTENT_MD5 = 52 +HTTP_QUERY_CONTENT_RANGE = 53 +HTTP_QUERY_ETAG = 54 +HTTP_QUERY_HOST = 55 +HTTP_QUERY_IF_MATCH = 56 +HTTP_QUERY_IF_NONE_MATCH = 57 +HTTP_QUERY_IF_RANGE = 58 +HTTP_QUERY_IF_UNMODIFIED_SINCE = 59 +HTTP_QUERY_MAX_FORWARDS = 60 +HTTP_QUERY_PROXY_AUTHORIZATION = 61 +HTTP_QUERY_RANGE = 62 +HTTP_QUERY_TRANSFER_ENCODING = 63 +HTTP_QUERY_UPGRADE = 64 +HTTP_QUERY_VARY = 65 +HTTP_QUERY_VIA = 66 +HTTP_QUERY_WARNING = 67 +HTTP_QUERY_EXPECT = 68 +HTTP_QUERY_PROXY_CONNECTION = 69 +HTTP_QUERY_UNLESS_MODIFIED_SINCE = 70 +HTTP_QUERY_ECHO_REQUEST = 71 +HTTP_QUERY_ECHO_REPLY = 72 +HTTP_QUERY_ECHO_HEADERS = 73 +HTTP_QUERY_ECHO_HEADERS_CRLF = 74 +HTTP_QUERY_PROXY_SUPPORT = 75 +HTTP_QUERY_AUTHENTICATION_INFO = 76 +HTTP_QUERY_PASSPORT_URLS = 77 +HTTP_QUERY_PASSPORT_CONFIG = 78 +HTTP_QUERY_MAX = 78 +HTTP_QUERY_CUSTOM = 65535 +HTTP_QUERY_FLAG_REQUEST_HEADERS = -2147483648 +HTTP_QUERY_FLAG_SYSTEMTIME = 0x40000000 +HTTP_QUERY_FLAG_NUMBER = 0x20000000 +HTTP_QUERY_FLAG_COALESCE = 0x10000000 +HTTP_QUERY_MODIFIER_FLAGS_MASK = ( + HTTP_QUERY_FLAG_REQUEST_HEADERS + | HTTP_QUERY_FLAG_SYSTEMTIME + | HTTP_QUERY_FLAG_NUMBER + | HTTP_QUERY_FLAG_COALESCE +) +HTTP_QUERY_HEADER_MASK = ~HTTP_QUERY_MODIFIER_FLAGS_MASK +HTTP_STATUS_CONTINUE = 100 +HTTP_STATUS_SWITCH_PROTOCOLS = 101 +HTTP_STATUS_OK = 200 +HTTP_STATUS_CREATED = 201 +HTTP_STATUS_ACCEPTED = 202 +HTTP_STATUS_PARTIAL = 203 +HTTP_STATUS_NO_CONTENT = 204 +HTTP_STATUS_RESET_CONTENT = 205 +HTTP_STATUS_PARTIAL_CONTENT = 206 +HTTP_STATUS_WEBDAV_MULTI_STATUS = 207 +HTTP_STATUS_AMBIGUOUS = 300 +HTTP_STATUS_MOVED = 301 +HTTP_STATUS_REDIRECT = 302 +HTTP_STATUS_REDIRECT_METHOD = 303 +HTTP_STATUS_NOT_MODIFIED = 304 +HTTP_STATUS_USE_PROXY = 305 +HTTP_STATUS_REDIRECT_KEEP_VERB = 307 +HTTP_STATUS_BAD_REQUEST = 400 +HTTP_STATUS_DENIED = 401 +HTTP_STATUS_PAYMENT_REQ = 402 +HTTP_STATUS_FORBIDDEN = 403 +HTTP_STATUS_NOT_FOUND = 404 +HTTP_STATUS_BAD_METHOD = 405 +HTTP_STATUS_NONE_ACCEPTABLE = 406 +HTTP_STATUS_PROXY_AUTH_REQ = 407 +HTTP_STATUS_REQUEST_TIMEOUT = 408 +HTTP_STATUS_CONFLICT = 409 +HTTP_STATUS_GONE = 410 +HTTP_STATUS_LENGTH_REQUIRED = 411 +HTTP_STATUS_PRECOND_FAILED = 412 +HTTP_STATUS_REQUEST_TOO_LARGE = 413 +HTTP_STATUS_URI_TOO_LONG = 414 +HTTP_STATUS_UNSUPPORTED_MEDIA = 415 +HTTP_STATUS_RETRY_WITH = 449 +HTTP_STATUS_SERVER_ERROR = 500 +HTTP_STATUS_NOT_SUPPORTED = 501 +HTTP_STATUS_BAD_GATEWAY = 502 +HTTP_STATUS_SERVICE_UNAVAIL = 503 +HTTP_STATUS_GATEWAY_TIMEOUT = 504 +HTTP_STATUS_VERSION_NOT_SUP = 505 +HTTP_STATUS_FIRST = HTTP_STATUS_CONTINUE +HTTP_STATUS_LAST = HTTP_STATUS_VERSION_NOT_SUP +HTTP_ADDREQ_INDEX_MASK = 0x0000FFFF +HTTP_ADDREQ_FLAGS_MASK = -65536 +HTTP_ADDREQ_FLAG_ADD_IF_NEW = 0x10000000 +HTTP_ADDREQ_FLAG_ADD = 0x20000000 +HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = 0x40000000 +HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = 0x01000000 +HTTP_ADDREQ_FLAG_COALESCE = HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA +HTTP_ADDREQ_FLAG_REPLACE = -2147483648 +HSR_ASYNC = WININET_API_FLAG_ASYNC +HSR_SYNC = WININET_API_FLAG_SYNC +HSR_USE_CONTEXT = WININET_API_FLAG_USE_CONTEXT +HSR_INITIATE = 0x00000008 +HSR_DOWNLOAD = 0x00000010 +HSR_CHUNKED = 0x00000020 +INTERNET_COOKIE_IS_SECURE = 0x01 +INTERNET_COOKIE_IS_SESSION = 0x02 +INTERNET_COOKIE_THIRD_PARTY = 0x10 +INTERNET_COOKIE_PROMPT_REQUIRED = 0x20 +INTERNET_COOKIE_EVALUATE_P3P = 0x40 +INTERNET_COOKIE_APPLY_P3P = 0x80 +INTERNET_COOKIE_P3P_ENABLED = 0x100 +INTERNET_COOKIE_IS_RESTRICTED = 0x200 +INTERNET_COOKIE_IE6 = 0x400 +INTERNET_COOKIE_IS_LEGACY = 0x800 +FLAG_ICC_FORCE_CONNECTION = 0x00000001 +FLAGS_ERROR_UI_FILTER_FOR_ERRORS = 0x01 +FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS = 0x02 +FLAGS_ERROR_UI_FLAGS_GENERATE_DATA = 0x04 +FLAGS_ERROR_UI_FLAGS_NO_UI = 0x08 +FLAGS_ERROR_UI_SERIALIZE_DIALOGS = 0x10 +INTERNET_ERROR_BASE = 12000 +ERROR_INTERNET_OUT_OF_HANDLES = INTERNET_ERROR_BASE + 1 +ERROR_INTERNET_TIMEOUT = INTERNET_ERROR_BASE + 2 +ERROR_INTERNET_EXTENDED_ERROR = INTERNET_ERROR_BASE + 3 +ERROR_INTERNET_INTERNAL_ERROR = INTERNET_ERROR_BASE + 4 +ERROR_INTERNET_INVALID_URL = INTERNET_ERROR_BASE + 5 +ERROR_INTERNET_UNRECOGNIZED_SCHEME = INTERNET_ERROR_BASE + 6 +ERROR_INTERNET_NAME_NOT_RESOLVED = INTERNET_ERROR_BASE + 7 +ERROR_INTERNET_PROTOCOL_NOT_FOUND = INTERNET_ERROR_BASE + 8 +ERROR_INTERNET_INVALID_OPTION = INTERNET_ERROR_BASE + 9 +ERROR_INTERNET_BAD_OPTION_LENGTH = INTERNET_ERROR_BASE + 10 +ERROR_INTERNET_OPTION_NOT_SETTABLE = INTERNET_ERROR_BASE + 11 +ERROR_INTERNET_SHUTDOWN = INTERNET_ERROR_BASE + 12 +ERROR_INTERNET_INCORRECT_USER_NAME = INTERNET_ERROR_BASE + 13 +ERROR_INTERNET_INCORRECT_PASSWORD = INTERNET_ERROR_BASE + 14 +ERROR_INTERNET_LOGIN_FAILURE = INTERNET_ERROR_BASE + 15 +ERROR_INTERNET_INVALID_OPERATION = INTERNET_ERROR_BASE + 16 +ERROR_INTERNET_OPERATION_CANCELLED = INTERNET_ERROR_BASE + 17 +ERROR_INTERNET_INCORRECT_HANDLE_TYPE = INTERNET_ERROR_BASE + 18 +ERROR_INTERNET_INCORRECT_HANDLE_STATE = INTERNET_ERROR_BASE + 19 +ERROR_INTERNET_NOT_PROXY_REQUEST = INTERNET_ERROR_BASE + 20 +ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND = INTERNET_ERROR_BASE + 21 +ERROR_INTERNET_BAD_REGISTRY_PARAMETER = INTERNET_ERROR_BASE + 22 +ERROR_INTERNET_NO_DIRECT_ACCESS = INTERNET_ERROR_BASE + 23 +ERROR_INTERNET_NO_CONTEXT = INTERNET_ERROR_BASE + 24 +ERROR_INTERNET_NO_CALLBACK = INTERNET_ERROR_BASE + 25 +ERROR_INTERNET_REQUEST_PENDING = INTERNET_ERROR_BASE + 26 +ERROR_INTERNET_INCORRECT_FORMAT = INTERNET_ERROR_BASE + 27 +ERROR_INTERNET_ITEM_NOT_FOUND = INTERNET_ERROR_BASE + 28 +ERROR_INTERNET_CANNOT_CONNECT = INTERNET_ERROR_BASE + 29 +ERROR_INTERNET_CONNECTION_ABORTED = INTERNET_ERROR_BASE + 30 +ERROR_INTERNET_CONNECTION_RESET = INTERNET_ERROR_BASE + 31 +ERROR_INTERNET_FORCE_RETRY = INTERNET_ERROR_BASE + 32 +ERROR_INTERNET_INVALID_PROXY_REQUEST = INTERNET_ERROR_BASE + 33 +ERROR_INTERNET_NEED_UI = INTERNET_ERROR_BASE + 34 +ERROR_INTERNET_HANDLE_EXISTS = INTERNET_ERROR_BASE + 36 +ERROR_INTERNET_SEC_CERT_DATE_INVALID = INTERNET_ERROR_BASE + 37 +ERROR_INTERNET_SEC_CERT_CN_INVALID = INTERNET_ERROR_BASE + 38 +ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR = INTERNET_ERROR_BASE + 39 +ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR = INTERNET_ERROR_BASE + 40 +ERROR_INTERNET_MIXED_SECURITY = INTERNET_ERROR_BASE + 41 +ERROR_INTERNET_CHG_POST_IS_NON_SECURE = INTERNET_ERROR_BASE + 42 +ERROR_INTERNET_POST_IS_NON_SECURE = INTERNET_ERROR_BASE + 43 +ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED = INTERNET_ERROR_BASE + 44 +ERROR_INTERNET_INVALID_CA = INTERNET_ERROR_BASE + 45 +ERROR_INTERNET_CLIENT_AUTH_NOT_SETUP = INTERNET_ERROR_BASE + 46 +ERROR_INTERNET_ASYNC_THREAD_FAILED = INTERNET_ERROR_BASE + 47 +ERROR_INTERNET_REDIRECT_SCHEME_CHANGE = INTERNET_ERROR_BASE + 48 +ERROR_INTERNET_DIALOG_PENDING = INTERNET_ERROR_BASE + 49 +ERROR_INTERNET_RETRY_DIALOG = INTERNET_ERROR_BASE + 50 +ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR = INTERNET_ERROR_BASE + 52 +ERROR_INTERNET_INSERT_CDROM = INTERNET_ERROR_BASE + 53 +ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED = INTERNET_ERROR_BASE + 54 +ERROR_INTERNET_SEC_CERT_ERRORS = INTERNET_ERROR_BASE + 55 +ERROR_INTERNET_SEC_CERT_NO_REV = INTERNET_ERROR_BASE + 56 +ERROR_INTERNET_SEC_CERT_REV_FAILED = INTERNET_ERROR_BASE + 57 +ERROR_FTP_TRANSFER_IN_PROGRESS = INTERNET_ERROR_BASE + 110 +ERROR_FTP_DROPPED = INTERNET_ERROR_BASE + 111 +ERROR_FTP_NO_PASSIVE_MODE = INTERNET_ERROR_BASE + 112 +ERROR_GOPHER_PROTOCOL_ERROR = INTERNET_ERROR_BASE + 130 +ERROR_GOPHER_NOT_FILE = INTERNET_ERROR_BASE + 131 +ERROR_GOPHER_DATA_ERROR = INTERNET_ERROR_BASE + 132 +ERROR_GOPHER_END_OF_DATA = INTERNET_ERROR_BASE + 133 +ERROR_GOPHER_INVALID_LOCATOR = INTERNET_ERROR_BASE + 134 +ERROR_GOPHER_INCORRECT_LOCATOR_TYPE = INTERNET_ERROR_BASE + 135 +ERROR_GOPHER_NOT_GOPHER_PLUS = INTERNET_ERROR_BASE + 136 +ERROR_GOPHER_ATTRIBUTE_NOT_FOUND = INTERNET_ERROR_BASE + 137 +ERROR_GOPHER_UNKNOWN_LOCATOR = INTERNET_ERROR_BASE + 138 +ERROR_HTTP_HEADER_NOT_FOUND = INTERNET_ERROR_BASE + 150 +ERROR_HTTP_DOWNLEVEL_SERVER = INTERNET_ERROR_BASE + 151 +ERROR_HTTP_INVALID_SERVER_RESPONSE = INTERNET_ERROR_BASE + 152 +ERROR_HTTP_INVALID_HEADER = INTERNET_ERROR_BASE + 153 +ERROR_HTTP_INVALID_QUERY_REQUEST = INTERNET_ERROR_BASE + 154 +ERROR_HTTP_HEADER_ALREADY_EXISTS = INTERNET_ERROR_BASE + 155 +ERROR_HTTP_REDIRECT_FAILED = INTERNET_ERROR_BASE + 156 +ERROR_HTTP_NOT_REDIRECTED = INTERNET_ERROR_BASE + 160 +ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION = INTERNET_ERROR_BASE + 161 +ERROR_HTTP_COOKIE_DECLINED = INTERNET_ERROR_BASE + 162 +ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION = INTERNET_ERROR_BASE + 168 +ERROR_INTERNET_SECURITY_CHANNEL_ERROR = INTERNET_ERROR_BASE + 157 +ERROR_INTERNET_UNABLE_TO_CACHE_FILE = INTERNET_ERROR_BASE + 158 +ERROR_INTERNET_TCPIP_NOT_INSTALLED = INTERNET_ERROR_BASE + 159 +ERROR_INTERNET_DISCONNECTED = INTERNET_ERROR_BASE + 163 +ERROR_INTERNET_SERVER_UNREACHABLE = INTERNET_ERROR_BASE + 164 +ERROR_INTERNET_PROXY_SERVER_UNREACHABLE = INTERNET_ERROR_BASE + 165 +ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT = INTERNET_ERROR_BASE + 166 +ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT = INTERNET_ERROR_BASE + 167 +ERROR_INTERNET_SEC_INVALID_CERT = INTERNET_ERROR_BASE + 169 +ERROR_INTERNET_SEC_CERT_REVOKED = INTERNET_ERROR_BASE + 170 +ERROR_INTERNET_FAILED_DUETOSECURITYCHECK = INTERNET_ERROR_BASE + 171 +ERROR_INTERNET_NOT_INITIALIZED = INTERNET_ERROR_BASE + 172 +ERROR_INTERNET_NEED_MSN_SSPI_PKG = INTERNET_ERROR_BASE + 173 +ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY = INTERNET_ERROR_BASE + 174 +INTERNET_ERROR_LAST = ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY +NORMAL_CACHE_ENTRY = 0x00000001 +STICKY_CACHE_ENTRY = 0x00000004 +EDITED_CACHE_ENTRY = 0x00000008 +TRACK_OFFLINE_CACHE_ENTRY = 0x00000010 +TRACK_ONLINE_CACHE_ENTRY = 0x00000020 +SPARSE_CACHE_ENTRY = 0x00010000 +COOKIE_CACHE_ENTRY = 0x00100000 +URLHISTORY_CACHE_ENTRY = 0x00200000 +URLCACHE_FIND_DEFAULT_FILTER = ( + NORMAL_CACHE_ENTRY + | COOKIE_CACHE_ENTRY + | URLHISTORY_CACHE_ENTRY + | TRACK_OFFLINE_CACHE_ENTRY + | TRACK_ONLINE_CACHE_ENTRY + | STICKY_CACHE_ENTRY +) +CACHEGROUP_ATTRIBUTE_GET_ALL = -1 +CACHEGROUP_ATTRIBUTE_BASIC = 0x00000001 +CACHEGROUP_ATTRIBUTE_FLAG = 0x00000002 +CACHEGROUP_ATTRIBUTE_TYPE = 0x00000004 +CACHEGROUP_ATTRIBUTE_QUOTA = 0x00000008 +CACHEGROUP_ATTRIBUTE_GROUPNAME = 0x00000010 +CACHEGROUP_ATTRIBUTE_STORAGE = 0x00000020 +CACHEGROUP_FLAG_NONPURGEABLE = 0x00000001 +CACHEGROUP_FLAG_GIDONLY = 0x00000004 +CACHEGROUP_FLAG_FLUSHURL_ONDELETE = 0x00000002 +CACHEGROUP_SEARCH_ALL = 0x00000000 +CACHEGROUP_SEARCH_BYURL = 0x00000001 +CACHEGROUP_TYPE_INVALID = 0x00000001 +CACHEGROUP_READWRITE_MASK = ( + CACHEGROUP_ATTRIBUTE_TYPE + | CACHEGROUP_ATTRIBUTE_QUOTA + | CACHEGROUP_ATTRIBUTE_GROUPNAME + | CACHEGROUP_ATTRIBUTE_STORAGE +) +GROUPNAME_MAX_LENGTH = 120 +GROUP_OWNER_STORAGE_SIZE = 4 +CACHE_ENTRY_ATTRIBUTE_FC = 0x00000004 +CACHE_ENTRY_HITRATE_FC = 0x00000010 +CACHE_ENTRY_MODTIME_FC = 0x00000040 +CACHE_ENTRY_EXPTIME_FC = 0x00000080 +CACHE_ENTRY_ACCTIME_FC = 0x00000100 +CACHE_ENTRY_SYNCTIME_FC = 0x00000200 +CACHE_ENTRY_HEADERINFO_FC = 0x00000400 +CACHE_ENTRY_EXEMPT_DELTA_FC = 0x00000800 +INTERNET_CACHE_GROUP_ADD = 0 +INTERNET_CACHE_GROUP_REMOVE = 1 +INTERNET_DIAL_FORCE_PROMPT = 0x2000 +INTERNET_DIAL_SHOW_OFFLINE = 0x4000 +INTERNET_DIAL_UNATTENDED = 0x8000 +INTERENT_GOONLINE_REFRESH = 0x00000001 +INTERENT_GOONLINE_MASK = 0x00000001 +INTERNET_AUTODIAL_FORCE_ONLINE = 1 +INTERNET_AUTODIAL_FORCE_UNATTENDED = 2 +INTERNET_AUTODIAL_FAILIFSECURITYCHECK = 4 +INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT = 8 +INTERNET_AUTODIAL_FLAGS_MASK = ( + INTERNET_AUTODIAL_FORCE_ONLINE + | INTERNET_AUTODIAL_FORCE_UNATTENDED + | INTERNET_AUTODIAL_FAILIFSECURITYCHECK + | INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT +) +PROXY_AUTO_DETECT_TYPE_DHCP = 1 +PROXY_AUTO_DETECT_TYPE_DNS_A = 2 +INTERNET_CONNECTION_MODEM = 0x01 +INTERNET_CONNECTION_LAN = 0x02 +INTERNET_CONNECTION_PROXY = 0x04 +INTERNET_CONNECTION_MODEM_BUSY = 0x08 +INTERNET_RAS_INSTALLED = 0x10 +INTERNET_CONNECTION_OFFLINE = 0x20 +INTERNET_CONNECTION_CONFIGURED = 0x40 +INTERNET_CUSTOMDIAL_CONNECT = 0 +INTERNET_CUSTOMDIAL_UNATTENDED = 1 +INTERNET_CUSTOMDIAL_DISCONNECT = 2 +INTERNET_CUSTOMDIAL_SHOWOFFLINE = 4 +INTERNET_CUSTOMDIAL_SAFE_FOR_UNATTENDED = 1 +INTERNET_CUSTOMDIAL_WILL_SUPPLY_STATE = 2 +INTERNET_CUSTOMDIAL_CAN_HANGUP = 4 +INTERNET_DIALSTATE_DISCONNECTED = 1 +INTERNET_IDENTITY_FLAG_PRIVATE_CACHE = 0x01 +INTERNET_IDENTITY_FLAG_SHARED_CACHE = 0x02 +INTERNET_IDENTITY_FLAG_CLEAR_DATA = 0x04 +INTERNET_IDENTITY_FLAG_CLEAR_COOKIES = 0x08 +INTERNET_IDENTITY_FLAG_CLEAR_HISTORY = 0x10 +INTERNET_IDENTITY_FLAG_CLEAR_CONTENT = 0x20 +INTERNET_SUPPRESS_RESET_ALL = 0x00 +INTERNET_SUPPRESS_COOKIE_POLICY = 0x01 +INTERNET_SUPPRESS_COOKIE_POLICY_RESET = 0x02 +PRIVACY_TEMPLATE_NO_COOKIES = 0 +PRIVACY_TEMPLATE_HIGH = 1 +PRIVACY_TEMPLATE_MEDIUM_HIGH = 2 +PRIVACY_TEMPLATE_MEDIUM = 3 +PRIVACY_TEMPLATE_MEDIUM_LOW = 4 +PRIVACY_TEMPLATE_LOW = 5 +PRIVACY_TEMPLATE_CUSTOM = 100 +PRIVACY_TEMPLATE_ADVANCED = 101 +PRIVACY_TEMPLATE_MAX = PRIVACY_TEMPLATE_LOW +PRIVACY_TYPE_FIRST_PARTY = 0 +PRIVACY_TYPE_THIRD_PARTY = 1 + +# Generated by h2py from winhttp.h +WINHTTP_FLAG_ASYNC = 0x10000000 +WINHTTP_FLAG_SECURE = 0x00800000 +WINHTTP_FLAG_ESCAPE_PERCENT = 0x00000004 +WINHTTP_FLAG_NULL_CODEPAGE = 0x00000008 +WINHTTP_FLAG_BYPASS_PROXY_CACHE = 0x00000100 +WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE +WINHTTP_FLAG_ESCAPE_DISABLE = 0x00000040 +WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = 0x00000080 +INTERNET_SCHEME_HTTP = 1 +INTERNET_SCHEME_HTTPS = 2 +WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001 +WINHTTP_AUTOPROXY_CONFIG_URL = 0x00000002 +WINHTTP_AUTOPROXY_RUN_INPROCESS = 0x00010000 +WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = 0x00020000 +WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001 +WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002 +WINHTTP_TIME_FORMAT_BUFSIZE = 62 +WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0 +WINHTTP_ACCESS_TYPE_NO_PROXY = 1 +WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3 +WINHTTP_OPTION_CALLBACK = 1 +WINHTTP_OPTION_RESOLVE_TIMEOUT = 2 +WINHTTP_OPTION_CONNECT_TIMEOUT = 3 +WINHTTP_OPTION_CONNECT_RETRIES = 4 +WINHTTP_OPTION_SEND_TIMEOUT = 5 +WINHTTP_OPTION_RECEIVE_TIMEOUT = 6 +WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7 +WINHTTP_OPTION_HANDLE_TYPE = 9 +WINHTTP_OPTION_READ_BUFFER_SIZE = 12 +WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13 +WINHTTP_OPTION_PARENT_HANDLE = 21 +WINHTTP_OPTION_EXTENDED_ERROR = 24 +WINHTTP_OPTION_SECURITY_FLAGS = 31 +WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32 +WINHTTP_OPTION_URL = 34 +WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36 +WINHTTP_OPTION_PROXY = 38 +WINHTTP_OPTION_USER_AGENT = 41 +WINHTTP_OPTION_CONTEXT_VALUE = 45 +WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47 +WINHTTP_OPTION_REQUEST_PRIORITY = 58 +WINHTTP_OPTION_HTTP_VERSION = 59 +WINHTTP_OPTION_DISABLE_FEATURE = 63 +WINHTTP_OPTION_CODEPAGE = 68 +WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73 +WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74 +WINHTTP_OPTION_AUTOLOGON_POLICY = 77 +WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78 +WINHTTP_OPTION_ENABLE_FEATURE = 79 +WINHTTP_OPTION_WORKER_THREAD_COUNT = 80 +WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81 +WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82 +WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83 +WINHTTP_OPTION_SECURE_PROTOCOLS = 84 +WINHTTP_OPTION_ENABLETRACING = 85 +WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86 +WINHTTP_OPTION_PASSPORT_RETURN_URL = 87 +WINHTTP_OPTION_REDIRECT_POLICY = 88 +WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89 +WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90 +WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91 +WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92 +WINHTTP_OPTION_CONNECTION_INFO = 93 +WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94 +WINHTTP_OPTION_SPN = 96 +WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97 +WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98 +WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99 +WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100 +WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101 +WINHTTP_LAST_OPTION = WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS +WINHTTP_OPTION_USERNAME = 0x1000 +WINHTTP_OPTION_PASSWORD = 0x1001 +WINHTTP_OPTION_PROXY_USERNAME = 0x1002 +WINHTTP_OPTION_PROXY_PASSWORD = 0x1003 +WINHTTP_CONNS_PER_SERVER_UNLIMITED = -1 +WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0 +WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1 +WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2 +WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM +WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0 +WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1 +WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2 +WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS +WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = ( + WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP +) +WINHTTP_DISABLE_PASSPORT_AUTH = 0x00000000 +WINHTTP_ENABLE_PASSPORT_AUTH = 0x10000000 +WINHTTP_DISABLE_PASSPORT_KEYRING = 0x20000000 +WINHTTP_ENABLE_PASSPORT_KEYRING = 0x40000000 +WINHTTP_DISABLE_COOKIES = 0x00000001 +WINHTTP_DISABLE_REDIRECTS = 0x00000002 +WINHTTP_DISABLE_AUTHENTICATION = 0x00000004 +WINHTTP_DISABLE_KEEP_ALIVE = 0x00000008 +WINHTTP_ENABLE_SSL_REVOCATION = 0x00000001 +WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = 0x00000002 +WINHTTP_DISABLE_SPN_SERVER_PORT = 0x00000000 +WINHTTP_ENABLE_SPN_SERVER_PORT = 0x00000001 +WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT +WINHTTP_HANDLE_TYPE_SESSION = 1 +WINHTTP_HANDLE_TYPE_CONNECT = 2 +WINHTTP_HANDLE_TYPE_REQUEST = 3 +WINHTTP_AUTH_SCHEME_BASIC = 0x00000001 +WINHTTP_AUTH_SCHEME_NTLM = 0x00000002 +WINHTTP_AUTH_SCHEME_PASSPORT = 0x00000004 +WINHTTP_AUTH_SCHEME_DIGEST = 0x00000008 +WINHTTP_AUTH_SCHEME_NEGOTIATE = 0x00000010 +WINHTTP_AUTH_TARGET_SERVER = 0x00000000 +WINHTTP_AUTH_TARGET_PROXY = 0x00000001 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = 0x00000001 +WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = 0x00000002 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = 0x00000004 +WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = 0x00000008 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = 0x00000010 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = 0x00000020 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = 0x00000040 +WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = -2147483648 +WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = 0x00000008 +WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = 0x00000020 +WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = 0x00000080 +WINHTTP_FLAG_SECURE_PROTOCOL_ALL = ( + WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 + | WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 + | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 +) +WINHTTP_CALLBACK_STATUS_RESOLVING_NAME = 0x00000001 +WINHTTP_CALLBACK_STATUS_NAME_RESOLVED = 0x00000002 +WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER = 0x00000004 +WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER = 0x00000008 +WINHTTP_CALLBACK_STATUS_SENDING_REQUEST = 0x00000010 +WINHTTP_CALLBACK_STATUS_REQUEST_SENT = 0x00000020 +WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE = 0x00000040 +WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED = 0x00000080 +WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION = 0x00000100 +WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED = 0x00000200 +WINHTTP_CALLBACK_STATUS_HANDLE_CREATED = 0x00000400 +WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING = 0x00000800 +WINHTTP_CALLBACK_STATUS_DETECTING_PROXY = 0x00001000 +WINHTTP_CALLBACK_STATUS_REDIRECT = 0x00004000 +WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE = 0x00008000 +WINHTTP_CALLBACK_STATUS_SECURE_FAILURE = 0x00010000 +WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE = 0x00020000 +WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE = 0x00040000 +WINHTTP_CALLBACK_STATUS_READ_COMPLETE = 0x00080000 +WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE = 0x00100000 +WINHTTP_CALLBACK_STATUS_REQUEST_ERROR = 0x00200000 +WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE = 0x00400000 +API_RECEIVE_RESPONSE = 1 +API_QUERY_DATA_AVAILABLE = 2 +API_READ_DATA = 3 +API_WRITE_DATA = 4 +API_SEND_REQUEST = 5 +WINHTTP_CALLBACK_FLAG_RESOLVE_NAME = ( + WINHTTP_CALLBACK_STATUS_RESOLVING_NAME | WINHTTP_CALLBACK_STATUS_NAME_RESOLVED +) +WINHTTP_CALLBACK_FLAG_CONNECT_TO_SERVER = ( + WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER + | WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER +) +WINHTTP_CALLBACK_FLAG_SEND_REQUEST = ( + WINHTTP_CALLBACK_STATUS_SENDING_REQUEST | WINHTTP_CALLBACK_STATUS_REQUEST_SENT +) +WINHTTP_CALLBACK_FLAG_RECEIVE_RESPONSE = ( + WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE + | WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED +) +WINHTTP_CALLBACK_FLAG_CLOSE_CONNECTION = ( + WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION + | WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED +) +WINHTTP_CALLBACK_FLAG_HANDLES = ( + WINHTTP_CALLBACK_STATUS_HANDLE_CREATED | WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING +) +WINHTTP_CALLBACK_FLAG_DETECTING_PROXY = WINHTTP_CALLBACK_STATUS_DETECTING_PROXY +WINHTTP_CALLBACK_FLAG_REDIRECT = WINHTTP_CALLBACK_STATUS_REDIRECT +WINHTTP_CALLBACK_FLAG_INTERMEDIATE_RESPONSE = ( + WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE +) +WINHTTP_CALLBACK_FLAG_SECURE_FAILURE = WINHTTP_CALLBACK_STATUS_SECURE_FAILURE +WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE = ( + WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE +) +WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE = WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE +WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE = WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE +WINHTTP_CALLBACK_FLAG_READ_COMPLETE = WINHTTP_CALLBACK_STATUS_READ_COMPLETE +WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE = WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE +WINHTTP_CALLBACK_FLAG_REQUEST_ERROR = WINHTTP_CALLBACK_STATUS_REQUEST_ERROR +WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS = ( + WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE + | WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE + | WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE + | WINHTTP_CALLBACK_STATUS_READ_COMPLETE + | WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE + | WINHTTP_CALLBACK_STATUS_REQUEST_ERROR +) +WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS = -1 +WINHTTP_QUERY_MIME_VERSION = 0 +WINHTTP_QUERY_CONTENT_TYPE = 1 +WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2 +WINHTTP_QUERY_CONTENT_ID = 3 +WINHTTP_QUERY_CONTENT_DESCRIPTION = 4 +WINHTTP_QUERY_CONTENT_LENGTH = 5 +WINHTTP_QUERY_CONTENT_LANGUAGE = 6 +WINHTTP_QUERY_ALLOW = 7 +WINHTTP_QUERY_PUBLIC = 8 +WINHTTP_QUERY_DATE = 9 +WINHTTP_QUERY_EXPIRES = 10 +WINHTTP_QUERY_LAST_MODIFIED = 11 +WINHTTP_QUERY_MESSAGE_ID = 12 +WINHTTP_QUERY_URI = 13 +WINHTTP_QUERY_DERIVED_FROM = 14 +WINHTTP_QUERY_COST = 15 +WINHTTP_QUERY_LINK = 16 +WINHTTP_QUERY_PRAGMA = 17 +WINHTTP_QUERY_VERSION = 18 +WINHTTP_QUERY_STATUS_CODE = 19 +WINHTTP_QUERY_STATUS_TEXT = 20 +WINHTTP_QUERY_RAW_HEADERS = 21 +WINHTTP_QUERY_RAW_HEADERS_CRLF = 22 +WINHTTP_QUERY_CONNECTION = 23 +WINHTTP_QUERY_ACCEPT = 24 +WINHTTP_QUERY_ACCEPT_CHARSET = 25 +WINHTTP_QUERY_ACCEPT_ENCODING = 26 +WINHTTP_QUERY_ACCEPT_LANGUAGE = 27 +WINHTTP_QUERY_AUTHORIZATION = 28 +WINHTTP_QUERY_CONTENT_ENCODING = 29 +WINHTTP_QUERY_FORWARDED = 30 +WINHTTP_QUERY_FROM = 31 +WINHTTP_QUERY_IF_MODIFIED_SINCE = 32 +WINHTTP_QUERY_LOCATION = 33 +WINHTTP_QUERY_ORIG_URI = 34 +WINHTTP_QUERY_REFERER = 35 +WINHTTP_QUERY_RETRY_AFTER = 36 +WINHTTP_QUERY_SERVER = 37 +WINHTTP_QUERY_TITLE = 38 +WINHTTP_QUERY_USER_AGENT = 39 +WINHTTP_QUERY_WWW_AUTHENTICATE = 40 +WINHTTP_QUERY_PROXY_AUTHENTICATE = 41 +WINHTTP_QUERY_ACCEPT_RANGES = 42 +WINHTTP_QUERY_SET_COOKIE = 43 +WINHTTP_QUERY_COOKIE = 44 +WINHTTP_QUERY_REQUEST_METHOD = 45 +WINHTTP_QUERY_REFRESH = 46 +WINHTTP_QUERY_CONTENT_DISPOSITION = 47 +WINHTTP_QUERY_AGE = 48 +WINHTTP_QUERY_CACHE_CONTROL = 49 +WINHTTP_QUERY_CONTENT_BASE = 50 +WINHTTP_QUERY_CONTENT_LOCATION = 51 +WINHTTP_QUERY_CONTENT_MD5 = 52 +WINHTTP_QUERY_CONTENT_RANGE = 53 +WINHTTP_QUERY_ETAG = 54 +WINHTTP_QUERY_HOST = 55 +WINHTTP_QUERY_IF_MATCH = 56 +WINHTTP_QUERY_IF_NONE_MATCH = 57 +WINHTTP_QUERY_IF_RANGE = 58 +WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59 +WINHTTP_QUERY_MAX_FORWARDS = 60 +WINHTTP_QUERY_PROXY_AUTHORIZATION = 61 +WINHTTP_QUERY_RANGE = 62 +WINHTTP_QUERY_TRANSFER_ENCODING = 63 +WINHTTP_QUERY_UPGRADE = 64 +WINHTTP_QUERY_VARY = 65 +WINHTTP_QUERY_VIA = 66 +WINHTTP_QUERY_WARNING = 67 +WINHTTP_QUERY_EXPECT = 68 +WINHTTP_QUERY_PROXY_CONNECTION = 69 +WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70 +WINHTTP_QUERY_PROXY_SUPPORT = 75 +WINHTTP_QUERY_AUTHENTICATION_INFO = 76 +WINHTTP_QUERY_PASSPORT_URLS = 77 +WINHTTP_QUERY_PASSPORT_CONFIG = 78 +WINHTTP_QUERY_MAX = 78 +WINHTTP_QUERY_CUSTOM = 65535 +WINHTTP_QUERY_FLAG_REQUEST_HEADERS = -2147483648 +WINHTTP_QUERY_FLAG_SYSTEMTIME = 0x40000000 +WINHTTP_QUERY_FLAG_NUMBER = 0x20000000 +WINHTTP_ADDREQ_INDEX_MASK = 0x0000FFFF +WINHTTP_ADDREQ_FLAGS_MASK = -65536 +WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = 0x10000000 +WINHTTP_ADDREQ_FLAG_ADD = 0x20000000 +WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = 0x40000000 +WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = 0x01000000 +WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA +WINHTTP_ADDREQ_FLAG_REPLACE = -2147483648 +WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH = 0 +WINHTTP_ERROR_BASE = 12000 +ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1 +ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2 +ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4 +ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5 +ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6 +ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7 +ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9 +ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11 +ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12 +ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15 +ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17 +ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18 +ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19 +ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29 +ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30 +ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32 +ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44 +ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100 +ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101 +ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102 +ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103 +ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150 +ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152 +ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153 +ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154 +ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155 +ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156 +ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178 +ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166 +ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167 +ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172 +ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175 +ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37 +ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38 +ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45 +ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57 +ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157 +ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169 +ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170 +ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179 +ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180 +ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181 +ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182 +ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183 +ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184 +ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185 +ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186 +WINHTTP_ERROR_LAST = WINHTTP_ERROR_BASE + 186 + +WINHTTP_NO_PROXY_NAME = None +WINHTTP_NO_PROXY_BYPASS = None +WINHTTP_NO_REFERER = None +WINHTTP_DEFAULT_ACCEPT_TYPES = None +WINHTTP_NO_ADDITIONAL_HEADERS = None +WINHTTP_NO_REQUEST_DATA = None diff --git a/MLPY/Lib/site-packages/win32/lib/win32netcon.py b/MLPY/Lib/site-packages/win32/lib/win32netcon.py new file mode 100644 index 0000000000000000000000000000000000000000..63e97a14b56a3f353537cf0ed62ae130aa85e2e3 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32netcon.py @@ -0,0 +1,627 @@ +# Generated by h2py from lmaccess.h + +# Included from lmcons.h +CNLEN = 15 +LM20_CNLEN = 15 +DNLEN = CNLEN +LM20_DNLEN = LM20_CNLEN +UNCLEN = CNLEN + 2 +LM20_UNCLEN = LM20_CNLEN + 2 +NNLEN = 80 +LM20_NNLEN = 12 +RMLEN = UNCLEN + 1 + NNLEN +LM20_RMLEN = LM20_UNCLEN + 1 + LM20_NNLEN +SNLEN = 80 +LM20_SNLEN = 15 +STXTLEN = 256 +LM20_STXTLEN = 63 +PATHLEN = 256 +LM20_PATHLEN = 256 +DEVLEN = 80 +LM20_DEVLEN = 8 +EVLEN = 16 +UNLEN = 256 +LM20_UNLEN = 20 +GNLEN = UNLEN +LM20_GNLEN = LM20_UNLEN +PWLEN = 256 +LM20_PWLEN = 14 +SHPWLEN = 8 +CLTYPE_LEN = 12 +MAXCOMMENTSZ = 256 +LM20_MAXCOMMENTSZ = 48 +QNLEN = NNLEN +LM20_QNLEN = LM20_NNLEN +ALERTSZ = 128 +NETBIOS_NAME_LEN = 16 +CRYPT_KEY_LEN = 7 +CRYPT_TXT_LEN = 8 +ENCRYPTED_PWLEN = 16 +SESSION_PWLEN = 24 +SESSION_CRYPT_KLEN = 21 +PARMNUM_ALL = 0 +PARM_ERROR_NONE = 0 +PARMNUM_BASE_INFOLEVEL = 1000 +NULL = 0 +PLATFORM_ID_DOS = 300 +PLATFORM_ID_OS2 = 400 +PLATFORM_ID_NT = 500 +PLATFORM_ID_OSF = 600 +PLATFORM_ID_VMS = 700 +MAX_LANMAN_MESSAGE_ID = 5799 +UF_SCRIPT = 1 +UF_ACCOUNTDISABLE = 2 +UF_HOMEDIR_REQUIRED = 8 +UF_LOCKOUT = 16 +UF_PASSWD_NOTREQD = 32 +UF_PASSWD_CANT_CHANGE = 64 +UF_TEMP_DUPLICATE_ACCOUNT = 256 +UF_NORMAL_ACCOUNT = 512 +UF_INTERDOMAIN_TRUST_ACCOUNT = 2048 +UF_WORKSTATION_TRUST_ACCOUNT = 4096 +UF_SERVER_TRUST_ACCOUNT = 8192 +UF_MACHINE_ACCOUNT_MASK = ( + UF_INTERDOMAIN_TRUST_ACCOUNT + | UF_WORKSTATION_TRUST_ACCOUNT + | UF_SERVER_TRUST_ACCOUNT +) +UF_ACCOUNT_TYPE_MASK = ( + UF_TEMP_DUPLICATE_ACCOUNT + | UF_NORMAL_ACCOUNT + | UF_INTERDOMAIN_TRUST_ACCOUNT + | UF_WORKSTATION_TRUST_ACCOUNT + | UF_SERVER_TRUST_ACCOUNT +) +UF_DONT_EXPIRE_PASSWD = 65536 +UF_MNS_LOGON_ACCOUNT = 131072 +UF_SETTABLE_BITS = ( + UF_SCRIPT + | UF_ACCOUNTDISABLE + | UF_LOCKOUT + | UF_HOMEDIR_REQUIRED + | UF_PASSWD_NOTREQD + | UF_PASSWD_CANT_CHANGE + | UF_ACCOUNT_TYPE_MASK + | UF_DONT_EXPIRE_PASSWD + | UF_MNS_LOGON_ACCOUNT +) +FILTER_TEMP_DUPLICATE_ACCOUNT = 1 +FILTER_NORMAL_ACCOUNT = 2 +FILTER_INTERDOMAIN_TRUST_ACCOUNT = 8 +FILTER_WORKSTATION_TRUST_ACCOUNT = 16 +FILTER_SERVER_TRUST_ACCOUNT = 32 +LG_INCLUDE_INDIRECT = 1 +AF_OP_PRINT = 1 +AF_OP_COMM = 2 +AF_OP_SERVER = 4 +AF_OP_ACCOUNTS = 8 +AF_SETTABLE_BITS = AF_OP_PRINT | AF_OP_COMM | AF_OP_SERVER | AF_OP_ACCOUNTS +UAS_ROLE_STANDALONE = 0 +UAS_ROLE_MEMBER = 1 +UAS_ROLE_BACKUP = 2 +UAS_ROLE_PRIMARY = 3 +USER_NAME_PARMNUM = 1 +USER_PASSWORD_PARMNUM = 3 +USER_PASSWORD_AGE_PARMNUM = 4 +USER_PRIV_PARMNUM = 5 +USER_HOME_DIR_PARMNUM = 6 +USER_COMMENT_PARMNUM = 7 +USER_FLAGS_PARMNUM = 8 +USER_SCRIPT_PATH_PARMNUM = 9 +USER_AUTH_FLAGS_PARMNUM = 10 +USER_FULL_NAME_PARMNUM = 11 +USER_USR_COMMENT_PARMNUM = 12 +USER_PARMS_PARMNUM = 13 +USER_WORKSTATIONS_PARMNUM = 14 +USER_LAST_LOGON_PARMNUM = 15 +USER_LAST_LOGOFF_PARMNUM = 16 +USER_ACCT_EXPIRES_PARMNUM = 17 +USER_MAX_STORAGE_PARMNUM = 18 +USER_UNITS_PER_WEEK_PARMNUM = 19 +USER_LOGON_HOURS_PARMNUM = 20 +USER_PAD_PW_COUNT_PARMNUM = 21 +USER_NUM_LOGONS_PARMNUM = 22 +USER_LOGON_SERVER_PARMNUM = 23 +USER_COUNTRY_CODE_PARMNUM = 24 +USER_CODE_PAGE_PARMNUM = 25 +USER_PRIMARY_GROUP_PARMNUM = 51 +USER_PROFILE = 52 +USER_PROFILE_PARMNUM = 52 +USER_HOME_DIR_DRIVE_PARMNUM = 53 +USER_NAME_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_NAME_PARMNUM +USER_PASSWORD_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_PASSWORD_PARMNUM +USER_PASSWORD_AGE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_PASSWORD_AGE_PARMNUM +USER_PRIV_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_PRIV_PARMNUM +USER_HOME_DIR_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_HOME_DIR_PARMNUM +USER_COMMENT_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_COMMENT_PARMNUM +USER_FLAGS_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_FLAGS_PARMNUM +USER_SCRIPT_PATH_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_SCRIPT_PATH_PARMNUM +USER_AUTH_FLAGS_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_AUTH_FLAGS_PARMNUM +USER_FULL_NAME_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_FULL_NAME_PARMNUM +USER_USR_COMMENT_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_USR_COMMENT_PARMNUM +USER_PARMS_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_PARMS_PARMNUM +USER_WORKSTATIONS_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_WORKSTATIONS_PARMNUM +USER_LAST_LOGON_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_LAST_LOGON_PARMNUM +USER_LAST_LOGOFF_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_LAST_LOGOFF_PARMNUM +USER_ACCT_EXPIRES_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_ACCT_EXPIRES_PARMNUM +USER_MAX_STORAGE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_MAX_STORAGE_PARMNUM +USER_UNITS_PER_WEEK_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_UNITS_PER_WEEK_PARMNUM +USER_LOGON_HOURS_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_LOGON_HOURS_PARMNUM +USER_PAD_PW_COUNT_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_PAD_PW_COUNT_PARMNUM +USER_NUM_LOGONS_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_NUM_LOGONS_PARMNUM +USER_LOGON_SERVER_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_LOGON_SERVER_PARMNUM +USER_COUNTRY_CODE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_COUNTRY_CODE_PARMNUM +USER_CODE_PAGE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_CODE_PAGE_PARMNUM +USER_PRIMARY_GROUP_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_PRIMARY_GROUP_PARMNUM +USER_HOME_DIR_DRIVE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + USER_HOME_DIR_DRIVE_PARMNUM +NULL_USERSETINFO_PASSWD = " " +UNITS_PER_DAY = 24 +UNITS_PER_WEEK = UNITS_PER_DAY * 7 +USER_PRIV_MASK = 3 +USER_PRIV_GUEST = 0 +USER_PRIV_USER = 1 +USER_PRIV_ADMIN = 2 +MAX_PASSWD_LEN = PWLEN +DEF_MIN_PWLEN = 6 +DEF_PWUNIQUENESS = 5 +DEF_MAX_PWHIST = 8 +DEF_MAX_BADPW = 0 +VALIDATED_LOGON = 0 +PASSWORD_EXPIRED = 2 +NON_VALIDATED_LOGON = 3 +VALID_LOGOFF = 1 +MODALS_MIN_PASSWD_LEN_PARMNUM = 1 +MODALS_MAX_PASSWD_AGE_PARMNUM = 2 +MODALS_MIN_PASSWD_AGE_PARMNUM = 3 +MODALS_FORCE_LOGOFF_PARMNUM = 4 +MODALS_PASSWD_HIST_LEN_PARMNUM = 5 +MODALS_ROLE_PARMNUM = 6 +MODALS_PRIMARY_PARMNUM = 7 +MODALS_DOMAIN_NAME_PARMNUM = 8 +MODALS_DOMAIN_ID_PARMNUM = 9 +MODALS_LOCKOUT_DURATION_PARMNUM = 10 +MODALS_LOCKOUT_OBSERVATION_WINDOW_PARMNUM = 11 +MODALS_LOCKOUT_THRESHOLD_PARMNUM = 12 +MODALS_MIN_PASSWD_LEN_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_MIN_PASSWD_LEN_PARMNUM +MODALS_MAX_PASSWD_AGE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_MAX_PASSWD_AGE_PARMNUM +MODALS_MIN_PASSWD_AGE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_MIN_PASSWD_AGE_PARMNUM +MODALS_FORCE_LOGOFF_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_FORCE_LOGOFF_PARMNUM +MODALS_PASSWD_HIST_LEN_INFOLEVEL = ( + PARMNUM_BASE_INFOLEVEL + MODALS_PASSWD_HIST_LEN_PARMNUM +) +MODALS_ROLE_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_ROLE_PARMNUM +MODALS_PRIMARY_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_PRIMARY_PARMNUM +MODALS_DOMAIN_NAME_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_DOMAIN_NAME_PARMNUM +MODALS_DOMAIN_ID_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + MODALS_DOMAIN_ID_PARMNUM +GROUPIDMASK = 32768 +GROUP_ALL_PARMNUM = 0 +GROUP_NAME_PARMNUM = 1 +GROUP_COMMENT_PARMNUM = 2 +GROUP_ATTRIBUTES_PARMNUM = 3 +GROUP_ALL_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + GROUP_ALL_PARMNUM +GROUP_NAME_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + GROUP_NAME_PARMNUM +GROUP_COMMENT_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + GROUP_COMMENT_PARMNUM +GROUP_ATTRIBUTES_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + GROUP_ATTRIBUTES_PARMNUM +LOCALGROUP_NAME_PARMNUM = 1 +LOCALGROUP_COMMENT_PARMNUM = 2 +MAXPERMENTRIES = 64 +ACCESS_NONE = 0 +ACCESS_READ = 1 +ACCESS_WRITE = 2 +ACCESS_CREATE = 4 +ACCESS_EXEC = 8 +ACCESS_DELETE = 16 +ACCESS_ATRIB = 32 +ACCESS_PERM = 64 +ACCESS_GROUP = 32768 +ACCESS_AUDIT = 1 +ACCESS_SUCCESS_OPEN = 16 +ACCESS_SUCCESS_WRITE = 32 +ACCESS_SUCCESS_DELETE = 64 +ACCESS_SUCCESS_ACL = 128 +ACCESS_SUCCESS_MASK = 240 +ACCESS_FAIL_OPEN = 256 +ACCESS_FAIL_WRITE = 512 +ACCESS_FAIL_DELETE = 1024 +ACCESS_FAIL_ACL = 2048 +ACCESS_FAIL_MASK = 3840 +ACCESS_FAIL_SHIFT = 4 +ACCESS_RESOURCE_NAME_PARMNUM = 1 +ACCESS_ATTR_PARMNUM = 2 +ACCESS_COUNT_PARMNUM = 3 +ACCESS_ACCESS_LIST_PARMNUM = 4 +ACCESS_RESOURCE_NAME_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + ACCESS_RESOURCE_NAME_PARMNUM +ACCESS_ATTR_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + ACCESS_ATTR_PARMNUM +ACCESS_COUNT_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + ACCESS_COUNT_PARMNUM +ACCESS_ACCESS_LIST_INFOLEVEL = PARMNUM_BASE_INFOLEVEL + ACCESS_ACCESS_LIST_PARMNUM +ACCESS_LETTERS = "RWCXDAP " +NETLOGON_CONTROL_QUERY = 1 +NETLOGON_CONTROL_REPLICATE = 2 +NETLOGON_CONTROL_SYNCHRONIZE = 3 +NETLOGON_CONTROL_PDC_REPLICATE = 4 +NETLOGON_CONTROL_REDISCOVER = 5 +NETLOGON_CONTROL_TC_QUERY = 6 +NETLOGON_CONTROL_TRANSPORT_NOTIFY = 7 +NETLOGON_CONTROL_FIND_USER = 8 +NETLOGON_CONTROL_UNLOAD_NETLOGON_DLL = 65531 +NETLOGON_CONTROL_BACKUP_CHANGE_LOG = 65532 +NETLOGON_CONTROL_TRUNCATE_LOG = 65533 +NETLOGON_CONTROL_SET_DBFLAG = 65534 +NETLOGON_CONTROL_BREAKPOINT = 65535 +NETLOGON_REPLICATION_NEEDED = 1 +NETLOGON_REPLICATION_IN_PROGRESS = 2 +NETLOGON_FULL_SYNC_REPLICATION = 4 +NETLOGON_REDO_NEEDED = 8 + +###################### +# Manual stuff + +TEXT = lambda x: x + +MAX_PREFERRED_LENGTH = -1 +PARM_ERROR_UNKNOWN = -1 +MESSAGE_FILENAME = TEXT("NETMSG") +OS2MSG_FILENAME = TEXT("BASE") +HELP_MSG_FILENAME = TEXT("NETH") +BACKUP_MSG_FILENAME = TEXT("BAK.MSG") +TIMEQ_FOREVER = -1 +USER_MAXSTORAGE_UNLIMITED = -1 +USER_NO_LOGOFF = -1 +DEF_MAX_PWAGE = TIMEQ_FOREVER +DEF_MIN_PWAGE = 0 +DEF_FORCE_LOGOFF = -1 +ONE_DAY = 1 * 24 * 3600 +GROUP_SPECIALGRP_USERS = "USERS" +GROUP_SPECIALGRP_ADMINS = "ADMINS" +GROUP_SPECIALGRP_GUESTS = "GUESTS" +GROUP_SPECIALGRP_LOCAL = "LOCAL" +ACCESS_ALL = ( + ACCESS_READ + | ACCESS_WRITE + | ACCESS_CREATE + | ACCESS_EXEC + | ACCESS_DELETE + | ACCESS_ATRIB + | ACCESS_PERM +) + +# From lmserver.h +SV_PLATFORM_ID_OS2 = 400 +SV_PLATFORM_ID_NT = 500 +MAJOR_VERSION_MASK = 15 +SV_TYPE_WORKSTATION = 1 +SV_TYPE_SERVER = 2 +SV_TYPE_SQLSERVER = 4 +SV_TYPE_DOMAIN_CTRL = 8 +SV_TYPE_DOMAIN_BAKCTRL = 16 +SV_TYPE_TIME_SOURCE = 32 +SV_TYPE_AFP = 64 +SV_TYPE_NOVELL = 128 +SV_TYPE_DOMAIN_MEMBER = 256 +SV_TYPE_PRINTQ_SERVER = 512 +SV_TYPE_DIALIN_SERVER = 1024 +SV_TYPE_XENIX_SERVER = 2048 +SV_TYPE_SERVER_UNIX = SV_TYPE_XENIX_SERVER +SV_TYPE_NT = 4096 +SV_TYPE_WFW = 8192 +SV_TYPE_SERVER_MFPN = 16384 +SV_TYPE_SERVER_NT = 32768 +SV_TYPE_POTENTIAL_BROWSER = 65536 +SV_TYPE_BACKUP_BROWSER = 131072 +SV_TYPE_MASTER_BROWSER = 262144 +SV_TYPE_DOMAIN_MASTER = 524288 +SV_TYPE_SERVER_OSF = 1048576 +SV_TYPE_SERVER_VMS = 2097152 +SV_TYPE_WINDOWS = 4194304 +SV_TYPE_DFS = 8388608 +SV_TYPE_CLUSTER_NT = 16777216 +SV_TYPE_DCE = 268435456 +SV_TYPE_ALTERNATE_XPORT = 536870912 +SV_TYPE_LOCAL_LIST_ONLY = 1073741824 +SV_TYPE_DOMAIN_ENUM = -2147483648 +SV_TYPE_ALL = -1 +SV_NODISC = -1 +SV_USERSECURITY = 1 +SV_SHARESECURITY = 0 +SV_HIDDEN = 1 +SV_VISIBLE = 0 +SV_PLATFORM_ID_PARMNUM = 101 +SV_NAME_PARMNUM = 102 +SV_VERSION_MAJOR_PARMNUM = 103 +SV_VERSION_MINOR_PARMNUM = 104 +SV_TYPE_PARMNUM = 105 +SV_COMMENT_PARMNUM = 5 +SV_USERS_PARMNUM = 107 +SV_DISC_PARMNUM = 10 +SV_HIDDEN_PARMNUM = 16 +SV_ANNOUNCE_PARMNUM = 17 +SV_ANNDELTA_PARMNUM = 18 +SV_USERPATH_PARMNUM = 112 +SV_ULIST_MTIME_PARMNUM = 401 +SV_GLIST_MTIME_PARMNUM = 402 +SV_ALIST_MTIME_PARMNUM = 403 +SV_ALERTS_PARMNUM = 11 +SV_SECURITY_PARMNUM = 405 +SV_NUMADMIN_PARMNUM = 406 +SV_LANMASK_PARMNUM = 407 +SV_GUESTACC_PARMNUM = 408 +SV_CHDEVQ_PARMNUM = 410 +SV_CHDEVJOBS_PARMNUM = 411 +SV_CONNECTIONS_PARMNUM = 412 +SV_SHARES_PARMNUM = 413 +SV_OPENFILES_PARMNUM = 414 +SV_SESSREQS_PARMNUM = 417 +SV_ACTIVELOCKS_PARMNUM = 419 +SV_NUMREQBUF_PARMNUM = 420 +SV_NUMBIGBUF_PARMNUM = 422 +SV_NUMFILETASKS_PARMNUM = 423 +SV_ALERTSCHED_PARMNUM = 37 +SV_ERRORALERT_PARMNUM = 38 +SV_LOGONALERT_PARMNUM = 39 +SV_ACCESSALERT_PARMNUM = 40 +SV_DISKALERT_PARMNUM = 41 +SV_NETIOALERT_PARMNUM = 42 +SV_MAXAUDITSZ_PARMNUM = 43 +SV_SRVHEURISTICS_PARMNUM = 431 +SV_SESSOPENS_PARMNUM = 501 +SV_SESSVCS_PARMNUM = 502 +SV_OPENSEARCH_PARMNUM = 503 +SV_SIZREQBUF_PARMNUM = 504 +SV_INITWORKITEMS_PARMNUM = 505 +SV_MAXWORKITEMS_PARMNUM = 506 +SV_RAWWORKITEMS_PARMNUM = 507 +SV_IRPSTACKSIZE_PARMNUM = 508 +SV_MAXRAWBUFLEN_PARMNUM = 509 +SV_SESSUSERS_PARMNUM = 510 +SV_SESSCONNS_PARMNUM = 511 +SV_MAXNONPAGEDMEMORYUSAGE_PARMNUM = 512 +SV_MAXPAGEDMEMORYUSAGE_PARMNUM = 513 +SV_ENABLESOFTCOMPAT_PARMNUM = 514 +SV_ENABLEFORCEDLOGOFF_PARMNUM = 515 +SV_TIMESOURCE_PARMNUM = 516 +SV_ACCEPTDOWNLEVELAPIS_PARMNUM = 517 +SV_LMANNOUNCE_PARMNUM = 518 +SV_DOMAIN_PARMNUM = 519 +SV_MAXCOPYREADLEN_PARMNUM = 520 +SV_MAXCOPYWRITELEN_PARMNUM = 521 +SV_MINKEEPSEARCH_PARMNUM = 522 +SV_MAXKEEPSEARCH_PARMNUM = 523 +SV_MINKEEPCOMPLSEARCH_PARMNUM = 524 +SV_MAXKEEPCOMPLSEARCH_PARMNUM = 525 +SV_THREADCOUNTADD_PARMNUM = 526 +SV_NUMBLOCKTHREADS_PARMNUM = 527 +SV_SCAVTIMEOUT_PARMNUM = 528 +SV_MINRCVQUEUE_PARMNUM = 529 +SV_MINFREEWORKITEMS_PARMNUM = 530 +SV_XACTMEMSIZE_PARMNUM = 531 +SV_THREADPRIORITY_PARMNUM = 532 +SV_MAXMPXCT_PARMNUM = 533 +SV_OPLOCKBREAKWAIT_PARMNUM = 534 +SV_OPLOCKBREAKRESPONSEWAIT_PARMNUM = 535 +SV_ENABLEOPLOCKS_PARMNUM = 536 +SV_ENABLEOPLOCKFORCECLOSE_PARMNUM = 537 +SV_ENABLEFCBOPENS_PARMNUM = 538 +SV_ENABLERAW_PARMNUM = 539 +SV_ENABLESHAREDNETDRIVES_PARMNUM = 540 +SV_MINFREECONNECTIONS_PARMNUM = 541 +SV_MAXFREECONNECTIONS_PARMNUM = 542 +SV_INITSESSTABLE_PARMNUM = 543 +SV_INITCONNTABLE_PARMNUM = 544 +SV_INITFILETABLE_PARMNUM = 545 +SV_INITSEARCHTABLE_PARMNUM = 546 +SV_ALERTSCHEDULE_PARMNUM = 547 +SV_ERRORTHRESHOLD_PARMNUM = 548 +SV_NETWORKERRORTHRESHOLD_PARMNUM = 549 +SV_DISKSPACETHRESHOLD_PARMNUM = 550 +SV_MAXLINKDELAY_PARMNUM = 552 +SV_MINLINKTHROUGHPUT_PARMNUM = 553 +SV_LINKINFOVALIDTIME_PARMNUM = 554 +SV_SCAVQOSINFOUPDATETIME_PARMNUM = 555 +SV_MAXWORKITEMIDLETIME_PARMNUM = 556 +SV_MAXRAWWORKITEMS_PARMNUM = 557 +SV_PRODUCTTYPE_PARMNUM = 560 +SV_SERVERSIZE_PARMNUM = 561 +SV_CONNECTIONLESSAUTODISC_PARMNUM = 562 +SV_SHARINGVIOLATIONRETRIES_PARMNUM = 563 +SV_SHARINGVIOLATIONDELAY_PARMNUM = 564 +SV_MAXGLOBALOPENSEARCH_PARMNUM = 565 +SV_REMOVEDUPLICATESEARCHES_PARMNUM = 566 +SV_LOCKVIOLATIONRETRIES_PARMNUM = 567 +SV_LOCKVIOLATIONOFFSET_PARMNUM = 568 +SV_LOCKVIOLATIONDELAY_PARMNUM = 569 +SV_MDLREADSWITCHOVER_PARMNUM = 570 +SV_CACHEDOPENLIMIT_PARMNUM = 571 +SV_CRITICALTHREADS_PARMNUM = 572 +SV_RESTRICTNULLSESSACCESS_PARMNUM = 573 +SV_ENABLEWFW311DIRECTIPX_PARMNUM = 574 +SV_OTHERQUEUEAFFINITY_PARMNUM = 575 +SV_QUEUESAMPLESECS_PARMNUM = 576 +SV_BALANCECOUNT_PARMNUM = 577 +SV_PREFERREDAFFINITY_PARMNUM = 578 +SV_MAXFREERFCBS_PARMNUM = 579 +SV_MAXFREEMFCBS_PARMNUM = 580 +SV_MAXFREELFCBS_PARMNUM = 581 +SV_MAXFREEPAGEDPOOLCHUNKS_PARMNUM = 582 +SV_MINPAGEDPOOLCHUNKSIZE_PARMNUM = 583 +SV_MAXPAGEDPOOLCHUNKSIZE_PARMNUM = 584 +SV_SENDSFROMPREFERREDPROCESSOR_PARMNUM = 585 +SV_MAXTHREADSPERQUEUE_PARMNUM = 586 +SV_CACHEDDIRECTORYLIMIT_PARMNUM = 587 +SV_MAXCOPYLENGTH_PARMNUM = 588 +SV_ENABLEBULKTRANSFER_PARMNUM = 589 +SV_ENABLECOMPRESSION_PARMNUM = 590 +SV_AUTOSHAREWKS_PARMNUM = 591 +SV_AUTOSHARESERVER_PARMNUM = 592 +SV_ENABLESECURITYSIGNATURE_PARMNUM = 593 +SV_REQUIRESECURITYSIGNATURE_PARMNUM = 594 +SV_MINCLIENTBUFFERSIZE_PARMNUM = 595 +SV_CONNECTIONNOSESSIONSTIMEOUT_PARMNUM = 596 +SVI1_NUM_ELEMENTS = 5 +SVI2_NUM_ELEMENTS = 40 +SVI3_NUM_ELEMENTS = 44 +SW_AUTOPROF_LOAD_MASK = 1 +SW_AUTOPROF_SAVE_MASK = 2 +SV_MAX_SRV_HEUR_LEN = 32 +SV_USERS_PER_LICENSE = 5 +SVTI2_REMAP_PIPE_NAMES = 2 + +# Generated by h2py from lmshare.h +SHARE_NETNAME_PARMNUM = 1 +SHARE_TYPE_PARMNUM = 3 +SHARE_REMARK_PARMNUM = 4 +SHARE_PERMISSIONS_PARMNUM = 5 +SHARE_MAX_USES_PARMNUM = 6 +SHARE_CURRENT_USES_PARMNUM = 7 +SHARE_PATH_PARMNUM = 8 +SHARE_PASSWD_PARMNUM = 9 +SHARE_FILE_SD_PARMNUM = 501 +SHI1_NUM_ELEMENTS = 4 +SHI2_NUM_ELEMENTS = 10 +STYPE_DISKTREE = 0 +STYPE_PRINTQ = 1 +STYPE_DEVICE = 2 +STYPE_IPC = 3 +STYPE_SPECIAL = -2147483648 +SHI1005_FLAGS_DFS = 1 +SHI1005_FLAGS_DFS_ROOT = 2 +COW_PERMACHINE = 4 +COW_PERUSER = 8 +CSC_CACHEABLE = 16 +CSC_NOFLOWOPS = 32 +CSC_AUTO_INWARD = 64 +CSC_AUTO_OUTWARD = 128 +SHI1005_VALID_FLAGS_SET = ( + CSC_CACHEABLE + | CSC_NOFLOWOPS + | CSC_AUTO_INWARD + | CSC_AUTO_OUTWARD + | COW_PERMACHINE + | COW_PERUSER +) +SHI1007_VALID_FLAGS_SET = SHI1005_VALID_FLAGS_SET +SESS_GUEST = 1 +SESS_NOENCRYPTION = 2 +SESI1_NUM_ELEMENTS = 8 +SESI2_NUM_ELEMENTS = 9 +PERM_FILE_READ = 1 +PERM_FILE_WRITE = 2 +PERM_FILE_CREATE = 4 + +# Generated by h2py from d:\mssdk\include\winnetwk.h +WNNC_NET_MSNET = 65536 +WNNC_NET_LANMAN = 131072 +WNNC_NET_NETWARE = 196608 +WNNC_NET_VINES = 262144 +WNNC_NET_10NET = 327680 +WNNC_NET_LOCUS = 393216 +WNNC_NET_SUN_PC_NFS = 458752 +WNNC_NET_LANSTEP = 524288 +WNNC_NET_9TILES = 589824 +WNNC_NET_LANTASTIC = 655360 +WNNC_NET_AS400 = 720896 +WNNC_NET_FTP_NFS = 786432 +WNNC_NET_PATHWORKS = 851968 +WNNC_NET_LIFENET = 917504 +WNNC_NET_POWERLAN = 983040 +WNNC_NET_BWNFS = 1048576 +WNNC_NET_COGENT = 1114112 +WNNC_NET_FARALLON = 1179648 +WNNC_NET_APPLETALK = 1245184 +WNNC_NET_INTERGRAPH = 1310720 +WNNC_NET_SYMFONET = 1376256 +WNNC_NET_CLEARCASE = 1441792 +WNNC_NET_FRONTIER = 1507328 +WNNC_NET_BMC = 1572864 +WNNC_NET_DCE = 1638400 +WNNC_NET_DECORB = 2097152 +WNNC_NET_PROTSTOR = 2162688 +WNNC_NET_FJ_REDIR = 2228224 +WNNC_NET_DISTINCT = 2293760 +WNNC_NET_TWINS = 2359296 +WNNC_NET_RDR2SAMPLE = 2424832 +RESOURCE_CONNECTED = 1 +RESOURCE_GLOBALNET = 2 +RESOURCE_REMEMBERED = 3 +RESOURCE_RECENT = 4 +RESOURCE_CONTEXT = 5 +RESOURCETYPE_ANY = 0 +RESOURCETYPE_DISK = 1 +RESOURCETYPE_PRINT = 2 +RESOURCETYPE_RESERVED = 8 +RESOURCETYPE_UNKNOWN = -1 +RESOURCEUSAGE_CONNECTABLE = 1 +RESOURCEUSAGE_CONTAINER = 2 +RESOURCEUSAGE_NOLOCALDEVICE = 4 +RESOURCEUSAGE_SIBLING = 8 +RESOURCEUSAGE_ATTACHED = 16 +RESOURCEUSAGE_ALL = ( + RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED +) +RESOURCEUSAGE_RESERVED = -2147483648 +RESOURCEDISPLAYTYPE_GENERIC = 0 +RESOURCEDISPLAYTYPE_DOMAIN = 1 +RESOURCEDISPLAYTYPE_SERVER = 2 +RESOURCEDISPLAYTYPE_SHARE = 3 +RESOURCEDISPLAYTYPE_FILE = 4 +RESOURCEDISPLAYTYPE_GROUP = 5 +RESOURCEDISPLAYTYPE_NETWORK = 6 +RESOURCEDISPLAYTYPE_ROOT = 7 +RESOURCEDISPLAYTYPE_SHAREADMIN = 8 +RESOURCEDISPLAYTYPE_DIRECTORY = 9 +RESOURCEDISPLAYTYPE_TREE = 10 +RESOURCEDISPLAYTYPE_NDSCONTAINER = 11 +NETPROPERTY_PERSISTENT = 1 +CONNECT_UPDATE_PROFILE = 1 +CONNECT_UPDATE_RECENT = 2 +CONNECT_TEMPORARY = 4 +CONNECT_INTERACTIVE = 8 +CONNECT_PROMPT = 16 +CONNECT_NEED_DRIVE = 32 +CONNECT_REFCOUNT = 64 +CONNECT_REDIRECT = 128 +CONNECT_LOCALDRIVE = 256 +CONNECT_CURRENT_MEDIA = 512 +CONNECT_DEFERRED = 1024 +CONNECT_RESERVED = -16777216 +CONNDLG_RO_PATH = 1 +CONNDLG_CONN_POINT = 2 +CONNDLG_USE_MRU = 4 +CONNDLG_HIDE_BOX = 8 +CONNDLG_PERSIST = 16 +CONNDLG_NOT_PERSIST = 32 +DISC_UPDATE_PROFILE = 1 +DISC_NO_FORCE = 64 +UNIVERSAL_NAME_INFO_LEVEL = 1 +REMOTE_NAME_INFO_LEVEL = 2 +WNFMT_MULTILINE = 1 +WNFMT_ABBREVIATED = 2 +WNFMT_INENUM = 16 +WNFMT_CONNECTION = 32 +NETINFO_DLL16 = 1 +NETINFO_DISKRED = 4 +NETINFO_PRINTERRED = 8 +RP_LOGON = 1 +RP_INIFILE = 2 +PP_DISPLAYERRORS = 1 +WNCON_FORNETCARD = 1 +WNCON_NOTROUTED = 2 +WNCON_SLOWLINK = 4 +WNCON_DYNAMIC = 8 + +## NETSETUP_NAME_TYPE, used with NetValidateName +NetSetupUnknown = 0 +NetSetupMachine = 1 +NetSetupWorkgroup = 2 +NetSetupDomain = 3 +NetSetupNonExistentDomain = 4 +NetSetupDnsMachine = 5 + +## NETSETUP_JOIN_STATUS, use with NetGetJoinInformation +NetSetupUnknownStatus = 0 +NetSetupUnjoined = 1 +NetSetupWorkgroupName = 2 +NetSetupDomainName = 3 + +NetValidateAuthentication = 1 +NetValidatePasswordChange = 2 +NetValidatePasswordReset = 3 diff --git a/MLPY/Lib/site-packages/win32/lib/win32pdhquery.py b/MLPY/Lib/site-packages/win32/lib/win32pdhquery.py new file mode 100644 index 0000000000000000000000000000000000000000..a48db08a8369677699751fcec69c082002e30c91 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32pdhquery.py @@ -0,0 +1,571 @@ +""" +Performance Data Helper (PDH) Query Classes + +Wrapper classes for end-users and high-level access to the PDH query +mechanisms. PDH is a win32-specific mechanism for accessing the +performance data made available by the system. The Python for Windows +PDH module does not implement the "Registry" interface, implementing +the more straightforward Query-based mechanism. + +The basic idea of a PDH Query is an object which can query the system +about the status of any number of "counters." The counters are paths +to a particular piece of performance data. For instance, the path +'\\Memory\\Available Bytes' describes just about exactly what it says +it does, the amount of free memory on the default computer expressed +in Bytes. These paths can be considerably more complex than this, +but part of the point of this wrapper module is to hide that +complexity from the end-user/programmer. + +EXAMPLE: A more complex Path + '\\\\RAISTLIN\\PhysicalDisk(_Total)\\Avg. Disk Bytes/Read' + Raistlin --> Computer Name + PhysicalDisk --> Object Name + _Total --> The particular Instance (in this case, all instances, i.e. all drives) + Avg. Disk Bytes/Read --> The piece of data being monitored. + +EXAMPLE: Collecting Data with a Query + As an example, the following code implements a logger which allows the + user to choose what counters they would like to log, and logs those + counters for 30 seconds, at two-second intervals. + + query = Query() + query.addcounterbybrowsing() + query.collectdatafor(30,2) + + The data is now stored in a list of lists as: + query.curresults + + The counters(paths) which were used to collect the data are: + query.curpaths + + You can use the win32pdh.ParseCounterPath(path) utility function + to turn the paths into more easily read values for your task, or + write the data to a file, or do whatever you want with it. + +OTHER NOTABLE METHODS: + query.collectdatawhile(period) # start a logging thread for collecting data + query.collectdatawhile_stop() # signal the logging thread to stop logging + query.collectdata() # run the query only once + query.addperfcounter(object, counter, machine=None) # add a standard performance counter + query.addinstcounter(object, counter,machine=None,objtype = 'Process',volatile=1,format = win32pdh.PDH_FMT_LONG) # add a possibly volatile counter + +### Known bugs and limitations ### +Due to a problem with threading under the PythonWin interpreter, there +will be no data logged if the PythonWin window is not the foreground +application. Workaround: scripts using threading should be run in the +python.exe interpreter. + +The volatile-counter handlers are possibly buggy, they haven't been +tested to any extent. The wrapper Query makes it safe to pass invalid +paths (a -1 will be returned, or the Query will be totally ignored, +depending on the missing element), so you should be able to work around +the error by including all possible paths and filtering out the -1's. + +There is no way I know of to stop a thread which is currently sleeping, +so you have to wait until the thread in collectdatawhile is activated +again. This might become a problem in situations where the collection +period is multiple minutes (or hours, or whatever). + +Should make the win32pdh.ParseCounter function available to the Query +classes as a method or something similar, so that it can be accessed +by programmes that have just picked up an instance from somewhere. + +Should explicitly mention where QueryErrors can be raised, and create a +full test set to see if there are any uncaught win32api.error's still +hanging around. + +When using the python.exe interpreter, the addcounterbybrowsing- +generated browser window is often hidden behind other windows. No known +workaround other than Alt-tabing to reach the browser window. + +### Other References ### +The win32pdhutil module (which should be in the %pythonroot%/win32/lib +directory) provides quick-and-dirty utilities for one-off access to +variables from the PDH. Almost everything in that module can be done +with a Query object, but it provides task-oriented functions for a +number of common one-off tasks. + +If you can access the MS Developers Network Library, you can find +information about the PDH API as MS describes it. For a background article, +try: +http://msdn.microsoft.com/library/en-us/dnperfmo/html/msdn_pdhlib.asp + +The reference guide for the PDH API was last spotted at: +http://msdn.microsoft.com/library/en-us/perfmon/base/using_the_pdh_interface.asp + + +In general the Python version of the API is just a wrapper around the +Query-based version of this API (as far as I can see), so you can learn what +you need to from there. From what I understand, the MSDN Online +resources are available for the price of signing up for them. I can't +guarantee how long that's supposed to last. (Or anything for that +matter). +http://premium.microsoft.com/isapi/devonly/prodinfo/msdnprod/msdnlib.idc?theURL=/msdn/library/sdkdoc/perfdata_4982.htm + +The eventual plan is for my (Mike Fletcher's) Starship account to include +a section on NT Administration, and the Query is the first project +in this plan. There should be an article describing the creation of +a simple logger there, but the example above is 90% of the work of +that project, so don't sweat it if you don't find anything there. +(currently the account hasn't been set up). +http://starship.skyport.net/crew/mcfletch/ + +If you need to contact me immediately, (why I can't imagine), you can +email me at mcfletch@golden.net, or just post your question to the +Python newsgroup with a catchy subject line. +news:comp.lang.python + +### Other Stuff ### +The Query classes are by Mike Fletcher, with the working code +being corruptions of Mark Hammonds win32pdhutil module. + +Use at your own risk, no warranties, no guarantees, no assurances, +if you use it, you accept the risk of using it, etceteras. + +""" +# Feb 12, 98 - MH added "rawaddcounter" so caller can get exception details. + +import _thread +import copy +import time + +import win32api +import win32pdh + + +class BaseQuery: + """ + Provides wrapped access to the Performance Data Helper query + objects, generally you should use the child class Query + unless you have need of doing weird things :) + + This class supports two major working paradigms. In the first, + you open the query, and run it as many times as you need, closing + the query when you're done with it. This is suitable for static + queries (ones where processes being monitored don't disappear). + + In the second, you allow the query to be opened each time and + closed afterward. This causes the base query object to be + destroyed after each call. Suitable for dynamic queries (ones + which watch processes which might be closed while watching.) + """ + + def __init__(self, paths=None): + """ + The PDH Query object is initialised with a single, optional + list argument, that must be properly formatted PDH Counter + paths. Generally this list will only be provided by the class + when it is being unpickled (removed from storage). Normal + use is to call the class with no arguments and use the various + addcounter functions (particularly, for end user's, the use of + addcounterbybrowsing is the most common approach) You might + want to provide the list directly if you want to hard-code the + elements with which your query deals (and thereby avoid the + overhead of unpickling the class). + """ + self.counters = [] + if paths: + self.paths = paths + else: + self.paths = [] + self._base = None + self.active = 0 + self.curpaths = [] + + def addcounterbybrowsing( + self, flags=win32pdh.PERF_DETAIL_WIZARD, windowtitle="Python Browser" + ): + """ + Adds possibly multiple paths to the paths attribute of the query, + does this by calling the standard counter browsing dialogue. Within + this dialogue, find the counter you want to log, and click: Add, + repeat for every path you want to log, then click on close. The + paths are appended to the non-volatile paths list for this class, + subclasses may create a function which parses the paths and decides + (via heuristics) whether to add the path to the volatile or non-volatile + path list. + e.g.: + query.addcounter() + """ + win32pdh.BrowseCounters(None, 0, self.paths.append, flags, windowtitle) + + def rawaddcounter(self, object, counter, instance=None, inum=-1, machine=None): + """ + Adds a single counter path, without catching any exceptions. + + See addcounter for details. + """ + path = win32pdh.MakeCounterPath( + (machine, object, instance, None, inum, counter) + ) + self.paths.append(path) + + def addcounter(self, object, counter, instance=None, inum=-1, machine=None): + """ + Adds a single counter path to the paths attribute. Normally + this will be called by a child class' speciality functions, + rather than being called directly by the user. (Though it isn't + hard to call manually, since almost everything is given a default) + This method is only functional when the query is closed (or hasn't + yet been opened). This is to prevent conflict in multi-threaded + query applications). + e.g.: + query.addcounter('Memory','Available Bytes') + """ + if not self.active: + try: + self.rawaddcounter(object, counter, instance, inum, machine) + return 0 + except win32api.error: + return -1 + else: + return -1 + + def open(self): + """ + Build the base query object for this wrapper, + then add all of the counters required for the query. + Raise a QueryError if we can't complete the functions. + If we are already open, then do nothing. + """ + if not self.active: # to prevent having multiple open queries + # curpaths are made accessible here because of the possibility of volatile paths + # which may be dynamically altered by subclasses. + self.curpaths = copy.copy(self.paths) + try: + base = win32pdh.OpenQuery() + for path in self.paths: + try: + self.counters.append(win32pdh.AddCounter(base, path)) + except win32api.error: # we passed a bad path + self.counters.append(0) + pass + self._base = base + self.active = 1 + return 0 # open succeeded + except: # if we encounter any errors, kill the Query + try: + self.killbase(base) + except NameError: # failed in creating query + pass + self.active = 0 + self.curpaths = [] + raise QueryError(self) + return 1 # already open + + def killbase(self, base=None): + """ + ### This is not a public method + Mission critical function to kill the win32pdh objects held + by this object. User's should generally use the close method + instead of this method, in case a sub-class has overridden + close to provide some special functionality. + """ + # Kill Pythonic references to the objects in this object's namespace + self._base = None + counters = self.counters + self.counters = [] + # we don't kill the curpaths for convenience, this allows the + # user to close a query and still access the last paths + self.active = 0 + # Now call the delete functions on all of the objects + try: + map(win32pdh.RemoveCounter, counters) + except: + pass + try: + win32pdh.CloseQuery(base) + except: + pass + del counters + del base + + def close(self): + """ + Makes certain that the underlying query object has been closed, + and that all counters have been removed from it. This is + important for reference counting. + You should only need to call close if you have previously called + open. The collectdata methods all can handle opening and + closing the query. Calling close multiple times is acceptable. + """ + try: + self.killbase(self._base) + except AttributeError: + self.killbase() + + __del__ = close + + def collectdata(self, format=win32pdh.PDH_FMT_LONG): + """ + Returns the formatted current values for the Query + """ + if self._base: # we are currently open, don't change this + return self.collectdataslave(format) + else: # need to open and then close the _base, should be used by one-offs and elements tracking application instances + self.open() # will raise QueryError if couldn't open the query + temp = self.collectdataslave(format) + self.close() # will always close + return temp + + def collectdataslave(self, format=win32pdh.PDH_FMT_LONG): + """ + ### Not a public method + Called only when the Query is known to be open, runs over + the whole set of counters, appending results to the temp, + returns the values as a list. + """ + try: + win32pdh.CollectQueryData(self._base) + temp = [] + for counter in self.counters: + ok = 0 + try: + if counter: + temp.append( + win32pdh.GetFormattedCounterValue(counter, format)[1] + ) + ok = 1 + except win32api.error: + pass + if not ok: + temp.append(-1) # a better way to signal failure??? + return temp + except ( + win32api.error + ): # will happen if, for instance, no counters are part of the query and we attempt to collect data for it. + return [-1] * len(self.counters) + + # pickle functions + def __getinitargs__(self): + """ + ### Not a public method + """ + return (self.paths,) + + +class Query(BaseQuery): + """ + Performance Data Helper(PDH) Query object: + + Provides a wrapper around the native PDH query object which + allows for query reuse, query storage, and general maintenance + functions (adding counter paths in various ways being the most + obvious ones). + """ + + def __init__(self, *args, **namedargs): + """ + The PDH Query object is initialised with a single, optional + list argument, that must be properly formatted PDH Counter + paths. Generally this list will only be provided by the class + when it is being unpickled (removed from storage). Normal + use is to call the class with no arguments and use the various + addcounter functions (particularly, for end user's, the use of + addcounterbybrowsing is the most common approach) You might + want to provide the list directly if you want to hard-code the + elements with which your query deals (and thereby avoid the + overhead of unpickling the class). + """ + self.volatilecounters = [] + BaseQuery.__init__(*(self,) + args, **namedargs) + + def addperfcounter(self, object, counter, machine=None): + """ + A "Performance Counter" is a stable, known, common counter, + such as Memory, or Processor. The use of addperfcounter by + end-users is deprecated, since the use of + addcounterbybrowsing is considerably more flexible and general. + It is provided here to allow the easy development of scripts + which need to access variables so common we know them by name + (such as Memory|Available Bytes), and to provide symmetry with + the add inst counter method. + usage: + query.addperfcounter('Memory', 'Available Bytes') + It is just as easy to access addcounter directly, the following + has an identicle effect. + query.addcounter('Memory', 'Available Bytes') + """ + BaseQuery.addcounter(self, object=object, counter=counter, machine=machine) + + def addinstcounter( + self, + object, + counter, + machine=None, + objtype="Process", + volatile=1, + format=win32pdh.PDH_FMT_LONG, + ): + """ + The purpose of using an instcounter is to track particular + instances of a counter object (e.g. a single processor, a single + running copy of a process). For instance, to track all python.exe + instances, you would need merely to ask: + query.addinstcounter('python','Virtual Bytes') + You can find the names of the objects and their available counters + by doing an addcounterbybrowsing() call on a query object (or by + looking in performance monitor's add dialog.) + + Beyond merely rearranging the call arguments to make more sense, + if the volatile flag is true, the instcounters also recalculate + the paths of the available instances on every call to open the + query. + """ + if volatile: + self.volatilecounters.append((object, counter, machine, objtype, format)) + else: + self.paths[len(self.paths) :] = self.getinstpaths( + object, counter, machine, objtype, format + ) + + def getinstpaths( + self, + object, + counter, + machine=None, + objtype="Process", + format=win32pdh.PDH_FMT_LONG, + ): + """ + ### Not an end-user function + Calculate the paths for an instance object. Should alter + to allow processing for lists of object-counter pairs. + """ + items, instances = win32pdh.EnumObjectItems(None, None, objtype, -1) + # find out how many instances of this element we have... + instances.sort() + try: + cur = instances.index(object) + except ValueError: + return [] # no instances of this object + temp = [object] + try: + while instances[cur + 1] == object: + temp.append(object) + cur = cur + 1 + except IndexError: # if we went over the end + pass + paths = [] + for ind in range(len(temp)): + # can this raise an error? + paths.append( + win32pdh.MakeCounterPath( + (machine, "Process", object, None, ind, counter) + ) + ) + return paths # should also return the number of elements for naming purposes + + def open(self, *args, **namedargs): + """ + Explicitly open a query: + When you are needing to make multiple calls to the same query, + it is most efficient to open the query, run all of the calls, + then close the query, instead of having the collectdata method + automatically open and close the query each time it runs. + There are currently no arguments to open. + """ + # do all the normal opening stuff, self._base is now the query object + BaseQuery.open(*(self,) + args, **namedargs) + # should rewrite getinstpaths to take a single tuple + paths = [] + for tup in self.volatilecounters: + paths[len(paths) :] = self.getinstpaths(*tup) + for path in paths: + try: + self.counters.append(win32pdh.AddCounter(self._base, path)) + self.curpaths.append( + path + ) # if we fail on the line above, this path won't be in the table or the counters + except win32api.error: + pass # again, what to do with a malformed path??? + + def collectdatafor(self, totalperiod, period=1): + """ + Non-threaded collection of performance data: + This method allows you to specify the total period for which you would + like to run the Query, and the time interval between individual + runs. The collected data is stored in query.curresults at the + _end_ of the run. The pathnames for the query are stored in + query.curpaths. + e.g.: + query.collectdatafor(30,2) + Will collect data for 30seconds at 2 second intervals + """ + tempresults = [] + try: + self.open() + for ind in range(totalperiod / period): + tempresults.append(self.collectdata()) + time.sleep(period) + self.curresults = tempresults + finally: + self.close() + + def collectdatawhile(self, period=1): + """ + Threaded collection of performance data: + This method sets up a simple semaphor system for signalling + when you would like to start and stop a threaded data collection + method. The collection runs every period seconds until the + semaphor attribute is set to a non-true value (which normally + should be done by calling query.collectdatawhile_stop() .) + e.g.: + query.collectdatawhile(2) + # starts the query running, returns control to the caller immediately + # is collecting data every two seconds. + # do whatever you want to do while the thread runs, then call: + query.collectdatawhile_stop() + # when you want to deal with the data. It is generally a good idea + # to sleep for period seconds yourself, since the query will not copy + # the required data until the next iteration: + time.sleep(2) + # now you can access the data from the attributes of the query + query.curresults + query.curpaths + """ + self.collectdatawhile_active = 1 + _thread.start_new_thread(self.collectdatawhile_slave, (period,)) + + def collectdatawhile_stop(self): + """ + Signals the collectdatawhile slave thread to stop collecting data + on the next logging iteration. + """ + self.collectdatawhile_active = 0 + + def collectdatawhile_slave(self, period): + """ + ### Not a public function + Does the threaded work of collecting the data and storing it + in an attribute of the class. + """ + tempresults = [] + try: + self.open() # also sets active, so can't be changed. + while self.collectdatawhile_active: + tempresults.append(self.collectdata()) + time.sleep(period) + self.curresults = tempresults + finally: + self.close() + + # pickle functions + def __getinitargs__(self): + return (self.paths,) + + def __getstate__(self): + return self.volatilecounters + + def __setstate__(self, volatilecounters): + self.volatilecounters = volatilecounters + + +class QueryError: + def __init__(self, query): + self.query = query + + def __repr__(self): + return "" % repr(self.query) + + __str__ = __repr__ diff --git a/MLPY/Lib/site-packages/win32/lib/win32pdhutil.py b/MLPY/Lib/site-packages/win32/lib/win32pdhutil.py new file mode 100644 index 0000000000000000000000000000000000000000..7795dd904e4b86ba1267f662ed86f6e556fac066 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32pdhutil.py @@ -0,0 +1,210 @@ +"""Utilities for the win32 Performance Data Helper module + +Example: + To get a single bit of data: + >>> import win32pdhutil + >>> win32pdhutil.GetPerformanceAttributes("Memory", "Available Bytes") + 6053888 + >>> win32pdhutil.FindPerformanceAttributesByName("python", counter="Virtual Bytes") + [22278144] + + First example returns data which is not associated with any specific instance. + + The second example reads data for a specific instance - hence the list return - + it would return one result for each instance of Python running. + + In general, it can be tricky finding exactly the "name" of the data you wish to query. + Although you can use (None,None,(eg)"Memory", -1) to do this, + the easiest way is often to simply use PerfMon to find out the names. +""" + +import time + +import win32pdh + +error = win32pdh.error + +# Handle some localization issues. +# see http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q287/1/59.asp&NoWebContent=1 +# Build a map of english_counter_name: counter_id +counter_english_map = {} + + +def find_pdh_counter_localized_name(english_name, machine_name=None): + if not counter_english_map: + import win32api + import win32con + + counter_reg_value = win32api.RegQueryValueEx( + win32con.HKEY_PERFORMANCE_DATA, "Counter 009" + ) + counter_list = counter_reg_value[0] + for i in range(0, len(counter_list) - 1, 2): + try: + counter_id = int(counter_list[i]) + except ValueError: + continue + counter_english_map[counter_list[i + 1].lower()] = counter_id + return win32pdh.LookupPerfNameByIndex( + machine_name, counter_english_map[english_name.lower()] + ) + + +def GetPerformanceAttributes( + object, counter, instance=None, inum=-1, format=win32pdh.PDH_FMT_LONG, machine=None +): + # NOTE: Many counters require 2 samples to give accurate results, + # including "% Processor Time" (as by definition, at any instant, a + # thread's CPU usage is either 0 or 100). To read counters like this, + # you should copy this function, but keep the counter open, and call + # CollectQueryData() each time you need to know. + # See http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262938 + # and http://msdn.microsoft.com/library/en-us/dnperfmo/html/perfmonpt2.asp + # My older explanation for this was that the "AddCounter" process forced + # the CPU to 100%, but the above makes more sense :) + path = win32pdh.MakeCounterPath((machine, object, instance, None, inum, counter)) + hq = win32pdh.OpenQuery() + try: + hc = win32pdh.AddCounter(hq, path) + try: + win32pdh.CollectQueryData(hq) + type, val = win32pdh.GetFormattedCounterValue(hc, format) + return val + finally: + win32pdh.RemoveCounter(hc) + finally: + win32pdh.CloseQuery(hq) + + +def FindPerformanceAttributesByName( + instanceName, + object=None, + counter=None, + format=win32pdh.PDH_FMT_LONG, + machine=None, + bRefresh=0, +): + """Find performance attributes by (case insensitive) instance name. + + Given a process name, return a list with the requested attributes. + Most useful for returning a tuple of PIDs given a process name. + """ + if object is None: + object = find_pdh_counter_localized_name("Process", machine) + if counter is None: + counter = find_pdh_counter_localized_name("ID Process", machine) + if bRefresh: # PDH docs say this is how you do a refresh. + win32pdh.EnumObjects(None, machine, 0, 1) + instanceName = instanceName.lower() + items, instances = win32pdh.EnumObjectItems(None, None, object, -1) + # Track multiple instances. + instance_dict = {} + for instance in instances: + try: + instance_dict[instance] = instance_dict[instance] + 1 + except KeyError: + instance_dict[instance] = 0 + + ret = [] + for instance, max_instances in instance_dict.items(): + for inum in range(max_instances + 1): + if instance.lower() == instanceName: + ret.append( + GetPerformanceAttributes( + object, counter, instance, inum, format, machine + ) + ) + return ret + + +def ShowAllProcesses(): + object = find_pdh_counter_localized_name("Process") + items, instances = win32pdh.EnumObjectItems( + None, None, object, win32pdh.PERF_DETAIL_WIZARD + ) + # Need to track multiple instances of the same name. + instance_dict = {} + for instance in instances: + try: + instance_dict[instance] = instance_dict[instance] + 1 + except KeyError: + instance_dict[instance] = 0 + + # Bit of a hack to get useful info. + items = [find_pdh_counter_localized_name("ID Process")] + items[:5] + print("Process Name", ",".join(items)) + for instance, max_instances in instance_dict.items(): + for inum in range(max_instances + 1): + hq = win32pdh.OpenQuery() + hcs = [] + for item in items: + path = win32pdh.MakeCounterPath( + (None, object, instance, None, inum, item) + ) + hcs.append(win32pdh.AddCounter(hq, path)) + win32pdh.CollectQueryData(hq) + # as per http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262938, some "%" based + # counters need two collections + time.sleep(0.01) + win32pdh.CollectQueryData(hq) + print("%-15s\t" % (instance[:15]), end=" ") + for hc in hcs: + type, val = win32pdh.GetFormattedCounterValue(hc, win32pdh.PDH_FMT_LONG) + print("%5d" % (val), end=" ") + win32pdh.RemoveCounter(hc) + print() + win32pdh.CloseQuery(hq) + + +# NOTE: This BrowseCallback doesn't seem to work on Vista for markh. +# XXX - look at why!? +# Some counters on Vista require elevation, and callback would previously +# clear exceptions without printing them. +def BrowseCallBackDemo(counters): + ## BrowseCounters can now return multiple counter paths + for counter in counters: + ( + machine, + object, + instance, + parentInstance, + index, + counterName, + ) = win32pdh.ParseCounterPath(counter) + + result = GetPerformanceAttributes( + object, counterName, instance, index, win32pdh.PDH_FMT_DOUBLE, machine + ) + print("Value of '%s' is" % counter, result) + print( + "Added '%s' on object '%s' (machine %s), instance %s(%d)-parent of %s" + % (counterName, object, machine, instance, index, parentInstance) + ) + return 0 + + +def browse( + callback=BrowseCallBackDemo, + title="Python Browser", + level=win32pdh.PERF_DETAIL_WIZARD, +): + win32pdh.BrowseCounters(None, 0, callback, level, title, ReturnMultiple=True) + + +if __name__ == "__main__": + ShowAllProcesses() + # Show how to get a couple of attributes by name. + counter = find_pdh_counter_localized_name("Virtual Bytes") + print( + "Virtual Bytes = ", FindPerformanceAttributesByName("python", counter=counter) + ) + print( + "Available Bytes = ", + GetPerformanceAttributes( + find_pdh_counter_localized_name("Memory"), + find_pdh_counter_localized_name("Available Bytes"), + ), + ) + # And a browser. + print("Browsing for counters...") + browse() diff --git a/MLPY/Lib/site-packages/win32/lib/win32rcparser.py b/MLPY/Lib/site-packages/win32/lib/win32rcparser.py new file mode 100644 index 0000000000000000000000000000000000000000..effe1429fa1716a5afe6a9cfe849f0a71410b281 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32rcparser.py @@ -0,0 +1,677 @@ +# Windows dialog .RC file parser, by Adam Walker. + +# This module was adapted from the spambayes project, and is Copyright +# 2003/2004 The Python Software Foundation and is covered by the Python +# Software Foundation license. +""" +This is a parser for Windows .rc files, which are text files which define +dialogs and other Windows UI resources. +""" +__author__ = "Adam Walker" +__version__ = "0.11" + +import os +import pprint +import shlex +import stat +import sys + +import commctrl +import win32con + +_controlMap = { + "DEFPUSHBUTTON": 0x80, + "PUSHBUTTON": 0x80, + "Button": 0x80, + "GROUPBOX": 0x80, + "Static": 0x82, + "CTEXT": 0x82, + "RTEXT": 0x82, + "LTEXT": 0x82, + "LISTBOX": 0x83, + "SCROLLBAR": 0x84, + "COMBOBOX": 0x85, + "EDITTEXT": 0x81, + "ICON": 0x82, + "RICHEDIT": "RichEdit20A", +} + +# These are "default styles" for certain controls - ie, Visual Studio assumes +# the styles will be applied, and emits a "NOT {STYLE_NAME}" if it is to be +# disabled. These defaults have been determined by experimentation, so may +# not be completely accurate (most notably, some styles and/or control-types +# may be missing. +_addDefaults = { + "EDITTEXT": win32con.WS_BORDER | win32con.WS_TABSTOP, + "GROUPBOX": win32con.BS_GROUPBOX, + "LTEXT": win32con.SS_LEFT, + "DEFPUSHBUTTON": win32con.BS_DEFPUSHBUTTON | win32con.WS_TABSTOP, + "PUSHBUTTON": win32con.WS_TABSTOP, + "CTEXT": win32con.SS_CENTER, + "RTEXT": win32con.SS_RIGHT, + "ICON": win32con.SS_ICON, + "LISTBOX": win32con.LBS_NOTIFY, +} + +defaultControlStyle = win32con.WS_CHILD | win32con.WS_VISIBLE +defaultControlStyleEx = 0 + + +class DialogDef: + name = "" + id = 0 + style = 0 + styleEx = None + caption = "" + font = "MS Sans Serif" + fontSize = 8 + x = 0 + y = 0 + w = 0 + h = 0 + template = None + + def __init__(self, n, i): + self.name = n + self.id = i + self.styles = [] + self.stylesEx = [] + self.controls = [] + # print "dialog def for ",self.name, self.id + + def createDialogTemplate(self): + t = None + self.template = [ + [ + self.caption, + (self.x, self.y, self.w, self.h), + self.style, + self.styleEx, + (self.fontSize, self.font), + ] + ] + # Add the controls + for control in self.controls: + self.template.append(control.createDialogTemplate()) + return self.template + + +class ControlDef: + id = "" + controlType = "" + subType = "" + idNum = 0 + style = defaultControlStyle + styleEx = defaultControlStyleEx + label = "" + x = 0 + y = 0 + w = 0 + h = 0 + + def __init__(self): + self.styles = [] + self.stylesEx = [] + + def toString(self): + s = ( + "" + ) + return s + + def createDialogTemplate(self): + ct = self.controlType + if "CONTROL" == ct: + ct = self.subType + if ct in _controlMap: + ct = _controlMap[ct] + t = [ + ct, + self.label, + self.idNum, + (self.x, self.y, self.w, self.h), + self.style, + self.styleEx, + ] + # print t + return t + + +class StringDef: + def __init__(self, id, idNum, value): + self.id = id + self.idNum = idNum + self.value = value + + def __repr__(self): + return "StringDef(%r, %r, %r)" % (self.id, self.idNum, self.value) + + +class RCParser: + next_id = 1001 + dialogs = {} + _dialogs = {} + debugEnabled = False + token = "" + + def __init__(self): + self.ungot = False + self.ids = {"IDC_STATIC": -1} + self.names = {-1: "IDC_STATIC"} + self.bitmaps = {} + self.stringTable = {} + self.icons = {} + + def debug(self, *args): + if self.debugEnabled: + print(args) + + def getToken(self): + if self.ungot: + self.ungot = False + self.debug("getToken returns (ungot):", self.token) + return self.token + self.token = self.lex.get_token() + self.debug("getToken returns:", self.token) + if self.token == "": + self.token = None + return self.token + + def ungetToken(self): + self.ungot = True + + def getCheckToken(self, expected): + tok = self.getToken() + assert tok == expected, "Expected token '%s', but got token '%s'!" % ( + expected, + tok, + ) + return tok + + def getCommaToken(self): + return self.getCheckToken(",") + + # Return the *current* token as a number, only consuming a token + # if it is the negative-sign. + def currentNumberToken(self): + mult = 1 + if self.token == "-": + mult = -1 + self.getToken() + return int(self.token) * mult + + # Return the *current* token as a string literal (ie, self.token will be a + # quote. consumes all tokens until the end of the string + def currentQuotedString(self): + # Handle quoted strings - pity shlex doesn't handle it. + assert self.token.startswith('"'), self.token + bits = [self.token] + while 1: + tok = self.getToken() + if not tok.startswith('"'): + self.ungetToken() + break + bits.append(tok) + sval = "".join(bits)[1:-1] # Remove end quotes. + # Fixup quotes in the body, and all (some?) quoted characters back + # to their raw value. + for i, o in ('""', '"'), ("\\r", "\r"), ("\\n", "\n"), ("\\t", "\t"): + sval = sval.replace(i, o) + return sval + + def load(self, rcstream): + """ + RCParser.loadDialogs(rcFileName) -> None + Load the dialog information into the parser. Dialog Definations can then be accessed + using the "dialogs" dictionary member (name->DialogDef). The "ids" member contains the dictionary of id->name. + The "names" member contains the dictionary of name->id + """ + self.open(rcstream) + self.getToken() + while self.token != None: + self.parse() + self.getToken() + + def open(self, rcstream): + self.lex = shlex.shlex(rcstream) + self.lex.commenters = "//#" + + def parseH(self, file): + lex = shlex.shlex(file) + lex.commenters = "//" + token = " " + while token is not None: + token = lex.get_token() + if token == "" or token is None: + token = None + else: + if token == "define": + n = lex.get_token() + i = int(lex.get_token()) + self.ids[n] = i + if i in self.names: + # Dupe ID really isn't a problem - most consumers + # want to go from name->id, and this is OK. + # It means you can't go from id->name though. + pass + # ignore AppStudio special ones + # if not n.startswith("_APS_"): + # print "Duplicate id",i,"for",n,"is", self.names[i] + else: + self.names[i] = n + if self.next_id <= i: + self.next_id = i + 1 + + def parse(self): + noid_parsers = { + "STRINGTABLE": self.parse_stringtable, + } + + id_parsers = { + "DIALOG": self.parse_dialog, + "DIALOGEX": self.parse_dialog, + # "TEXTINCLUDE": self.parse_textinclude, + "BITMAP": self.parse_bitmap, + "ICON": self.parse_icon, + } + deep = 0 + base_token = self.token + rp = noid_parsers.get(base_token) + if rp is not None: + rp() + else: + # Not something we parse that isn't prefixed by an ID + # See if it is an ID prefixed item - if it is, our token + # is the resource ID. + resource_id = self.token + self.getToken() + if self.token is None: + return + + if "BEGIN" == self.token: + # A 'BEGIN' for a structure we don't understand - skip to the + # matching 'END' + deep = 1 + while deep != 0 and self.token is not None: + self.getToken() + self.debug("Zooming over", self.token) + if "BEGIN" == self.token: + deep += 1 + elif "END" == self.token: + deep -= 1 + else: + rp = id_parsers.get(self.token) + if rp is not None: + self.debug("Dispatching '%s'" % (self.token,)) + rp(resource_id) + else: + # We don't know what the resource type is, but we + # have already consumed the next, which can cause problems, + # so push it back. + self.debug("Skipping top-level '%s'" % base_token) + self.ungetToken() + + def addId(self, id_name): + if id_name in self.ids: + id = self.ids[id_name] + else: + # IDOK, IDCANCEL etc are special - if a real resource has this value + for n in ["IDOK", "IDCANCEL", "IDYES", "IDNO", "IDABORT"]: + if id_name == n: + v = getattr(win32con, n) + self.ids[n] = v + self.names[v] = n + return v + id = self.next_id + self.next_id += 1 + self.ids[id_name] = id + self.names[id] = id_name + return id + + def lang(self): + while ( + self.token[0:4] == "LANG" + or self.token[0:7] == "SUBLANG" + or self.token == "," + ): + self.getToken() + + def parse_textinclude(self, res_id): + while self.getToken() != "BEGIN": + pass + while 1: + if self.token == "END": + break + s = self.getToken() + + def parse_stringtable(self): + while self.getToken() != "BEGIN": + pass + while 1: + self.getToken() + if self.token == "END": + break + sid = self.token + self.getToken() + sd = StringDef(sid, self.addId(sid), self.currentQuotedString()) + self.stringTable[sid] = sd + + def parse_bitmap(self, name): + return self.parse_bitmap_or_icon(name, self.bitmaps) + + def parse_icon(self, name): + return self.parse_bitmap_or_icon(name, self.icons) + + def parse_bitmap_or_icon(self, name, dic): + self.getToken() + while not self.token.startswith('"'): + self.getToken() + bmf = self.token[1:-1] # quotes + dic[name] = bmf + + def parse_dialog(self, name): + dlg = DialogDef(name, self.addId(name)) + assert len(dlg.controls) == 0 + self._dialogs[name] = dlg + extras = [] + self.getToken() + while not self.token.isdigit(): + self.debug("extra", self.token) + extras.append(self.token) + self.getToken() + dlg.x = int(self.token) + self.getCommaToken() + self.getToken() # number + dlg.y = int(self.token) + self.getCommaToken() + self.getToken() # number + dlg.w = int(self.token) + self.getCommaToken() + self.getToken() # number + dlg.h = int(self.token) + self.getToken() + while not (self.token == None or self.token == "" or self.token == "END"): + if self.token == "STYLE": + self.dialogStyle(dlg) + elif self.token == "EXSTYLE": + self.dialogExStyle(dlg) + elif self.token == "CAPTION": + self.dialogCaption(dlg) + elif self.token == "FONT": + self.dialogFont(dlg) + elif self.token == "BEGIN": + self.controls(dlg) + else: + break + self.dialogs[name] = dlg.createDialogTemplate() + + def dialogStyle(self, dlg): + dlg.style, dlg.styles = self.styles([], win32con.DS_SETFONT) + + def dialogExStyle(self, dlg): + self.getToken() + dlg.styleEx, dlg.stylesEx = self.styles([], 0) + + def styles(self, defaults, defaultStyle): + list = defaults + style = defaultStyle + + if "STYLE" == self.token: + self.getToken() + i = 0 + Not = False + while ( + (i % 2 == 1 and ("|" == self.token or "NOT" == self.token)) or (i % 2 == 0) + ) and not self.token == None: + Not = False + if "NOT" == self.token: + Not = True + self.getToken() + i += 1 + if self.token != "|": + if self.token in win32con.__dict__: + value = getattr(win32con, self.token) + else: + if self.token in commctrl.__dict__: + value = getattr(commctrl, self.token) + else: + value = 0 + if Not: + list.append("NOT " + self.token) + self.debug("styles add Not", self.token, value) + style &= ~value + else: + list.append(self.token) + self.debug("styles add", self.token, value) + style |= value + self.getToken() + self.debug("style is ", style) + + return style, list + + def dialogCaption(self, dlg): + if "CAPTION" == self.token: + self.getToken() + self.token = self.token[1:-1] + self.debug("Caption is:", self.token) + dlg.caption = self.token + self.getToken() + + def dialogFont(self, dlg): + if "FONT" == self.token: + self.getToken() + dlg.fontSize = int(self.token) + self.getCommaToken() + self.getToken() # Font name + dlg.font = self.token[1:-1] # it's quoted + self.getToken() + while "BEGIN" != self.token: + self.getToken() + + def controls(self, dlg): + if self.token == "BEGIN": + self.getToken() + # All controls look vaguely like: + # TYPE [text, ] Control_id, l, t, r, b [, style] + # .rc parser documents all control types as: + # CHECKBOX, COMBOBOX, CONTROL, CTEXT, DEFPUSHBUTTON, EDITTEXT, GROUPBOX, + # ICON, LISTBOX, LTEXT, PUSHBUTTON, RADIOBUTTON, RTEXT, SCROLLBAR + without_text = ["EDITTEXT", "COMBOBOX", "LISTBOX", "SCROLLBAR"] + while self.token != "END": + control = ControlDef() + control.controlType = self.token + self.getToken() + if control.controlType not in without_text: + if self.token[0:1] == '"': + control.label = self.currentQuotedString() + # Some funny controls, like icons and picture controls use + # the "window text" as extra resource ID (ie, the ID of the + # icon itself). This may be either a literal, or an ID string. + elif self.token == "-" or self.token.isdigit(): + control.label = str(self.currentNumberToken()) + else: + # An ID - use the numeric equiv. + control.label = str(self.addId(self.token)) + self.getCommaToken() + self.getToken() + # Control IDs may be "names" or literal ints + if self.token == "-" or self.token.isdigit(): + control.id = self.currentNumberToken() + control.idNum = control.id + else: + # name of an ID + control.id = self.token + control.idNum = self.addId(control.id) + self.getCommaToken() + + if control.controlType == "CONTROL": + self.getToken() + control.subType = self.token[1:-1] + thisDefaultStyle = defaultControlStyle | _addDefaults.get( + control.subType, 0 + ) + # Styles + self.getCommaToken() + self.getToken() + control.style, control.styles = self.styles([], thisDefaultStyle) + else: + thisDefaultStyle = defaultControlStyle | _addDefaults.get( + control.controlType, 0 + ) + # incase no style is specified. + control.style = thisDefaultStyle + # Rect + control.x = int(self.getToken()) + self.getCommaToken() + control.y = int(self.getToken()) + self.getCommaToken() + control.w = int(self.getToken()) + self.getCommaToken() + self.getToken() + control.h = int(self.token) + self.getToken() + if self.token == ",": + self.getToken() + control.style, control.styles = self.styles([], thisDefaultStyle) + if self.token == ",": + self.getToken() + control.styleEx, control.stylesEx = self.styles( + [], defaultControlStyleEx + ) + # print control.toString() + dlg.controls.append(control) + + +def ParseStreams(rc_file, h_file): + rcp = RCParser() + if h_file: + rcp.parseH(h_file) + try: + rcp.load(rc_file) + except: + lex = getattr(rcp, "lex", None) + if lex: + print("ERROR parsing dialogs at line", lex.lineno) + print("Next 10 tokens are:") + for i in range(10): + print(lex.get_token(), end=" ") + print() + raise + return rcp + + +def Parse(rc_name, h_name=None): + if h_name: + h_file = open(h_name, "r") + else: + # See if same basename as the .rc + h_name = rc_name[:-2] + "h" + try: + h_file = open(h_name, "r") + except IOError: + # See if MSVC default of 'resource.h' in the same dir. + h_name = os.path.join(os.path.dirname(rc_name), "resource.h") + try: + h_file = open(h_name, "r") + except IOError: + # .h files are optional anyway + h_file = None + rc_file = open(rc_name, "r") + try: + return ParseStreams(rc_file, h_file) + finally: + if h_file is not None: + h_file.close() + rc_file.close() + return rcp + + +def GenerateFrozenResource(rc_name, output_name, h_name=None): + """Converts an .rc windows resource source file into a python source file + with the same basic public interface as the rest of this module. + Particularly useful for py2exe or other 'freeze' type solutions, + where a frozen .py file can be used inplace of a real .rc file. + """ + rcp = Parse(rc_name, h_name) + in_stat = os.stat(rc_name) + + out = open(output_name, "wt") + out.write("#%s\n" % output_name) + out.write("#This is a generated file. Please edit %s instead.\n" % rc_name) + out.write("__version__=%r\n" % __version__) + out.write( + "_rc_size_=%d\n_rc_mtime_=%d\n" + % (in_stat[stat.ST_SIZE], in_stat[stat.ST_MTIME]) + ) + + out.write("class StringDef:\n") + out.write("\tdef __init__(self, id, idNum, value):\n") + out.write("\t\tself.id = id\n") + out.write("\t\tself.idNum = idNum\n") + out.write("\t\tself.value = value\n") + out.write("\tdef __repr__(self):\n") + out.write( + '\t\treturn "StringDef(%r, %r, %r)" % (self.id, self.idNum, self.value)\n' + ) + + out.write("class FakeParser:\n") + + for name in "dialogs", "ids", "names", "bitmaps", "icons", "stringTable": + out.write("\t%s = \\\n" % (name,)) + pprint.pprint(getattr(rcp, name), out) + out.write("\n") + + out.write("def Parse(s):\n") + out.write("\treturn FakeParser()\n") + out.close() + + +if __name__ == "__main__": + if len(sys.argv) <= 1: + print(__doc__) + print() + print("See test_win32rcparser.py, and the win32rcparser directory (both") + print("in the test suite) for an example of this module's usage.") + else: + import pprint + + filename = sys.argv[1] + if "-v" in sys.argv: + RCParser.debugEnabled = 1 + print("Dumping all resources in '%s'" % filename) + resources = Parse(filename) + for id, ddef in resources.dialogs.items(): + print("Dialog %s (%d controls)" % (id, len(ddef))) + pprint.pprint(ddef) + print() + for id, sdef in resources.stringTable.items(): + print("String %s=%r" % (id, sdef.value)) + print() + for id, sdef in resources.bitmaps.items(): + print("Bitmap %s=%r" % (id, sdef)) + print() + for id, sdef in resources.icons.items(): + print("Icon %s=%r" % (id, sdef)) + print() diff --git a/MLPY/Lib/site-packages/win32/lib/win32serviceutil.py b/MLPY/Lib/site-packages/win32/lib/win32serviceutil.py new file mode 100644 index 0000000000000000000000000000000000000000..fb1875302cd0fbf2f6e1c9cf4c195def00a4615d --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32serviceutil.py @@ -0,0 +1,1071 @@ +# General purpose service utilities, both for standard Python scripts, +# and for for Python programs which run as services... +# +# Note that most utility functions here will raise win32api.error's +# (which is win32service.error, pywintypes.error, etc) +# when things go wrong - eg, not enough permissions to hit the +# registry etc. + +import importlib +import os +import sys +import warnings + +import pywintypes +import win32api +import win32con +import win32service +import winerror + +_d = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else "" +error = RuntimeError + + +# Returns the full path to an executable for hosting a Python service - typically +# 'pythonservice.exe' +# * If you pass a param and it exists as a file, you'll get the abs path back +# * Otherwise we'll use the param instead of 'pythonservice.exe', and we will +# look for it. +def LocatePythonServiceExe(exe=None): + if not exe and hasattr(sys, "frozen"): + # If py2exe etc calls this with no exe, default is current exe, + # and all setup is their problem :) + return sys.executable + + if exe and os.path.isfile(exe): + return win32api.GetFullPathName(exe) + + # We are confused if we aren't now looking for our default. But if that + # exists as specified we assume it's good. + exe = f"pythonservice{_d}.exe" + if os.path.isfile(exe): + return win32api.GetFullPathName(exe) + + # Now we are searching for the .exe + # We are going to want it here. + correct = os.path.join(sys.exec_prefix, exe) + # Even if that file already exists, we copy the one installed by pywin32 + # in-case it was upgraded. + # pywin32 installed it next to win32service.pyd (but we can't run it from there) + maybe = os.path.join(os.path.dirname(win32service.__file__), exe) + if os.path.exists(maybe): + print(f"copying host exe '{maybe}' -> '{correct}'") + win32api.CopyFile(maybe, correct) + + if not os.path.exists(correct): + raise error(f"Can't find '{correct}'") + + # If pywintypes.dll isn't next to us, or at least next to pythonXX.dll, + # there's a good chance the service will not run. That's usually copied by + # `pywin32_postinstall`, but putting it next to the python DLL seems + # reasonable. + # (Unlike the .exe above, we don't unconditionally copy this, and possibly + # copy it to a different place. Doesn't seem a good reason for that!?) + python_dll = win32api.GetModuleFileName(sys.dllhandle) + pyw = f"pywintypes{sys.version_info[0]}{sys.version_info[1]}{_d}.dll" + correct_pyw = os.path.join(os.path.dirname(python_dll), pyw) + + if not os.path.exists(correct_pyw): + print(f"copying helper dll '{pywintypes.__file__}' -> '{correct_pyw}'") + win32api.CopyFile(pywintypes.__file__, correct_pyw) + + return correct + + +def _GetServiceShortName(longName): + # looks up a services name + # from the display name + # Thanks to Andy McKay for this code. + access = ( + win32con.KEY_READ | win32con.KEY_ENUMERATE_SUB_KEYS | win32con.KEY_QUERY_VALUE + ) + hkey = win32api.RegOpenKey( + win32con.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services", 0, access + ) + num = win32api.RegQueryInfoKey(hkey)[0] + longName = longName.lower() + # loop through number of subkeys + for x in range(0, num): + # find service name, open subkey + svc = win32api.RegEnumKey(hkey, x) + skey = win32api.RegOpenKey(hkey, svc, 0, access) + try: + # find display name + thisName = str(win32api.RegQueryValueEx(skey, "DisplayName")[0]) + if thisName.lower() == longName: + return svc + except win32api.error: + # in case there is no key called DisplayName + pass + return None + + +# Open a service given either it's long or short name. +def SmartOpenService(hscm, name, access): + try: + return win32service.OpenService(hscm, name, access) + except win32api.error as details: + if details.winerror not in [ + winerror.ERROR_SERVICE_DOES_NOT_EXIST, + winerror.ERROR_INVALID_NAME, + ]: + raise + name = win32service.GetServiceKeyName(hscm, name) + return win32service.OpenService(hscm, name, access) + + +def LocateSpecificServiceExe(serviceName): + # Return the .exe name of any service. + hkey = win32api.RegOpenKey( + win32con.HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\%s" % (serviceName), + 0, + win32con.KEY_ALL_ACCESS, + ) + try: + return win32api.RegQueryValueEx(hkey, "ImagePath")[0] + finally: + hkey.Close() + + +def InstallPerfmonForService(serviceName, iniName, dllName=None): + # If no DLL name, look it up in the INI file name + if not dllName: # May be empty string! + dllName = win32api.GetProfileVal("Python", "dll", "", iniName) + # Still not found - look for the standard one in the same dir as win32service.pyd + if not dllName: + try: + tryName = os.path.join( + os.path.split(win32service.__file__)[0], "perfmondata.dll" + ) + if os.path.isfile(tryName): + dllName = tryName + except AttributeError: + # Frozen app? - anyway, can't find it! + pass + if not dllName: + raise ValueError("The name of the performance DLL must be available") + dllName = win32api.GetFullPathName(dllName) + # Now setup all the required "Performance" entries. + hkey = win32api.RegOpenKey( + win32con.HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\%s" % (serviceName), + 0, + win32con.KEY_ALL_ACCESS, + ) + try: + subKey = win32api.RegCreateKey(hkey, "Performance") + try: + win32api.RegSetValueEx(subKey, "Library", 0, win32con.REG_SZ, dllName) + win32api.RegSetValueEx( + subKey, "Open", 0, win32con.REG_SZ, "OpenPerformanceData" + ) + win32api.RegSetValueEx( + subKey, "Close", 0, win32con.REG_SZ, "ClosePerformanceData" + ) + win32api.RegSetValueEx( + subKey, "Collect", 0, win32con.REG_SZ, "CollectPerformanceData" + ) + finally: + win32api.RegCloseKey(subKey) + finally: + win32api.RegCloseKey(hkey) + # Now do the "Lodctr" thang... + + try: + import perfmon + + path, fname = os.path.split(iniName) + oldPath = os.getcwd() + if path: + os.chdir(path) + try: + perfmon.LoadPerfCounterTextStrings("python.exe " + fname) + finally: + os.chdir(oldPath) + except win32api.error as details: + print("The service was installed OK, but the performance monitor") + print("data could not be loaded.", details) + + +def _GetCommandLine(exeName, exeArgs): + if exeArgs is not None: + return exeName + " " + exeArgs + else: + return exeName + + +def InstallService( + pythonClassString, + serviceName, + displayName, + startType=None, + errorControl=None, + bRunInteractive=0, + serviceDeps=None, + userName=None, + password=None, + exeName=None, + perfMonIni=None, + perfMonDll=None, + exeArgs=None, + description=None, + delayedstart=None, +): + # Handle the default arguments. + if startType is None: + startType = win32service.SERVICE_DEMAND_START + serviceType = win32service.SERVICE_WIN32_OWN_PROCESS + if bRunInteractive: + serviceType = serviceType | win32service.SERVICE_INTERACTIVE_PROCESS + if errorControl is None: + errorControl = win32service.SERVICE_ERROR_NORMAL + + exeName = '"%s"' % LocatePythonServiceExe(exeName) + commandLine = _GetCommandLine(exeName, exeArgs) + hscm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ALL_ACCESS) + try: + hs = win32service.CreateService( + hscm, + serviceName, + displayName, + win32service.SERVICE_ALL_ACCESS, # desired access + serviceType, # service type + startType, + errorControl, # error control type + commandLine, + None, + 0, + serviceDeps, + userName, + password, + ) + if description is not None: + try: + win32service.ChangeServiceConfig2( + hs, win32service.SERVICE_CONFIG_DESCRIPTION, description + ) + except NotImplementedError: + pass ## ChangeServiceConfig2 and description do not exist on NT + if delayedstart is not None: + try: + win32service.ChangeServiceConfig2( + hs, + win32service.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + delayedstart, + ) + except (win32service.error, NotImplementedError): + ## delayed start only exists on Vista and later - warn only when trying to set delayed to True + warnings.warn("Delayed Start not available on this system") + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + InstallPythonClassString(pythonClassString, serviceName) + # If I have performance monitor info to install, do that. + if perfMonIni is not None: + InstallPerfmonForService(serviceName, perfMonIni, perfMonDll) + + +def ChangeServiceConfig( + pythonClassString, + serviceName, + startType=None, + errorControl=None, + bRunInteractive=0, + serviceDeps=None, + userName=None, + password=None, + exeName=None, + displayName=None, + perfMonIni=None, + perfMonDll=None, + exeArgs=None, + description=None, + delayedstart=None, +): + # Before doing anything, remove any perfmon counters. + try: + import perfmon + + perfmon.UnloadPerfCounterTextStrings("python.exe " + serviceName) + except (ImportError, win32api.error): + pass + + # The EXE location may have changed + exeName = '"%s"' % LocatePythonServiceExe(exeName) + + # Handle the default arguments. + if startType is None: + startType = win32service.SERVICE_NO_CHANGE + if errorControl is None: + errorControl = win32service.SERVICE_NO_CHANGE + + hscm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ALL_ACCESS) + serviceType = win32service.SERVICE_WIN32_OWN_PROCESS + if bRunInteractive: + serviceType = serviceType | win32service.SERVICE_INTERACTIVE_PROCESS + commandLine = _GetCommandLine(exeName, exeArgs) + try: + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + try: + win32service.ChangeServiceConfig( + hs, + serviceType, # service type + startType, + errorControl, # error control type + commandLine, + None, + 0, + serviceDeps, + userName, + password, + displayName, + ) + if description is not None: + try: + win32service.ChangeServiceConfig2( + hs, win32service.SERVICE_CONFIG_DESCRIPTION, description + ) + except NotImplementedError: + pass ## ChangeServiceConfig2 and description do not exist on NT + if delayedstart is not None: + try: + win32service.ChangeServiceConfig2( + hs, + win32service.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + delayedstart, + ) + except (win32service.error, NotImplementedError): + ## Delayed start only exists on Vista and later. On Nt, will raise NotImplementedError since ChangeServiceConfig2 + ## doensn't exist. On Win2k and XP, will fail with ERROR_INVALID_LEVEL + ## Warn only if trying to set delayed to True + if delayedstart: + warnings.warn("Delayed Start not available on this system") + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + InstallPythonClassString(pythonClassString, serviceName) + # If I have performance monitor info to install, do that. + if perfMonIni is not None: + InstallPerfmonForService(serviceName, perfMonIni, perfMonDll) + + +def InstallPythonClassString(pythonClassString, serviceName): + # Now setup our Python specific entries. + if pythonClassString: + key = win32api.RegCreateKey( + win32con.HKEY_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\%s\\PythonClass" % serviceName, + ) + try: + win32api.RegSetValue(key, None, win32con.REG_SZ, pythonClassString) + finally: + win32api.RegCloseKey(key) + + +# Utility functions for Services, to allow persistant properties. +def SetServiceCustomOption(serviceName, option, value): + try: + serviceName = serviceName._svc_name_ + except AttributeError: + pass + key = win32api.RegCreateKey( + win32con.HKEY_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\%s\\Parameters" % serviceName, + ) + try: + if type(value) == type(0): + win32api.RegSetValueEx(key, option, 0, win32con.REG_DWORD, value) + else: + win32api.RegSetValueEx(key, option, 0, win32con.REG_SZ, value) + finally: + win32api.RegCloseKey(key) + + +def GetServiceCustomOption(serviceName, option, defaultValue=None): + # First param may also be a service class/instance. + # This allows services to pass "self" + try: + serviceName = serviceName._svc_name_ + except AttributeError: + pass + key = win32api.RegCreateKey( + win32con.HKEY_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\%s\\Parameters" % serviceName, + ) + try: + try: + return win32api.RegQueryValueEx(key, option)[0] + except win32api.error: # No value. + return defaultValue + finally: + win32api.RegCloseKey(key) + + +def RemoveService(serviceName): + try: + import perfmon + + perfmon.UnloadPerfCounterTextStrings("python.exe " + serviceName) + except (ImportError, win32api.error): + pass + + hscm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ALL_ACCESS) + try: + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + win32service.DeleteService(hs) + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + + import win32evtlogutil + + try: + win32evtlogutil.RemoveSourceFromRegistry(serviceName) + except win32api.error: + pass + + +def ControlService(serviceName, code, machine=None): + hscm = win32service.OpenSCManager(machine, None, win32service.SC_MANAGER_ALL_ACCESS) + try: + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + try: + status = win32service.ControlService(hs, code) + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + return status + + +def __FindSvcDeps(findName): + if type(findName) is pywintypes.UnicodeType: + findName = str(findName) + dict = {} + k = win32api.RegOpenKey( + win32con.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services" + ) + num = 0 + while 1: + try: + svc = win32api.RegEnumKey(k, num) + except win32api.error: + break + num = num + 1 + sk = win32api.RegOpenKey(k, svc) + try: + deps, typ = win32api.RegQueryValueEx(sk, "DependOnService") + except win32api.error: + deps = () + for dep in deps: + dep = dep.lower() + dep_on = dict.get(dep, []) + dep_on.append(svc) + dict[dep] = dep_on + + return __ResolveDeps(findName, dict) + + +def __ResolveDeps(findName, dict): + items = dict.get(findName.lower(), []) + retList = [] + for svc in items: + retList.insert(0, svc) + retList = __ResolveDeps(svc, dict) + retList + return retList + + +def WaitForServiceStatus(serviceName, status, waitSecs, machine=None): + """Waits for the service to return the specified status. You + should have already requested the service to enter that state""" + for i in range(waitSecs * 4): + now_status = QueryServiceStatus(serviceName, machine)[1] + if now_status == status: + break + win32api.Sleep(250) + else: + raise pywintypes.error( + winerror.ERROR_SERVICE_REQUEST_TIMEOUT, + "QueryServiceStatus", + win32api.FormatMessage(winerror.ERROR_SERVICE_REQUEST_TIMEOUT)[:-2], + ) + + +def __StopServiceWithTimeout(hs, waitSecs=30): + try: + status = win32service.ControlService(hs, win32service.SERVICE_CONTROL_STOP) + except pywintypes.error as exc: + if exc.winerror != winerror.ERROR_SERVICE_NOT_ACTIVE: + raise + for i in range(waitSecs): + status = win32service.QueryServiceStatus(hs) + if status[1] == win32service.SERVICE_STOPPED: + break + win32api.Sleep(1000) + else: + raise pywintypes.error( + winerror.ERROR_SERVICE_REQUEST_TIMEOUT, + "ControlService", + win32api.FormatMessage(winerror.ERROR_SERVICE_REQUEST_TIMEOUT)[:-2], + ) + + +def StopServiceWithDeps(serviceName, machine=None, waitSecs=30): + # Stop a service recursively looking for dependant services + hscm = win32service.OpenSCManager(machine, None, win32service.SC_MANAGER_ALL_ACCESS) + try: + deps = __FindSvcDeps(serviceName) + for dep in deps: + hs = win32service.OpenService(hscm, dep, win32service.SERVICE_ALL_ACCESS) + try: + __StopServiceWithTimeout(hs, waitSecs) + finally: + win32service.CloseServiceHandle(hs) + # Now my service! + hs = win32service.OpenService( + hscm, serviceName, win32service.SERVICE_ALL_ACCESS + ) + try: + __StopServiceWithTimeout(hs, waitSecs) + finally: + win32service.CloseServiceHandle(hs) + + finally: + win32service.CloseServiceHandle(hscm) + + +def StopService(serviceName, machine=None): + return ControlService(serviceName, win32service.SERVICE_CONTROL_STOP, machine) + + +def StartService(serviceName, args=None, machine=None): + hscm = win32service.OpenSCManager(machine, None, win32service.SC_MANAGER_ALL_ACCESS) + try: + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + try: + win32service.StartService(hs, args) + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + + +def RestartService(serviceName, args=None, waitSeconds=30, machine=None): + "Stop the service, and then start it again (with some tolerance for allowing it to stop.)" + try: + StopService(serviceName, machine) + except pywintypes.error as exc: + # Allow only "service not running" error + if exc.winerror != winerror.ERROR_SERVICE_NOT_ACTIVE: + raise + # Give it a few goes, as the service may take time to stop + for i in range(waitSeconds): + try: + StartService(serviceName, args, machine) + break + except pywintypes.error as exc: + if exc.winerror != winerror.ERROR_SERVICE_ALREADY_RUNNING: + raise + win32api.Sleep(1000) + else: + print("Gave up waiting for the old service to stop!") + + +def _DebugCtrlHandler(evt): + if evt in (win32con.CTRL_C_EVENT, win32con.CTRL_BREAK_EVENT): + assert g_debugService + print("Stopping debug service.") + g_debugService.SvcStop() + return True + return False + + +def DebugService(cls, argv=[]): + # Run a service in "debug" mode. Re-implements what pythonservice.exe + # does when it sees a "-debug" param. + # Currently only used by "frozen" (ie, py2exe) programs (but later may + # end up being used for all services should we ever remove + # pythonservice.exe) + import servicemanager + + global g_debugService + + print("Debugging service %s - press Ctrl+C to stop." % (cls._svc_name_,)) + servicemanager.Debugging(True) + servicemanager.PrepareToHostSingle(cls) + g_debugService = cls(argv) + # Setup a ctrl+c handler to simulate a "stop" + win32api.SetConsoleCtrlHandler(_DebugCtrlHandler, True) + try: + g_debugService.SvcRun() + finally: + win32api.SetConsoleCtrlHandler(_DebugCtrlHandler, False) + servicemanager.Debugging(False) + g_debugService = None + + +def GetServiceClassString(cls, argv=None): + if argv is None: + argv = sys.argv + import pickle + + modName = pickle.whichmodule(cls, cls.__name__) + if modName == "__main__": + try: + fname = win32api.GetFullPathName(argv[0]) + path = os.path.split(fname)[0] + # Eaaaahhhh - sometimes this will be a short filename, which causes + # problems with 1.5.1 and the silly filename case rule. + filelist = win32api.FindFiles(fname) + # win32api.FindFiles will not detect files in a zip or exe. If list is empty, + # skip the test and hope the file really exists. + if len(filelist) != 0: + # Get the long name + fname = os.path.join(path, filelist[0][8]) + except win32api.error: + raise error( + "Could not resolve the path name '%s' to a full path" % (argv[0]) + ) + modName = os.path.splitext(fname)[0] + return modName + "." + cls.__name__ + + +def QueryServiceStatus(serviceName, machine=None): + hscm = win32service.OpenSCManager(machine, None, win32service.SC_MANAGER_CONNECT) + try: + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_QUERY_STATUS) + try: + status = win32service.QueryServiceStatus(hs) + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + return status + + +def usage(): + try: + fname = os.path.split(sys.argv[0])[1] + except: + fname = sys.argv[0] + print( + "Usage: '%s [options] install|update|remove|start [...]|stop|restart [...]|debug [...]'" + % fname + ) + print("Options for 'install' and 'update' commands only:") + print(" --username domain\\username : The Username the service is to run under") + print(" --password password : The password for the username") + print( + " --startup [manual|auto|disabled|delayed] : How the service starts, default = manual" + ) + print(" --interactive : Allow the service to interact with the desktop.") + print( + " --perfmonini file: .ini file to use for registering performance monitor data" + ) + print(" --perfmondll file: .dll file to use when querying the service for") + print(" performance data, default = perfmondata.dll") + print("Options for 'start' and 'stop' commands only:") + print(" --wait seconds: Wait for the service to actually start or stop.") + print(" If you specify --wait with the 'stop' option, the service") + print(" and all dependent services will be stopped, each waiting") + print(" the specified period.") + sys.exit(1) + + +def HandleCommandLine( + cls, + serviceClassString=None, + argv=None, + customInstallOptions="", + customOptionHandler=None, +): + """Utility function allowing services to process the command line. + + Allows standard commands such as 'start', 'stop', 'debug', 'install' etc. + + Install supports 'standard' command line options prefixed with '--', such as + --username, --password, etc. In addition, + the function allows custom command line options to be handled by the calling function. + """ + err = 0 + + if argv is None: + argv = sys.argv + + if len(argv) <= 1: + usage() + + serviceName = cls._svc_name_ + serviceDisplayName = cls._svc_display_name_ + if serviceClassString is None: + serviceClassString = GetServiceClassString(cls) + + # Pull apart the command line + import getopt + + try: + opts, args = getopt.getopt( + argv[1:], + customInstallOptions, + [ + "password=", + "username=", + "startup=", + "perfmonini=", + "perfmondll=", + "interactive", + "wait=", + ], + ) + except getopt.error as details: + print(details) + usage() + userName = None + password = None + perfMonIni = perfMonDll = None + startup = None + delayedstart = None + interactive = None + waitSecs = 0 + for opt, val in opts: + if opt == "--username": + userName = val + elif opt == "--password": + password = val + elif opt == "--perfmonini": + perfMonIni = val + elif opt == "--perfmondll": + perfMonDll = val + elif opt == "--interactive": + interactive = 1 + elif opt == "--startup": + map = { + "manual": win32service.SERVICE_DEMAND_START, + "auto": win32service.SERVICE_AUTO_START, + "delayed": win32service.SERVICE_AUTO_START, ## ChangeServiceConfig2 called later + "disabled": win32service.SERVICE_DISABLED, + } + try: + startup = map[val.lower()] + except KeyError: + print("'%s' is not a valid startup option" % val) + if val.lower() == "delayed": + delayedstart = True + elif val.lower() == "auto": + delayedstart = False + ## else no change + elif opt == "--wait": + try: + waitSecs = int(val) + except ValueError: + print("--wait must specify an integer number of seconds.") + usage() + + arg = args[0] + knownArg = 0 + # First we process all arguments which pass additional args on + if arg == "start": + knownArg = 1 + print("Starting service %s" % (serviceName)) + try: + StartService(serviceName, args[1:]) + if waitSecs: + WaitForServiceStatus( + serviceName, win32service.SERVICE_RUNNING, waitSecs + ) + except win32service.error as exc: + print("Error starting service: %s" % exc.strerror) + err = exc.winerror + + elif arg == "restart": + knownArg = 1 + print("Restarting service %s" % (serviceName)) + RestartService(serviceName, args[1:]) + if waitSecs: + WaitForServiceStatus(serviceName, win32service.SERVICE_RUNNING, waitSecs) + + elif arg == "debug": + knownArg = 1 + if not hasattr(sys, "frozen"): + # non-frozen services use pythonservice.exe which handles a + # -debug option + svcArgs = " ".join(args[1:]) + try: + exeName = LocateSpecificServiceExe(serviceName) + except win32api.error as exc: + if exc.winerror == winerror.ERROR_FILE_NOT_FOUND: + print("The service does not appear to be installed.") + print("Please install the service before debugging it.") + sys.exit(1) + raise + try: + os.system("%s -debug %s %s" % (exeName, serviceName, svcArgs)) + # ^C is used to kill the debug service. Sometimes Python also gets + # interrupted - ignore it... + except KeyboardInterrupt: + pass + else: + # py2exe services don't use pythonservice - so we simulate + # debugging here. + DebugService(cls, args) + + if not knownArg and len(args) != 1: + usage() # the rest of the cmds don't take addn args + + if arg == "install": + knownArg = 1 + try: + serviceDeps = cls._svc_deps_ + except AttributeError: + serviceDeps = None + try: + exeName = cls._exe_name_ + except AttributeError: + exeName = None # Default to PythonService.exe + try: + exeArgs = cls._exe_args_ + except AttributeError: + exeArgs = None + try: + description = cls._svc_description_ + except AttributeError: + description = None + print("Installing service %s" % (serviceName,)) + # Note that we install the service before calling the custom option + # handler, so if the custom handler fails, we have an installed service (from NT's POV) + # but is unlikely to work, as the Python code controlling it failed. Therefore + # we remove the service if the first bit works, but the second doesnt! + try: + InstallService( + serviceClassString, + serviceName, + serviceDisplayName, + serviceDeps=serviceDeps, + startType=startup, + bRunInteractive=interactive, + userName=userName, + password=password, + exeName=exeName, + perfMonIni=perfMonIni, + perfMonDll=perfMonDll, + exeArgs=exeArgs, + description=description, + delayedstart=delayedstart, + ) + if customOptionHandler: + customOptionHandler(*(opts,)) + print("Service installed") + except win32service.error as exc: + if exc.winerror == winerror.ERROR_SERVICE_EXISTS: + arg = "update" # Fall through to the "update" param! + else: + print( + "Error installing service: %s (%d)" % (exc.strerror, exc.winerror) + ) + err = exc.winerror + except ValueError as msg: # Can be raised by custom option handler. + print("Error installing service: %s" % str(msg)) + err = -1 + # xxx - maybe I should remove after _any_ failed install - however, + # xxx - it may be useful to help debug to leave the service as it failed. + # xxx - We really _must_ remove as per the comments above... + # As we failed here, remove the service, so the next installation + # attempt works. + try: + RemoveService(serviceName) + except win32api.error: + print("Warning - could not remove the partially installed service.") + + if arg == "update": + knownArg = 1 + try: + serviceDeps = cls._svc_deps_ + except AttributeError: + serviceDeps = None + try: + exeName = cls._exe_name_ + except AttributeError: + exeName = None # Default to PythonService.exe + try: + exeArgs = cls._exe_args_ + except AttributeError: + exeArgs = None + try: + description = cls._svc_description_ + except AttributeError: + description = None + print("Changing service configuration") + try: + ChangeServiceConfig( + serviceClassString, + serviceName, + serviceDeps=serviceDeps, + startType=startup, + bRunInteractive=interactive, + userName=userName, + password=password, + exeName=exeName, + displayName=serviceDisplayName, + perfMonIni=perfMonIni, + perfMonDll=perfMonDll, + exeArgs=exeArgs, + description=description, + delayedstart=delayedstart, + ) + if customOptionHandler: + customOptionHandler(*(opts,)) + print("Service updated") + except win32service.error as exc: + print( + "Error changing service configuration: %s (%d)" + % (exc.strerror, exc.winerror) + ) + err = exc.winerror + + elif arg == "remove": + knownArg = 1 + print("Removing service %s" % (serviceName)) + try: + RemoveService(serviceName) + print("Service removed") + except win32service.error as exc: + print("Error removing service: %s (%d)" % (exc.strerror, exc.winerror)) + err = exc.winerror + elif arg == "stop": + knownArg = 1 + print("Stopping service %s" % (serviceName)) + try: + if waitSecs: + StopServiceWithDeps(serviceName, waitSecs=waitSecs) + else: + StopService(serviceName) + except win32service.error as exc: + print("Error stopping service: %s (%d)" % (exc.strerror, exc.winerror)) + err = exc.winerror + if not knownArg: + err = -1 + print("Unknown command - '%s'" % arg) + usage() + return err + + +# +# Useful base class to build services from. +# +class ServiceFramework: + # Required Attributes: + # _svc_name_ = The service name + # _svc_display_name_ = The service display name + + # Optional Attributes: + _svc_deps_ = None # sequence of service names on which this depends + _exe_name_ = None # Default to PythonService.exe + _exe_args_ = None # Default to no arguments + _svc_description_ = ( + None # Only exists on Windows 2000 or later, ignored on windows NT + ) + + def __init__(self, args): + import servicemanager + + self.ssh = servicemanager.RegisterServiceCtrlHandler( + args[0], self.ServiceCtrlHandlerEx, True + ) + servicemanager.SetEventSourceName(self._svc_name_) + self.checkPoint = 0 + + def GetAcceptedControls(self): + # Setup the service controls we accept based on our attributes. Note + # that if you need to handle controls via SvcOther[Ex](), you must + # override this. + accepted = 0 + if hasattr(self, "SvcStop"): + accepted = accepted | win32service.SERVICE_ACCEPT_STOP + if hasattr(self, "SvcPause") and hasattr(self, "SvcContinue"): + accepted = accepted | win32service.SERVICE_ACCEPT_PAUSE_CONTINUE + if hasattr(self, "SvcShutdown"): + accepted = accepted | win32service.SERVICE_ACCEPT_SHUTDOWN + return accepted + + def ReportServiceStatus( + self, serviceStatus, waitHint=5000, win32ExitCode=0, svcExitCode=0 + ): + if self.ssh is None: # Debugging! + return + if serviceStatus == win32service.SERVICE_START_PENDING: + accepted = 0 + else: + accepted = self.GetAcceptedControls() + + if serviceStatus in [ + win32service.SERVICE_RUNNING, + win32service.SERVICE_STOPPED, + ]: + checkPoint = 0 + else: + self.checkPoint = self.checkPoint + 1 + checkPoint = self.checkPoint + + # Now report the status to the control manager + status = ( + win32service.SERVICE_WIN32_OWN_PROCESS, + serviceStatus, + accepted, # dwControlsAccepted, + win32ExitCode, # dwWin32ExitCode; + svcExitCode, # dwServiceSpecificExitCode; + checkPoint, # dwCheckPoint; + waitHint, + ) + win32service.SetServiceStatus(self.ssh, status) + + def SvcInterrogate(self): + # Assume we are running, and everyone is happy. + self.ReportServiceStatus(win32service.SERVICE_RUNNING) + + def SvcOther(self, control): + try: + print("Unknown control status - %d" % control) + except IOError: + # services may not have a valid stdout! + pass + + def ServiceCtrlHandler(self, control): + return self.ServiceCtrlHandlerEx(control, 0, None) + + # The 'Ex' functions, which take additional params + def SvcOtherEx(self, control, event_type, data): + # The default here is to call self.SvcOther as that is the old behaviour. + # If you want to take advantage of the extra data, override this method + return self.SvcOther(control) + + def ServiceCtrlHandlerEx(self, control, event_type, data): + if control == win32service.SERVICE_CONTROL_STOP: + return self.SvcStop() + elif control == win32service.SERVICE_CONTROL_PAUSE: + return self.SvcPause() + elif control == win32service.SERVICE_CONTROL_CONTINUE: + return self.SvcContinue() + elif control == win32service.SERVICE_CONTROL_INTERROGATE: + return self.SvcInterrogate() + elif control == win32service.SERVICE_CONTROL_SHUTDOWN: + return self.SvcShutdown() + else: + return self.SvcOtherEx(control, event_type, data) + + def SvcRun(self): + # This is the entry point the C framework calls when the Service is + # started. Your Service class should implement SvcDoRun(). + # Or you can override this method for more control over the Service + # statuses reported to the SCM. + + # If this method raises an exception, the C framework will detect this + # and report a SERVICE_STOPPED status with a non-zero error code. + + self.ReportServiceStatus(win32service.SERVICE_RUNNING) + self.SvcDoRun() + # Once SvcDoRun terminates, the service has stopped. + # We tell the SCM the service is still stopping - the C framework + # will automatically tell the SCM it has stopped when this returns. + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) diff --git a/MLPY/Lib/site-packages/win32/lib/win32timezone.py b/MLPY/Lib/site-packages/win32/lib/win32timezone.py new file mode 100644 index 0000000000000000000000000000000000000000..569ea9b9415fcc0c973bb9d15fc9f57ad9d08ea2 --- /dev/null +++ b/MLPY/Lib/site-packages/win32/lib/win32timezone.py @@ -0,0 +1,1023 @@ +# -*- coding: UTF-8 -*- + +""" +win32timezone: + Module for handling datetime.tzinfo time zones using the windows +registry for time zone information. The time zone names are dependent +on the registry entries defined by the operating system. + + This module may be tested using the doctest module. + + Written by Jason R. Coombs (jaraco@jaraco.com). + Copyright © 2003-2012. + All Rights Reserved. + + This module is licenced for use in Mark Hammond's pywin32 +library under the same terms as the pywin32 library. + + To use this time zone module with the datetime module, simply pass +the TimeZoneInfo object to the datetime constructor. For example, + +>>> import win32timezone, datetime +>>> assert 'Mountain Standard Time' in win32timezone.TimeZoneInfo.get_sorted_time_zone_names() +>>> MST = win32timezone.TimeZoneInfo('Mountain Standard Time') +>>> now = datetime.datetime.now(MST) + + The now object is now a time-zone aware object, and daylight savings- +aware methods may be called on it. + +>>> now.utcoffset() in (datetime.timedelta(-1, 61200), datetime.timedelta(-1, 64800)) +True + +(note that the result of utcoffset call will be different based on when now was +generated, unless standard time is always used) + +>>> now = datetime.datetime.now(TimeZoneInfo('Mountain Standard Time', True)) +>>> now.utcoffset() +datetime.timedelta(days=-1, seconds=61200) + +>>> aug2 = datetime.datetime(2003, 8, 2, tzinfo = MST) +>>> tuple(aug2.utctimetuple()) +(2003, 8, 2, 6, 0, 0, 5, 214, 0) +>>> nov2 = datetime.datetime(2003, 11, 25, tzinfo = MST) +>>> tuple(nov2.utctimetuple()) +(2003, 11, 25, 7, 0, 0, 1, 329, 0) + +To convert from one timezone to another, just use the astimezone method. + +>>> aug2.isoformat() +'2003-08-02T00:00:00-06:00' +>>> aug2est = aug2.astimezone(win32timezone.TimeZoneInfo('Eastern Standard Time')) +>>> aug2est.isoformat() +'2003-08-02T02:00:00-04:00' + +calling the displayName member will return the display name as set in the +registry. + +>>> est = win32timezone.TimeZoneInfo('Eastern Standard Time') +>>> str(est.displayName) +'(UTC-05:00) Eastern Time (US & Canada)' + +>>> gmt = win32timezone.TimeZoneInfo('GMT Standard Time', True) +>>> str(gmt.displayName) +'(UTC+00:00) Dublin, Edinburgh, Lisbon, London' + +To get the complete list of available time zone keys, +>>> zones = win32timezone.TimeZoneInfo.get_all_time_zones() + +If you want to get them in an order that's sorted longitudinally +>>> zones = win32timezone.TimeZoneInfo.get_sorted_time_zones() + +TimeZoneInfo now supports being pickled and comparison +>>> import pickle +>>> tz = win32timezone.TimeZoneInfo('China Standard Time') +>>> tz == pickle.loads(pickle.dumps(tz)) +True + +It's possible to construct a TimeZoneInfo from a TimeZoneDescription +including the currently-defined zone. +>>> tz = win32timezone.TimeZoneInfo(TimeZoneDefinition.current()) +>>> tz == pickle.loads(pickle.dumps(tz)) +True + +>>> aest = win32timezone.TimeZoneInfo('AUS Eastern Standard Time') +>>> est = win32timezone.TimeZoneInfo('E. Australia Standard Time') +>>> dt = datetime.datetime(2006, 11, 11, 1, 0, 0, tzinfo = aest) +>>> estdt = dt.astimezone(est) +>>> estdt.strftime('%Y-%m-%d %H:%M:%S') +'2006-11-11 00:00:00' + +>>> dt = datetime.datetime(2007, 1, 12, 1, 0, 0, tzinfo = aest) +>>> estdt = dt.astimezone(est) +>>> estdt.strftime('%Y-%m-%d %H:%M:%S') +'2007-01-12 00:00:00' + +>>> dt = datetime.datetime(2007, 6, 13, 1, 0, 0, tzinfo = aest) +>>> estdt = dt.astimezone(est) +>>> estdt.strftime('%Y-%m-%d %H:%M:%S') +'2007-06-13 01:00:00' + +Microsoft now has a patch for handling time zones in 2007 (see +http://support.microsoft.com/gp/cp_dst) + +As a result, patched systems will give an incorrect result for +dates prior to the designated year except for Vista and its +successors, which have dynamic time zone support. +>>> nov2_pre_change = datetime.datetime(2003, 11, 2, tzinfo = MST) +>>> old_response = (2003, 11, 2, 7, 0, 0, 6, 306, 0) +>>> incorrect_patch_response = (2003, 11, 2, 6, 0, 0, 6, 306, 0) +>>> pre_response = nov2_pre_change.utctimetuple() +>>> pre_response in (old_response, incorrect_patch_response) +True + +Furthermore, unpatched systems pre-Vista will give an incorrect +result for dates after 2007. +>>> nov2_post_change = datetime.datetime(2007, 11, 2, tzinfo = MST) +>>> incorrect_unpatched_response = (2007, 11, 2, 7, 0, 0, 4, 306, 0) +>>> new_response = (2007, 11, 2, 6, 0, 0, 4, 306, 0) +>>> post_response = nov2_post_change.utctimetuple() +>>> post_response in (new_response, incorrect_unpatched_response) +True + + +There is a function you can call to get some capabilities of the time +zone data. +>>> caps = GetTZCapabilities() +>>> isinstance(caps, dict) +True +>>> 'MissingTZPatch' in caps +True +>>> 'DynamicTZSupport' in caps +True + +>>> both_dates_correct = (pre_response == old_response and post_response == new_response) +>>> old_dates_wrong = (pre_response == incorrect_patch_response) +>>> new_dates_wrong = (post_response == incorrect_unpatched_response) + +>>> caps['DynamicTZSupport'] == both_dates_correct +True + +>>> (not caps['DynamicTZSupport'] and caps['MissingTZPatch']) == new_dates_wrong +True + +>>> (not caps['DynamicTZSupport'] and not caps['MissingTZPatch']) == old_dates_wrong +True + +This test helps ensure language support for unicode characters +>>> x = TIME_ZONE_INFORMATION(0, u'français') + + +Test conversion from one time zone to another at a DST boundary +=============================================================== + +>>> tz_hi = TimeZoneInfo('Hawaiian Standard Time') +>>> tz_pac = TimeZoneInfo('Pacific Standard Time') +>>> time_before = datetime.datetime(2011, 11, 5, 15, 59, 59, tzinfo=tz_hi) +>>> tz_hi.utcoffset(time_before) +datetime.timedelta(days=-1, seconds=50400) +>>> tz_hi.dst(time_before) +datetime.timedelta(0) + +Hawaii doesn't need dynamic TZ info +>>> getattr(tz_hi, 'dynamicInfo', None) + +Here's a time that gave some trouble as reported in #3523104 +because one minute later, the equivalent UTC time changes from DST +in the U.S. +>>> dt_hi = datetime.datetime(2011, 11, 5, 15, 59, 59, 0, tzinfo=tz_hi) +>>> dt_hi.timetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=15, tm_min=59, tm_sec=59, tm_wday=5, tm_yday=309, tm_isdst=0) +>>> dt_hi.utctimetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=1, tm_min=59, tm_sec=59, tm_wday=6, tm_yday=310, tm_isdst=0) + +Convert the time to pacific time. +>>> dt_pac = dt_hi.astimezone(tz_pac) +>>> dt_pac.timetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=18, tm_min=59, tm_sec=59, tm_wday=5, tm_yday=309, tm_isdst=1) + +Notice that the UTC time is almost 2am. +>>> dt_pac.utctimetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=1, tm_min=59, tm_sec=59, tm_wday=6, tm_yday=310, tm_isdst=0) + +Now do the same tests one minute later in Hawaii. +>>> time_after = datetime.datetime(2011, 11, 5, 16, 0, 0, 0, tzinfo=tz_hi) +>>> tz_hi.utcoffset(time_after) +datetime.timedelta(days=-1, seconds=50400) +>>> tz_hi.dst(time_before) +datetime.timedelta(0) + +>>> dt_hi = datetime.datetime(2011, 11, 5, 16, 0, 0, 0, tzinfo=tz_hi) +>>> print(dt_hi.timetuple()) +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=16, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=309, tm_isdst=0) +>>> print(dt_hi.utctimetuple()) +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=2, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=310, tm_isdst=0) + +According to the docs, this is what astimezone does. +>>> utc = (dt_hi - dt_hi.utcoffset()).replace(tzinfo=tz_pac) +>>> utc +datetime.datetime(2011, 11, 6, 2, 0, tzinfo=TimeZoneInfo('Pacific Standard Time')) +>>> tz_pac.fromutc(utc) == dt_hi.astimezone(tz_pac) +True +>>> tz_pac.fromutc(utc) +datetime.datetime(2011, 11, 5, 19, 0, tzinfo=TimeZoneInfo('Pacific Standard Time')) + +Make sure the converted time is correct. +>>> dt_pac = dt_hi.astimezone(tz_pac) +>>> dt_pac.timetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=19, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=309, tm_isdst=1) +>>> dt_pac.utctimetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=2, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=310, tm_isdst=0) + +Check some internal methods +>>> tz_pac._getStandardBias(datetime.datetime(2011, 1, 1)) +datetime.timedelta(seconds=28800) +>>> tz_pac._getDaylightBias(datetime.datetime(2011, 1, 1)) +datetime.timedelta(seconds=25200) + +Test the offsets +>>> offset = tz_pac.utcoffset(datetime.datetime(2011, 11, 6, 2, 0)) +>>> offset == datetime.timedelta(hours=-8) +True +>>> dst_offset = tz_pac.dst(datetime.datetime(2011, 11, 6, 2, 0) + offset) +>>> dst_offset == datetime.timedelta(hours=1) +True +>>> (offset + dst_offset) == datetime.timedelta(hours=-7) +True + + +Test offsets that occur right at the DST changeover +>>> datetime.datetime.utcfromtimestamp(1320570000).replace( +... tzinfo=TimeZoneInfo.utc()).astimezone(tz_pac) +datetime.datetime(2011, 11, 6, 1, 0, tzinfo=TimeZoneInfo('Pacific Standard Time')) + +""" +__author__ = "Jason R. Coombs " + +import datetime +import logging +import operator +import re +import struct +import winreg +from itertools import count + +import win32api + +log = logging.getLogger(__file__) + + +# A couple of objects for working with objects as if they were native C-type +# structures. +class _SimpleStruct(object): + _fields_ = None # must be overridden by subclasses + + def __init__(self, *args, **kw): + for i, (name, typ) in enumerate(self._fields_): + def_arg = None + if i < len(args): + def_arg = args[i] + if name in kw: + def_arg = kw[name] + if def_arg is not None: + if not isinstance(def_arg, tuple): + def_arg = (def_arg,) + else: + def_arg = () + if len(def_arg) == 1 and isinstance(def_arg[0], typ): + # already an object of this type. + # XXX - should copy.copy??? + def_val = def_arg[0] + else: + def_val = typ(*def_arg) + setattr(self, name, def_val) + + def field_names(self): + return [f[0] for f in self._fields_] + + def __eq__(self, other): + if not hasattr(other, "_fields_"): + return False + if self._fields_ != other._fields_: + return False + for name, _ in self._fields_: + if getattr(self, name) != getattr(other, name): + return False + return True + + def __ne__(self, other): + return not self.__eq__(other) + + +class SYSTEMTIME(_SimpleStruct): + _fields_ = [ + ("year", int), + ("month", int), + ("day_of_week", int), + ("day", int), + ("hour", int), + ("minute", int), + ("second", int), + ("millisecond", int), + ] + + +class TIME_ZONE_INFORMATION(_SimpleStruct): + _fields_ = [ + ("bias", int), + ("standard_name", str), + ("standard_start", SYSTEMTIME), + ("standard_bias", int), + ("daylight_name", str), + ("daylight_start", SYSTEMTIME), + ("daylight_bias", int), + ] + + +class DYNAMIC_TIME_ZONE_INFORMATION(_SimpleStruct): + _fields_ = TIME_ZONE_INFORMATION._fields_ + [ + ("key_name", str), + ("dynamic_daylight_time_disabled", bool), + ] + + +class TimeZoneDefinition(DYNAMIC_TIME_ZONE_INFORMATION): + """ + A time zone definition class based on the win32 + DYNAMIC_TIME_ZONE_INFORMATION structure. + + Describes a bias against UTC (bias), and two dates at which a separate + additional bias applies (standard_bias and daylight_bias). + """ + + def __init__(self, *args, **kwargs): + """ + Try to construct a TimeZoneDefinition from + a) [DYNAMIC_]TIME_ZONE_INFORMATION args + b) another TimeZoneDefinition + c) a byte structure (using _from_bytes) + """ + try: + super(TimeZoneDefinition, self).__init__(*args, **kwargs) + return + except (TypeError, ValueError): + pass + + try: + self.__init_from_other(*args, **kwargs) + return + except TypeError: + pass + + try: + self.__init_from_bytes(*args, **kwargs) + return + except TypeError: + pass + + raise TypeError("Invalid arguments for %s" % self.__class__) + + def __init_from_bytes( + self, + bytes, + standard_name="", + daylight_name="", + key_name="", + daylight_disabled=False, + ): + format = "3l8h8h" + components = struct.unpack(format, bytes) + bias, standard_bias, daylight_bias = components[:3] + standard_start = SYSTEMTIME(*components[3:11]) + daylight_start = SYSTEMTIME(*components[11:19]) + super(TimeZoneDefinition, self).__init__( + bias, + standard_name, + standard_start, + standard_bias, + daylight_name, + daylight_start, + daylight_bias, + key_name, + daylight_disabled, + ) + + def __init_from_other(self, other): + if not isinstance(other, TIME_ZONE_INFORMATION): + raise TypeError("Not a TIME_ZONE_INFORMATION") + for name in other.field_names(): + # explicitly get the value from the underlying structure + value = super(TimeZoneDefinition, other).__getattribute__(other, name) + setattr(self, name, value) + # consider instead of the loop above just copying the memory directly + # size = max(ctypes.sizeof(DYNAMIC_TIME_ZONE_INFO), ctypes.sizeof(other)) + # ctypes.memmove(ctypes.addressof(self), other, size) + + def __getattribute__(self, attr): + value = super(TimeZoneDefinition, self).__getattribute__(attr) + if "bias" in attr: + value = datetime.timedelta(minutes=value) + return value + + @classmethod + def current(class_): + "Windows Platform SDK GetTimeZoneInformation" + code, tzi = win32api.GetTimeZoneInformation(True) + return code, class_(*tzi) + + def set(self): + tzi = tuple(getattr(self, n) for n, t in self._fields_) + win32api.SetTimeZoneInformation(tzi) + + def copy(self): + # XXX - this is no longer a copy! + return self.__class__(self) + + def locate_daylight_start(self, year): + return self._locate_day(year, self.daylight_start) + + def locate_standard_start(self, year): + return self._locate_day(year, self.standard_start) + + @staticmethod + def _locate_day(year, cutoff): + """ + Takes a SYSTEMTIME object, such as retrieved from a TIME_ZONE_INFORMATION + structure or call to GetTimeZoneInformation and interprets it based on the given + year to identify the actual day. + + This method is necessary because the SYSTEMTIME structure refers to a day by its + day of the week and week of the month (e.g. 4th saturday in March). + + >>> SATURDAY = 6 + >>> MARCH = 3 + >>> st = SYSTEMTIME(2000, MARCH, SATURDAY, 4, 0, 0, 0, 0) + + # according to my calendar, the 4th Saturday in March in 2009 was the 28th + >>> expected_date = datetime.datetime(2009, 3, 28) + >>> TimeZoneDefinition._locate_day(2009, st) == expected_date + True + """ + # MS stores Sunday as 0, Python datetime stores Monday as zero + target_weekday = (cutoff.day_of_week + 6) % 7 + # For SYSTEMTIMEs relating to time zone inforamtion, cutoff.day + # is the week of the month + week_of_month = cutoff.day + # so the following is the first day of that week + day = (week_of_month - 1) * 7 + 1 + result = datetime.datetime( + year, + cutoff.month, + day, + cutoff.hour, + cutoff.minute, + cutoff.second, + cutoff.millisecond, + ) + # now the result is the correct week, but not necessarily the correct day of the week + days_to_go = (target_weekday - result.weekday()) % 7 + result += datetime.timedelta(days_to_go) + # if we selected a day in the month following the target month, + # move back a week or two. + # This is necessary because Microsoft defines the fifth week in a month + # to be the last week in a month and adding the time delta might have + # pushed the result into the next month. + while result.month == cutoff.month + 1: + result -= datetime.timedelta(weeks=1) + return result + + +class TimeZoneInfo(datetime.tzinfo): + """ + Main class for handling Windows time zones. + Usage: + TimeZoneInfo(