├── pkg
└── vswhere
│ ├── .gitignore
│ ├── tools
│ └── VERIFICATION.txt
│ ├── build
│ └── vswhere.props
│ ├── vswhere.nuspec
│ └── vswhere.signproj
├── docker
├── Tests
│ ├── .gitignore
│ ├── legacy.tests.ps1
│ └── find.tests.ps1
├── docker-compose.debug.yml
├── docker-compose.yml
├── Dockerfile
├── Instances
│ ├── 1
│ │ └── state.json
│ ├── 2
│ │ └── state.json
│ ├── 3
│ │ └── state.json
│ ├── 4
│ │ └── state.json
│ └── 5
│ │ └── state.json
└── Debug.dockerfile
├── src
├── vswhere.lib
│ ├── resource.h
│ ├── stdafx.cpp
│ ├── packages.config
│ ├── targetver.h
│ ├── ValueFormatter.cpp
│ ├── ILegacyProvider.h
│ ├── CoInitializer.h
│ ├── Utilities.cpp
│ ├── XmlScope.cpp
│ ├── Exceptions.cpp
│ ├── Utilities.h
│ ├── CommandParser.h
│ ├── XmlScope.h
│ ├── ValueFormatter.h
│ ├── ResourceManager.h
│ ├── Exceptions.h
│ ├── Module.h
│ ├── LegacyProvider.h
│ ├── ResourceManager.cpp
│ ├── TextFormatter.h
│ ├── Glob.h
│ ├── TextFormatter.cpp
│ ├── LegacyProvider.cpp
│ ├── SafeArray.h
│ ├── Console.h
│ ├── JsonScope.h
│ ├── InstanceSelector.h
│ ├── XmlFormatter.h
│ ├── CommandParser.cpp
│ ├── JsonScope.cpp
│ ├── JsonFormatter.h
│ ├── stdafx.h
│ ├── Scope.h
│ ├── VersionRange.h
│ ├── XmlFormatter.cpp
│ ├── LegacyInstance.h
│ ├── Module.cpp
│ ├── Console.cpp
│ ├── LegacyInstance.cpp
│ ├── JsonFormatter.cpp
│ ├── Formatter.h
│ ├── CommandArgs.h
│ ├── vswhere.lib.vcxproj.filters
│ ├── vswhere.lib.rc
│ └── Glob.cpp
└── vswhere
│ ├── stdafx.cpp
│ ├── vswhere.exe.manifest
│ ├── resource.h
│ ├── targetver.h
│ ├── stdafx.h
│ ├── packages.config
│ ├── vswhere.vcxproj.filters
│ └── Program.cpp
├── .nuget
└── packages.config
├── .vscode
└── settings.json
├── .config
└── tsaoptions.json
├── tools
├── test.cmd
└── test.ps1
├── test
└── vswhere.test
│ ├── stdafx.cpp
│ ├── TestHelper.cpp
│ ├── TestModule.h
│ ├── packages.config
│ ├── targetver.h
│ ├── resource.h
│ ├── stdafx.h
│ ├── TestConsole.cpp
│ ├── TestLegacyProvider.h
│ ├── TestLegacyProvider.cpp
│ ├── TestModule.cpp
│ ├── ModuleTests.cpp
│ ├── TestConsole.h
│ ├── ExceptionsTests.cpp
│ ├── UtilitiesTests.cpp
│ ├── TestEnumInstances.h
│ ├── TestHelper.h
│ ├── vswhere.test.vcxproj.filters
│ ├── TestPackageReference.h
│ └── TestPropertyStore.h
├── CODE_OF_CONDUCT.md
├── version.json
├── pipelines
└── templates
│ ├── 1es-publish-task.yml
│ ├── ado-publish-task.yml
│ └── build.yml
├── inc
├── References.props
├── Common.props
├── Common.Debug.props
└── VersionInfo.props
├── azure-pipelines.yml
├── .vsconfig
├── LICENSE.txt
├── .vsts-ci.yml
├── .gitattributes
├── SECURITY.md
├── vswhere.sln
├── README.md
├── CONTRIBUTING.md
├── .vsts-compliance.yml
└── .gitignore
/pkg/vswhere/.gitignore:
--------------------------------------------------------------------------------
1 | !build
2 |
--------------------------------------------------------------------------------
/docker/Tests/.gitignore:
--------------------------------------------------------------------------------
1 | [Rr]esults.xml
2 |
--------------------------------------------------------------------------------
/src/vswhere.lib/resource.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/vswhere/HEAD/src/vswhere.lib/resource.h
--------------------------------------------------------------------------------
/.nuget/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.insertSpaces": true,
3 | "editor.tabSize": 4,
4 | "files.associations": {
5 | "functional": "cpp",
6 | "string": "cpp",
7 | "unordered_map": "cpp"
8 | }
9 | }
--------------------------------------------------------------------------------
/.config/tsaoptions.json:
--------------------------------------------------------------------------------
1 | {
2 | "codebaseName": "VSWhere",
3 | "instanceUrl": "https://devdiv.visualstudio.com/defaultcollection",
4 | "projectName": "DevDiv",
5 | "areaPath": "DevDiv\\VS Setup",
6 | "iterationPath": "DevDiv",
7 | "allTools": true
8 | }
9 |
--------------------------------------------------------------------------------
/src/vswhere/stdafx.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
--------------------------------------------------------------------------------
/tools/test.cmd:
--------------------------------------------------------------------------------
1 | @if not defined _echo echo off
2 |
3 | REM Copyright (C) Microsoft Corporation. All rights reserved.
4 | REM Licensed under the MIT license. See LICENSE.txt in the project root for license information.
5 |
6 | powershell.exe -NoLogo -ExecutionPolicy Bypass -Command "%~dp0\test.ps1" %*
7 |
--------------------------------------------------------------------------------
/src/vswhere.lib/stdafx.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
--------------------------------------------------------------------------------
/test/vswhere.test/stdafx.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
--------------------------------------------------------------------------------
/pkg/vswhere/tools/VERIFICATION.txt:
--------------------------------------------------------------------------------
1 | VERIFICATION
2 | Verification is intended to assist the Chocolatey moderators and community
3 | in verifying that this package's contents are trustworthy.
4 |
5 | tools\vswhere.exe is produced by us from the same repository as this package: https://github.com/Microsoft/vswhere
6 |
--------------------------------------------------------------------------------
/pkg/vswhere/build/vswhere.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildThisFileDirectory)..\tools\
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/vswhere.lib/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/test/vswhere.test/TestHelper.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | const ci_equal TestHelper::s_comparer;
9 |
--------------------------------------------------------------------------------
/test/vswhere.test/TestModule.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | std::wstring __cdecl format(_In_ LPCWSTR fmt, ...);
9 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | Code of Conduct
2 | ===============
3 |
4 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/src/vswhere/vswhere.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 |
7 |
8 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "3.1",
4 | "buildNumberOffset": -1,
5 | "publicReleaseRefSpec": [
6 | "^refs/heads/main$",
7 | "^refs/tags/v\\d+\\.\\d+"
8 | ],
9 | "cloudBuild": {
10 | "setAllVariables": true,
11 | "buildNumber": {
12 | "enabled": false
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/test/vswhere.test/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/vswhere/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by vswhere.rc
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/src/vswhere/targetver.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | #include
9 |
10 | #ifdef _WIN32_WINNT
11 | #undef _WIN32_WINNT
12 | #endif
13 |
14 | #define _WIN32_WINNT 0x601
15 |
16 | #include
17 |
--------------------------------------------------------------------------------
/src/vswhere.lib/targetver.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | #include
9 |
10 | #ifdef _WIN32_WINNT
11 | #undef _WIN32_WINNT
12 | #endif
13 |
14 | #define _WIN32_WINNT 0x601
15 |
16 | #include
17 |
--------------------------------------------------------------------------------
/test/vswhere.test/targetver.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | #include
9 |
10 | #ifdef _WIN32_WINNT
11 | #undef _WIN32_WINNT
12 | #endif
13 |
14 | #define _WIN32_WINNT 0x601
15 |
16 | #include
17 |
--------------------------------------------------------------------------------
/test/vswhere.test/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by vswhere.test.rc
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/src/vswhere.lib/ValueFormatter.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | void ValueFormatter::WriteProperty(_In_ const std::wstring& name, _In_ const std::wstring& value)
11 | {
12 | Console().WriteLine(value);
13 | }
14 |
--------------------------------------------------------------------------------
/src/vswhere.lib/ILegacyProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class ILegacyProvider
9 | {
10 | public:
11 | virtual bool HasLegacyInstances() const = 0;
12 | virtual bool TryGetLegacyInstance(_In_ LPCWSTR wzVersion, _Out_ ISetupInstance** ppInstance) const = 0;
13 | };
14 |
--------------------------------------------------------------------------------
/pipelines/templates/1es-publish-task.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: path
3 | type: string
4 |
5 | - name: artifactName
6 | type: string
7 |
8 | - name: displayName
9 | type: string
10 | default: 'Publish artifact'
11 |
12 | - name: condition
13 | type: string
14 | default: succeeded()
15 |
16 | steps:
17 | - task: 1ES.PublishPipelineArtifact@1
18 | displayName: ${{ parameters.displayName }}
19 | condition: ${{ parameters.condition }}
20 | inputs:
21 | targetPath: ${{ parameters.path }}
22 | artifactName: ${{ parameters.artifactName }}
--------------------------------------------------------------------------------
/pipelines/templates/ado-publish-task.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: path
3 | type: string
4 |
5 | - name: artifactName
6 | type: string
7 |
8 | - name: displayName
9 | type: string
10 | default: 'Publish artifact'
11 |
12 | - name: condition
13 | type: string
14 | default: succeeded()
15 |
16 | steps:
17 | - task: PublishBuildArtifacts@1
18 | displayName: ${{ parameters.displayName }}
19 | condition: ${{ parameters.condition }}
20 | inputs:
21 | PathtoPublish: ${{ parameters.path }}
22 | ArtifactName: ${{ parameters.artifactName }}
--------------------------------------------------------------------------------
/docker/docker-compose.debug.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | version: "2.1"
5 | services:
6 | test:
7 | image: microsoft/vssetup:debug
8 | build:
9 | context: .
10 | dockerfile: Debug.dockerfile
11 | network_mode: nat
12 | expose:
13 | - "3702/udp"
14 | - "4022-4023"
15 | command: >
16 | -Command "&'C:\Program Files\Microsoft Visual Studio 15.0\Common7\IDE\Remote Debugger\x64\msvsmon.exe' /silent /noauth /anyuser"
17 |
--------------------------------------------------------------------------------
/src/vswhere.lib/CoInitializer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class CoInitializer
9 | {
10 | public:
11 | CoInitializer()
12 | {
13 | auto hr = ::CoInitialize(NULL);
14 | if (FAILED(hr))
15 | {
16 | throw win32_error(hr);
17 | }
18 | }
19 |
20 | ~CoInitializer()
21 | {
22 | ::CoUninitialize();
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/inc/References.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | $(SolutionDir)src\vswhere.lib;$(IncludePath)
7 | $(OutDir);$(LibraryPath)
8 |
9 |
10 |
11 | vswhere.lib;vswhere.lib.res;%(AdditionalDependencies)
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | version: "2.1"
5 | services:
6 | test:
7 | image: microsoft/vssetup:test
8 | build: .
9 | volumes:
10 | - ../bin/${CONFIGURATION:-Debug}:C:/bin:ro
11 | - ./Instances:C:/ProgramData/Microsoft/VisualStudio/Packages/_Instances:ro
12 | - ./Tests:C:/Tests
13 | - C:/VS/Community
14 | - C:/VS/Professional
15 | - C:/VS/Enterprise
16 | - C:/BuildTools
17 | - C:/VS/Preview
18 | network_mode: none
19 | command: -Command Invoke-Pester C:\Tests -EnableExit
20 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | trigger: none
5 |
6 | pr:
7 | branches:
8 | include:
9 | - main
10 | paths:
11 | exclude:
12 | - README.md
13 |
14 | pool:
15 | vmImage: windows-2022
16 |
17 | variables:
18 | BuildConfiguration: Release
19 | BuildPlatform: x86
20 |
21 | steps:
22 | - template: /pipelines/templates/build.yml@self
23 | parameters:
24 | BuildConfiguration: $(BuildConfiguration)
25 | BuildPlatform: $(BuildPlatform)
26 | Docker: true
27 | PublishArtifactTemplate: /pipelines/templates/ado-publish-task.yml@self
--------------------------------------------------------------------------------
/src/vswhere/stdafx.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | #include "targetver.h"
9 |
10 | #define WIN32_LEAN_AND_MEAN
11 |
12 | // Windows headers
13 | #include
14 |
15 | // STL headers
16 | #include
17 |
18 | // Project headers
19 | #include
20 | #include
21 |
22 | _COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
23 | _COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
24 |
--------------------------------------------------------------------------------
/src/vswhere.lib/Utilities.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | std::string to_string(const std::wstring& value) {
9 | if (value.empty()) return std::string();
10 | int size_needed = WideCharToMultiByte(CP_UTF8, 0, value.data(), (int)value.size(), NULL, 0, NULL, NULL);
11 | std::string result(size_needed, 0);
12 | WideCharToMultiByte(CP_UTF8, 0, value.data(), (int)value.size(), result.data(), size_needed, NULL, NULL);
13 | return result;
14 | }
15 |
--------------------------------------------------------------------------------
/src/vswhere.lib/XmlScope.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | void XmlScope::WriteStartImpl()
11 | {
12 | Console().Write(Padding());
13 | Console().WriteLine(L"%ls<%ls>%ls", Console().Color(XmlFormatter::ColorTag), Name().c_str(), Console().ResetColor());
14 | }
15 |
16 | void XmlScope::WriteEndImpl()
17 | {
18 | Console().Write(Padding());
19 | Console().WriteLine(L"%ls%ls>%ls", Console().Color(XmlFormatter::ColorTag), Name().c_str(), Console().ResetColor());
20 | }
21 |
--------------------------------------------------------------------------------
/src/vswhere.lib/Exceptions.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | wstring win32_error::format_message(_In_ int code)
11 | {
12 | const size_t max = 65536;
13 |
14 | wstring err(max, wstring::value_type());
15 | if (auto ch = ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0, const_cast(err.c_str()), err.size(), NULL))
16 | {
17 | err.resize(ch);
18 | return err;
19 | }
20 |
21 | return L"unknown error";
22 | }
23 |
--------------------------------------------------------------------------------
/src/vswhere/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/test/vswhere.test/stdafx.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | #include "targetver.h"
9 | #include "cppunittest.h"
10 |
11 | #define WIN32_LEAN_AND_MEAN
12 |
13 | // Windows headers
14 | #include
15 | #include
16 |
17 | // STL headers
18 | #include
19 | #include
20 |
21 | // Project headers
22 | #include
23 | #include "TestModule.h"
24 | #include "TestConsole.h"
25 | #include "TestEnumInstances.h"
26 | #include "TestHelper.h"
27 | #include "TestPropertyStore.h"
28 | #include "TestInstance.h"
29 | #include "TestLegacyProvider.h"
30 | #include "TestPackageReference.h"
31 |
--------------------------------------------------------------------------------
/test/vswhere.test/TestConsole.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | void TestConsole::Write(_In_ LPCWSTR wzFormat, va_list args)
11 | {
12 | // include space for trailing null character
13 | size_t ch = ::_vscwprintf_p(wzFormat, args) + 1;
14 | size_t pos = m_output.size();
15 | m_output.resize(m_output.size() + ch);
16 |
17 | size_t rem = m_output.size() - pos;
18 | auto end = const_cast(m_output.c_str()) + pos;
19 | ::_vswprintf_p(end, rem, wzFormat, args);
20 |
21 | // remove trailing null character
22 | m_output.resize(m_output.size() - 1);
23 | }
24 |
--------------------------------------------------------------------------------
/test/vswhere.test/TestLegacyProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class TestLegacyProvider :
9 | public ILegacyProvider
10 | {
11 | public:
12 | typedef std::unordered_map, ci_equal> MapType;
13 |
14 | TestLegacyProvider(_In_ std::initializer_list list) :
15 | m_instances(list.begin(), list.end())
16 | {
17 | }
18 |
19 | bool HasLegacyInstances() const override;
20 | bool TryGetLegacyInstance(_In_ LPCWSTR wzVersion, _Out_ ISetupInstance** ppInstance) const override;
21 |
22 | private:
23 | MapType m_instances;
24 | };
25 |
--------------------------------------------------------------------------------
/inc/Common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | $(SolutionDir)bin\$(Configuration)\
7 |
8 |
9 |
10 | stdcpp14
11 | MultiThreaded
12 | Guard
13 | ProgramDatabase
14 | /ZH:SHA_256 %(AdditionalOptions)
15 |
16 |
17 | shell32.lib
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/inc/Common.Debug.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | $(SolutionDir)bin\$(Configuration)\
7 |
8 |
9 |
10 | stdcpp14
11 | MultiThreadedDebug
12 | Guard
13 | ProgramDatabase
14 | /ZH:SHA_256 %(AdditionalOptions)
15 |
16 |
17 | shell32.lib
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/vswhere.lib/Utilities.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | std::string to_string(const std::wstring& value);
9 |
10 | struct ci_equal
11 | {
12 | bool operator()(const std::wstring& lhs, const std::wstring& rhs) const
13 | {
14 | return CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, lhs.c_str(), lhs.size(), rhs.c_str(), rhs.size());
15 | }
16 | };
17 |
18 | struct ci_less
19 | {
20 | bool operator()(const std::wstring& lhs, const std::wstring& rhs) const
21 | {
22 | return CSTR_EQUAL > ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, lhs.c_str(), lhs.size(), rhs.c_str(), rhs.size());
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/test/vswhere.test/TestLegacyProvider.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | bool TestLegacyProvider::HasLegacyInstances() const
11 | {
12 | return !m_instances.empty();
13 | }
14 |
15 | bool TestLegacyProvider::TryGetLegacyInstance(_In_ LPCWSTR wzVersion, _Out_ ISetupInstance** ppInstance) const
16 | {
17 | _ASSERT(ppInstance);
18 |
19 | *ppInstance = NULL;
20 |
21 | auto it = m_instances.find(wzVersion);
22 | if (it != m_instances.end())
23 | {
24 | *ppInstance = new LegacyInstance(it->first.c_str(), it->second.c_str());
25 | return true;
26 | }
27 |
28 | return false;
29 | }
30 |
--------------------------------------------------------------------------------
/inc/VersionInfo.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Microsoft Corporation
7 | Visual Studio Setup
8 | Copyright (C) Microsoft Corporation. All rights reserved.
9 |
10 |
11 |
12 | $(IntermediateOutputPath);%(AdditionalIncludeDirectories)
13 |
14 |
15 | $(IntermediateOutputPath);%(AdditionalIncludeDirectories)
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/vswhere.lib/CommandParser.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class CommandParser
9 | {
10 | public:
11 | struct Token
12 | {
13 | enum { eNone, eParameter, eArgument } Type;
14 | std::wstring Value;
15 | };
16 |
17 | CommandParser() noexcept
18 | {
19 | }
20 |
21 | CommandParser(const CommandParser& obj) :
22 | m_path(obj.m_path)
23 | {
24 | }
25 |
26 | const std::wstring& get_Path() const noexcept
27 | {
28 | return m_path;
29 | }
30 |
31 | std::vector Parse(_In_ LPCWSTR wszCommandLine);
32 | std::vector Parse(_In_ int argc, _In_ LPCWSTR argv[]);
33 |
34 | private:
35 | std::wstring m_path;
36 | };
37 |
--------------------------------------------------------------------------------
/.vsconfig:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "components": [
4 | "Microsoft.VisualStudio.Component.CoreEditor",
5 | "Microsoft.VisualStudio.Component.NuGet",
6 | "Microsoft.Component.MSBuild",
7 | "Microsoft.VisualStudio.Component.TextTemplating",
8 | "Microsoft.VisualStudio.Component.VC.CoreIde",
9 | "Microsoft.Component.VC.Runtime.UCRTSDK",
10 | "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
11 | "Microsoft.VisualStudio.Component.Graphics.Tools",
12 | "Microsoft.VisualStudio.Component.VC.DiagnosticTools",
13 | "Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
14 | "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
15 | "Microsoft.VisualStudio.Component.Windows10SDK.19041",
16 | "Microsoft.VisualStudio.Component.VC.v141.x86.x64",
17 | "Microsoft.VisualStudio.Workload.NativeDesktop",
18 | "Microsoft.VisualStudio.Component.Git",
19 | "Microsoft.VisualStudio.Component.WinXP"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/src/vswhere.lib/XmlScope.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class XmlScope :
9 | public Scope
10 | {
11 | public:
12 | XmlScope(_In_opt_ XmlScope* pParent, _In_ ::Console& console, _In_ const std::wstring& padding, _In_ const std::wstring& name) :
13 | Scope(pParent, console, padding, name)
14 | {
15 | }
16 |
17 | XmlScope(_In_opt_ XmlScope* pParent, _In_ ::Console& console, _In_ std::wstring& padding, _In_ std::wstring::const_pointer name) :
18 | Scope(pParent, console, padding, name)
19 | {
20 | }
21 |
22 | XmlScope(_In_ const XmlScope& obj) :
23 | Scope(obj)
24 | {
25 | }
26 |
27 | protected:
28 | void WriteStartImpl() override;
29 | void WriteEndImpl() override;
30 | };
31 |
--------------------------------------------------------------------------------
/src/vswhere.lib/ValueFormatter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class ValueFormatter :
9 | public Formatter
10 | {
11 | public:
12 | static std::unique_ptr Create(_In_ CommandArgs& args, _In_ ::Console& console)
13 | {
14 | return std::unique_ptr(new ValueFormatter(args, console));
15 | }
16 |
17 | ValueFormatter(_In_ CommandArgs& args, _In_ ::Console& console) :
18 | Formatter(args, console)
19 | {
20 | }
21 |
22 | ValueFormatter(_In_ const ValueFormatter& obj) :
23 | Formatter(obj)
24 | {
25 | }
26 |
27 | bool ShowLogo() const override
28 | {
29 | return false;
30 | }
31 |
32 | protected:
33 | void WriteProperty(_In_ const std::wstring& name, _In_ const std::wstring& value) override;
34 | };
35 |
--------------------------------------------------------------------------------
/src/vswhere.lib/ResourceManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class ResourceManager
9 | {
10 | public:
11 | static void SetInstance(_In_ HINSTANCE hInstance)
12 | {
13 | s_hInstance = hInstance;
14 | }
15 |
16 | static std::wstring GetString(_In_ DWORD nID);
17 | static std::wstring __cdecl FormatString(_In_ DWORD nID, ...)
18 | {
19 | va_list args;
20 |
21 | va_start(args, nID);
22 | auto wsz = FormatString(nID, args);
23 | va_end(args);
24 |
25 | return wsz;
26 | }
27 |
28 | private:
29 | ResourceManager() {}
30 | ResourceManager(const ResourceManager& obj) {}
31 | ResourceManager(ResourceManager&& obj) noexcept {}
32 |
33 | static std::wstring FormatString(_In_ DWORD nID, _In_ va_list args);
34 |
35 | static HINSTANCE s_hInstance;
36 | };
37 |
--------------------------------------------------------------------------------
/src/vswhere.lib/Exceptions.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class win32_error :
9 | public std::system_error
10 | {
11 | public:
12 | win32_error() :
13 | win32_error(::GetLastError())
14 | {
15 | }
16 |
17 | win32_error(_In_ int code, _In_ const std::string message = "") :
18 | system_error(code, std::system_category(), message),
19 | m_message(format_message(code))
20 | {
21 | }
22 |
23 | win32_error(_In_ int code, _In_ const std::wstring message) :
24 | system_error(code, std::system_category(), to_string(message)),
25 | m_message(message)
26 | {
27 | }
28 |
29 | const wchar_t* wwhat() const
30 | {
31 | return m_message.c_str();
32 | }
33 |
34 | private:
35 | static std::wstring format_message(_In_ int code);
36 |
37 | std::wstring m_message;
38 | };
39 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
--------------------------------------------------------------------------------
/src/vswhere.lib/Module.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class Module
9 | {
10 | public:
11 | Module() :
12 | m_hModule(NULL)
13 | {
14 | }
15 |
16 | Module(_In_ const Module& obj) :
17 | m_hModule(obj.m_hModule),
18 | m_path(obj.m_path),
19 | m_fileVersion(obj.m_fileVersion)
20 | {
21 | }
22 |
23 | ~Module()
24 | {
25 | if (m_hModule)
26 | {
27 | ::FreeLibrary(m_hModule);
28 | }
29 | }
30 |
31 | // Avoid throwing non-catastrophic exceptions since information is for diagnostics only.
32 | void FromIUnknown(_In_opt_ const IUnknown* pUnk) noexcept;
33 | const std::wstring& get_Path() noexcept;
34 | const std::wstring& get_FileVersion() noexcept;
35 |
36 | private:
37 | HMODULE m_hModule;
38 | std::wstring m_path;
39 | std::wstring m_fileVersion;
40 | };
41 |
--------------------------------------------------------------------------------
/test/vswhere.test/TestModule.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 | using namespace Microsoft::VisualStudio::CppUnitTestFramework;
10 |
11 | wstring __cdecl format(_In_ LPCWSTR fmt, ...)
12 | {
13 | va_list args;
14 | va_start(args, fmt);
15 |
16 | auto ch = _vscwprintf_p(fmt, args);
17 | if (0 > ch)
18 | {
19 | throw win32_error(ERROR_INVALID_PARAMETER);
20 | }
21 |
22 | wstring wsz;
23 | wsz.resize(++ch);
24 |
25 | if (0 > _vswprintf_p(&wsz[0], ch, fmt, args))
26 | {
27 | throw win32_error(ERROR_INVALID_PARAMETER);
28 | }
29 |
30 | va_end(args);
31 |
32 | // trim the terminating null
33 | wsz.resize(ch - 1);
34 |
35 | return wsz;
36 | }
37 |
38 | TEST_MODULE_INITIALIZE(ModuleInitialize)
39 | {
40 | #pragma warning(suppress: 6387) // Ignore potential failure when getting module handle
41 | ResourceManager::SetInstance(::GetModuleHandleW(L"vswhere.test.dll"));
42 | }
43 |
--------------------------------------------------------------------------------
/test/vswhere.test/ModuleTests.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 | using namespace Microsoft::VisualStudio::CppUnitTestFramework;
10 |
11 | // Wrap something cheap and easy to create.
12 | _COM_SMARTPTR_TYPEDEF(IBindCtx, __uuidof(IBindCtx));
13 |
14 | TEST_CLASS(ModuleTests)
15 | {
16 | public:
17 | TEST_METHOD(FromIUnknown_NULL)
18 | {
19 | Module sut;
20 | sut.FromIUnknown(NULL);
21 |
22 | Assert::AreEqual(0, sut.get_Path().length());
23 | Assert::AreEqual(0, sut.get_FileVersion().length());
24 | }
25 |
26 | TEST_METHOD(FromIUnknown_Not_NULL)
27 | {
28 | IBindCtxPtr binder;
29 | Assert::AreEqual(S_OK, ::CreateBindCtx(0, &binder));
30 |
31 | Module sut;
32 | sut.FromIUnknown(binder);
33 |
34 | Assert::AreNotEqual(0, sut.get_Path().length());
35 | Assert::AreNotEqual(0, sut.get_FileVersion().length());
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/src/vswhere.lib/LegacyProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class LegacyProvider :
9 | public ILegacyProvider
10 | {
11 | public:
12 | static ILegacyProvider& Instance;
13 |
14 | LegacyProvider() :
15 | m_hKey(NULL)
16 | {
17 | auto err = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &m_hKey);
18 | if (ERROR_SUCCESS != err && ERROR_FILE_NOT_FOUND != err)
19 | {
20 | throw win32_error(err);
21 | }
22 | }
23 |
24 | LegacyProvider(const LegacyProvider& obj) = delete;
25 |
26 | ~LegacyProvider()
27 | {
28 | if (m_hKey)
29 | {
30 | ::CloseHandle(m_hKey);
31 | m_hKey = NULL;
32 | }
33 | }
34 |
35 | bool HasLegacyInstances() const override;
36 | bool TryGetLegacyInstance(_In_ LPCWSTR wzVersion, _Out_ ISetupInstance** ppInstance) const override;
37 |
38 | private:
39 | HKEY m_hKey;
40 | };
41 |
--------------------------------------------------------------------------------
/test/vswhere.test/TestConsole.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class TestConsole :
9 | public Console
10 | {
11 | public:
12 | TestConsole(_In_ const CommandArgs& args) :
13 | Console(args),
14 | m_color(false)
15 | {
16 | }
17 |
18 | TestConsole(_In_ const TestConsole& obj) :
19 | Console(obj),
20 | m_output(obj.m_output),
21 | m_color(obj.m_color)
22 | {
23 | }
24 |
25 | void Initialize() noexcept override
26 | {
27 | m_fInitialized = true;
28 | }
29 |
30 | operator const wchar_t*() const
31 | {
32 | return m_output.c_str();
33 | }
34 |
35 | void SetColorSupported(bool enable) noexcept
36 | {
37 | m_color = enable;
38 | }
39 |
40 | bool IsColorSupported() const override
41 | {
42 | return m_color;
43 | }
44 |
45 | protected:
46 | void Write(_In_ LPCWSTR wzFormat, va_list args) override;
47 |
48 | private:
49 | std::wstring m_output;
50 | bool m_color;
51 | };
52 |
--------------------------------------------------------------------------------
/src/vswhere.lib/ResourceManager.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | HINSTANCE ResourceManager::s_hInstance = ::GetModuleHandleW(NULL);
11 |
12 | wstring ResourceManager::GetString(_In_ DWORD nID)
13 | {
14 | LPCWSTR wsz = NULL;
15 |
16 | auto ch = ::LoadStringW(s_hInstance, nID, (LPWSTR)&wsz, 0);
17 | if (!ch)
18 | {
19 | throw win32_error();
20 | }
21 |
22 | return wstring(wsz, wsz + ch);
23 | }
24 |
25 | wstring ResourceManager::FormatString(_In_ DWORD nID, _In_ va_list args)
26 | {
27 | auto fmt = GetString(nID);
28 |
29 | auto ch = _vscwprintf_p(fmt.c_str(), args);
30 | if (0 > ch)
31 | {
32 | throw win32_error(ERROR_INVALID_PARAMETER);
33 | }
34 |
35 | wstring wsz;
36 | wsz.resize(++ch);
37 |
38 | if (0 > _vswprintf_p(&wsz[0], ch, fmt.c_str(), args))
39 | {
40 | throw win32_error(ERROR_INVALID_PARAMETER);
41 | }
42 |
43 | // trim the terminating null
44 | wsz.resize(ch - 1);
45 |
46 | return wsz;
47 | }
48 |
--------------------------------------------------------------------------------
/src/vswhere.lib/TextFormatter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class TextFormatter :
9 | public Formatter
10 | {
11 | public:
12 | static std::unique_ptr Create(_In_ CommandArgs& args, _In_ ::Console& console)
13 | {
14 | return std::unique_ptr(new TextFormatter(args, console));
15 | }
16 |
17 | TextFormatter(_In_ CommandArgs& args, _In_ ::Console& console) :
18 | Formatter(args, console),
19 | m_first(false)
20 | {
21 | }
22 |
23 | TextFormatter(_In_ const TextFormatter& obj) :
24 | Formatter(obj),
25 | m_first(obj.m_first),
26 | m_scopes(obj.m_scopes)
27 | {
28 | }
29 |
30 | protected:
31 | void StartArray(_In_opt_ const std::wstring& name = empty_wstring) override;
32 | void StartObject(_In_opt_ const std::wstring& name = empty_wstring) override;
33 | void WriteProperty(_In_ const std::wstring& name, _In_ const std::wstring& value) override;
34 | void EndObject() override;
35 |
36 | private:
37 | bool m_first;
38 | std::stack m_scopes;
39 | };
40 |
--------------------------------------------------------------------------------
/src/vswhere.lib/Glob.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class Glob
9 | {
10 | public:
11 | Glob(_In_ const std::wstring& root, _In_ const std::wstring& pattern);
12 | Glob(_In_ const Glob& obj) noexcept :
13 | m_root(obj.m_root),
14 | m_root_length(obj.m_root_length),
15 | #ifdef _DEBUG
16 | m_pattern(obj.m_pattern),
17 | #endif
18 | m_re(obj.m_re)
19 | {
20 | }
21 |
22 | const std::wstring& Root() const noexcept
23 | {
24 | return m_root.native();
25 | }
26 |
27 | const std::vector Entries(_In_ bool sort = false) const;
28 | bool Match(_In_ const std::wstring& value) const;
29 |
30 | private:
31 | static bool IsInvalid(_In_ const wchar_t ch);
32 | static bool RequiresEscape(_In_ const wchar_t ch);
33 | static void ThrowError(_In_ const std::wstring& pattern);
34 |
35 | std::filesystem::path m_root;
36 | size_t m_root_length;
37 | std::wregex m_re;
38 |
39 | #ifdef _DEBUG
40 | public:
41 | const std::wstring& Pattern() const noexcept
42 | {
43 | return m_pattern;
44 | }
45 |
46 | private:
47 | std::wstring m_pattern;
48 | #endif
49 | };
50 |
--------------------------------------------------------------------------------
/test/vswhere.test/ExceptionsTests.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 | using namespace Microsoft::VisualStudio::CppUnitTestFramework;
10 |
11 | TEST_CLASS(ExceptionsTests)
12 | {
13 | public:
14 | TEST_METHOD_INITIALIZE(Initialize)
15 | {
16 | ::SetThreadLocale(1033);
17 | }
18 |
19 | TEST_METHOD(win32_error_last_error)
20 | {
21 | ::SetLastError(ERROR_NOT_FOUND);
22 |
23 | win32_error sut;
24 | Assert::AreEqual(ERROR_NOT_FOUND, sut.code().value());
25 | }
26 |
27 | TEST_METHOD(win32_error_explicit)
28 | {
29 | win32_error sut(ERROR_NOT_FOUND);
30 | Assert::AreEqual(ERROR_NOT_FOUND, sut.code().value());
31 | Assert::AreEqual("Element not found.", sut.what());
32 | Assert::AreEqual(L"Element not found.\r\n", sut.wwhat());
33 | }
34 |
35 | TEST_METHOD(win32_error_custom_message)
36 | {
37 | win32_error sut(ERROR_NOT_FOUND, L"property not found");
38 | Assert::AreEqual(ERROR_NOT_FOUND, sut.code().value());
39 | Assert::AreEqual("property not found: Element not found.", sut.what());
40 | Assert::AreEqual(L"property not found", sut.wwhat());
41 | }
42 | };
43 |
--------------------------------------------------------------------------------
/src/vswhere.lib/TextFormatter.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | void TextFormatter::StartArray(_In_opt_ const std::wstring& name)
11 | {
12 | m_first = true;
13 | }
14 |
15 | void TextFormatter::StartObject(_In_opt_ const wstring& name)
16 | {
17 | if (!m_first && m_scopes.empty())
18 | {
19 | Console().WriteLine();
20 | }
21 |
22 | m_first = false;
23 |
24 | if (!m_scopes.empty())
25 | {
26 | m_scopes.push(m_scopes.top() + name + L"_");
27 | }
28 | else if (!name.empty())
29 | {
30 | m_scopes.push(name + L"_");
31 | }
32 | else
33 | {
34 | m_scopes.push(name);
35 | }
36 | }
37 |
38 | void TextFormatter::WriteProperty(_In_ const std::wstring& name, _In_ const std::wstring& value)
39 | {
40 | wstring prefix = L"";
41 | if (!m_scopes.empty())
42 | {
43 | prefix = m_scopes.top();
44 | }
45 |
46 | Console().Write(L"%ls%ls%ls%ls: ", Console().Color(ColorName), prefix.c_str(), name.c_str(), Console().ResetColor());
47 | Console().WriteLine(L"%ls%ls%ls", Console().Color(ColorValue), value.c_str(), Console().ResetColor());
48 | }
49 |
50 | void TextFormatter::EndObject()
51 | {
52 | m_scopes.pop();
53 | }
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | #escape=`
2 |
3 | # Copyright (C) Microsoft Corporation. All rights reserved.
4 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
5 |
6 | # Based on latest image cached by Azure Pipelines: https://docs.microsoft.com/azure/devops/pipelines/agents/hosted#software
7 | FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022
8 | SHELL ["powershell.exe", "-ExecutionPolicy", "Bypass", "-Command"]
9 |
10 | ENV INSTALLER_VERSION=1.14.190.31519 `
11 | INSTALLER_URI=https://download.visualstudio.microsoft.com/download/pr/100516681/d68d54e233c956ff79799fdf63753c54/Microsoft.VisualStudio.Setup.Configuration.msi `
12 | INSTALLER_HASH=8917aa7b4116e574856d43e8e62862c1d6f25512be54917f2ef95f9cac103810
13 |
14 | # Download and register the query API
15 | RUN $ErrorActionPreference = 'Stop' ; `
16 | $VerbosePreference = 'Continue' ; `
17 | $null = New-Item C:\TEMP -ItemType Directory -ea SilentlyContinue; `
18 | Invoke-WebRequest -Uri $env:INSTALLER_URI -OutFile C:\TEMP\Microsoft.VisualStudio.Setup.Configuration.msi; `
19 | if ((Get-FileHash -Path C:\TEMP\Microsoft.VisualStudio.Setup.Configuration.msi -Algorithm SHA256).Hash -ne $env:INSTALLER_HASH) { throw 'Download hash does not match' }; `
20 | Start-Process -Wait -FilePath C:\Windows\System32\msiexec.exe -ArgumentList '/i C:\TEMP\Microsoft.VisualStudio.Setup.Configuration.msi /qn /l*vx C:\TEMP\Microsoft.VisualStudio.Setup.Configuration.log'
21 |
22 | ENTRYPOINT ["powershell.exe", "-ExecutionPolicy", "Bypass"]
23 | CMD ["-NoExit"]
24 |
--------------------------------------------------------------------------------
/src/vswhere/vswhere.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;manifest
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 |
29 |
30 | Source Files
31 |
32 |
33 | Source Files
34 |
35 |
36 |
37 |
38 |
39 | Resource Files
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/vswhere.lib/LegacyProvider.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | ILegacyProvider& LegacyProvider::Instance = LegacyProvider();
11 |
12 | bool LegacyProvider::HasLegacyInstances() const
13 | {
14 | return NULL != m_hKey;
15 | }
16 |
17 | bool LegacyProvider::TryGetLegacyInstance(_In_ LPCWSTR wzVersion, _Out_ ISetupInstance** ppInstance) const
18 | {
19 | _ASSERT(ppInstance);
20 |
21 | *ppInstance = NULL;
22 |
23 | if (!m_hKey)
24 | {
25 | return false;
26 | }
27 |
28 | DWORD dwType = 0;
29 | DWORD cbData = 0;
30 |
31 | auto err = ::RegQueryValueExW(m_hKey, wzVersion, NULL, &dwType, NULL, &cbData);
32 | if (ERROR_FILE_NOT_FOUND == err || REG_SZ != dwType)
33 | {
34 | return false;
35 | }
36 | else if (ERROR_SUCCESS != err)
37 | {
38 | throw win32_error(err);
39 | }
40 |
41 | wstring sz(cbData / sizeof(wstring::value_type), wstring::value_type());
42 | auto lpData = reinterpret_cast(const_cast(sz.c_str()));
43 |
44 | err = ::RegQueryValueExW(m_hKey, wzVersion, NULL, NULL, lpData, &cbData);
45 | if (ERROR_SUCCESS != err)
46 | {
47 | throw win32_error(err);
48 | }
49 |
50 | *ppInstance = new (nothrow) LegacyInstance(wzVersion, sz.c_str());
51 | if (!*ppInstance)
52 | {
53 | throw win32_error(E_OUTOFMEMORY);
54 | }
55 |
56 | return true;
57 | }
58 |
--------------------------------------------------------------------------------
/src/vswhere.lib/SafeArray.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | // Simple container for a single-dimension SAFEARRAY.
9 | template
10 | class SafeArray
11 | {
12 | public:
13 | SafeArray(_In_ const LPSAFEARRAY psa) :
14 | m_psa(psa)
15 | {
16 | Lock();
17 | }
18 |
19 | SafeArray(_In_ const SafeArray& obj) :
20 | m_psa(obj.m_psa)
21 | {
22 | Lock();
23 | }
24 |
25 | ~SafeArray()
26 | {
27 | Unlock();
28 | Destroy();
29 | }
30 |
31 | const std::vector<_Element>& Elements() const
32 | {
33 | return m_elements;
34 | }
35 |
36 | private:
37 | void Lock()
38 | {
39 | if (m_psa)
40 | {
41 | auto hr = ::SafeArrayLock(m_psa);
42 | if (FAILED(hr))
43 | {
44 | throw win32_error(hr);
45 | }
46 |
47 | auto pvData = (_Element*)m_psa->pvData;
48 | auto celt = m_psa->rgsabound[0].cElements;
49 |
50 | m_elements.assign(pvData, pvData + celt);
51 | }
52 | }
53 |
54 | void Unlock()
55 | {
56 | if (m_psa)
57 | {
58 | ::SafeArrayUnlock(m_psa);
59 | }
60 | }
61 |
62 | void Destroy()
63 | {
64 | if (m_psa)
65 | {
66 | ::SafeArrayDestroy(m_psa);
67 | }
68 | }
69 |
70 | LPSAFEARRAY m_psa;
71 | std::vector<_Element> m_elements;
72 | };
73 |
--------------------------------------------------------------------------------
/src/vswhere.lib/Console.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class Console
9 | {
10 | public:
11 | Console(_In_ const CommandArgs& args) :
12 | m_args(args),
13 | m_fInitialized(false),
14 | m_fColorSupported(false)
15 | {
16 | }
17 |
18 | Console(_In_ const Console& obj) :
19 | m_args(obj.m_args),
20 | m_fInitialized(obj.m_fInitialized),
21 | m_fColorSupported(obj.m_fColorSupported)
22 | {
23 | }
24 |
25 | virtual void Initialize() noexcept;
26 |
27 | LPCWSTR Color(_In_ LPCWSTR wzColor) const;
28 | LPCWSTR ResetColor() const;
29 |
30 | void __cdecl Write(_In_ LPCWSTR wzFormat, ...);
31 | void __cdecl Write(_In_ const std::wstring& value);
32 | void __cdecl WriteLine(_In_opt_ LPCWSTR wzFormat = NULL, ...);
33 | void __cdecl WriteLine(_In_ const std::wstring& value);
34 |
35 | virtual bool IsColorSupported() const
36 | {
37 | _ASSERTE(m_fInitialized);
38 | return m_fColorSupported && m_args.get_Color();
39 | }
40 |
41 | protected:
42 | virtual void Write(_In_ LPCWSTR wzFormat, va_list args);
43 |
44 | const CommandArgs& Args() const noexcept
45 | {
46 | return m_args;
47 | }
48 |
49 | bool m_fInitialized;
50 |
51 | private:
52 | bool static IsConsole(_In_ FILE* f) noexcept;
53 | bool static IsVirtualTerminal(_In_ FILE* f) noexcept;
54 |
55 | const CommandArgs& m_args;
56 | bool m_fColorSupported;
57 | };
--------------------------------------------------------------------------------
/pkg/vswhere/vswhere.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | vswhere
5 | $Version$
6 | Visual Studio Locator
7 | Microsoft
8 | Microsoft
9 | false
10 | https://go.microsoft.com/fwlink/?linkid=839265
11 | https://github.com/Microsoft/vswhere/tree/$CommitId$/LICENSE.txt
12 | https://github.com/Microsoft/vswhere
13 | Locate Visual Studio 2017 and newer installations
14 | Locate Visual Studio 2017 and newer installations
15 | © Microsoft Corporation. All rights reserved.
16 | vs vs2017 visualstudio
17 | true
18 | https://github.com/Microsoft/vswhere/tree/$CommitId$
19 | https://github.com/Microsoft/vswhere/tree/$CommitId$/pkg/vswhere
20 | https://github.com/Microsoft/vswhere/wiki
21 | https://github.com/Microsoft/vswhere/issues
22 | https://github.com/Microsoft/vswhere/releases/tag/$Tag$
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/vswhere.lib/JsonScope.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class JsonScope :
9 | public Scope
10 | {
11 | public:
12 | typedef enum { array, object } Type;
13 |
14 | JsonScope(_In_opt_ JsonScope* pParent, _In_ ::Console& console, _In_ const std::wstring& padding, _In_ Type type, _In_ const std::wstring& name) :
15 | Scope(pParent, console, padding, name),
16 | m_type(type),
17 | m_requireSep(false)
18 | {
19 | }
20 |
21 | JsonScope(_In_ const JsonScope& obj) :
22 | Scope(obj),
23 | m_type(obj.m_type),
24 | m_requireSep(obj.m_requireSep)
25 | {
26 | }
27 |
28 | bool IsArray() const noexcept
29 | {
30 | return m_type == Type::array;
31 | }
32 |
33 | bool IsObject() const noexcept
34 | {
35 | return m_type == Type::object;
36 | }
37 |
38 | void StartScope();
39 | void StartProperty();
40 |
41 | protected:
42 | void WriteStartImpl() override;
43 | void WriteEndImpl() override;
44 |
45 | private:
46 | void RequireSeparator() noexcept;
47 | void WriteSeparator();
48 |
49 | wchar_t StartChar() const noexcept
50 | {
51 | if (m_type == Type::array)
52 | {
53 | return L'[';
54 | }
55 |
56 | return L'{';
57 | }
58 |
59 | wchar_t EndChar() const noexcept
60 | {
61 | if (m_type == Type::array)
62 | {
63 | return L']';
64 | }
65 |
66 | return L'}';
67 | }
68 |
69 | const Type m_type;
70 | bool m_requireSep;
71 | };
72 |
--------------------------------------------------------------------------------
/src/vswhere.lib/InstanceSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class InstanceSelector
9 | {
10 | public:
11 | InstanceSelector(_In_ const CommandArgs& args, _In_opt_ ISetupHelper* pHelper = NULL) :
12 | InstanceSelector(args, LegacyProvider::Instance, pHelper)
13 | {
14 | }
15 |
16 | InstanceSelector(_In_ const CommandArgs& args, _In_ ILegacyProvider& provider, _In_opt_ ISetupHelper* pHelper = NULL);
17 | InstanceSelector(_In_ const InstanceSelector& obj) :
18 | m_args(obj.m_args),
19 | m_provider(obj.m_provider),
20 | m_helper(obj.m_helper),
21 | m_ullMinimumVersion(obj.m_ullMinimumVersion),
22 | m_ullMaximumVersion(obj.m_ullMaximumVersion)
23 | {
24 | }
25 |
26 | bool Less(const ISetupInstancePtr& a, const ISetupInstancePtr& b) const;
27 | std::vector Select(_In_opt_ IEnumSetupInstances* pEnum) const;
28 |
29 | private:
30 | static ci_equal s_comparer;
31 |
32 | static std::wstring GetId(_In_ ISetupPackageReference* pPackageReference);
33 | bool IsMatch(_In_ ISetupInstance* pInstance) const;
34 | bool IsProductMatch(_In_ ISetupInstance2* pInstance) const;
35 | bool IsWorkloadMatch(_In_ ISetupInstance2* pInstance) const;
36 | bool IsVersionMatch(_In_ ISetupInstance* pInstance) const;
37 | bool HasVersionRange() const
38 | {
39 | return m_ullMinimumVersion != 0 && m_ullMaximumVersion != 0;
40 | }
41 |
42 | const CommandArgs& m_args;
43 | const ILegacyProvider& m_provider;
44 | ULONGLONG m_ullMinimumVersion;
45 | ULONGLONG m_ullMaximumVersion;
46 | ISetupHelperPtr m_helper;
47 | };
48 |
--------------------------------------------------------------------------------
/src/vswhere.lib/XmlFormatter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class XmlFormatter :
9 | public Formatter
10 | {
11 | public:
12 | static std::unique_ptr Create(_In_ CommandArgs& args, _In_ ::Console& console)
13 | {
14 | return std::unique_ptr(new XmlFormatter(args, console));
15 | }
16 |
17 | XmlFormatter(_In_ CommandArgs& args, _In_ ::Console& console) :
18 | Formatter(args, console)
19 | {
20 | }
21 |
22 | XmlFormatter(_In_ const XmlFormatter& obj) :
23 | Formatter(obj),
24 | m_padding(obj.m_padding),
25 | m_scopes(obj.m_scopes)
26 | {
27 | }
28 |
29 | bool ShowLogo() const override
30 | {
31 | return false;
32 | }
33 |
34 | bool SupportsPackages() const override
35 | {
36 | return true;
37 | }
38 |
39 | static const LPCWSTR ColorTag;
40 |
41 | protected:
42 | void StartDocument() override;
43 | void StartArray(_In_opt_ const std::wstring& name = empty_wstring) override;
44 | void StartObject(_In_opt_ const std::wstring& name = empty_wstring) override;
45 | void WriteProperty(_In_ const std::wstring& name, _In_ const std::wstring& value) override;
46 | void EndObject() override;
47 | void EndArray() override;
48 | std::wstring FormatDate(_In_ const FILETIME& value) override;
49 |
50 | private:
51 | static const size_t padding_size = 2;
52 |
53 | void Push();
54 | void Pop();
55 |
56 | void StartScope(_In_opt_ const std::wstring& name, _In_ std::wstring::const_pointer fallback);
57 | void EndScope();
58 |
59 | std::wstring m_padding;
60 | std::stack m_scopes;
61 | };
62 |
--------------------------------------------------------------------------------
/.vsts-ci.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | variables:
5 | SignType: Real
6 |
7 | trigger:
8 | batch: true
9 | branches:
10 | include:
11 | - main
12 | paths:
13 | exclude:
14 | - README.md
15 | tags:
16 | include:
17 | - "*"
18 |
19 | pr: none
20 |
21 | resources:
22 | repositories:
23 | - repository: MicroBuildTemplate
24 | type: git
25 | name: 1ESPipelineTemplates/MicroBuildTemplate
26 | ref: refs/tags/release
27 |
28 | extends:
29 | template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
30 | parameters:
31 | pool:
32 | name: VSEngSS-MicroBuild2022-1ES
33 | sdl:
34 | sourceAnalysisPool:
35 | name: AzurePipelines-EO
36 | image: 1ESPT-Windows2022
37 | policheck:
38 | enabled: true
39 | binskim:
40 | enabled: true
41 | scanOutputDirectoryOnly: true # BinSkim scans whole source tree but we only need to scan the output dir.
42 | analyzeTargetGlob: +:f|$(Build.ArtifactStagingDirectory)\out\**;-:f|$(Build.ArtifactStagingDirectory)\out\**\*.test.*
43 | tsa:
44 | enabled: true
45 | configFile: $(Build.SourcesDirectory)\.config\tsaoptions.json
46 | onboard: false
47 |
48 | stages:
49 | - stage: Build
50 | jobs:
51 | - job: Build
52 | templateContext:
53 | mb:
54 | signing:
55 | enabled: true
56 | signType: $(SignType)
57 | signWithProd: true
58 |
59 | steps:
60 | - template: /pipelines/templates/build.yml@self
61 | parameters:
62 | BuildConfiguration: $(BuildConfiguration)
63 | BuildPlatform: $(BuildPlatform)
64 | Sign: true
65 | PublishArtifactTemplate: /pipelines/templates/1es-publish-task.yml@self
66 |
--------------------------------------------------------------------------------
/test/vswhere.test/UtilitiesTests.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 | using namespace Microsoft::VisualStudio::CppUnitTestFramework;
10 |
11 | TEST_CLASS(UtilitiesTests)
12 | {
13 | public:
14 | TEST_METHOD(ci_equal_theory)
15 | {
16 | vector> data =
17 | {
18 | { L"a", L"a", true },
19 | { L"a", L"A", true },
20 | { L"a", L"b", false },
21 | { L"b", L"a", false },
22 | { L"foo", L"foobar", false },
23 | { L"foobar", L"foo", false },
24 | };
25 |
26 | ci_equal sut;
27 | for (const auto& item : data)
28 | {
29 | wstring lhs, rhs;
30 | bool expected;
31 |
32 | tie(lhs, rhs, expected) = item;
33 | auto actual = sut(lhs, rhs);
34 |
35 | Assert::AreEqual(expected, actual, format(L"ci_equal(%ls, %ls)", lhs.c_str(), rhs.c_str()).c_str());
36 | }
37 | }
38 |
39 | TEST_METHOD(ci_less_theory)
40 | {
41 | vector> data =
42 | {
43 | { L"a", L"a", false },
44 | { L"a", L"A", false },
45 | { L"a", L"b", true },
46 | { L"b", L"a", false },
47 | { L"foo", L"foobar", true },
48 | { L"foobar", L"foo", false },
49 | };
50 |
51 | ci_less sut;
52 | for (const auto& item : data)
53 | {
54 | wstring lhs, rhs;
55 | bool expected;
56 |
57 | tie(lhs, rhs, expected) = item;
58 | auto actual = sut(lhs, rhs);
59 |
60 | Assert::AreEqual(expected, actual, format(L"ci_less(%ls, %ls)", lhs.c_str(), rhs.c_str()).c_str());
61 | }
62 | }
63 | };
64 |
--------------------------------------------------------------------------------
/src/vswhere.lib/CommandParser.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | vector CommandParser::Parse(_In_ LPCWSTR wszCommandLine)
11 | {
12 | _ASSERT(wszCommandLine && *wszCommandLine);
13 |
14 | int argc = 0;
15 | auto argv = ::CommandLineToArgvW(wszCommandLine, &argc);
16 |
17 | if (!argv)
18 | {
19 | throw win32_error();
20 | }
21 |
22 | // Make sure the argument array is released when it falls out of scope.
23 | unique_ptr args(&argv, [](_In_opt_ LPWSTR** ppwsz)
24 | {
25 | if (ppwsz)
26 | {
27 | ::LocalFree(*ppwsz);
28 | }
29 | });
30 |
31 | return Parse(argc, const_cast(*args));
32 | }
33 |
34 | vector CommandParser::Parse(_In_ int argc, _In_ LPCWSTR argv[])
35 | {
36 | vector tokens;
37 |
38 | // Parse program path from first argument.
39 | if (argc < 1)
40 | {
41 | // TODO: Provide localized error message.
42 | throw win32_error(ERROR_INVALID_PARAMETER, "missing program argument");
43 | }
44 |
45 | m_path = argv[0];
46 |
47 | // Parse remaining arguments.
48 | for (auto i = 1; i < argc; ++i)
49 | {
50 | auto arg = argv[i];
51 |
52 | if (!arg || !*arg)
53 | {
54 | // TODO: Provide localized error message.
55 | throw win32_error(ERROR_INVALID_PARAMETER, "empty argument");
56 | }
57 |
58 | if (L'-' == arg[0] || L'/' == arg[0])
59 | {
60 | tokens.push_back({ Token::eParameter, &arg[1] });
61 | }
62 | else
63 | {
64 | tokens.push_back({ Token::eArgument, arg });
65 | }
66 | }
67 |
68 | return tokens;
69 | }
70 |
--------------------------------------------------------------------------------
/src/vswhere.lib/JsonScope.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #include "stdafx.h"
7 |
8 | using namespace std;
9 |
10 | void JsonScope::StartScope()
11 | {
12 | WriteSeparator();
13 | }
14 |
15 | void JsonScope::StartProperty()
16 | {
17 | // Delay writing the parent scope until we write a property.
18 | WriteStart();
19 |
20 | WriteSeparator();
21 | RequireSeparator();
22 | }
23 |
24 | void JsonScope::WriteStartImpl()
25 | {
26 | bool writeKey = false;
27 |
28 | WriteSeparator();
29 |
30 | if (Parent())
31 | {
32 | if (Parent()->IsObject())
33 | {
34 | writeKey = true;
35 | }
36 |
37 | // Write new line if not the root scope.
38 | Console().WriteLine();
39 | }
40 |
41 | if (writeKey && Name().length())
42 | {
43 | Console().Write(
44 | L"%ls%ls\"%ls\"%ls: %lc",
45 | Padding().c_str(),
46 | Console().Color(JsonFormatter::ColorName),
47 | Name().c_str(),
48 | Console().ResetColor(),
49 | StartChar());
50 | }
51 | else
52 | {
53 | Console().Write(L"%ls%lc", Padding().c_str(), StartChar());
54 | }
55 | }
56 |
57 | void JsonScope::WriteEndImpl()
58 | {
59 | if (m_requireSep)
60 | {
61 | // Write new line and padding only if elements were written.
62 | // This keeps empty arrays and objects looking like [] and {}.
63 | Console().Write(L"\n%ls", Padding().c_str());
64 | }
65 |
66 | Console().Write(L"%lc", EndChar());
67 | }
68 |
69 | void JsonScope::RequireSeparator() noexcept
70 | {
71 | m_requireSep = true;
72 |
73 | if (auto p = Parent())
74 | {
75 | p->RequireSeparator();
76 | }
77 | }
78 |
79 | void JsonScope::WriteSeparator()
80 | {
81 | if (m_requireSep)
82 | {
83 | Console().Write(L",");
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/vswhere.lib/JsonFormatter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | class JsonFormatter :
9 | public Formatter
10 | {
11 | public:
12 | static std::unique_ptr Create(_In_ CommandArgs& args, _In_ ::Console& console)
13 | {
14 | return std::unique_ptr(new JsonFormatter(args, console));
15 | }
16 |
17 | JsonFormatter(_In_ CommandArgs& args, _In_ ::Console& console) :
18 | Formatter(args, console)
19 | {
20 | }
21 |
22 | JsonFormatter(_In_ const JsonFormatter& obj) :
23 | Formatter(obj),
24 | m_padding(obj.m_padding),
25 | m_scopes(obj.m_scopes)
26 | {
27 | }
28 |
29 | static std::wstring Escape(_In_ const std::wstring& value);
30 |
31 | bool ShowLogo() const override
32 | {
33 | return false;
34 | }
35 |
36 | bool SupportsPackages() const override
37 | {
38 | return true;
39 | }
40 |
41 | static const LPCWSTR ColorBool;
42 | static const LPCWSTR ColorNumber;
43 |
44 | protected:
45 | void StartArray(_In_opt_ const std::wstring& name = empty_wstring) override;
46 | void StartObject(_In_opt_ const std::wstring& name = empty_wstring) override;
47 | void WriteProperty(_In_ const std::wstring& name, _In_ const std::wstring& value) override;
48 | void WriteProperty(_In_ const std::wstring& name, _In_ bool value) override;
49 | void WriteProperty(_In_ const std::wstring& name, _In_ long long value) override;
50 | void EndObject() override;
51 | void EndArray() override;
52 | void EndDocument() override;
53 | std::wstring FormatDate(_In_ const FILETIME& value) override;
54 |
55 | private:
56 | static const size_t padding_size = 2;
57 |
58 | void Push();
59 | void Pop();
60 |
61 | void StartScope(_In_ JsonScope::Type type, _In_ const std::wstring& name);
62 | void StartProperty(_In_ const std::wstring& name);
63 | void EndScope();
64 |
65 | std::wstring m_padding;
66 | std::stack m_scopes;
67 | };
68 |
--------------------------------------------------------------------------------
/src/vswhere.lib/stdafx.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | #pragma once
7 |
8 | #include "targetver.h"
9 |
10 | #define WIN32_LEAN_AND_MEAN
11 |
12 | // Windows headers
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | // CRT header files
19 | #include
20 |
21 | // COM support header files
22 | #include
23 | #include
24 |
25 | // STL headers
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include