├── .gitattributes ├── .github └── workflows │ └── pymi-cd.yml ├── .gitignore ├── LICENSE ├── MI ├── MI++.cpp ├── MI++.h ├── MI.vcxproj ├── MI.vcxproj.filters ├── MIExceptions.cpp ├── MIExceptions.h ├── MIValue.cpp ├── MIValue.h ├── PythonDir.props ├── ReadMe.txt ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── PyMI.sln ├── PyMI ├── Application.cpp ├── Application.h ├── Callbacks.cpp ├── Callbacks.h ├── Class.cpp ├── Class.h ├── DestinationOptions.cpp ├── DestinationOptions.h ├── Instance.cpp ├── Instance.h ├── MiError.cpp ├── MiError.h ├── Operation.cpp ├── Operation.h ├── OperationOptions.cpp ├── OperationOptions.h ├── PyMI.cpp ├── PyMI.h ├── PyMI.vcxproj ├── PyMI.vcxproj.filters ├── PythonDir.props ├── README.rst ├── Serializer.cpp ├── Serializer.h ├── Session.cpp ├── Session.h ├── Utils.cpp ├── Utils.h ├── setup_vs.py ├── src │ └── mi │ │ └── __init__.py ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── README.rst ├── requirements.txt ├── setup.cfg ├── setup.py └── wmi ├── __init__.py ├── samples ├── benchmark.py ├── benchmark2.py ├── benchmark3.py └── custom_operation_options.py └── tests ├── __init__.py └── functional ├── __init__.py ├── test_base.py ├── test_basic_ops.py └── test_timeouts.py /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/pymi-cd.yml: -------------------------------------------------------------------------------- 1 | name: PyMI CD 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: windows-latest 9 | strategy: 10 | max-parallel: 100 11 | matrix: 12 | python-version: ["3.10", "3.11", "3.12"] 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Set up Python ${{ matrix.python-version }} 17 | uses: actions/setup-python@v4 18 | with: 19 | python-version: ${{ matrix.python-version }} 20 | - name: Test and build PyMI 21 | shell: cmd 22 | run: | 23 | SETLOCAL EnableDelayedExpansion 24 | pip install -r requirements.txt || exit /b 25 | pip install nose testtools wheel || exit /b 26 | pip install . || exit /b 27 | python -m unittest discover || exit /b 28 | python setup.py bdist_wheel || exit /b 29 | - uses: actions/upload-artifact@v3 30 | with: 31 | name: pymi_wheel_py${{ matrix.python-version }} 32 | path: 'dist' 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug*/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease*/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | *.sap 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding add-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | _NCrunch_* 111 | .*crunch*.local.xml 112 | nCrunchTemp_* 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | 154 | # Windows Azure Build Output 155 | csx/ 156 | *.build.csdef 157 | 158 | # Windows Azure Emulator 159 | efc/ 160 | rfc/ 161 | 162 | # Windows Store app package directory 163 | AppPackages/ 164 | 165 | # Visual Studio cache files 166 | # files ending in .cache can be ignored 167 | *.[Cc]ache 168 | # but keep track of directories ending in .cache 169 | !*.[Cc]ache/ 170 | 171 | # Others 172 | ClientBin/ 173 | [Ss]tyle[Cc]op.* 174 | ~$* 175 | *~ 176 | *.dbmdl 177 | *.dbproj.schemaview 178 | *.pfx 179 | *.publishsettings 180 | node_modules/ 181 | orleans.codegen.cs 182 | 183 | # RIA/Silverlight projects 184 | Generated_Code/ 185 | 186 | # Backup & report files from converting an old project file 187 | # to a newer Visual Studio version. Backup files are not needed, 188 | # because we have git ;-) 189 | _UpgradeReport_Files/ 190 | Backup*/ 191 | UpgradeLog*.XML 192 | UpgradeLog*.htm 193 | 194 | # SQL Server files 195 | *.mdf 196 | *.ldf 197 | 198 | # Business Intelligence projects 199 | *.rdl.data 200 | *.bim.layout 201 | *.bim_*.settings 202 | 203 | # Microsoft Fakes 204 | FakesAssemblies/ 205 | 206 | # GhostDoc plugin setting file 207 | *.GhostDoc.xml 208 | 209 | # Node.js Tools for Visual Studio 210 | .ntvs_analysis.dat 211 | 212 | # Visual Studio 6 build log 213 | *.plg 214 | 215 | # Visual Studio 6 workspace options file 216 | *.opt 217 | 218 | # Visual Studio LightSwitch build output 219 | **/*.HTMLClient/GeneratedArtifacts 220 | **/*.DesktopClient/GeneratedArtifacts 221 | **/*.DesktopClient/ModelManifest.xml 222 | **/*.Server/GeneratedArtifacts 223 | **/*.Server/ModelManifest.xml 224 | _Pvt_Extensions 225 | 226 | # Paket dependency manager 227 | .paket/paket.exe 228 | 229 | # FAKE - F# Make 230 | .fake/ 231 | 232 | *.pyc 233 | *.pyd 234 | *.egg-info 235 | dist 236 | 237 | *.metaproj 238 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | -------------------------------------------------------------------------------- /MI/MI++.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "MIValue.h" 10 | 11 | namespace MI 12 | { 13 | class Session; 14 | class Instance; 15 | class Operation; 16 | class Class; 17 | class Serializer; 18 | class OperationOptions; 19 | class DestinationOptions; 20 | 21 | class Callbacks 22 | { 23 | public: 24 | virtual bool WriteError(std::shared_ptr operation, std::shared_ptr instance) 25 | { 26 | return true; 27 | } 28 | virtual void WriteMessage(std::shared_ptr operation, unsigned channel, const std::wstring& message) 29 | { 30 | } 31 | virtual void WriteProgress(std::shared_ptr operation, const std::wstring& activity, 32 | const std::wstring& currentOperation, const std::wstring& statusDescription, unsigned percentageComplete, 33 | unsigned secondsRemaining) 34 | { 35 | } 36 | virtual void ClassResult(std::shared_ptr operation, std::shared_ptr miClass, bool moreResults, 37 | MI_Result resultCode, const std::wstring& errorString, std::shared_ptr errorDetails) 38 | { 39 | } 40 | virtual void InstanceResult(std::shared_ptr operation, std::shared_ptr instance, bool moreResults, 41 | MI_Result resultCode, const std::wstring& errorString, std::shared_ptr errorDetails) 42 | { 43 | } 44 | virtual void IndicationResult(std::shared_ptr operation, std::shared_ptr instance, 45 | const std::wstring& bookmark, const std::wstring& machineID, bool moreResults, MI_Result resultCode, 46 | const std::wstring& errorString, std::shared_ptr errorDetails) 47 | { 48 | } 49 | virtual void StreamedParameterResult(std::shared_ptr operation, const std::wstring& parameterName, 50 | MI_Type resultType, const MI_Value& result) 51 | { 52 | } 53 | virtual ~Callbacks() 54 | { 55 | } 56 | }; 57 | 58 | class Application 59 | { 60 | private: 61 | MI_Application m_app; 62 | Application(const Application &obj) {} 63 | 64 | friend class Session; 65 | 66 | public: 67 | Application(const std::wstring& appId = L""); 68 | void Close(); 69 | bool IsClosed(); 70 | virtual ~Application(); 71 | std::shared_ptr NewInstance(const std::wstring& className); 72 | std::shared_ptr NewMethodParamsInstance(const Class& miClass, const std::wstring& methodName); 73 | std::shared_ptr NewInstanceFromClass(const std::wstring& className, const Class& miClass); 74 | std::shared_ptr NewSession(const std::wstring& protocol = L"", const std::wstring& computerName = L".", 75 | std::shared_ptr destinationOptions = nullptr); 76 | std::shared_ptr NewOperationOptions(); 77 | std::shared_ptr NewDestinationOptions(); 78 | std::shared_ptr NewSerializer(); 79 | }; 80 | 81 | class OperationOptions 82 | { 83 | private: 84 | MI_OperationOptions m_operationOptions; 85 | OperationOptions(MI_OperationOptions operationOptions) : m_operationOptions(operationOptions) {} 86 | OperationOptions(const OperationOptions &obj) {} 87 | 88 | friend Application; 89 | friend Session; 90 | 91 | public: 92 | std::shared_ptr Clone() const; 93 | void SetTimeout(const MI_Interval& timeout); 94 | MI_Interval GetTimeout(); 95 | void SetCustomOption(const std::wstring& optionName, 96 | MI_Type optionValueType, 97 | const MIValue& optionValue, 98 | MI_Boolean mustComply); 99 | void Delete(); 100 | virtual ~OperationOptions(); 101 | }; 102 | 103 | class DestinationOptions 104 | { 105 | private: 106 | MI_DestinationOptions m_destinationOptions; 107 | DestinationOptions(MI_DestinationOptions destinationOptions) : m_destinationOptions(destinationOptions) {} 108 | DestinationOptions(const DestinationOptions &obj) {} 109 | 110 | friend Application; 111 | 112 | public: 113 | std::shared_ptr Clone() const; 114 | void SetTimeout(const MI_Interval& timeout); 115 | MI_Interval GetTimeout(); 116 | void SetUILocale(const std::wstring& locale); 117 | std::wstring GetUILocale(); 118 | void SetTransport(const std::wstring& transport); 119 | std::wstring GetTransport(); 120 | void AddCredentials(const std::wstring& authType, 121 | const std::wstring& certThumbprint); 122 | void AddCredentials(const std::wstring& authType, const std::wstring& domain, 123 | const std::wstring& username, const std::wstring& password); 124 | void Delete(); 125 | virtual ~DestinationOptions(); 126 | }; 127 | 128 | class Session 129 | { 130 | private: 131 | MI_Session m_session; 132 | Session(MI_Session session) : m_session(session) {} 133 | Session(const Session &obj) {} 134 | 135 | friend Application; 136 | 137 | public: 138 | std::shared_ptr ExecQuery(const std::wstring& ns, const std::wstring& query, 139 | const std::wstring& dialect = L"WQL", 140 | std::shared_ptr operationOptions = nullptr); 141 | std::shared_ptr InvokeMethod( 142 | Instance& instance, const std::wstring& methodName, std::shared_ptr inboundParams, 143 | std::shared_ptr operationOptions = nullptr); 144 | std::shared_ptr InvokeMethod( 145 | const std::wstring& ns, const std::wstring& className, const std::wstring& methodName, std::shared_ptr, 146 | std::shared_ptr operationOptions = nullptr); 147 | void CreateInstance(const std::wstring& ns, const Instance& instance, 148 | std::shared_ptr operationOptions = nullptr); 149 | void ModifyInstance(const std::wstring& ns, const Instance& instance, 150 | std::shared_ptr operationOptions = nullptr); 151 | void DeleteInstance(const std::wstring& ns, const Instance& instance, 152 | std::shared_ptr operationOptions = nullptr); 153 | std::shared_ptr GetClass(const std::wstring& ns, const std::wstring& className); 154 | std::shared_ptr GetInstance(const std::wstring& ns, const Instance& keyInstance); 155 | std::shared_ptr GetAssociators(const std::wstring& ns, const Instance& instance, const std::wstring& assocClass = L"", 156 | const std::wstring& resultClass = L"", const std::wstring& role = L"", 157 | const std::wstring& resultRole = L"", bool keysOnly = false, 158 | std::shared_ptr operationOptions = nullptr); 159 | std::shared_ptr Subscribe(const std::wstring& ns, const std::wstring& query, std::shared_ptr callback = nullptr, 160 | std::shared_ptr operationOptions = nullptr, const std::wstring& dialect = L"WQL"); 161 | void Close(); 162 | bool IsClosed(); 163 | virtual ~Session(); 164 | }; 165 | 166 | struct Qualifier 167 | { 168 | public: 169 | std::wstring m_name; 170 | MI_Type m_type; 171 | MI_Value m_value; 172 | MI_Uint32 m_flags; 173 | }; 174 | 175 | struct BaseElementInfo 176 | { 177 | public: 178 | std::wstring m_name; 179 | unsigned m_index; 180 | MI_Type m_type; 181 | }; 182 | 183 | struct ParameterInfo : public BaseElementInfo 184 | { 185 | public: 186 | std::map> m_qualifiers; 187 | }; 188 | 189 | struct MethodInfo 190 | { 191 | public: 192 | std::wstring m_name; 193 | unsigned m_index; 194 | std::map> m_qualifiers; 195 | std::map> m_parameters; 196 | }; 197 | 198 | struct BaseElementInfoWithFlags : public BaseElementInfo 199 | { 200 | public: 201 | MI_Uint32 m_flags; 202 | }; 203 | 204 | struct ValueElement : public BaseElementInfoWithFlags 205 | { 206 | public: 207 | MI_Value m_value; 208 | }; 209 | 210 | struct ClassElement : public ValueElement 211 | { 212 | public: 213 | MI_Boolean m_valueExists; 214 | std::map> m_qualifiers; 215 | }; 216 | 217 | class ScopedItem; 218 | 219 | class ScopeContextOwner 220 | { 221 | public: 222 | virtual void RemoveFromScopeContext(ScopedItem* item) = 0; 223 | }; 224 | 225 | class ScopedItem 226 | { 227 | private: 228 | ScopeContextOwner* m_scopeOwner = nullptr; 229 | public: 230 | ScopedItem(ScopeContextOwner* scopeOwner) : m_scopeOwner(scopeOwner) {}; 231 | virtual void SetOutOfScope() { m_scopeOwner = nullptr; }; 232 | virtual void RemoveFromScopeContext(); 233 | virtual ~ScopedItem(); 234 | }; 235 | 236 | class Class : private ScopedItem 237 | { 238 | private: 239 | MI_Class* m_class = nullptr; 240 | bool m_ownsInstance = false; 241 | std::shared_ptr> m_key = nullptr; 242 | 243 | Class(const Class &obj) : ScopedItem(nullptr) {} // Use Clone 244 | 245 | friend Application; 246 | friend Instance; 247 | friend Operation; 248 | friend Serializer; 249 | 250 | public: 251 | Class(MI_Class* miClass, bool ownsInstance, ScopeContextOwner* scopeOwner = nullptr) : 252 | m_class(miClass), m_ownsInstance(ownsInstance), ScopedItem(scopeOwner) {} 253 | unsigned GetElementsCount() const; 254 | std::shared_ptr> GetKey(); 255 | std::shared_ptr operator[] (const std::wstring& name) const; 256 | std::shared_ptr operator[] (unsigned index) const; 257 | unsigned GetMethodCount() const; 258 | std::shared_ptr GetMethodInfo(const std::wstring& name) const; 259 | std::shared_ptr GetMethodInfo(unsigned index) const; 260 | std::wstring GetClassName() const; 261 | std::wstring GetNameSpace() const; 262 | std::wstring GetServerName() const; 263 | std::wstring GetParentClassName() const; 264 | std::shared_ptr GetParentClass() const; 265 | std::shared_ptr Clone() const; 266 | void SetOutOfScope(); 267 | void Delete(); 268 | virtual ~Class(); 269 | }; 270 | 271 | class Instance : private ScopedItem 272 | { 273 | private: 274 | MI_Instance* m_instance = nullptr; 275 | bool m_ownsInstance = false; 276 | std::shared_ptr> m_keyElementNames = nullptr; 277 | 278 | Instance(const Instance &obj) : ScopedItem(nullptr) {} // Use Clone 279 | const std::vector& GetKeyElementNames(); 280 | 281 | friend Application; 282 | friend Operation; 283 | friend Session; 284 | friend Serializer; 285 | 286 | public: 287 | Instance(MI_Instance* instance, bool ownsInstance, ScopeContextOwner* scopeOwner = nullptr) : 288 | m_instance(instance), m_ownsInstance(ownsInstance), ScopedItem(scopeOwner) {} 289 | MI_Instance* GetMIObject() { return this->m_instance; } 290 | std::shared_ptr Clone() const; 291 | std::shared_ptr GetClass() const; 292 | std::wstring GetClassName() const; 293 | std::wstring GetNameSpace() const; 294 | std::wstring GetServerName() const; 295 | unsigned GetElementsCount() const; 296 | std::wstring GetPath(); 297 | std::shared_ptr operator[] (const std::wstring& name) const; 298 | std::shared_ptr operator[] (unsigned index) const; 299 | void AddElement(const std::wstring& name, const MIValue& value); 300 | void SetElement(const std::wstring& name, const MIValue& value); 301 | void SetElement(unsigned index, const MIValue& value); 302 | MI_Type GetElementType(const std::wstring& name) const; 303 | MI_Type GetElementType(unsigned index) const; 304 | void ClearElement(const std::wstring& name); 305 | void ClearElement(unsigned index); 306 | void SetOutOfScope(); 307 | void Delete(); 308 | virtual ~Instance(); 309 | }; 310 | 311 | class Operation : private ScopeContextOwner 312 | { 313 | private: 314 | MI_Operation m_operation; 315 | MI_Boolean m_hasMoreResults = TRUE; 316 | bool m_ownsInstance = false; 317 | ScopedItem* m_currentItem = nullptr; 318 | 319 | Operation(const Operation &obj) {} 320 | void RemoveFromScopeContext(ScopedItem* item); 321 | void SetCurrentItem(ScopedItem* currentItem); 322 | 323 | friend Session; 324 | 325 | public: 326 | Operation(MI_Operation& operation, bool ownsInstance=true) : m_operation(operation), m_ownsInstance(ownsInstance) {} 327 | std::shared_ptr GetNextInstance(); 328 | std::shared_ptr GetNextClass(); 329 | std::shared_ptr GetNextIndication(); 330 | bool HasMoreResults() { return m_hasMoreResults != FALSE; } 331 | void Cancel(); 332 | void Close(); 333 | bool IsClosed(); 334 | virtual ~Operation(); 335 | }; 336 | 337 | class Serializer 338 | { 339 | private: 340 | MI_Serializer m_serializer; 341 | Serializer(const Serializer &obj) {} // Use Clone 342 | Serializer(MI_Serializer& serializer) : m_serializer(serializer) {} 343 | 344 | friend Application; 345 | 346 | public: 347 | std::wstring SerializeInstance(const Instance& instance, bool includeClass=false); 348 | std::wstring SerializeClass(const Class& miClass, bool deep=false); 349 | void Close(); 350 | bool IsClosed(); 351 | virtual ~Serializer(); 352 | }; 353 | }; 354 | -------------------------------------------------------------------------------- /MI/MI.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /MI/MIExceptions.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "MIExceptions.h" 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | using namespace MI; 9 | 10 | const wchar_t* MI::MI_RESULT_STRINGS[] = 11 | { 12 | L"MI_RESULT_OK", 13 | L"MI_RESULT_FAILED", 14 | L"MI_RESULT_ACCESS_DENIED", 15 | L"MI_RESULT_INVALID_NAMESPACE", 16 | L"MI_RESULT_INVALID_PARAMETER", 17 | L"MI_RESULT_INVALID_CLASS", 18 | L"MI_RESULT_NOT_FOUND", 19 | L"MI_RESULT_NOT_SUPPORTED", 20 | L"MI_RESULT_CLASS_HAS_CHILDREN", 21 | L"MI_RESULT_CLASS_HAS_INSTANCES", 22 | L"MI_RESULT_INVALID_SUPERCLASS", 23 | L"MI_RESULT_ALREADY_EXISTS", 24 | L"MI_RESULT_NO_SUCH_PROPERTY", 25 | L"MI_RESULT_TYPE_MISMATCH", 26 | L"MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED", 27 | L"MI_RESULT_INVALID_QUERY", 28 | L"MI_RESULT_METHOD_NOT_AVAILABLE", 29 | L"MI_RESULT_METHOD_NOT_FOUND", 30 | L"MI_RESULT_NAMESPACE_NOT_EMPTY", 31 | L"MI_RESULT_INVALID_ENUMERATION_CONTEXT", 32 | L"MI_RESULT_INVALID_OPERATION_TIMEOUT", 33 | L"MI_RESULT_PULL_HAS_BEEN_ABANDONED", 34 | L"MI_RESULT_PULL_CANNOT_BE_ABANDONED", 35 | L"MI_RESULT_FILTERED_ENUMERATION_NOT_SUPPORTED", 36 | L"MI_RESULT_CONTINUATION_ON_ERROR_NOT_SUPPORTED", 37 | L"MI_RESULT_SERVER_LIMITS_EXCEEDED", 38 | L"MI_RESULT_SERVER_IS_SHUTTING_DOWN" 39 | }; 40 | 41 | const char* Exception::what() const noexcept 42 | { 43 | return this->m_message.c_str(); 44 | } 45 | 46 | void Exception::SetMessageFromWString(const std::wstring& message) 47 | { 48 | // Convert to UTF8 49 | std::wstring_convert, wchar_t> cv; 50 | this->m_message = cv.to_bytes(message).c_str(); 51 | } 52 | 53 | std::wstring MIException::MIResultToWString(MI_Result miResult) const 54 | { 55 | 56 | if (miResult < sizeof(MI_RESULT_STRINGS) / sizeof(MI_RESULT_STRINGS[0])) 57 | { 58 | return MI_RESULT_STRINGS[miResult]; 59 | } 60 | else 61 | { 62 | return L"Unknown MI_Result"; 63 | } 64 | } 65 | 66 | MIException::MIException(MI_Result result, MI_Uint32 errorCode, const std::wstring& message) : 67 | m_result(result), m_errorCode(errorCode), Exception(message) 68 | { 69 | if (!message.length()) 70 | { 71 | this->SetMessageFromWString(this->MIResultToWString(this->m_result)); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /MI/MIExceptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define WMI_ERR_TIMEOUT 0x00040004 8 | 9 | 10 | namespace MI 11 | { 12 | extern const wchar_t* MI_RESULT_STRINGS[27]; 13 | 14 | class Exception : public std::exception 15 | { 16 | protected: 17 | std::string m_message; 18 | void SetMessageFromWString(const std::wstring& message); 19 | 20 | public: 21 | Exception(const std::wstring& message) { SetMessageFromWString(message); }; 22 | const char* what() const noexcept; 23 | }; 24 | 25 | class MIException : public Exception 26 | { 27 | private: 28 | const MI_Result m_result; 29 | const MI_Uint32 m_errorCode; 30 | std::wstring MIResultToWString(MI_Result miResult) const; 31 | 32 | public: 33 | MIException(MI_Result result, MI_Uint32 errorCode = 0, const std::wstring& message = L""); 34 | MI_Result GetResult() const { return m_result; } 35 | MI_Uint32 GetErrorCode() const { return m_errorCode; } 36 | }; 37 | 38 | class MITimeoutException : public MIException 39 | { 40 | public: 41 | MITimeoutException(MI_Result result = MI_RESULT_FAILED, 42 | MI_Uint32 errorCode = WMI_ERR_TIMEOUT, 43 | const std::wstring& message = L"A timeout occurred") : MIException(result, errorCode, message) {} 44 | }; 45 | 46 | class OutOfMemoryException : public Exception 47 | { 48 | public: 49 | OutOfMemoryException() : Exception(L"Out of memory") {} 50 | }; 51 | 52 | class TypeConversionException : public Exception 53 | { 54 | public: 55 | TypeConversionException(const std::wstring& message = L"Unsupported type conversion") : Exception(message) {} 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /MI/MIValue.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "MIValue.h" 3 | #include "MI++.h" 4 | #include "MIExceptions.h" 5 | 6 | using namespace MI; 7 | 8 | unsigned MIValue::GetItemSize(MI_Type valueType) 9 | { 10 | switch (valueType) 11 | { 12 | case MI_BOOLEAN: 13 | return sizeof(MI_Boolean); 14 | case MI_SINT8: 15 | return sizeof(MI_Sint8); 16 | case MI_UINT8: 17 | return sizeof(MI_Uint8); 18 | case MI_SINT16: 19 | return sizeof(MI_Sint16); 20 | case MI_UINT16: 21 | return sizeof(MI_Uint16); 22 | case MI_SINT32: 23 | return sizeof(MI_Sint32); 24 | case MI_UINT32: 25 | return sizeof(MI_Uint32); 26 | case MI_SINT64: 27 | return sizeof(MI_Sint64); 28 | case MI_UINT64: 29 | return sizeof(MI_Uint64); 30 | case MI_REAL32: 31 | return sizeof(MI_Real32); 32 | case MI_REAL64: 33 | return sizeof(MI_Real64); 34 | case MI_CHAR16: 35 | return sizeof(MI_Char16); 36 | case MI_DATETIME: 37 | return sizeof(MI_Datetime); 38 | case MI_STRING: 39 | return sizeof(MI_Char*); 40 | case MI_INSTANCE: 41 | case MI_REFERENCE: 42 | return sizeof(MI_Instance*); 43 | default: 44 | throw TypeConversionException(); 45 | } 46 | } 47 | 48 | void MIValue::SetNullValue() 49 | { 50 | m_flags = MI_FLAG_NULL; 51 | ::ZeroMemory(&m_value, sizeof(m_value)); 52 | } 53 | 54 | void MIValue::CopyString(const std::string& value) 55 | { 56 | int len = (int)(value.length() + 1); 57 | m_value.string = new MI_Char[len]; 58 | if (::MultiByteToWideChar(CP_ACP, 0, value.c_str(), len, m_value.string, len) != len) 59 | { 60 | delete[] m_value.string; 61 | throw Exception(L"MultiByteToWideChar failed"); 62 | } 63 | } 64 | 65 | void MIValue::CopyWString(const std::wstring& value) 66 | { 67 | auto len = value.length() + 1; 68 | m_value.string = new MI_Char[len]; 69 | memcpy_s(m_value.string, len * sizeof(MI_Char), value.c_str(), len * sizeof(MI_Char)); 70 | } 71 | 72 | void MIValue::Delete(MI_Value& value, MI_Type type) 73 | { 74 | if (type & MI_ARRAY) 75 | { 76 | unsigned len = value.uint8a.size; 77 | for (unsigned i = 0; i < len; i++) 78 | { 79 | MI_Type itemType = MI_Type(type ^ MI_ARRAY); 80 | unsigned itemSize = GetItemSize(itemType); 81 | Delete(*((MI_Value*)&value.uint8a.data[i * itemSize]), itemType); 82 | } 83 | delete[] value.uint8a.data; 84 | value.uint8a.data = nullptr; 85 | } 86 | else 87 | { 88 | switch (type) 89 | { 90 | case MI_STRING: 91 | delete[] value.string; 92 | value.string = nullptr; 93 | break; 94 | } 95 | } 96 | } 97 | 98 | void MIValue::SetArrayItem(const MIValue& value, MI_Uint32 index) 99 | { 100 | if (!(m_type & MI_ARRAY)) 101 | { 102 | throw new Exception(L"Not an array"); 103 | } 104 | 105 | if (value.m_type != (m_type ^ MI_ARRAY)) 106 | { 107 | throw new Exception(L"The item's MI type must match the array's item type"); 108 | } 109 | 110 | if (index >= m_value.uint8a.size) 111 | { 112 | throw new Exception(L"Array index out of range"); 113 | } 114 | 115 | unsigned itemSize = this->GetItemSize(value.m_type); 116 | if (value.m_type == MI_STRING) 117 | { 118 | MI_Char* strDest = nullptr; 119 | if (value.m_value.string) 120 | { 121 | auto len = lstrlen(value.m_value.string) + 1; 122 | strDest = new MI_Char[len]; 123 | memcpy_s(strDest, len * sizeof(MI_Char), value.m_value.string, len * sizeof(MI_Char)); 124 | } 125 | else 126 | { 127 | throw Exception(L"Array item cannot be NULL"); 128 | } 129 | memcpy_s(&m_value.uint8a.data[index * itemSize], itemSize, &strDest, itemSize); 130 | } 131 | else 132 | { 133 | memcpy_s(&m_value.uint8a.data[index * itemSize], itemSize, &value.m_value, itemSize); 134 | } 135 | } 136 | 137 | std::shared_ptr MIValue::CreateArray(MI_Uint32 arraySize, MI_Type type) 138 | { 139 | auto self = std::make_shared(type); 140 | if (arraySize) 141 | { 142 | // All array members of the MI_Value union have "pointer", "size" members. 143 | // It is safe to rely on one instead of referencing value.stringa, value.booleana, etc 144 | unsigned itemSize = self->GetItemSize((MI_Type)(type ^ MI_ARRAY)); 145 | self->m_value.uint8a.data = (MI_Uint8*)new MI_Uint8[itemSize * arraySize]; 146 | ::ZeroMemory(self->m_value.uint8a.data, itemSize * arraySize); 147 | self->m_value.uint8a.size = (unsigned)arraySize; 148 | } 149 | self->m_flags = 0; 150 | return self; 151 | } 152 | 153 | std::shared_ptr MIValue::FromBoolean(MI_Boolean value) 154 | { 155 | return std::make_shared((void*)&value, MI_BOOLEAN); 156 | } 157 | 158 | std::shared_ptr MIValue::FromSint8(MI_Sint8 value) 159 | { 160 | return std::make_shared((void*)&value, MI_SINT8); 161 | } 162 | 163 | std::shared_ptr MIValue::FromUint8(MI_Uint8 value) 164 | { 165 | return std::make_shared((void*)&value, MI_UINT8); 166 | } 167 | 168 | std::shared_ptr MIValue::FromSint16(MI_Sint16 value) 169 | { 170 | return std::make_shared((void*)&value, MI_SINT16); 171 | } 172 | 173 | std::shared_ptr MIValue::FromUint16(MI_Uint16 value) 174 | { 175 | return std::make_shared((void*)&value, MI_UINT16); 176 | } 177 | 178 | std::shared_ptr MIValue::FromChar16(MI_Char16 value) 179 | { 180 | return std::make_shared((void*)&value, MI_CHAR16); 181 | } 182 | 183 | std::shared_ptr MIValue::FromSint32(MI_Sint32 value) 184 | { 185 | return std::make_shared((void*)&value, MI_SINT32); 186 | } 187 | 188 | std::shared_ptr MIValue::FromUint32(MI_Uint32 value) 189 | { 190 | return std::make_shared((void*)&value, MI_UINT32); 191 | } 192 | 193 | std::shared_ptr MIValue::FromSint64(MI_Sint64 value) 194 | { 195 | return std::make_shared((void*)&value, MI_SINT64); 196 | } 197 | 198 | std::shared_ptr MIValue::FromUint64(MI_Uint64 value) 199 | { 200 | return std::make_shared((void*)&value, MI_UINT64); 201 | } 202 | 203 | std::shared_ptr MIValue::FromReal32(MI_Real32 value) 204 | { 205 | return std::make_shared((void*)&value, MI_REAL32); 206 | } 207 | 208 | std::shared_ptr MIValue::FromReal64(MI_Real64 value) 209 | { 210 | return std::make_shared((void*)&value, MI_REAL64); 211 | } 212 | 213 | std::shared_ptr MIValue::FromString(const std::string& value) 214 | { 215 | auto self = std::make_shared(MI_STRING); 216 | self->CopyString(value); 217 | self->m_flags = 0; 218 | return self; 219 | } 220 | 221 | std::shared_ptr MIValue::FromString(const std::wstring& value) 222 | { 223 | auto self = std::make_shared(MI_STRING); 224 | self->CopyWString(value); 225 | self->m_flags = 0; 226 | return self; 227 | } 228 | 229 | MIValue::MIValue(MI_Type type) : m_type(type) 230 | { 231 | SetNullValue(); 232 | } 233 | 234 | std::shared_ptr MIValue::FromInstance(MI::Instance& value) 235 | { 236 | auto self = std::make_shared(MI_INSTANCE); 237 | self->m_value.instance = value.GetMIObject(); 238 | self->m_flags = 0; 239 | return self; 240 | } 241 | 242 | std::shared_ptr MIValue::FromReference(MI::Instance& value) 243 | { 244 | auto self = std::make_shared(MI_REFERENCE); 245 | self->m_value.reference = value.GetMIObject(); 246 | self->m_flags = 0; 247 | return self; 248 | } 249 | 250 | MIValue::MIValue(void* value, MI_Type type) : MIValue(type) 251 | { 252 | auto size = this->GetItemSize(type); 253 | memcpy_s(&m_value, size, value, size); 254 | m_flags = 0; 255 | } 256 | 257 | MIValue::~MIValue() 258 | { 259 | Delete(m_value, m_type); 260 | } 261 | -------------------------------------------------------------------------------- /MI/MIValue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace MI 6 | { 7 | class Instance; 8 | class OperationOptions; 9 | 10 | class MIValue 11 | { 12 | private: 13 | MI_Value m_value; 14 | MI_Type m_type; 15 | MI_Uint32 m_flags = 0; 16 | 17 | void Delete(MI_Value& value, MI_Type type); 18 | void SetNullValue(); 19 | void CopyString(const std::string& value); 20 | void CopyWString(const std::wstring& value); 21 | 22 | friend Instance; 23 | friend OperationOptions; 24 | 25 | public: 26 | static std::shared_ptr FromBoolean(MI_Boolean value); 27 | static std::shared_ptr FromSint8(MI_Sint8 value); 28 | static std::shared_ptr FromUint8(MI_Uint8 value); 29 | static std::shared_ptr FromSint16(MI_Sint16 value); 30 | static std::shared_ptr FromUint16(MI_Uint16 value); 31 | static std::shared_ptr FromChar16(MI_Char16 value); 32 | static std::shared_ptr FromSint32(MI_Sint32 value); 33 | static std::shared_ptr FromUint32(MI_Uint32 value); 34 | static std::shared_ptr FromSint64(MI_Sint64 value); 35 | static std::shared_ptr FromUint64(MI_Uint64 value); 36 | static std::shared_ptr FromReal32(MI_Real32 value); 37 | static std::shared_ptr FromReal64(MI_Real64 value); 38 | static std::shared_ptr FromString(const std::string& value); 39 | static std::shared_ptr FromString(const std::wstring& value); 40 | static std::shared_ptr FromInstance(MI::Instance& value); 41 | static std::shared_ptr FromReference(MI::Instance& value); 42 | static std::shared_ptr CreateArray(MI_Uint32 arraySize, MI_Type type); 43 | void SetArrayItem(const MIValue& value, MI_Uint32 index); 44 | 45 | MIValue(void* value, MI_Type type); 46 | MIValue(MI_Type type); 47 | MIValue(const MI_Value& value, MI_Type type, MI_Uint32 flags = 0) : m_value(value), m_type(type), m_flags(flags) {} 48 | virtual ~MIValue(); 49 | 50 | static unsigned GetItemSize(MI_Type valueType); 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /MI/PythonDir.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MI/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : MI Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this MI library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your MI application. 9 | 10 | 11 | MI.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | MI.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | StdAfx.h, StdAfx.cpp 28 | These files are used to build a precompiled header (PCH) file 29 | named MI.pch and a precompiled types file named StdAfx.obj. 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | Other notes: 33 | 34 | AppWizard uses "TODO:" comments to indicate parts of the source code you 35 | should add to or customize. 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | -------------------------------------------------------------------------------- /MI/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // MI.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /MI/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include -------------------------------------------------------------------------------- /MI/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #define _WIN32_WINNT 0x0a00 9 | 10 | #include 11 | -------------------------------------------------------------------------------- /PyMI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2000 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PyMI", "PyMI\PyMI.vcxproj", "{99CD5168-1D78-4584-A9DA-5ABF96FC89CF}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3} = {87DACAD9-74AA-46EE-AF08-BDB918FD13F3} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MI++", "MI\MI.vcxproj", "{87DACAD9-74AA-46EE-AF08-BDB918FD13F3}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug (Python 2.7)|x64 = Debug (Python 2.7)|x64 16 | Debug (Python 2.7)|x86 = Debug (Python 2.7)|x86 17 | Debug (Python 3.4)|x64 = Debug (Python 3.4)|x64 18 | Debug (Python 3.4)|x86 = Debug (Python 3.4)|x86 19 | Debug (Python 3.5)|x64 = Debug (Python 3.5)|x64 20 | Debug (Python 3.5)|x86 = Debug (Python 3.5)|x86 21 | Release (Python 2.7)|x64 = Release (Python 2.7)|x64 22 | Release (Python 2.7)|x86 = Release (Python 2.7)|x86 23 | Release (Python 3.4)|x64 = Release (Python 3.4)|x64 24 | Release (Python 3.4)|x86 = Release (Python 3.4)|x86 25 | Release (Python 3.5)|x64 = Release (Python 3.5)|x64 26 | Release (Python 3.5)|x86 = Release (Python 3.5)|x86 27 | Release (Python 3.6)|x64 = Release (Python 3.6)|x64 28 | Release (Python 3.6)|x86 = Release (Python 3.6)|x86 29 | Release (Python 3.7)|x64 = Release (Python 3.7)|x64 30 | Release (Python 3.7)|x86 = Release (Python 3.7)|x86 31 | EndGlobalSection 32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 33 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 2.7)|x64.ActiveCfg = Debug|x64 34 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 2.7)|x64.Build.0 = Debug|x64 35 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 2.7)|x86.ActiveCfg = Debug|Win32 36 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 2.7)|x86.Build.0 = Debug|Win32 37 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.4)|x64.ActiveCfg = Debug (Python 3.4)|x64 38 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.4)|x64.Build.0 = Debug (Python 3.4)|x64 39 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.4)|x86.ActiveCfg = Debug (Python 3.4)|Win32 40 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.4)|x86.Build.0 = Debug (Python 3.4)|Win32 41 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.5)|x64.ActiveCfg = Debug (Python 3.5)|x64 42 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.5)|x64.Build.0 = Debug (Python 3.5)|x64 43 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.5)|x86.ActiveCfg = Debug (Python 3.5)|Win32 44 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Debug (Python 3.5)|x86.Build.0 = Debug (Python 3.5)|Win32 45 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 2.7)|x64.ActiveCfg = Release|x64 46 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 2.7)|x64.Build.0 = Release|x64 47 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 2.7)|x86.ActiveCfg = Release|Win32 48 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 2.7)|x86.Build.0 = Release|Win32 49 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.4)|x64.ActiveCfg = Release (Python 3.4)|x64 50 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.4)|x64.Build.0 = Release (Python 3.4)|x64 51 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.4)|x86.ActiveCfg = Release (Python 3.4)|Win32 52 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.4)|x86.Build.0 = Release (Python 3.4)|Win32 53 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.5)|x64.ActiveCfg = Release (Python 3.5)|x64 54 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.5)|x64.Build.0 = Release (Python 3.5)|x64 55 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.5)|x86.ActiveCfg = Release (Python 3.5)|Win32 56 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.5)|x86.Build.0 = Release (Python 3.5)|Win32 57 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.6)|x64.ActiveCfg = Release (Python 3.6)|x64 58 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.6)|x64.Build.0 = Release (Python 3.6)|x64 59 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.6)|x86.ActiveCfg = Release (Python 3.6)|Win32 60 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.6)|x86.Build.0 = Release (Python 3.6)|Win32 61 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.7)|x64.ActiveCfg = Release (Python 3.7)|x64 62 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.7)|x64.Build.0 = Release (Python 3.7)|x64 63 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.7)|x86.ActiveCfg = Release (Python 3.7)|Win32 64 | {99CD5168-1D78-4584-A9DA-5ABF96FC89CF}.Release (Python 3.7)|x86.Build.0 = Release (Python 3.7)|Win32 65 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 2.7)|x64.ActiveCfg = Debug|x64 66 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 2.7)|x64.Build.0 = Debug|x64 67 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 2.7)|x86.ActiveCfg = Debug|Win32 68 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 2.7)|x86.Build.0 = Debug|Win32 69 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.4)|x64.ActiveCfg = Debug (Python 3.4)|x64 70 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.4)|x64.Build.0 = Debug (Python 3.4)|x64 71 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.4)|x86.ActiveCfg = Debug (Python 3.4)|Win32 72 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.4)|x86.Build.0 = Debug (Python 3.4)|Win32 73 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.5)|x64.ActiveCfg = Debug (Python 3.5)|x64 74 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.5)|x64.Build.0 = Debug (Python 3.5)|x64 75 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.5)|x86.ActiveCfg = Debug (Python 3.5)|Win32 76 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Debug (Python 3.5)|x86.Build.0 = Debug (Python 3.5)|Win32 77 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 2.7)|x64.ActiveCfg = Release|x64 78 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 2.7)|x64.Build.0 = Release|x64 79 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 2.7)|x86.ActiveCfg = Release|Win32 80 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 2.7)|x86.Build.0 = Release|Win32 81 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.4)|x64.ActiveCfg = Release (Python 3.4)|x64 82 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.4)|x64.Build.0 = Release (Python 3.4)|x64 83 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.4)|x86.ActiveCfg = Release (Python 3.4)|Win32 84 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.4)|x86.Build.0 = Release (Python 3.4)|Win32 85 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.5)|x64.ActiveCfg = Release (Python 3.5)|x64 86 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.5)|x64.Build.0 = Release (Python 3.5)|x64 87 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.5)|x86.ActiveCfg = Release (Python 3.5)|Win32 88 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.5)|x86.Build.0 = Release (Python 3.5)|Win32 89 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.6)|x64.ActiveCfg = Release (Python 3.6)|x64 90 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.6)|x64.Build.0 = Release (Python 3.6)|x64 91 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.6)|x86.ActiveCfg = Release (Python 3.6)|Win32 92 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.6)|x86.Build.0 = Release (Python 3.6)|Win32 93 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.7)|x64.ActiveCfg = Release (Python 3.7)|x64 94 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.7)|x64.Build.0 = Release (Python 3.7)|x64 95 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.7)|x86.ActiveCfg = Release (Python 3.7)|Win32 96 | {87DACAD9-74AA-46EE-AF08-BDB918FD13F3}.Release (Python 3.7)|x86.Build.0 = Release (Python 3.7)|Win32 97 | EndGlobalSection 98 | GlobalSection(SolutionProperties) = preSolution 99 | HideSolutionNode = FALSE 100 | EndGlobalSection 101 | GlobalSection(ExtensibilityGlobals) = postSolution 102 | SolutionGuid = {7BCA7706-CB41-4634-92EC-3DB937C8DB20} 103 | EndGlobalSection 104 | EndGlobal 105 | -------------------------------------------------------------------------------- /PyMI/Application.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Application.h" 3 | #include "Session.h" 4 | #include "Class.h" 5 | #include "Instance.h" 6 | #include "Serializer.h" 7 | #include "OperationOptions.h" 8 | #include "DestinationOptions.h" 9 | #include "Utils.h" 10 | 11 | 12 | static PyObject* Application_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 13 | { 14 | Application* self = NULL; 15 | self = (Application*)type->tp_alloc(type, 0); 16 | ::InitializeCriticalSection(&self->cs); 17 | return (PyObject *)self; 18 | } 19 | 20 | static int Application_init(Application *self, PyObject *args, PyObject *kwds) 21 | { 22 | char* appId = ""; 23 | static char *kwlist[] = { "app_id", NULL }; 24 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &appId)) 25 | return -1; 26 | 27 | try 28 | { 29 | AllowThreads(&self->cs, [&]() { 30 | self->app = std::make_shared(ToWstring(appId).c_str()); 31 | }); 32 | return 0; 33 | } 34 | catch (std::exception& ex) 35 | { 36 | SetPyException(ex); 37 | return -1; 38 | } 39 | } 40 | 41 | static PyObject* Application_NewSession(Application *self, PyObject *args, PyObject *kwds) 42 | { 43 | char* protocol = ""; 44 | char* computerName = "."; 45 | PyObject* destinationOptions = NULL; 46 | 47 | static char *kwlist[] = { "protocol", "computer_name", "destination_options", NULL }; 48 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssO", kwlist, &protocol, &computerName, &destinationOptions)) 49 | return NULL; 50 | 51 | try 52 | { 53 | if (!CheckPyNone(destinationOptions) && !PyObject_IsInstance(destinationOptions, reinterpret_cast(&DestinationOptionsType))) 54 | { 55 | throw MI::TypeConversionException(L"\"destination_options\" must have type DestinationOptions"); 56 | } 57 | 58 | std::shared_ptr session; 59 | AllowThreads(&self->cs, [&]() { 60 | session = self->app->NewSession(ToWstring(protocol).c_str(), ToWstring(computerName).c_str(), 61 | !CheckPyNone(destinationOptions) ? ((DestinationOptions*)destinationOptions)->destinationOptions : NULL); 62 | }); 63 | return (PyObject*)Session_New(session); 64 | } 65 | catch (std::exception& ex) 66 | { 67 | SetPyException(ex); 68 | return NULL; 69 | } 70 | } 71 | 72 | static void Application_dealloc(Application* self) 73 | { 74 | if (self->app) 75 | { 76 | AllowThreads(&self->cs, [&]() { 77 | self->app = NULL; 78 | }); 79 | } 80 | ::DeleteCriticalSection(&self->cs); 81 | Py_TYPE(self)->tp_free((PyObject*)self); 82 | } 83 | 84 | static PyObject* Application_NewMethodInboundParameters(Application *self, PyObject *args, PyObject *kwds) 85 | { 86 | PyObject* pyClass = NULL; 87 | char* methodName = NULL; 88 | 89 | static char *kwlist[] = { "mi_class", "method_name", NULL }; 90 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os", kwlist, &pyClass, &methodName)) 91 | return NULL; 92 | 93 | try 94 | { 95 | if (!PyObject_IsInstance(pyClass, reinterpret_cast(&ClassType))) 96 | throw MI::TypeConversionException(L"\"mi_class\" must have type Class"); 97 | 98 | std::shared_ptr instance; 99 | AllowThreads(&self->cs, [&]() { 100 | instance = self->app->NewMethodParamsInstance(*((Class*)pyClass)->miClass, ToWstring(methodName).c_str()); 101 | }); 102 | return (PyObject*)Instance_New(instance); 103 | } 104 | catch (std::exception& ex) 105 | { 106 | SetPyException(ex); 107 | return NULL; 108 | } 109 | } 110 | 111 | static PyObject* Application_NewInstance(Application *self, PyObject *args, PyObject *kwds) 112 | { 113 | char* className = NULL; 114 | static char *kwlist[] = { "class_name", NULL }; 115 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &className)) 116 | return NULL; 117 | 118 | try 119 | { 120 | std::shared_ptr instance; 121 | AllowThreads(&self->cs, [&]() { 122 | instance = self->app->NewInstance(ToWstring(className).c_str()); 123 | }); 124 | return (PyObject*)Instance_New(instance); 125 | } 126 | catch (std::exception& ex) 127 | { 128 | SetPyException(ex); 129 | return NULL; 130 | } 131 | } 132 | 133 | static PyObject* Application_NewInstanceFromClass(Application *self, PyObject *args, PyObject *kwds) 134 | { 135 | char* className = NULL; 136 | PyObject* miClass = NULL; 137 | static char *kwlist[] = { "class_name", "mi_class", NULL }; 138 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", kwlist, &className, &miClass)) 139 | return NULL; 140 | 141 | try 142 | { 143 | if (!PyObject_IsInstance(miClass, reinterpret_cast(&ClassType))) 144 | throw MI::TypeConversionException(L"\"mi_class\" must have type Class"); 145 | 146 | std::shared_ptr instance; 147 | AllowThreads(&self->cs, [&]() { 148 | instance = self->app->NewInstanceFromClass(ToWstring(className).c_str(), *((Class*)miClass)->miClass); 149 | }); 150 | return (PyObject*)Instance_New(instance); 151 | } 152 | catch (std::exception& ex) 153 | { 154 | SetPyException(ex); 155 | return NULL; 156 | } 157 | } 158 | 159 | static PyObject* Application_NewSerializer(Application* self, PyObject*) 160 | { 161 | try 162 | { 163 | std::shared_ptr serializer; 164 | AllowThreads(&self->cs, [&]() { 165 | serializer = self->app->NewSerializer(); 166 | }); 167 | return (PyObject*)Serializer_New(serializer); 168 | } 169 | catch (std::exception& ex) 170 | { 171 | SetPyException(ex); 172 | return NULL; 173 | } 174 | } 175 | 176 | static PyObject* Application_NewOperationOptions(Application* self, PyObject*) 177 | { 178 | try 179 | { 180 | std::shared_ptr operationOptions; 181 | AllowThreads(&self->cs, [&]() { 182 | operationOptions = self->app->NewOperationOptions(); 183 | }); 184 | return (PyObject*)OperationOptions_New(operationOptions); 185 | } 186 | catch (std::exception& ex) 187 | { 188 | SetPyException(ex); 189 | return NULL; 190 | } 191 | } 192 | 193 | static PyObject* Application_NewDestinationOptions(Application* self, PyObject*) 194 | { 195 | try 196 | { 197 | std::shared_ptr destinationOptions; 198 | AllowThreads(&self->cs, [&]() { 199 | destinationOptions = self->app->NewDestinationOptions(); 200 | }); 201 | return (PyObject*)DestinationOptions_New(destinationOptions); 202 | } 203 | catch (std::exception& ex) 204 | { 205 | SetPyException(ex); 206 | return NULL; 207 | } 208 | } 209 | 210 | static PyObject* Application_Close(Application *self, PyObject*) 211 | { 212 | try 213 | { 214 | AllowThreads(&self->cs, [&]() { 215 | self->app->Close(); 216 | }); 217 | Py_RETURN_NONE; 218 | } 219 | catch (std::exception& ex) 220 | { 221 | SetPyException(ex); 222 | return NULL; 223 | } 224 | } 225 | 226 | static PyObject* Application_self(Application *self, PyObject*) 227 | { 228 | Py_INCREF(self); 229 | return (PyObject *)self; 230 | } 231 | 232 | static PyObject* Application_exit(Application* self, PyObject*) 233 | { 234 | AllowThreads(&self->cs, [&]() { 235 | if (!self->app->IsClosed()) 236 | self->app->Close(); 237 | }); 238 | Py_RETURN_NONE; 239 | } 240 | 241 | static PyMemberDef Application_members[] = { 242 | { NULL } /* Sentinel */ 243 | }; 244 | 245 | static PyMethodDef Application_methods[] = { 246 | { "create_session", (PyCFunction)Application_NewSession, METH_VARARGS | METH_KEYWORDS, "Creates a new session." }, 247 | { "create_instance", (PyCFunction)Application_NewInstance, METH_VARARGS | METH_KEYWORDS, "Creates a new instance." }, 248 | { "create_instance_from_class", (PyCFunction)Application_NewInstanceFromClass, METH_VARARGS | METH_KEYWORDS, "Creates a new instance from a class." }, 249 | { "create_method_params", (PyCFunction)Application_NewMethodInboundParameters, METH_VARARGS | METH_KEYWORDS, "Creates a new __parameters instance with a method's inbound parameters." }, 250 | { "create_serializer", (PyCFunction)Application_NewSerializer, METH_NOARGS, "Creates a serializer." }, 251 | { "create_operation_options", (PyCFunction)Application_NewOperationOptions, METH_NOARGS, "Creates a new OperationObjects instance." }, 252 | { "create_destination_options", (PyCFunction)Application_NewDestinationOptions, METH_NOARGS, "Creates a new DestinationOptions instance."}, 253 | { "close", (PyCFunction)Application_Close, METH_NOARGS, "Closes the application." }, 254 | { "__enter__", (PyCFunction)Application_self, METH_NOARGS, "" }, 255 | { "__exit__", (PyCFunction)Application_exit, METH_VARARGS, "" }, 256 | { NULL } /* Sentinel */ 257 | }; 258 | 259 | PyTypeObject ApplicationType = { 260 | PyVarObject_HEAD_INIT(NULL, 0) 261 | "mi.Application", /*tp_name*/ 262 | sizeof(Application), /*tp_basicsize*/ 263 | 0, /*tp_itemsize*/ 264 | (destructor)Application_dealloc, /*tp_dealloc*/ 265 | 0, /*tp_print*/ 266 | 0, /*tp_getattr*/ 267 | 0, /*tp_setattr*/ 268 | 0, /*tp_compare*/ 269 | 0, /*tp_repr*/ 270 | 0, /*tp_as_number*/ 271 | 0, /*tp_as_sequence*/ 272 | 0, /*tp_as_mapping*/ 273 | 0, /*tp_hash */ 274 | 0, /*tp_call*/ 275 | 0, /*tp_str*/ 276 | 0, /*tp_getattro*/ 277 | 0, /*tp_setattro*/ 278 | 0, /*tp_as_buffer*/ 279 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 280 | "Application objects", /* tp_doc */ 281 | 0, /* tp_traverse */ 282 | 0, /* tp_clear */ 283 | 0, /* tp_richcompare */ 284 | 0, /* tp_weaklistoffset */ 285 | 0, /* tp_iter */ 286 | 0, /* tp_iternext */ 287 | Application_methods, /* tp_methods */ 288 | Application_members, /* tp_members */ 289 | 0, /* tp_getset */ 290 | 0, /* tp_base */ 291 | 0, /* tp_dict */ 292 | 0, /* tp_descr_get */ 293 | 0, /* tp_descr_set */ 294 | 0, /* tp_dictoffset */ 295 | (initproc)Application_init, /* tp_init */ 296 | 0, /* tp_alloc */ 297 | Application_new, /* tp_new */ 298 | }; 299 | -------------------------------------------------------------------------------- /PyMI/Application.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | /* Type-specific fields go here. */ 10 | std::shared_ptr app; 11 | CRITICAL_SECTION cs; 12 | } Application; 13 | 14 | extern PyTypeObject ApplicationType; 15 | -------------------------------------------------------------------------------- /PyMI/Callbacks.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Callbacks.h" 3 | #include "Instance.h" 4 | #include "Utils.h" 5 | #include "PyMI.h" 6 | 7 | 8 | PythonMICallbacks::PythonMICallbacks(PyObject* indicationResult) : m_indicationResult(indicationResult) 9 | { 10 | Py_XINCREF(m_indicationResult); 11 | } 12 | 13 | bool PythonMICallbacks::WriteError(std::shared_ptr operation, std::shared_ptr instance) 14 | { 15 | return true; 16 | } 17 | 18 | void PythonMICallbacks::IndicationResult(std::shared_ptr operation, std::shared_ptr instance, 19 | const std::wstring& bookmark, const std::wstring& machineID, bool moreResults, MI_Result resultCode, 20 | const std::wstring& errorString, std::shared_ptr errorDetails) 21 | { 22 | if (m_indicationResult) 23 | { 24 | PyGILState_STATE gstate = PyGILState_Ensure(); 25 | PyObject* instanceObj = NULL; 26 | PyObject* errorDetailsObj = NULL; 27 | 28 | try 29 | { 30 | if (instance) 31 | { 32 | instanceObj = (PyObject*)Instance_New(std::const_pointer_cast(instance)); 33 | } 34 | else 35 | { 36 | instanceObj = Py_None; 37 | Py_INCREF(Py_None); 38 | } 39 | 40 | if (errorDetails) 41 | { 42 | errorDetailsObj = (PyObject*)Instance_New(std::const_pointer_cast(errorDetails)); 43 | } 44 | else 45 | { 46 | errorDetailsObj = Py_None; 47 | Py_INCREF(Py_None); 48 | } 49 | 50 | CallPythonCallback(m_indicationResult, "(OuuIIuO)", instanceObj, bookmark.c_str(), machineID.c_str(), moreResults ? 1 : 0, 51 | resultCode, errorString.c_str(), errorDetailsObj); 52 | 53 | Py_DECREF(instanceObj); 54 | Py_DECREF(errorDetailsObj); 55 | PyGILState_Release(gstate); 56 | } 57 | catch (std::exception&) 58 | { 59 | Py_DECREF(instanceObj); 60 | Py_DECREF(errorDetailsObj); 61 | PyGILState_Release(gstate); 62 | throw; 63 | } 64 | } 65 | } 66 | 67 | PythonMICallbacks::~PythonMICallbacks() 68 | { 69 | Py_XDECREF(m_indicationResult); 70 | m_indicationResult = NULL; 71 | } 72 | -------------------------------------------------------------------------------- /PyMI/Callbacks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class PythonMICallbacks : public MI::Callbacks 8 | { 9 | private: 10 | PyObject* m_indicationResult = NULL; 11 | public: 12 | PythonMICallbacks(PyObject* indicationResult); 13 | bool WriteError(std::shared_ptr operation, std::shared_ptr instance); 14 | void IndicationResult(std::shared_ptr operation, std::shared_ptr instance, 15 | const std::wstring& bookmark, const std::wstring& machineID, bool moreResults, MI_Result resultCode, 16 | const std::wstring& errorString, std::shared_ptr errorDetails); 17 | ~PythonMICallbacks(); 18 | }; 19 | -------------------------------------------------------------------------------- /PyMI/Class.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Class.h" 3 | #include "Utils.h" 4 | #include "PyMI.h" 5 | 6 | 7 | static PyObject* Class_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 8 | { 9 | Class* self = NULL; 10 | self = (Class*)type->tp_alloc(type, 0); 11 | self->miClass = NULL; 12 | ::InitializeCriticalSection(&self->cs); 13 | return (PyObject *)self; 14 | } 15 | 16 | static int Class_init(Class* self, PyObject* args, PyObject* kwds) 17 | { 18 | PyErr_SetString(PyMIError, "A class object cannot be allocated directly."); 19 | return -1; 20 | } 21 | 22 | static void Class_dealloc(Class* self) 23 | { 24 | AllowThreads(&self->cs, [&]() { 25 | self->miClass = NULL; 26 | }); 27 | ::DeleteCriticalSection(&self->cs); 28 | Py_TYPE(self)->tp_free((PyObject*)self); 29 | } 30 | 31 | static PyObject* Class_subscript(Class *self, PyObject *item) 32 | { 33 | try 34 | { 35 | std::wstring name; 36 | Py_ssize_t i; 37 | GetIndexOrName(item, name, i); 38 | 39 | std::shared_ptr element; 40 | AllowThreads(&self->cs, [&]() { 41 | if (i >= 0) 42 | { 43 | element = (*self->miClass)[(unsigned)i]; 44 | } 45 | else 46 | { 47 | element = (*self->miClass)[name]; 48 | } 49 | }); 50 | return MI2Py(element->m_value, element->m_type, element->m_flags); 51 | } 52 | catch (std::exception& ex) 53 | { 54 | SetPyException(ex); 55 | return NULL; 56 | } 57 | } 58 | 59 | static Py_ssize_t Class_length(Class *self) 60 | { 61 | try 62 | { 63 | Py_ssize_t l = 0; 64 | AllowThreads(&self->cs, [&]() { 65 | l = self->miClass->GetElementsCount(); 66 | }); 67 | return l; 68 | } 69 | catch (std::exception& ex) 70 | { 71 | SetPyException(ex); 72 | return -1; 73 | } 74 | } 75 | 76 | static PyObject* Class_getattro(Class *self, PyObject* name) 77 | { 78 | PyObject* attr = PyObject_GenericGetAttr((PyObject*)self, name); 79 | if (attr) 80 | { 81 | return attr; 82 | } 83 | 84 | return Class_subscript(self, name); 85 | } 86 | 87 | Class* Class_New(std::shared_ptr miClass) 88 | { 89 | Class* obj = (Class*)Class_new(&ClassType, NULL, NULL); 90 | obj->miClass = miClass; 91 | return obj; 92 | } 93 | 94 | static PyObject* Class_Clone(Class* self, PyObject*) 95 | { 96 | try 97 | { 98 | std::shared_ptr miClass; 99 | AllowThreads(&self->cs, [&]() { 100 | miClass = self->miClass->Clone(); 101 | }); 102 | return (PyObject*)Class_New(miClass); 103 | } 104 | catch (std::exception& ex) 105 | { 106 | SetPyException(ex); 107 | return NULL; 108 | } 109 | } 110 | 111 | static PyObject* Class_GetClassName(Class* self, PyObject*) 112 | { 113 | try 114 | { 115 | std::wstring className = self->miClass->GetClassName(); 116 | return PyUnicode_FromWideChar(className.c_str(), className.length()); 117 | } 118 | catch (std::exception& ex) 119 | { 120 | SetPyException(ex); 121 | return NULL; 122 | } 123 | } 124 | 125 | static PyObject* Class_GetNameSpace(Class* self, PyObject*) 126 | { 127 | try 128 | { 129 | std::wstring nameSpace = self->miClass->GetNameSpace(); 130 | return PyUnicode_FromWideChar(nameSpace.c_str(), nameSpace.length()); 131 | } 132 | catch (std::exception& ex) 133 | { 134 | SetPyException(ex); 135 | return NULL; 136 | } 137 | } 138 | 139 | static PyObject* Class_GetServerName(Class* self, PyObject*) 140 | { 141 | try 142 | { 143 | std::wstring serverName = self->miClass->GetServerName(); 144 | return PyUnicode_FromWideChar(serverName.c_str(), serverName.length()); 145 | } 146 | catch (std::exception& ex) 147 | { 148 | SetPyException(ex); 149 | return NULL; 150 | } 151 | } 152 | 153 | static PyMemberDef Class_members[] = { 154 | { NULL } /* Sentinel */ 155 | }; 156 | 157 | static PyMethodDef Class_methods[] = { 158 | { "get_class_name", (PyCFunction)Class_GetClassName, METH_NOARGS, "" }, 159 | { "get_namespace", (PyCFunction)Class_GetNameSpace, METH_NOARGS, "" }, 160 | { "get_server_name", (PyCFunction)Class_GetServerName, METH_NOARGS, "" }, 161 | { "__getitem__", (PyCFunction)Class_subscript, METH_O | METH_COEXIST, "" }, 162 | { "clone", (PyCFunction)Class_Clone, METH_NOARGS, "Clones this class." }, 163 | { NULL } /* Sentinel */ 164 | }; 165 | 166 | static PyMappingMethods Class_as_mapping = { 167 | (lenfunc)Class_length, 168 | (binaryfunc)Class_subscript, 169 | NULL 170 | }; 171 | 172 | PyTypeObject ClassType = { 173 | PyVarObject_HEAD_INIT(NULL, 0) 174 | "mi.Class", /*tp_name*/ 175 | sizeof(Class), /*tp_basicsize*/ 176 | 0, /*tp_itemsize*/ 177 | (destructor)Class_dealloc, /*tp_dealloc*/ 178 | 0, /*tp_print*/ 179 | 0, /*tp_getattr*/ 180 | 0, /*tp_setattr*/ 181 | 0, /*tp_compare*/ 182 | 0, /*tp_repr*/ 183 | 0, /*tp_as_number*/ 184 | 0, /*tp_as_sequence*/ 185 | &Class_as_mapping, /*tp_as_mapping*/ 186 | 0, /*tp_hash */ 187 | 0, /*tp_call*/ 188 | 0, /*tp_str*/ 189 | (getattrofunc)Class_getattro, /*tp_getattro*/ 190 | 0, /*tp_setattro*/ 191 | 0, /*tp_as_buffer*/ 192 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 193 | "Class objects", /* tp_doc */ 194 | 0, /* tp_traverse */ 195 | 0, /* tp_clear */ 196 | 0, /* tp_richcompare */ 197 | 0, /* tp_weaklistoffset */ 198 | 0, /* tp_iter */ 199 | 0, /* tp_iternext */ 200 | Class_methods, /* tp_methods */ 201 | Class_members, /* tp_members */ 202 | 0, /* tp_getset */ 203 | 0, /* tp_base */ 204 | 0, /* tp_dict */ 205 | 0, /* tp_descr_get */ 206 | 0, /* tp_descr_set */ 207 | 0, /* tp_dictoffset */ 208 | (initproc)Class_init, /* tp_init */ 209 | 0, /* tp_alloc */ 210 | Class_new, /* tp_new */ 211 | }; 212 | 213 | -------------------------------------------------------------------------------- /PyMI/Class.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | /* Type-specific fields go here. */ 10 | std::shared_ptr miClass; 11 | CRITICAL_SECTION cs; 12 | } Class; 13 | 14 | extern PyTypeObject ClassType; 15 | 16 | Class* Class_New(std::shared_ptr miClass); 17 | -------------------------------------------------------------------------------- /PyMI/DestinationOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "DestinationOptions.h" 3 | #include "PyMI.h" 4 | #include "Utils.h" 5 | 6 | #include 7 | 8 | 9 | static PyObject* DestinationOptions_new(PyTypeObject* type, PyObject* args, PyObject* kwds) 10 | { 11 | DestinationOptions* self = NULL; 12 | sizeof(DestinationOptions); 13 | self = (DestinationOptions*)type->tp_alloc(type, 0); 14 | self->destinationOptions = NULL; 15 | ::InitializeCriticalSection(&self->cs); 16 | return (PyObject *)self; 17 | } 18 | 19 | static int DestinationOptions_init(DestinationOptions* self, PyObject* args, PyObject* kwds) 20 | { 21 | PyErr_SetString(PyMIError, "An DestinationOptions object cannot be allocated directly."); 22 | return -1; 23 | } 24 | 25 | static void DestinationOptions_dealloc(DestinationOptions* self) 26 | { 27 | AllowThreads(&self->cs, [&]() { 28 | self->destinationOptions = NULL; 29 | }); 30 | ::DeleteCriticalSection(&self->cs); 31 | Py_TYPE(self)->tp_free((PyObject*)self); 32 | } 33 | 34 | DestinationOptions* DestinationOptions_New(std::shared_ptr destinationOptions) 35 | { 36 | DestinationOptions* obj = (DestinationOptions*)DestinationOptions_new(&DestinationOptionsType, NULL, NULL); 37 | obj->destinationOptions = destinationOptions; 38 | return obj; 39 | } 40 | 41 | static PyObject* DestinationOptions_Clone(DestinationOptions *self, PyObject*) 42 | { 43 | try 44 | { 45 | std::shared_ptr destinationOptions; 46 | AllowThreads(&self->cs, [&]() { 47 | destinationOptions = self->destinationOptions->Clone(); 48 | }); 49 | return (PyObject*)DestinationOptions_New(destinationOptions); 50 | } 51 | catch (std::exception& ex) 52 | { 53 | SetPyException(ex); 54 | return NULL; 55 | } 56 | } 57 | 58 | static PyObject* DestinationOptions_GetUILocale(DestinationOptions* self) 59 | { 60 | try 61 | { 62 | std::wstring locale; 63 | AllowThreads(&self->cs, [&]() { 64 | locale = self->destinationOptions->GetUILocale(); 65 | }); 66 | const std::string sTmp(locale.begin(), locale.end()); 67 | return PyUnicode_FromString(sTmp.c_str()); 68 | } 69 | catch (std::exception& ex) 70 | { 71 | SetPyException(ex); 72 | return NULL; 73 | } 74 | } 75 | 76 | static PyObject* DestinationOptions_SetUILocale(DestinationOptions* self, PyObject *args, PyObject *kwds) 77 | { 78 | char* locale = NULL; 79 | static char *kwlist[] = { "locale_name", NULL }; 80 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &locale)) 81 | return NULL; 82 | 83 | try 84 | { 85 | AllowThreads(&self->cs, [&]() { 86 | self->destinationOptions->SetUILocale(ToWstring(locale).c_str()); 87 | }); 88 | Py_RETURN_NONE; 89 | } 90 | catch (std::exception& ex) 91 | { 92 | SetPyException(ex); 93 | return NULL; 94 | } 95 | } 96 | 97 | static PyObject* DestinationOptions_GetTimeout(DestinationOptions* self, PyObject* timeout) 98 | { 99 | try 100 | { 101 | MI_Interval interval; 102 | AllowThreads(&self->cs, [&]() { 103 | interval = self->destinationOptions->GetTimeout(); 104 | }); 105 | return PyDeltaFromMIInterval(interval); 106 | } 107 | catch (std::exception& ex) 108 | { 109 | SetPyException(ex); 110 | return NULL; 111 | } 112 | } 113 | 114 | static PyObject* DestinationOptions_SetTimeout(DestinationOptions* self, PyObject* timeout) 115 | { 116 | PyDateTime_IMPORT; 117 | 118 | if (!PyDelta_Check(timeout)) 119 | { 120 | PyErr_SetString(PyExc_TypeError, "parameter timeout must be of type datetime.timedelta"); 121 | return NULL; 122 | } 123 | 124 | try 125 | { 126 | MI_Interval miTimeout; 127 | MIIntervalFromPyDelta(timeout, miTimeout); 128 | AllowThreads(&self->cs, [&]() { 129 | self->destinationOptions->SetTimeout(miTimeout); 130 | }); 131 | Py_RETURN_NONE; 132 | } 133 | catch (std::exception& ex) 134 | { 135 | SetPyException(ex); 136 | return NULL; 137 | } 138 | } 139 | 140 | static PyObject* DestinationOptions_SetTransport(DestinationOptions* self, PyObject *args, PyObject *kwds) 141 | { 142 | char* transport = NULL; 143 | static char *kwlist[] = { "transport", NULL }; 144 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &transport)) 145 | return NULL; 146 | 147 | try 148 | { 149 | AllowThreads(&self->cs, [&]() { 150 | self->destinationOptions->SetTransport(ToWstring(transport).c_str()); 151 | }); 152 | Py_RETURN_NONE; 153 | } 154 | catch (std::exception& ex) 155 | { 156 | SetPyException(ex); 157 | return NULL; 158 | } 159 | } 160 | 161 | static PyObject* DestinationOptions_GetTransport(DestinationOptions* self) 162 | { 163 | try 164 | { 165 | std::wstring transport; 166 | AllowThreads(&self->cs, [&]() { 167 | transport = self->destinationOptions->GetTransport(); 168 | }); 169 | const std::string sTmp(transport.begin(), transport.end()); 170 | return PyUnicode_FromString(sTmp.c_str()); 171 | } 172 | catch (std::exception& ex) 173 | { 174 | SetPyException(ex); 175 | return NULL; 176 | } 177 | } 178 | 179 | static PyObject* DestinationOptions_AddCredentials(DestinationOptions* self, PyObject *args, PyObject *kwds) 180 | { 181 | char* authType = NULL; 182 | char* domain = NULL; 183 | char* username = NULL; 184 | char* password = NULL; 185 | char* certThumbprint = NULL; 186 | 187 | static char *kwlist[] = { "auth_type", "domain", "username", "password", "cert_thumbprint", NULL }; 188 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ssss", kwlist, 189 | &authType, &domain, &username, &password, &certThumbprint)) 190 | return NULL; 191 | 192 | try 193 | { 194 | if (ToWstring(certThumbprint).c_str() && wcslen(ToWstring(certThumbprint).c_str())) 195 | AllowThreads(&self->cs, [&]() { 196 | self->destinationOptions->AddCredentials(ToWstring(authType).c_str(), ToWstring(certThumbprint).c_str()); 197 | }); 198 | else 199 | AllowThreads(&self->cs, [&]() { 200 | self->destinationOptions->AddCredentials(ToWstring(authType).c_str(), ToWstring(domain).c_str(), ToWstring(username).c_str(), ToWstring(password).c_str()); 201 | }); 202 | Py_RETURN_NONE; 203 | } 204 | catch (std::exception& ex) 205 | { 206 | SetPyException(ex); 207 | return NULL; 208 | } 209 | } 210 | 211 | 212 | static PyMemberDef DestinationOptions_members[] = { 213 | { NULL } /* Sentinel */ 214 | }; 215 | 216 | static PyMethodDef DestinationOptions_methods[] = { 217 | { "clone", (PyCFunction)DestinationOptions_Clone, METH_NOARGS, "Clones the DestinationOptions." }, 218 | { "get_ui_locale", (PyCFunction)DestinationOptions_GetUILocale, METH_NOARGS, "Returns the UI locale." }, 219 | { "set_ui_locale", (PyCFunction)DestinationOptions_SetUILocale, METH_VARARGS | METH_KEYWORDS, "Sets the UI locale." }, 220 | { "get_transport", (PyCFunction)DestinationOptions_GetTransport, METH_VARARGS | METH_KEYWORDS, "Gets the transport protocol." }, 221 | { "set_transport", (PyCFunction)DestinationOptions_SetTransport, METH_VARARGS | METH_KEYWORDS, "Sets the transport protocol." }, 222 | { "get_timeout", (PyCFunction)DestinationOptions_GetTimeout, METH_NOARGS, "Returns the default operation timeout." }, 223 | { "set_timeout", (PyCFunction)DestinationOptions_SetTimeout, METH_O, "Sets the default operation timeout." }, 224 | { "add_credentials", (PyCFunction)DestinationOptions_AddCredentials, METH_VARARGS | METH_KEYWORDS, "Adds credentials." }, 225 | { NULL } /* Sentinel */ 226 | }; 227 | 228 | PyTypeObject DestinationOptionsType = { 229 | PyVarObject_HEAD_INIT(NULL, 0) 230 | "mi.destinationoptions", /*tp_name*/ 231 | sizeof(DestinationOptions), /*tp_basicsize*/ 232 | 0, /*tp_itemsize*/ 233 | (destructor)DestinationOptions_dealloc, /*tp_dealloc*/ 234 | 0, /*tp_print*/ 235 | 0, /*tp_getattr*/ 236 | 0, /*tp_setattr*/ 237 | 0, /*tp_compare*/ 238 | 0, /*tp_repr*/ 239 | 0, /*tp_as_number*/ 240 | 0, /*tp_as_sequence*/ 241 | 0, /*tp_as_mapping*/ 242 | 0, /*tp_hash */ 243 | 0, /*tp_call*/ 244 | 0, /*tp_str*/ 245 | 0, /*tp_getattro*/ 246 | 0, /*tp_setattro*/ 247 | 0, /*tp_as_buffer*/ 248 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 249 | "DestinationOptions objects", /* tp_doc */ 250 | 0, /* tp_traverse */ 251 | 0, /* tp_clear */ 252 | 0, /* tp_richcompare */ 253 | 0, /* tp_weaklistoffset */ 254 | 0, /* tp_iter */ 255 | 0, /* tp_iternext */ 256 | DestinationOptions_methods, /* tp_methods */ 257 | DestinationOptions_members, /* tp_members */ 258 | 0, /* tp_getset */ 259 | 0, /* tp_base */ 260 | 0, /* tp_dict */ 261 | 0, /* tp_descr_get */ 262 | 0, /* tp_descr_set */ 263 | 0, /* tp_dictoffset */ 264 | (initproc)DestinationOptions_init, /* tp_init */ 265 | 0, /* tp_alloc */ 266 | DestinationOptions_new, /* tp_new */ 267 | }; 268 | -------------------------------------------------------------------------------- /PyMI/DestinationOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | /* Type-specific fields go here. */ 10 | std::shared_ptr destinationOptions; 11 | CRITICAL_SECTION cs; 12 | } DestinationOptions; 13 | 14 | extern PyTypeObject DestinationOptionsType; 15 | 16 | DestinationOptions* DestinationOptions_New(std::shared_ptr destinationOptions); 17 | 18 | -------------------------------------------------------------------------------- /PyMI/Instance.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Instance.h" 3 | #include "Class.h" 4 | #include "Utils.h" 5 | #include "PyMI.h" 6 | 7 | 8 | static PyObject* Instance_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 9 | { 10 | Instance* self = NULL; 11 | self = (Instance*)type->tp_alloc(type, 0); 12 | self->instance = NULL; 13 | ::InitializeCriticalSection(&self->cs); 14 | return (PyObject *)self; 15 | } 16 | 17 | static int Instance_init(Instance* self, PyObject* args, PyObject* kwds) 18 | { 19 | PyErr_SetString(PyMIError, "An Instance object cannot be allocated directly."); 20 | return -1; 21 | } 22 | 23 | static void Instance_dealloc(Instance* self) 24 | { 25 | AllowThreads(&self->cs, [&]() { 26 | self->instance = NULL; 27 | }); 28 | ::DeleteCriticalSection(&self->cs); 29 | Py_TYPE(self)->tp_free((PyObject*)self); 30 | } 31 | 32 | std::shared_ptr GetElement(Instance *self, PyObject *item) 33 | { 34 | std::wstring name; 35 | Py_ssize_t i; 36 | GetIndexOrName(item, name, i); 37 | 38 | std::shared_ptr element; 39 | AllowThreads(&self->cs, [&]() { 40 | if (i >= 0) 41 | { 42 | element = (*self->instance)[(unsigned)i]; 43 | } 44 | else 45 | { 46 | element = (*self->instance)[name]; 47 | } 48 | }); 49 | return element; 50 | } 51 | 52 | static PyObject* Instance_subscript(Instance *self, PyObject *item) 53 | { 54 | try 55 | { 56 | auto element = GetElement(self, item); 57 | return MI2Py(element->m_value, element->m_type, element->m_flags); 58 | } 59 | catch (std::exception& ex) 60 | { 61 | SetPyException(ex); 62 | return NULL; 63 | } 64 | } 65 | 66 | static PyObject* Instance_GetElement(Instance *self, PyObject *item) 67 | { 68 | try 69 | { 70 | auto element = GetElement(self, item); 71 | PyObject* tuple = PyTuple_New(3); 72 | PyTuple_SetItem(tuple, 0, PyUnicode_FromWideChar(element->m_name.c_str(), element->m_name.length())); 73 | #ifdef IS_PY3K 74 | PyTuple_SetItem(tuple, 1, PyLong_FromLong(element->m_type)); 75 | #else 76 | PyTuple_SetItem(tuple, 1, PyInt_FromLong(element->m_type)); 77 | #endif 78 | PyTuple_SetItem(tuple, 2, MI2Py(element->m_value, element->m_type, element->m_flags)); 79 | return tuple; 80 | } 81 | catch (std::exception& ex) 82 | { 83 | SetPyException(ex); 84 | return NULL; 85 | } 86 | } 87 | 88 | static Py_ssize_t Instance_length(Instance *self) 89 | { 90 | try 91 | { 92 | Py_ssize_t l = 0; 93 | AllowThreads(&self->cs, [&]() { 94 | l = self->instance->GetElementsCount(); 95 | }); 96 | return l; 97 | } 98 | catch (std::exception& ex) 99 | { 100 | SetPyException(ex); 101 | return -1; 102 | } 103 | } 104 | 105 | static int Instance_ass_subscript(Instance* self, PyObject* item, PyObject* value) 106 | { 107 | try 108 | { 109 | std::wstring name; 110 | Py_ssize_t i = 0; 111 | GetIndexOrName(item, name, i); 112 | 113 | MI_Type miType; 114 | AllowThreads(&self->cs, [&]() { 115 | if (i >= 0) 116 | { 117 | miType = self->instance->GetElementType((unsigned)i); 118 | } 119 | else 120 | { 121 | miType = self->instance->GetElementType(name); 122 | } 123 | }); 124 | 125 | auto miValue = Py2MI(value, miType); 126 | 127 | AllowThreads(&self->cs, [&]() { 128 | if (i >= 0) 129 | { 130 | self->instance->SetElement((unsigned)i, *miValue); 131 | } 132 | else 133 | { 134 | self->instance->SetElement(name, *miValue); 135 | } 136 | }); 137 | 138 | return 0; 139 | } 140 | catch (std::exception& ex) 141 | { 142 | SetPyException(ex); 143 | return -1; 144 | } 145 | } 146 | 147 | static PyObject* Instance_getattro(Instance *self, PyObject* name) 148 | { 149 | PyObject* attr = PyObject_GenericGetAttr((PyObject*)self, name); 150 | if (attr) 151 | { 152 | return attr; 153 | } 154 | 155 | return Instance_subscript(self, name); 156 | } 157 | 158 | static int Instance_setattro(Instance *self, PyObject* name, PyObject* value) 159 | { 160 | return -1; 161 | } 162 | 163 | static PyObject* Instance_GetClass(Instance *self, PyObject*) 164 | { 165 | try 166 | { 167 | std::shared_ptr c; 168 | AllowThreads(&self->cs, [&]() { 169 | c = self->instance->GetClass(); 170 | }); 171 | return (PyObject*)Class_New(c); 172 | } 173 | catch (std::exception& ex) 174 | { 175 | SetPyException(ex); 176 | return NULL; 177 | } 178 | } 179 | 180 | static PyObject* Instance_Clone(Instance *self, PyObject*) 181 | { 182 | try 183 | { 184 | std::shared_ptr instance; 185 | AllowThreads(&self->cs, [&]() { 186 | instance = self->instance->Clone(); 187 | }); 188 | return (PyObject*)Instance_New(instance); 189 | } 190 | catch (std::exception& ex) 191 | { 192 | SetPyException(ex); 193 | return NULL; 194 | } 195 | } 196 | 197 | static PyObject* Instance_GetPath(Instance *self, PyObject*) 198 | { 199 | try 200 | { 201 | std::wstring path = self->instance->GetPath(); 202 | return PyUnicode_FromWideChar(path.c_str(), path.length()); 203 | } 204 | catch (std::exception& ex) 205 | { 206 | SetPyException(ex); 207 | return NULL; 208 | } 209 | } 210 | 211 | static PyObject* Instance_GetClassName(Instance *self, PyObject*) 212 | { 213 | try 214 | { 215 | std::wstring className = self->instance->GetClassName(); 216 | return PyUnicode_FromWideChar(className.c_str(), className.length()); 217 | } 218 | catch (std::exception& ex) 219 | { 220 | SetPyException(ex); 221 | return NULL; 222 | } 223 | } 224 | 225 | static PyObject* Instance_GetNameSpace(Instance* self, PyObject*) 226 | { 227 | try 228 | { 229 | std::wstring nameSpace = self->instance->GetNameSpace(); 230 | return PyUnicode_FromWideChar(nameSpace.c_str(), nameSpace.length()); 231 | } 232 | catch (std::exception& ex) 233 | { 234 | SetPyException(ex); 235 | return NULL; 236 | } 237 | } 238 | 239 | static PyObject* Instance_GetServerName(Instance* self, PyObject*) 240 | { 241 | try 242 | { 243 | std::wstring serverName = self->instance->GetServerName(); 244 | return PyUnicode_FromWideChar(serverName.c_str(), serverName.length()); 245 | } 246 | catch (std::exception& ex) 247 | { 248 | SetPyException(ex); 249 | return NULL; 250 | } 251 | } 252 | 253 | Instance* Instance_New(std::shared_ptr instance) 254 | { 255 | Instance* obj = (Instance*)Instance_new(&InstanceType, NULL, NULL); 256 | obj->instance = instance; 257 | return obj; 258 | } 259 | 260 | static PyMemberDef Instance_members[] = { 261 | { NULL } /* Sentinel */ 262 | }; 263 | 264 | static PyMethodDef Instance_methods[] = { 265 | { "__getitem__", (PyCFunction)Instance_subscript, METH_O | METH_COEXIST, "" }, 266 | { "get_element", (PyCFunction)Instance_GetElement, METH_O, "Returns an element by either index or name" }, 267 | { "get_path", (PyCFunction)Instance_GetPath, METH_NOARGS, "" }, 268 | { "get_class_name", (PyCFunction)Instance_GetClassName, METH_NOARGS, "" }, 269 | { "get_namespace", (PyCFunction)Instance_GetNameSpace, METH_NOARGS, "" }, 270 | { "get_server_name", (PyCFunction)Instance_GetServerName, METH_NOARGS, "" }, 271 | { "get_class", (PyCFunction)Instance_GetClass, METH_NOARGS, "" }, 272 | { "clone", (PyCFunction)Instance_Clone, METH_NOARGS, "Clones this instance." }, 273 | { NULL } /* Sentinel */ 274 | }; 275 | 276 | static PyMappingMethods Instance_as_mapping = { 277 | (lenfunc)Instance_length, 278 | (binaryfunc)Instance_subscript, 279 | (objobjargproc)Instance_ass_subscript 280 | }; 281 | 282 | PyTypeObject InstanceType = { 283 | PyVarObject_HEAD_INIT(NULL, 0) 284 | "mi.Instance", /*tp_name*/ 285 | sizeof(Instance), /*tp_basicsize*/ 286 | 0, /*tp_itemsize*/ 287 | (destructor)Instance_dealloc, /*tp_dealloc*/ 288 | 0, /*tp_print*/ 289 | 0, /*tp_getattr*/ 290 | 0, /*tp_setattr*/ 291 | 0, /*tp_compare*/ 292 | 0, /*tp_repr*/ 293 | 0, /*tp_as_number*/ 294 | 0, /*tp_as_sequence*/ 295 | &Instance_as_mapping, /*tp_as_mapping*/ 296 | 0, /*tp_hash */ 297 | 0, /*tp_call*/ 298 | 0, /*tp_str*/ 299 | (getattrofunc)Instance_getattro, /*tp_getattro*/ 300 | (setattrofunc)Instance_setattro, /*tp_setattro*/ 301 | 0, /*tp_as_buffer*/ 302 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 303 | "Instance objects", /* tp_doc */ 304 | 0, /* tp_traverse */ 305 | 0, /* tp_clear */ 306 | 0, /* tp_richcompare */ 307 | 0, /* tp_weaklistoffset */ 308 | 0, /* tp_iter */ 309 | 0, /* tp_iternext */ 310 | Instance_methods, /* tp_methods */ 311 | Instance_members, /* tp_members */ 312 | 0, /* tp_getset */ 313 | 0, /* tp_base */ 314 | 0, /* tp_dict */ 315 | 0, /* tp_descr_get */ 316 | 0, /* tp_descr_set */ 317 | 0, /* tp_dictoffset */ 318 | (initproc)Instance_init, /* tp_init */ 319 | 0, /* tp_alloc */ 320 | Instance_new, /* tp_new */ 321 | }; 322 | -------------------------------------------------------------------------------- /PyMI/Instance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | /* Type-specific fields go here. */ 10 | std::shared_ptr instance; 11 | CRITICAL_SECTION cs; 12 | } Instance; 13 | 14 | extern PyTypeObject InstanceType; 15 | 16 | Instance* Instance_New(std::shared_ptr instance); 17 | -------------------------------------------------------------------------------- /PyMI/MiError.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "MiError.h" 3 | #include "PyMI.h" 4 | 5 | #include 6 | 7 | PyObject* MiError_Init(void) 8 | { 9 | PyObject* m = NULL; 10 | 11 | #ifdef IS_PY3K 12 | m = PyModule_Create(&mi_error_module); 13 | if (m == NULL) 14 | return NULL; 15 | #else 16 | m = Py_InitModule3("mi_error", mi_error_methods, "MI errors module."); 17 | if (m == NULL) 18 | return NULL; 19 | #endif 20 | 21 | for (int i = 0; i < sizeof(MI::MI_RESULT_STRINGS) / sizeof(MI::MI_RESULT_STRINGS[0]); i++) 22 | { 23 | PyObject* err_str = PyUnicode_FromWideChar(MI::MI_RESULT_STRINGS[i], 24 | wcslen(MI::MI_RESULT_STRINGS[i])); 25 | PyObject* err_code = PyLong_FromLong(i); 26 | PyObject_SetAttr(m, err_str, err_code); 27 | } 28 | 29 | return m; 30 | } 31 | -------------------------------------------------------------------------------- /PyMI/MiError.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | static PyMethodDef mi_error_methods[] = { 7 | { NULL, NULL, 0, NULL } /* Sentinel */ 8 | }; 9 | 10 | #ifdef IS_PY3K 11 | static PyModuleDef mi_error_module = { 12 | PyModuleDef_HEAD_INIT, 13 | "mi_error", 14 | "MI errors module.", 15 | -1, 16 | mi_error_methods 17 | }; 18 | #endif 19 | 20 | PyObject* MiError_Init(void); 21 | -------------------------------------------------------------------------------- /PyMI/Operation.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Operation.h" 3 | #include "Instance.h" 4 | #include "Class.h" 5 | #include "Utils.h" 6 | #include "PyMI.h" 7 | 8 | 9 | static PyObject* Operation_new(PyTypeObject* type, PyObject* args, PyObject* kwds) 10 | { 11 | Operation* self = NULL; 12 | self = (Operation*)type->tp_alloc(type, 0); 13 | self->operation = NULL; 14 | ::InitializeCriticalSection(&self->cs); 15 | return (PyObject *)self; 16 | } 17 | 18 | static int Operation_init(Operation* self, PyObject* args, PyObject* kwds) 19 | { 20 | PyErr_SetString(PyMIError, "An Operation object cannot be allocated directly."); 21 | return -1; 22 | } 23 | 24 | static void Operation_dealloc(Operation* self) 25 | { 26 | AllowThreads(&self->cs, [&]() { 27 | self->operation = NULL; 28 | }); 29 | ::DeleteCriticalSection(&self->cs); 30 | Py_TYPE(self)->tp_free((PyObject*)self); 31 | } 32 | 33 | static PyObject* Operation_Cancel(Operation* self, PyObject*) 34 | { 35 | try 36 | { 37 | AllowThreads(&self->cs, [&]() { 38 | self->operation->Cancel(); 39 | }); 40 | Py_RETURN_NONE; 41 | } 42 | catch (std::exception& ex) 43 | { 44 | SetPyException(ex); 45 | return NULL; 46 | } 47 | } 48 | 49 | static PyObject* Operation_GetNextInstance(Operation* self, PyObject*) 50 | { 51 | try 52 | { 53 | std::shared_ptr instance; 54 | AllowThreads(&self->cs, [&]() { 55 | instance = self->operation->GetNextInstance(); 56 | }); 57 | if (instance) 58 | { 59 | return (PyObject*)Instance_New(instance); 60 | } 61 | Py_RETURN_NONE; 62 | } 63 | catch (std::exception& ex) 64 | { 65 | SetPyException(ex); 66 | return NULL; 67 | } 68 | } 69 | 70 | static PyObject* Operation_GetNextIndication(Operation* self, PyObject*) 71 | { 72 | try 73 | { 74 | std::shared_ptr instance; 75 | AllowThreads(&self->cs, [&]() { 76 | instance = self->operation->GetNextIndication(); 77 | }); 78 | if (instance) 79 | { 80 | return (PyObject*)Instance_New(instance); 81 | } 82 | Py_RETURN_NONE; 83 | } 84 | catch (std::exception& ex) 85 | { 86 | SetPyException(ex); 87 | return NULL; 88 | } 89 | } 90 | 91 | static PyObject* Operation_GetNextClass(Operation* self, PyObject*) 92 | { 93 | try 94 | { 95 | std::shared_ptr miClass; 96 | AllowThreads(&self->cs, [&]() { 97 | miClass = self->operation->GetNextClass(); 98 | }); 99 | if (miClass) 100 | { 101 | return (PyObject*)Class_New(miClass); 102 | } 103 | Py_RETURN_NONE; 104 | } 105 | catch (std::exception& ex) 106 | { 107 | SetPyException(ex); 108 | return NULL; 109 | } 110 | } 111 | 112 | static PyObject* Operation_HasMoreResults(Operation* self, PyObject*) 113 | { 114 | try 115 | { 116 | if (self->operation->HasMoreResults()) 117 | { 118 | Py_RETURN_TRUE; 119 | } 120 | else 121 | { 122 | Py_RETURN_FALSE; 123 | } 124 | } 125 | catch (std::exception& ex) 126 | { 127 | SetPyException(ex); 128 | return NULL; 129 | } 130 | } 131 | 132 | 133 | static PyObject* Operation_Close(Operation *self, PyObject*) 134 | { 135 | try 136 | { 137 | self->operation->Close(); 138 | Py_RETURN_NONE; 139 | } 140 | catch (std::exception& ex) 141 | { 142 | SetPyException(ex); 143 | return NULL; 144 | } 145 | } 146 | 147 | static PyObject* Operation_self(Operation *self, PyObject*) 148 | { 149 | Py_INCREF(self); 150 | return (PyObject *)self; 151 | } 152 | 153 | static PyObject* Operation_exit(Operation* self, PyObject*) 154 | { 155 | AllowThreads(&self->cs, [&]() { 156 | if (!self->operation->IsClosed()) 157 | self->operation->Close(); 158 | }); 159 | Py_RETURN_NONE; 160 | } 161 | 162 | Operation* Operation_New(std::shared_ptr operation) 163 | { 164 | Operation* obj = (Operation*)Operation_new(&OperationType, NULL, NULL); 165 | obj->operation = operation; 166 | return obj; 167 | } 168 | 169 | static PyMemberDef Operation_members[] = { 170 | { NULL } /* Sentinel */ 171 | }; 172 | 173 | static PyMethodDef Operation_methods[] = { 174 | { "get_next_instance", (PyCFunction)Operation_GetNextInstance, METH_NOARGS, "Returns the next instance." }, 175 | { "get_next_class", (PyCFunction)Operation_GetNextClass, METH_NOARGS, "Returns the next class." }, 176 | { "get_next_indication", (PyCFunction)Operation_GetNextIndication, METH_NOARGS, "Returns the next result from a subscription." }, 177 | { "has_more_results", (PyCFunction)Operation_HasMoreResults, METH_NOARGS, "Returns whether the current operation has more results." }, 178 | { "cancel", (PyCFunction)Operation_Cancel, METH_NOARGS, "Cancels the operation." }, 179 | { "close", (PyCFunction)Operation_Close, METH_NOARGS, "Closes the operation." }, 180 | { "__enter__", (PyCFunction)Operation_self, METH_NOARGS, "" }, 181 | { "__exit__", (PyCFunction)Operation_exit, METH_VARARGS, "" }, 182 | { NULL } /* Sentinel */ 183 | }; 184 | 185 | PyTypeObject OperationType = { 186 | PyVarObject_HEAD_INIT(NULL, 0) 187 | "mi.operation", /*tp_name*/ 188 | sizeof(Operation), /*tp_basicsize*/ 189 | 0, /*tp_itemsize*/ 190 | (destructor)Operation_dealloc, /*tp_dealloc*/ 191 | 0, /*tp_print*/ 192 | 0, /*tp_getattr*/ 193 | 0, /*tp_setattr*/ 194 | 0, /*tp_compare*/ 195 | 0, /*tp_repr*/ 196 | 0, /*tp_as_number*/ 197 | 0, /*tp_as_sequence*/ 198 | 0, /*tp_as_mapping*/ 199 | 0, /*tp_hash */ 200 | 0, /*tp_call*/ 201 | 0, /*tp_str*/ 202 | 0, /*tp_getattro*/ 203 | 0, /*tp_setattro*/ 204 | 0, /*tp_as_buffer*/ 205 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 206 | "Operation objects", /* tp_doc */ 207 | 0, /* tp_traverse */ 208 | 0, /* tp_clear */ 209 | 0, /* tp_richcompare */ 210 | 0, /* tp_weaklistoffset */ 211 | 0, /* tp_iter */ 212 | 0, /* tp_iternext */ 213 | Operation_methods, /* tp_methods */ 214 | Operation_members, /* tp_members */ 215 | 0, /* tp_getset */ 216 | 0, /* tp_base */ 217 | 0, /* tp_dict */ 218 | 0, /* tp_descr_get */ 219 | 0, /* tp_descr_set */ 220 | 0, /* tp_dictoffset */ 221 | (initproc)Operation_init, /* tp_init */ 222 | 0, /* tp_alloc */ 223 | Operation_new, /* tp_new */ 224 | }; 225 | -------------------------------------------------------------------------------- /PyMI/Operation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | /* Type-specific fields go here. */ 10 | std::shared_ptr operation; 11 | CRITICAL_SECTION cs; 12 | } Operation; 13 | 14 | extern PyTypeObject OperationType; 15 | 16 | Operation* Operation_New(std::shared_ptr operation); 17 | -------------------------------------------------------------------------------- /PyMI/OperationOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "OperationOptions.h" 3 | #include "PyMI.h" 4 | #include "Utils.h" 5 | 6 | #include 7 | 8 | 9 | static PyObject* OperationOptions_new(PyTypeObject* type, PyObject* args, PyObject* kwds) 10 | { 11 | OperationOptions* self = NULL; 12 | self = (OperationOptions*)type->tp_alloc(type, 0); 13 | self->operationOptions = NULL; 14 | ::InitializeCriticalSection(&self->cs); 15 | return (PyObject *)self; 16 | } 17 | 18 | static int OperationOptions_init(OperationOptions* self, PyObject* args, PyObject* kwds) 19 | { 20 | PyErr_SetString(PyMIError, "An OperationOptions object cannot be allocated directly."); 21 | return -1; 22 | } 23 | 24 | static void OperationOptions_dealloc(OperationOptions* self) 25 | { 26 | AllowThreads(&self->cs, [&]() { 27 | self->operationOptions = NULL; 28 | }); 29 | ::DeleteCriticalSection(&self->cs); 30 | Py_TYPE(self)->tp_free((PyObject*)self); 31 | } 32 | 33 | OperationOptions* OperationOptions_New(std::shared_ptr operationOptions) 34 | { 35 | OperationOptions* obj = (OperationOptions*)OperationOptions_new(&OperationOptionsType, NULL, NULL); 36 | obj->operationOptions = operationOptions; 37 | return obj; 38 | } 39 | 40 | static PyObject* OperationOptions_Clone(OperationOptions *self, PyObject*) 41 | { 42 | try 43 | { 44 | std::shared_ptr operationOptions; 45 | AllowThreads(&self->cs, [&]() { 46 | operationOptions = self->operationOptions->Clone(); 47 | }); 48 | return (PyObject*)OperationOptions_New(operationOptions); 49 | } 50 | catch (std::exception& ex) 51 | { 52 | SetPyException(ex); 53 | return NULL; 54 | } 55 | } 56 | 57 | static PyObject* OperationOptions_GetTimeout(OperationOptions* self, PyObject* timeout) 58 | { 59 | try 60 | { 61 | MI_Interval interval; 62 | AllowThreads(&self->cs, [&]() { 63 | interval = self->operationOptions->GetTimeout(); 64 | }); 65 | return PyDeltaFromMIInterval(interval); 66 | } 67 | catch (std::exception& ex) 68 | { 69 | SetPyException(ex); 70 | return NULL; 71 | } 72 | } 73 | 74 | 75 | static PyObject* OperationOptions_SetTimeout(OperationOptions* self, PyObject* timeout) 76 | { 77 | PyDateTime_IMPORT; 78 | 79 | if (!PyDelta_Check(timeout)) 80 | { 81 | PyErr_SetString(PyExc_TypeError, "parameter timeout must be of type datetime.timedelta"); 82 | return NULL; 83 | } 84 | 85 | try 86 | { 87 | MI_Interval miTimeout; 88 | MIIntervalFromPyDelta(timeout, miTimeout); 89 | AllowThreads(&self->cs, [&]() { 90 | self->operationOptions->SetTimeout(miTimeout); 91 | }); 92 | Py_RETURN_NONE; 93 | } 94 | catch (std::exception& ex) 95 | { 96 | SetPyException(ex); 97 | return NULL; 98 | } 99 | } 100 | 101 | 102 | static PyObject* OperationOptions_SetCustomOption(OperationOptions* self, PyObject *args, PyObject *kwds) 103 | { 104 | char* optionName = NULL; 105 | unsigned int optionValueType = 0; 106 | PyObject* optionValue = NULL; 107 | PyObject* mustComply = NULL; 108 | 109 | static char *kwlist[] = { "name", "value_type", "value", "must_comply", NULL }; 110 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "sIO|O", kwlist, 111 | &optionName, &optionValueType, 112 | &optionValue, &mustComply)) 113 | return NULL; 114 | 115 | try 116 | { 117 | auto miValue = Py2MI(optionValue, (MI_Type)optionValueType); 118 | AllowThreads(&self->cs, [&]() { 119 | self->operationOptions->SetCustomOption(ToWstring(optionName).c_str(), (MI_Type)optionValueType, 120 | *miValue, PyObject_IsTrue(mustComply)); 121 | }); 122 | Py_RETURN_NONE; 123 | } 124 | catch (std::exception& ex) 125 | { 126 | SetPyException(ex); 127 | return NULL; 128 | } 129 | } 130 | 131 | 132 | static PyMemberDef OperationOptions_members[] = { 133 | { NULL } /* Sentinel */ 134 | }; 135 | 136 | static PyMethodDef OperationOptions_methods[] = { 137 | { "clone", (PyCFunction)OperationOptions_Clone, METH_NOARGS, "Clones the OperationOptions." }, 138 | { "get_timeout", (PyCFunction)OperationOptions_GetTimeout, METH_NOARGS, "Returns the timeout." }, 139 | { "set_timeout", (PyCFunction)OperationOptions_SetTimeout, METH_O, "Sets a timeout." }, 140 | { "set_custom_option", (PyCFunction)OperationOptions_SetCustomOption, 141 | METH_VARARGS | METH_KEYWORDS, "Sets a custom option." }, 142 | { NULL } /* Sentinel */ 143 | }; 144 | 145 | PyTypeObject OperationOptionsType = { 146 | PyVarObject_HEAD_INIT(NULL, 0) 147 | "mi.operationoptions", /*tp_name*/ 148 | sizeof(OperationOptions), /*tp_basicsize*/ 149 | 0, /*tp_itemsize*/ 150 | (destructor)OperationOptions_dealloc, /*tp_dealloc*/ 151 | 0, /*tp_print*/ 152 | 0, /*tp_getattr*/ 153 | 0, /*tp_setattr*/ 154 | 0, /*tp_compare*/ 155 | 0, /*tp_repr*/ 156 | 0, /*tp_as_number*/ 157 | 0, /*tp_as_sequence*/ 158 | 0, /*tp_as_mapping*/ 159 | 0, /*tp_hash */ 160 | 0, /*tp_call*/ 161 | 0, /*tp_str*/ 162 | 0, /*tp_getattro*/ 163 | 0, /*tp_setattro*/ 164 | 0, /*tp_as_buffer*/ 165 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 166 | "OperationOptions objects", /* tp_doc */ 167 | 0, /* tp_traverse */ 168 | 0, /* tp_clear */ 169 | 0, /* tp_richcompare */ 170 | 0, /* tp_weaklistoffset */ 171 | 0, /* tp_iter */ 172 | 0, /* tp_iternext */ 173 | OperationOptions_methods, /* tp_methods */ 174 | OperationOptions_members, /* tp_members */ 175 | 0, /* tp_getset */ 176 | 0, /* tp_base */ 177 | 0, /* tp_dict */ 178 | 0, /* tp_descr_get */ 179 | 0, /* tp_descr_set */ 180 | 0, /* tp_dictoffset */ 181 | (initproc)OperationOptions_init, /* tp_init */ 182 | 0, /* tp_alloc */ 183 | OperationOptions_new, /* tp_new */ 184 | }; 185 | -------------------------------------------------------------------------------- /PyMI/OperationOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | /* Type-specific fields go here. */ 10 | std::shared_ptr operationOptions; 11 | CRITICAL_SECTION cs; 12 | } OperationOptions; 13 | 14 | extern PyTypeObject OperationOptionsType; 15 | 16 | OperationOptions* OperationOptions_New(std::shared_ptr operationOptions); 17 | 18 | -------------------------------------------------------------------------------- /PyMI/PyMI.cpp: -------------------------------------------------------------------------------- 1 | // PyMI.cpp : Defines the exported functions for the DLL application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "PyMI.h" 6 | #include "Application.h" 7 | #include "Session.h" 8 | #include "Class.h" 9 | #include "Operation.h" 10 | #include "Instance.h" 11 | #include "Serializer.h" 12 | #include "OperationOptions.h" 13 | #include "DestinationOptions.h" 14 | #include "MiError.h" 15 | 16 | #include 17 | 18 | PyObject *PyMIError; 19 | PyObject *PyMITimeoutError; 20 | 21 | static PyMethodDef mi_methods[] = { 22 | { NULL, NULL, 0, NULL } /* Sentinel */ 23 | }; 24 | 25 | #ifdef IS_PY3K 26 | static PyModuleDef mimodule = { 27 | PyModuleDef_HEAD_INIT, 28 | "mi", 29 | "Management Infrastructure API module.", 30 | -1, 31 | mi_methods 32 | }; 33 | #endif 34 | 35 | PyObject* _initmi(void) 36 | { 37 | if (!PyEval_ThreadsInitialized()) 38 | { 39 | PyEval_InitThreads(); 40 | } 41 | 42 | PyDateTime_IMPORT; 43 | 44 | PyObject* m = NULL; 45 | 46 | if (PyType_Ready(&ApplicationType) < 0) 47 | return NULL; 48 | 49 | if (PyType_Ready(&SessionType) < 0) 50 | return NULL; 51 | 52 | if (PyType_Ready(&ClassType) < 0) 53 | return NULL; 54 | 55 | if (PyType_Ready(&InstanceType) < 0) 56 | return NULL; 57 | 58 | if (PyType_Ready(&OperationType) < 0) 59 | return NULL; 60 | 61 | if (PyType_Ready(&SerializerType) < 0) 62 | return NULL; 63 | 64 | if (PyType_Ready(&OperationOptionsType) < 0) 65 | return NULL; 66 | 67 | if (PyType_Ready(&DestinationOptionsType) < 0) 68 | return NULL; 69 | 70 | #ifdef IS_PY3K 71 | m = PyModule_Create(&mimodule); 72 | if (m == NULL) 73 | return NULL; 74 | #else 75 | m = Py_InitModule3("mi", mi_methods, "MI module."); 76 | if (m == NULL) 77 | return NULL; 78 | #endif 79 | 80 | Py_INCREF(&ApplicationType); 81 | PyModule_AddObject(m, "Application", (PyObject*)&ApplicationType); 82 | 83 | Py_INCREF(&SessionType); 84 | PyModule_AddObject(m, "Session", (PyObject*)&SessionType); 85 | 86 | Py_INCREF(&ClassType); 87 | PyModule_AddObject(m, "Class", (PyObject*)&ClassType); 88 | 89 | Py_INCREF(&InstanceType); 90 | PyModule_AddObject(m, "Instance", (PyObject*)&InstanceType); 91 | 92 | Py_INCREF(&OperationType); 93 | PyModule_AddObject(m, "Operation", (PyObject*)&OperationType); 94 | 95 | Py_INCREF(&SerializerType); 96 | PyModule_AddObject(m, "Serializer", (PyObject*)&SerializerType); 97 | 98 | Py_INCREF(&OperationOptionsType); 99 | PyModule_AddObject(m, "OperationOptions", (PyObject*)&OperationOptionsType); 100 | 101 | Py_INCREF(&DestinationOptionsType); 102 | PyModule_AddObject(m, "DestinationOptions", (PyObject*)&DestinationOptionsType); 103 | 104 | PyMIError = PyErr_NewException("PyMI.error", NULL, NULL); 105 | Py_INCREF(PyMIError); 106 | PyModule_AddObject(m, "error", PyMIError); 107 | 108 | PyMITimeoutError = PyErr_NewException("PyMI.timeouterror", PyMIError, NULL); 109 | Py_INCREF(PyMITimeoutError); 110 | PyModule_AddObject(m, "timeouterror", PyMITimeoutError); 111 | 112 | PyObject_SetAttrString(m, "PROTOCOL_WINRM", PyUnicode_FromString("WINRM")); 113 | PyObject_SetAttrString(m, "PROTOCOL_WMIDCOM", PyUnicode_FromString("WMIDCOM")); 114 | 115 | PyObject_SetAttrString(m, "MI_BOOLEAN", PyLong_FromLong(MI_BOOLEAN)); 116 | PyObject_SetAttrString(m, "MI_UINT8", PyLong_FromLong(MI_UINT8)); 117 | PyObject_SetAttrString(m, "MI_SINT8", PyLong_FromLong(MI_SINT8)); 118 | PyObject_SetAttrString(m, "MI_UINT16", PyLong_FromLong(MI_UINT16)); 119 | PyObject_SetAttrString(m, "MI_SINT16", PyLong_FromLong(MI_SINT16)); 120 | PyObject_SetAttrString(m, "MI_UINT32", PyLong_FromLong(MI_UINT32)); 121 | PyObject_SetAttrString(m, "MI_SINT32", PyLong_FromLong(MI_SINT32)); 122 | PyObject_SetAttrString(m, "MI_UINT64", PyLong_FromLong(MI_UINT64)); 123 | PyObject_SetAttrString(m, "MI_SINT64", PyLong_FromLong(MI_SINT64)); 124 | PyObject_SetAttrString(m, "MI_REAL32", PyLong_FromLong(MI_REAL32)); 125 | PyObject_SetAttrString(m, "MI_REAL64", PyLong_FromLong(MI_REAL64)); 126 | PyObject_SetAttrString(m, "MI_CHAR16", PyLong_FromLong(MI_CHAR16)); 127 | PyObject_SetAttrString(m, "MI_DATETIME", PyLong_FromLong(MI_DATETIME)); 128 | PyObject_SetAttrString(m, "MI_STRING", PyLong_FromLong(MI_STRING)); 129 | PyObject_SetAttrString(m, "MI_REFERENCE", PyLong_FromLong(MI_REFERENCE)); 130 | PyObject_SetAttrString(m, "MI_INSTANCE", PyLong_FromLong(MI_INSTANCE)); 131 | PyObject_SetAttrString(m, "MI_UINT8A", PyLong_FromLong(MI_UINT8A)); 132 | PyObject_SetAttrString(m, "MI_SINT8A", PyLong_FromLong(MI_SINT8A)); 133 | PyObject_SetAttrString(m, "MI_UINT16A", PyLong_FromLong(MI_UINT16A)); 134 | PyObject_SetAttrString(m, "MI_SINT16A", PyLong_FromLong(MI_SINT16A)); 135 | PyObject_SetAttrString(m, "MI_UINT32A", PyLong_FromLong(MI_UINT32A)); 136 | PyObject_SetAttrString(m, "MI_SINT32A", PyLong_FromLong(MI_SINT32A)); 137 | PyObject_SetAttrString(m, "MI_UINT64A", PyLong_FromLong(MI_UINT64A)); 138 | PyObject_SetAttrString(m, "MI_SINT64A", PyLong_FromLong(MI_SINT64A)); 139 | PyObject_SetAttrString(m, "MI_REAL32A", PyLong_FromLong(MI_REAL32A)); 140 | PyObject_SetAttrString(m, "MI_REAL64A", PyLong_FromLong(MI_REAL64A)); 141 | PyObject_SetAttrString(m, "MI_CHAR16A", PyLong_FromLong(MI_CHAR16A)); 142 | PyObject_SetAttrString(m, "MI_DATETIMEA", PyLong_FromLong(MI_DATETIMEA)); 143 | PyObject_SetAttrString(m, "MI_STRINGA", PyLong_FromLong(MI_STRINGA)); 144 | PyObject_SetAttrString(m, "MI_REFERENCEA", PyLong_FromLong(MI_REFERENCEA)); 145 | PyObject_SetAttrString(m, "MI_INSTANCEA", PyLong_FromLong(MI_INSTANCEA)); 146 | PyObject_SetAttrString(m, "MI_ARRAY", PyLong_FromLong(MI_ARRAY)); 147 | 148 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_DEFAULT", 149 | PyUnicode_FromWideChar(MI_AUTH_TYPE_DEFAULT, 150 | wcslen(MI_AUTH_TYPE_DEFAULT))); 151 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_NONE", 152 | PyUnicode_FromWideChar(MI_AUTH_TYPE_NONE, 153 | wcslen(MI_AUTH_TYPE_NONE))); 154 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_DIGEST", 155 | PyUnicode_FromWideChar(MI_AUTH_TYPE_DIGEST, 156 | wcslen(MI_AUTH_TYPE_DIGEST))); 157 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_NEGO_WITH_CREDS", 158 | PyUnicode_FromWideChar(MI_AUTH_TYPE_NEGO_WITH_CREDS, 159 | wcslen(MI_AUTH_TYPE_NEGO_WITH_CREDS))); 160 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_NEGO_NO_CREDS", 161 | PyUnicode_FromWideChar(MI_AUTH_TYPE_NEGO_NO_CREDS, 162 | wcslen(MI_AUTH_TYPE_NEGO_NO_CREDS))); 163 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_BASIC", 164 | PyUnicode_FromWideChar(MI_AUTH_TYPE_BASIC, 165 | wcslen(MI_AUTH_TYPE_BASIC))); 166 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_KERBEROS", 167 | PyUnicode_FromWideChar(MI_AUTH_TYPE_KERBEROS, 168 | wcslen(MI_AUTH_TYPE_KERBEROS))); 169 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_CLIENT_CERTS", 170 | PyUnicode_FromWideChar(MI_AUTH_TYPE_CLIENT_CERTS, 171 | wcslen(MI_AUTH_TYPE_CLIENT_CERTS))); 172 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_NTLM", 173 | PyUnicode_FromWideChar(MI_AUTH_TYPE_NTLM, 174 | wcslen(MI_AUTH_TYPE_NTLM))); 175 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_CREDSSP", 176 | PyUnicode_FromWideChar(MI_AUTH_TYPE_CREDSSP, 177 | wcslen(MI_AUTH_TYPE_CREDSSP))); 178 | PyObject_SetAttrString(m, "MI_AUTH_TYPE_ISSUER_CERT", 179 | PyUnicode_FromWideChar(MI_AUTH_TYPE_ISSUER_CERT, 180 | wcslen(MI_AUTH_TYPE_ISSUER_CERT))); 181 | 182 | PyObject_SetAttrString(m, "MI_TRANSPORT_HTTP", 183 | PyUnicode_FromWideChar(MI_DESTINATIONOPTIONS_TRANSPORT_HTTP, 184 | wcslen(MI_DESTINATIONOPTIONS_TRANSPORT_HTTP))); 185 | // The misspelling of 'transport' is intentional, as this is how it's defined by MI.h. 186 | PyObject_SetAttrString(m, "MI_TRANSPORT_HTTPS", 187 | PyUnicode_FromWideChar(MI_DESTINATIONOPTIONS_TRANPSORT_HTTPS, 188 | wcslen(MI_DESTINATIONOPTIONS_TRANPSORT_HTTPS))); 189 | 190 | PyObject* mi_error = MiError_Init(); 191 | if (mi_error == NULL) 192 | return NULL; 193 | else 194 | PyObject_SetAttrString(m, "mi_error", mi_error); 195 | 196 | return m; 197 | } 198 | 199 | #ifdef IS_PY3K 200 | PyMODINIT_FUNC PyInit_mi(void) 201 | #else 202 | PyMODINIT_FUNC initmi(void) 203 | #endif 204 | { 205 | PyObject* m = _initmi(); 206 | #ifdef IS_PY3K 207 | return m; 208 | #endif 209 | } 210 | -------------------------------------------------------------------------------- /PyMI/PyMI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | extern PyObject *PyMIError; 6 | extern PyObject *PyMITimeoutError; 7 | -------------------------------------------------------------------------------- /PyMI/PyMI.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {30ce0327-f4e7-4c58-ab46-eecd70b49fa3} 18 | py 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | Header Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | Header Files 36 | 37 | 38 | Header Files 39 | 40 | 41 | Header Files 42 | 43 | 44 | Header Files 45 | 46 | 47 | Header Files 48 | 49 | 50 | Header Files 51 | 52 | 53 | Header Files 54 | 55 | 56 | Header Files 57 | 58 | 59 | Header Files 60 | 61 | 62 | Header Files 63 | 64 | 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | Source Files 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Source Files 83 | 84 | 85 | Source Files 86 | 87 | 88 | Source Files 89 | 90 | 91 | Source Files 92 | 93 | 94 | Source Files 95 | 96 | 97 | Source Files 98 | 99 | 100 | Source Files 101 | 102 | 103 | Source Files 104 | 105 | 106 | 107 | 108 | Python 109 | 110 | 111 | Python 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /PyMI/PythonDir.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | c:\Python27 6 | c:\Python27_x64 7 | c:\Python35 8 | c:\Python35_x64 9 | c:\Python34 10 | c:\Python34_x64 11 | c:\Python36_x64 12 | c:\Python36 13 | c:\Python37_x64 14 | c:\Python37 15 | 16 | 17 | 18 | 19 | 20 | $(PythonDir_27_x86) 21 | 22 | 23 | $(PythonDir_27_x64) 24 | 25 | 26 | $(PythonDir_35_x86) 27 | 28 | 29 | $(PythonDir_35_x64) 30 | 31 | 32 | $(PythonDir_34_x86) 33 | 34 | 35 | $(PythonDir_34_x64) 36 | 37 | 38 | $(PythonDir_36_x64) 39 | true 40 | 41 | 42 | $(PythonDir_36_x86) 43 | true 44 | 45 | 46 | $(PythonDir_37_x64) 47 | true 48 | 49 | 50 | $(PythonDir_37_x86) 51 | true 52 | 53 | 54 | -------------------------------------------------------------------------------- /PyMI/README.rst: -------------------------------------------------------------------------------- 1 | PyMI - Windows Management Infrastructure API for Python 2 | ======================================================= 3 | 4 | This project provides a Python native module wrapper over the Windows 5 | Management Infrastructure (MI) API [#miapi]_. 6 | 7 | Works with Python 2.7 and 3.x on any Windows version which supports the MI API, 8 | both x86 and x64. 9 | 10 | It includes also a drop-in replacement for the Python WMI [#pywmi]_ module, 11 | proving much faster execution times and no dependency on pywin32. 12 | 13 | Installation 14 | ------------ 15 | 16 | Pip is the preferred way to install PyMI. Pre-compiled binary wheels are 17 | available on Pypi [#pymipypi]_: 18 | 19 | .. code-block:: powershell 20 | 21 | pip install PyMI 22 | 23 | Usage 24 | ----- 25 | 26 | This project can be used either with a lower level interface that reflects the 27 | underlying MI API structure or with the higher level (and slightly slower) 28 | WMI module replacement. 29 | 30 | MI module basic usage 31 | ^^^^^^^^^^^^^^^^^^^^^ 32 | 33 | Here's a simple example which enumerates all processes and kills any instance of 34 | "KillerRabbitOfCaerbannog.exe". 35 | 36 | .. code-block:: python 37 | 38 | import mi 39 | 40 | with mi.Application() as a: 41 | with a.create_session(protocol=mi.PROTOCOL_WMIDCOM) as s: 42 | proc_name = u'notepad.exe' 43 | with s.exec_query( 44 | u"root\\cimv2", u"select * from Win32_Process") as q: 45 | i = q.get_next_instance() 46 | while i is not None: 47 | if i[u'name'].lower() == u"KillerRabbitOfCaerbannog.exe": 48 | cls = i.get_class() 49 | # Prepare parameters 50 | params = a.create_method_params(cls, u"Terminate") 51 | # Exit code 52 | params['reason'] = 10 53 | # Invoke method 54 | with s.invoke_method(i, u"Terminate", params) as op: 55 | op.get_next_instance() 56 | i = q.get_next_instance() 57 | 58 | WMI module basic usage 59 | ^^^^^^^^^^^^^^^^^^^^^^ 60 | 61 | And here's the same example written using the *WMI* module replacement, 62 | which provides a simpler and higher level interface over the *mi* API: 63 | 64 | .. code-block:: python 65 | 66 | import wmi 67 | 68 | conn = wmi.WMI() 69 | for p in conn.Win32_Process(): 70 | if p.Name == u"KillerRabbitOfCaerbannog.exe": 71 | p.Terminate(reason=10) 72 | 73 | 74 | Build 75 | ----- 76 | 77 | Use the following to build Python 3 wheels. Those will be copied to the build 78 | dir. 79 | 80 | .. code-block:: powershell 81 | 82 | python setup.py bdist_wheel 83 | 84 | The best way to build PyMI for Python 2.7 or 3.4 and below is to use the 85 | Visual Studio solution (described below). This will statically link the 86 | vc140 runtime, which is required by PyMI. 87 | 88 | Custom VS env vars 89 | ^^^^^^^^^^^^^^^^^^ 90 | 91 | distutils will automatically locate your Visual Studio and Windows SDK 92 | installation. If you'd like to call vcvarsall.bat yourself and use a specific 93 | version, use the following: 94 | 95 | .. code-block:: powershell 96 | 97 | function SetVCVars($vcvarsdir, $platform="amd64") 98 | { 99 | pushd $vcvarsdir 100 | try 101 | { 102 | cmd /c "vcvarsall.bat $platform & set" | 103 | foreach { 104 | if ($_ -match "=") { 105 | $v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])" 106 | } 107 | } 108 | } 109 | finally 110 | { 111 | popd 112 | } 113 | } 114 | 115 | # Replace this folder with the one in which the vcvarsall.bat script is 116 | # located (the exact location depends on the Visual Studio version). 117 | # SetVCVars "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build" 118 | SetVCVars "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" 119 | 120 | $env:DISTUTILS_USE_SDK=1 121 | $env:MSSdk=1 122 | 123 | python setup.py bdist_wheel 124 | 125 | Make sure to use the Visual Studio toolset that matches the Python version 126 | that you're targetting: https://wiki.python.org/moin/WindowsCompilers. 127 | 128 | By default, we're statically linking the VC runtime. To enable dynamic 129 | linking, set ``$env:PYMI_VCRUNTIME_DYNAMIC_LINKING="y"``. 130 | 131 | Debug builds 132 | ^^^^^^^^^^^^ 133 | 134 | The easiest way to do a debug build is to set the following in setup.cfg: 135 | 136 | .. code-block:: 137 | 138 | [build] 139 | debug = 1 140 | 141 | This will be honored regardless of the build type (e.g. stdist, wheel, etc). 142 | 143 | To enable distutils debug logging, you may set the following: 144 | 145 | .. code-block:: powershell 146 | 147 | $env:DISTUTILS_DEBUG = 1 148 | 149 | Before doing a debug build, you may wish to clean the build dir. 150 | 151 | Using the Visual Studio Solution 152 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 153 | 154 | Open the provided *PyMI.sln* solution in Visual Studio 2015 [#VS2015]_, choose 155 | your target Python version / platform and build. Wheel packages are 156 | automatically generated in the *dist* folder for release builds. 157 | 158 | Note: the target Python version must be present. The Python path can be 159 | customized by setting the corresponding PythonDir* user macro, 160 | e.g. *PythonDir_34_x64*. The *wheel* and *GitPython* packages are required during the build process: 161 | 162 | .. code-block:: powershell 163 | 164 | pip install wheel 165 | pip install GitPython 166 | 167 | As an alternative, you can use the MSBuild CLI tool: 168 | 169 | .. code-block:: powershell 170 | 171 | $env:MSBuildEmitSolution="TRUE" 172 | MSBuild.exe .\PyMI.sln /p:Configuration="Release (Python 3.7)" 173 | 174 | 175 | References 176 | ---------- 177 | 178 | .. [#miapi] MI API https://msdn.microsoft.com/en-us/library/hh404805(v=vs.85).aspx 179 | .. [#pywmi] Python WMI module https://pypi.python.org/pypi/WMI 180 | .. [#pymipypi] PyMI on Pypi https://pypi.python.org/pypi/PyMI 181 | .. [#vs2015] Visual Studio 2015 download https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx 182 | -------------------------------------------------------------------------------- /PyMI/Serializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Serializer.h" 3 | #include "PyMI.h" 4 | #include "Instance.h" 5 | #include "Class.h" 6 | #include "Utils.h" 7 | 8 | 9 | static PyObject* Serializer_new(PyTypeObject* type, PyObject* args, PyObject* kwds) 10 | { 11 | Serializer* self = NULL; 12 | self = (Serializer*)type->tp_alloc(type, 0); 13 | ::InitializeCriticalSection(&self->cs); 14 | return (PyObject *)self; 15 | } 16 | 17 | static void Serializer_dealloc(Serializer* self) 18 | { 19 | AllowThreads(&self->cs, [&]() { 20 | self->serializer = NULL; 21 | }); 22 | ::DeleteCriticalSection(&self->cs); 23 | Py_TYPE(self)->tp_free((PyObject*)self); 24 | } 25 | 26 | static int Serializer_init(Serializer* self, PyObject* args, PyObject* kwds) 27 | { 28 | PyErr_SetString(PyMIError, "Please use Serializer.create_serializer to allocate a Serializer object."); 29 | return -1; 30 | } 31 | 32 | Serializer* Serializer_New(std::shared_ptr serializer) 33 | { 34 | Serializer* obj = (Serializer*)Serializer_new(&SerializerType, NULL, NULL); 35 | obj->serializer = serializer; 36 | return obj; 37 | } 38 | 39 | static PyObject* Serializer_self(Serializer *self, PyObject*) 40 | { 41 | Py_INCREF(self); 42 | return (PyObject *)self; 43 | } 44 | 45 | static PyObject* Serializer_exit(Serializer* self, PyObject*) 46 | { 47 | AllowThreads(&self->cs, [&]() { 48 | if (!self->serializer->IsClosed()) 49 | self->serializer->Close(); 50 | }); 51 | Py_RETURN_NONE; 52 | } 53 | 54 | static PyObject* Serializer_SerializeInstance(Serializer* self, PyObject* args, PyObject* kwds) 55 | { 56 | PyObject* instance = NULL; 57 | PyObject* includeClassObj = NULL; 58 | static char *kwlist[] = { "instance", "include_class", NULL }; 59 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &instance, &includeClassObj)) 60 | return NULL; 61 | 62 | try 63 | { 64 | if (!PyObject_IsInstance(instance, reinterpret_cast(&InstanceType))) 65 | throw MI::TypeConversionException(L"\"instance\" must have type Instance"); 66 | 67 | bool includeClass = includeClassObj && PyObject_IsTrue(includeClassObj); 68 | 69 | std::wstring data; 70 | AllowThreads(&self->cs, [&]() { 71 | data = self->serializer->SerializeInstance(*((Instance*)instance)->instance, includeClass); 72 | }); 73 | return PyUnicode_FromWideChar(data.c_str(), data.length()); 74 | } 75 | catch (std::exception& ex) 76 | { 77 | SetPyException(ex); 78 | return NULL; 79 | } 80 | } 81 | 82 | static PyObject* Serializer_SerializeClass(Serializer* self, PyObject* args, PyObject* kwds) 83 | { 84 | PyObject* miClass = NULL; 85 | PyObject* deepObj = NULL; 86 | static char *kwlist[] = { "mi_class", "deep", NULL }; 87 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &miClass, &deepObj)) 88 | return NULL; 89 | 90 | try 91 | { 92 | if (!PyObject_IsInstance(miClass, reinterpret_cast(&ClassType))) 93 | throw MI::TypeConversionException(L"\"mi_class\" must have type Class"); 94 | 95 | bool deep = deepObj && PyObject_IsTrue(deepObj); 96 | 97 | std::wstring data; 98 | AllowThreads(&self->cs, [&]() { 99 | data = self->serializer->SerializeClass(*((Class*)miClass)->miClass, deep); 100 | }); 101 | return PyUnicode_FromWideChar(data.c_str(), data.length()); 102 | } 103 | catch (std::exception& ex) 104 | { 105 | SetPyException(ex); 106 | return NULL; 107 | } 108 | } 109 | 110 | static PyMemberDef Serializer_members[] = { 111 | { NULL } /* Sentinel */ 112 | }; 113 | 114 | static PyMethodDef Serializer_methods[] = { 115 | { "serialize_instance", (PyCFunction)Serializer_SerializeInstance, METH_VARARGS | METH_KEYWORDS, "Serializes an instance." }, 116 | { "serialize_class", (PyCFunction)Serializer_SerializeClass, METH_VARARGS | METH_KEYWORDS, "Serializes a class." }, 117 | { "__enter__", (PyCFunction)Serializer_self, METH_NOARGS, "" }, 118 | { "__exit__", (PyCFunction)Serializer_exit, METH_VARARGS, "" }, 119 | { NULL } /* Sentinel */ 120 | }; 121 | 122 | PyTypeObject SerializerType = { 123 | PyVarObject_HEAD_INIT(NULL, 0) 124 | "mi.Serializer", /*tp_name*/ 125 | sizeof(Serializer), /*tp_basicsize*/ 126 | 0, /*tp_itemsize*/ 127 | (destructor)Serializer_dealloc, /*tp_dealloc*/ 128 | 0, /*tp_print*/ 129 | 0, /*tp_getattr*/ 130 | 0, /*tp_setattr*/ 131 | 0, /*tp_compare*/ 132 | 0, /*tp_repr*/ 133 | 0, /*tp_as_number*/ 134 | 0, /*tp_as_sequence*/ 135 | 0, /*tp_as_mapping*/ 136 | 0, /*tp_hash */ 137 | 0, /*tp_call*/ 138 | 0, /*tp_str*/ 139 | 0, /*tp_getattro*/ 140 | 0, /*tp_setattro*/ 141 | 0, /*tp_as_buffer*/ 142 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 143 | "Serializer objects", /* tp_doc */ 144 | 0, /* tp_traverse */ 145 | 0, /* tp_clear */ 146 | 0, /* tp_richcompare */ 147 | 0, /* tp_weaklistoffset */ 148 | 0, /* tp_iter */ 149 | 0, /* tp_iternext */ 150 | Serializer_methods, /* tp_methods */ 151 | Serializer_members, /* tp_members */ 152 | 0, /* tp_getset */ 153 | 0, /* tp_base */ 154 | 0, /* tp_dict */ 155 | 0, /* tp_descr_get */ 156 | 0, /* tp_descr_set */ 157 | 0, /* tp_dictoffset */ 158 | (initproc)Serializer_init, /* tp_init */ 159 | 0, /* tp_alloc */ 160 | Serializer_new, /* tp_new */ 161 | }; 162 | -------------------------------------------------------------------------------- /PyMI/Serializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | /* Type-specific fields go here. */ 10 | std::shared_ptr serializer; 11 | CRITICAL_SECTION cs; 12 | } Serializer; 13 | 14 | extern PyTypeObject SerializerType; 15 | 16 | Serializer* Serializer_New(std::shared_ptr serializer); 17 | -------------------------------------------------------------------------------- /PyMI/Session.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Session.h" 3 | #include "Application.h" 4 | #include "Operation.h" 5 | #include "Instance.h" 6 | #include "Class.h" 7 | #include "Callbacks.h" 8 | #include "OperationOptions.h" 9 | #include "Utils.h" 10 | #include "PyMI.h" 11 | 12 | 13 | static PyObject* Session_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 14 | { 15 | Session* self = NULL; 16 | self = (Session*)type->tp_alloc(type, 0); 17 | ::InitializeCriticalSection(&self->cs); 18 | self->session = NULL; 19 | self->operationCallbacks = std::make_shared>>(); 20 | return (PyObject *)self; 21 | } 22 | 23 | static int Session_init(Session* self, PyObject* args, PyObject* kwds) 24 | { 25 | PyErr_SetString(PyMIError, "Please use Application.create_session to allocate a Session object."); 26 | return -1; 27 | } 28 | 29 | static void Session_dealloc(Session* self) 30 | { 31 | AllowThreads(&self->cs, [&]() { 32 | self->session = NULL; 33 | }); 34 | self->operationCallbacks = NULL; 35 | ::DeleteCriticalSection(&self->cs); 36 | Py_TYPE(self)->tp_free((PyObject*)self); 37 | } 38 | 39 | 40 | static PyObject* Session_ExecQuery(Session *self, PyObject *args, PyObject *kwds) 41 | { 42 | char* ns = NULL; 43 | char* query = NULL; 44 | char* dialect = "WQL"; 45 | PyObject* operationOptions = NULL; 46 | 47 | static char *kwlist[] = { "ns", "query", "dialect", "operation_options", NULL }; 48 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|sO", kwlist, &ns, &query, 49 | &dialect, &operationOptions)) 50 | return NULL; 51 | 52 | try 53 | { 54 | ValidatePyObjectType(operationOptions, L"operation_options", 55 | &OperationOptionsType, L"OperationOptions"); 56 | std::shared_ptr op; 57 | AllowThreads(&self->cs, [&]() { 58 | op = self->session->ExecQuery( 59 | ToWstring(ns).c_str(), ToWstring(query).c_str(), ToWstring(dialect).c_str(), 60 | !CheckPyNone(operationOptions) 61 | ? ((OperationOptions*)operationOptions)->operationOptions 62 | : NULL); 63 | }); 64 | return (PyObject*)Operation_New(op); 65 | } 66 | catch (std::exception& ex) 67 | { 68 | SetPyException(ex); 69 | return NULL; 70 | } 71 | } 72 | 73 | static PyObject* Session_GetAssociators(Session *self, PyObject *args, PyObject *kwds) 74 | { 75 | PyObject* instance = NULL; 76 | char* ns = NULL; 77 | char* assocClass = ""; 78 | char* resultClass = ""; 79 | char* role = ""; 80 | char* resultRole = ""; 81 | PyObject* keysOnlyObj = NULL; 82 | PyObject* operationOptions = NULL; 83 | 84 | static char *kwlist[] = { "ns", "instance", "assoc_class", "result_class", 85 | "role", "result_role", "keys_only", "operation_options", NULL }; 86 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|ssssOO", kwlist, &ns, &instance, 87 | &assocClass, &resultClass, &role, &resultRole, 88 | &keysOnlyObj, &operationOptions)) 89 | return NULL; 90 | 91 | try 92 | { 93 | ValidatePyObjectType(instance, L"instance", &InstanceType, L"Instance", false); 94 | ValidatePyObjectType(operationOptions, L"operation_options", 95 | &OperationOptionsType, L"OperationOptions"); 96 | 97 | bool keysOnly = keysOnlyObj && PyObject_IsTrue(keysOnlyObj); 98 | 99 | std::shared_ptr op; 100 | AllowThreads(&self->cs, [&]() { 101 | op = self->session->GetAssociators( 102 | ToWstring(ns).c_str(), *((Instance*)instance)->instance, ToWstring(assocClass).c_str(), 103 | ToWstring(resultClass).c_str(), ToWstring(role).c_str(), ToWstring(resultRole).c_str(), keysOnly, 104 | !CheckPyNone(operationOptions) 105 | ? ((OperationOptions*)operationOptions)->operationOptions 106 | : NULL); 107 | }); 108 | return (PyObject*)Operation_New(op); 109 | } 110 | catch (std::exception& ex) 111 | { 112 | SetPyException(ex); 113 | return NULL; 114 | } 115 | } 116 | 117 | static PyObject* Session_Close(Session *self, PyObject*) 118 | { 119 | try 120 | { 121 | AllowThreads(&self->cs, [&]() 122 | { 123 | self->session->Close(); 124 | }); 125 | Py_RETURN_NONE; 126 | } 127 | catch (std::exception& ex) 128 | { 129 | SetPyException(ex); 130 | return NULL; 131 | } 132 | } 133 | 134 | static PyObject* Session_self(Operation *self, PyObject*) 135 | { 136 | Py_INCREF(self); 137 | return (PyObject *)self; 138 | } 139 | 140 | static PyObject* Session_exit(Session* self, PyObject*) 141 | { 142 | AllowThreads(&self->cs, [&]() 143 | { 144 | if (!self->session->IsClosed()) 145 | self->session->Close(); 146 | }); 147 | 148 | Py_RETURN_NONE; 149 | } 150 | 151 | static PyObject* Session_CreateInstance(Session *self, PyObject *args, PyObject *kwds) 152 | { 153 | char* ns = NULL; 154 | PyObject* instance = NULL; 155 | PyObject* operationOptions = NULL; 156 | 157 | static char *kwlist[] = { "ns", "instance", "operation_options", NULL }; 158 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O", kwlist, &ns, 159 | &instance, &operationOptions)) 160 | return NULL; 161 | 162 | try 163 | { 164 | ValidatePyObjectType(instance, L"instance", &InstanceType, L"Instance", false); 165 | ValidatePyObjectType(operationOptions, L"operation_options", 166 | &OperationOptionsType, L"OperationOptions"); 167 | 168 | AllowThreads(&self->cs, [&]() { 169 | self->session->CreateInstance( 170 | ToWstring(ns).c_str(), *((Instance*)instance)->instance, 171 | !CheckPyNone(operationOptions) 172 | ? ((OperationOptions*)operationOptions)->operationOptions 173 | : NULL); 174 | }); 175 | Py_RETURN_NONE; 176 | } 177 | catch (std::exception& ex) 178 | { 179 | SetPyException(ex); 180 | return NULL; 181 | } 182 | } 183 | 184 | static PyObject* Session_ModifyInstance(Session *self, PyObject *args, PyObject *kwds) 185 | { 186 | char* ns = NULL; 187 | PyObject* instance = NULL; 188 | PyObject* operationOptions = NULL; 189 | 190 | static char *kwlist[] = { "ns", "instance", "operation_options", NULL }; 191 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O", kwlist, &ns, 192 | &instance, &operationOptions)) 193 | return NULL; 194 | 195 | try 196 | { 197 | ValidatePyObjectType(instance, L"instance", &InstanceType, L"Instance", false); 198 | ValidatePyObjectType(operationOptions, L"operation_options", 199 | &OperationOptionsType, L"OperationOptions"); 200 | 201 | AllowThreads(&self->cs, [&]() { 202 | self->session->ModifyInstance( 203 | ToWstring(ns).c_str(), *((Instance*)instance)->instance, 204 | !CheckPyNone(operationOptions) 205 | ? ((OperationOptions*)operationOptions)->operationOptions 206 | : NULL); 207 | }); 208 | Py_RETURN_NONE; 209 | } 210 | catch (std::exception& ex) 211 | { 212 | SetPyException(ex); 213 | return NULL; 214 | } 215 | } 216 | 217 | static PyObject* Session_DeleteInstance(Session *self, PyObject *args, PyObject *kwds) 218 | { 219 | char* ns = NULL; 220 | PyObject* instance = NULL; 221 | PyObject* operationOptions = NULL; 222 | 223 | static char *kwlist[] = { "ns", "instance", "operation_options", NULL }; 224 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O", kwlist, &ns, 225 | &instance, &operationOptions)) 226 | return NULL; 227 | 228 | try 229 | { 230 | ValidatePyObjectType(instance, L"instance", &InstanceType, L"Instance", false); 231 | ValidatePyObjectType(operationOptions, L"operation_options", 232 | &OperationOptionsType, L"OperationOptions"); 233 | 234 | AllowThreads(&self->cs, [&]() { 235 | self->session->DeleteInstance( 236 | ToWstring(ns).c_str(), *((Instance*)instance)->instance, 237 | !CheckPyNone(operationOptions) 238 | ? ((OperationOptions*)operationOptions)->operationOptions 239 | : NULL); 240 | }); 241 | Py_RETURN_NONE; 242 | } 243 | catch (std::exception& ex) 244 | { 245 | SetPyException(ex); 246 | return NULL; 247 | } 248 | } 249 | 250 | static PyObject* Session_GetClass(Session *self, PyObject *args, PyObject *kwds) 251 | { 252 | char* ns = NULL; 253 | char* className = NULL; 254 | 255 | static char *kwlist[] = { "ns", "class_name", NULL }; 256 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, &ns, &className)) 257 | return NULL; 258 | 259 | try 260 | { 261 | std::shared_ptr op; 262 | AllowThreads(&self->cs, [&]() { 263 | op = self->session->GetClass(ToWstring(ns).c_str(), ToWstring(className).c_str()); 264 | }); 265 | return (PyObject*)Operation_New(op); 266 | } 267 | catch (std::exception& ex) 268 | { 269 | SetPyException(ex); 270 | return NULL; 271 | } 272 | } 273 | 274 | static PyObject* Session_GetInstance(Session *self, PyObject *args, PyObject *kwds) 275 | { 276 | char* ns = NULL; 277 | PyObject* keyInstance = NULL; 278 | 279 | static char *kwlist[] = { "ns", "key_instance", NULL }; 280 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", kwlist, &ns, &keyInstance)) 281 | return NULL; 282 | 283 | try 284 | { 285 | if (!PyObject_IsInstance(keyInstance, reinterpret_cast(&InstanceType))) 286 | throw MI::TypeConversionException(L"\"instance\" must have type Instance"); 287 | 288 | std::shared_ptr op; 289 | AllowThreads(&self->cs, [&]() { 290 | op = self->session->GetInstance(ToWstring(ns).c_str(), *((Instance*)keyInstance)->instance); 291 | }); 292 | return (PyObject*)Operation_New(op); 293 | } 294 | catch (std::exception& ex) 295 | { 296 | SetPyException(ex); 297 | return NULL; 298 | } 299 | } 300 | 301 | static PyObject* Session_Subscribe(Session *self, PyObject *args, PyObject *kwds) 302 | { 303 | char* ns = NULL; 304 | char* query = NULL; 305 | PyObject* indicationResultCallback = NULL; 306 | PyObject* operationOptions = NULL; 307 | char* dialect = "WQL"; 308 | 309 | static char *kwlist[] = { "ns", "query", "indication_result", "operation_options", "dialect", NULL }; 310 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|OOs", kwlist, &ns, &query, &indicationResultCallback, &operationOptions, &dialect)) 311 | return NULL; 312 | 313 | try 314 | { 315 | if (!CheckPyNone(indicationResultCallback) && !PyCallable_Check(indicationResultCallback)) 316 | { 317 | throw MI::TypeConversionException(L"\"indication_result\" must be callable"); 318 | } 319 | if (!CheckPyNone(operationOptions) && !PyObject_IsInstance(operationOptions, reinterpret_cast(&OperationOptionsType))) 320 | { 321 | throw MI::TypeConversionException(L"\"operation_options\" must have type OperationOptions"); 322 | } 323 | 324 | auto callbacks = !CheckPyNone(indicationResultCallback) ? std::make_shared(indicationResultCallback) : NULL; 325 | 326 | std::shared_ptr op; 327 | AllowThreads(&self->cs, [&]() { 328 | op = self->session->Subscribe(ToWstring(ns).c_str(), ToWstring(query).c_str(), callbacks, 329 | !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions : NULL, 330 | ToWstring(dialect).c_str()); 331 | }); 332 | PyObject* obj = (PyObject*)Operation_New(op); 333 | if (callbacks) 334 | { 335 | self->operationCallbacks->push_back(callbacks); 336 | } 337 | return obj; 338 | } 339 | catch (std::exception& ex) 340 | { 341 | SetPyException(ex); 342 | return NULL; 343 | } 344 | } 345 | 346 | static PyObject* Session_InvokeMethod(Session *self, PyObject *args, PyObject *kwds) 347 | { 348 | PyObject* target = NULL; 349 | char* methodName = NULL; 350 | PyObject* inboundParams = NULL; 351 | PyObject* operationOptions = NULL; 352 | 353 | static char *kwlist[] = { "target", "method_name", "inbound_params", "operation_options", NULL }; 354 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os|OO", kwlist, 355 | &target, &methodName, &inboundParams, &operationOptions)) 356 | return NULL; 357 | 358 | try 359 | { 360 | ValidatePyObjectType(inboundParams, L"inbound_params", &InstanceType, L"Instance"); 361 | ValidatePyObjectType(operationOptions, L"operation_options", 362 | &OperationOptionsType, L"OperationOptions"); 363 | 364 | std::shared_ptr op; 365 | if (PyObject_IsInstance(target, reinterpret_cast(&InstanceType))) 366 | { 367 | AllowThreads(&self->cs, [&]() { 368 | op = self->session->InvokeMethod(*((Instance*)target)->instance, ToWstring(methodName).c_str(), 369 | !CheckPyNone(inboundParams) ? ((Instance*)inboundParams)->instance : NULL, 370 | !CheckPyNone(operationOptions) 371 | ? ((OperationOptions*)operationOptions)->operationOptions 372 | : NULL); 373 | }); 374 | } 375 | else if (PyObject_IsInstance(target, reinterpret_cast(&ClassType))) 376 | { 377 | AllowThreads(&self->cs, [&]() { 378 | auto miClass = ((Class*)target)->miClass; 379 | op = self->session->InvokeMethod(miClass->GetNameSpace(), miClass->GetClassName(), ToWstring(methodName).c_str(), 380 | !CheckPyNone(inboundParams) ? ((Instance*)inboundParams)->instance : NULL, 381 | !CheckPyNone(operationOptions) 382 | ? ((OperationOptions*)operationOptions)->operationOptions 383 | : NULL); 384 | }); 385 | } 386 | else 387 | { 388 | throw MI::TypeConversionException(L"\"target\" must have type Instance or Class"); 389 | } 390 | 391 | if (op) 392 | { 393 | return (PyObject*)Operation_New(op); 394 | } 395 | Py_RETURN_NONE; 396 | } 397 | catch (std::exception& ex) 398 | { 399 | SetPyException(ex); 400 | return NULL; 401 | } 402 | } 403 | 404 | Session* Session_New(std::shared_ptr session) 405 | { 406 | Session* obj = (Session*)Session_new(&SessionType, NULL, NULL); 407 | obj->session = session; 408 | return obj; 409 | } 410 | 411 | static PyMemberDef Session_members[] = { 412 | { NULL } /* Sentinel */ 413 | }; 414 | 415 | static PyMethodDef Session_methods[] = { 416 | { "exec_query", (PyCFunction)Session_ExecQuery, METH_VARARGS | METH_KEYWORDS, "Executes a query." }, 417 | { "invoke_method", (PyCFunction)Session_InvokeMethod, METH_VARARGS | METH_KEYWORDS, "Invokes a method." }, 418 | { "get_associators", (PyCFunction)Session_GetAssociators, METH_VARARGS | METH_KEYWORDS, "Retrieves the associators of an instance." }, 419 | { "get_class", (PyCFunction)Session_GetClass, METH_VARARGS | METH_KEYWORDS, "Gets a class." }, 420 | { "create_instance", (PyCFunction)Session_CreateInstance, METH_VARARGS | METH_KEYWORDS, "Creates an instance." }, 421 | { "modify_instance", (PyCFunction)Session_ModifyInstance, METH_VARARGS | METH_KEYWORDS, "Modifies an instance." }, 422 | { "delete_instance", (PyCFunction)Session_DeleteInstance, METH_VARARGS | METH_KEYWORDS, "Deletes an instance." }, 423 | { "get_instance", (PyCFunction)Session_GetInstance, METH_VARARGS | METH_KEYWORDS, "Retrieves an instance." }, 424 | { "subscribe", (PyCFunction)Session_Subscribe, METH_VARARGS | METH_KEYWORDS, "Subscribes to events." }, 425 | { "close", (PyCFunction)Session_Close, METH_NOARGS, "Closes the session." }, 426 | { "__enter__", (PyCFunction)Session_self, METH_NOARGS, "" }, 427 | { "__exit__", (PyCFunction)Session_exit, METH_VARARGS, "" }, 428 | { NULL } /* Sentinel */ 429 | }; 430 | 431 | PyTypeObject SessionType = { 432 | PyVarObject_HEAD_INIT(NULL, 0) 433 | "mi.Session", /*tp_name*/ 434 | sizeof(Session), /*tp_basicsize*/ 435 | 0, /*tp_itemsize*/ 436 | (destructor)Session_dealloc, /*tp_dealloc*/ 437 | 0, /*tp_print*/ 438 | 0, /*tp_getattr*/ 439 | 0, /*tp_setattr*/ 440 | 0, /*tp_compare*/ 441 | 0, /*tp_repr*/ 442 | 0, /*tp_as_number*/ 443 | 0, /*tp_as_sequence*/ 444 | 0, /*tp_as_mapping*/ 445 | 0, /*tp_hash */ 446 | 0, /*tp_call*/ 447 | 0, /*tp_str*/ 448 | 0, /*tp_getattro*/ 449 | 0, /*tp_setattro*/ 450 | 0, /*tp_as_buffer*/ 451 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 452 | "Session objects", /* tp_doc */ 453 | 0, /* tp_traverse */ 454 | 0, /* tp_clear */ 455 | 0, /* tp_richcompare */ 456 | 0, /* tp_weaklistoffset */ 457 | 0, /* tp_iter */ 458 | 0, /* tp_iternext */ 459 | Session_methods, /* tp_methods */ 460 | Session_members, /* tp_members */ 461 | 0, /* tp_getset */ 462 | 0, /* tp_base */ 463 | 0, /* tp_dict */ 464 | 0, /* tp_descr_get */ 465 | 0, /* tp_descr_set */ 466 | 0, /* tp_dictoffset */ 467 | (initproc)Session_init, /* tp_init */ 468 | 0, /* tp_alloc */ 469 | Session_new, /* tp_new */ 470 | }; 471 | -------------------------------------------------------------------------------- /PyMI/Session.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct { 9 | PyObject_HEAD 10 | /* Type-specific fields go here. */ 11 | std::shared_ptr session; 12 | std::shared_ptr>> operationCallbacks; 13 | CRITICAL_SECTION cs; 14 | } Session; 15 | 16 | extern PyTypeObject SessionType; 17 | 18 | Session* Session_New(std::shared_ptr session); 19 | -------------------------------------------------------------------------------- /PyMI/Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "PyMI.h" 3 | #include "Utils.h" 4 | #include "instance.h" 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | bool CheckPyNone(PyObject* obj) 11 | { 12 | return !obj || obj == Py_None; 13 | } 14 | 15 | void AllowThreads(PCRITICAL_SECTION cs, std::function action) 16 | { 17 | PyThreadState* _save = nullptr; 18 | try 19 | { 20 | // Py_BEGIN_ALLOW_THREADS 21 | _save = PyEval_SaveThread(); 22 | if (cs) 23 | { 24 | ::EnterCriticalSection(cs); 25 | } 26 | 27 | action(); 28 | 29 | if (cs) 30 | { 31 | ::LeaveCriticalSection(cs); 32 | } 33 | // Py_END_ALLOW_THREADS 34 | PyEval_RestoreThread(_save); 35 | } 36 | catch (std::exception&) 37 | { 38 | if (cs) 39 | { 40 | ::LeaveCriticalSection(cs); 41 | } 42 | if (_save) 43 | { 44 | PyEval_RestoreThread(_save); 45 | } 46 | throw; 47 | } 48 | } 49 | 50 | void CallPythonCallback(PyObject* callable, const char* format, ...) 51 | { 52 | va_list vargs; 53 | va_start(vargs, format); 54 | PyObject* arglist = Py_VaBuildValue(format, vargs); 55 | va_end(vargs); 56 | 57 | if (arglist) 58 | { 59 | PyObject* result = PyObject_CallObject(callable, arglist); 60 | Py_DECREF(arglist); 61 | if (result) 62 | { 63 | Py_DECREF(result); 64 | } 65 | else 66 | { 67 | PyErr_Print(); 68 | } 69 | } 70 | else 71 | { 72 | PyErr_Print(); 73 | } 74 | } 75 | 76 | PyObject* PyDeltaFromMIInterval(const MI_Interval& interval) 77 | { 78 | return PyDelta_FromDSU(interval.days, interval.hours * 3600 + interval.minutes * 60 + interval.seconds, interval.microseconds); 79 | } 80 | 81 | void MIIntervalFromPyDelta(PyObject* pyDelta, MI_Interval& interval) 82 | { 83 | ZeroMemory(&interval, sizeof(MI_Interval)); 84 | 85 | int days = PyDateTime_DELTA_GET_DAYS(pyDelta); 86 | if (days < 0) 87 | { 88 | throw MI::Exception(L"Negative datetime.timedelta intervals are not supported"); 89 | } 90 | 91 | interval.days = (MI_Uint32)days; 92 | MI_Uint32 daySeconds = (MI_Uint32)PyDateTime_DELTA_GET_SECONDS(pyDelta); 93 | interval.hours = daySeconds / 3600; 94 | interval.minutes = (daySeconds - interval.hours * 3600) / 60; 95 | interval.seconds = daySeconds - interval.hours * 3600 - interval.minutes * 60; 96 | interval.microseconds = (MI_Uint32)PyDateTime_DELTA_GET_MICROSECONDS(pyDelta); 97 | } 98 | 99 | void GetIndexOrName(PyObject *item, std::wstring& name, Py_ssize_t& i) 100 | { 101 | name.clear(); 102 | i = -1; 103 | 104 | #ifndef IS_PY3K 105 | if (PyString_Check(item)) 106 | { 107 | char* s = PyString_AsString(item); 108 | DWORD len = lstrlenA(s) + 1; 109 | wchar_t* w = new wchar_t[len]; 110 | 111 | if (::MultiByteToWideChar(CP_ACP, 0, s, len, w, len) != len) 112 | { 113 | delete [] w; 114 | throw MI::Exception(L"MultiByteToWideChar failed"); 115 | } 116 | name.assign(w, len); 117 | delete[] w; 118 | } 119 | else 120 | #endif 121 | if (PyUnicode_Check(item)) 122 | { 123 | Py_ssize_t len = PyUnicode_GetLength(item) + 1; 124 | wchar_t* w = new wchar_t[len]; 125 | 126 | if (PyUnicode_AsWideChar((PYUNICODEASVARCHARARG1TYPE*)item, w, len) < 0) 127 | { 128 | delete[] w; 129 | throw MI::Exception(L"PyUnicode_AsWideChar failed"); 130 | } 131 | name.assign(w, len); 132 | delete[] w; 133 | } 134 | else if (PyIndex_Check(item)) 135 | { 136 | i = PyNumber_AsSsize_t(item, PyExc_IndexError); 137 | if (i == -1 && PyErr_Occurred()) 138 | throw MI::Exception(L"Index error"); 139 | } 140 | else 141 | throw MI::Exception(L"Invalid name or index"); 142 | } 143 | 144 | std::wstring Py2WString(PyObject* pyValue) 145 | { 146 | auto len = PyUnicode_GetLength(pyValue) + 1; 147 | wchar_t* w = new wchar_t[len]; 148 | 149 | if (PyUnicode_AsWideChar((PYUNICODEASVARCHARARG1TYPE*)pyValue, w, len) < 0) 150 | { 151 | delete[] w; 152 | throw MI::Exception(L"PyUnicode_AsWideChar failed"); 153 | } 154 | 155 | auto value = std::wstring(w, len); 156 | delete[] w; 157 | return value; 158 | } 159 | 160 | std::shared_ptr Py2StrMIValue(PyObject* pyValue) 161 | { 162 | PyObject* pyStrValue = PyObject_CallMethod(pyValue, "__str__", NULL); 163 | if (!pyStrValue) 164 | { 165 | throw MI::Exception(L"PyObject_CallMethod failed for __str__"); 166 | } 167 | 168 | try 169 | { 170 | #ifdef IS_PY3K 171 | auto value = Py2WString(pyStrValue); 172 | #else 173 | auto value = std::string(PyString_AsString(pyStrValue)); 174 | #endif 175 | Py_DECREF(pyStrValue); 176 | return MI::MIValue::FromString(value); 177 | } 178 | catch (std::exception&) 179 | { 180 | Py_DECREF(pyStrValue); 181 | throw; 182 | } 183 | } 184 | 185 | std::shared_ptr Str2PyLong2MI(char* strValue, MI_Type valueType) 186 | { 187 | auto obj = PyLong_FromString(strValue, NULL, 10); 188 | if (!obj) 189 | { 190 | throw MI::TypeConversionException(); 191 | } 192 | try 193 | { 194 | auto retVal = Py2MI(obj, valueType); 195 | Py_DECREF(obj); 196 | return retVal; 197 | } 198 | catch (std::exception&) 199 | { 200 | Py_DECREF(obj); 201 | throw; 202 | } 203 | } 204 | 205 | std::shared_ptr Py2MI(PyObject* pyValue, MI_Type valueType) 206 | { 207 | if (pyValue == Py_None) 208 | { 209 | return std::make_shared(valueType); 210 | } 211 | if (PyObject_IsInstance(pyValue, reinterpret_cast(&PyBool_Type))) 212 | { 213 | return MI::MIValue::FromBoolean(PyObject_IsTrue(pyValue) ? MI_TRUE : MI_FALSE); 214 | } 215 | else if (PyObject_IsInstance(pyValue, reinterpret_cast(&PyLong_Type))) 216 | { 217 | switch (valueType) 218 | { 219 | case MI_BOOLEAN: 220 | return MI::MIValue::FromBoolean(PyLong_AsLong(pyValue) != 0); 221 | case MI_UINT8: 222 | return MI::MIValue::FromUint8((MI_Uint8)PyLong_AsUnsignedLong(pyValue)); 223 | case MI_SINT8: 224 | return MI::MIValue::FromSint8((MI_Sint8)PyLong_AsLong(pyValue)); 225 | case MI_UINT16: 226 | return MI::MIValue::FromUint16((MI_Uint16)PyLong_AsUnsignedLong(pyValue)); 227 | case MI_SINT16: 228 | return MI::MIValue::FromSint16((MI_Sint16)PyLong_AsLong(pyValue)); 229 | case MI_CHAR16: 230 | return MI::MIValue::FromChar16((MI_Char16)PyLong_AsLong(pyValue)); 231 | case MI_UINT32: 232 | return MI::MIValue::FromUint32(PyLong_AsUnsignedLong(pyValue)); 233 | case MI_SINT32: 234 | return MI::MIValue::FromSint32(PyLong_AsLong(pyValue)); 235 | case MI_UINT64: 236 | return MI::MIValue::FromUint64(PyLong_AsUnsignedLongLong(pyValue)); 237 | case MI_SINT64: 238 | return MI::MIValue::FromSint64(PyLong_AsLongLong(pyValue)); 239 | case MI_REAL32: 240 | return MI::MIValue::FromReal32((MI_Real32)PyLong_AsDouble(pyValue)); 241 | case MI_REAL64: 242 | return MI::MIValue::FromReal64(PyLong_AsDouble(pyValue)); 243 | case MI_STRING: 244 | return Py2StrMIValue(pyValue); 245 | default: 246 | throw MI::TypeConversionException(); 247 | } 248 | } 249 | #ifndef IS_PY3K 250 | else if (PyObject_IsInstance(pyValue, reinterpret_cast(&PyInt_Type))) 251 | { 252 | switch (valueType) 253 | { 254 | case MI_BOOLEAN: 255 | return MI::MIValue::FromBoolean(PyInt_AsLong(pyValue) != 0); 256 | case MI_UINT8: 257 | return MI::MIValue::FromUint8((MI_Uint8)PyInt_AsLong(pyValue)); 258 | case MI_SINT8: 259 | return MI::MIValue::FromSint8((MI_Sint8)PyInt_AsLong(pyValue)); 260 | case MI_UINT16: 261 | return MI::MIValue::FromUint16((MI_Uint16)PyInt_AsLong(pyValue)); 262 | case MI_SINT16: 263 | return MI::MIValue::FromSint16((MI_Sint16)PyInt_AsLong(pyValue)); 264 | case MI_CHAR16: 265 | return MI::MIValue::FromChar16((MI_Char16)PyLong_AsLong(pyValue)); 266 | case MI_UINT32: 267 | return MI::MIValue::FromUint32((MI_Uint32)PyInt_AsLong(pyValue)); 268 | case MI_SINT32: 269 | return MI::MIValue::FromSint32((MI_Sint32)PyInt_AsLong(pyValue)); 270 | case MI_UINT64: 271 | return MI::MIValue::FromUint64((MI_Uint64)PyInt_AsLong(pyValue)); 272 | case MI_SINT64: 273 | return MI::MIValue::FromSint64((MI_Sint64)PyInt_AsLong(pyValue)); 274 | case MI_REAL32: 275 | return MI::MIValue::FromReal32((MI_Real32)PyInt_AsLong(pyValue)); 276 | case MI_REAL64: 277 | return MI::MIValue::FromReal64((MI_Real64)PyInt_AsLong(pyValue)); 278 | case MI_STRING: 279 | return Py2StrMIValue(pyValue); 280 | default: 281 | throw MI::TypeConversionException(); 282 | } 283 | } 284 | else if (PyObject_IsInstance(pyValue, reinterpret_cast(&PyString_Type))) 285 | { 286 | switch (valueType) 287 | { 288 | case MI_STRING: 289 | return MI::MIValue::FromString(std::string(PyString_AsString(pyValue))); 290 | case MI_SINT8: 291 | case MI_UINT8: 292 | case MI_SINT16: 293 | case MI_UINT16: 294 | case MI_CHAR16: 295 | case MI_SINT32: 296 | case MI_UINT32: 297 | case MI_SINT64: 298 | case MI_UINT64: 299 | case MI_REAL32: 300 | case MI_REAL64: 301 | return Str2PyLong2MI(PyString_AsString(pyValue), valueType); 302 | default: 303 | throw MI::TypeConversionException(); 304 | } 305 | } 306 | #endif 307 | else if (PyObject_IsInstance(pyValue, reinterpret_cast(&PyUnicode_Type))) 308 | { 309 | switch (valueType) 310 | { 311 | case MI_STRING: 312 | return MI::MIValue::FromString(Py2WString(pyValue)); 313 | case MI_SINT8: 314 | case MI_UINT8: 315 | case MI_SINT16: 316 | case MI_UINT16: 317 | case MI_CHAR16: 318 | case MI_SINT32: 319 | case MI_UINT32: 320 | case MI_SINT64: 321 | case MI_UINT64: 322 | case MI_REAL32: 323 | case MI_REAL64: 324 | { 325 | auto str = Py2WString(pyValue); 326 | std::wstring_convert, wchar_t> cv; 327 | return Str2PyLong2MI((char*)cv.to_bytes(str).c_str(), valueType); 328 | } 329 | default: 330 | throw MI::TypeConversionException(); 331 | } 332 | } 333 | else if (PyObject_IsInstance(pyValue, reinterpret_cast(&InstanceType))) 334 | { 335 | switch (valueType) 336 | { 337 | case MI_INSTANCE: 338 | // TODO: Set the same ScopeContextOwner as the container instance / class 339 | return MI::MIValue::FromInstance(*((Instance*)pyValue)->instance); 340 | case MI_REFERENCE: 341 | // TODO: Set the same ScopeContextOwner as the container instance / class 342 | return MI::MIValue::FromReference(*((Instance*)pyValue)->instance); 343 | default: 344 | throw MI::TypeConversionException(); 345 | } 346 | } 347 | else if (PyObject_IsInstance(pyValue, reinterpret_cast(&PyTuple_Type)) || 348 | PyObject_IsInstance(pyValue, reinterpret_cast(&PyList_Type))) 349 | { 350 | bool isTuple = PyObject_IsInstance(pyValue, reinterpret_cast(&PyTuple_Type)) != 0; 351 | Py_ssize_t size = 0; 352 | if (isTuple) 353 | { 354 | size = PyTuple_Size(pyValue); 355 | } 356 | else 357 | { 358 | size = PyList_Size(pyValue); 359 | } 360 | 361 | MI_Type itemType = (MI_Type)(valueType ^ MI_ARRAY); 362 | auto value = MI::MIValue::CreateArray((unsigned)size, valueType); 363 | 364 | for (Py_ssize_t i = 0; i < size; i++) 365 | { 366 | PyObject* pyObj = NULL; 367 | if (isTuple) 368 | { 369 | pyObj = PyTuple_GetItem(pyValue, i); 370 | } 371 | else 372 | { 373 | pyObj = PyList_GetItem(pyValue, i); 374 | } 375 | 376 | auto tmpValue = Py2MI(pyObj, itemType); 377 | value->SetArrayItem(*tmpValue, (unsigned)i); 378 | } 379 | return value; 380 | } 381 | else 382 | { 383 | switch (valueType) 384 | { 385 | case MI_STRING: 386 | return Py2StrMIValue(pyValue); 387 | default: 388 | throw MI::TypeConversionException(); 389 | } 390 | } 391 | } 392 | 393 | PyObject* MIArray2PyTuple(const MI_Value& value, MI_Type itemType) 394 | { 395 | // All array members of the MI_Value union have "pointer", "size" members. 396 | // It is safe to rely on one instead of referencing value.stringa, value.booleana, etc 397 | MI_Uint32 size = value.uint8a.size; 398 | PyObject* pyObj = PyTuple_New(size); 399 | unsigned itemSize = MI::MIValue::GetItemSize(itemType); 400 | for (MI_Uint32 i = 0; i < size; i++) 401 | { 402 | MI_Value tmpVal; 403 | memcpy(&tmpVal, &value.uint8a.data[i * itemSize], itemSize); 404 | if (PyTuple_SetItem(pyObj, i, MI2Py(tmpVal, itemType, 0))) 405 | { 406 | Py_DECREF(pyObj); 407 | throw MI::Exception(L"PyTuple_SetItem failed"); 408 | } 409 | } 410 | return pyObj; 411 | } 412 | 413 | PyObject* MI2Py(const MI_Value& value, MI_Type valueType, MI_Uint32 flags) 414 | { 415 | if (flags & MI_FLAG_NULL) 416 | Py_RETURN_NONE; 417 | 418 | if (valueType & MI_ARRAY) 419 | { 420 | return MIArray2PyTuple(value, (MI_Type)(valueType ^ MI_ARRAY)); 421 | } 422 | 423 | switch (valueType) 424 | { 425 | case MI_BOOLEAN: 426 | return PyBool_FromLong(value.boolean); 427 | case MI_SINT8: 428 | return PyLong_FromLong(value.sint8); 429 | case MI_UINT8: 430 | return PyLong_FromUnsignedLong(value.uint8); 431 | case MI_SINT16: 432 | return PyLong_FromLong(value.sint16); 433 | case MI_UINT16: 434 | return PyLong_FromUnsignedLong(value.uint16); 435 | case MI_SINT32: 436 | return PyLong_FromLong(value.sint32); 437 | case MI_UINT32: 438 | return PyLong_FromUnsignedLong(value.uint32); 439 | case MI_SINT64: 440 | return PyLong_FromLongLong(value.sint64); 441 | case MI_UINT64: 442 | return PyLong_FromUnsignedLongLong(value.uint64); 443 | case MI_REAL32: 444 | return PyFloat_FromDouble(value.real32); 445 | case MI_REAL64: 446 | return PyFloat_FromDouble(value.real64); 447 | case MI_CHAR16: 448 | return PyLong_FromLong(value.char16); 449 | case MI_DATETIME: 450 | // TODO: understand where this import needs to be called 451 | PyDateTime_IMPORT; 452 | if (value.datetime.isTimestamp) 453 | { 454 | const MI_Timestamp& ts = value.datetime.u.timestamp; 455 | // TODO: Add timezone support! 456 | return PyDateTime_FromDateAndTime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, ts.microseconds); 457 | } 458 | else 459 | { 460 | return PyDeltaFromMIInterval(value.datetime.u.interval); 461 | } 462 | break; 463 | case MI_STRING: 464 | return PyUnicode_FromWideChar(value.string, wcslen(value.string)); 465 | case MI_INSTANCE: 466 | return (PyObject*)Instance_New(std::make_shared(value.instance, false)); 467 | case MI_REFERENCE: 468 | return (PyObject*)Instance_New(std::make_shared(value.reference, false)); 469 | default: 470 | throw MI::TypeConversionException(); 471 | } 472 | } 473 | 474 | void SetPyException(const std::exception& ex) 475 | { 476 | const char* message = ex.what(); 477 | if (dynamic_cast(&ex)) 478 | { 479 | PyErr_SetString(PyExc_TypeError, message); 480 | } 481 | else 482 | { 483 | PyObject* d = PyDict_New(); 484 | PyObject* pyEx = nullptr; 485 | if (dynamic_cast(&ex)) 486 | { 487 | pyEx = PyMITimeoutError; 488 | } 489 | else 490 | { 491 | pyEx = PyMIError; 492 | } 493 | 494 | if (dynamic_cast(&ex)) 495 | { 496 | auto miex = static_cast(&ex); 497 | PyDict_SetItemString(d, "error_code", PyLong_FromUnsignedLong(miex->GetErrorCode())); 498 | PyDict_SetItemString(d, "mi_result", PyLong_FromUnsignedLong(miex->GetResult())); 499 | } 500 | 501 | PyDict_SetItemString(d, "message", PyUnicode_FromString(message)); 502 | PyErr_SetObject(pyEx, d); 503 | Py_DECREF(d); 504 | } 505 | } 506 | 507 | void ValidatePyObjectType(PyObject* obj, const std::wstring& objName, 508 | PyTypeObject* expectedType, const std::wstring& expectedTypeName, 509 | bool allowNone) 510 | { 511 | bool isNone = CheckPyNone(obj); 512 | 513 | if ((isNone && !allowNone) || 514 | (!isNone && !PyObject_IsInstance(obj, 515 | reinterpret_cast(expectedType)))) 516 | throw MI::TypeConversionException( 517 | L"\"" + objName + L"\"must have type " + expectedTypeName); 518 | } 519 | 520 | std::wstring ToWstring(const std::string& inString) 521 | { 522 | if (inString.empty()) 523 | { 524 | return L""; 525 | } 526 | 527 | int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, &inString.at(0), (int)inString.size(), nullptr, 0); 528 | if (sizeNeeded <= 0) 529 | { 530 | DWORD err = GetLastError(); 531 | throw MI::TypeConversionException( 532 | L"wstring conversion failed. Error: " + std::to_wstring(err)); 533 | } 534 | 535 | std::wstring result(sizeNeeded, 0); 536 | sizeNeeded = MultiByteToWideChar( 537 | CP_UTF8, 0, &inString.at(0), (int)inString.size(), 538 | &result.at(0), sizeNeeded); 539 | if (sizeNeeded <= 0) { 540 | DWORD err = GetLastError(); 541 | throw MI::TypeConversionException( 542 | L"wstring conversion failed. Error: " + std::to_wstring(err)); 543 | } 544 | 545 | return result; 546 | } 547 | -------------------------------------------------------------------------------- /PyMI/Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "mi++.h" 10 | 11 | PyObject* MI2Py(const MI_Value& value, MI_Type valueType, MI_Uint32 flags); 12 | std::shared_ptr Py2MI(PyObject* pyValue, MI_Type valueType); 13 | void GetIndexOrName(PyObject *item, std::wstring& name, Py_ssize_t& i); 14 | void SetPyException(const std::exception& ex); 15 | void AllowThreads(PCRITICAL_SECTION cs, std::function action); 16 | void CallPythonCallback(PyObject* callable, const char* format, ...); 17 | void MIIntervalFromPyDelta(PyObject* pyDelta, MI_Interval& interval); 18 | PyObject* PyDeltaFromMIInterval(const MI_Interval& interval); 19 | bool CheckPyNone(PyObject* obj); 20 | void ValidatePyObjectType(PyObject* obj, const std::wstring& objName, 21 | PyTypeObject* expectedType, const std::wstring& expectedTypeName, 22 | bool allowNone = true); 23 | std::wstring ToWstring(const std::string& inString); -------------------------------------------------------------------------------- /PyMI/setup_vs.py: -------------------------------------------------------------------------------- 1 | # This module is used by the Visual Studio solution. 2 | 3 | import git 4 | import os 5 | from setuptools import setup, find_packages 6 | from setuptools.command import build_clib 7 | 8 | 9 | def get_git_version(): 10 | g = git.Git(".") 11 | return g.describe(tags=True) 12 | 13 | 14 | def read(fname): 15 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 16 | 17 | 18 | setup( 19 | name="PyMI", 20 | version=get_git_version(), 21 | author="Alessandro Pilotti", 22 | author_email="info@cloudbasesolutions.com", 23 | description=("Windows Management Infrastructure API for Python."), 24 | license="Apache 2.0", 25 | keywords="wmi mi windows", 26 | url="https://github.com/cloudbase/PyMI", 27 | packages=find_packages("src") + find_packages(".."), 28 | package_dir={'mi': 'src/mi', 'wmi': '../wmi'}, 29 | # Note: this extension is compiled in Visual Studio 30 | package_data={'mi': ['mi.pyd', 'mi.pdb']}, 31 | long_description=read('README.rst'), 32 | install_requires=['setuptools'], 33 | classifiers=[ 34 | 'Development Status :: 5 - Production/Stable', 35 | 'Programming Language :: Python :: 2', 36 | 'Programming Language :: Python :: 2.7', 37 | 'Programming Language :: Python :: 3', 38 | 'Programming Language :: Python :: 3.4', 39 | 'Programming Language :: Python :: 3.5', 40 | 'Environment :: Win32 (MS Windows)', 41 | 'Intended Audience :: Developers', 42 | 'Intended Audience :: System Administrators', 43 | 'License :: OSI Approved :: Apache Software License', 44 | 'Natural Language :: English', 45 | 'Operating System :: Microsoft :: Windows', 46 | 'Topic :: System :: Systems Administration' 47 | ], 48 | ) 49 | -------------------------------------------------------------------------------- /PyMI/src/mi/__init__.py: -------------------------------------------------------------------------------- 1 | from .mi import * # nopep8 2 | -------------------------------------------------------------------------------- /PyMI/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // PyMI.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | // Uncomment to enable memory leak detection 7 | // Get VLD from: https://vld.codeplex.com/ 8 | //#include 9 | -------------------------------------------------------------------------------- /PyMI/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | #include 14 | 15 | #ifdef _DEBUG 16 | #define _DEBUG_TMP 17 | #undef _DEBUG 18 | #endif 19 | 20 | #include 21 | #include 22 | 23 | #ifdef _DEBUG_TMP 24 | #define _DEBUG 1 25 | #undef _DEBUG_TMP 26 | #endif 27 | 28 | #if PY_MAJOR_VERSION >= 3 29 | #define IS_PY3K 30 | #define PYUNICODEASVARCHARARG1TYPE PyObject 31 | #else 32 | #define PYUNICODEASVARCHARARG1TYPE PyUnicodeObject 33 | 34 | #define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) 35 | #define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds) 36 | #define PyDateTime_DELTA_GET_MICROSECONDS(o) \ 37 | (((PyDateTime_Delta*)o)->microseconds) 38 | 39 | #endif 40 | 41 | // TODO: reference additional headers your program requires here 42 | -------------------------------------------------------------------------------- /PyMI/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #define _WIN32_WINNT 0x0a00 9 | 10 | #include 11 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | This repository includes the following projects: 2 | 3 | MI++ 4 | ---- 5 | 6 | A C++ wrapper over the Windows Management Infrastructure API. 7 | 8 | PyMI 9 | ---- 10 | 11 | Windows Management Infrastructure API for Python. 12 | 13 | For more details read the project's `README.rst `_. 14 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pbr!=2.1.0,>=2.0.0 # Apache-2.0 2 | six>=1.10.0 # MIT 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = PyMI 3 | summary = Windows Management Infrastructure API for Python. 4 | author = Alessandro Pilotti 5 | author-email = info@cloudbasesolutions.com 6 | home-page = https://github.com/cloudbase/PyMI 7 | description-file = PyMI/README.rst 8 | long_description_content_type = text/x-rst 9 | classifier = 10 | Development Status :: 5 - Production/Stable 11 | Programming Language :: Python :: 2 12 | Programming Language :: Python :: 2.7 13 | Programming Language :: Python :: 3 14 | Programming Language :: Python :: 3.4 15 | Programming Language :: Python :: 3.5 16 | Programming Language :: Python :: 3.6 17 | Programming Language :: Python :: 3.7 18 | Programming Language :: Python :: 3.8 19 | Programming Language :: Python :: 3.9 20 | Programming Language :: Python :: 3.10 21 | Programming Language :: Python :: 3.11 22 | Programming Language :: Python :: 3.12 23 | Environment :: Win32 (MS Windows) 24 | Intended Audience :: Developers 25 | Intended Audience :: System Administrators 26 | License :: OSI Approved :: Apache Software License 27 | Natural Language :: English 28 | Operating System :: Microsoft :: Windows 29 | Topic :: System :: Systems Administration 30 | keywords = wmi mi windows 31 | 32 | [files] 33 | # mi.pyd is declared separately as an extension. 34 | packages = wmi 35 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils import _msvccompiler 2 | from distutils import ccompiler 3 | import os 4 | import setuptools 5 | import sys 6 | 7 | try: 8 | import multiprocessing # noqa 9 | except ImportError: 10 | pass 11 | 12 | 13 | # MSVCP140.dll isn't included by Python along with the C runtime, 14 | # for which reason we're going to statically link it for now. 15 | # This can be disabled using the PYMI_VCRUNTIME_DYNAMIC_LINKING 16 | # flag. 17 | # Unfortunately distutils harcodes the "/MD" flag. 18 | class Compiler(_msvccompiler.MSVCCompiler): 19 | def initialize(self, *args, **kwargs): 20 | super(Compiler, self).initialize(*args, **kwargs) 21 | 22 | dynamically_link_runtime = os.environ.get( 23 | "PYMI_VCRUNTIME_DYNAMIC_LINKING", "").lower() in ( 24 | "yes", "y", "1", "true", "t") 25 | if not dynamically_link_runtime: 26 | self._statically_link_runtime() 27 | 28 | def _statically_link_runtime(self): 29 | if '/MD' in self.compile_options: 30 | self.compile_options.remove('/MD') 31 | self.compile_options.append('/MT') 32 | if '/MDd' in self.compile_options_debug: 33 | self.compile_options_debug.remove('/MDd') 34 | self.compile_options_debug.append('/MTd') 35 | 36 | 37 | def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0): 38 | return Compiler(None, dry_run, force) 39 | 40 | 41 | if 'MSC' in sys.version: 42 | ccompiler.new_compiler = new_compiler 43 | 44 | 45 | # Setuptools requires relative paths 46 | mi_dir = 'MI' 47 | pymi_dir = 'PyMI' 48 | 49 | libmipp = ( 50 | 'mi++', 51 | {'sources': [os.path.join(mi_dir, src) for src in 52 | ['MI++.cpp', 'MIExceptions.cpp', 'MIValue.cpp']], 53 | 'macros': [('UNICODE', 1), ('_UNICODE', 1)]} 54 | ) 55 | pymi_ext = setuptools.Extension( 56 | "mi", 57 | sources=[os.path.join(pymi_dir, src) for src in 58 | ['Application.cpp', 59 | 'Callbacks.cpp', 60 | 'Class.cpp', 61 | 'DestinationOptions.cpp', 62 | 'Instance.cpp', 63 | 'MiError.cpp', 64 | 'Operation.cpp', 65 | 'OperationOptions.cpp', 66 | 'PyMI.cpp', 67 | 'Serializer.cpp', 68 | 'Session.cpp', 69 | 'stdafx.cpp', 70 | 'Utils.cpp']], 71 | libraries=['mi++', 'mi', 'kernel32', 'user32', 'gdi32', 72 | 'winspool', 'comdlg32', 'advapi32', 'shell32', 73 | 'ole32', 'oleaut32', 'uuid', 'odbc32', 74 | 'odbccp32'], 75 | include_dirs=[mi_dir], 76 | define_macros=[('UNICODE', 1), ('_UNICODE', 1)], 77 | ) 78 | 79 | setuptools.setup( 80 | libraries=[libmipp], 81 | ext_modules=[pymi_ext], 82 | setup_requires=['pbr>=2.0.0'], 83 | pbr=True 84 | ) 85 | -------------------------------------------------------------------------------- /wmi/samples/benchmark.py: -------------------------------------------------------------------------------- 1 | def test_mi(): 2 | import mi 3 | 4 | with mi.Application() as a: 5 | with a.create_session(protocol=mi.PROTOCOL_WMIDCOM) as s: 6 | with s.exec_query( 7 | u"root\\cimv2", u"select * from win32_process") as q: 8 | i = q.get_next_instance() 9 | while i is not None: 10 | s = i[u'name'] 11 | i = q.get_next_instance() 12 | 13 | 14 | def test_wmi(): 15 | import wmi 16 | 17 | conn = wmi.WMI(moniker="root\\cimv2") 18 | for i in conn.win32_process(): 19 | s = i.name 20 | 21 | 22 | if __name__ == '__main__': 23 | import timeit 24 | print(timeit.timeit( 25 | "test_mi()", setup="from __main__ import test_mi", number=20)) 26 | print(timeit.timeit( 27 | "test_wmi()", setup="from __main__ import test_wmi", number=20)) 28 | -------------------------------------------------------------------------------- /wmi/samples/benchmark2.py: -------------------------------------------------------------------------------- 1 | import imp 2 | import os 3 | 4 | from distutils import sysconfig 5 | 6 | path = os.path.dirname(os.path.abspath(__file__)) 7 | mi_wmi_path = os.path.join( 8 | os.path.join(os.path.dirname(path), "wmi"), "__init__.py") 9 | 10 | path = sysconfig.get_python_lib() 11 | old_wmi_path = os.path.join(path, "wmi.py") 12 | 13 | VM_NAME = 'vm1' 14 | 15 | 16 | def test_mi(): 17 | import mi 18 | 19 | with mi.Application() as a: 20 | with a.create_session(protocol=mi.PROTOCOL_WMIDCOM) as s: 21 | with s.exec_query( 22 | u"root/virtualization/v2", 23 | u"select * from Msvm_VirtualSystemManagementService") as q: 24 | svc = q.get_next_instance() 25 | 26 | c = svc.get_class() 27 | p = a.create_method_params(c, u"GetSummaryInformation") 28 | 29 | with s.exec_query( 30 | u"root/virtualization/v2", 31 | u"select * from Msvm_ComputerSystem where " 32 | "ElementName = '%s'" % VM_NAME) as q1: 33 | vm = q1.get_next_instance() 34 | 35 | with s.get_associators( 36 | u"root/virtualization/v2", 37 | vm, assoc_class=u"Msvm_SettingsDefineState", 38 | result_class=u"Msvm_VirtualSystem" 39 | "SettingData") as q2: 40 | vssd = q2.get_next_instance() 41 | 42 | p[u'SettingData'] = (vssd,) 43 | p[u'requestedInformation'] = (4, 100, 103, 105) 44 | 45 | with s.invoke_method( 46 | svc, u"GetSummaryInformation", p) as q3: 47 | r = q3.get_next_instance() 48 | print("Result: %s" % r[u"ReturnValue"]) 49 | summary_info = r[u"SummaryInformation"][0] 50 | 51 | print("vCPUs: %s" % 52 | summary_info[u"NumberOfProcessors"]) 53 | print("EnabledState: %s" % 54 | summary_info[u"EnabledState"]) 55 | print("Memory: %s" % summary_info[u"MemoryUsage"]) 56 | print("UpTime: %s" % summary_info[u"UpTime"]) 57 | 58 | 59 | def test_wmi_new(): 60 | wmi = imp.load_source('wmi', old_wmi_path) 61 | test_wmi(wmi) 62 | 63 | 64 | def test_wmi_old(): 65 | wmi = imp.load_source('wmi', mi_wmi_path) 66 | test_wmi(wmi) 67 | 68 | 69 | def test_wmi(wmi): 70 | conn = wmi.WMI(moniker="root\\virtualization\\v2") 71 | svc = conn.Msvm_VirtualSystemManagementService()[0] 72 | vm = conn.query( 73 | "select * from Msvm_ComputerSystem where ElementName = '%s'" % 74 | VM_NAME)[0] 75 | 76 | vssd = vm.associators( 77 | wmi_association_class="Msvm_SettingsDefineState", 78 | wmi_result_class="Msvm_VirtualSystemSettingData")[0] 79 | 80 | (ret_val, summary_info) = svc.GetSummaryInformation( 81 | [4, 100, 103, 105], 82 | [vssd.path_()]) 83 | 84 | print("Result: %s" % ret_val) 85 | summary_info = summary_info[0] 86 | 87 | print("vCPUs: %s" % summary_info.NumberOfProcessors) 88 | print("EnabledState: %s" % summary_info.EnabledState) 89 | print("Memory: %s" % summary_info.MemoryUsage) 90 | print("UpTime: %s" % summary_info.UpTime) 91 | 92 | 93 | if __name__ == '__main__': 94 | import timeit 95 | print("Running with MI module...") 96 | t_new = timeit.timeit( 97 | "test_mi()", setup="from __main__ import test_mi", number=10) 98 | print("Running with new WMI module...") 99 | t_wrap = timeit.timeit( 100 | "test_wmi_new()", setup="from __main__ import test_wmi_new", number=10) 101 | print("Running with old WMI module...") 102 | t_old = timeit.timeit( 103 | "test_wmi_old()", setup="from __main__ import test_wmi_old", number=10) 104 | 105 | print("Old WMI module: %s seconds" % t_old) 106 | print("New WMI module: %s seconds" % t_wrap) 107 | print("MI module: %s seconds" % t_new) 108 | 109 | print("Performance improvement (MI over old WMI): {percent:.2%}".format( 110 | percent=(1 - t_new / t_old))) 111 | -------------------------------------------------------------------------------- /wmi/samples/benchmark3.py: -------------------------------------------------------------------------------- 1 | import imp 2 | import os 3 | 4 | from distutils import sysconfig 5 | 6 | 7 | path = os.path.dirname(os.path.abspath(__file__)) 8 | mi_wmi_path = os.path.join( 9 | os.path.join(os.path.dirname(path), "wmi"), "__init__.py") 10 | 11 | path = sysconfig.get_python_lib() 12 | old_wmi_path = os.path.join(path, "wmi.py") 13 | 14 | VM_NAME = "wmi_benchmark_vm1" 15 | PORT_NAME = "port_name" 16 | SWITCH_NAME = 'external' 17 | 18 | 19 | def run_test(): 20 | from hyperv.neutron import utilsv2 21 | from hyperv.neutron import security_groups_driver 22 | from hyperv.nova import constants 23 | from hyperv.nova import vmutilsv2 24 | 25 | u = vmutilsv2.VMUtilsV2() 26 | 27 | net_utils = utilsv2.HyperVUtilsV2R2() 28 | sg_gen = security_groups_driver.SecurityGroupRuleGeneratorR2() 29 | sg_rules = sg_gen.create_default_sg_rules() 30 | 31 | if u.vm_exists(VM_NAME): 32 | u.destroy_vm(VM_NAME) 33 | 34 | u.create_vm(VM_NAME, False, 1, "c:\\openstack\\test", ['blah']) 35 | u.update_vm(VM_NAME, 256, 256, 1, 1, False, 1.0) 36 | 37 | u.set_boot_order(VM_NAME, (0, 1, 2, 3)) 38 | 39 | u.create_nic(VM_NAME, PORT_NAME, "00:99:99:99:99:99") 40 | 41 | u.create_scsi_controller(VM_NAME) 42 | u.get_vm_ide_controller(VM_NAME, 0) 43 | u.attach_ide_drive( 44 | VM_NAME, "c:\\VHDs\\test.vhdx", 0, 0, constants.DISK) 45 | 46 | u.get_vm_summary_info(VM_NAME) 47 | u.list_instances() 48 | u.get_vm_id(VM_NAME) 49 | u.set_vm_state(VM_NAME, constants.HYPERV_VM_STATE_ENABLED) 50 | 51 | net_utils.connect_vnic_to_vswitch(SWITCH_NAME, PORT_NAME) 52 | net_utils.set_vswitch_port_vlan_id(1000, PORT_NAME) 53 | net_utils.create_security_rules(PORT_NAME, sg_rules) 54 | net_utils.remove_all_security_rules(PORT_NAME) 55 | 56 | u.set_vm_state(VM_NAME, constants.HYPERV_VM_STATE_DISABLED) 57 | u.destroy_vm(VM_NAME) 58 | 59 | 60 | def test_mi(): 61 | wmi = imp.load_source('wmi', mi_wmi_path) 62 | # Simple way to check we're loading the right module 63 | wmi._Connection 64 | run_test() 65 | 66 | 67 | def test_wmi(): 68 | wmi = imp.load_source('wmi', old_wmi_path) 69 | # Simple way to check we're loading the right module 70 | wmi.handle_com_error 71 | run_test() 72 | 73 | 74 | if __name__ == '__main__': 75 | import timeit 76 | print("Running with new WMI module...") 77 | t_new = timeit.timeit( 78 | "test_mi()", setup="from __main__ import test_mi", number=1) 79 | print("Running with old WMI module...") 80 | t_old = timeit.timeit( 81 | "test_wmi()", setup="from __main__ import test_wmi", number=1) 82 | 83 | print("Old WMI module: %s seconds" % t_old) 84 | print("New WMI module: %s seconds" % t_new) 85 | 86 | print("Performance improvement: {percent:.2%}".format( 87 | percent=(1 - t_new / t_old))) 88 | -------------------------------------------------------------------------------- /wmi/samples/custom_operation_options.py: -------------------------------------------------------------------------------- 1 | import mi 2 | import wmi 3 | 4 | # This sample describes the usage of custom operation options 5 | # by creating a nic team. 6 | 7 | conn = wmi.WMI(moniker='root/standardcimv2') 8 | 9 | def new_lbfo_team(team_members, team_name): 10 | obj = conn.MSFT_NetLbfoTeam.new() 11 | obj.Name = 'nic_team' 12 | custom_options = [ 13 | {'name': 'TeamMembers', 14 | 'value_type': mi.MI_ARRAY | mi.MI_STRING, 15 | 'value': team_members 16 | }, 17 | {'name': 'TeamNicName', 18 | 'value_type': mi.MI_STRING, 19 | 'value': 'nic_team'} 20 | ] 21 | operation_options = {'custom_options': custom_options} 22 | obj.put(operation_options=operation_options) 23 | 24 | new_lbfo_team(team_members=['eth2', 'eth3'], 25 | team_name='nic_team') 26 | -------------------------------------------------------------------------------- /wmi/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudbase/PyMI/762e6394bb7ecd22018b9f1c5982bedd3bd31425/wmi/tests/__init__.py -------------------------------------------------------------------------------- /wmi/tests/functional/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudbase/PyMI/762e6394bb7ecd22018b9f1c5982bedd3bd31425/wmi/tests/functional/__init__.py -------------------------------------------------------------------------------- /wmi/tests/functional/test_base.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Cloudbase Solutions Srl 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | import os 17 | import functools 18 | import tempfile 19 | 20 | import testtools 21 | 22 | import wmi 23 | 24 | 25 | class BaseFunctionalTestCase(testtools.TestCase): 26 | _storage_namespace = 'root/microsoft/windows/storage' 27 | 28 | def setUp(self): 29 | super(BaseFunctionalTestCase, self).setUp() 30 | self._conn_cimv2 = wmi.WMI() 31 | self._conn_storage = wmi.WMI(moniker=self._storage_namespace) 32 | 33 | @staticmethod 34 | def pass_temp_file(f): 35 | @functools.wraps(f) 36 | def wrapper(*args, **kwargs): 37 | try: 38 | (fd, tmp_path) = tempfile.mkstemp(suffix='pymi-test') 39 | os.close(fd) 40 | # This will behave similar to the mock.patch decorator. 41 | args += (tmp_path, ) 42 | return f(*args, **kwargs) 43 | finally: 44 | if os.path.exists(tmp_path): 45 | os.unlink(tmp_path) 46 | return wrapper 47 | -------------------------------------------------------------------------------- /wmi/tests/functional/test_basic_ops.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Cloudbase Solutions Srl 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | import time 17 | 18 | import wmi 19 | from wmi.tests.functional import test_base 20 | 21 | 22 | class BasicOpsTestCase(test_base.BaseFunctionalTestCase): 23 | def test_query(self): 24 | win_version_str = self._conn_cimv2.Win32_OperatingSystem()[0].Version 25 | win_version = list(map(int, win_version_str.split('.'))) 26 | 27 | self.assertTrue(win_version >= [6, 0]) 28 | 29 | @test_base.BaseFunctionalTestCase.pass_temp_file 30 | def test_invoke_method(self, temp_file_path): 31 | content = str(time.time()) 32 | cmd = "cmd /c echo %s > %s" % (content, temp_file_path) 33 | startup_info = self._conn_cimv2.Win32_ProcessStartup.new() 34 | startup_info.ShowWindow = 0 35 | 36 | pid, ret_val = self._conn_cimv2.Win32_Process.Create( 37 | CommandLine=cmd, 38 | CurrentDirectory=None, 39 | ProcessStartupInformation=startup_info) 40 | 41 | time.sleep(0.5) 42 | 43 | with open(temp_file_path, 'r') as f: 44 | actual_content = f.read().strip('\n ') 45 | 46 | self.assertEqual(content, actual_content) 47 | 48 | def test_associators(self): 49 | logical_disks = self._conn_cimv2.Win32_LogicalDisk() 50 | found_associators = False 51 | for logical_disk in logical_disks: 52 | root_dirs = logical_disk.associators( 53 | wmi_association_class="Win32_LogicalDiskRootDirectory") 54 | if len(root_dirs) == 1: 55 | found_associators = True 56 | root_dir = root_dirs[0] 57 | self.assertEqual(logical_disk.Name.lower(), 58 | root_dir.Name.lower().strip('\\')) 59 | self.assertTrue(found_associators) 60 | 61 | def test_new_conn_invalid_creds(self): 62 | err_code = None 63 | try: 64 | wmi.WMI(user='invalidcredstest') 65 | except wmi.x_wmi as exc: 66 | err_code = exc.com_error.hresult & 0xFFFF 67 | 68 | error_logon_failure = 0x52e 69 | self.assertEqual(error_logon_failure, err_code) 70 | -------------------------------------------------------------------------------- /wmi/tests/functional/test_timeouts.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Cloudbase Solutions Srl 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | import os 17 | import time 18 | import unittest 19 | 20 | import wmi 21 | from wmi.tests.functional import test_base 22 | 23 | 24 | # The following tests perform various operations, 25 | # setting timeouts that are expected to be hit. 26 | class OperationTimeoutTestCase(test_base.BaseFunctionalTestCase): 27 | def _check_op_timeout(self, f, *args, **kwargs): 28 | # 'f' is expected to be a method that accepts 29 | # operation options. 30 | self.assertRaises(wmi.x_wmi_timed_out, 31 | f, *args, 32 | operation_options={'operation_timeout': 0.001}, 33 | **kwargs) 34 | 35 | @unittest.skipIf(os.getenv("GITHUB_ACTIONS") == "true", 36 | "Skipping on GitHub actions") 37 | def test_query(self): 38 | self._check_op_timeout(self._conn_cimv2.Win32_Process) 39 | 40 | @test_base.BaseFunctionalTestCase.pass_temp_file 41 | @test_base.BaseFunctionalTestCase.pass_temp_file 42 | def test_invoke_method(self, temp_src, temp_dest): 43 | with open(temp_src, 'w') as f: 44 | f.write('random data' * (10 << 20)) 45 | os.unlink(temp_dest) 46 | 47 | datafile = self._conn_cimv2.Cim_DataFile(Name=temp_src)[0] 48 | self._check_op_timeout(datafile.Copy, temp_dest) 49 | 50 | time.sleep(0.5) 51 | 52 | def test_associators(self): 53 | disk = self._conn_cimv2.Win32_DiskDrive()[0] 54 | self._check_op_timeout(disk.associators) 55 | 56 | @test_base.BaseFunctionalTestCase.pass_temp_file 57 | def test_modify_delete(self, temp_file_path): 58 | operation_options = {'operation_timeout': 1} 59 | 60 | datafile = self._conn_cimv2.Cim_DataFile(Name=temp_file_path)[0] 61 | datafile.Description = 'fake_description' 62 | datafile.put(operation_options=operation_options) 63 | datafile.Delete_(operation_options=operation_options) 64 | 65 | def test_per_session_timeouts(self): 66 | conn = wmi.WMI(operation_timeout=0.1) 67 | self.assertRaises(wmi.x_wmi_timed_out, 68 | conn.Win32_Processor) 69 | 70 | # We expect the query to be successful after we override the 71 | # session based operation timeout. 72 | conn.Win32_Process(operation_options={'operation_timeout': 10}) 73 | --------------------------------------------------------------------------------