Repository: Squirrel/Squirrel.Windows
Branch: develop
Commit: 51f5e2cb01ad
Files: 216
Total size: 58.8 MB
Directory structure:
gitextract_rd62uedp/
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── bug_report.md
│ └── workflows/
│ └── build.yml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── COPYING
├── README.md
├── Squirrel.sln
├── devbuild.cmd
├── docs/
│ ├── contributing/
│ │ ├── branching-strategy.md
│ │ ├── building-squirrel.md
│ │ ├── contributing.md
│ │ └── vs-solution-overview.md
│ ├── faq.md
│ ├── getting-started/
│ │ ├── 0-overview.md
│ │ ├── 1-integrating.md
│ │ ├── 2-packaging.md
│ │ ├── 3-distributing.md
│ │ ├── 4-installing.md
│ │ └── 5-updating.md
│ ├── goals.md
│ ├── readme.md
│ └── using/
│ ├── amazon-s3.md
│ ├── application-signing.md
│ ├── custom-squirrel-events-non-cs.md
│ ├── custom-squirrel-events.md
│ ├── debugging-installs.md
│ ├── debugging-updates.md
│ ├── delta-packages.md
│ ├── github.md
│ ├── install-process.md
│ ├── loading-gif.md
│ ├── machine-wide-installs.md
│ ├── microsoft-iis.md
│ ├── naming.md
│ ├── nuget-package-metadata.md
│ ├── octopack.md
│ ├── packaging-tools.md
│ ├── squirrel-command-line.md
│ ├── staged-rollouts.md
│ ├── teamcity.md
│ ├── update-manager.md
│ ├── update-process.md
│ ├── visual-studio-packaging.md
│ └── x-doc-template.md
├── src/
│ ├── Directory.Build.props
│ ├── Setup/
│ │ ├── FxHelper.cpp
│ │ ├── FxHelper.h
│ │ ├── MachineInstaller.cpp
│ │ ├── MachineInstaller.h
│ │ ├── Setup.h
│ │ ├── Setup.rc
│ │ ├── Setup.vcxproj
│ │ ├── Setup.vcxproj.filters
│ │ ├── UpdateRunner.cpp
│ │ ├── UpdateRunner.h
│ │ ├── compat.manifest
│ │ ├── resource.h
│ │ ├── stdafx.cpp
│ │ ├── stdafx.h
│ │ ├── targetver.h
│ │ ├── unzip.cpp
│ │ ├── unzip.h
│ │ ├── winmain.cpp
│ │ └── wtl90/
│ │ ├── atlapp.h
│ │ ├── atlcrack.h
│ │ ├── atlctrls.h
│ │ ├── atlctrlw.h
│ │ ├── atlctrlx.h
│ │ ├── atlddx.h
│ │ ├── atldlgs.h
│ │ ├── atldwm.h
│ │ ├── atlfind.h
│ │ ├── atlframe.h
│ │ ├── atlgdi.h
│ │ ├── atlmisc.h
│ │ ├── atlprint.h
│ │ ├── atlres.h
│ │ ├── atlresce.h
│ │ ├── atlribbon.h
│ │ ├── atlscrl.h
│ │ ├── atlsplit.h
│ │ ├── atltheme.h
│ │ ├── atluser.h
│ │ ├── atlwince.h
│ │ └── atlwinx.h
│ ├── Squirrel/
│ │ ├── ApplyReleasesProgress.cs
│ │ ├── BinaryPatchUtility.cs
│ │ ├── ContentType.cs
│ │ ├── DeltaPackage.cs
│ │ ├── EnumerableExtensions.cs
│ │ ├── FileDownloader.cs
│ │ ├── IUpdateManager.cs
│ │ ├── MarkdownSharp.cs
│ │ ├── MsDeltaCompression.cs
│ │ ├── NativeMethods.cs
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ ├── ReleaseEntry.cs
│ │ ├── ReleaseExtensions.cs
│ │ ├── ReleasePackage.cs
│ │ ├── ShellFile.cs
│ │ ├── SimpleJson/
│ │ │ └── SimpleJson.cs
│ │ ├── SimpleSplat/
│ │ │ ├── AssemblyFinder.cs
│ │ │ ├── Logging.cs
│ │ │ ├── MemoizingMRUCache.cs
│ │ │ ├── ModeDetector.cs
│ │ │ ├── PlatformModeDetector.cs
│ │ │ └── ServiceLocation.cs
│ │ ├── Squirrel.csproj
│ │ ├── SquirrelAwareApp.cs
│ │ ├── SquirrelAwareExecutableDetector.cs
│ │ ├── TaskbarHelper.cs
│ │ ├── TrayHelper.cs
│ │ ├── UpdateInfo.cs
│ │ ├── UpdateManager.ApplyReleases.cs
│ │ ├── UpdateManager.CheckForUpdates.cs
│ │ ├── UpdateManager.DownloadReleases.cs
│ │ ├── UpdateManager.Factory.cs
│ │ ├── UpdateManager.InstallHelpers.cs
│ │ ├── UpdateManager.cs
│ │ └── Utility.cs
│ ├── Squirrel.nuspec
│ ├── StubExecutable/
│ │ ├── LICENSE.md
│ │ ├── Resource.h
│ │ ├── Semver200_comparator.cpp
│ │ ├── Semver200_parser.cpp
│ │ ├── StubExecutable.cpp
│ │ ├── StubExecutable.h
│ │ ├── StubExecutable.rc
│ │ ├── StubExecutable.vcxproj
│ │ ├── StubExecutable.vcxproj.filters
│ │ ├── semver200.h
│ │ ├── stdafx.cpp
│ │ ├── stdafx.h
│ │ ├── targetver.h
│ │ ├── version.h
│ │ └── version.inl
│ ├── SyncReleases/
│ │ ├── App.config
│ │ ├── Mono.Options/
│ │ │ └── Options.cs
│ │ ├── Program.cs
│ │ ├── SyncImplementations.cs
│ │ └── SyncReleases.csproj
│ ├── Update/
│ │ ├── AnimatedGifWindow.cs
│ │ ├── App.config
│ │ ├── AuthenticodeTools.cs
│ │ ├── CopStache.cs
│ │ ├── Mono.Options/
│ │ │ └── Options.cs
│ │ ├── Program.cs
│ │ ├── StartupOption.cs
│ │ ├── Update-Mono.csproj
│ │ ├── Update.com
│ │ ├── Update.csproj
│ │ ├── app.manifest
│ │ └── packages.config
│ ├── WriteZipToSetup/
│ │ ├── WriteZipToSetup.cpp
│ │ ├── WriteZipToSetup.vcxproj
│ │ ├── WriteZipToSetup.vcxproj.filters
│ │ ├── stdafx.cpp
│ │ └── stdafx.h
│ ├── build_official.cmd
│ └── squirrel.windows.props
├── test/
│ ├── Directory.Build.props
│ ├── Squirrel.Tests/
│ │ ├── ApplyReleasesProgressTests.cs
│ │ ├── ApplyReleasesTests.cs
│ │ ├── CheckForUpdateTests.cs
│ │ ├── ContentTypeTests.cs
│ │ ├── DeltaPackageTests.cs
│ │ ├── DownloadReleasesTests.cs
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ ├── ReleaseEntryTests.cs
│ │ ├── ReleasePackageTests.cs
│ │ ├── Squirrel.Tests.csproj
│ │ ├── SquirrelAwareExecutableDetectorTests.cs
│ │ ├── TestHelpers/
│ │ │ ├── AssertExtensions.cs
│ │ │ ├── ExposedClass.cs
│ │ │ ├── ExposedObject.cs
│ │ │ ├── ExposedObjectHelper.cs
│ │ │ ├── IntegrationTestHelper.cs
│ │ │ └── StaticHttpServer.cs
│ │ ├── UpdateManagerTests.cs
│ │ ├── UtilityTests.cs
│ │ └── fixtures/
│ │ ├── Caliburn.Micro.1.4.1.nupkg
│ │ ├── Caliburn.Micro.1.5.2.nupkg
│ │ ├── CaliburnMicroDemo.1.0.0.nupkg
│ │ ├── ProjectDependsOnJsonDotNet.1.0.nupkg
│ │ ├── ProjectWithContent.1.0.0.0-beta-full.nupkg
│ │ ├── ProjectWithContent.1.0.0.0-beta.nupkg
│ │ ├── RELEASES-OnePointOh
│ │ ├── RELEASES-OnePointOne
│ │ ├── SpecialCharacters-0.1.0-full.nupkg
│ │ ├── Squirrel.Core.1.0.0.0-full.nupkg
│ │ ├── Squirrel.Core.1.0.0.0.nupkg
│ │ ├── Squirrel.Core.1.1.0.0-delta.nupkg
│ │ ├── Squirrel.Core.1.1.0.0-full.nupkg
│ │ ├── Squirrel.Core.1.1.0.0.nupkg
│ │ ├── Squirrel.Core.1.1.0.0.nuspec
│ │ ├── Squirrel.Core.1.2.0.0-full.nupkg
│ │ ├── Squirrel.Core.1.3.0.0-full.nupkg
│ │ ├── Squirrel.Core.NoDependencies.1.0.0.0.nupkg
│ │ ├── Squirrel.Tests.0.1.0-pre.nupkg
│ │ ├── Squirrel.Tests.0.2.0-pre.nupkg
│ │ ├── SquirrelInstalledApp.nuspec
│ │ ├── ThisShouldBeANet45Project.1.0.nupkg
│ │ ├── content-types/
│ │ │ ├── basic-merged.xml
│ │ │ ├── basic.xml
│ │ │ ├── complex-merged.xml
│ │ │ └── complex.xml
│ │ ├── slack-1.1.8-full.nupkg
│ │ └── slack-1.2.0-delta.nupkg
│ └── test_official.cmd
├── vendor/
│ └── wix/
│ ├── candle.exe.config
│ ├── darice.cub
│ ├── light.exe.config
│ └── template.wxs
└── version.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text diff=csharp
*.vb text
*.c text
*.cpp text
*.cxx text
*.h text
*.hxx text
*.py text
*.rb text
*.java text
*.html text
*.htm text
*.css text
*.scss text
*.sass text
*.less text
*.js text
*.lisp text
*.clj text
*.sql text
*.php text
*.lua text
*.m text
*.asm text
*.erl text
*.fs text
*.fsx text
*.hs text
*.csproj text merge=union
*.vbproj text merge=union
*.fsproj text merge=union
*.dbproj text merge=union
*.sln text eol=crlf merge=union
src/Setup/resource.h binary
src/Setup/Setup.rc binary
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Feedback to help us improve the project
title: ''
labels: ''
assignees: ''
---
**Squirrel version(s)**
_Which version(s) of the project are you using?_
**Description**
_Replace this text with a short description of the problem_
**Steps to recreate**
1. Replace this
2. text with
3. the steps
4. to recreate
**Expected behavior**
_Explain what it's doing and why it's wrong_
**Actual behavior**
_Explain what it should be doing after it's fixed_
**Additional information**
_Add any other context about the problem here_
================================================
FILE: .github/workflows/build.yml
================================================
name: Build Squirrel
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
DOTNET_NOLOGO: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
NUGET_XMLDOC_MODE: skip
jobs:
build:
name: Build
runs-on: windows-2019
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0
submodules: recursive
- name: Build Squirrel
shell: cmd
run: ./src/build_official.cmd
- name: Test Squirrel
shell: cmd
run: ./test/test_official.cmd
- name: Save build
uses: actions/upload-artifact@v2
with:
name: artifacts
path: build/artifacts/
================================================
FILE: .gitignore
================================================
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
*.sln.ide
# Build results
**/[Dd]ebug/
**/[Rr]elease/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
**/*.dotCover
**/packages/
packages
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
# ReSharper is a .NET coding add-in
_ReSharper*
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish
# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
############
## Windows
############
# Windows image file caches
Thumbs.db
# Folder config file
Desktop.ini
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
# Mac crap
.DS_Store
# NCrunch crap
*ncrunch*
## WiX PDBs
*.wixpdb
*.wixobj
## NUnit Test Output
nunit-Squirrel.Tests.xml
## Pester Test Output
tests/Test.xml
## CPP db crap
*.db
*.opendb
.vs/
================================================
FILE: .gitmodules
================================================
[submodule "vendor/nuget"]
path = vendor/nuget
url = https://github.com/Squirrel/NuGet
branch = fix-prerelease-comparison
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at github@brendanforster.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
================================================
FILE: COPYING
================================================
Copyright (c) 2012 GitHub, Inc.
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:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
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.
================================================
FILE: README.md
================================================
| README.md |
|:---|
# Contributors Needed
We are looking for help with maintaining this important project - please read the discussion in [#1470](https://github.com/Squirrel/Squirrel.Windows/issues/1470) for more information.
---
# Squirrel: It's like ClickOnce but Works™

[](https://dev.azure.com/squirrel-installers/Squirrel.Windows/_build/latest?definitionId=1&branchName=master)
Squirrel is both a set of tools and a library, to completely manage both installation and updating your Desktop Windows application, written in either C# or any other language (i.e., Squirrel can manage native C++ applications).
Squirrel uses NuGet packages to create installation and update packages, which means that you probably already know most of what you need to create an installer.
## What Do We Want?
Windows apps should be as fast and as easy to install and update as apps like Google Chrome. From an app developer's side, it should be really straightforward to create an installer for my app, and publish updates to it, without having to jump through insane hoops.
* **Integrating** an app to use Squirrel should be extremely easy, provide a client API, and be developer friendly.
* **Packaging** is really easy, can be automated, and supports delta update packages.
* **Distributing** should be straightforward, use simple HTTP updates, and provide multiple "channels" (a-la Chrome Dev/Beta/Release).
* **Installing** is Wizard-Free™, with no UAC dialogs, does not require reboot, and is .NET Framework friendly.
* **Updating** is in the background, doesn't interrupt the user, and does not require a reboot.
Refer to our full list of goals for [integrating, packaging, distributing, installing, and updating](docs/goals.md).
## Documentation
See the documentation [Table of Contents](docs/readme.md) for an overview of the available documentation for Squirrel.Windows. It includes a [Getting Started Guide](docs/getting-started/0-overview.md) as well as additional topics related to using Squirrel in your applications.
## Building Squirrel
For the impatient:
```sh
git clone --recursive https://github.com/squirrel/squirrel.windows
cd squirrel.windows
devbuild.cmd
```
See [Contributing](docs/contributing/contributing.md) for additional information on building and contributing to Squirrel.
## License and Usage
See [COPYING](COPYING) for details on copyright and usage of the Squirrel.Windows software.
================================================
FILE: Squirrel.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.352
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrel", "src\Squirrel\Squirrel.csproj", "{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrel.Tests", "test\Squirrel.Tests\Squirrel.Tests.csproj", "{98AEB048-E27D-42F4-9440-505B7F78BAFD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Setup", "src\Setup\Setup.vcxproj", "{C1D40624-A484-438A-B846-052F321C89D1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Update", "src\Update\Update.csproj", "{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SyncReleases", "src\SyncReleases\SyncReleases.csproj", "{EB521191-1EBF-4D06-8541-ED192E2EE378}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionLevel", "SolutionLevel", "{ED657D2C-F8A0-4012-A64F-7367D41BE4D2}"
ProjectSection(SolutionItems) = preProject
src\Squirrel.nuspec = src\Squirrel.nuspec
vendor\wix\template.wxs = vendor\wix\template.wxs
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "vendor\nuget\src\Core\Core.csproj", "{F879F274-EFA0-4157-8404-33A19B4E6AEC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WriteZipToSetup", "src\WriteZipToSetup\WriteZipToSetup.vcxproj", "{4D3C8B70-075D-48A5-9FF3-EDB87347B136}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Update-Mono", "src\Update\Update-Mono.csproj", "{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StubExecutable", "src\StubExecutable\StubExecutable.vcxproj", "{C028DB2A-E7C5-4232-8C22-D5FBA2176136}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CIBuild|Any CPU = CIBuild|Any CPU
CIBuild|Mixed Platforms = CIBuild|Mixed Platforms
CIBuild|x64 = CIBuild|x64
CIBuild|x86 = CIBuild|x86
Coverage|Any CPU = Coverage|Any CPU
Coverage|Mixed Platforms = Coverage|Mixed Platforms
Coverage|x64 = Coverage|x64
Coverage|x86 = Coverage|x86
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Mono Debug|Any CPU = Mono Debug|Any CPU
Mono Debug|Mixed Platforms = Mono Debug|Mixed Platforms
Mono Debug|x64 = Mono Debug|x64
Mono Debug|x86 = Mono Debug|x86
Mono Release|Any CPU = Mono Release|Any CPU
Mono Release|Mixed Platforms = Mono Release|Mixed Platforms
Mono Release|x64 = Mono Release|x64
Mono Release|x86 = Mono Release|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|Any CPU.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|Any CPU.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|Mixed Platforms.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|Mixed Platforms.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|x64.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|x64.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|x86.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.CIBuild|x86.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|Any CPU.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|Mixed Platforms.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|Mixed Platforms.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|x64.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|x64.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|x86.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Coverage|x86.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|x64.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|x64.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|x86.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Debug|x86.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|Any CPU.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|x64.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|x64.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|x86.ActiveCfg = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Debug|x86.Build.0 = Debug|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|Any CPU.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|Any CPU.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|Mixed Platforms.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|x64.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|x64.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|x86.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Mono Release|x86.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|Any CPU.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|x64.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|x64.Build.0 = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|x86.ActiveCfg = Release|Any CPU
{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}.Release|x86.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|Any CPU.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|Any CPU.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|Mixed Platforms.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|Mixed Platforms.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|x64.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|x64.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|x86.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.CIBuild|x86.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|Any CPU.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|Mixed Platforms.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|Mixed Platforms.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|x64.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|x64.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|x86.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Coverage|x86.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|x64.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|x64.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|x86.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Debug|x86.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|Any CPU.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|x64.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|x64.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|x86.ActiveCfg = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Debug|x86.Build.0 = Debug|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|Any CPU.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|Any CPU.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|Mixed Platforms.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|x64.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|x64.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|x86.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Mono Release|x86.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|Any CPU.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|x64.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|x64.Build.0 = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|x86.ActiveCfg = Release|Any CPU
{98AEB048-E27D-42F4-9440-505B7F78BAFD}.Release|x86.Build.0 = Release|Any CPU
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|Any CPU.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|Any CPU.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|Mixed Platforms.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|Mixed Platforms.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|x64.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|x64.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|x86.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.CIBuild|x86.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|Any CPU.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|Any CPU.Build.0 = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|Mixed Platforms.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|Mixed Platforms.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|x64.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|x64.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|x86.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Coverage|x86.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Debug|Any CPU.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Debug|Any CPU.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Debug|x64.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Debug|x86.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Debug|x86.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|Any CPU.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|Any CPU.Build.0 = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|Mixed Platforms.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|x64.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|x64.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|x86.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Debug|x86.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|Any CPU.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|Any CPU.Build.0 = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|Mixed Platforms.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|Mixed Platforms.Build.0 = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|x64.ActiveCfg = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|x64.Build.0 = Debug|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|x86.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Mono Release|x86.Build.0 = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Release|Any CPU.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Release|Any CPU.Build.0 = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Release|Mixed Platforms.Build.0 = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Release|x64.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Release|x86.ActiveCfg = Release|Win32
{C1D40624-A484-438A-B846-052F321C89D1}.Release|x86.Build.0 = Release|Win32
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|Any CPU.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|Any CPU.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|Mixed Platforms.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|Mixed Platforms.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|x64.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|x64.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|x86.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.CIBuild|x86.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|Any CPU.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|Any CPU.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|Mixed Platforms.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|x64.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|x64.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|x86.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Coverage|x86.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|x64.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|x64.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|x86.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Debug|x86.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|Any CPU.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|x64.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|x64.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|x86.ActiveCfg = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Debug|x86.Build.0 = Debug|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|Any CPU.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|Any CPU.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|Mixed Platforms.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|x64.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|x64.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|x86.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Mono Release|x86.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|Any CPU.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|x64.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|x64.Build.0 = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|x86.ActiveCfg = Release|Any CPU
{1EEBACBC-6982-4696-BD4E-899ED0AC6CD2}.Release|x86.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|Any CPU.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|Any CPU.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|Mixed Platforms.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|Mixed Platforms.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|x64.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|x64.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|x86.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.CIBuild|x86.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|Any CPU.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|Any CPU.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|Mixed Platforms.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|x64.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|x64.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|x86.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Coverage|x86.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|x64.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|x64.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|x86.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Debug|x86.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|Any CPU.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|x64.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|x64.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|x86.ActiveCfg = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Debug|x86.Build.0 = Debug|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|Any CPU.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|Any CPU.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|Mixed Platforms.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|x64.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|x64.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|x86.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Mono Release|x86.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|Any CPU.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|x64.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|x64.Build.0 = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|x86.ActiveCfg = Release|Any CPU
{EB521191-1EBF-4D06-8541-ED192E2EE378}.Release|x86.Build.0 = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|Any CPU.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|Any CPU.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|Mixed Platforms.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|Mixed Platforms.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|x64.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|x64.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|x86.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.CIBuild|x86.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|Any CPU.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|Any CPU.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|Mixed Platforms.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|Mixed Platforms.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|x64.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|x64.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|x86.ActiveCfg = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Coverage|x86.Build.0 = Coverage|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|x64.ActiveCfg = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|x64.Build.0 = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|x86.ActiveCfg = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Debug|x86.Build.0 = Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|Any CPU.ActiveCfg = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|Any CPU.Build.0 = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|Mixed Platforms.ActiveCfg = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|Mixed Platforms.Build.0 = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|x64.ActiveCfg = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|x64.Build.0 = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|x86.ActiveCfg = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Debug|x86.Build.0 = Mono Debug|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|Any CPU.ActiveCfg = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|Any CPU.Build.0 = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|Mixed Platforms.ActiveCfg = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|Mixed Platforms.Build.0 = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|x64.ActiveCfg = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|x64.Build.0 = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|x86.ActiveCfg = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Mono Release|x86.Build.0 = Mono Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|Any CPU.Build.0 = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|x64.ActiveCfg = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|x64.Build.0 = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|x86.ActiveCfg = Release|Any CPU
{F879F274-EFA0-4157-8404-33A19B4E6AEC}.Release|x86.Build.0 = Release|Any CPU
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|Any CPU.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|Any CPU.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|Mixed Platforms.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|Mixed Platforms.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|x64.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|x64.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|x86.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.CIBuild|x86.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|Any CPU.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|Any CPU.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|Mixed Platforms.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|Mixed Platforms.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|x64.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|x64.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|x86.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Coverage|x86.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Debug|Any CPU.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Debug|Any CPU.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Debug|x64.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Debug|x86.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Debug|x86.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|Any CPU.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|Any CPU.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|Mixed Platforms.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|x64.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|x64.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|x86.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Debug|x86.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|Any CPU.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|Any CPU.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|Mixed Platforms.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|Mixed Platforms.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|x64.ActiveCfg = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|x64.Build.0 = Debug|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|x86.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|x86.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Any CPU.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Any CPU.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Mixed Platforms.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|x64.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|x86.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|x86.Build.0 = Release|Win32
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|Any CPU.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|Any CPU.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|Mixed Platforms.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|Mixed Platforms.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|x64.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|x64.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|x86.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.CIBuild|x86.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|Any CPU.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|Mixed Platforms.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|Mixed Platforms.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|x64.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|x64.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|x86.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Coverage|x86.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|x64.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|x64.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|x86.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Debug|x86.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|Any CPU.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|x64.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|x64.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|x86.ActiveCfg = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Debug|x86.Build.0 = Debug|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|Any CPU.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|Any CPU.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|Mixed Platforms.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|x64.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|x64.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|x86.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Mono Release|x86.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|Any CPU.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|x64.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|x64.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|x86.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|x86.Build.0 = Release|Any CPU
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x86.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x86.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Any CPU.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Any CPU.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x64.ActiveCfg = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x64.Build.0 = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x86.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x86.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Mixed Platforms.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x64.ActiveCfg = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x64.Build.0 = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x86.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x86.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x86.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Any CPU.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Any CPU.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {68CA987A-9BAB-4C75-8EEB-4596BA6BBD07}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
$0.TextStylePolicy = $1
$1.inheritsSet = VisualStudio
$1.inheritsScope = text/plain
$1.scope = text/plain
$0.CSharpFormattingPolicy = $2
$2.IndentSwitchBody = True
$2.IndentBlocksInsideExpressions = True
$2.AnonymousMethodBraceStyle = NextLine
$2.PropertyBraceStyle = NextLine
$2.PropertyGetBraceStyle = NextLine
$2.PropertySetBraceStyle = NextLine
$2.EventBraceStyle = NextLine
$2.EventAddBraceStyle = NextLine
$2.EventRemoveBraceStyle = NextLine
$2.StatementBraceStyle = NextLine
$2.ElseNewLinePlacement = NewLine
$2.CatchNewLinePlacement = NewLine
$2.FinallyNewLinePlacement = NewLine
$2.WhileNewLinePlacement = DoNotCare
$2.ArrayInitializerWrapping = DoNotChange
$2.ArrayInitializerBraceStyle = NextLine
$2.BeforeMethodDeclarationParentheses = False
$2.BeforeMethodCallParentheses = False
$2.BeforeConstructorDeclarationParentheses = False
$2.NewLineBeforeConstructorInitializerColon = NewLine
$2.NewLineAfterConstructorInitializerColon = SameLine
$2.BeforeDelegateDeclarationParentheses = False
$2.NewParentheses = False
$2.SpacesBeforeBrackets = False
$2.inheritsSet = Mono
$2.inheritsScope = text/x-csharp
$2.scope = text/x-csharp
EndGlobalSection
EndGlobal
================================================
FILE: devbuild.cmd
================================================
@echo off
setlocal
pushd %~dp0
:parse_args
if /i "%1"=="release" set _C=/p:Configuration=Release
if /i "%1"=="init" set _INIT=1
if /i "%1"=="initialize" set _INIT=1
if /i "%1"=="inc" set _INCREMENTAL=1
if /i "%1"=="incremental" set _INCREMENTAL=1
if /i "%1"=="clean" set _INCREMENTAL= & set _CLEAN=1
if not "%1"=="" shift & goto parse_args
if not "%_INCREMENTAL"=="1" rd /s /q build packages 2> nul
if not "%_CLEAN%"=="" goto end
if "%_INIT%"=="1" git submodule update --init --recursive
nuget restore
msbuild -Restore %_C% -m -nr:false -v:m
:end
popd
endlocal
================================================
FILE: docs/contributing/branching-strategy.md
================================================
| [docs](..) / [contributing](.) / branching-strategy.md
|:---|
# tl;dr
1. Fork Squirrel.Windows on GitHub
2. Send features/fixes via pull request targeting the default branch: `develop`
# Branching Strategy
Squirrel.Windows uses a very lightweight rendition of [gitflow](https://nvie.com/posts/a-successful-git-branching-model/).
* `master` branch - the `master` branch is where official releases of squirrel are built. Changes to `master` are made only via merge commits from the `develop` branch. Tags are made for each each release.
* `develop` branch - the `develop` branch is where the next version of squirrel is under development. Changes to `develop` are made via pull request from forks and feature branches. So `develop` is the default branch on GitHub.
* fork - your development takes place in fork. When a feature/fix is ready, a pull request is sent to Squirrel.Windows targeting the `develop` branch.
**Why gitflow?** This lightweight rendition of giflow adds minimal "overhead" in the `develop` branch. The `develop` branch allows us to experiment with new ideas and iterate on features. When "enough" work is completed for a release, complete integration testing--including multi-version upgrades--is done on the `develop` branch. When the testing is completed successfully, the `develop` branch is integrated into `master` and a release is automatically built and released.
## See Also
* [Building Squirrel](building-squirrel.md) - steps to build squirrel for the impatient.
* [VS Solution Overview](vs-solution-overview.md) - overview of the various projects in the Squirrel.Windows Visual Studio solution.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/contributing/building-squirrel.md
================================================
| [docs](..) / [contributing](.) / building-squirrel.md
|:---|
# Building Squirrel
Squirrel.Windows is a fairly typical C# / C++ project, the only special part is making sure to clone submodules via the command shown below.
For the Impatient:
```sh
git clone https://github.com/squirrel/squirrel.windows
cd squirrel.windows
git submodule update --init --recursive ## THIS IS THE PART YOU PROBABLY FORGOT
devbuild.cmd
```
**Tip:** You can compile the Squirrel.Windows solution with Visual Studio version 2019 and above (including community edition).
**Tip:** For Visual Studio versions that use the Visual Studio Installer (2017/2019 and above), you will need to have at least both Desktop .NET development and Desktop C++ development workloads checked in the Visual Studio Installer. You will also need to make sure that the individual package for the VC++ version used by Squirrel is checked.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/contributing/contributing.md
================================================
| [docs](..) / [contributing](.) / contributing.md
|:---|
# Contributing
Why not give back and help make Squirrel even better? Here is an overview of ways you can become more involved.
* **Contribute Documentation** - improve the documentation or provide additional code examples to benefit others.
* **Subscribe to Issues on GitHub** - have some experience using Squirrel? Help answer questions under issues or post a Pull Request fixing a bug.
* **Contribute Code** - have a great feature that you feel is a good fit for Squirrel? Send a Pull Request.
## See Also
* [Building Squirrel](building-squirrel.md) - steps to build squirrel for the impatient.
* [VS Solution Overview](vs-solution-overview.md) - overview of the various projects in the Squirrel.Windows Visual Studio solution.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/contributing/vs-solution-overview.md
================================================
| [docs](..) / [contributing](.) / vs-solution-overview.md
|:---|
# Visual Studio Solution Overview
An overview of the various projects in the Squirrel.Windows Visual Studio solution and how they relate to different aspects of the update process.
| Project / Assembly Name | Libraries (NuGet) | Libraries (NuGet) | Releases Directory (releasify output) | MyApp (install location) |
|--------------------------------|---------|-----|------------------|-------------|
| **Core** NuGet.Squirrel.dll | NuGet.Squirrel.dll | | | |
| **Squirrel** Squirrel.dll | Squirrel.dll | | | |
| **SyncRelease** SyncRelease.exe | | SyncRelease.exe | | |
| **Update** Update.exe | | Squirrel.exe | | Update.exe |
| **Setup** Setup.exe | | Setup.exe | Setup.exe (+MyApp.Latest.nupkg) | |
| **WriteZipToSetup** WriteZipToSetup.exe | | WriteZipToSetup.exe | | |
* **Project / Assembly Name**: Solution project name (from Squirrel.sln) and output assembly name.
* **Libraries (NuGet)**: Program libraries installed added as references in your MyApp solution when adding the Squirrel.Windows NuGet package to your project.
* **Libraries (NuGet)**: Executable tools included in the Squirrel.Windows NuGet package used to prepare deployments via the Package Manager Console (e.g., Squirrel.exe).
* **Releases Directory (releasify output)**: Directory where the Squirrel --releasify process outputs the packages and Setup application for your project (e.g., MyAppSourceCode/Releases).
* **MyApp (install location)**: MyApp install directory (e.g., %LOCALAPPDATA%\MyApp) where the application is actually installed and updated via Squirrel.Windows.
**Note**: Note that the Squirrel.exe application found in the tools directory of the Squirrel.Windows NuGet package is actually a renamed version of the Update.exe application (see Squirrel.Windows\src\Squirrel.nuspec)
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/faq.md
================================================
| [docs](.) / faq.md |
|:---|
# Frequently Asked Questions (FAQ)
Frequently Asked Questions for Squirrel.Windows, organized by area below.
## Integrating
1. **Can Squirrel.Windows be used on applications that aren't made with .Net?**
Yes, you can package a non-c# application in the same manner as described in the Getting Started guide. For additional customization, see [custom squirrel events for non-c# apps](using/custom-squirrel-events-non-cs.md).
1. **How do I migrate a ClickOnce app to Squirrel?**
You may want to look into the [ClickOnceToSquirrelMigrator](https://github.com/flagbug/ClickOnceToSquirrelMigrator) migration helper.
1. **How can I determine if my app is a Squirrel app? I provide a squirrel and non-squirrel install version and want to know which is running.**
You can check for the `Update.exe` in the parent directory to determine if the app is using Squirrel ([see #574](https://github.com/Squirrel/Squirrel.Windows/issues/574#issuecomment-176043311)).
```
var assembly = Assembly.GetEntryAssembly();
var updateDotExe = Path.Combine(Path.GetDirectoryName(assembly.Location), "..", "Update.exe");
var isSquirrelInstall = File.Exists(updateDotExe);
```
## Packaging
1. **How can I tell what is going wrong with the releasify?**
Check `packages\Squirrel.Windows.VERSION\tools\SquirrelSetup.log` for logging information when creating packages.
2. **Do I really have to add all the Squirrel DLLs to my app ?**
Yes, you have to add them all to the NuGet package, however, [others](https://github.com/Squirrel/Squirrel.Windows/issues/531) have used [ILMerge](https://www.microsoft.com/en-us/research/people/mbarnett/#ilmerge) to generate a single assembly.
## Distributing
1. **Can I distribute update files on IIS?**
Yes you can, see [Microsoft IIS](using/microsoft-iis.md) for details.
## Installing
1. **The Initial Install via `Setup.exe` is failing. How do I learn what is going wrong?**
Check `%LocalAppData%\SquirrelTemp\SquirrelSetup.log` for logs related to the initial install.
1. **Installer application doesn't do anything. The animation flashes but the application never starts.**
The app is likely crashing on the first run (see [Debugging Installs](using/debugging-installs.md) for details).
1. **The Installer seems to be blocked in Enterprise environments. How can I confirm this?**
Squirrel may be prevented from installing if Group Policy disallows the running of executables from `%LocalAppData%`. In this case, the "show log" button on the "installation failed" dialog will fail because `Update.exe` can not run to create a log file.
The `Setup.exe` for your application should still copy files to `%LocalAppData%\SquirrelTemp` as a pre-installation step. To verify that Group Policy is restricting you, execute `Update.exe` from the command line as follows:
```
C:\>%LocalAppData\MyApp\Update.exe
This program is blocked by group policy. For more information, contact your system administrator.
```
The best course of action is to request that executables for Squirrel and your application be whitelisted by your corporate overlords.
1. **No Shortcuts are Created for my Application**
Verify that the NuGet Package Metadata `id` property doesn't have a [space or \[dot\]](https://github.com/Squirrel/Squirrel.Windows/issues/530) in it.
1. **Can I use a different name for the `Setup.exe` install application?**
Yes, you can rename the `Setup.exe` to what ever you wish (e.g., `MyAppSetup.exe`) ([see #611](https://github.com/Squirrel/Squirrel.Windows/issues/611))
1. **Virus scanner is returning false positives on `MyApp.exe` or `Update.exe`. What can I do?**
[Application Signing](using/application-signing.md) will help. In addition, you can submit false positives to the various antivirus authors (e.g., [Symantec](https://submit.symantec.com/false_positive/), [Microsoft](https://www.microsoft.com/security/portal/Submission/Submit.aspx), [AVG](http://www.avg.com/submit-sample), [Comodo](https://www.comodo.com/home/internet-security/submit.php), [McAfee](https://support.mcafeesaas.com/MCAFEE/_cs/AnswerDetail.aspx?aid=65), [List of Submission Locations](http://www.techsupportalert.com/content/how-report-malware-or-false-positives-multiple-antivirus-vendors.htm), [see #218](https://github.com/Squirrel/Squirrel.Windows/issues/218#issuecomment-166406180)).
1. **Why is my application icon mangled after installation?**
Application icons specified in the [NuGet Package Metadata](using/nuget-package-metadata.md) must be of type icon (.ICO) rather than an image file (source: [issue #745](https://github.com/Squirrel/Squirrel.Windows/issues/745))
## Updating
1. **How do I determine what is going wrong with the UpdateManager in MyApp?**
You can setup your `\bin` directory so you can execute MyApp in the Visual Studio debugger and simply step through the update process as well as catch exceptions and log the results (see [Debugging Updates](using/debugging-updates.md) for details)
2. **I've Distributed a Broken Copy of Update.exe. How can I fix this?**
Sometimes, you might ship a broken copy of `Update.exe` that succeeds the initial install, but doesn't do what you want for some reason. To fix this, you can force an update of the `Update.exe` by including a copy of `Squirrel.exe` in your app update package. If Squirrel sees this, it will copy in this latest version to the local app installation.
3. **How can you replace DLLs while they're loaded? Impossible!**
You can't. So, how can you do it? The basic trick that ClickOnce uses is, you have a folder of EXEs and DLLs, and an Application Shortcut. When ClickOnce goes to update its stuff, it builds a completely *new* folder of binaries, then the last thing it does is rewrite the app shortcut to point to the new folder.
4. **My previous application version is still around after the update. Doesn't Squirrel clean up old versions?**
The current and immediately previous version of your application are not deleted on clean up (see [issue #589](https://github.com/Squirrel/Squirrel.Windows/issues/589)).
5. **How can I persist the [.NET Application Settings](https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/application-settings-overview) after an update?**
See (https://github.com/Squirrel/Squirrel.Windows/issues/198#issuecomment-299262613) for a simple workaround if you want to keep using .NET Application Settings. Alternatively, consider using a solution that lets you control where the settings are persisted, and store settings in an app-specific location under `%LOCALAPPDATA%`.
---
| Return: [Table of Contents](readme.md) |
|:---|
================================================
FILE: docs/getting-started/0-overview.md
================================================
| [docs](..) / [getting-started](.) / 0-overview.md|
|:---|
# Getting Started Guide
Getting Started will walk you through the integration of Squirrel.Windows for a basic c# Windows Forms application named MyApp.
## MyApp
MyApp simply displays the assembly location and application version on a simple form.

For simplicity, any unneeded references and files have been removed from the solution.

If you wish to follow along, you can [download](example/MyApp.zip) a zip file of the MyApp solution.
## Overview
This guide will go over the following steps to demonstrate using Squirrel.Windows to distribute and update MyApp.
1. [Integrating](1-integrating.md) - integrating Squirrel `UpdateManager` into your application.
1. [Packaging](2-packaging.md) - packaging application files and preparing them for release.
1. [Distributing](3-distributing.md) - providing install and update files for users.
1. [Installing](4-installing.md) - process of initial installation of your application.
1. [Updating](5-updating.md) - process of updating an existing install.
---
| Next: [1. Integrating](1-integrating.md)|
|:---|
================================================
FILE: docs/getting-started/1-integrating.md
================================================
| [docs](..) / [getting-started](.) / 1-integrating.md |
|:---|
# Step 1. Integrating
The first step is to configure MyApp to work with Squirrel.Windows. This requires you to install the Squirrel.Windows NuGet Package into the `MyApp.sln`.
## Installing Squirrel.Windows
The easiest way to install the Squirrel.Windows is using the [Package Manager Console](https://docs.NuGet.org/consume/package-manager-console) in Visual Studio after loading the MyApp solution.
~~~powershell
PM> Install-Package Squirrel.Windows
~~~
### Squirrel.Windows References
The package will install a number of dependent packages as well as tools that will be used to prepare MyApp to be released. The References in the Solution Explorer of the MyApp project now looks like the following (as of Squirrel.Windows version 1.2.2):

**Tip:** Alternatively, you can use the "Manage NuGet Packages" GUI to install Squirrel.Windows (right clicking on your project in the Solution Explorer of Visual Studio and select "Manage NuGet Packages...").
## Basic Updating
For the basic example we are going to have MyApp update from your local file system rather than distributing the files via the web. See section [Packaging](2-packaging.md) for additional options related to the distributing the update files.
### Basic Squirrel.Windows Update Code
The following code is added to MyApp `Program.cs` to cause the application to check for, download, and install any new releases of MyApp in the background while you use the application.
**`Program.cs`**
~~~cs
using Squirrel;
using System.Threading.Tasks;
~~~
**`static async Task Main()`**
~~~cs
using (var mgr = new UpdateManager("C:\\Projects\\MyApp\\Releases"))
{
await mgr.UpdateApp();
}
~~~
The code above demonstrates the most basic update mechanism using the `UpdateApp()` method in an asynchronous task. The actions it takes will be discussed further in section [Updating](5-updating.md).
**Caution:** The path you provide the `UpdateManager` is the path to the directory where the `RELEASES` file is located (which is also named `Releases` by default), and not the actual `RELEASES` file.
**Tip:** By default, the files for updating MyApp will be placed in the same directory as your `MyApp.sln` file under a `Releases` directory (e.g., `C:\Projects\MyApp\Releases`).
**Tip:** In this example we simply put the code in the `Program.cs` file. For a production application, place the update code later in start-up process so as to avoid slowing down your program start.
**Tip:** If you attempt to debug the application via Visual Studio, you will get an exception of `Update.exe not found, not a Squirrel-installed app?`. You can resolve this by placing a copy of the Update.exe in your bin directory (see [Debugging Updates: Update.exe not found?](../using/debugging-updates.md) section for details).
---
| Previous: [Getting Started Guide](0-overview.md) | Next: [2. Packaging](2-packaging.md)|
|:---|:---|
================================================
FILE: docs/getting-started/2-packaging.md
================================================
| [docs](..) / [getting-started](.) / 2-packaging.md |
|:---|
# Step 2. Packaging
Packaging is the process of building, packing, and preparing MyApp release packages for distribution.
## Building
The first step in preparing the application for distribution is to build the application.
1. **Set MyApp Version** - set the initial application version.
**`Properties\AssemblyInfo.cs`**
~~~cs
[assembly: AssemblyVersion("1.0.0")]
[assembly: AssemblyFileVersion("1.0.0")]
~~~
2. **Switch to Release** - switch your build configuration to `Release`.
3. **Build MyApp** - build your application to ensure the latest changes are included in the package we will be creating.
## Packing
Squirrel uses [NuGet](https://www.NuGet.org/) for bundling application files and various application properties (e.g., application name, version, description) in a single release package.
Section [NuGet Package Metadata](../using/nuget-package-metadata.md) provides additional details on using NuGet and `.nuspec` files to automate the packing of your application. We will be going through the process using the [NuGet Package Explorer](https://github.com/NuGetPackageExplorer/NuGetPackageExplorer) to manually create a NuGet package.
1. **Creating a New NuGet Package** - the first step is to create a new NuGet package.
2. **Edit Metadata** - update package metadata for MyApp.
* **Id** - name of the application (no spaces)
* **Version** - version specified in `Properties\Assembly.cs`
* **Dependencies** - Squirrel expects no dependencies in the package (all files should be explicitly added to the package)
3. **Add lib & net45** - add the `lib` folder and the `net45` folder to the project. Squirrel is expecting a single `lib / net45` directory provided regardless of whether your app is a `net45` application.
4. **Add Release Files** - add all the files from `bin\Release` needed by MyApp to execute (including the various files required by Squirrel).
* **Include MyApp Files:** MyApp.exe, MyApp.exe.config, any non-standard .NET dll's needed by MyApp.exe.
* **Include Squirrel Files:** Squirrel.dll, Splat.dll, NuGet.Squirrel.dll, Mono.Cecil.\*, DeltaCompressionDotNet.\*,
* **Exclude:** *.vshost.\*, *.pdb files
5. **Save the NuGet Package File** - save the NuGet package file to where you can easily access later (e.g., `MyApp.sln` directory). Follow the given naming format (e.g., `MyApp.1.0.0.nupkg`).

## Releasifying
Releasifying is the process of preparing the `MyApp.1.0.0.nupkg` for distribution.
### Using Releasify
You use the `Squirrel.exe` tool that was included in the Squirrel.Windows package you installed in the `MyApp.sln` previously.
Use the [Package Manager Console](https://docs.NuGet.org/consume/package-manager-console) to execute `Squirrel.exe --releasify` command.
~~~powershell
PM> Squirrel --releasify MyApp.1.0.0.nupkg
~~~
**Tip:** If you get an error stating that `...'Squirrel' is not recognized...` then you may simply need to restart Visual Studio so the `Package Manager Console` will have loaded all the package tools.
### Releasify Output
The `Squirrel --releasify` command completes the following:
* **Create `Releases` Directory** - creates a Releases directory (in the `MyApp.sln` directory by default).
* **Create `Setup.exe`** - creates a `Setup.exe` file which includes the latest version of the application to be installed.
* **Create `RELEASES` File** - creates a file that provides a list of all release files for MyApp to be used during the update process
* **Create `MyApp.1.0.0-full.nupkg`** - copies the package you created to the `Releases` directory.
* **Create `MyApp.*.*.*-delta.nupkg`** - if you are releasing an update, releasify creates a delta file package to reduce the update package size (see [Updating](5-updating.md) for details).
**`C:\Projects\MyApp\Releases`**

## See Also
* [Visual Studio Build Packaging](../using/visual-studio-packaging.md) - integrating NuGet packaging into your visual studio build process to include packing and releasifying.
---
| Previous: [1. Integrating](1-integrating.md) | Next: [3. Distributing](3-distributing.md)|
|:---|:---|
================================================
FILE: docs/getting-started/3-distributing.md
================================================
| [docs](..) / [getting-started](.) / 3-distributing.md |
|:---|
# Step 3. Distributing
After packaging MyApp for distribution, the various files in the `Releases` directory are used to distribute MyApp to users.
* **Setup Application** - the `Setup.exe` application is provided to new users to install the current version of MyApp (see [Installing](4-installing.md) for details).
* **Update Files** - the `RELEASES` file, along with versioned full and delta packages, are used by the update process (see [Updating](5-updating.md) for details).
## Local File Distribution
For simplicity, this Getting Started guide uses a local file system location for updates. The location is defined in the update location provided to the `UpdateManager` (see code in [Integrating: Basic Updating](1-integrating.md)).
This generally is not practical for updates, unless all your users have access to similar network path where the files could be easily placed.
---
| Previous: [2. Packaging](2-packaging.md) | Next: [4. Installing](4-installing.md)|
|:---|:---|
================================================
FILE: docs/getting-started/4-installing.md
================================================
| [docs](..) / [getting-started](.) / 4-installing.md |
|:---|
# Step 4. Installing
The process to install MyApp is as simple as executing the `Setup.exe` application. `Setup.exe` is generated by the `Squirrel --releasify` process and is located in the `Releases` directory.
## Setup.exe
`Setup.exe` is a C++ bootstrapper application used to install MyApp on the user's local system. It includes the latest full version of the MyApp package files embedded in the exe file (see [Install Process](../using/install-process.md) for details).
## Install Process Overview
The `Setup.exe` application does the following (see [Install Process](../using/install-process.md) for details):
* Creates a `%LocalAppData%\MyApp` directory for the MyApp to be installed.
* Extracts and prepares the MyApp files under an `app-1.0.0` directory.
* Launches `app-1.0.0\MyApp.exe` at the end of the setup process.
### Installed File Structure
An installation for MyApp will look like the following after the initial installation.
#### `%LocalAppData%\MyApp` Directory

---
| Previous: [3. Distributing](3-distributing.md) | Next: [5. Updating](5-updating.md)|
|:---|:---|
================================================
FILE: docs/getting-started/5-updating.md
================================================
| [docs](..) / [getting-started](.) / 5-updating.md |
|:---|
# Step 5. Updating
The update process uses the update files generated by the `Squirrel --releasify` process. This includes the `RELEASES` file as well as versioned full and delta packages as required. The location of where to look for the distributed update files is provided to the `UpdateManager` in the MyApp code (see code in [Integrating: Basic Updating](1-integrating.md)).
Updating MyApp to a new version is the culmination of integrating, packaging, and distributing after installing MyApp. The process will cause you to revisit the packaging and distributing steps.
HH
To release a new update, you must first build, pack, and releasify your updated application.
### Building
1. **Update MyApp Version** - update the application version.
**`Properties\AssemblyInfo.cs`**
~~~cs
[assembly: AssemblyVersion("1.0.1")]
[assembly: AssemblyFileVersion("1.0.1")]
~~~
2. **Switch to Release** - switch your build configuration to `Release`.
3. **Build MyApp** - build your application to ensure the latest changes are included in the package we will be creating.
### Packing
Using [NuGet Package Explorer](https://npe.codeplex.com/) complete the following:
1. **Open Previous NuGet Package** - open the previous NuGet package you created for MyApp version 1.0.0.
2. **Update Version** - update the version in the metadata.
4. **Replace Release Files** - replace the changed files under `lib\net45`. You can simply drag and drop any program specific files that have changed (i.e., the `MyApp.exe` file is the only one that has updated in the example).
5. **Save the NuGet Package File as New Version** - use the "Save As..." feature to save the new version of the package `MyApp.1.0.1.nupkg`.
### Releasifying
Use the [Package Manager Console](https://docs.NuGet.org/consume/package-manager-console) to execute `Squirrel.exe --releasify` command using the new `MyApp.1.0.1.nupkg` package.
~~~powershell
PM> Squirrel --releasify MyApp.1.0.1.nupkg
~~~
**Tip:** If you get an error stating that `...'Squirrel' is not recognized...` then you may simply need to restart Visual Studio so the `Package Manager Console` will have loaded all the package tools. This behavior has been seen on the Community Edition of VS 2013 and 2015.
#### Releasify Output
After packaging the new MyApp version 1.0.1, the `Releases` directory has been updated as follows:
* **Updated Setup Application** - the `Setup.exe` application has been updated to include the latest MyApp version 1.0.1 package.
* **Updated Files** - the `RELEASES` file has been appended to include the newly created full and delta packages.
## Distributing the New Release
The `Releases` directory now includes the updated files to distribute to your users.
**`Releases` Directory**

The `RELEASES` file contains SHA1 hash, filename, and file size for each package. This information is utilized by the application update process.
**`RELEASES` File**
~~~
E3F67244E4166A65310C816221A12685C83F8E6F MyApp-1.0.0-full.nupkg 600725
0D777EA94C612E8BF1EA7379164CAEFBA6E24463 MyApp-1.0.1-delta.nupkg 6030
85F4D657F8424DD437D1B33CC4511EA7AD86B1A7 MyApp-1.0.1-full.nupkg 600752
~~~
## Application Updating
In [Step 1. Integrating](1-integrating.md), we configured MyApp to look for and install any updates in the background each time MyApp is executed. In the MyApp example, a path to the `Releases` directory on the file system was specified.
### Updating Process Overview
The following steps are performed by the `UpdateManager` each time MyApp is executed (see [Update Process](../using/update-process.md) for details):
* The `UpdateManager` checks the `RELEASES` file at the distribution location for any updates.
* Any update packages are downloaded and the new MyApp is prepared for execution.
* App shortcuts are updated and old versions of MyApp are cleaned up.
### MyApp Example
The first time I run MyApp after providing the update the application is executed like normal.

In the background, MyApp has obtained and applied the updates in the installation directory.

The next time MyApp is executed, it will be the newly installed version.

---
| Previous: [4. Installing](4-installing.md) | Return: [Table of Contents](../readme.md)|
|:---|:---|
================================================
FILE: docs/goals.md
================================================
| [docs](.) / goals.md |
|:---|
# What Do We Want?
Deployment and Updates for Desktop applications are a real drag. ClickOnce almost works, but has some glaring bugs that don't seem like they'll ever be fixed. So let's own our own future and build a new one.
Windows apps should be as fast and as easy to install and update as apps like Google Chrome. From an app developer's side, it should be really straightforward to create an installer for my app, and publish updates to it, without having to jump through insane hoops
## Configuring
* Integrating the installer for an existing .NET application should be really easy.
* The client API should be able to check for updates and receive a (preferably in HTML) ChangeLog.
* Developer should have control over custom actions and events during installing and updating.
* Uninstall gives a chance for the application to clean up (i.e. I get to run a chunk of code on uninstall)
## Packaging
* Generating an installer given an existing .NET application should be really easy, like it is for ClickOnce.
* Creating an update for my app should be a very simple process that is easily automated.
* Packaging will support delta files to reduce the size of update packages.
## Distributing
* Hosting an update server should be really straightforward, and should be able to be done using simple HTTP (i.e. I should be able to host my installer and update feed via S3).
* Support for multiple "channels" (a-la Chrome Dev/Beta/Release).
## Installing
* Install is Wizard-Free™ and doesn't look awful (or at least, it should have the *possibility* to not look awful).
* No UAC dialogs, which means....
* ...installs to the local user account (i.e. under `%LocalAppData%`).
* No Reboots. None!
* Can pull down the .NET Framework if need be.
## Updating
* Updates should be able to be applied while the application is running.
* At no time should the user ever be forced to stop what he or she is doing.
* No Reboots. None!
---
| Return: [Table of Contents](readme.md) |
|:---|
================================================
FILE: docs/readme.md
================================================
| [docs](.) / readme.md |
|:---|

# Table of Contents
This document provides a table of contents for all the Squirrel documentation.
## General Documentation
* **[Squirrel Goals](goals.md)** - overview of the goals of the Squirrel.Windows project.
* **[Frequently Asked Questions (FAQ)](faq.md)** - list of frequently asked questions.
* **[Squirrel.Windows License](../COPYING)** - copyright and license for using Squirrel.Windows
## Getting Started Guide
The **[Getting Started Guide](getting-started/0-overview.md)** provides a step-by-step guide for integrating Squirrel into a simple Windows Forms application named MyApp.
1. **[Integrating](getting-started/1-integrating.md)** - integrating Squirrel `UpdateManager` into MyApp.
1. **[Packaging](getting-started/2-packaging.md)** - packaging MyApp files and preparing them for release.
1. **[Distributing](getting-started/3-distributing.md)** - providing install and update files for MyApp.
1. **[Installing](getting-started/4-installing.md)** - process of initial installation of MyApp.
1. **[Updating](getting-started/5-updating.md)** - process of updating an existing install of MyApp.
## Using Squirrel
* **Installing** - documentation related to the initial installation of your application via Setup.exe (and Setup.msi).
* [Install Process](using/install-process.md) - overview of the steps in the install process.
* [Custom Squirrel Events](using/custom-squirrel-events.md) - preforming custom actions for Squirrel events.
* [Custom Squirrel Events (non-c# apps)](using/custom-squirrel-events-non-cs.md) - steps on making a non-c# application Squirrel Aware and handling custom events.
* [Loading GIF](using/loading-gif.md) - specify a "loading" image during initial install of large applications.
* [GitHub](using/github.md) - overview of using GitHub for installing, distributing, and updating.
* [Machine-wide Installs](using/machine-wide-installs.md) - generating an MSI file suitable for installation via Group Policy.
* [Debugging Installs](using/debugging-installs.md) - tips for debugging Squirrel.Windows initial installs.
* **Packaging** - documentation related to packaging app files and preparing them for release.
* [Naming Conventions](using/naming.md) - overview of sources used in naming (e.g., shortcut name).
* [NuGet Package Metadata](using/nuget-package-metadata.md) - overview of the NuGet metadata and its uses by Squirrel.
* [Packaging Tools](using/packaging-tools.md) - tools available to assist in the process of packaging your application (e.g., NuGet, OctoPack, Auto.Squirrel)
* [Squirrel Command Line](using/squirrel-command-line.md) - command line options for `Squirrel --releasify`
* [Delta Packages](using/delta-packages.md) - an overview of how `Squirrel.exe` creates delta packages.
* [Application Signing](using/application-signing.md) - adding code signing to `Setup.exe` and your application.
* **Distributing** - documentation related to distributing the Setup.exe and update package files.
* [Microsoft IIS](using/microsoft-iis.md) - overview of using Microsoft IIS for distributing your application.
* [Amazon S3](using/amazon-s3.md) - overview of using Amazon S3 for distributing your application.
* [GitHub](using/github.md) - overview of using GitHub for installing, distributing, and updating.
* **Updating** - documentation related to updating an existing install via the `UpdateManager`.
* [Update Process](using/update-process.md) - overview of the steps in the update process.
* [Update Manager](using/update-manager.md) - reference guide for the `UpdateManager`.
* [GitHub](using/github.md) - overview of using GitHub for installing, distributing, and updating.
* [Debugging Updates](using/debugging-updates.md) - tips for debugging Squirrel.Windows updates.
* [Staged Rollouts](using/staged-rollouts.md) - how to use staged rollouts to ramp up install distribution over time
## Contributing
Why not give back and help make Squirrel even better by contributing to the project.
* [Contributing](contributing/contributing.md) - overview of ways you can become more involved with Squirrel.Windows.
* [Building Squirrel](contributing/building-squirrel.md) - steps to build squirrel for the impatient.
* [VS Solution Overview](contributing/vs-solution-overview.md) - overview of the various projects in the Squirrel.Windows Visual Studio solution.
* [Branching Strategy](contributing/branching-strategy.md) - overview of the different branches used in squirrel development.
================================================
FILE: docs/using/amazon-s3.md
================================================
| [docs](..) / [using](.) / amazon-s3.md
|:---|
# Amazon S3
Amazon S3 can be used as an easy mechanism to host your releases
## Amazon S3 Setup
The following steps setup an S3 account and prepares MyApp for distribution.
1. **Register for Amazon AWS** - if you haven't already, register for an Amazon AWS account and go to the AWS Console.
2. **Create Bucket** - create a new bucket to hold your application updates
3. **Update the Package Location** - update the package location on the `UpdateManager` in MyApp to use the S3 `Link` address for the files minus the actual file name. This is the address for downloading the file and is similar to the following address:
`https://s3-us-west-2.amazonaws.com/myapp.bucket`
4. **Build, Pack, Releasify** - perform the necessary steps to build, package, and releasify MyApp for distribution.
3. **Upload Files** - upload the files from the Squirrel `Releases` directory into the S3 bucket.
4. **Make Public** - make the files public by selecting the files and performing the "Make Public" action.
## Amazon S3 Updates
After you have setup your S3 account, the following steps will distribute a new package for release.
4. **Build, Pack, Releasify** - perform the necessary steps to build, package, and releasify MyApp for distribution.
3. **Upload Files** - upload the new files from the Squirrel `Releases` directory. Make sure to include the new `Setup.exe` and `RELEASES` file along with any full and delta files for the new version.
4. **Make Public** - make the new files public by selecting the files and performing the "Make Public" action.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/application-signing.md
================================================
| [docs](..) / [using](.) / application-signing.md
|:---|
# Application Signing
Signing your installer with a valid code signing certificate is one of the most important things that you need to do for production apps. Both IE SmartScreen as well as virus scanning software will give a significant amount of "points" to apps that are signed correctly, preventing your users from getting scary dialogs.
Acquire a code-signing certificate - it's recommended to get a Windows Error Reporting-compatible certificate, see this [MSDN article](https://msdn.microsoft.com/library/windows/hardware/hh801887.aspx) for more information, then pass the -n parameter, which are the parameters you would pass to `signtool.exe sign` to sign the app.
Squirrel makes signing easy, as it signs all of your application's executables *as well* as the final generated Setup.exe.
An example invocation including both of these features would be something like:
~~~powershell
PM> Squirrel --releasify MyApp.1.0.0.nupkg -n "/a /f CodeCert.pfx /p MySecretCertPassword /fd sha256 /tr http://timestamp.digicert.com /td sha256"
~~~
If you are using the [Visual Studio Build Packaging](visual-studio-packaging.md) process be careful how you escape your quotation marks in the `XML` of your `.csproj` file for the -n, --signWithParams argument. The wrapping quotation marks must be defined in `XML` safe ampersand escape strings or `"`. Within this command you will likely need quotation marks around your certificate password. Since this is already within a quoted string you will need to double quote the password: `/p ""PASSWORD""`.
~~~xml
~~~
## See Also
* [Squirrel Command Line](squirrel-command-line.md) - command line options for `Squirrel --releasify`
* [Visual Studio Build Packaging](visual-studio-packaging.md) - integrating Squirrel packaging into your build process
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/custom-squirrel-events-non-cs.md
================================================
| [docs](..) / [using](.) / custom-squirrel-events-non-cs.md
|:---|
# Custom Squirrel Events (Non-C# Apps)
Squirrel events allow you to handle custom events around the installation and updating process.
### Making Your App Squirrel Aware
Add an entry to the *English* Version Block info called "SquirrelAwareVersion" with a value of "1". Typically this is done via the "App.rc" resource file. Here's a typical entry:
```
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "Installer for Squirrel-based applications"
VALUE "FileVersion", "0.5.0.0"
VALUE "InternalName", "Setup.exe"
VALUE "LegalCopyright", "Copyright (C) 2014"
VALUE "OriginalFilename", "Setup.exe"
VALUE "ProductName", "Squirrel-based application"
VALUE "ProductVersion", "0.5.0.0"
VALUE "SquirrelAwareVersion", "1"
END
END
```
### Application Startup Commands
This means that this EXE will be executed by the installer in a number of different scenarios, with special flags - you should handle them correctly:
* `--squirrel-install x.y.z.m` - called when your app is installed. Exit as soon as you're finished setting up the app
* `--squirrel-firstrun` - called after everything is set up. You should treat this like a normal app run (maybe show the "Welcome" screen)
* `--squirrel-updated x.y.z.m` - called when your app is updated to the given version. Exit as soon as you're finished.
* `--squirrel-obsolete x.y.z.m` - called when your out-of-date app is no longer the newest version. Exit as soon as you're finished.
* `--squirrel-uninstall x.y.z.m` - called when your app is uninstalled. Exit as soon as you're finished.
## See Also
* [Custom Squirrel Events for c# Apps](custom-squirrel-events.md) - steps on making a c# application Squirrel Aware and handling custom events.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/custom-squirrel-events.md
================================================
| [docs](..) / [using](.) / custom-squirrel-events.md
|:---|
# Custom Squirrel Events
## Handling Squirrel Events
Squirrel events allow you to handle custom events around the installation and updating process, which is important because Squirrel doesn't do much of anything at installation time automatically. However, since the code is executing inside your application, it's way easier to do stuff than other systems where you're writing custom "installer DLLs".
### Overriding Default Behaviors
When none of the apps in your package are "Squirrel-Aware", Squirrel does some things on your behalf to make your life easier, the primary one being that every EXE in your app package automatically gets a shortcut on both the Desktop and the Start Menu. Once you enable Squirrel events *for even a single EXE file*, you must do this yourself.
### Making Your App Squirrel Aware
In your app's `AssemblyInfo.cs`, add the following line:
```
[assembly: AssemblyMetadata("SquirrelAwareVersion", "1")]
```
### Using the `SquirrelAwareApp` Helper
If you are writing a C# app, it is **highly encouraged** to use the `SquirrelAwareApp` helper class to implement this. Here's an implementation that is similar to the default (i.e. non-squirrel-aware) behavior:
```cs
static bool ShowTheWelcomeWizard;
...
static int Main(string[] args)
{
// NB: Note here that HandleEvents is being called as early in startup
// as possible in the app. This is very important! Do _not_ call this
// method as part of your app's "check for updates" code.
using (var mgr = new UpdateManager(updateUrl))
{
// Note, in most of these scenarios, the app exits after this method
// completes!
SquirrelAwareApp.HandleEvents(
onInitialInstall: v => mgr.CreateShortcutForThisExe(),
onAppUpdate: v => mgr.CreateShortcutForThisExe(),
onAppUninstall: v => mgr.RemoveShortcutForThisExe(),
onFirstRun: () => ShowTheWelcomeWizard = true);
}
}
```
## App Setup Helper Methods
These methods help you to set up your application in Squirrel events - if you're not using custom Squirrel events, you probably don't need to call these methods.
* `[Create/Remove]ShortcutsForExecutable` - creates and removes shortcuts on the desktop or in the Start Menu.
* `[Create/Remove]UninstallerRegistryEntry` - creates and removes the uninstaller entry. Normally called by `Update.exe`.
## See Also
* [Custom Squirrel Events for non-c# Apps](custom-squirrel-events-non-cs.md) - steps on making a non-c# application Squirrel Aware and handling custom events.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/debugging-installs.md
================================================
| [docs](..) / [using](.) / debugging-installs.md
|:---|
# Debugging Installs
The following tips will help you to debug the installation of an Squirrel app.
## Simulating an Install and First Run
If the install of your application doesn't seem to be working, you can explore the behavior by executing the install steps from the command line:
~~~ps
C:\user\AppData\Local\MyApp> Update.exe --squirrel-install 1.0.0
C:\user\AppData\Local\MyApp> Update.exe --squirrel-firstrun
~~~
The first cmd should create some shortcuts then immediately exit, then the 2nd one should start your app ([source](https://github.com/Squirrel/Squirrel.Windows/issues/525))
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/debugging-updates.md
================================================
| [docs](..) / [using](.) / debugging-updates.md
|:---|
# Debugging Updates
The following tips will help you to debug the update process in your application.
## Update.exe not found?
Executing MyApp from Visual Studio will execute the update process and you will get the following exception from the `UpdateManager`:
~~~
Update.exe not found, not a Squirrel-installed app?
~~~
The `UpdateManager` is expecting to find the `Update.exe` application installed one directory up from the EXE (e.g., the `\bin` directory for default Visual Studio projects).
To resolve this, you can simply place a file named `Update.exe` or you can copy the `Squirrel.exe` from the `MyApp\packages\squirrel.windows.1.2.2.tools` directory and rename it Update.exe (this is the actual Update.exe packaged inside `Setup.exe`).
Executing MyApp from Visual Studio will now cause it to complete the update process and your `\bin` directory will resemble the `%LocalAppData\MyApp%` install directory:

**Tip:** If you want to ensure that the Update.exe is always available in your output directory, you can add the Update.exe file to the Visual Studio project and set its Properties > Copy To Output Directory to 'Copy if newer'.
## Catching Update Exceptions
You can catch thrown exceptions and log the results.
~~~cs
using (var mgr = new UpdateManager("C:\\Projects\\MyApp\\Releases"))
{
await mgr.UpdateApp();
}
~~~
Alternatively, set up Splat Logging, see [here](https://github.com/Squirrel/Squirrel.Windows.Next/blob/6d7ae23602a3d9a7636265403d42c1090260e6dc/src/Update/Program.cs#L53) for an example.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/delta-packages.md
================================================
| [docs](..) / [using](.) / delta-packages.md
|:---|
# Delta Packages
Now, once we've got a full package, we need to generate a Delta package. To do this, we'll replace all the DLL/EXEs in the NuGet packages with bsdiff files. [bspatch/bsdiff](http://code.logos.com/blog/2010/12/binary_patching_with_bsdiff.html) is a mostly efficient algorithm for calculating diffs between binary files (especially Native binaries, but it works well for .NET ones too), and a way to apply them.
So, this is pretty easy:
1. Extract the previous NuGet package
1. Extract the current NuGet package
1. Replace every EXE/DLL with the bsdiff. So, `lib\net40\MyCoolApp.exe` becomes `lib\net40\MyCoolApp.exe.diff`. Create a file that contains a SHA1 of the expected resulting file and its filesize called `lib\net40\MyCoolApp.exe.shasum`
1. New DLLs in current get put in verbatim
1. Zip it back up
The .shasum file has the same format as the Releases file described in the "'Latest' Pointer" section, except that it will only have one entry.
So now we've got all of the *metadata* of the original package, just none of its *contents*. To get the final package, we do the following:
1. Take the previous version, expand it out
1. Take the delta version, do the same
1. For each DLL in the previous package, we bspatch it, then check the shasum file to ensure we created the correct resulting file
1. If we find a DLL in the new package, just copy it over
1. If we can't find a bspatch for a file, nuke it (it doesn't exist in the new rev)
1. Zip it back up
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/github.md
================================================
| [docs](..) / [using](.) / github.md
|:---|
# Using GitHub
GitHub release assets can be used to distribute the necessary Squirrel files for the Squirrel install and update process. It still requires you to upload all the release files as assets for each release, but provides you a means of hosting your update files via your GitHub repository.
**Important:** GitHub since February 22, 2018 [only support TLS 1.2 connections](https://githubengineering.com/crypto-removal-notice/). The host application is therefore required to use .NET framework 4.6.1, otherwise TLS 1.1 is the default protocol and check for update won't work.
## Installing from GitHub
GitHub allows you to provide a [static link](https://help.github.com/articles/linking-to-releases/) to a repositories latest release page. You can direct your users to download the `Setup.exe` from the list of assets you uploaded for the release.
~~~
https://github.com/myuser/MyApp/releases/latest
~~~
**Tip:** This link simply redirects to the repositories latest release page, and cannot be used to download an asset directly (i.e., you can't simply make a static link to ".../releases/latest/Setup.exe"). However, you can use the [GitHub API with ajax](http://stackoverflow.com/a/26454035) to provide a direct link on your website and avoid the user having to select the correct file or navigate to the GitHub website.
## Distributing from GitHub
The following steps are required to distribute your RELEASES and update NuGet packages with GitHub:
1. **Commit Latest Code** - In order for GitHub to mark a new release as the `Latest`, you have at least one additional commit since the last release tag was added (i.e., releases tags must not share the same commit).
1. **Create a New Release** - [Create a new GitHub release](https://help.github.com/articles/creating-releases/) in your MyApp repository matching your current release version (e.g., 1.0.0).
2. **Upload Release Files** - upload all of the files from `Releases` as assets of the GitHub release (e.g., RELEASES, MyApp.1.0.0-full.nupkg, MyApp.1.0.1-delta.nupkg, MyApp.1.0.1-full.nupkg).
3. **Set Pre-release (optional)** - if desired, set the release as a pre-release.
4. **Publish the Release** - click the "Publish Release" to make the release available to the general public and your users.
**Important:** You must upload all packages as assets you wish to be available for update (i.e., the GitHubUpdateManager doesn't look back to previous GitHub releases for previous version packages). If you only include the latest packages, Squirrel will be forced to download the latest full package for each update.
## Updating with GitHub
The Updating process requires you to build, package, releasify, and distribute the update files.
**Important:** You must ensure there is at least one additional commit since the last version release before adding a new release. GitHub will not update the latest release if the new release tag is tied to the same last commit as a previous release tag.
### GitHub Update Manager
To use GitHub release assets as your distribution mechanism you need to replace `UpdateManager` with `GitHubUpdateManager` when integrating Squirrel in your app:
**`Program.cs`**
~~~cs
using Squirrel;
using System.Threading.Tasks;
~~~
**`static async Task Main()`**
~~~cs
using (var mgr = UpdateManager.GitHubUpdateManager("https://github.com/myuser/myapp"))
{
await mgr.Result.UpdateApp();
}
~~~
**Important:** Make sure your url doesn't end in a forward slash ("/"). Adding the trailing forward slash will cause it to fail with a 404 error ([see #641](https://github.com/Squirrel/Squirrel.Windows/issues/641#issuecomment-201478324)).
**Tip:** You can also specify that the update manager should use `prerelease` for updating (see method signature for details).
**Source:** See [Issue #442](https://github.com/Squirrel/Squirrel.Windows/issues/442) for more information.
### How it Works
The GitHub API is used by the `GitHubUpdateManager` to obtain the correct release and asset files for downloading. The following actions are performed:
1. Extracts the username and repository from the url (e.g., "myuser" and "myapp").
2. Uses the GitHub API to get the latest release information. For example, the following url obtains a json list of all release information for the Squirrel.Windows repository: [https://api.github.com/repos/Squirrel/Squirrel.Windows/releases](https://api.github.com/repos/Squirrel/Squirrel.Windows/releases)
3. Obtains the correct download path from the `html_url` attribute of the latest release (or pre-release if specified) to be used as the path for downloading assets.
4. Follows the normal Squirrel update process by looking for a `RELEASES` file and downloading the necessary delta or full application packages.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/install-process.md
================================================
| [docs](..) / [using](.) / install-process.md
|:---|
# Install Process
This section goes into detail about the install process.
## Setup.exe
`Setup.exe` is a C++ bootstrapper application used to install your app on the user's local system. It is generated as part of the `Squirrel --releasify` process.
The `Setup.exe` file includes the `Update.exe` application and the latest version of the MyApp package to be installed. A single executable file can be provided due to the `WriteZipToSetup.exe` tool injecting the appropriate files into the exe.
In addition, the `Setup.exe` will also ensure that .NET 4.5 is installed on the user's computer.
## Install Location
The `Setup.exe`, and later the `UpdateManager` in MyApp must have the ability to write files to and execute files from the application install location. To ensure permission for all types of users, the user's application data directory is selected as the install location (i.e., `%LocalAppData%\MyApp`).
The installation root really only needs to consist of two types of folders:
* **Packages** - folder used to download and assemble the update package files.
* **App Folders** - the "installed" application files for a given version of MyApp.
```
\%LocalAppData%\MyApp
\packages
MyApp-1.0.0.nupkg
MyApp-1.0.1-delta.nupkg
MyApp-1.0.1.nupkg
\app-1.0.0
MyApp.exe
\app-1.0.1
MyApp.exe
```
The packages directory is effectively immutable, it simply consists of the packages we've downloaded. Using the user's local application data directory means that we the needed write-access to the install directory on a per-user basis.
**Tip:** See [Machine-wide Installs](machine-wide-installs.md) for more information on ensuring your application pushed to all users in an enterprise environment.
## Install Process Overview
The `Setup.exe` application preforms the following:
1. **Ensures .NET Framework Installed** - determines if .NET Framework is available, and if not relaunches itself with `/installfx45` to download and launch the .NET Framework installer.
1. **Create `%LocalAppData%\MyApp` Directory** - creates a directory for the MyApp to be installed.
2. **Extracts `Update.exe`** - extracts the `Update.exe` application to the application directory (`%LocalAppData%\MyApp`).
3. **Extracts `MyApp.1.0.0-full.nupkg`** - extracts the MyApp full application package to the `%LocalAppData%\MyApp\packages\temp` directory.
4. **Executes `Update.exe` to Finish Install** - executes the `Update.exe` application with the `/install` switch to finish the application installation and then launch the application.
1. **Copy MyApp to `app-1.0.0` Directory** - copy the full version of MyApp files to a application sub-directory (e.g., `MyApp\app-1.0.0`).
2. **Launch MyApp** - at the end of the setup process, the Updater launches the newly installed version of MyApp.
6. **MyApp Creates Shortcuts** - the first execution of the application will cause shortcuts to be created on the desktop and Windows start menu for MyApp.
## Desktop & Windows Start Shortcuts
By default, application shortcuts are created on the desktop and the Windows Start menu that point to the `Update.exe` application with additional arguments pointing to the correct application to execute.
**`MyApp.lnk` (Application Shortcut)**
* **Target:** `C:\Users\kbailey\AppData\Local\MyApp\Update.exe --processStart MyApp.exe`
* **Start in:** `C:\Users\kbailey\AppData\Local\MyApp\app-1.0.0`
## See Also
* [Loading GIF](loading-gif.md) - specify a "loading" image during initial install of large applications.
* [Machine-wide Installs](machine-wide-installs.md) - generating an MSI file suitable for installation via Group Policy.
* [NuGet Package Metadata](nuget-package-metadata.md) - overview of the NuGet metadata and its uses by Squirrel.
* [Naming Conventions](naming.md) - A more complete view of how Squirrel names everything.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/loading-gif.md
================================================
| [docs](..) / [using](.) / loading-gif.md
|:---|
# Loading GIF
Squirrel installers don't have any UI - the goal of a Squirrel installer is to install so blindingly fast that double-clicking on Setup.exe *feels* like double-clicking on an app shortcut. Make your installer **fast**.
However, for large applications, this isn't possible. For these apps, Squirrel will optionally display a graphic as a "splash screen" while installation is processing, but only if installation takes more than a pre-set amount of time. This will be centered, backed by a transparent window, and can optionally be an animated GIF. Specify this via the `-g` parameter.
~~~powershell
PM> Squirrel --releasify MyApp.1.0.0.nupkg -g .\loading.gif
~~~
## See Also
* [Squirrel Command Line](squirrel-command-line.md) - command line options for `Squirrel --releasify`
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/machine-wide-installs.md
================================================
| [docs](..) / [using](.) / machine-wide-installs.md
|:---|
# Machine-wide Installs
Squirrel's Releasify command generates an MSI file suitable for installation via Group Policy. This MSI isn't a general-purpose installer, this means that once you run the MSI, users from now on will get the app installed, on next Login.
So, most normal users should continue to run the Setup.exe's generated by Releasify, but if you want to have an IT Admin Friendly version, you can hand off the MSI
## Common pitfalls
### Missing data in `.nuspec`
Most users of Squirrel won't have to do anything new to enable this behavior, though certain NuGet package IDs / names might cause problems with MSI.
**Source:** See [issue #466](https://github.com/Squirrel/Squirrel.Windows/issues/466) for more details.
### Nothing happens on login
In cases where the end user has previously installed your application, the installer that runs on login will not re-install your application on every login. This can easily be the case if you as a developer is testing out both the EXE and the MSI.
Squirrel leaves behind an almost-empty `%LocalAppData%\MyApp` folder after an uninstall. Deleting this folder (the entire folder, not just the contents) will allow the installer that runs on login to install successfully.
**Source:**: See [issue #555](https://github.com/Squirrel/Squirrel.Windows/issues/555#issuecomment-253265130) for details.
## Disabling MSI Generation
Generating MSIs can be disabled via the --no-msi flag as shown below:
~~~powershell
PM> Squirrel --releasify MyApp.1.0.0.nupkg --no-msi
~~~
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/microsoft-iis.md
================================================
| [docs](..) / [using](.) / microsoft-iis.md
|:---|
# Microsoft IIS
If you use Microsoft IIS to distribute the necessary Squirrel files, you must provide a custom `Web.config` file as described below.
## Hosting on IIS
All versions of IIS (including Microsoft Azure PaaS) deny serving files when
the extension MIME type is unknown. If you are hosting your updates in this
manner then you will need to add a `Web.config` to your downloads repository as
follows:
**`~/downloads/Web.config` File**
~~~xml
~~~
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/naming.md
================================================
| [docs](..) / [using](.) / naming.md
|:---|
# Naming Conventions
In addition to the [NuGet Package Metadata](nuget-package-metadata.md), there are other places that squirrel pulls naming information from. Here is the logic:
## Shortcut name
The shortcut name is selected from the first non-null item below:
1. `[assembly: AssemblyProduct("MyApp")` (from `AssemblyInfo.cs`)
2. Squirrel NuGet Package Metadata `title` property.
3. `[assembly: AssemblyDescription("MyApp")` (from `AssemblyInfo.cs`)
4. Filename of the Exe (e.g., MyApp)
## Local Install location
The local install location is determined by the `id` in the NuGet package metadata.
* `%LocalAppData%\`
**Warning:** Using \[dots\] (i.e., "."'s) in your package id will cause issues ([see issue #523](https://github.com/Squirrel/Squirrel.Windows/issues/523)).
## Program and Features Entry
The entry in the Windows Uninstall is determined as follows:
* Squirrel NuGet Package Metadata `title` property
## Releases Folder
The `Squirrel --releasify` command will create update packages based on the following:
* `--delta.nupkg`
* `--full.nupkg`

## See Also
* [NuGet Package Metadata](nuget-package-metadata.md) - naming from the NuGet Package Metadata perspective.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/nuget-package-metadata.md
================================================
| [docs](..) / [using](.) / nuget-package-metadata.md
|:---|
# NuGet Package Metadata
Squirrel uses information from your app's EXE as well as the NuGet package Metadata for the setup and uninstall UI.
* **Id** - name of the application (**warning:** you must **[avoid using spaces and dots](https://github.com/Squirrel/Squirrel.Windows/issues/523)** in the Id).
* Name of the release packages (e.g., **MyApp**-1.0.0-full.nupkg).
* Local installation directory (e.g., `%LocalAppData%\MyApp`).
* **Title** - used for the name of the application in the Windows Application Uninstaller.
* **Version** - version specified in `Properties\Assembly.cs`.
* Name of the release package (e.g., MyApp-**1.0.0**-full.nupkg).
* Version number in the Windows Uninstaller (see screenshot below).
* **Icon Url** - url to an icon to be used for the application. Used for the shortcuts and Windows Uninstaller icons. This must be an icon file (*.ICO) to work correctly. Note that the icon is fetched at installation time rather than
packaging (source: [issue #745](https://github.com/Squirrel/Squirrel.Windows/issues/745))
* **Language** Changes the codepage in to support non english characters. Defaults to 1252 if not present.

## See Also
* [Naming Conventions](naming.md) - overview of sources used naming (including those outside of the NuGet Package Metadata).
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/octopack.md
================================================
| [docs](..) / [using](.) / octopack.md
|:---|
# Using OctoPack
In order to automatically construct your nuget packages you can use [OctoPack](https://github.com/OctopusDeploy/OctoPack). Octopack allows you to specify a .nuspec file which will be used to specify how your .nupkg should be created.
Follow the core instructions for creating your .nuspec file on the [OctoPack](https://github.com/OctopusDeploy/OctoPack) page.
You'll then need to add a files specification to match Squirrel's expected .nupkg structure:
~~~
~~~
If you're building using Visual Studio, you will also need to edit your .csproj file to include a property group.
~~~
true
~~~
If you're using a build server, see OctoPack's guides on how to trigger it to be run.
---
| Return: [Packaging Tools](packaging-tools.md) |
|----|
================================================
FILE: docs/using/packaging-tools.md
================================================
| [docs](..) / [using](.) / packaging-tools.md
|:---|
# Packaging Tools
The following tools can simplify and/or automate the packaging process.
* [NuGet Docs](http://docs.nuget.org/) - documentation for NuGet packaging manager.
* [NuGet Package Explorer](https://npe.codeplex.com/) - GUI tool for building NuGet packages.
* [Visual Studio Build Packaging](visual-studio-packaging.md) - integrating NuGet packaging into your visual studio build process.
* [OctoPack](octopack.md) - steps to use OctoPack to build the source NuGet package to provide to `squirrel --releasify`.
* [Auto.Squirrel Package Manager](https://github.com/tenacious/Auto.Squirrel) - tool to fully automatize the application deploy, from build to upload the updated files.
* [Paket](http://fsprojects.github.io/Paket/template-files.html) - dependency manager for .NET and mono projects, which is designed to work well with NuGet packages and also enables referencing files directly from Git repositories or any HTTP resource.
* [TeamCity](teamcity.md) - tips on using the TeamCity build server to package your app.
## See Also
* [Step 2. Packaging](../getting-started/2-packaging.md) - step from getting started guide on using NuGet Package Explorer.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/squirrel-command-line.md
================================================
| [docs](..) / [using](.) / squirrel-command-line.md
|:---|
# Squirrel Command Line
Here is a simplified help output specifically around creating releases:
```
Usage: Squirrel.exe command [OPTS]
Creates Squirrel packages
Commands
--releasify=VALUE Update or generate a releases directory with a
given NuGet package
Options:
-h, -?, --help Display Help and exit
-r, --releaseDir=VALUE Path to a release directory to use with Releasify
-p, --packagesDir=VALUE Path to the NuGet Packages directory for C# apps
--bootstrapperExe=VALUE
Path to the Setup.exe to use as a template
-g, --loadingGif=VALUE Path to an animated GIF to be displayed during
installation
-n, --signWithParams=VALUE Sign the installer via SignTool.exe with the
parameters given
--setupIcon=VALUE Path to an ICO file that will be used for the
Setup executable's icon
-b --baseUrl=VALUE Provides a base URL to prefix the RELEASES file
packages with
--no-msi Don't generate an MSI package
--msi-win64 Mark the MSI as 64-bit, which is useful in
Enterprise deployment scenarios
--no-delta Don't generate delta packages to save time
--framework-version=VALUE
Set the required .NET framework version, e.g. net461
```
## See Also
* [Loading GIF](loading-gif.md) - specify a "loading" image during initial install of large applications.
* [Application Signing](application-signing.md) - adding code signing to `Setup.exe` and your application.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/staged-rollouts.md
================================================
| [docs](..) / [using](.) / staged-rollouts.md
|:---|
# Staged Rollouts
Staged rollouts allow you to distribute the latest version of your app to a subset of users that you can increase over time, similar to rollouts on platforms like Google Play. This feature requires Squirrel.Windows 1.4.0 or above.
### How to use
Staged rollouts are controlled by manually editing your `RELEASES` file. Here's an example:
~~~
e3f67244e4166a65310c816221a12685c83f8e6f myapp-1.0.0-full.nupkg 600725
~~~
Now let's ship a new version to 10% of our userbase.
```
e3f67244e4166a65310c816221a12685c83f8e6f myapp-1.0.0-full.nupkg 600725
0d777ea94c612e8bf1ea7379164caefba6e24463 myapp-1.0.1-delta.nupkg 6030# 10%
85f4d657f8424dd437d1b33cc4511ea7ad86b1a7 myapp-1.0.1-full.nupkg 600752# 10%
```
Note that the syntax is `# nn%` - due to a bug in earlier versions of Squirrel.Windows, for now, you *must* put the `#` immediately following the file size, no spaces. Once all of your users have Squirrel 1.4.0 or higher, you can add a space after the `#` (similar to a comment).
Assuming that this rollout is going well, at some point you can upload a new version of the `RELEASES` file:
```
e3f67244e4166a65310c816221a12685c83f8e6f myapp-1.0.0-full.nupkg 600725
0d777ea94c612e8bf1ea7379164caefba6e24463 myapp-1.0.1-delta.nupkg 6030# 50%
85f4d657f8424dd437d1b33cc4511ea7ad86b1a7 myapp-1.0.1-full.nupkg 600752# 50%
```
When you're confident that this release has gone successfully, you can remove the comment so that 100% of users get the file:
```
e3f67244e4166a65310c816221a12685c83f8e6f myapp-1.0.0-full.nupkg 600725
0d777ea94c612e8bf1ea7379164caefba6e24463 myapp-1.0.1-delta.nupkg 6030
85f4d657f8424dd437d1b33cc4511ea7ad86b1a7 myapp-1.0.1-full.nupkg 600752
```
### Handling failed rollouts
If you want to pull a staged release because it hasn't gone well, you should hand-edit the RELEASES file to completely remove the bad version:
~~~
e3f67244e4166a65310c816221a12685c83f8e6f myapp-1.0.0-full.nupkg 600725
~~~
Once you do this, you **must** increment the version number higher than your broken release (in this example, we would need to release MyApp 1.0.2). Because some of your users will be on the broken 1.0.1, releasing a _new_ 1.0.1 would result in them staying on a broken version.
================================================
FILE: docs/using/teamcity.md
================================================
| [docs](..) / [using](.) / teamcity.md
|:---|
# Team City Packaging
## Adding the Packaging Step
When TeamCity pulls down your code, the squirrel.exe will sit under packages if it was added to your solution using NuGet.
1. Add a NuGet Pack process which will create the .nupkg based on a .nuspec file to ensure the package is correct.
2. Create a command line build process and add the following:
~~~
%system.teamcity.build.workingDir%\packages\squirrel.windows.1.4.0\tools\squirrel --releasify [BUILD_SERVER_NUPKG_PATH]\%system.build.number%.nupkg -r [OUTPUT_PATH]
~~~
**Note:** Paths may vary depending on your structure so make sure to update the path information above correctly.
This will cause the appropriate files to be created just as if you had run it from the Package Manager Console.
**Source:** [Issue #737](https://github.com/Squirrel/Squirrel.Windows/issues/737)
## See Also
* [Packaging Tools](packaging-tools.md) - list of packaging tools to simplify and/or automate the packaging process.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/update-manager.md
================================================
| [docs](..) / [using](.) / update-manager.md
|:---|
# Update Manager Reference
## Basic Updating
The "Easy Mode" method that does everything all in one go.
* `UpdateApp` - downloads and updates the app to the latest version.
## Advanced Updating
The following methods are provided to allow you to have more control of the update process (i.e., to interact with app updates and apply them if desired).
* `CheckForUpdate` - checks on the server if there are updates available. Returns an `UpdateInfo` object that contains information about any pending updates.
* `DownloadReleases` - downloads release files (the `nupkg` file deltas) from the server to the local machine
* `ApplyReleases` - installs the downloaded packages, and returns the new `app-[version]` directory path.
### UpdateInfo
The `UpdateInfo` class contains information about available and installed releases.
~~~cs
public class UpdateInfo
{
public ReleaseEntry CurrentlyInstalledVersion;
public ReleaseEntry FutureReleaseEntry;
public List ReleasesToApply;
}
~~~
### ReleaseEntry
The `ReleaseEntry` class contains the specifics of each release.
~~~cs
public interface ReleaseEntry
{
public string SHA1;
public string Filename;
public long Filesize;
public bool IsDelta;
}
~~~
## See Also
* [Update Process](update-process.md) - overview of the steps in the update process.
* [GitHub Update Manager](github.md) - process of using `GitHubUpdateManager`.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/update-process.md
================================================
| [docs](..) / [using](.) / update-process.md
|:---|
# Update Process
The following steps are performed by the `UpdateManager` each time your app is executed:
1. **Check for Updates** - the `RELEASES` file at the distribution location is downloaded and compared to local `RELEASES` file to check for any updates.
2. **Download & Verify Update Packages** - if there is a new release, the `UpdateManager` determines whether to download the deltas or the latest full package (by calculating which one requires less total downloading) to update to the current version. The packages are compared against their SHA1 in the `RELEASES` file for verification.
3. **Build Full Package from Deltas** - if delta packages were downloaded, a new full package is created from the previous full package and the downloaded delta file.
3. **Install New Version** - the current version of MyApp is extracted from the full package and placed in a new `%LocalAppData%\MyApp` install directory based on the version number (e.g., `app-1.0.1`).
4. **Update Shortcuts** - desktop and Windows Start Menu shortcuts are updated to point to the new MyApp version (via the `--processStart` command line parameter passed to `Update.exe`).
5. **Previous Version Clean-up** - on the next startup of MyApp, all but current and immediately previous version of your app are deleted as part of clean up (e.g., after updating to app-1.0.5, app-1.0.4 will remain, but app-1.0.3 and before will be deleted - see [issue #589](https://github.com/Squirrel/Squirrel.Windows/issues/589)).
## Rollback
Currently, there is no built-in support for rolling back to a previous version.
## See Also
* [Update Manager](update-manager.md) - reference guide for the `UpdateManager`.
* [Debugging Updates](debugging-updates.md) - tips on debugging your Squirrel application.
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: docs/using/visual-studio-packaging.md
================================================
| [docs](..) / [using](.) / visual-studio-packaging.md
|:---|
# Visual Studio Build Packaging
Squirrel packaging can be easily integrated directly into your build process using only NuGet and Squirrel.
## Define Build Target
The first step is to define a build target in your `.csproj` file.
```xml
```
This will generate a NuGet package from .nuspec file setting version from AssemblyInfo.cs and place it in OutDir (by default bin\Release). Then it will generate release files from it.
## Example .nuspec file for MyApp
Here is an example `MyApp.nuspec` file for the above build target example.
```xml
MyApp
0.0.0.0
title
authors
description
false
Copyright 2016
```
## Additional Notes
Please be aware of the following when using this solution:
* Solution needs to have nuget.exe available which can be accomplished by installing `NuGet.CommandLine` package in your solution.
```pm
PM> Install-Package NuGet.CommandLine
```
* It suffers from a bug when sometimes NuGet packages are not loaded properly and throws nuget/squirrel is not recogized (9009) errors.
**Tip:** In this case you may simply need to restart Visual Studio so the Package Manager Console will have loaded all the package tools
* If you get the following error you may need add the full path to squirrel.exe in the build target `Exec Command` call. `'squirrel' is not recognized as an internal or external command`
**Source:** [Issue #630](https://github.com/Squirrel/Squirrel.Windows/issues/630)
---
| Return: [Packaging Tools](packaging-tools.md) |
|----|
================================================
FILE: docs/using/x-doc-template.md
================================================
| [docs](..) / [using](.) / filename.md
|:---|
# Title
text
## Sub-title
text
~~~cs
code
~~~
**Tip:** text
## See Also
* [seealso]() - text
---
| Return: [Table of Contents](../readme.md) |
|----|
================================================
FILE: src/Directory.Build.props
================================================
Debug
false
$(MSBuildProjectName)
$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))
$(BaseOutputPath)obj\$(Configuration)\$(ProjectName)\
$(BaseOutputPath)$(Configuration)\
GitHub
Copyright © GitHub 2013-2015
MS-RL
Squirrel
Win32
$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\
$(OutputPath)$(Platform)\
================================================
FILE: src/Setup/FxHelper.cpp
================================================
#include "stdafx.h"
#include "FxHelper.h"
#include "resource.h"
// http://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx#net_b
static const wchar_t* ndpPath = L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full";
static const int fx45ReleaseVersion = 378389;
static const int fx451ReleaseVersion = 378675; //Minimum version for .NET 4.5.1
static const int fx452ReleaseVersion = 379893;
static const int fx46ReleaseVersion = 393295; //Windows 10 version, other systems are higher
static const int fx461ReleaseVersion = 394254; // Minimum version for .NET 4.6.1
static const int fx462ReleaseVersion = 394802; // Minimum version for .NET 4.6.2
static const int fx47ReleaseVersion = 460798; // Minimum version for .NET 4.7
static const int fx471ReleaseVersion = 461308; // Minimum version for .NET 4.7.1
static const int fx472ReleaseVersion = 461808; // Minimum version for .NET 4.7.2
static const int fx48ReleaseVersion = 528040; // Minimum version for .NET 4.8
// According to https://msdn.microsoft.com/en-us/library/8z6watww%28v=vs.110%29.aspx,
// to install .NET 4.5 we must be Vista SP2+, Windows 7 SP1+, or later.
// However Anas thinks this is just for customer support, anything >= Vista will generally work.
bool CFxHelper::CanInstallDotNet4_5()
{
return IsWindowsVistaOrGreater();
}
NetVersion CFxHelper::GetRequiredDotNetVersion()
{
wchar_t* versionFlag = (wchar_t*)LoadResource(NULL, FindResource(NULL, (LPCWSTR)IDR_FX_VERSION_FLAG, L"FLAGS"));
CString resourceFlag(versionFlag);
if (resourceFlag.Compare(L"net451") == 0) return NetVersion::net451;
if (resourceFlag.Compare(L"net452") == 0) return NetVersion::net452;
if (resourceFlag.Compare(L"net46") == 0) return NetVersion::net46;
if (resourceFlag.Compare(L"net461") == 0) return NetVersion::net461;
if (resourceFlag.Compare(L"net462") == 0) return NetVersion::net462;
if (resourceFlag.Compare(L"net47") == 0) return NetVersion::net47;
if (resourceFlag.Compare(L"net471") == 0) return NetVersion::net471;
if (resourceFlag.Compare(L"net472") == 0) return NetVersion::net472;
if (resourceFlag.Compare(L"net48") == 0) return NetVersion::net48;
//Default to standard net45
return NetVersion::net45;
}
bool CFxHelper::IsDotNetInstalled(NetVersion required)
{
ATL::CRegKey key;
if (key.Open(HKEY_LOCAL_MACHINE, ndpPath, KEY_READ) != ERROR_SUCCESS) {
return false;
}
DWORD dwReleaseInfo = 0;
if (key.QueryDWORDValue(L"Release", dwReleaseInfo) != ERROR_SUCCESS ||
dwReleaseInfo < GetDotNetVersionReleaseNumber(required)) {
return false;
}
return true;
}
UINT CFxHelper::GetDotNetVersionReleaseNumber(NetVersion version)
{
switch (version) {
case NetVersion::net451:
return fx451ReleaseVersion;
case NetVersion::net452:
return fx452ReleaseVersion;
case NetVersion::net46:
return fx46ReleaseVersion;
case NetVersion::net461:
return fx461ReleaseVersion;
case NetVersion::net462:
return fx462ReleaseVersion;
case NetVersion::net47:
return fx47ReleaseVersion;
case NetVersion::net471:
return fx471ReleaseVersion;
case NetVersion::net472:
return fx472ReleaseVersion;
case NetVersion::net48:
return fx48ReleaseVersion;
case NetVersion::net45:
default:
return fx45ReleaseVersion;
}
}
class ATL_NO_VTABLE CDownloadProgressCallback :
public CComObjectRoot,
public IBindStatusCallback
{
public:
CDownloadProgressCallback()
{
}
DECLARE_NOT_AGGREGATABLE(CDownloadProgressCallback)
BEGIN_COM_MAP(CDownloadProgressCallback)
COM_INTERFACE_ENTRY(IBindStatusCallback)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct() { return S_OK; }
void FinalRelease()
{
}
void SetProgressDialog(IProgressDialog* pd)
{
m_spProgressDialog = pd;
}
STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG /*ulStatusCode*/, LPCWSTR /*szStatusText*/)
{
if (m_spProgressDialog != nullptr) {
if (m_spProgressDialog->HasUserCancelled()) {
return E_ABORT;
}
m_spProgressDialog->SetProgress(ulProgress, ulProgressMax);
}
return S_OK;
}
STDMETHOD(OnStartBinding)(DWORD /*dwReserved*/, IBinding *pBinding) { return E_NOTIMPL; }
STDMETHOD(GetPriority)(LONG *pnPriority) { return E_NOTIMPL; }
STDMETHOD(OnLowResource)(DWORD /*reserved*/) { return E_NOTIMPL; }
STDMETHOD(OnStopBinding)(HRESULT /*hresult*/, LPCWSTR /*szError*/) { return E_NOTIMPL; }
STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindInfo) { return E_NOTIMPL; }
STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC * /*pformatetc*/, STGMEDIUM *pstgmed) { return E_NOTIMPL; }
STDMETHOD(OnObjectAvailable)(REFIID /*riid*/, IUnknown * /*punk*/) { return E_NOTIMPL; }
private:
CComPtr m_spProgressDialog;
};
HRESULT CFxHelper::InstallDotNetFramework(NetVersion version, bool isQuiet)
{
if (!isQuiet) {
CTaskDialog dlg;
TASKDIALOG_BUTTON buttons[] = {
{ 1, L"Install", },
{ 2, L"Cancel", },
};
dlg.SetButtons(buttons, 2);
dlg.SetMainInstructionText(GetInstallerMainInstructionForVersion(version));
dlg.SetContentText(GetInstallerContentForVersion(version));
dlg.SetMainIcon(TD_INFORMATION_ICON);
dlg.SetExpandedInformationText(GetInstallerExpandedInfoForVersion(version));
int nButton;
if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton)) || nButton != 1) {
return S_FALSE;
}
}
HRESULT hr = E_FAIL;
WCHAR szFinalTempFileName[_MAX_PATH] = L"";
CComPtr bscb;
CComPtr pd;
SHELLEXECUTEINFO execInfo = { sizeof(execInfo), };
CString url;
url.LoadString(GetInstallerUrlForVersion(version));
WCHAR szTempPath[_MAX_PATH];
DWORD dwTempPathResult = GetTempPath(_MAX_PATH, szTempPath);
if (dwTempPathResult == 0) {
hr = AtlHresultFromLastError();
goto out;
} else if (dwTempPathResult > _MAX_PATH) {
hr = DISP_E_BUFFERTOOSMALL;
goto out;
}
WCHAR szTempFileName[_MAX_PATH];
if (!GetTempFileName(szTempPath, L"NDP", 0, szTempFileName)) {
hr = AtlHresultFromLastError();
goto out;
}
szTempFileName[_countof(szTempFileName) - 1] = L'\0';
if (wcscpy_s(szFinalTempFileName, _countof(szFinalTempFileName), szTempFileName) != 0) {
hr = E_FAIL;
goto out;
}
WCHAR* pLastDot = wcsrchr(szFinalTempFileName, L'.');
if (pLastDot == nullptr) {
if (wcscat_s(szFinalTempFileName, _countof(szFinalTempFileName), L".exe") != 0) {
hr = E_FAIL;
goto out;
}
} else {
if (wcscpy_s(pLastDot, _countof(szFinalTempFileName) - (pLastDot - szFinalTempFileName), L".exe") != 0) {
hr = E_FAIL;
goto out;
}
}
if (!MoveFile(szTempFileName, szFinalTempFileName)) {
hr = AtlHresultFromLastError();
goto out;
}
if (!isQuiet) {
pd.CoCreateInstance(CLSID_ProgressDialog);
if (pd != nullptr) {
pd->SetTitle(L"Downloading");
pd->SetLine(1, L"Downloading the .NET Framework installer", FALSE, nullptr);
pd->StartProgressDialog(nullptr, nullptr, 0, nullptr);
CComObject* bscbObj = nullptr;
if (SUCCEEDED(CComObject::CreateInstance(&bscbObj))) {
bscbObj->SetProgressDialog(pd);
bscb = bscbObj;
}
}
}
hr = URLDownloadToFile(nullptr, url, szFinalTempFileName, 0, bscb);
if (pd != nullptr) {
pd->StopProgressDialog();
}
if (hr != S_OK) {
goto out;
}
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
execInfo.lpVerb = L"open";
execInfo.lpFile = szFinalTempFileName;
if (isQuiet) {
execInfo.lpParameters = L"/q /norestart";
}
else {
execInfo.lpParameters = L"/passive /norestart /showrmui";
}
execInfo.nShow = SW_SHOW;
if (!ShellExecuteEx(&execInfo)) {
hr = AtlHresultFromLastError();
goto out;
}
WaitForSingleObject(execInfo.hProcess, INFINITE);
DWORD exitCode;
if (!GetExitCodeProcess(execInfo.hProcess, &exitCode)) {
hr = AtlHresultFromLastError();
goto out;
}
if (exitCode == 1641 || exitCode == 3010) {
// The framework installer wants a reboot before we can continue
// See https://msdn.microsoft.com/en-us/library/ee942965%28v=vs.110%29.aspx
hr = HandleRebootRequirement(isQuiet);
// Exit as a failure, so that setup doesn't carry on now
}
else {
hr = exitCode != 0 ? E_FAIL : S_OK;
}
out:
if (execInfo.hProcess != NULL && execInfo.hProcess != INVALID_HANDLE_VALUE) {
CloseHandle(execInfo.hProcess);
}
if (*szFinalTempFileName != L'\0') {
DeleteFile(szFinalTempFileName);
}
return hr;
}
UINT CFxHelper::GetInstallerMainInstructionForVersion(NetVersion version)
{
if (version >= NetVersion::net48) {
return IDS_FXINSTRUCTION48;
}
if (version >= NetVersion::net47) {
return IDS_FXINSTRUCTION47;
}
if (version >= NetVersion::net46) {
return IDS_FXINSTRUCTION46;
}
return IDS_FXINSTRUCTION;
}
UINT CFxHelper::GetInstallerContentForVersion(NetVersion version)
{
if (version >= NetVersion::net48) {
return IDS_FXCONTENT48;
}
if (version >= NetVersion::net47) {
return IDS_FXCONTENT47;
}
if (version >= NetVersion::net46) {
return IDS_FXCONTENT46;
}
return IDS_FXCONTENT;
}
UINT CFxHelper::GetInstallerExpandedInfoForVersion(NetVersion version)
{
if (version >= NetVersion::net48) {
return IDS_FXEXPANDEDINFO48;
}
if (version >= NetVersion::net47) {
return IDS_FXEXPANDEDINFO47;
}
if (version >= NetVersion::net46) {
return IDS_FXEXPANDEDINFO46;
}
return IDS_FXEXPANDEDINFO;
}
UINT CFxHelper::GetInstallerUrlForVersion(NetVersion version)
{
if (version >= NetVersion::net48) {
return IDS_FXDOWNLOADURL48;
}
if (version >= NetVersion::net47) {
return IDS_FXDOWNLOADURL47;
}
if (version >= NetVersion::net46) {
return IDS_FXDOWNLOADURL46;
}
return IDS_FXDOWNLOADURL;
}
// Deal with the aftermath of the framework installer telling us that we need to reboot
HRESULT CFxHelper::HandleRebootRequirement(bool isQuiet)
{
if (isQuiet) {
// Don't silently reboot - just error-out
fprintf_s(stderr, "A reboot is required following .NET installation - reboot then run installer again.\n");
return E_FAIL;
}
CTaskDialog dlg;
TASKDIALOG_BUTTON buttons[] = {
{ 1, L"Restart Now", },
{ 2, L"Cancel", },
};
dlg.SetButtons(buttons, 2);
dlg.SetMainInstructionText(L"Restart System");
dlg.SetContentText(L"To finish installing the .NET Framework, the system now needs to restart. The installation will finish after you restart and log-in again.");
dlg.SetMainIcon(TD_INFORMATION_ICON);
dlg.SetExpandedInformationText(L"If you click 'Cancel', you'll need to re-run this setup program yourself, after restarting your system.");
int nButton;
if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton)) || nButton != 1) {
return S_FALSE;
}
// We need to set up a runonce entry to restart this installer once the reboot has happened
if (!WriteRunOnceEntry()) {
return E_FAIL;
}
// And now, reboot
if (!RebootSystem()) {
return E_FAIL;
}
// About to reboot, but just in case...
return S_FALSE;
}
//
// Write a runonce entry to the registry to tell it to continue with
// setup after a reboot
//
bool CFxHelper::WriteRunOnceEntry()
{
ATL::CRegKey key;
if (key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", KEY_WRITE) != ERROR_SUCCESS) {
return false;
}
TCHAR exePath[MAX_PATH];
GetModuleFileName(NULL, exePath, MAX_PATH);
if (key.SetStringValue(L"SquirrelInstall", exePath) != ERROR_SUCCESS) {
return false;
}
return true;
}
bool CFxHelper::RebootSystem()
{
// First we need to enable the SE_SHUTDOWN_NAME privilege
LUID luid;
if (!LookupPrivilegeValue(L"", SE_SHUTDOWN_NAME, &luid)) {
return false;
}
HANDLE hToken = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
return false;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, 0)) {
CloseHandle(hToken);
return false;
}
// Now we have that privilege, we can ask Windows to restart
return ExitWindowsEx(EWX_REBOOT, 0) != 0;
}
================================================
FILE: src/Setup/FxHelper.h
================================================
#pragma once
enum class NetVersion {net45=0, net451=1, net452=2, net46=3, net461=4, net462=5, net47=6, net471=7, net472=8, net48=9};
class CFxHelper
{
public:
static NetVersion GetRequiredDotNetVersion();
static bool CanInstallDotNet4_5();
static bool IsDotNetInstalled(NetVersion requiredVersion);
static HRESULT InstallDotNetFramework(NetVersion version, bool isQuiet);
private:
static HRESULT HandleRebootRequirement(bool isQuiet);
static bool WriteRunOnceEntry();
static bool RebootSystem();
static UINT GetDotNetVersionReleaseNumber(NetVersion version);
static UINT GetInstallerUrlForVersion(NetVersion version);
static UINT GetInstallerMainInstructionForVersion(NetVersion version);
static UINT GetInstallerContentForVersion(NetVersion version);
static UINT GetInstallerExpandedInfoForVersion(NetVersion version);
};
================================================
FILE: src/Setup/MachineInstaller.cpp
================================================
#include "stdafx.h"
#include "unzip.h"
#include "MachineInstaller.h"
#include "resource.h"
#include
bool directoryExists(wchar_t* path) {
DWORD dwResult = GetFileAttributes(path);
if (dwResult != INVALID_FILE_ATTRIBUTES) {
return true;
}
// NB: The directory could exist but we can't access it, let's check
DWORD dwLastError = GetLastError();
if (dwLastError == ERROR_FILE_NOT_FOUND) return false;
if (dwLastError == ERROR_PATH_NOT_FOUND) return false;
return true;
}
bool MachineInstaller::ShouldSilentInstall()
{
// Figure out the package name from our own EXE name
// The name consist of [$pkgName]DeploymentTool.exe
wchar_t ourFile[MAX_PATH];
HMODULE hMod = GetModuleHandle(NULL);
GetModuleFileName(hMod, ourFile, _countof(ourFile));
CString fullPath = CString(ourFile);
CString pkgName = CString(ourFile + fullPath.ReverseFind(L'\\'));
pkgName.Replace(L"DeploymentTool.exe", L"");
wchar_t installFolder[MAX_PATH];
// NB: Users often get into the sitch where they install the MSI, then try to
// install the standalone package on top of that. In previous versions we tried
// to detect if the app was properly installed, but now we're taking the much
// more conservative approach, that if the package dir exists in any way, we're
// bailing out
// C:\Users\Username\AppData\Local\$pkgName
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder);
wcscat(installFolder, L"\\");
wcscat(installFolder, pkgName);
if (directoryExists(installFolder)) {
return false;
}
// C:\ProgramData\$pkgName\$username
wchar_t username[512];
DWORD unamesize = _countof(username);
SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder);
GetUserName(username, &unamesize);
wcscat(installFolder, L"\\");
wcscat(installFolder, pkgName);
wcscat(installFolder, L"\\");
wcscat(installFolder, username);
if (directoryExists(installFolder)) {
return false;
}
// None of these exist, we should install
return true;
}
================================================
FILE: src/Setup/MachineInstaller.h
================================================
#pragma once
class MachineInstaller
{
public:
static bool ShouldSilentInstall();
};
================================================
FILE: src/Setup/Setup.h
================================================
#pragma once
#include "resource.h"
================================================
FILE: src/Setup/Setup.vcxproj
================================================
Debug
Win32
Release
Win32
{C1D40624-A484-438A-B846-052F321C89D1}
Application
Win32Proj
v142
Unicode
Setup
10.0
true
false
false
true
true
$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)/wtl90
false
$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)/wtl90
Use
Level3
Disabled
WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
true
Windows
true
urlmon.lib
comctl32.dll;shell32.dll;shlwapi.dll;urlmon.dll;%(DelayLoadDLLs)
compat.manifest
Level3
Use
MinSpace
true
true
WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
true
Size
true
MultiThreaded
true
Windows
true
true
true
AsInvoker
urlmon.lib
comctl32.dll;shell32.dll;shlwapi.dll;urlmon.dll;%(DelayLoadDLLs)
compat.manifest
true
Create
================================================
FILE: src/Setup/Setup.vcxproj.filters
================================================
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
{93995380-89BD-4b04-88EB-625FBE52EBFB}
h;hh;hpp;hxx;hm;inl;inc;xsd
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Source Files
Source Files
Source Files
Source Files
Source Files
Source Files
Resource Files
Resource Files
Resource Files
Resource Files
Resource Files
================================================
FILE: src/Setup/UpdateRunner.cpp
================================================
#include "stdafx.h"
#include "unzip.h"
#include "Resource.h"
#include "UpdateRunner.h"
#include
void CUpdateRunner::DisplayErrorMessage(CString& errorMessage, wchar_t* logFile)
{
CTaskDialog dlg;
TASKDIALOG_BUTTON buttons[] = {
{ 1, L"Open Setup Log", },
{ 2, L"Close", },
};
// TODO: Something about contacting support?
if (logFile == NULL) {
dlg.SetButtons(&buttons[1], 1, 1);
} else {
dlg.SetButtons(buttons, 2, 1);
}
dlg.SetMainInstructionText(L"Installation has failed");
dlg.SetContentText(errorMessage);
dlg.SetMainIcon(TD_ERROR_ICON);
int nButton;
if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton))) {
return;
}
if (nButton == 1 && logFile != NULL) {
ShellExecute(NULL, NULL, logFile, NULL, NULL, SW_SHOW);
}
}
HRESULT CUpdateRunner::AreWeInWine()
{
// NB: Behaving differently in Wine is *usually* discouraged
// https://wiki.winehq.org/Developer_FAQ#How_can_I_detect_Wine.3F
HMODULE hntdll = GetModuleHandle(L"ntdll.dll");
if (!hntdll) {
// NB: This can never fail but we'll be pedantic
return E_FAIL;
}
return GetProcAddress(hntdll, "wine_get_version") != NULL ? S_OK : S_FALSE;
}
HRESULT CUpdateRunner::AreWeUACElevated()
{
HANDLE hProcess = GetCurrentProcess();
HANDLE hToken = 0;
HRESULT hr;
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto out;
}
TOKEN_ELEVATION_TYPE elevType;
DWORD dontcare;
if (!GetTokenInformation(hToken, TokenElevationType, &elevType, sizeof(TOKEN_ELEVATION_TYPE), &dontcare)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto out;
}
hr = (elevType == TokenElevationTypeFull ? S_OK : S_FALSE);
out:
if (hToken) {
CloseHandle(hToken);
}
return hr;
}
HRESULT FindDesktopFolderView(REFIID riid, void **ppv)
{
HRESULT hr;
CComPtr spShellWindows;
spShellWindows.CoCreateInstance(CLSID_ShellWindows);
CComVariant vtLoc(CSIDL_DESKTOP);
CComVariant vtEmpty;
long lhwnd;
CComPtr spdisp;
hr = spShellWindows->FindWindowSW(
&vtLoc, &vtEmpty,
SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);
if (FAILED(hr)) return hr;
CComPtr spBrowser;
hr = CComQIPtr(spdisp)->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser));
if (FAILED(hr)) return hr;
CComPtr spView;
hr = spBrowser->QueryActiveShellView(&spView);
if (FAILED(hr)) return hr;
hr = spView->QueryInterface(riid, ppv);
if (FAILED(hr)) return hr;
return S_OK;
}
HRESULT GetDesktopAutomationObject(REFIID riid, void **ppv)
{
HRESULT hr;
CComPtr spsv;
hr = FindDesktopFolderView(IID_PPV_ARGS(&spsv));
if (FAILED(hr)) return hr;
CComPtr spdispView;
hr = spsv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&spdispView));
if (FAILED(hr)) return hr;
return spdispView->QueryInterface(riid, ppv);
}
HRESULT CUpdateRunner::ShellExecuteFromExplorer(LPWSTR pszFile, LPWSTR pszParameters)
{
HRESULT hr;
CComPtr spFolderView;
hr = GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView));
if (FAILED(hr)) return hr;
CComPtr spdispShell;
hr = spFolderView->get_Application(&spdispShell);
if (FAILED(hr)) return hr;
return CComQIPtr(spdispShell)->ShellExecute(
CComBSTR(pszFile),
CComVariant(pszParameters ? pszParameters : L""),
CComVariant(L""),
CComVariant(L""),
CComVariant(SW_SHOWDEFAULT));
}
bool CUpdateRunner::DirectoryExists(wchar_t* szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool CUpdateRunner::DirectoryIsWritable(wchar_t * szPath)
{
wchar_t szTempFileName[MAX_PATH];
UINT uRetVal = GetTempFileNameW(szPath, L"Squirrel", 0, szTempFileName);
if (uRetVal == 0) {
return false;
}
DeleteFile(szTempFileName);
return true;
}
int CUpdateRunner::ExtractUpdaterAndRun(wchar_t* lpCommandLine, bool useFallbackDir)
{
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
CResource zipResource;
wchar_t targetDir[MAX_PATH] = { 0 };
wchar_t logFile[MAX_PATH];
std::vector to_delete;
wchar_t* envSquirrelTemp = _wgetenv(L"SQUIRREL_TEMP");
if (envSquirrelTemp &&
DirectoryExists(envSquirrelTemp) &&
DirectoryIsWritable(envSquirrelTemp) &&
!PathIsUNCW(envSquirrelTemp)) {
_swprintf_c(targetDir, _countof(targetDir), L"%s", envSquirrelTemp);
goto gotADir;
}
if (!useFallbackDir) {
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, targetDir);
goto gotADir;
}
wchar_t username[512];
wchar_t appDataDir[MAX_PATH];
ULONG unameSize = _countof(username);
SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, appDataDir);
GetUserName(username, &unameSize);
_swprintf_c(targetDir, _countof(targetDir), L"%s\\%s", appDataDir, username);
if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
wchar_t err[4096];
_swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir);
DisplayErrorMessage(CString(err), NULL);
return -1;
}
gotADir:
wcscat_s(targetDir, _countof(targetDir), L"\\SquirrelTemp");
if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
wchar_t err[4096];
_swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir);
if (useFallbackDir) {
DisplayErrorMessage(CString(err), NULL);
}
goto failedExtract;
}
swprintf_s(logFile, L"%s\\SquirrelSetup.log", targetDir);
if (!zipResource.Load(L"DATA", IDR_UPDATE_ZIP)) {
goto failedExtract;
}
DWORD dwSize = zipResource.GetSize();
if (dwSize < 0x100) {
goto failedExtract;
}
BYTE* pData = (BYTE*)zipResource.Lock();
HZIP zipFile = OpenZip(pData, dwSize, NULL);
SetUnzipBaseDir(zipFile, targetDir);
// NB: This library is kind of a disaster
ZRESULT zr;
int index = 0;
do {
ZIPENTRY zentry;
wchar_t targetFile[MAX_PATH];
zr = GetZipItem(zipFile, index, &zentry);
if (zr != ZR_OK && zr != ZR_MORE) {
break;
}
// NB: UnzipItem won't overwrite data, we need to do it ourselves
swprintf_s(targetFile, L"%s\\%s", targetDir, zentry.name);
DeleteFile(targetFile);
if (UnzipItem(zipFile, index, zentry.name) != ZR_OK) break;
to_delete.push_back(CString(targetFile));
index++;
} while (zr == ZR_MORE || zr == ZR_OK);
CloseZip(zipFile);
zipResource.Release();
// nfi if the zip extract actually worked, check for Update.exe
wchar_t updateExePath[MAX_PATH];
swprintf_s(updateExePath, L"%s\\%s", targetDir, L"Update.exe");
if (GetFileAttributes(updateExePath) == INVALID_FILE_ATTRIBUTES) {
goto failedExtract;
}
// Run Update.exe
si.cb = sizeof(STARTUPINFO);
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW;
if (!lpCommandLine || wcsnlen_s(lpCommandLine, MAX_PATH) < 1) {
lpCommandLine = L"";
}
wchar_t cmd[MAX_PATH];
swprintf_s(cmd, L"\"%s\" --install . %s", updateExePath, lpCommandLine);
if (!CreateProcess(NULL, cmd, NULL, NULL, false, 0, NULL, targetDir, &si, &pi)) {
goto failedExtract;
}
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD dwExitCode;
if (!GetExitCodeProcess(pi.hProcess, &dwExitCode)) {
dwExitCode = (DWORD)-1;
}
if (dwExitCode != 0) {
DisplayErrorMessage(CString(
L"There was an error while installing the application. "
L"Check the setup log for more information and contact the author."), logFile);
}
for (unsigned int i = 0; i < to_delete.size(); i++) {
DeleteFile(to_delete[i]);
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return (int) dwExitCode;
failedExtract:
if (!useFallbackDir) {
// Take another pass at it, using C:\ProgramData instead
return ExtractUpdaterAndRun(lpCommandLine, true);
}
DisplayErrorMessage(CString(L"Failed to extract installer"), NULL);
return (int) dwExitCode;
}
================================================
FILE: src/Setup/UpdateRunner.h
================================================
#pragma once
class CUpdateRunner
{
public:
static void DisplayErrorMessage(CString& errorMessage, wchar_t* logFile);
static HRESULT AreWeInWine();
static HRESULT AreWeUACElevated();
static HRESULT ShellExecuteFromExplorer(LPWSTR pszFile, LPWSTR pszParameters);
static bool DirectoryExists(wchar_t* szPath);
static bool DirectoryIsWritable(wchar_t* szPath);
static int ExtractUpdaterAndRun(wchar_t* lpCommandLine, bool useFallbackDir);
};
================================================
FILE: src/Setup/compat.manifest
================================================
================================================
FILE: src/Setup/stdafx.cpp
================================================
// stdafx.cpp : source file that includes just the standard includes
// Setup.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
================================================
FILE: src/Setup/stdafx.h
================================================
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define SECURITY_WIN32
// Windows Header Files:
#include
#include
#include
#include
// C RunTime Header Files
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined _M_IX86
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
================================================
FILE: src/Setup/targetver.h
================================================
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include
#define _WIN32_WINNT 0x0600
#include
================================================
FILE: src/Setup/unzip.cpp
================================================
#include "stdafx.h"
#include "unzip.h"
// THIS FILE is almost entirely based upon code by Jean-loup Gailly
// and Mark Adler. It has been modified by Lucian Wischik.
// The modifications were: incorporate the bugfixes of 1.1.4, allow
// unzipping to/from handles/pipes/files/memory, encryption, unicode,
// a windowsish api, and putting everything into a single .cpp file.
// The original code may be found at http://www.gzip.org/zlib/
// The original copyright text follows.
//
//
//
// zlib.h -- interface of the 'zlib' general purpose compression library
// version 1.1.3, July 9th, 1998
//
// Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// Jean-loup Gailly Mark Adler
// jloup@gzip.org madler@alumni.caltech.edu
//
//
// The data format used by the zlib library is described by RFCs (Request for
// Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
// (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
//
//
// The 'zlib' compression library provides in-memory compression and
// decompression functions, including integrity checks of the uncompressed
// data. This version of the library supports only one compression method
// (deflation) but other algorithms will be added later and will have the same
// stream interface.
//
// Compression can be done in a single step if the buffers are large
// enough (for example if an input file is mmap'ed), or can be done by
// repeated calls of the compression function. In the latter case, the
// application must provide more input and/or consume the output
// (providing more output space) before each call.
//
// The library also supports reading and writing files in gzip (.gz) format
// with an interface similar to that of stdio.
//
// The library does not install any signal handler. The decoder checks
// the consistency of the compressed data, so the library should never
// crash even in case of corrupted input.
//
// for more info about .ZIP format, see ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
// PkWare has also a specification at ftp://ftp.pkware.com/probdesc.zip
#define ZIP_HANDLE 1
#define ZIP_FILENAME 2
#define ZIP_MEMORY 3
#define zmalloc(len) malloc(len)
#define zfree(p) free(p)
/*
void *zmalloc(unsigned int len)
{ char *buf = new char[len+32];
for (int i=0; i<16; i++)
{ buf[i]=i;
buf[len+31-i]=i;
}
*((unsigned int*)buf) = len;
char c[1000]; wsprintf(c,"malloc 0x%lx - %lu",buf+16,len);
OutputDebugString(c);
return buf+16;
}
void zfree(void *buf)
{ char c[1000]; wsprintf(c,"free 0x%lx",buf);
OutputDebugString(c);
char *p = ((char*)buf)-16;
unsigned int len = *((unsigned int*)p);
bool blown=false;
for (int i=0; i<16; i++)
{ char lo = p[i];
char hi = p[len+31-i];
if (hi!=i || (lo!=i && i>4)) blown=true;
}
if (blown)
{ OutputDebugString("BLOWN!!!");
}
delete[] p;
}
*/
typedef struct tm_unz_s
{ unsigned int tm_sec; // seconds after the minute - [0,59]
unsigned int tm_min; // minutes after the hour - [0,59]
unsigned int tm_hour; // hours since midnight - [0,23]
unsigned int tm_mday; // day of the month - [1,31]
unsigned int tm_mon; // months since January - [0,11]
unsigned int tm_year; // years - [1980..2044]
} tm_unz;
// unz_global_info structure contain global data about the ZIPfile
typedef struct unz_global_info_s
{ unsigned long number_entry; // total number of entries in the central dir on this disk
unsigned long size_comment; // size of the global comment of the zipfile
} unz_global_info;
// unz_file_info contain information about a file in the zipfile
typedef struct unz_file_info_s
{ unsigned long version; // version made by 2 bytes
unsigned long version_needed; // version needed to extract 2 bytes
unsigned long flag; // general purpose bit flag 2 bytes
unsigned long compression_method; // compression method 2 bytes
unsigned long dosDate; // last mod file date in Dos fmt 4 bytes
unsigned long crc; // crc-32 4 bytes
unsigned long compressed_size; // compressed size 4 bytes
unsigned long uncompressed_size; // uncompressed size 4 bytes
unsigned long size_filename; // filename length 2 bytes
unsigned long size_file_extra; // extra field length 2 bytes
unsigned long size_file_comment; // file comment length 2 bytes
unsigned long disk_num_start; // disk number start 2 bytes
unsigned long internal_fa; // internal file attributes 2 bytes
unsigned long external_fa; // external file attributes 4 bytes
tm_unz tmu_date;
} unz_file_info;
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
#define UNZ_PASSWORD (-106)
#define ZLIB_VERSION "1.1.3"
// Allowed flush values; see deflate() for details
#define Z_NO_FLUSH 0
#define Z_SYNC_FLUSH 2
#define Z_FULL_FLUSH 3
#define Z_FINISH 4
// compression levels
#define Z_NO_COMPRESSION 0
#define Z_BEST_SPEED 1
#define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1)
// compression strategy; see deflateInit2() for details
#define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2
#define Z_DEFAULT_STRATEGY 0
// Possible values of the data_type field
#define Z_BINARY 0
#define Z_ASCII 1
#define Z_UNKNOWN 2
// The deflate compression method (the only one supported in this version)
#define Z_DEFLATED 8
// for initializing zalloc, zfree, opaque
#define Z_NULL 0
// case sensitivity when searching for filenames
#define CASE_SENSITIVE 1
#define CASE_INSENSITIVE 2
// Return codes for the compression/decompression functions. Negative
// values are errors, positive values are used for special but normal events.
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_NEED_DICT 2
#define Z_ERRNO (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
#define Z_VERSION_ERROR (-6)
// Basic data types
typedef unsigned char Byte; // 8 bits
typedef unsigned int uInt; // 16 bits or more
typedef unsigned long uLong; // 32 bits or more
typedef void *voidpf;
typedef void *voidp;
typedef long z_off_t;
typedef voidpf (*alloc_func) (voidpf opaque, uInt items, uInt size);
typedef void (*free_func) (voidpf opaque, voidpf address);
struct internal_state;
typedef struct z_stream_s {
Byte *next_in; // next input byte
uInt avail_in; // number of bytes available at next_in
uLong total_in; // total nb of input bytes read so far
Byte *next_out; // next output byte should be put there
uInt avail_out; // remaining free space at next_out
uLong total_out; // total nb of bytes output so far
char *msg; // last error message, NULL if no error
struct internal_state *state; // not visible by applications
alloc_func zalloc; // used to allocate the internal state
free_func zfree; // used to free the internal state
voidpf opaque; // private data object passed to zalloc and zfree
int data_type; // best guess about the data type: ascii or binary
uLong adler; // adler32 value of the uncompressed data
uLong reserved; // reserved for future use
} z_stream;
typedef z_stream *z_streamp;
// The application must update next_in and avail_in when avail_in has
// dropped to zero. It must update next_out and avail_out when avail_out
// has dropped to zero. The application must initialize zalloc, zfree and
// opaque before calling the init function. All other fields are set by the
// compression library and must not be updated by the application.
//
// The opaque value provided by the application will be passed as the first
// parameter for calls of zalloc and zfree. This can be useful for custom
// memory management. The compression library attaches no meaning to the
// opaque value.
//
// zalloc must return Z_NULL if there is not enough memory for the object.
// If zlib is used in a multi-threaded application, zalloc and zfree must be
// thread safe.
//
// The fields total_in and total_out can be used for statistics or
// progress reports. After compression, total_in holds the total size of
// the uncompressed data and may be saved for use in the decompressor
// (particularly if the decompressor wants to decompress everything in
// a single step).
//
// basic functions
const char *zlibVersion ();
// The application can compare zlibVersion and ZLIB_VERSION for consistency.
// If the first character differs, the library code actually used is
// not compatible with the zlib.h header file used by the application.
// This check is automatically made by inflateInit.
int inflate (z_streamp strm, int flush);
//
// inflate decompresses as much data as possible, and stops when the input
// buffer becomes empty or the output buffer becomes full. It may some
// introduce some output latency (reading input without producing any output)
// except when forced to flush.
//
// The detailed semantics are as follows. inflate performs one or both of the
// following actions:
//
// - Decompress more input starting at next_in and update next_in and avail_in
// accordingly. If not all input can be processed (because there is not
// enough room in the output buffer), next_in is updated and processing
// will resume at this point for the next call of inflate().
//
// - Provide more output starting at next_out and update next_out and avail_out
// accordingly. inflate() provides as much output as possible, until there
// is no more input data or no more space in the output buffer (see below
// about the flush parameter).
//
// Before the call of inflate(), the application should ensure that at least
// one of the actions is possible, by providing more input and/or consuming
// more output, and updating the next_* and avail_* values accordingly.
// The application can consume the uncompressed output when it wants, for
// example when the output buffer is full (avail_out == 0), or after each
// call of inflate(). If inflate returns Z_OK and with zero avail_out, it
// must be called again after making room in the output buffer because there
// might be more output pending.
//
// If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
// output as possible to the output buffer. The flushing behavior of inflate is
// not specified for values of the flush parameter other than Z_SYNC_FLUSH
// and Z_FINISH, but the current implementation actually flushes as much output
// as possible anyway.
//
// inflate() should normally be called until it returns Z_STREAM_END or an
// error. However if all decompression is to be performed in a single step
// (a single call of inflate), the parameter flush should be set to
// Z_FINISH. In this case all pending input is processed and all pending
// output is flushed; avail_out must be large enough to hold all the
// uncompressed data. (The size of the uncompressed data may have been saved
// by the compressor for this purpose.) The next operation on this stream must
// be inflateEnd to deallocate the decompression state. The use of Z_FINISH
// is never required, but can be used to inform inflate that a faster routine
// may be used for the single inflate() call.
//
// If a preset dictionary is needed at this point (see inflateSetDictionary
// below), inflate sets strm-adler to the adler32 checksum of the
// dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
// it sets strm->adler to the adler32 checksum of all output produced
// so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
// an error code as described below. At the end of the stream, inflate()
// checks that its computed adler32 checksum is equal to that saved by the
// compressor and returns Z_STREAM_END only if the checksum is correct.
//
// inflate() returns Z_OK if some progress has been made (more input processed
// or more output produced), Z_STREAM_END if the end of the compressed data has
// been reached and all uncompressed output has been produced, Z_NEED_DICT if a
// preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
// corrupted (input stream not conforming to the zlib format or incorrect
// adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
// (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
// enough memory, Z_BUF_ERROR if no progress is possible or if there was not
// enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
// case, the application may then call inflateSync to look for a good
// compression block.
//
int inflateEnd (z_streamp strm);
//
// All dynamically allocated data structures for this stream are freed.
// This function discards any unprocessed input and does not flush any
// pending output.
//
// inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
// was inconsistent. In the error case, msg may be set but then points to a
// static string (which must not be deallocated).
// Advanced functions
// The following functions are needed only in some special applications.
int inflateSetDictionary (z_streamp strm,
const Byte *dictionary,
uInt dictLength);
//
// Initializes the decompression dictionary from the given uncompressed byte
// sequence. This function must be called immediately after a call of inflate
// if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
// can be determined from the Adler32 value returned by this call of
// inflate. The compressor and decompressor must use exactly the same
// dictionary.
//
// inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
// parameter is invalid (such as NULL dictionary) or the stream state is
// inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
// expected one (incorrect Adler32 value). inflateSetDictionary does not
// perform any decompression: this will be done by subsequent calls of
// inflate().
int inflateSync (z_streamp strm);
//
// Skips invalid compressed data until a full flush point can be found, or until all
// available input is skipped. No output is provided.
//
// inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
// if no more input was provided, Z_DATA_ERROR if no flush point has been found,
// or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
// case, the application may save the current current value of total_in which
// indicates where valid compressed data was found. In the error case, the
// application may repeatedly call inflateSync, providing more input each time,
// until success or end of the input data.
int inflateReset (z_streamp strm);
// This function is equivalent to inflateEnd followed by inflateInit,
// but does not free and reallocate all the internal decompression state.
// The stream will keep attributes that may have been set by inflateInit2.
//
// inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
// stream state was inconsistent (such as zalloc or state being NULL).
//
// checksum functions
// These functions are not related to compression but are exported
// anyway because they might be useful in applications using the
// compression library.
uLong adler32 (uLong adler, const Byte *buf, uInt len);
// Update a running Adler-32 checksum with the bytes buf[0..len-1] and
// return the updated checksum. If buf is NULL, this function returns
// the required initial value for the checksum.
// An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
// much faster. Usage example:
//
// uLong adler = adler32(0L, Z_NULL, 0);
//
// while (read_buffer(buffer, length) != EOF) {
// adler = adler32(adler, buffer, length);
// }
// if (adler != original_adler) error();
uLong ucrc32 (uLong crc, const Byte *buf, uInt len);
// Update a running crc with the bytes buf[0..len-1] and return the updated
// crc. If buf is NULL, this function returns the required initial value
// for the crc. Pre- and post-conditioning (one's complement) is performed
// within this function so it shouldn't be done by the application.
// Usage example:
//
// uLong crc = crc32(0L, Z_NULL, 0);
//
// while (read_buffer(buffer, length) != EOF) {
// crc = crc32(crc, buffer, length);
// }
// if (crc != original_crc) error();
const char *zError (int err);
int inflateSyncPoint (z_streamp z);
const uLong *get_crc_table (void);
typedef unsigned char uch;
typedef uch uchf;
typedef unsigned short ush;
typedef ush ushf;
typedef unsigned long ulg;
const char * const z_errmsg[10] = { // indexed by 2-zlib_error
"need dictionary", // Z_NEED_DICT 2
"stream end", // Z_STREAM_END 1
"", // Z_OK 0
"file error", // Z_ERRNO (-1)
"stream error", // Z_STREAM_ERROR (-2)
"data error", // Z_DATA_ERROR (-3)
"insufficient memory", // Z_MEM_ERROR (-4)
"buffer error", // Z_BUF_ERROR (-5)
"incompatible version",// Z_VERSION_ERROR (-6)
""};
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = (char*)ERR_MSG(err), (err))
// To be used only when the state is known to be valid
// common constants
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
// The three kinds of block type
#define MIN_MATCH 3
#define MAX_MATCH 258
// The minimum and maximum match lengths
#define PRESET_DICT 0x20 // preset dictionary flag in zlib header
// target dependencies
#define OS_CODE 0x0b // Window 95 & Windows NT
// functions
#define zmemzero(dest, len) memset(dest, 0, len)
// Diagnostic functions
#define LuAssert(cond,msg)
#define LuTrace(x)
#define LuTracev(x)
#define LuTracevv(x)
#define LuTracec(c,x)
#define LuTracecv(c,x)
typedef uLong (*check_func) (uLong check, const Byte *buf, uInt len);
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size);
void zcfree (voidpf opaque, voidpf ptr);
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
//void ZFREE(z_streamp strm,voidpf addr)
//{ *((strm)->zfree))((strm)->opaque, addr);
//}
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
// Huffman code lookup table entry--this entry is four bytes for machines
// that have 16-bit pointers (e.g. PC's in the small or medium model).
typedef struct inflate_huft_s inflate_huft;
struct inflate_huft_s {
union {
struct {
Byte Exop; // number of extra bits or operation
Byte Bits; // number of bits in this code or subcode
} what;
uInt pad; // pad structure to a power of 2 (4 bytes for
} word; // 16-bit, 8 bytes for 32-bit int's)
uInt base; // literal, length base, distance base, or table offset
};
// Maximum size of dynamic tree. The maximum found in a long but non-
// exhaustive search was 1004 huft structures (850 for length/literals
// and 154 for distances, the latter actually the result of an
// exhaustive search). The actual maximum is not known, but the
// value below is more than safe.
#define MANY 1440
int inflate_trees_bits (
uInt *, // 19 code lengths
uInt *, // bits tree desired/actual depth
inflate_huft * *, // bits tree result
inflate_huft *, // space for trees
z_streamp); // for messages
int inflate_trees_dynamic (
uInt, // number of literal/length codes
uInt, // number of distance codes
uInt *, // that many (total) code lengths
uInt *, // literal desired/actual bit depth
uInt *, // distance desired/actual bit depth
inflate_huft * *, // literal/length tree result
inflate_huft * *, // distance tree result
inflate_huft *, // space for trees
z_streamp); // for messages
int inflate_trees_fixed (
uInt *, // literal desired/actual bit depth
uInt *, // distance desired/actual bit depth
const inflate_huft * *, // literal/length tree result
const inflate_huft * *, // distance tree result
z_streamp); // for memory allocation
struct inflate_blocks_state;
typedef struct inflate_blocks_state inflate_blocks_statef;
inflate_blocks_statef * inflate_blocks_new (
z_streamp z,
check_func c, // check function
uInt w); // window size
int inflate_blocks (
inflate_blocks_statef *,
z_streamp ,
int); // initial return code
void inflate_blocks_reset (
inflate_blocks_statef *,
z_streamp ,
uLong *); // check value on output
int inflate_blocks_free (
inflate_blocks_statef *,
z_streamp);
void inflate_set_dictionary (
inflate_blocks_statef *s,
const Byte *d, // dictionary
uInt n); // dictionary length
int inflate_blocks_sync_point (
inflate_blocks_statef *s);
struct inflate_codes_state;
typedef struct inflate_codes_state inflate_codes_statef;
inflate_codes_statef *inflate_codes_new (
uInt, uInt,
const inflate_huft *, const inflate_huft *,
z_streamp );
int inflate_codes (
inflate_blocks_statef *,
z_streamp ,
int);
void inflate_codes_free (
inflate_codes_statef *,
z_streamp );
typedef enum {
IBM_TYPE, // get type bits (3, including end bit)
IBM_LENS, // get lengths for stored
IBM_STORED, // processing stored block
IBM_TABLE, // get table lengths
IBM_BTREE, // get bit lengths tree for a dynamic block
IBM_DTREE, // get length, distance trees for a dynamic block
IBM_CODES, // processing fixed or dynamic block
IBM_DRY, // output remaining window bytes
IBM_DONE, // finished last block, done
IBM_BAD} // got a data error--stuck here
inflate_block_mode;
// inflate blocks semi-private state
struct inflate_blocks_state {
// mode
inflate_block_mode mode; // current inflate_block mode
// mode dependent information
union {
uInt left; // if STORED, bytes left to copy
struct {
uInt table; // table lengths (14 bits)
uInt index; // index into blens (or border)
uInt *blens; // bit lengths of codes
uInt bb; // bit length tree depth
inflate_huft *tb; // bit length decoding tree
} trees; // if DTREE, decoding info for trees
struct {
inflate_codes_statef
*codes;
} decode; // if CODES, current state
} sub; // submode
uInt last; // true if this block is the last block
// mode independent information
uInt bitk; // bits in bit buffer
uLong bitb; // bit buffer
inflate_huft *hufts; // single malloc for tree space
Byte *window; // sliding window
Byte *end; // one byte after sliding window
Byte *read; // window read pointer
Byte *write; // window write pointer
check_func checkfn; // check function
uLong check; // check on output
};
// defines for inflate input/output
// update pointers and return
#define UPDBITS {s->bitb=b;s->bitk=k;}
#define UPDIN {z->avail_in=n;z->total_in+=(uLong)(p-z->next_in);z->next_in=p;}
#define UPDOUT {s->write=q;}
#define UPDATE {UPDBITS UPDIN UPDOUT}
#define LEAVE {UPDATE return inflate_flush(s,z,r);}
// get bytes and bits
#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
#define NEXTBYTE (n--,*p++)
#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);}
// output bytes
#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q)
#define LOADOUT {q=s->write;m=(uInt)WAVAIL;m;}
#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
// load local pointers
#define LOAD {LOADIN LOADOUT}
// masks for lower bits (size given to avoid silly warnings with Visual C++)
// And'ing with mask[n] masks the lower n bits
const uInt inflate_mask[17] = {
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
// copy as much as possible from the sliding window to the output area
int inflate_flush (inflate_blocks_statef *, z_streamp, int);
int inflate_fast (uInt, uInt, const inflate_huft *, const inflate_huft *, inflate_blocks_statef *, z_streamp );
const uInt fixed_bl = 9;
const uInt fixed_bd = 5;
const inflate_huft fixed_tl[] = {
{{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
{{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
{{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
{{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
{{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
{{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
{{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
{{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
{{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
{{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
{{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
{{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
{{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
{{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
{{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
{{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
{{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
{{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
{{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
{{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
{{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
{{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
{{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
{{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
{{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
{{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
{{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
{{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
{{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
{{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
{{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
{{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
{{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
{{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
{{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
{{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
{{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
{{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
{{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
{{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
{{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
{{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
{{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
{{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
{{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
{{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
{{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
{{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
{{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
{{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
{{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
{{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
{{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
{{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
{{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
{{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
{{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
{{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
{{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
{{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
{{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
{{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
{{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
{{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
{{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
{{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
{{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
{{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
{{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
{{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
{{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
{{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
{{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
{{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
{{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
{{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
{{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
{{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
{{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
{{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
{{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
{{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
{{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
{{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
{{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
{{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
{{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
{{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
{{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
{{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
{{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
{{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
{{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
{{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
{{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
{{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
{{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
{{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
{{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
{{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
{{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
{{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
{{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
{{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
{{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
{{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
{{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
{{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
{{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
{{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
{{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
{{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
{{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
{{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
{{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
{{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
{{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
{{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
{{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
{{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
{{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
{{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
{{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
{{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
{{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
};
const inflate_huft fixed_td[] = {
{{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
{{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
{{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
{{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
{{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
{{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
{{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
{{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
};
// copy as much as possible from the sliding window to the output area
int inflate_flush(inflate_blocks_statef *s,z_streamp z,int r)
{
uInt n;
Byte *p;
Byte *q;
// local copies of source and destination pointers
p = z->next_out;
q = s->read;
// compute number of bytes to copy as far as end of window
n = (uInt)((q <= s->write ? s->write : s->end) - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
// update counters
z->avail_out -= n;
z->total_out += n;
// update check information
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
// copy as far as end of window
if (n!=0) // check for n!=0 to avoid waking up CodeGuard
{ memcpy(p, q, n);
p += n;
q += n;
}
// see if more to copy at beginning of window
if (q == s->end)
{
// wrap pointers
q = s->window;
if (s->write == s->end)
s->write = s->window;
// compute bytes to copy
n = (uInt)(s->write - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
// update counters
z->avail_out -= n;
z->total_out += n;
// update check information
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
// copy
if (n!=0) {memcpy(p,q,n); p+=n; q+=n;}
}
// update pointers
z->next_out = p;
s->read = q;
// done
return r;
}
// simplify the use of the inflate_huft type with some defines
#define exop word.what.Exop
#define bits word.what.Bits
typedef enum { // waiting for "i:"=input, "o:"=output, "x:"=nothing
START, // x: set up for LEN
LEN, // i: get length/literal/eob next
LENEXT, // i: getting length extra (have base)
DIST, // i: get distance next
DISTEXT, // i: getting distance extra
COPY, // o: copying bytes in window, waiting for space
LIT, // o: got literal, waiting for output space
WASH, // o: got eob, possibly still output waiting
END, // x: got eob and all data flushed
BADCODE} // x: got error
inflate_codes_mode;
// inflate codes private state
struct inflate_codes_state {
// mode
inflate_codes_mode mode; // current inflate_codes mode
// mode dependent information
uInt len;
union {
struct {
const inflate_huft *tree; // pointer into tree
uInt need; // bits needed
} code; // if LEN or DIST, where in tree
uInt lit; // if LIT, literal
struct {
uInt get; // bits to get for extra
uInt dist; // distance back to copy from
} copy; // if EXT or COPY, where and how much
} sub; // submode
// mode independent information
Byte lbits; // ltree bits decoded per branch
Byte dbits; // dtree bits decoder per branch
const inflate_huft *ltree; // literal/length/eob tree
const inflate_huft *dtree; // distance tree
};
inflate_codes_statef *inflate_codes_new(
uInt bl, uInt bd,
const inflate_huft *tl,
const inflate_huft *td, // need separate declaration for Borland C++
z_streamp z)
{
inflate_codes_statef *c;
if ((c = (inflate_codes_statef *)
ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
{
c->mode = START;
c->lbits = (Byte)bl;
c->dbits = (Byte)bd;
c->ltree = tl;
c->dtree = td;
LuTracev((stderr, "inflate: codes new\n"));
}
return c;
}
int inflate_codes(inflate_blocks_statef *s, z_streamp z, int r)
{
uInt j; // temporary storage
const inflate_huft *t; // temporary pointer
uInt e; // extra bits or operation
uLong b; // bit buffer
uInt k; // bits in bit buffer
Byte *p; // input data pointer
uInt n; // bytes available there
Byte *q; // output window write pointer
uInt m; // bytes to end of window or read pointer
Byte *f; // pointer to copy strings from
inflate_codes_statef *c = s->sub.decode.codes; // codes state
// copy input/output information to locals (UPDATE macro restores)
LOAD
// process input and output based on current state
for(;;) switch (c->mode)
{ // waiting for "i:"=input, "o:"=output, "x:"=nothing
case START: // x: set up for LEN
#ifndef SLOW
if (m >= 258 && n >= 10)
{
UPDATE
r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
LOAD
if (r != Z_OK)
{
c->mode = r == Z_STREAM_END ? WASH : BADCODE;
break;
}
}
#endif // !SLOW
c->sub.code.need = c->lbits;
c->sub.code.tree = c->ltree;
c->mode = LEN;
case LEN: // i: get length/literal/eob next
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e == 0) // literal
{
c->sub.lit = t->base;
LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", t->base));
c->mode = LIT;
break;
}
if (e & 16) // length
{
c->sub.copy.get = e & 15;
c->len = t->base;
c->mode = LENEXT;
break;
}
if ((e & 64) == 0) // next table
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
if (e & 32) // end of block
{
LuTracevv((stderr, "inflate: end of block\n"));
c->mode = WASH;
break;
}
c->mode = BADCODE; // invalid code
z->msg = (char*)"invalid literal/length code";
r = Z_DATA_ERROR;
LEAVE
case LENEXT: // i: getting length extra (have base)
j = c->sub.copy.get;
NEEDBITS(j)
c->len += (uInt)b & inflate_mask[j];
DUMPBITS(j)
c->sub.code.need = c->dbits;
c->sub.code.tree = c->dtree;
LuTracevv((stderr, "inflate: length %u\n", c->len));
c->mode = DIST;
case DIST: // i: get distance next
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e & 16) // distance
{
c->sub.copy.get = e & 15;
c->sub.copy.dist = t->base;
c->mode = DISTEXT;
break;
}
if ((e & 64) == 0) // next table
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
c->mode = BADCODE; // invalid code
z->msg = (char*)"invalid distance code";
r = Z_DATA_ERROR;
LEAVE
case DISTEXT: // i: getting distance extra
j = c->sub.copy.get;
NEEDBITS(j)
c->sub.copy.dist += (uInt)b & inflate_mask[j];
DUMPBITS(j)
LuTracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
c->mode = COPY;
case COPY: // o: copying bytes in window, waiting for space
f = q - c->sub.copy.dist;
while (f < s->window) // modulo window size-"while" instead
f += s->end - s->window; // of "if" handles invalid distances
while (c->len)
{
NEEDOUT
OUTBYTE(*f++)
if (f == s->end)
f = s->window;
c->len--;
}
c->mode = START;
break;
case LIT: // o: got literal, waiting for output space
NEEDOUT
OUTBYTE(c->sub.lit)
c->mode = START;
break;
case WASH: // o: got eob, possibly more output
if (k > 7) // return unused byte, if any
{
//Assert(k < 16, "inflate_codes grabbed too many bytes")
k -= 8;
n++;
p--; // can always return one
}
FLUSH
if (s->read != s->write)
LEAVE
c->mode = END;
case END:
r = Z_STREAM_END;
LEAVE
case BADCODE: // x: got error
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
}
void inflate_codes_free(inflate_codes_statef *c,z_streamp z)
{ ZFREE(z, c);
LuTracev((stderr, "inflate: codes free\n"));
}
// infblock.c -- interpret and process block types to last block
// Copyright (C) 1995-1998 Mark Adler
// For conditions of distribution and use, see copyright notice in zlib.h
//struct inflate_codes_state {int dummy;}; // for buggy compilers
// Table for deflate from PKZIP's appnote.txt.
const uInt border[] = { // Order of the bit length code lengths
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
//
// Notes beyond the 1.93a appnote.txt:
//
// 1. Distance pointers never point before the beginning of the output stream.
// 2. Distance pointers can point back across blocks, up to 32k away.
// 3. There is an implied maximum of 7 bits for the bit length table and
// 15 bits for the actual data.
// 4. If only one code exists, then it is encoded using one bit. (Zero
// would be more efficient, but perhaps a little confusing.) If two
// codes exist, they are coded using one bit each (0 and 1).
// 5. There is no way of sending zero distance codes--a dummy must be
// sent if there are none. (History: a pre 2.0 version of PKZIP would
// store blocks with no distance codes, but this was discovered to be
// too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
// zero distance codes, which is sent as one code of zero bits in
// length.
// 6. There are up to 286 literal/length codes. Code 256 represents the
// end-of-block. Note however that the static length tree defines
// 288 codes just to fill out the Huffman codes. Codes 286 and 287
// cannot be used though, since there is no length base or extra bits
// defined for them. Similarily, there are up to 30 distance codes.
// However, static trees define 32 codes (all 5 bits) to fill out the
// Huffman codes, but the last two had better not show up in the data.
// 7. Unzip can check dynamic Huffman blocks for complete code sets.
// The exception is that a single code would not be complete (see #4).
// 8. The five bits following the block type is really the number of
// literal codes sent minus 257.
// 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
// (1+6+6). Therefore, to output three times the length, you output
// three codes (1+1+1), whereas to output four times the same length,
// you only need two codes (1+3). Hmm.
//10. In the tree reconstruction algorithm, Code = Code + Increment
// only if BitLength(i) is not zero. (Pretty obvious.)
//11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
//12. Note: length code 284 can represent 227-258, but length code 285
// really is 258. The last length deserves its own, short code
// since it gets used a lot in very redundant files. The length
// 258 is special since 258 - 3 (the min match length) is 255.
//13. The literal/length and distance code bit lengths are read as a
// single stream of lengths. It is possible (and advantageous) for
// a repeat code (16, 17, or 18) to go across the boundary between
// the two sets of lengths.
void inflate_blocks_reset(inflate_blocks_statef *s, z_streamp z, uLong *c)
{
if (c != Z_NULL)
*c = s->check;
if (s->mode == IBM_BTREE || s->mode == IBM_DTREE)
ZFREE(z, s->sub.trees.blens);
if (s->mode == IBM_CODES)
inflate_codes_free(s->sub.decode.codes, z);
s->mode = IBM_TYPE;
s->bitk = 0;
s->bitb = 0;
s->read = s->write = s->window;
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(0L, (const Byte *)Z_NULL, 0);
LuTracev((stderr, "inflate: blocks reset\n"));
}
inflate_blocks_statef *inflate_blocks_new(z_streamp z, check_func c, uInt w)
{
inflate_blocks_statef *s;
if ((s = (inflate_blocks_statef *)ZALLOC
(z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
return s;
if ((s->hufts =
(inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
{
ZFREE(z, s);
return Z_NULL;
}
if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL)
{
ZFREE(z, s->hufts);
ZFREE(z, s);
return Z_NULL;
}
s->end = s->window + w;
s->checkfn = c;
s->mode = IBM_TYPE;
LuTracev((stderr, "inflate: blocks allocated\n"));
inflate_blocks_reset(s, z, Z_NULL);
return s;
}
int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r)
{
uInt t; // temporary storage
uLong b; // bit buffer
uInt k; // bits in bit buffer
Byte *p; // input data pointer
uInt n; // bytes available there
Byte *q; // output window write pointer
uInt m; // bytes to end of window or read pointer
// copy input/output information to locals (UPDATE macro restores)
LOAD
// process input based on current state
for(;;) switch (s->mode)
{
case IBM_TYPE:
NEEDBITS(3)
t = (uInt)b & 7;
s->last = t & 1;
switch (t >> 1)
{
case 0: // stored
LuTracev((stderr, "inflate: stored block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
t = k & 7; // go to byte boundary
DUMPBITS(t)
s->mode = IBM_LENS; // get length of stored block
break;
case 1: // fixed
LuTracev((stderr, "inflate: fixed codes block%s\n",
s->last ? " (last)" : ""));
{
uInt bl, bd;
const inflate_huft *tl, *td;
inflate_trees_fixed(&bl, &bd, &tl, &td, z);
s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
if (s->sub.decode.codes == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
}
DUMPBITS(3)
s->mode = IBM_CODES;
break;
case 2: // dynamic
LuTracev((stderr, "inflate: dynamic codes block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
s->mode = IBM_TABLE;
break;
case 3: // illegal
DUMPBITS(3)
s->mode = IBM_BAD;
z->msg = (char*)"invalid block type";
r = Z_DATA_ERROR;
LEAVE
}
break;
case IBM_LENS:
NEEDBITS(32)
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
{
s->mode = IBM_BAD;
z->msg = (char*)"invalid stored block lengths";
r = Z_DATA_ERROR;
LEAVE
}
s->sub.left = (uInt)b & 0xffff;
b = k = 0; // dump bits
LuTracev((stderr, "inflate: stored length %u\n", s->sub.left));
s->mode = s->sub.left ? IBM_STORED : (s->last ? IBM_DRY : IBM_TYPE);
break;
case IBM_STORED:
if (n == 0)
LEAVE
NEEDOUT
t = s->sub.left;
if (t > n) t = n;
if (t > m) t = m;
memcpy(q, p, t);
p += t; n -= t;
q += t; m -= t;
if ((s->sub.left -= t) != 0)
break;
LuTracev((stderr, "inflate: stored end, %lu total out\n",
z->total_out + (q >= s->read ? q - s->read :
(s->end - s->read) + (q - s->window))));
s->mode = s->last ? IBM_DRY : IBM_TYPE;
break;
case IBM_TABLE:
NEEDBITS(14)
s->sub.trees.table = t = (uInt)b & 0x3fff;
// remove this section to workaround bug in pkzip
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
{
s->mode = IBM_BAD;
z->msg = (char*)"too many length or distance symbols";
r = Z_DATA_ERROR;
LEAVE
}
// end remove
t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
DUMPBITS(14)
s->sub.trees.index = 0;
LuTracev((stderr, "inflate: table sizes ok\n"));
s->mode = IBM_BTREE;
case IBM_BTREE:
while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
{
NEEDBITS(3)
s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
DUMPBITS(3)
}
while (s->sub.trees.index < 19)
s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
s->sub.trees.bb = 7;
t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
&s->sub.trees.tb, s->hufts, z);
if (t != Z_OK)
{
r = t;
if (r == Z_DATA_ERROR)
{
ZFREE(z, s->sub.trees.blens);
s->mode = IBM_BAD;
}
LEAVE
}
s->sub.trees.index = 0;
LuTracev((stderr, "inflate: bits tree ok\n"));
s->mode = IBM_DTREE;
case IBM_DTREE:
while (t = s->sub.trees.table,
s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
{
inflate_huft *h;
uInt i, j, c;
t = s->sub.trees.bb;
NEEDBITS(t)
h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
t = h->bits;
c = h->base;
if (c < 16)
{
DUMPBITS(t)
s->sub.trees.blens[s->sub.trees.index++] = c;
}
else // c == 16..18
{
i = c == 18 ? 7 : c - 14;
j = c == 18 ? 11 : 3;
NEEDBITS(t + i)
DUMPBITS(t)
j += (uInt)b & inflate_mask[i];
DUMPBITS(i)
i = s->sub.trees.index;
t = s->sub.trees.table;
if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
(c == 16 && i < 1))
{
ZFREE(z, s->sub.trees.blens);
s->mode = IBM_BAD;
z->msg = (char*)"invalid bit length repeat";
r = Z_DATA_ERROR;
LEAVE
}
c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
do {
s->sub.trees.blens[i++] = c;
} while (--j);
s->sub.trees.index = i;
}
}
s->sub.trees.tb = Z_NULL;
{
uInt bl, bd;
inflate_huft *tl, *td;
inflate_codes_statef *c;
bl = 9; // must be <= 9 for lookahead assumptions
bd = 6; // must be <= 9 for lookahead assumptions
t = s->sub.trees.table;
t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
s->sub.trees.blens, &bl, &bd, &tl, &td,
s->hufts, z);
if (t != Z_OK)
{
if (t == (uInt)Z_DATA_ERROR)
{
ZFREE(z, s->sub.trees.blens);
s->mode = IBM_BAD;
}
r = t;
LEAVE
}
LuTracev((stderr, "inflate: trees ok\n"));
if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
s->sub.decode.codes = c;
}
ZFREE(z, s->sub.trees.blens);
s->mode = IBM_CODES;
case IBM_CODES:
UPDATE
if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
return inflate_flush(s, z, r);
r = Z_OK;
inflate_codes_free(s->sub.decode.codes, z);
LOAD
LuTracev((stderr, "inflate: codes end, %lu total out\n",
z->total_out + (q >= s->read ? q - s->read :
(s->end - s->read) + (q - s->window))));
if (!s->last)
{
s->mode = IBM_TYPE;
break;
}
s->mode = IBM_DRY;
case IBM_DRY:
FLUSH
if (s->read != s->write)
LEAVE
s->mode = IBM_DONE;
case IBM_DONE:
r = Z_STREAM_END;
LEAVE
case IBM_BAD:
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
}
int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z)
{
inflate_blocks_reset(s, z, Z_NULL);
ZFREE(z, s->window);
ZFREE(z, s->hufts);
ZFREE(z, s);
LuTracev((stderr, "inflate: blocks freed\n"));
return Z_OK;
}
// inftrees.c -- generate Huffman trees for efficient decoding
// Copyright (C) 1995-1998 Mark Adler
// For conditions of distribution and use, see copyright notice in zlib.h
//
extern const char inflate_copyright[] =
" inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
// If you use the zlib library in a product, an acknowledgment is welcome
// in the documentation of your product. If for some reason you cannot
// include such an acknowledgment, I would appreciate that you keep this
// copyright string in the executable of your product.
int huft_build (
uInt *, // code lengths in bits
uInt, // number of codes
uInt, // number of "simple" codes
const uInt *, // list of base values for non-simple codes
const uInt *, // list of extra bits for non-simple codes
inflate_huft **,// result: starting table
uInt *, // maximum lookup bits (returns actual)
inflate_huft *, // space for trees
uInt *, // hufts used in space
uInt * ); // space for values
// Tables for deflate from PKZIP's appnote.txt.
const uInt cplens[31] = { // Copy lengths for literal codes 257..285
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
// see note #13 above about 258
const uInt cplext[31] = { // Extra bits for literal codes 257..285
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; // 112==invalid
const uInt cpdist[30] = { // Copy offsets for distance codes 0..29
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
const uInt cpdext[30] = { // Extra bits for distance codes
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
//
// Huffman code decoding is performed using a multi-level table lookup.
// The fastest way to decode is to simply build a lookup table whose
// size is determined by the longest code. However, the time it takes
// to build this table can also be a factor if the data being decoded
// is not very long. The most common codes are necessarily the
// shortest codes, so those codes dominate the decoding time, and hence
// the speed. The idea is you can have a shorter table that decodes the
// shorter, more probable codes, and then point to subsidiary tables for
// the longer codes. The time it costs to decode the longer codes is
// then traded against the time it takes to make longer tables.
//
// This results of this trade are in the variables lbits and dbits
// below. lbits is the number of bits the first level table for literal/
// length codes can decode in one step, and dbits is the same thing for
// the distance codes. Subsequent tables are also less than or equal to
// those sizes. These values may be adjusted either when all of the
// codes are shorter than that, in which case the longest code length in
// bits is used, or when the shortest code is *longer* than the requested
// table size, in which case the length of the shortest code in bits is
// used.
//
// There are two different values for the two tables, since they code a
// different number of possibilities each. The literal/length table
// codes 286 possible values, or in a flat code, a little over eight
// bits. The distance table codes 30 possible values, or a little less
// than five bits, flat. The optimum values for speed end up being
// about one bit more than those, so lbits is 8+1 and dbits is 5+1.
// The optimum values may differ though from machine to machine, and
// possibly even between compilers. Your mileage may vary.
//
// If BMAX needs to be larger than 16, then h and x[] should be uLong.
#define BMAX 15 // maximum bit length of any code
int huft_build(
uInt *b, // code lengths in bits (all assumed <= BMAX)
uInt n, // number of codes (assumed <= 288)
uInt s, // number of simple-valued codes (0..s-1)
const uInt *d, // list of base values for non-simple codes
const uInt *e, // list of extra bits for non-simple codes
inflate_huft * *t, // result: starting table
uInt *m, // maximum lookup bits, returns actual
inflate_huft *hp, // space for trees
uInt *hn, // hufts used in space
uInt *v) // working area: values in order of bit length
// Given a list of code lengths and a maximum table size, make a set of
// tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
// if the given code set is incomplete (the tables are still built in this
// case), or Z_DATA_ERROR if the input is invalid.
{
uInt a; // counter for codes of length k
uInt c[BMAX+1]; // bit length count table
uInt f; // i repeats in table every f entries
int g; // maximum code length
int h; // table level
register uInt i; // counter, current code
register uInt j; // counter
register int k; // number of bits in current code
int l; // bits per table (returned in m)
uInt mask; // (1 << w) - 1, to avoid cc -O bug on HP
register uInt *p; // pointer into c[], b[], or v[]
inflate_huft *q; // points to current table
struct inflate_huft_s r; // table entry for structure assignment
inflate_huft *u[BMAX]; // table stack
register int w; // bits before this table == (l * h)
uInt x[BMAX+1]; // bit offsets, then code stack
uInt *xp; // pointer into x
int y; // number of dummy codes added
uInt z; // number of entries in current table
// Generate counts for each bit length
p = c;
#define C0 *p++ = 0;
#define C2 C0 C0 C0 C0
#define C4 C2 C2 C2 C2
C4; p; // clear c[]--assume BMAX+1 is 16
p = b; i = n;
do {
c[*p++]++; // assume all entries <= BMAX
} while (--i);
if (c[0] == n) // null input--all zero length codes
{
*t = (inflate_huft *)Z_NULL;
*m = 0;
return Z_OK;
}
// Find minimum and maximum length, bound *m by those
l = *m;
for (j = 1; j <= BMAX; j++)
if (c[j])
break;
k = j; // minimum code length
if ((uInt)l < j)
l = j;
for (i = BMAX; i; i--)
if (c[i])
break;
g = i; // maximum code length
if ((uInt)l > i)
l = i;
*m = l;
// Adjust last length count to fill out codes, if needed
for (y = 1 << j; j < i; j++, y <<= 1)
if ((y -= c[j]) < 0)
return Z_DATA_ERROR;
if ((y -= c[i]) < 0)
return Z_DATA_ERROR;
c[i] += y;
// Generate starting offsets into the value table for each length
x[1] = j = 0;
p = c + 1; xp = x + 2;
while (--i) { // note that i == g from above
*xp++ = (j += *p++);
}
// Make a table of values in order of bit lengths
p = b; i = 0;
do {
if ((j = *p++) != 0)
v[x[j]++] = i;
} while (++i < n);
n = x[g]; // set n to length of v
// Generate the Huffman codes and for each, make the table entries
x[0] = i = 0; // first Huffman code is zero
p = v; // grab values in bit order
h = -1; // no tables yet--level -1
w = -l; // bits decoded == (l * h)
u[0] = (inflate_huft *)Z_NULL; // just to keep compilers happy
q = (inflate_huft *)Z_NULL; // ditto
z = 0; // ditto
// go through the bit lengths (k already is bits in shortest code)
for (; k <= g; k++)
{
a = c[k];
while (a--)
{
// here i is the Huffman code of length k bits for value *p
// make tables up to required level
while (k > w + l)
{
h++;
w += l; // previous table always l bits
// compute minimum size table less than or equal to l bits
z = g - w;
z = z > (uInt)l ? l : z; // table size upper limit
if ((f = 1 << (j = k - w)) > a + 1) // try a k-w bit table
{ // too few codes for k-w bit table
f -= a + 1; // deduct codes from patterns left
xp = c + k;
if (j < z)
while (++j < z) // try smaller tables up to z bits
{
if ((f <<= 1) <= *++xp)
break; // enough codes to use up j bits
f -= *xp; // else deduct codes from patterns
}
}
z = 1 << j; // table entries for j-bit table
// allocate new table
if (*hn + z > MANY) // (note: doesn't matter for fixed)
return Z_DATA_ERROR; // overflow of MANY
u[h] = q = hp + *hn;
*hn += z;
// connect to last table, if there is one
if (h)
{
x[h] = i; // save pattern for backing up
r.bits = (Byte)l; // bits to dump before this table
r.exop = (Byte)j; // bits in this table
j = i >> (w - l);
r.base = (uInt)(q - u[h-1] - j); // offset to this table
u[h-1][j] = r; // connect to last table
}
else
*t = q; // first table is returned result
}
// set up table entry in r
r.bits = (Byte)(k - w);
if (p >= v + n)
r.exop = 128 + 64; // out of values--invalid code
else if (*p < s)
{
r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); // 256 is end-of-block
r.base = *p++; // simple code is just the value
}
else
{
r.exop = (Byte)(e[*p - s] + 16 + 64);// non-simple--look up in lists
r.base = d[*p++ - s];
}
// fill code-like entries with r
f = 1 << (k - w);
for (j = i >> w; j < z; j += f)
q[j] = r;
// backwards increment the k-bit code i
for (j = 1 << (k - 1); i & j; j >>= 1)
i ^= j;
i ^= j;
// backup over finished tables
mask = (1 << w) - 1; // needed on HP, cc -O bug
while ((i & mask) != x[h])
{
h--; // don't need to update q
w -= l;
mask = (1 << w) - 1;
}
}
}
// Return Z_BUF_ERROR if we were given an incomplete table
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
}
int inflate_trees_bits(
uInt *c, // 19 code lengths
uInt *bb, // bits tree desired/actual depth
inflate_huft * *tb, // bits tree result
inflate_huft *hp, // space for trees
z_streamp z) // for messages
{
int r;
uInt hn = 0; // hufts used in space
uInt *v; // work area for huft_build
if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL,
tb, bb, hp, &hn, v);
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed dynamic bit lengths tree";
else if (r == Z_BUF_ERROR || *bb == 0)
{
z->msg = (char*)"incomplete dynamic bit lengths tree";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
}
int inflate_trees_dynamic(
uInt nl, // number of literal/length codes
uInt nd, // number of distance codes
uInt *c, // that many (total) code lengths
uInt *bl, // literal desired/actual bit depth
uInt *bd, // distance desired/actual bit depth
inflate_huft * *tl, // literal/length tree result
inflate_huft * *td, // distance tree result
inflate_huft *hp, // space for trees
z_streamp z) // for messages
{
int r;
uInt hn = 0; // hufts used in space
uInt *v; // work area for huft_build
// allocate work area
if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
// build literal/length tree
r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
if (r != Z_OK || *bl == 0)
{
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed literal/length tree";
else if (r != Z_MEM_ERROR)
{
z->msg = (char*)"incomplete literal/length tree";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
}
// build distance tree
r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
if (r != Z_OK || (*bd == 0 && nl > 257))
{
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed distance tree";
else if (r == Z_BUF_ERROR) {
z->msg = (char*)"incomplete distance tree";
r = Z_DATA_ERROR;
}
else if (r != Z_MEM_ERROR)
{
z->msg = (char*)"empty distance tree with lengths";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
}
// done
ZFREE(z, v);
return Z_OK;
}
int inflate_trees_fixed(
uInt *bl, // literal desired/actual bit depth
uInt *bd, // distance desired/actual bit depth
const inflate_huft * * tl, // literal/length tree result
const inflate_huft * *td, // distance tree result
z_streamp ) // for memory allocation
{
*bl = fixed_bl;
*bd = fixed_bd;
*tl = fixed_tl;
*td = fixed_td;
return Z_OK;
}
// inffast.c -- process literals and length/distance pairs fast
// Copyright (C) 1995-1998 Mark Adler
// For conditions of distribution and use, see copyright notice in zlib.h
//
//struct inflate_codes_state {int dummy;}; // for buggy compilers
// macros for bit input with no checking and for returning unused bytes
#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;}
// Called with number of bytes left to write in window at least 258
// (the maximum string length) and number of input bytes available
// at least ten. The ten bytes are six bytes for the longest length/
// distance pair plus four bytes for overloading the bit buffer.
int inflate_fast(
uInt bl, uInt bd,
const inflate_huft *tl,
const inflate_huft *td, // need separate declaration for Borland C++
inflate_blocks_statef *s,
z_streamp z)
{
const inflate_huft *t; // temporary pointer
uInt e; // extra bits or operation
uLong b; // bit buffer
uInt k; // bits in bit buffer
Byte *p; // input data pointer
uInt n; // bytes available there
Byte *q; // output window write pointer
uInt m; // bytes to end of window or read pointer
uInt ml; // mask for literal/length tree
uInt md; // mask for distance tree
uInt c; // bytes to copy
uInt d; // distance back to copy from
Byte *r; // copy source pointer
// load input, output, bit values
LOAD
// initialize masks
ml = inflate_mask[bl];
md = inflate_mask[bd];
// do until not enough input or output space for fast loop
do { // assume called with m >= 258 && n >= 10
// get literal/length code
GRABBITS(20) // max bits for literal/length code
if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
{
DUMPBITS(t->bits)
LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
*q++ = (Byte)t->base;
m--;
continue;
}
for (;;) {
DUMPBITS(t->bits)
if (e & 16)
{
// get extra bits for length
e &= 15;
c = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
LuTracevv((stderr, "inflate: * length %u\n", c));
// decode distance base of block to copy
GRABBITS(15); // max bits for distance code
e = (t = td + ((uInt)b & md))->exop;
for (;;) {
DUMPBITS(t->bits)
if (e & 16)
{
// get extra bits to add to distance base
e &= 15;
GRABBITS(e) // get extra bits (up to 13)
d = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
LuTracevv((stderr, "inflate: * distance %u\n", d));
// do the copy
m -= c;
r = q - d;
if (r < s->window) // wrap if needed
{
do {
r += s->end - s->window; // force pointer in window
} while (r < s->window); // covers invalid distances
e = (uInt) (s->end - r);
if (c > e)
{
c -= e; // wrapped copy
do {
*q++ = *r++;
} while (--e);
r = s->window;
do {
*q++ = *r++;
} while (--c);
}
else // normal copy
{
*q++ = *r++; c--;
*q++ = *r++; c--;
do {
*q++ = *r++;
} while (--c);
}
}
else /* normal copy */
{
*q++ = *r++; c--;
*q++ = *r++; c--;
do {
*q++ = *r++;
} while (--c);
}
break;
}
else if ((e & 64) == 0)
{
t += t->base;
e = (t += ((uInt)b & inflate_mask[e]))->exop;
}
else
{
z->msg = (char*)"invalid distance code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
};
break;
}
if ((e & 64) == 0)
{
t += t->base;
if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
{
DUMPBITS(t->bits)
LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
*q++ = (Byte)t->base;
m--;
break;
}
}
else if (e & 32)
{
LuTracevv((stderr, "inflate: * end of block\n"));
UNGRAB
UPDATE
return Z_STREAM_END;
}
else
{
z->msg = (char*)"invalid literal/length code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
};
} while (m >= 258 && n >= 10);
// not enough input or output--restore pointers and return
UNGRAB
UPDATE
return Z_OK;
}
// crc32.c -- compute the CRC-32 of a data stream
// Copyright (C) 1995-1998 Mark Adler
// For conditions of distribution and use, see copyright notice in zlib.h
// @(#) $Id$
// Table of CRC-32's of all single-byte values (made by make_crc_table)
const uLong crc_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
const uLong * get_crc_table()
{ return (const uLong *)crc_table;
}
#define CRC_DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define CRC_DO2(buf) CRC_DO1(buf); CRC_DO1(buf);
#define CRC_DO4(buf) CRC_DO2(buf); CRC_DO2(buf);
#define CRC_DO8(buf) CRC_DO4(buf); CRC_DO4(buf);
uLong ucrc32(uLong crc, const Byte *buf, uInt len)
{ if (buf == Z_NULL) return 0L;
crc = crc ^ 0xffffffffL;
while (len >= 8) {CRC_DO8(buf); len -= 8;}
if (len) do {CRC_DO1(buf);} while (--len);
return crc ^ 0xffffffffL;
}
// =============================================================
// some decryption routines
#define CRC32(c, b) (crc_table[((int)(c)^(b))&0xff]^((c)>>8))
void Uupdate_keys(unsigned long *keys, char c)
{ keys[0] = CRC32(keys[0],c);
keys[1] += keys[0] & 0xFF;
keys[1] = keys[1]*134775813L +1;
keys[2] = CRC32(keys[2], keys[1] >> 24);
}
char Udecrypt_byte(unsigned long *keys)
{ unsigned temp = ((unsigned)keys[2] & 0xffff) | 2;
return (char)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
char zdecode(unsigned long *keys, char c)
{ c^=Udecrypt_byte(keys);
Uupdate_keys(keys,c);
return c;
}
// adler32.c -- compute the Adler-32 checksum of a data stream
// Copyright (C) 1995-1998 Mark Adler
// For conditions of distribution and use, see copyright notice in zlib.h
// @(#) $Id$
#define BASE 65521L // largest prime smaller than 65536
#define NMAX 5552
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
#define AD_DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define AD_DO2(buf,i) AD_DO1(buf,i); AD_DO1(buf,i+1);
#define AD_DO4(buf,i) AD_DO2(buf,i); AD_DO2(buf,i+2);
#define AD_DO8(buf,i) AD_DO4(buf,i); AD_DO4(buf,i+4);
#define AD_DO16(buf) AD_DO8(buf,0); AD_DO8(buf,8);
// =========================================================================
uLong adler32(uLong adler, const Byte *buf, uInt len)
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff;
int k;
if (buf == Z_NULL) return 1L;
while (len > 0) {
k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16) {
AD_DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= BASE;
s2 %= BASE;
}
return (s2 << 16) | s1;
}
// zutil.c -- target dependent utility functions for the compression library
// Copyright (C) 1995-1998 Jean-loup Gailly.
// For conditions of distribution and use, see copyright notice in zlib.h
// @(#) $Id$
const char * zlibVersion()
{
return ZLIB_VERSION;
}
// exported to allow conversion of error code to string for compress() and
// uncompress()
const char * zError(int err)
{ return ERR_MSG(err);
}
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
if (opaque) items += size - size; // make compiler happy
return (voidpf)calloc(items, size);
}
void zcfree (voidpf opaque, voidpf ptr)
{
zfree(ptr);
if (opaque) return; // make compiler happy
}
// inflate.c -- zlib interface to inflate modules
// Copyright (C) 1995-1998 Mark Adler
// For conditions of distribution and use, see copyright notice in zlib.h
//struct inflate_blocks_state {int dummy;}; // for buggy compilers
typedef enum {
IM_METHOD, // waiting for method byte
IM_FLAG, // waiting for flag byte
IM_DICT4, // four dictionary check bytes to go
IM_DICT3, // three dictionary check bytes to go
IM_DICT2, // two dictionary check bytes to go
IM_DICT1, // one dictionary check byte to go
IM_DICT0, // waiting for inflateSetDictionary
IM_BLOCKS, // decompressing blocks
IM_CHECK4, // four check bytes to go
IM_CHECK3, // three check bytes to go
IM_CHECK2, // two check bytes to go
IM_CHECK1, // one check byte to go
IM_DONE, // finished check, done
IM_BAD} // got an error--stay here
inflate_mode;
// inflate private state
struct internal_state {
// mode
inflate_mode mode; // current inflate mode
// mode dependent information
union {
uInt method; // if IM_FLAGS, method byte
struct {
uLong was; // computed check value
uLong need; // stream check value
} check; // if CHECK, check values to compare
uInt marker; // if IM_BAD, inflateSync's marker bytes count
} sub; // submode
// mode independent information
int nowrap; // flag for no wrapper
uInt wbits; // log2(window size) (8..15, defaults to 15)
inflate_blocks_statef
*blocks; // current inflate_blocks state
};
int inflateReset(z_streamp z)
{
if (z == Z_NULL || z->state == Z_NULL)
return Z_STREAM_ERROR;
z->total_in = z->total_out = 0;
z->msg = Z_NULL;
z->state->mode = z->state->nowrap ? IM_BLOCKS : IM_METHOD;
inflate_blocks_reset(z->state->blocks, z, Z_NULL);
LuTracev((stderr, "inflate: reset\n"));
return Z_OK;
}
int inflateEnd(z_streamp z)
{
if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
return Z_STREAM_ERROR;
if (z->state->blocks != Z_NULL)
inflate_blocks_free(z->state->blocks, z);
ZFREE(z, z->state);
z->state = Z_NULL;
LuTracev((stderr, "inflate: end\n"));
return Z_OK;
}
int inflateInit2(z_streamp z)
{ const char *version = ZLIB_VERSION; int stream_size = sizeof(z_stream);
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != sizeof(z_stream)) return Z_VERSION_ERROR;
int w = -15; // MAX_WBITS: 32K LZ77 window.
// Warning: reducing MAX_WBITS makes minigzip unable to extract .gz files created by gzip.
// The memory requirements for deflate are (in bytes):
// (1 << (windowBits+2)) + (1 << (memLevel+9))
// that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
// plus a few kilobytes for small objects. For example, if you want to reduce
// the default memory requirements from 256K to 128K, compile with
// make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
// Of course this will generally degrade compression (there's no free lunch).
//
// The memory requirements for inflate are (in bytes) 1 << windowBits
// that is, 32K for windowBits=15 (default value) plus a few kilobytes
// for small objects.
// initialize state
if (z == Z_NULL) return Z_STREAM_ERROR;
z->msg = Z_NULL;
if (z->zalloc == Z_NULL)
{
z->zalloc = zcalloc;
z->opaque = (voidpf)0;
}
if (z->zfree == Z_NULL) z->zfree = zcfree;
if ((z->state = (struct internal_state *)
ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
return Z_MEM_ERROR;
z->state->blocks = Z_NULL;
// handle undocumented nowrap option (no zlib header or check)
z->state->nowrap = 0;
if (w < 0)
{
w = - w;
z->state->nowrap = 1;
}
// set window size
if (w < 8 || w > 15)
{
inflateEnd(z);
return Z_STREAM_ERROR;
}
z->state->wbits = (uInt)w;
// create inflate_blocks state
if ((z->state->blocks =
inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
== Z_NULL)
{
inflateEnd(z);
return Z_MEM_ERROR;
}
LuTracev((stderr, "inflate: allocated\n"));
// reset state
inflateReset(z);
return Z_OK;
}
#define IM_NEEDBYTE {if(z->avail_in==0)return r;r=f;}
#define IM_NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
int inflate(z_streamp z, int f)
{
int r;
uInt b;
if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
return Z_STREAM_ERROR;
f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
r = Z_BUF_ERROR;
for (;;) switch (z->state->mode)
{
case IM_METHOD:
IM_NEEDBYTE
if (((z->state->sub.method = IM_NEXTBYTE) & 0xf) != Z_DEFLATED)
{
z->state->mode = IM_BAD;
z->msg = (char*)"unknown compression method";
z->state->sub.marker = 5; // can't try inflateSync
break;
}
if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
{
z->state->mode = IM_BAD;
z->msg = (char*)"invalid window size";
z->state->sub.marker = 5; // can't try inflateSync
break;
}
z->state->mode = IM_FLAG;
case IM_FLAG:
IM_NEEDBYTE
b = IM_NEXTBYTE;
if (((z->state->sub.method << 8) + b) % 31)
{
z->state->mode = IM_BAD;
z->msg = (char*)"incorrect header check";
z->state->sub.marker = 5; // can't try inflateSync
break;
}
LuTracev((stderr, "inflate: zlib header ok\n"));
if (!(b & PRESET_DICT))
{
z->state->mode = IM_BLOCKS;
break;
}
z->state->mode = IM_DICT4;
case IM_DICT4:
IM_NEEDBYTE
z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24;
z->state->mode = IM_DICT3;
case IM_DICT3:
IM_NEEDBYTE
z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16;
z->state->mode = IM_DICT2;
case IM_DICT2:
IM_NEEDBYTE
z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8;
z->state->mode = IM_DICT1;
case IM_DICT1:
IM_NEEDBYTE; r;
z->state->sub.check.need += (uLong)IM_NEXTBYTE;
z->adler = z->state->sub.check.need;
z->state->mode = IM_DICT0;
return Z_NEED_DICT;
case IM_DICT0:
z->state->mode = IM_BAD;
z->msg = (char*)"need dictionary";
z->state->sub.marker = 0; // can try inflateSync
return Z_STREAM_ERROR;
case IM_BLOCKS:
r = inflate_blocks(z->state->blocks, z, r);
if (r == Z_DATA_ERROR)
{
z->state->mode = IM_BAD;
z->state->sub.marker = 0; // can try inflateSync
break;
}
if (r == Z_OK)
r = f;
if (r != Z_STREAM_END)
return r;
r = f;
inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
if (z->state->nowrap)
{
z->state->mode = IM_DONE;
break;
}
z->state->mode = IM_CHECK4;
case IM_CHECK4:
IM_NEEDBYTE
z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24;
z->state->mode = IM_CHECK3;
case IM_CHECK3:
IM_NEEDBYTE
z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16;
z->state->mode = IM_CHECK2;
case IM_CHECK2:
IM_NEEDBYTE
z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8;
z->state->mode = IM_CHECK1;
case IM_CHECK1:
IM_NEEDBYTE
z->state->sub.check.need += (uLong)IM_NEXTBYTE;
if (z->state->sub.check.was != z->state->sub.check.need)
{
z->state->mode = IM_BAD;
z->msg = (char*)"incorrect data check";
z->state->sub.marker = 5; // can't try inflateSync
break;
}
LuTracev((stderr, "inflate: zlib check ok\n"));
z->state->mode = IM_DONE;
case IM_DONE:
return Z_STREAM_END;
case IM_BAD:
return Z_DATA_ERROR;
default:
return Z_STREAM_ERROR;
}
}
// unzip.c -- IO on .zip files using zlib
// Version 0.15 beta, Mar 19th, 1998,
// Read unzip.h for more info
#define UNZ_BUFSIZE (16384)
#define UNZ_MAXFILENAMEINZIP (256)
#define SIZECENTRALDIRITEM (0x2e)
#define SIZEZIPLOCALHEADER (0x1e)
const char unz_copyright[] = " unzip 0.15 Copyright 1998 Gilles Vollant ";
// unz_file_info_interntal contain internal info about a file in zipfile
typedef struct unz_file_info_internal_s
{
uLong offset_curfile;// relative offset of local header 4 bytes
} unz_file_info_internal;
typedef struct
{ bool is_handle; // either a handle or memory
bool canseek;
// for handles:
HANDLE h; bool herr; unsigned long initial_offset; bool mustclosehandle;
// for memory:
void *buf; unsigned int len,pos; // if it's a memory block
} LUFILE;
LUFILE *lufopen(void *z,unsigned int len,DWORD flags,ZRESULT *err)
{ if (flags!=ZIP_HANDLE && flags!=ZIP_FILENAME && flags!=ZIP_MEMORY) {*err=ZR_ARGS; return NULL;}
//
HANDLE h=0; bool canseek=false; *err=ZR_OK;
bool mustclosehandle=false;
if (flags==ZIP_HANDLE||flags==ZIP_FILENAME)
{ if (flags==ZIP_HANDLE)
{ HANDLE hf = z;
h=hf; mustclosehandle=false;
#ifdef DuplicateHandle
BOOL res = DuplicateHandle(GetCurrentProcess(),hf,GetCurrentProcess(),&h,0,FALSE,DUPLICATE_SAME_ACCESS);
if (!res) mustclosehandle=true;
#endif
}
else
{ h=CreateFile((const TCHAR*)z,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (h==INVALID_HANDLE_VALUE) {*err=ZR_NOFILE; return NULL;}
mustclosehandle=true;
}
// test if we can seek on it. We can't use GetFileType(h)==FILE_TYPE_DISK since it's not on CE.
DWORD res = SetFilePointer(h,0,0,FILE_CURRENT);
canseek = (res!=0xFFFFFFFF);
}
LUFILE *lf = new LUFILE;
if (flags==ZIP_HANDLE||flags==ZIP_FILENAME)
{ lf->is_handle=true; lf->mustclosehandle=mustclosehandle;
lf->canseek=canseek;
lf->h=h; lf->herr=false;
lf->initial_offset=0;
if (canseek) lf->initial_offset = SetFilePointer(h,0,NULL,FILE_CURRENT);
}
else
{ lf->is_handle=false;
lf->canseek=true;
lf->mustclosehandle=false;
lf->buf=z; lf->len=len; lf->pos=0; lf->initial_offset=0;
}
*err=ZR_OK;
return lf;
}
int lufclose(LUFILE *stream)
{ if (stream==NULL) return EOF;
if (stream->mustclosehandle) CloseHandle(stream->h);
delete stream;
return 0;
}
int luferror(LUFILE *stream)
{ if (stream->is_handle && stream->herr) return 1;
else return 0;
}
long int luftell(LUFILE *stream)
{ if (stream->is_handle && stream->canseek) return SetFilePointer(stream->h,0,NULL,FILE_CURRENT)-stream->initial_offset;
else if (stream->is_handle) return 0;
else return stream->pos;
}
int lufseek(LUFILE *stream, long offset, int whence)
{ if (stream->is_handle && stream->canseek)
{ if (whence==SEEK_SET) SetFilePointer(stream->h,stream->initial_offset+offset,0,FILE_BEGIN);
else if (whence==SEEK_CUR) SetFilePointer(stream->h,offset,NULL,FILE_CURRENT);
else if (whence==SEEK_END) SetFilePointer(stream->h,offset,NULL,FILE_END);
else return 19; // EINVAL
return 0;
}
else if (stream->is_handle) return 29; // ESPIPE
else
{ if (whence==SEEK_SET) stream->pos=offset;
else if (whence==SEEK_CUR) stream->pos+=offset;
else if (whence==SEEK_END) stream->pos=stream->len+offset;
return 0;
}
}
size_t lufread(void *ptr,size_t size,size_t n,LUFILE *stream)
{ unsigned int toread = (unsigned int)(size*n);
if (stream->is_handle)
{ DWORD red; BOOL res = ReadFile(stream->h,ptr,toread,&red,NULL);
if (!res) stream->herr=true;
return red/size;
}
if (stream->pos+toread > stream->len) toread = stream->len-stream->pos;
memcpy(ptr, (char*)stream->buf + stream->pos, toread); DWORD red = toread;
stream->pos += red;
return red/size;
}
// file_in_zip_read_info_s contain internal information about a file in zipfile,
// when reading and decompress it
typedef struct
{
char *read_buffer; // internal buffer for compressed data
z_stream stream; // zLib stream structure for inflate
uLong pos_in_zipfile; // position in byte on the zipfile, for fseek
uLong stream_initialised; // flag set if stream structure is initialised
uLong offset_local_extrafield;// offset of the local extra field
uInt size_local_extrafield;// size of the local extra field
uLong pos_local_extrafield; // position in the local extra field in read
uLong crc32; // crc32 of all data uncompressed
uLong crc32_wait; // crc32 we must obtain after decompress all
uLong rest_read_compressed; // number of byte to be decompressed
uLong rest_read_uncompressed;//number of byte to be obtained after decomp
LUFILE* file; // io structore of the zipfile
uLong compression_method; // compression method (0==store)
uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx)
bool encrypted; // is it encrypted?
unsigned long keys[3]; // decryption keys, initialized by unzOpenCurrentFile
int encheadleft; // the first call(s) to unzReadCurrentFile will read this many encryption-header bytes first
char crcenctest; // if encrypted, we'll check the encryption buffer against this
} file_in_zip_read_info_s;
// unz_s contain internal information about the zipfile
typedef struct
{
LUFILE* file; // io structore of the zipfile
unz_global_info gi; // public global information
uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx)
uLong num_file; // number of the current file in the zipfile
uLong pos_in_central_dir; // pos of the current file in the central dir
uLong current_file_ok; // flag about the usability of the current file
uLong central_pos; // position of the beginning of the central dir
uLong size_central_dir; // size of the central directory
uLong offset_central_dir; // offset of start of central directory with respect to the starting disk number
unz_file_info cur_file_info; // public info about the current file in zip
unz_file_info_internal cur_file_info_internal; // private info about it
file_in_zip_read_info_s* pfile_in_zip_read; // structure about the current file if we are decompressing it
} unz_s, *unzFile;
int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity);
// Compare two filename (fileName1,fileName2).
z_off_t unztell (unzFile file);
// Give the current position in uncompressed data
int unzeof (unzFile file);
// return 1 if the end of file was reached, 0 elsewhere
int unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len);
// Read extra field from the current file (opened by unzOpenCurrentFile)
// This is the local-header version of the extra field (sometimes, there is
// more info in the local-header version than in the central-header)
//
// if buf==NULL, it return the size of the local extra field
//
// if buf!=NULL, len is the size of the buffer, the extra header is copied in
// buf.
// the return value is the number of bytes copied in buf, or (if <0)
// the error code
// ===========================================================================
// Read a byte from a gz_stream; update next_in and avail_in. Return EOF
// for end of file.
// IN assertion: the stream s has been sucessfully opened for reading.
int unzlocal_getByte(LUFILE *fin,int *pi)
{ unsigned char c;
int err = (int)lufread(&c, 1, 1, fin);
if (err==1)
{ *pi = (int)c;
return UNZ_OK;
}
else
{ if (luferror(fin)) return UNZ_ERRNO;
else return UNZ_EOF;
}
}
// ===========================================================================
// Reads a long in LSB order from the given gz_stream. Sets
int unzlocal_getShort (LUFILE *fin,uLong *pX)
{
uLong x ;
int i;
int err;
err = unzlocal_getByte(fin,&i);
x = (uLong)i;
if (err==UNZ_OK)
err = unzlocal_getByte(fin,&i);
x += ((uLong)i)<<8;
if (err==UNZ_OK)
*pX = x;
else
*pX = 0;
return err;
}
int unzlocal_getLong (LUFILE *fin,uLong *pX)
{
uLong x ;
int i;
int err;
err = unzlocal_getByte(fin,&i);
x = (uLong)i;
if (err==UNZ_OK)
err = unzlocal_getByte(fin,&i);
x += ((uLong)i)<<8;
if (err==UNZ_OK)
err = unzlocal_getByte(fin,&i);
x += ((uLong)i)<<16;
if (err==UNZ_OK)
err = unzlocal_getByte(fin,&i);
x += ((uLong)i)<<24;
if (err==UNZ_OK)
*pX = x;
else
*pX = 0;
return err;
}
// My own strcmpi / strcasecmp
int strcmpcasenosensitive_internal (const char* fileName1,const char *fileName2)
{
for (;;)
{
char c1=*(fileName1++);
char c2=*(fileName2++);
if ((c1>='a') && (c1<='z'))
c1 -= (char)0x20;
if ((c2>='a') && (c2<='z'))
c2 -= (char)0x20;
if (c1=='\0')
return ((c2=='\0') ? 0 : -1);
if (c2=='\0')
return 1;
if (c1c2)
return 1;
}
}
//
// Compare two filename (fileName1,fileName2).
// If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
// If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp)
//
int unzStringFileNameCompare (const char*fileName1,const char*fileName2,int iCaseSensitivity)
{ if (iCaseSensitivity==1) return strcmp(fileName1,fileName2);
else return strcmpcasenosensitive_internal(fileName1,fileName2);
}
#define BUFREADCOMMENT (0x400)
// Locate the Central directory of a zipfile (at the end, just before
// the global comment). Lu bugfix 2005.07.26 - returns 0xFFFFFFFF if not found,
// rather than 0, since 0 is a valid central-dir-location for an empty zipfile.
uLong unzlocal_SearchCentralDir(LUFILE *fin)
{ if (lufseek(fin,0,SEEK_END) != 0) return 0xFFFFFFFF;
uLong uSizeFile = luftell(fin);
uLong uMaxBack=0xffff; // maximum size of global comment
if (uMaxBack>uSizeFile) uMaxBack = uSizeFile;
unsigned char *buf = (unsigned char*)zmalloc(BUFREADCOMMENT+4);
if (buf==NULL) return 0xFFFFFFFF;
uLong uPosFound=0xFFFFFFFF;
uLong uBackRead = 4;
while (uBackReaduMaxBack) uBackRead = uMaxBack;
else uBackRead+=BUFREADCOMMENT;
uReadPos = uSizeFile-uBackRead ;
uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
if (lufseek(fin,uReadPos,SEEK_SET)!=0) break;
if (lufread(buf,(uInt)uReadSize,1,fin)!=1) break;
for (i=(int)uReadSize-3; (i--)>=0;)
{ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
{ uPosFound = uReadPos+i; break;
}
}
if (uPosFound!=0) break;
}
if (buf) zfree(buf);
return uPosFound;
}
int unzGoToFirstFile (unzFile file);
int unzCloseCurrentFile (unzFile file);
// Open a Zip file.
// If the zipfile cannot be opened (file don't exist or in not valid), return NULL.
// Otherwise, the return value is a unzFile Handle, usable with other unzip functions
unzFile unzOpenInternal(LUFILE *fin)
{ if (fin==NULL) return NULL;
if (unz_copyright[0]!=' ') {lufclose(fin); return NULL;}
int err=UNZ_OK;
unz_s us;
uLong central_pos,uL;
central_pos = unzlocal_SearchCentralDir(fin);
if (central_pos==0xFFFFFFFF) err=UNZ_ERRNO;
if (lufseek(fin,central_pos,SEEK_SET)!=0) err=UNZ_ERRNO;
// the signature, already checked
if (unzlocal_getLong(fin,&uL)!=UNZ_OK) err=UNZ_ERRNO;
// number of this disk
uLong number_disk; // number of the current dist, used for spanning ZIP, unsupported, always 0
if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) err=UNZ_ERRNO;
// number of the disk with the start of the central directory
uLong number_disk_with_CD; // number the the disk with central dir, used for spaning ZIP, unsupported, always 0
if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO;
// total number of entries in the central dir on this disk
if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO;
// total number of entries in the central dir
uLong number_entry_CD; // total number of entries in the central dir (same than number_entry on nospan)
if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO;
if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE;
// size of the central directory
if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO;
// offset of start of central directory with respect to the starting disk number
if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO;
// zipfile comment length
if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO;
if ((central_pos+fin->initial_offsetinitial_offset - (us.offset_central_dir+us.size_central_dir);
us.central_pos = central_pos;
us.pfile_in_zip_read = NULL;
fin->initial_offset = 0; // since the zipfile itself is expected to handle this
unz_s *s = (unz_s*)zmalloc(sizeof(unz_s));
*s=us;
unzGoToFirstFile((unzFile)s);
return (unzFile)s;
}
// Close a ZipFile opened with unzipOpen.
// If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
// these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
// return UNZ_OK if there is no problem.
int unzClose (unzFile file)
{
unz_s* s;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
if (s->pfile_in_zip_read!=NULL)
unzCloseCurrentFile(file);
lufclose(s->file);
if (s) zfree(s); // unused s=0;
return UNZ_OK;
}
// Write info about the ZipFile in the *pglobal_info structure.
// No preparation of the structure is needed
// return UNZ_OK if there is no problem.
int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info)
{
unz_s* s;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
*pglobal_info=s->gi;
return UNZ_OK;
}
// Translate date/time from Dos format to tm_unz (readable more easilty)
void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
{
uLong uDate;
uDate = (uLong)(ulDosDate>>16);
ptm->tm_mday = (uInt)(uDate&0x1f) ;
ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
}
// Get Info about the current file in the zipfile, with internal only info
int unzlocal_GetCurrentFileInfoInternal (unzFile file,
unz_file_info *pfile_info,
unz_file_info_internal
*pfile_info_internal,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize);
int unzlocal_GetCurrentFileInfoInternal (unzFile file, unz_file_info *pfile_info,
unz_file_info_internal *pfile_info_internal, char *szFileName,
uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize,
char *szComment, uLong commentBufferSize)
{
unz_s* s;
unz_file_info file_info;
unz_file_info_internal file_info_internal;
int err=UNZ_OK;
uLong uMagic;
long lSeek=0;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
if (lufseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
err=UNZ_ERRNO;
// we check the magic
if (err==UNZ_OK)
if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
err=UNZ_ERRNO;
else if (uMagic!=0x02014b50)
err=UNZ_BADZIPFILE;
if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
err=UNZ_ERRNO;
unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
err=UNZ_ERRNO;
lSeek+=file_info.size_filename;
if ((err==UNZ_OK) && (szFileName!=NULL))
{
uLong uSizeRead ;
if (file_info.size_filename0) && (fileNameBufferSize>0))
if (lufread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
err=UNZ_ERRNO;
lSeek -= uSizeRead;
}
if ((err==UNZ_OK) && (extraField!=NULL))
{
uLong uSizeRead ;
if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0)
lSeek=0;
else
err=UNZ_ERRNO;
if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
if (lufread(extraField,(uInt)uSizeRead,1,s->file)!=1)
err=UNZ_ERRNO;
lSeek += file_info.size_file_extra - uSizeRead;
}
else
lSeek+=file_info.size_file_extra;
if ((err==UNZ_OK) && (szComment!=NULL))
{
uLong uSizeRead ;
if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0)
{} // unused lSeek=0;
else
err=UNZ_ERRNO;
if ((file_info.size_file_comment>0) && (commentBufferSize>0))
if (lufread(szComment,(uInt)uSizeRead,1,s->file)!=1)
err=UNZ_ERRNO;
//unused lSeek+=file_info.size_file_comment - uSizeRead;
}
else {} //unused lSeek+=file_info.size_file_comment;
if ((err==UNZ_OK) && (pfile_info!=NULL))
*pfile_info=file_info;
if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
*pfile_info_internal=file_info_internal;
return err;
}
// Write info about the ZipFile in the *pglobal_info structure.
// No preparation of the structure is needed
// return UNZ_OK if there is no problem.
int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info,
char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize,
char *szComment, uLong commentBufferSize)
{ return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,szFileName,fileNameBufferSize,
extraField,extraFieldBufferSize, szComment,commentBufferSize);
}
// Set the current file of the zipfile to the first file.
// return UNZ_OK if there is no problem
int unzGoToFirstFile (unzFile file)
{
int err;
unz_s* s;
if (file==NULL) return UNZ_PARAMERROR;
s=(unz_s*)file;
s->pos_in_central_dir=s->offset_central_dir;
s->num_file=0;
err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
&s->cur_file_info_internal,
NULL,0,NULL,0,NULL,0);
s->current_file_ok = (err == UNZ_OK);
return err;
}
// Set the current file of the zipfile to the next file.
// return UNZ_OK if there is no problem
// return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
int unzGoToNextFile (unzFile file)
{
unz_s* s;
int err;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
if (!s->current_file_ok)
return UNZ_END_OF_LIST_OF_FILE;
if (s->num_file+1==s->gi.number_entry)
return UNZ_END_OF_LIST_OF_FILE;
s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
s->num_file++;
err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
&s->cur_file_info_internal,
NULL,0,NULL,0,NULL,0);
s->current_file_ok = (err == UNZ_OK);
return err;
}
// Try locate the file szFileName in the zipfile.
// For the iCaseSensitivity signification, see unzStringFileNameCompare
// return value :
// UNZ_OK if the file is found. It becomes the current file.
// UNZ_END_OF_LIST_OF_FILE if the file is not found
int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
{
unz_s* s;
int err;
uLong num_fileSaved;
uLong pos_in_central_dirSaved;
if (file==NULL)
return UNZ_PARAMERROR;
if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
return UNZ_PARAMERROR;
s=(unz_s*)file;
if (!s->current_file_ok)
return UNZ_END_OF_LIST_OF_FILE;
num_fileSaved = s->num_file;
pos_in_central_dirSaved = s->pos_in_central_dir;
err = unzGoToFirstFile(file);
while (err == UNZ_OK)
{
char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
unzGetCurrentFileInfo(file,NULL,
szCurrentFileName,sizeof(szCurrentFileName)-1,
NULL,0,NULL,0);
if (unzStringFileNameCompare(szCurrentFileName,szFileName,iCaseSensitivity)==0)
return UNZ_OK;
err = unzGoToNextFile(file);
}
s->num_file = num_fileSaved ;
s->pos_in_central_dir = pos_in_central_dirSaved ;
return err;
}
// Read the local header of the current zipfile
// Check the coherency of the local header and info in the end of central
// directory about this file
// store in *piSizeVar the size of extra info in local header
// (filename and size of extra field data)
int unzlocal_CheckCurrentFileCoherencyHeader (unz_s *s,uInt *piSizeVar,
uLong *poffset_local_extrafield, uInt *psize_local_extrafield)
{
uLong uMagic,uData,uFlags;
uLong size_filename;
uLong size_extra_field;
int err=UNZ_OK;
*piSizeVar = 0;
*poffset_local_extrafield = 0;
*psize_local_extrafield = 0;
if (lufseek(s->file,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,SEEK_SET)!=0)
return UNZ_ERRNO;
if (err==UNZ_OK)
if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
err=UNZ_ERRNO;
else if (uMagic!=0x04034b50)
err=UNZ_BADZIPFILE;
if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
err=UNZ_ERRNO;
// else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
// err=UNZ_BADZIPFILE;
if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
err=UNZ_ERRNO;
if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
err=UNZ_ERRNO;
else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
err=UNZ_BADZIPFILE;
if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
(s->cur_file_info.compression_method!=Z_DEFLATED))
err=UNZ_BADZIPFILE;
if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // date/time
err=UNZ_ERRNO;
if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // crc
err=UNZ_ERRNO;
else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
((uFlags & 8)==0))
err=UNZ_BADZIPFILE;
if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size compr
err=UNZ_ERRNO;
else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
((uFlags & 8)==0))
err=UNZ_BADZIPFILE;
if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size uncompr
err=UNZ_ERRNO;
else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
((uFlags & 8)==0))
err=UNZ_BADZIPFILE;
if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
err=UNZ_ERRNO;
else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
err=UNZ_BADZIPFILE;
*piSizeVar += (uInt)size_filename;
if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
err=UNZ_ERRNO;
*poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
SIZEZIPLOCALHEADER + size_filename;
*psize_local_extrafield = (uInt)size_extra_field;
*piSizeVar += (uInt)size_extra_field;
return err;
}
// Open for reading data the current file in the zipfile.
// If there is no error and the file is opened, the return value is UNZ_OK.
int unzOpenCurrentFile (unzFile file, const char *password)
{
int err;
int Store;
uInt iSizeVar;
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
uLong offset_local_extrafield; // offset of the local extra field
uInt size_local_extrafield; // size of the local extra field
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
if (!s->current_file_ok)
return UNZ_PARAMERROR;
if (s->pfile_in_zip_read != NULL)
unzCloseCurrentFile(file);
if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
&offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
return UNZ_BADZIPFILE;
pfile_in_zip_read_info = (file_in_zip_read_info_s*)zmalloc(sizeof(file_in_zip_read_info_s));
if (pfile_in_zip_read_info==NULL)
return UNZ_INTERNALERROR;
pfile_in_zip_read_info->read_buffer=(char*)zmalloc(UNZ_BUFSIZE);
pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
pfile_in_zip_read_info->pos_local_extrafield=0;
if (pfile_in_zip_read_info->read_buffer==NULL)
{
if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); //unused pfile_in_zip_read_info=0;
return UNZ_INTERNALERROR;
}
pfile_in_zip_read_info->stream_initialised=0;
if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED))
{ // unused err=UNZ_BADZIPFILE;
}
Store = s->cur_file_info.compression_method==0;
pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
pfile_in_zip_read_info->crc32=0;
pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
pfile_in_zip_read_info->file=s->file;
pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
pfile_in_zip_read_info->stream.total_out = 0;
if (!Store)
{
pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
pfile_in_zip_read_info->stream.zfree = (free_func)0;
pfile_in_zip_read_info->stream.opaque = (voidpf)0;
err=inflateInit2(&pfile_in_zip_read_info->stream);
if (err == Z_OK)
pfile_in_zip_read_info->stream_initialised=1;
// windowBits is passed < 0 to tell that there is no zlib header.
// Note that in this case inflate *requires* an extra "dummy" byte
// after the compressed stream in order to complete decompression and
// return Z_STREAM_END.
// In unzip, i don't wait absolutely Z_STREAM_END because I known the
// size of both compressed and uncompressed data
}
pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size ;
pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size ;
pfile_in_zip_read_info->encrypted = (s->cur_file_info.flag&1)!=0;
bool extlochead = (s->cur_file_info.flag&8)!=0;
if (extlochead) pfile_in_zip_read_info->crcenctest = (char)((s->cur_file_info.dosDate>>8)&0xff);
else pfile_in_zip_read_info->crcenctest = (char)(s->cur_file_info.crc >> 24);
pfile_in_zip_read_info->encheadleft = (pfile_in_zip_read_info->encrypted?12:0);
pfile_in_zip_read_info->keys[0] = 305419896L;
pfile_in_zip_read_info->keys[1] = 591751049L;
pfile_in_zip_read_info->keys[2] = 878082192L;
for (const char *cp=password; cp!=0 && *cp!=0; cp++) Uupdate_keys(pfile_in_zip_read_info->keys,*cp);
pfile_in_zip_read_info->pos_in_zipfile =
s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
iSizeVar;
pfile_in_zip_read_info->stream.avail_in = (uInt)0;
s->pfile_in_zip_read = pfile_in_zip_read_info;
return UNZ_OK;
}
// Read bytes from the current file.
// buf contain buffer where data must be copied
// len the size of buf.
// return the number of byte copied if somes bytes are copied (and also sets *reached_eof)
// return 0 if the end of file was reached. (and also sets *reached_eof).
// return <0 with error code if there is an error. (in which case *reached_eof is meaningless)
// (UNZ_ERRNO for IO error, or zLib error for uncompress error)
int unzReadCurrentFile (unzFile file, voidp buf, unsigned len, bool *reached_eof)
{ int err=UNZ_OK;
uInt iRead = 0;
if (reached_eof!=0) *reached_eof=false;
unz_s *s = (unz_s*)file;
if (s==NULL) return UNZ_PARAMERROR;
file_in_zip_read_info_s* pfile_in_zip_read_info = s->pfile_in_zip_read;
if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR;
if ((pfile_in_zip_read_info->read_buffer == NULL)) return UNZ_END_OF_LIST_OF_FILE;
if (len==0) return 0;
pfile_in_zip_read_info->stream.next_out = (Byte*)buf;
pfile_in_zip_read_info->stream.avail_out = (uInt)len;
if (len>pfile_in_zip_read_info->rest_read_uncompressed)
{ pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
}
while (pfile_in_zip_read_info->stream.avail_out>0)
{ if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0))
{ uInt uReadThis = UNZ_BUFSIZE;
if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed;
if (uReadThis == 0) {if (reached_eof!=0) *reached_eof=true; return UNZ_EOF;}
if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) return UNZ_ERRNO;
if (lufread(pfile_in_zip_read_info->read_buffer,uReadThis,1,pfile_in_zip_read_info->file)!=1) return UNZ_ERRNO;
pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
pfile_in_zip_read_info->stream.next_in = (Byte*)pfile_in_zip_read_info->read_buffer;
pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
//
if (pfile_in_zip_read_info->encrypted)
{ char *buf = (char*)pfile_in_zip_read_info->stream.next_in;
for (unsigned int i=0; ikeys,buf[i]);
}
}
unsigned int uDoEncHead = pfile_in_zip_read_info->encheadleft;
if (uDoEncHead>pfile_in_zip_read_info->stream.avail_in) uDoEncHead=pfile_in_zip_read_info->stream.avail_in;
if (uDoEncHead>0)
{ char bufcrc=pfile_in_zip_read_info->stream.next_in[uDoEncHead-1];
pfile_in_zip_read_info->rest_read_uncompressed-=uDoEncHead;
pfile_in_zip_read_info->stream.avail_in -= uDoEncHead;
pfile_in_zip_read_info->stream.next_in += uDoEncHead;
pfile_in_zip_read_info->encheadleft -= uDoEncHead;
if (pfile_in_zip_read_info->encheadleft==0)
{ if (bufcrc!=pfile_in_zip_read_info->crcenctest) return UNZ_PASSWORD;
}
}
if (pfile_in_zip_read_info->compression_method==0)
{ uInt uDoCopy,i ;
if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in)
{ uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
}
else
{ uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
}
for (i=0;istream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i);
pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,pfile_in_zip_read_info->stream.next_out,uDoCopy);
pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
pfile_in_zip_read_info->stream.next_out += uDoCopy;
pfile_in_zip_read_info->stream.next_in += uDoCopy;
pfile_in_zip_read_info->stream.total_out += uDoCopy;
iRead += uDoCopy;
if (pfile_in_zip_read_info->rest_read_uncompressed==0) {if (reached_eof!=0) *reached_eof=true;}
}
else
{ uLong uTotalOutBefore,uTotalOutAfter;
const Byte *bufBefore;
uLong uOutThis;
int flush=Z_SYNC_FLUSH;
uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
bufBefore = pfile_in_zip_read_info->stream.next_out;
//
err=inflate(&pfile_in_zip_read_info->stream,flush);
//
uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
uOutThis = uTotalOutAfter-uTotalOutBefore;
pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,bufBefore,(uInt)(uOutThis));
pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
if (err==Z_STREAM_END || pfile_in_zip_read_info->rest_read_uncompressed==0)
{ if (reached_eof!=0) *reached_eof=true;
return iRead;
}
if (err!=Z_OK) break;
}
}
if (err==Z_OK) return iRead;
return err;
}
// Give the current position in uncompressed data
z_off_t unztell (unzFile file)
{
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
if (pfile_in_zip_read_info==NULL)
return UNZ_PARAMERROR;
return (z_off_t)pfile_in_zip_read_info->stream.total_out;
}
// return 1 if the end of file was reached, 0 elsewhere
int unzeof (unzFile file)
{
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
if (pfile_in_zip_read_info==NULL)
return UNZ_PARAMERROR;
if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
return 1;
else
return 0;
}
// Read extra field from the current file (opened by unzOpenCurrentFile)
// This is the local-header version of the extra field (sometimes, there is
// more info in the local-header version than in the central-header)
// if buf==NULL, it return the size of the local extra field that can be read
// if buf!=NULL, len is the size of the buffer, the extra header is copied in buf.
// the return value is the number of bytes copied in buf, or (if <0) the error code
int unzGetLocalExtrafield (unzFile file,voidp buf,unsigned len)
{
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
uInt read_now;
uLong size_to_read;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
if (pfile_in_zip_read_info==NULL)
return UNZ_PARAMERROR;
size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
pfile_in_zip_read_info->pos_local_extrafield);
if (buf==NULL)
return (int)size_to_read;
if (len>size_to_read)
read_now = (uInt)size_to_read;
else
read_now = (uInt)len ;
if (read_now==0)
return 0;
if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
return UNZ_ERRNO;
if (lufread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
return UNZ_ERRNO;
return (int)read_now;
}
// Close the file in zip opened with unzipOpenCurrentFile
// Return UNZ_CRCERROR if all the file was read but the CRC is not good
int unzCloseCurrentFile (unzFile file)
{
int err=UNZ_OK;
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
if (file==NULL)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
if (pfile_in_zip_read_info==NULL)
return UNZ_PARAMERROR;
if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
{
if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
err=UNZ_CRCERROR;
}
if (pfile_in_zip_read_info->read_buffer!=0)
{ void *buf = pfile_in_zip_read_info->read_buffer;
zfree(buf);
pfile_in_zip_read_info->read_buffer=0;
}
pfile_in_zip_read_info->read_buffer = NULL;
if (pfile_in_zip_read_info->stream_initialised)
inflateEnd(&pfile_in_zip_read_info->stream);
pfile_in_zip_read_info->stream_initialised = 0;
if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); // unused pfile_in_zip_read_info=0;
s->pfile_in_zip_read=NULL;
return err;
}
// Get the global comment string of the ZipFile, in the szComment buffer.
// uSizeBuf is the size of the szComment buffer.
// return the number of byte copied or an error code <0
int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)
{ //int err=UNZ_OK;
unz_s* s;
uLong uReadThis ;
if (file==NULL) return UNZ_PARAMERROR;
s=(unz_s*)file;
uReadThis = uSizeBuf;
if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment;
if (lufseek(s->file,s->central_pos+22,SEEK_SET)!=0) return UNZ_ERRNO;
if (uReadThis>0)
{ *szComment='\0';
if (lufread(szComment,(uInt)uReadThis,1,s->file)!=1) return UNZ_ERRNO;
}
if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0';
return (int)uReadThis;
}
int unzOpenCurrentFile (unzFile file, const char *password);
int unzReadCurrentFile (unzFile file, void *buf, unsigned len);
int unzCloseCurrentFile (unzFile file);
typedef unsigned __int32 lutime_t; // define it ourselves since we don't include time.h
FILETIME timet2filetime(const lutime_t t)
{ LONGLONG i = Int32x32To64(t,10000000) + 116444736000000000;
FILETIME ft;
ft.dwLowDateTime = (DWORD) i;
ft.dwHighDateTime = (DWORD)(i >>32);
return ft;
}
FILETIME dosdatetime2filetime(WORD dosdate,WORD dostime)
{ // date: bits 0-4 are day of month 1-31. Bits 5-8 are month 1..12. Bits 9-15 are year-1980
// time: bits 0-4 are seconds/2, bits 5-10 are minute 0..59. Bits 11-15 are hour 0..23
SYSTEMTIME st;
st.wYear = (WORD)(((dosdate>>9)&0x7f) + 1980);
st.wMonth = (WORD)((dosdate>>5)&0xf);
st.wDay = (WORD)(dosdate&0x1f);
st.wHour = (WORD)((dostime>>11)&0x1f);
st.wMinute = (WORD)((dostime>>5)&0x3f);
st.wSecond = (WORD)((dostime&0x1f)*2);
st.wMilliseconds = 0;
FILETIME ft; SystemTimeToFileTime(&st,&ft);
return ft;
}
class TUnzip
{ public:
TUnzip(const char *pwd) : uf(0), unzbuf(0), currentfile(-1), czei(-1), password(0) {if (pwd!=0) {password=new char[strlen(pwd)+1]; strcpy_s(password,MAX_PATH,pwd);}}
~TUnzip() {if (password!=0) delete[] password; password=0; if (unzbuf!=0) delete[] unzbuf; unzbuf=0;}
unzFile uf; int currentfile; ZIPENTRY cze; int czei;
char *password;
char *unzbuf; // lazily created and destroyed, used by Unzip
TCHAR rootdir[MAX_PATH]; // includes a trailing slash
ZRESULT Open(void *z,unsigned int len,DWORD flags);
ZRESULT Get(int index,ZIPENTRY *ze);
ZRESULT Find(const TCHAR *name,bool ic,int *index,ZIPENTRY *ze);
ZRESULT Unzip(int index,void *dst,unsigned int len,DWORD flags);
ZRESULT SetUnzipBaseDir(const TCHAR *dir);
ZRESULT Close();
};
ZRESULT TUnzip::Open(void *z,unsigned int len,DWORD flags)
{ if (uf!=0 || currentfile!=-1) return ZR_NOTINITED;
//
#ifdef GetCurrentDirectory
GetCurrentDirectory(MAX_PATH,rootdir);
#else
_tcscpy(rootdir,_T("\\"));
#endif
TCHAR lastchar = rootdir[_tcslen(rootdir)-1];
if (lastchar!='\\' && lastchar!='/') _tcscat_s(rootdir,_T("\\"));
//
if (flags==ZIP_HANDLE)
{ // test if we can seek on it. We can't use GetFileType(h)==FILE_TYPE_DISK since it's not on CE.
DWORD res = SetFilePointer(z,0,0,FILE_CURRENT);
bool canseek = (res!=0xFFFFFFFF);
if (!canseek) return ZR_SEEK;
}
ZRESULT e; LUFILE *f = lufopen(z,len,flags,&e);
if (f==NULL) return e;
uf = unzOpenInternal(f);
if (uf==0) return ZR_NOFILE;
return ZR_OK;
}
ZRESULT TUnzip::SetUnzipBaseDir(const TCHAR *dir)
{
_tcscpy_s(rootdir, MAX_PATH, dir);
TCHAR lastchar = rootdir[_tcslen(rootdir)-1];
if (lastchar!='\\' && lastchar!='/') _tcscat_s(rootdir,_T("\\"));
return ZR_OK;
}
ZRESULT TUnzip::Get(int index,ZIPENTRY *ze)
{ if (index<-1 || index>=(int)uf->gi.number_entry) return ZR_ARGS;
if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
if (index==czei && index!=-1) {memcpy(ze,&cze,sizeof(ZIPENTRY)); return ZR_OK;}
if (index==-1)
{ ze->index = uf->gi.number_entry;
ze->name[0]=0;
ze->attr=0;
ze->atime.dwLowDateTime=0; ze->atime.dwHighDateTime=0;
ze->ctime.dwLowDateTime=0; ze->ctime.dwHighDateTime=0;
ze->mtime.dwLowDateTime=0; ze->mtime.dwHighDateTime=0;
ze->comp_size=0;
ze->unc_size=0;
return ZR_OK;
}
if (index<(int)uf->num_file) unzGoToFirstFile(uf);
while ((int)uf->num_filefile,offset,SEEK_SET)!=0) return ZR_READ;
unsigned char *extra = new unsigned char[extralen];
if (lufread(extra,1,(uInt)extralen,uf->file)!=extralen) {delete[] extra; return ZR_READ;}
//
ze->index=uf->num_file;
TCHAR tfn[MAX_PATH];
#ifdef UNICODE
MultiByteToWideChar(CP_UTF8,0,fn,-1,tfn,MAX_PATH);
#else
strcpy(tfn,fn);
#endif
// As a safety feature: if the zip filename had sneaky stuff
// like "c:\windows\file.txt" or "\windows\file.txt" or "fred\..\..\..\windows\file.txt"
// then we get rid of them all. That way, when the programmer does UnzipItem(hz,i,ze.name),
// it won't be a problem. (If the programmer really did want to get the full evil information,
// then they can edit out this security feature from here).
// In particular, we chop off any prefixes that are "c:\" or "\" or "/" or "[stuff]\.." or "[stuff]/.."
const TCHAR *sfn=tfn;
for (;;)
{ if (sfn[0]!=0 && sfn[1]==':') {sfn+=2; continue;}
if (sfn[0]=='\\') {sfn++; continue;}
if (sfn[0]=='/') {sfn++; continue;}
const TCHAR *c;
c=_tcsstr(sfn,_T("\\..\\")); if (c!=0) {sfn=c+4; continue;}
c=_tcsstr(sfn,_T("\\../")); if (c!=0) {sfn=c+4; continue;}
c=_tcsstr(sfn,_T("/../")); if (c!=0) {sfn=c+4; continue;}
c=_tcsstr(sfn,_T("/..\\")); if (c!=0) {sfn=c+4; continue;}
break;
}
_tcscpy_s(ze->name, MAX_PATH, sfn);
// zip has an 'attribute' 32bit value. Its lower half is windows stuff
// its upper half is standard unix stat.st_mode. We'll start trying
// to read it in unix mode
unsigned long a = ufi.external_fa;
bool isdir = (a&0x40000000)!=0;
bool readonly= (a&0x00800000)==0;
//bool readable= (a&0x01000000)!=0; // unused
//bool executable=(a&0x00400000)!=0; // unused
bool hidden=false, system=false, archive=true;
// but in normal hostmodes these are overridden by the lower half...
int host = ufi.version>>8;
if (host==0 || host==7 || host==11 || host==14)
{ readonly= (a&0x00000001)!=0;
hidden= (a&0x00000002)!=0;
system= (a&0x00000004)!=0;
isdir= (a&0x00000010)!=0;
archive= (a&0x00000020)!=0;
}
ze->attr=0;
if (isdir) ze->attr |= FILE_ATTRIBUTE_DIRECTORY;
if (archive) ze->attr|=FILE_ATTRIBUTE_ARCHIVE;
if (hidden) ze->attr|=FILE_ATTRIBUTE_HIDDEN;
if (readonly) ze->attr|=FILE_ATTRIBUTE_READONLY;
if (system) ze->attr|=FILE_ATTRIBUTE_SYSTEM;
ze->comp_size = ufi.compressed_size;
ze->unc_size = ufi.uncompressed_size;
//
WORD dostime = (WORD)(ufi.dosDate&0xFFFF);
WORD dosdate = (WORD)((ufi.dosDate>>16)&0xFFFF);
FILETIME ftd = dosdatetime2filetime(dosdate,dostime);
FILETIME ft; LocalFileTimeToFileTime(&ftd,&ft);
ze->atime=ft; ze->ctime=ft; ze->mtime=ft;
// the zip will always have at least that dostime. But if it also has
// an extra header, then we'll instead get the info from that.
unsigned int epos=0;
while (epos+4mtime = timet2filetime(mtime);
}
if (hasatime)
{ lutime_t atime = ((extra[epos+0])<<0) | ((extra[epos+1])<<8) |((extra[epos+2])<<16) | ((extra[epos+3])<<24);
epos+=4;
ze->atime = timet2filetime(atime);
}
if (hasctime)
{ lutime_t ctime = ((extra[epos+0])<<0) | ((extra[epos+1])<<8) |((extra[epos+2])<<16) | ((extra[epos+3])<<24);
epos+=4;
ze->ctime = timet2filetime(ctime);
}
break;
}
//
if (extra!=0) delete[] extra;
memcpy(&cze,ze,sizeof(ZIPENTRY)); czei=index;
return ZR_OK;
}
ZRESULT TUnzip::Find(const TCHAR *tname,bool ic,int *index,ZIPENTRY *ze)
{ char name[MAX_PATH];
#ifdef UNICODE
WideCharToMultiByte(CP_UTF8,0,tname,-1,name,MAX_PATH,0,0);
#else
strcpy(name,tname);
#endif
int res = unzLocateFile(uf,name,ic?CASE_INSENSITIVE:CASE_SENSITIVE);
if (res!=UNZ_OK)
{ if (index!=0) *index=-1;
if (ze!=NULL) {ZeroMemory(ze,sizeof(ZIPENTRY)); ze->index=-1;}
return ZR_NOTFOUND;
}
if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
int i = (int)uf->num_file;
if (index!=NULL) *index=i;
if (ze!=NULL)
{ ZRESULT zres = Get(i,ze);
if (zres!=ZR_OK) return zres;
}
return ZR_OK;
}
void EnsureDirectory(const TCHAR *rootdir, const TCHAR *dir)
{ if (rootdir!=0 && GetFileAttributes(rootdir)==0xFFFFFFFF) CreateDirectory(rootdir,0);
if (*dir==0) return;
const TCHAR *lastslash=dir, *c=lastslash;
while (*c!=0) {if (*c=='/' || *c=='\\') lastslash=c; c++;}
const TCHAR *name=lastslash;
if (lastslash!=dir)
{ TCHAR tmp[MAX_PATH]; memcpy(tmp,dir,sizeof(TCHAR)*(lastslash-dir));
tmp[lastslash-dir]=0;
EnsureDirectory(rootdir,tmp);
name++;
}
TCHAR cd[MAX_PATH]; *cd=0; if (rootdir!=0) _tcscpy_s(cd, MAX_PATH, rootdir); _tcscat_s(cd,dir);
if (GetFileAttributes(cd)==0xFFFFFFFF) CreateDirectory(cd,NULL);
}
ZRESULT TUnzip::Unzip(int index,void *dst,unsigned int len,DWORD flags)
{ if (flags!=ZIP_MEMORY && flags!=ZIP_FILENAME && flags!=ZIP_HANDLE) return ZR_ARGS;
if (flags==ZIP_MEMORY)
{ if (index!=currentfile)
{ if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
if (index>=(int)uf->gi.number_entry) return ZR_ARGS;
if (index<(int)uf->num_file) unzGoToFirstFile(uf);
while ((int)uf->num_file0) return ZR_MORE;
if (res==UNZ_PASSWORD) return ZR_PASSWORD;
return ZR_FLATE;
}
// otherwise we're writing to a handle or a file
if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
if (index>=(int)uf->gi.number_entry) return ZR_ARGS;
if (index<(int)uf->num_file) unzGoToFirstFile(uf);
while ((int)uf->num_file0) {DWORD writ; BOOL bres=WriteFile(h,unzbuf,res,&writ,NULL); if (!bres) {haderr=ZR_WRITE; break;}}
if (reached_eof) break;
if (res==0) {haderr=ZR_FLATE; break;}
}
if (!haderr) SetFileTime(h,&ze.ctime,&ze.atime,&ze.mtime); // may fail if it was a pipe
if (flags!=ZIP_HANDLE) CloseHandle(h);
unzCloseCurrentFile(uf);
if (haderr!=0) return haderr;
return ZR_OK;
}
ZRESULT TUnzip::Close()
{ if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
if (uf!=0) unzClose(uf); uf=0;
return ZR_OK;
}
ZRESULT lasterrorU=ZR_OK;
unsigned int FormatZipMessageU(ZRESULT code, TCHAR *buf,unsigned int len)
{ if (code==ZR_RECENT) code=lasterrorU;
const TCHAR *msg=_T("unknown zip result code");
switch (code)
{ case ZR_OK: msg=_T("Success"); break;
case ZR_NODUPH: msg=_T("Culdn't duplicate handle"); break;
case ZR_NOFILE: msg=_T("Couldn't create/open file"); break;
case ZR_NOALLOC: msg=_T("Failed to allocate memory"); break;
case ZR_WRITE: msg=_T("Error writing to file"); break;
case ZR_NOTFOUND: msg=_T("File not found in the zipfile"); break;
case ZR_MORE: msg=_T("Still more data to unzip"); break;
case ZR_CORRUPT: msg=_T("Zipfile is corrupt or not a zipfile"); break;
case ZR_READ: msg=_T("Error reading file"); break;
case ZR_PASSWORD: msg=_T("Correct password required"); break;
case ZR_ARGS: msg=_T("Caller: faulty arguments"); break;
case ZR_PARTIALUNZ: msg=_T("Caller: the file had already been partially unzipped"); break;
case ZR_NOTMMAP: msg=_T("Caller: can only get memory of a memory zipfile"); break;
case ZR_MEMSIZE: msg=_T("Caller: not enough space allocated for memory zipfile"); break;
case ZR_FAILED: msg=_T("Caller: there was a previous error"); break;
case ZR_ENDED: msg=_T("Caller: additions to the zip have already been ended"); break;
case ZR_ZMODE: msg=_T("Caller: mixing creation and opening of zip"); break;
case ZR_NOTINITED: msg=_T("Zip-bug: internal initialisation not completed"); break;
case ZR_SEEK: msg=_T("Zip-bug: trying to seek the unseekable"); break;
case ZR_MISSIZE: msg=_T("Zip-bug: the anticipated size turned out wrong"); break;
case ZR_NOCHANGE: msg=_T("Zip-bug: tried to change mind, but not allowed"); break;
case ZR_FLATE: msg=_T("Zip-bug: an internal error during flation"); break;
}
unsigned int mlen=(unsigned int)_tcslen(msg);
if (buf==0 || len==0) return mlen;
unsigned int n=mlen; if (n+1>len) n=len-1;
_tcsncpy_s(buf,MAX_PATH,msg,n); buf[n]=0;
return mlen;
}
typedef struct
{ DWORD flag;
TUnzip *unz;
} TUnzipHandleData;
HZIP OpenZipInternal(void *z,unsigned int len,DWORD flags, const char *password)
{ TUnzip *unz = new TUnzip(password);
lasterrorU = unz->Open(z,len,flags);
if (lasterrorU!=ZR_OK) {delete unz; return 0;}
TUnzipHandleData *han = new TUnzipHandleData;
han->flag=1; han->unz=unz; return (HZIP)han;
}
HZIP OpenZipHandle(HANDLE h, const char *password) {return OpenZipInternal((void*)h,0,ZIP_HANDLE,password);}
HZIP OpenZip(const TCHAR *fn, const char *password) {return OpenZipInternal((void*)fn,0,ZIP_FILENAME,password);}
HZIP OpenZip(void *z,unsigned int len, const char *password) {return OpenZipInternal(z,len,ZIP_MEMORY,password);}
ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze)
{ ze->index=0; *ze->name=0; ze->unc_size=0;
if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
TUnzipHandleData *han = (TUnzipHandleData*)hz;
if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
TUnzip *unz = han->unz;
lasterrorU = unz->Get(index,ze);
return lasterrorU;
}
ZRESULT FindZipItem(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze)
{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
TUnzipHandleData *han = (TUnzipHandleData*)hz;
if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
TUnzip *unz = han->unz;
lasterrorU = unz->Find(name,ic,index,ze);
return lasterrorU;
}
ZRESULT UnzipItemInternal(HZIP hz, int index, void *dst, unsigned int len, DWORD flags)
{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
TUnzipHandleData *han = (TUnzipHandleData*)hz;
if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
TUnzip *unz = han->unz;
lasterrorU = unz->Unzip(index,dst,len,flags);
return lasterrorU;
}
ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h) {return UnzipItemInternal(hz,index,(void*)h,0,ZIP_HANDLE);}
ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn) {return UnzipItemInternal(hz,index,(void*)fn,0,ZIP_FILENAME);}
ZRESULT UnzipItem(HZIP hz, int index, void *z,unsigned int len) {return UnzipItemInternal(hz,index,z,len,ZIP_MEMORY);}
ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir)
{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
TUnzipHandleData *han = (TUnzipHandleData*)hz;
if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
TUnzip *unz = han->unz;
lasterrorU = unz->SetUnzipBaseDir(dir);
return lasterrorU;
}
ZRESULT CloseZipU(HZIP hz)
{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
TUnzipHandleData *han = (TUnzipHandleData*)hz;
if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
TUnzip *unz = han->unz;
lasterrorU = unz->Close();
delete unz;
delete han;
return lasterrorU;
}
bool IsZipHandleU(HZIP hz)
{ if (hz==0) return false;
TUnzipHandleData *han = (TUnzipHandleData*)hz;
return (han->flag==1);
}
================================================
FILE: src/Setup/unzip.h
================================================
#ifndef _unzip_H
#define _unzip_H
// UNZIPPING functions -- for unzipping.
// This file is a repackaged form of extracts from the zlib code available
// at www.gzip.org/zlib, by Jean-Loup Gailly and Mark Adler. The original
// copyright notice may be found in unzip.cpp. The repackaging was done
// by Lucian Wischik to simplify and extend its use in Windows/C++. Also
// encryption and unicode filenames have been added.
#ifndef _zip_H
DECLARE_HANDLE(HZIP);
#endif
// An HZIP identifies a zip file that has been opened
typedef DWORD ZRESULT;
// return codes from any of the zip functions. Listed later.
typedef struct
{ int index; // index of this file within the zip
TCHAR name[MAX_PATH]; // filename within the zip
DWORD attr; // attributes, as in GetFileAttributes.
FILETIME atime,ctime,mtime;// access, create, modify filetimes
long comp_size; // sizes of item, compressed and uncompressed. These
long unc_size; // may be -1 if not yet known (e.g. being streamed in)
} ZIPENTRY;
HZIP OpenZip(const TCHAR *fn, const char *password);
HZIP OpenZip(void *z,unsigned int len, const char *password);
HZIP OpenZipHandle(HANDLE h, const char *password);
// OpenZip - opens a zip file and returns a handle with which you can
// subsequently examine its contents. You can open a zip file from:
// from a pipe: OpenZipHandle(hpipe_read,0);
// from a file (by handle): OpenZipHandle(hfile,0);
// from a file (by name): OpenZip("c:\\test.zip","password");
// from a memory block: OpenZip(bufstart, buflen,0);
// If the file is opened through a pipe, then items may only be
// accessed in increasing order, and an item may only be unzipped once,
// although GetZipItem can be called immediately before and after unzipping
// it. If it's opened in any other way, then full random access is possible.
// Note: pipe input is not yet implemented.
// Note: zip passwords are ascii, not unicode.
// Note: for windows-ce, you cannot close the handle until after CloseZip.
// but for real windows, the zip makes its own copy of your handle, so you
// can close yours anytime.
ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze);
// GetZipItem - call this to get information about an item in the zip.
// If index is -1 and the file wasn't opened through a pipe,
// then it returns information about the whole zipfile
// (and in particular ze.index returns the number of index items).
// Note: the item might be a directory (ze.attr & FILE_ATTRIBUTE_DIRECTORY)
// See below for notes on what happens when you unzip such an item.
// Note: if you are opening the zip through a pipe, then random access
// is not possible and GetZipItem(-1) fails and you can't discover the number
// of items except by calling GetZipItem on each one of them in turn,
// starting at 0, until eventually the call fails. Also, in the event that
// you are opening through a pipe and the zip was itself created into a pipe,
// then then comp_size and sometimes unc_size as well may not be known until
// after the item has been unzipped.
ZRESULT FindZipItem(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze);
// FindZipItem - finds an item by name. ic means 'insensitive to case'.
// It returns the index of the item, and returns information about it.
// If nothing was found, then index is set to -1 and the function returns
// an error code.
ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn);
ZRESULT UnzipItem(HZIP hz, int index, void *z,unsigned int len);
ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h);
// UnzipItem - given an index to an item, unzips it. You can unzip to:
// to a pipe: UnzipItemHandle(hz,i, hpipe_write);
// to a file (by handle): UnzipItemHandle(hz,i, hfile);
// to a file (by name): UnzipItem(hz,i, ze.name);
// to a memory block: UnzipItem(hz,i, buf,buflen);
// In the final case, if the buffer isn't large enough to hold it all,
// then the return code indicates that more is yet to come. If it was
// large enough, and you want to know precisely how big, GetZipItem.
// Note: zip files are normally stored with relative pathnames. If you
// unzip with ZIP_FILENAME a relative pathname then the item gets created
// relative to the current directory - it first ensures that all necessary
// subdirectories have been created. Also, the item may itself be a directory.
// If you unzip a directory with ZIP_FILENAME, then the directory gets created.
// If you unzip it to a handle or a memory block, then nothing gets created
// and it emits 0 bytes.
ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir);
// if unzipping to a filename, and it's a relative filename, then it will be relative to here.
// (defaults to current-directory).
ZRESULT CloseZip(HZIP hz);
// CloseZip - the zip handle must be closed with this function.
unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf,unsigned int len);
// FormatZipMessage - given an error code, formats it as a string.
// It returns the length of the error message. If buf/len points
// to a real buffer, then it also writes as much as possible into there.
// These are the result codes:
#define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned,
#define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage.
// The following come from general system stuff (e.g. files not openable)
#define ZR_GENMASK 0x0000FF00
#define ZR_NODUPH 0x00000100 // couldn't duplicate the handle
#define ZR_NOFILE 0x00000200 // couldn't create/open the file
#define ZR_NOALLOC 0x00000300 // failed to allocate some resource
#define ZR_WRITE 0x00000400 // a general error writing to the file
#define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip
#define ZR_MORE 0x00000600 // there's still more data to be unzipped
#define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile
#define ZR_READ 0x00000800 // a general error reading the file
#define ZR_PASSWORD 0x00001000 // we didn't get the right password to unzip the file
// The following come from mistakes on the part of the caller
#define ZR_CALLERMASK 0x00FF0000
#define ZR_ARGS 0x00010000 // general mistake with the arguments
#define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't
#define ZR_MEMSIZE 0x00030000 // the memory size is too small
#define ZR_FAILED 0x00040000 // the thing was already failed when you called this function
#define ZR_ENDED 0x00050000 // the zip creation has already been closed
#define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken
#define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped
#define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip
// The following come from bugs within the zip library itself
#define ZR_BUGMASK 0xFF000000
#define ZR_NOTINITED 0x01000000 // initialisation didn't work
#define ZR_SEEK 0x02000000 // trying to seek in an unseekable file
#define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed
#define ZR_FLATE 0x05000000 // an internal error in the de/inflation code
// e.g.
//
// SetCurrentDirectory("c:\\docs\\stuff");
// HZIP hz = OpenZip("c:\\stuff.zip",0);
// ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
// for (int i=0; i
#include
CAppModule* _Module;
typedef BOOL(WINAPI *SetDefaultDllDirectoriesFunction)(DWORD DirectoryFlags);
// Some libraries are still loaded from the current directories.
// If we pre-load them with an absolute path then we are good.
static void PreloadLibs()
{
wchar_t sys32Folder[MAX_PATH];
GetSystemDirectory(sys32Folder, MAX_PATH);
std::wstring version = (std::wstring(sys32Folder) + L"\\version.dll");
std::wstring logoncli = (std::wstring(sys32Folder) + L"\\logoncli.dll");
std::wstring sspicli = (std::wstring(sys32Folder) + L"\\sspicli.dll");
std::wstring urlmon = (std::wstring(sys32Folder) + L"\\urlmon.dll");
LoadLibrary(version.c_str());
LoadLibrary(logoncli.c_str());
LoadLibrary(sspicli.c_str());
LoadLibrary(urlmon.c_str());
}
static void MitigateDllHijacking()
{
// Set the default DLL lookup directory to System32 for ourselves and kernel32.dll
HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
if (hKernel32)
{
SetDefaultDllDirectoriesFunction pfn = (SetDefaultDllDirectoriesFunction)GetProcAddress(hKernel32, "SetDefaultDllDirectories");
if (pfn)
{
(*pfn)(LOAD_LIBRARY_SEARCH_SYSTEM32);
}
}
PreloadLibs();
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
MitigateDllHijacking();
int exitCode = -1;
CString cmdLine(lpCmdLine);
if (cmdLine.Find(L"--checkInstall") >= 0) {
// If we're already installed, exit as fast as possible
if (!MachineInstaller::ShouldSilentInstall()) {
return 0;
}
// Make sure update.exe gets silent
wcscat(lpCmdLine, L" --silent");
}
HRESULT hr = ::CoInitialize(NULL);
ATLASSERT(SUCCEEDED(hr));
AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);
_Module = new CAppModule();
hr = _Module->Init(NULL, hInstance);
bool isQuiet = (cmdLine.Find(L"-s") >= 0);
bool weAreUACElevated = CUpdateRunner::AreWeUACElevated() == S_OK;
bool attemptingToRerun = (cmdLine.Find(L"--rerunningWithoutUAC") >= 0);
if (weAreUACElevated && attemptingToRerun) {
CUpdateRunner::DisplayErrorMessage(CString(L"Please re-run this installer as a normal user instead of \"Run as Administrator\"."), NULL);
exitCode = E_FAIL;
goto out;
}
if (!CFxHelper::CanInstallDotNet4_5()) {
// Explain this as nicely as possible and give up.
MessageBox(0L, L"This program cannot run on Windows XP or before; it requires a later version of Windows.", L"Incompatible Operating System", 0);
exitCode = E_FAIL;
goto out;
}
NetVersion requiredVersion = CFxHelper::GetRequiredDotNetVersion();
if (!CFxHelper::IsDotNetInstalled(requiredVersion)) {
hr = CFxHelper::InstallDotNetFramework(requiredVersion, isQuiet);
if (FAILED(hr)) {
exitCode = hr; // #yolo
CUpdateRunner::DisplayErrorMessage(CString(L"Failed to install the .NET Framework, try installing the latest version manually"), NULL);
goto out;
}
// S_FALSE isn't failure, but we still shouldn't try to install
if (hr != S_OK) {
exitCode = 0;
goto out;
}
}
// If we're UAC-elevated, we shouldn't be because it will give us permissions
// problems later. Just silently rerun ourselves.
// (Skip this check in Wine, which always reports admin privileges)
if (weAreUACElevated && CUpdateRunner::AreWeInWine() != S_OK) {
wchar_t buf[4096];
HMODULE hMod = GetModuleHandle(NULL);
GetModuleFileNameW(hMod, buf, 4096);
wcscat(lpCmdLine, L" --rerunningWithoutUAC");
CUpdateRunner::ShellExecuteFromExplorer(buf, lpCmdLine);
exitCode = 0;
goto out;
}
exitCode = CUpdateRunner::ExtractUpdaterAndRun(lpCmdLine, false);
out:
_Module->Term();
return exitCode;
}
================================================
FILE: src/Setup/wtl90/atlapp.h
================================================
// Windows Template Library - WTL version 9.0
// Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
//
// This file is a part of the Windows Template Library.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
#ifndef __ATLAPP_H__
#define __ATLAPP_H__
#pragma once
#ifndef __cplusplus
#error WTL requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLBASE_H__
#error atlapp.h requires atlbase.h to be included first
#endif
#ifndef _WIN32_WCE
#if (WINVER < 0x0400)
#error WTL requires Windows version 4.0 or higher
#endif
#if (_WIN32_IE < 0x0300)
#error WTL requires IE version 3.0 or higher
#endif
#endif
#ifdef _ATL_NO_COMMODULE
#error WTL requires that _ATL_NO_COMMODULE is not defined
#endif
#if (_ATL_VER >= 0x0900) && defined(_ATL_MIN_CRT)
#error _ATL_MIN_CRT is not supported with ATL 9.0 and higher
#endif
#if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)
#pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT")
#endif
#include
#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
#include // for _beginthreadex
#endif
#if (_ATL_VER < 0x0800) && !defined(_DEBUG)
#include
#endif
#include
#ifndef _WIN32_WCE
#pragma comment(lib, "comctl32.lib")
#endif
#if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
#include
#endif
#ifndef _WIN32_WCE
#include "atlres.h"
#else // CE specific
#include "atlresce.h"
#endif // _WIN32_WCE
// We need to disable this warning because of template class arguments
#pragma warning(disable: 4127)
#if (_ATL_VER >= 0x0900) && !defined(_SECURE_ATL)
#define _SECURE_ATL 1
#endif
///////////////////////////////////////////////////////////////////////////////
// WTL version number
#define _WTL_VER 0x0900
///////////////////////////////////////////////////////////////////////////////
// Classes in this file:
//
// CMessageFilter
// CIdleHandler
// CMessageLoop
//
// CAppModule
// CServerAppModule
//
// CRegKeyEx
//
// Global functions:
// AtlGetDefaultGuiFont()
// AtlCreateControlFont()
// AtlCreateBoldFont()
// AtlInitCommonControls()
///////////////////////////////////////////////////////////////////////////////
// Global support for Windows CE
#ifdef _WIN32_WCE
#ifndef SW_SHOWDEFAULT
#define SW_SHOWDEFAULT SW_SHOWNORMAL
#endif // !SW_SHOWDEFAULT
// These get's OR-ed in a constant and will have no effect.
// Defining them reduces the number of #ifdefs required for CE.
#define LR_DEFAULTSIZE 0
#define LR_LOADFROMFILE 0
#ifndef SM_CXCURSOR
#define SM_CXCURSOR 13
#endif
#ifndef SM_CYCURSOR
#define SM_CYCURSOR 14
#endif
inline BOOL IsMenu(HMENU hMenu)
{
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
::SetLastError(0);
BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii);
if(!bRet)
bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE;
return bRet;
}
#if (_WIN32_WCE >= 410)
extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight);
#endif // (_WIN32_WCE >= 410)
inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator)
{
__int64 multiple = nNumber * nNumerator;
return static_cast(multiple / nDenominator);
}
#if (_ATL_VER >= 0x0800)
#ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW
#ifdef WS_OVERLAPPEDWINDOW
#undef WS_OVERLAPPEDWINDOW
#define WS_OVERLAPPEDWINDOW 0
#endif // WS_OVERLAPPEDWINDOW
#endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW
#ifndef RDW_FRAME
#define RDW_FRAME 0
#endif // !RDW_FRAME
#ifndef WM_WINDOWPOSCHANGING
#define WM_WINDOWPOSCHANGING 0
#endif // !WM_WINDOWPOSCHANGING
#define FreeResource(x)
#define UnlockResource(x)
namespace ATL
{
inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw()
{ return E_NOTIMPL; }
inline HRESULT CComModule::RevokeClassObjects() throw()
{ return E_NOTIMPL; }
}; // namespace ATL
#ifndef lstrlenW
#define lstrlenW (int)ATL::lstrlenW
#endif // lstrlenW
inline int WINAPI lstrlenA(LPCSTR lpszString)
{ return ATL::lstrlenA(lpszString); }
#ifdef lstrcpyn
#undef lstrcpyn
#define lstrcpyn ATL::lstrcpynW
#endif // lstrcpyn
#ifndef SetWindowLongPtrW
inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
{
return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );
}
#define SetWindowLongPtrW tmp_SetWindowLongPtrW
#endif
#ifndef GetWindowLongPtrW
inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex )
{
return( ::GetWindowLongW( hWnd, nIndex ) );
}
#define GetWindowLongPtrW tmp_GetWindowLongPtrW
#endif
#ifndef LongToPtr
#define LongToPtr(x) ((void*)x)
#endif
#ifndef PtrToInt
#define PtrToInt( p ) ((INT)(INT_PTR) (p) )
#endif
#else // !(_ATL_VER >= 0x0800)
#ifdef lstrlenW
#undef lstrlenW
#define lstrlenW (int)::wcslen
#endif // lstrlenW
#define lstrlenA (int)strlen
#ifndef lstrcpyn
inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)
{
if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
return NULL;
int nLen = __min(lstrlen(lpstrSrc), nLength - 1);
LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR));
lpstrDest[nLen] = 0;
return lpstrRet;
}
#endif // !lstrcpyn
#ifndef lstrcpynW
inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength)
{
return lstrcpyn(lpstrDest, lpstrSrc, nLength); // WinCE is Unicode only
}
#endif // !lstrcpynW
#ifndef lstrcpynA
inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength)
{
if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
return NULL;
int nLen = __min(lstrlenA(lpstrSrc), nLength - 1);
LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char));
lpstrDest[nLen] = 0;
return lpstrRet;
}
#endif // !lstrcpyn
#ifdef TrackPopupMenu
#undef TrackPopupMenu
#endif // TrackPopupMenu
#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
static CWndClassInfo& GetWndClassInfo() \
{ \
static CWndClassInfo wc = \
{ \
{ style, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
}; \
return wc; \
}
#ifndef _MAX_FNAME
#define _MAX_FNAME _MAX_PATH
#endif // _MAX_FNAME
#if (_WIN32_WCE < 400)
#define MAKEINTATOM(i) (LPTSTR)((ULONG_PTR)((WORD)(i)))
#endif // (_WIN32_WCE < 400)
#if (_WIN32_WCE < 410)
#define WHEEL_PAGESCROLL (UINT_MAX)
#define WHEEL_DELTA 120
#endif // (_WIN32_WCE < 410)
#ifdef DrawIcon
#undef DrawIcon
#endif
#ifndef VARCMP_LT
#define VARCMP_LT 0
#endif
#ifndef VARCMP_EQ
#define VARCMP_EQ 1
#endif
#ifndef VARCMP_GT
#define VARCMP_GT 2
#endif
#ifndef VARCMP_NULL
#define VARCMP_NULL 3
#endif
#ifndef RDW_ALLCHILDREN
#define RDW_ALLCHILDREN 0
#endif
#endif // !(_ATL_VER >= 0x0800)
#endif // _WIN32_WCE
///////////////////////////////////////////////////////////////////////////////
// Global support for using original VC++ 6.0 headers with WTL
#if (_MSC_VER < 1300) && !defined(_WIN32_WCE)
#ifndef REG_QWORD
#define REG_QWORD 11
#endif
#ifndef BS_PUSHBOX
#define BS_PUSHBOX 0x0000000AL
#endif
struct __declspec(uuid("000214e6-0000-0000-c000-000000000046")) IShellFolder;
struct __declspec(uuid("000214f9-0000-0000-c000-000000000046")) IShellLinkW;
struct __declspec(uuid("000214ee-0000-0000-c000-000000000046")) IShellLinkA;
#endif // (_MSC_VER < 1300) && !defined(_WIN32_WCE)
#ifndef _ATL_NO_OLD_HEADERS_WIN64
#if !defined(_WIN64) && (_ATL_VER < 0x0700)
#ifndef PSM_INSERTPAGE
#define PSM_INSERTPAGE (WM_USER + 119)
#endif // !PSM_INSERTPAGE
#ifndef GetClassLongPtr
#define GetClassLongPtrA GetClassLongA
#define GetClassLongPtrW GetClassLongW
#ifdef UNICODE
#define GetClassLongPtr GetClassLongPtrW
#else
#define GetClassLongPtr GetClassLongPtrA
#endif // !UNICODE
#endif // !GetClassLongPtr
#ifndef GCLP_HICONSM
#define GCLP_HICONSM (-34)
#endif // !GCLP_HICONSM
#ifndef GetWindowLongPtr
#define GetWindowLongPtrA GetWindowLongA
#define GetWindowLongPtrW GetWindowLongW
#ifdef UNICODE
#define GetWindowLongPtr GetWindowLongPtrW
#else
#define GetWindowLongPtr GetWindowLongPtrA
#endif // !UNICODE
#endif // !GetWindowLongPtr
#ifndef SetWindowLongPtr
#define SetWindowLongPtrA SetWindowLongA
#define SetWindowLongPtrW SetWindowLongW
#ifdef UNICODE
#define SetWindowLongPtr SetWindowLongPtrW
#else
#define SetWindowLongPtr SetWindowLongPtrA
#endif // !UNICODE
#endif // !SetWindowLongPtr
#ifndef GWLP_WNDPROC
#define GWLP_WNDPROC (-4)
#endif
#ifndef GWLP_HINSTANCE
#define GWLP_HINSTANCE (-6)
#endif
#ifndef GWLP_HWNDPARENT
#define GWLP_HWNDPARENT (-8)
#endif
#ifndef GWLP_USERDATA
#define GWLP_USERDATA (-21)
#endif
#ifndef GWLP_ID
#define GWLP_ID (-12)
#endif
#ifndef DWLP_MSGRESULT
#define DWLP_MSGRESULT 0
#endif
typedef long LONG_PTR;
typedef unsigned long ULONG_PTR;
typedef ULONG_PTR DWORD_PTR;
#ifndef HandleToUlong
#define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
#endif
#ifndef HandleToLong
#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
#endif
#ifndef LongToHandle
#define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
#endif
#ifndef PtrToUlong
#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
#endif
#ifndef PtrToLong
#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
#endif
#ifndef PtrToUint
#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
#endif
#ifndef PtrToInt
#define PtrToInt( p ) ((INT)(INT_PTR) (p) )
#endif
#ifndef PtrToUshort
#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
#endif
#ifndef PtrToShort
#define PtrToShort( p ) ((short)(LONG_PTR)(p) )
#endif
#ifndef IntToPtr
#define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i))
#endif
#ifndef UIntToPtr
#define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui))
#endif
#ifndef LongToPtr
#define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l))
#endif
#ifndef ULongToPtr
#define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul))
#endif
#endif // !defined(_WIN64) && (_ATL_VER < 0x0700)
#endif // !_ATL_NO_OLD_HEADERS_WIN64
///////////////////////////////////////////////////////////////////////////////
// Global support for using original VC++ 7.x headers with WTL
#if (_MSC_VER >= 1300) && (_MSC_VER < 1400)
#ifndef BS_PUSHBOX
#define BS_PUSHBOX 0x0000000AL
#endif
#pragma warning(disable: 4244) // conversion from 'type1' to 'type2', possible loss of data
#endif // (_MSC_VER >= 1300) && (_MSC_VER < 1400)
///////////////////////////////////////////////////////////////////////////////
// Global support for old SDK headers
#ifndef BTNS_BUTTON
#define BTNS_BUTTON TBSTYLE_BUTTON
#endif
#ifndef BTNS_SEP
#define BTNS_SEP TBSTYLE_SEP
#endif
#ifndef BTNS_CHECK
#define BTNS_CHECK TBSTYLE_CHECK
#endif
#ifndef BTNS_GROUP
#define BTNS_GROUP TBSTYLE_GROUP
#endif
#ifndef BTNS_CHECKGROUP
#define BTNS_CHECKGROUP TBSTYLE_CHECKGROUP
#endif
#if (_WIN32_IE >= 0x0300)
#ifndef BTNS_DROPDOWN
#define BTNS_DROPDOWN TBSTYLE_DROPDOWN
#endif
#endif
#if (_WIN32_IE >= 0x0400)
#ifndef BTNS_AUTOSIZE
#define BTNS_AUTOSIZE TBSTYLE_AUTOSIZE
#endif
#ifndef BTNS_NOPREFIX
#define BTNS_NOPREFIX TBSTYLE_NOPREFIX
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
// Global support for SecureHelper functions
#ifndef _TRUNCATE
#define _TRUNCATE ((size_t)-1)
#endif
#ifndef _ERRCODE_DEFINED
#define _ERRCODE_DEFINED
typedef int errno_t;
#endif
#ifndef _SECURECRT_ERRCODE_VALUES_DEFINED
#define _SECURECRT_ERRCODE_VALUES_DEFINED
#define EINVAL 22
#define STRUNCATE 80
#endif
#ifndef _countof
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#endif
///////////////////////////////////////////////////////////////////////////////
// Miscellaneous global support
// define useful macros from winuser.h
#ifndef IS_INTRESOURCE
#define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
#endif // IS_INTRESOURCE
// protect template members from windowsx.h macros
#ifdef _INC_WINDOWSX
#undef SubclassWindow
#endif // _INC_WINDOWSX
// define useful macros from windowsx.h
#ifndef GET_X_LPARAM
#define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
#endif
#ifndef GET_Y_LPARAM
#define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
#endif
// Dummy structs for compiling with /CLR
#if (_MSC_VER >= 1300) && defined(_MANAGED)
__if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }
__if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }
__if_not_exists(_PSP::_PSP) { struct _PSP { }; }
#endif
// Define ATLVERIFY macro for ATL3
#if (_ATL_VER < 0x0700)
#ifndef ATLVERIFY
#ifdef _DEBUG
#define ATLVERIFY(expr) ATLASSERT(expr)
#else
#define ATLVERIFY(expr) (expr)
#endif // DEBUG
#endif // ATLVERIFY
#endif // (_ATL_VER < 0x0700)
// Forward declaration for ATL3 and ATL11 fix
#if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)
namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); };
#endif
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
namespace WTL
{
#if (_ATL_VER >= 0x0700)
DECLARE_TRACE_CATEGORY(atlTraceUI);
#ifdef _DEBUG
__declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));
#endif // _DEBUG
#else // !(_ATL_VER >= 0x0700)
enum wtlTraceFlags
{
atlTraceUI = 0x10000000
};
#endif // !(_ATL_VER >= 0x0700)
// Windows version helper
inline bool AtlIsOldWindows()
{
#ifdef _versionhelpers_H_INCLUDED_
return !::IsWindowsVersionOrGreater(4, 90, 0);
#else // !_versionhelpers_H_INCLUDED_
OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
BOOL bRet = ::GetVersionEx(&ovi);
return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90)));
#endif // _versionhelpers_H_INCLUDED_
}
// Default GUI font helper - "MS Shell Dlg" stock font
inline HFONT AtlGetDefaultGuiFont()
{
#ifndef _WIN32_WCE
return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
#else // CE specific
return (HFONT)::GetStockObject(SYSTEM_FONT);
#endif // _WIN32_WCE
}
// Control font helper - default font for controls not in a dialog
// (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
inline HFONT AtlCreateControlFont()
{
#ifndef _WIN32_WCE
LOGFONT lf = { 0 };
ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
HFONT hFont = ::CreateFontIndirect(&lf);
ATLASSERT(hFont != NULL);
return hFont;
#else // CE specific
return (HFONT)::GetStockObject(SYSTEM_FONT);
#endif // _WIN32_WCE
}
// Bold font helper
// (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)
{
LOGFONT lf = { 0 };
#ifndef _WIN32_WCE
if(hFont == NULL)
ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
else
ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT));
#else // CE specific
if(hFont == NULL)
hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT));
#endif // _WIN32_WCE
lf.lfWeight = FW_BOLD;
HFONT hFontBold = ::CreateFontIndirect(&lf);
ATLASSERT(hFontBold != NULL);
return hFontBold;
}
// Common Controls initialization helper
inline BOOL AtlInitCommonControls(DWORD dwFlags)
{
INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };
BOOL bRet = ::InitCommonControlsEx(&iccx);
ATLASSERT(bRet);
return bRet;
}
///////////////////////////////////////////////////////////////////////////////
// RunTimeHelper - helper functions for Windows version and structure sizes
// Not for Windows CE
#if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE)
#define _WTL_NO_RUNTIME_STRUCT_SIZE
#endif
#ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
#ifndef _SIZEOF_STRUCT
#define _SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
#endif
#if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
#define REBARBANDINFO_V6_SIZE _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)
#endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
#if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
#define LVGROUP_V5_SIZE _SIZEOF_STRUCT(LVGROUP, uAlign)
#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
#if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
#define LVTILEINFO_V5_SIZE _SIZEOF_STRUCT(LVTILEINFO, puColumns)
#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
#define MCHITTESTINFO_V1_SIZE _SIZEOF_STRUCT(MCHITTESTINFO, st)
#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
#if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
#define NONCLIENTMETRICS_V1_SIZE _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)
#endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
#if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0501) && !defined(TTTOOLINFO_V2_SIZE)
#define TTTOOLINFO_V2_SIZE _SIZEOF_STRUCT(TTTOOLINFO, lParam)
#endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0501) && !defined(TTTOOLINFO_V2_SIZE)
#endif // !_WTL_NO_RUNTIME_STRUCT_SIZE
namespace RunTimeHelper
{
#ifndef _WIN32_WCE
inline bool IsCommCtrl6()
{
DWORD dwMajor = 0, dwMinor = 0;
HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
return (SUCCEEDED(hRet) && (dwMajor >= 6));
}
inline bool IsVista()
{
#ifdef _versionhelpers_H_INCLUDED_
return ::IsWindowsVistaOrGreater();
#else // !_versionhelpers_H_INCLUDED_
OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
BOOL bRet = ::GetVersionEx(&ovi);
return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));
#endif // _versionhelpers_H_INCLUDED_
}
inline bool IsThemeAvailable()
{
bool bRet = false;
if(IsCommCtrl6())
{
HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
if(hThemeDLL != NULL)
{
typedef BOOL (STDAPICALLTYPE *PFN_IsThemeActive)();
PFN_IsThemeActive pfnIsThemeActive = (PFN_IsThemeActive)::GetProcAddress(hThemeDLL, "IsThemeActive");
ATLASSERT(pfnIsThemeActive != NULL);
bRet = (pfnIsThemeActive != NULL) && (pfnIsThemeActive() != FALSE);
if(bRet)
{
typedef BOOL (STDAPICALLTYPE *PFN_IsAppThemed)();
PFN_IsAppThemed pfnIsAppThemed = (PFN_IsAppThemed)::GetProcAddress(hThemeDLL, "IsAppThemed");
ATLASSERT(pfnIsAppThemed != NULL);
bRet = (pfnIsAppThemed != NULL) && (pfnIsAppThemed() != FALSE);
}
::FreeLibrary(hThemeDLL);
}
}
return bRet;
}
inline bool IsWin7()
{
#ifdef _versionhelpers_H_INCLUDED_
return ::IsWindows7OrGreater();
#else // !_versionhelpers_H_INCLUDED_
OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
BOOL bRet = ::GetVersionEx(&ovi);
return ((bRet != FALSE) && (ovi.dwMajorVersion == 6) && (ovi.dwMinorVersion >= 1));
#endif // _versionhelpers_H_INCLUDED_
}
inline bool IsRibbonUIAvailable()
{
static INT iRibbonUI = -1;
#if defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
if (iRibbonUI == -1)
{
HMODULE hRibbonDLL = ::LoadLibrary(_T("propsys.dll"));
if (hRibbonDLL != NULL)
{
const GUID CLSID_UIRibbonFramework = { 0x926749fa, 0x2615, 0x4987, { 0x88, 0x45, 0xc3, 0x3e, 0x65, 0xf2, 0xb9, 0x57 } };
// block - create instance
{
ATL::CComPtr pIUIFramework;
iRibbonUI = SUCCEEDED(pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework)) ? 1 : 0;
}
::FreeLibrary(hRibbonDLL);
}
else
{
iRibbonUI = 0;
}
}
#endif // defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
return (iRibbonUI == 1);
}
#endif // !_WIN32_WCE
inline int SizeOf_REBARBANDINFO()
{
int nSize = sizeof(REBARBANDINFO);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
if(!(IsVista() && IsCommCtrl6()))
nSize = REBARBANDINFO_V6_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
return nSize;
}
#if (_WIN32_WINNT >= 0x501)
inline int SizeOf_LVGROUP()
{
int nSize = sizeof(LVGROUP);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
if(!IsVista())
nSize = LVGROUP_V5_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
return nSize;
}
inline int SizeOf_LVTILEINFO()
{
int nSize = sizeof(LVTILEINFO);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
if(!IsVista())
nSize = LVTILEINFO_V5_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
return nSize;
}
#endif // (_WIN32_WINNT >= 0x501)
inline int SizeOf_MCHITTESTINFO()
{
int nSize = sizeof(MCHITTESTINFO);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
if(!(IsVista() && IsCommCtrl6()))
nSize = MCHITTESTINFO_V1_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
return nSize;
}
#ifndef _WIN32_WCE
inline int SizeOf_NONCLIENTMETRICS()
{
int nSize = sizeof(NONCLIENTMETRICS);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
if(!IsVista())
nSize = NONCLIENTMETRICS_V1_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
return nSize;
}
inline int SizeOf_TOOLINFO()
{
int nSize = sizeof(TOOLINFO);
#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0501)
if(!IsVista())
nSize = TTTOOLINFO_V2_SIZE;
#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0501)
return nSize;
}
#endif // !_WIN32_WCE
};
///////////////////////////////////////////////////////////////////////////////
// ModuleHelper - helper functions for ATL3 and ATL7 module classes
namespace ModuleHelper
{
inline HINSTANCE GetModuleInstance()
{
#if (_ATL_VER >= 0x0700)
return ATL::_AtlBaseModule.GetModuleInstance();
#else // !(_ATL_VER >= 0x0700)
return ATL::_pModule->GetModuleInstance();
#endif // !(_ATL_VER >= 0x0700)
}
inline HINSTANCE GetResourceInstance()
{
#if (_ATL_VER >= 0x0700)
return ATL::_AtlBaseModule.GetResourceInstance();
#else // !(_ATL_VER >= 0x0700)
return ATL::_pModule->GetResourceInstance();
#endif // !(_ATL_VER >= 0x0700)
}
inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)
{
#if (_ATL_VER >= 0x0700)
ATL::_AtlWinModule.AddCreateWndData(pData, pObject);
#else // !(_ATL_VER >= 0x0700)
ATL::_pModule->AddCreateWndData(pData, pObject);
#endif // !(_ATL_VER >= 0x0700)
}
inline void* ExtractCreateWndData()
{
#if (_ATL_VER >= 0x0700)
return ATL::_AtlWinModule.ExtractCreateWndData();
#else // !(_ATL_VER >= 0x0700)
return ATL::_pModule->ExtractCreateWndData();
#endif // !(_ATL_VER >= 0x0700)
}
};
///////////////////////////////////////////////////////////////////////////////
// SecureHelper - helper functions for VS2005 secure CRT
namespace SecureHelper
{
inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
{
#if _SECURE_ATL
ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);
#else
if(cchDest > (size_t)lstrlenA(lpstrSrc))
ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL);
else
ATLASSERT(FALSE);
#endif
}
inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
{
#if _SECURE_ATL
ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);
#else
if(cchDest > (size_t)lstrlenW(lpstrSrc))
ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL);
else
ATLASSERT(FALSE);
#endif
}
inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
{
#ifdef _UNICODE
strcpyW_x(lpstrDest, cchDest, lpstrSrc);
#else
strcpyA_x(lpstrDest, cchDest, lpstrSrc);
#endif
}
inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)
{
#if _SECURE_ATL
return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
#else
errno_t nRet = 0;
if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
{
nRet = EINVAL;
}
else if(cchCount == _TRUNCATE)
{
cchCount = __min(cchDest - 1, size_t(lstrlenA(lpstrSrc)));
nRet = STRUNCATE;
}
else if(cchDest <= cchCount)
{
lpstrDest[0] = 0;
nRet = EINVAL;
}
if(nRet == 0 || nRet == STRUNCATE)
nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
ATLASSERT(nRet == 0 || nRet == STRUNCATE);
return nRet;
#endif
}
inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)
{
#if _SECURE_ATL
return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
#else
errno_t nRet = 0;
if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
{
nRet = EINVAL;
}
else if(cchCount == _TRUNCATE)
{
cchCount = __min(cchDest - 1, size_t(lstrlenW(lpstrSrc)));
nRet = STRUNCATE;
}
else if(cchDest <= cchCount)
{
lpstrDest[0] = 0;
nRet = EINVAL;
}
if(nRet == 0 || nRet == STRUNCATE)
nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
ATLASSERT(nRet == 0 || nRet == STRUNCATE);
return nRet;
#endif
}
inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)
{
#ifdef _UNICODE
return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);
#else
return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);
#endif
}
inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
{
#if _SECURE_ATL
ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);
#else
if(cchDest > (size_t)lstrlenA(lpstrSrc))
ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL);
else
ATLASSERT(FALSE);
#endif
}
inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
{
#if _SECURE_ATL
ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);
#else
if(cchDest > (size_t)lstrlenW(lpstrSrc))
ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL);
else
ATLASSERT(FALSE);
#endif
}
inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
{
#ifdef _UNICODE
strcatW_x(lpstrDest, cchDest, lpstrSrc);
#else
strcatA_x(lpstrDest, cchDest, lpstrSrc);
#endif
}
inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
{
#if _SECURE_ATL
ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);
#else
if(cbDest >= cbSrc)
memcpy(pDest, pSrc, cbSrc);
else
ATLASSERT(FALSE);
#endif
}
inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
{
#if _SECURE_ATL
ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);
#else
if(cbDest >= cbSrc)
memmove(pDest, pSrc, cbSrc);
else
ATLASSERT(FALSE);
#endif
}
inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
{
#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
#else
cchBuff; // Avoid unused argument warning
#pragma warning(push)
#pragma warning(disable: 4996)
return _vstprintf(lpstrBuff, lpstrFormat, args);
#pragma warning(pop)
#endif
}
inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
{
#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
#else
cchBuff; // Avoid unused argument warning
return ::wvsprintf(lpstrBuff, lpstrFormat, args);
#endif
}
inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
{
va_list args;
va_start(args, lpstrFormat);
int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
va_end(args);
return nRes;
}
inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
{
va_list args;
va_start(args, lpstrFormat);
int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
va_end(args);
return nRes;
}
}; // namespace SecureHelper
///////////////////////////////////////////////////////////////////////////////
// MinCrtHelper - helper functions for using _ATL_MIN_CRT
namespace MinCrtHelper
{
inline int _isspace(TCHAR ch)
{
#ifndef _ATL_MIN_CRT
return _istspace(ch);
#else // _ATL_MIN_CRT
WORD type = 0;
::GetStringTypeEx(::GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
return (type & C1_SPACE) == C1_SPACE;
#endif // _ATL_MIN_CRT
}
inline int _isdigit(TCHAR ch)
{
#ifndef _ATL_MIN_CRT
return _istdigit(ch);
#else // _ATL_MIN_CRT
WORD type = 0;
::GetStringTypeEx(::GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
return (type & C1_DIGIT) == C1_DIGIT;
#endif // _ATL_MIN_CRT
}
inline int _atoi(LPCTSTR str)
{
#ifndef _ATL_MIN_CRT
return _ttoi(str);
#else // _ATL_MIN_CRT
while(_isspace(*str) != 0)
++str;
TCHAR ch = *str++;
TCHAR sign = ch; // save sign indication
if(ch == _T('-') || ch == _T('+'))
ch = *str++; // skip sign
int total = 0;
while(_isdigit(ch) != 0)
{
total = 10 * total + (ch - '0'); // accumulate digit
ch = *str++; // get next char
}
return (sign == '-') ? -total : total; // return result, negated if necessary
#endif // _ATL_MIN_CRT
}
inline LPCTSTR _strrchr(LPCTSTR str, TCHAR ch)
{
#ifndef _ATL_MIN_CRT
return _tcsrchr(str, ch);
#else // _ATL_MIN_CRT
LPCTSTR lpsz = NULL;
while(*str != 0)
{
if(*str == ch)
lpsz = str;
str = ::CharNext(str);
}
return lpsz;
#endif // _ATL_MIN_CRT
}
inline LPTSTR _strrchr(LPTSTR str, TCHAR ch)
{
#ifndef _ATL_MIN_CRT
return _tcsrchr(str, ch);
#else // _ATL_MIN_CRT
LPTSTR lpsz = NULL;
while(*str != 0)
{
if(*str == ch)
lpsz = str;
str = ::CharNext(str);
}
return lpsz;
#endif // _ATL_MIN_CRT
}
}; // namespace MinCrtHelper
///////////////////////////////////////////////////////////////////////////////
// GenericWndClass - generic window class usable for subclassing
// Use in dialog templates to specify a placeholder to be subclassed
// Specify as a custom control with class name WTL_GenericWindow
// Call Rregister() before creating dialog (for example, in WinMain)
namespace GenericWndClass
{
inline LPCTSTR GetName()
{
return _T("WTL_GenericWindow");
}
inline ATOM Register()
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
wc.lpfnWndProc = ::DefWindowProc;
wc.hInstance = ModuleHelper::GetModuleInstance();
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = GetName();
ATOM atom = ::RegisterClassEx(&wc);
ATLASSERT(atom != 0);
return atom;
}
inline BOOL Unregister() // only needed for DLLs or tmp use
{
return ::UnregisterClass(GetName(), ModuleHelper::GetModuleInstance());
}
}; // namespace GenericWndClass
///////////////////////////////////////////////////////////////////////////////
// CMessageFilter - Interface for message filter support
class CMessageFilter
{
public:
virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
};
///////////////////////////////////////////////////////////////////////////////
// CIdleHandler - Interface for idle processing
class CIdleHandler
{
public:
virtual BOOL OnIdle() = 0;
};
#ifndef _ATL_NO_OLD_NAMES
// for compatilibility with old names only
typedef CIdleHandler CUpdateUIObject;
#define DoUpdate OnIdle
#endif // !_ATL_NO_OLD_NAMES
///////////////////////////////////////////////////////////////////////////////
// CMessageLoop - message loop implementation
class CMessageLoop
{
public:
ATL::CSimpleArray m_aMsgFilter;
ATL::CSimpleArray m_aIdleHandler;
MSG m_msg;
// Message filter operations
BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Add(pMessageFilter);
}
BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Remove(pMessageFilter);
}
// Idle handler operations
BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
{
return m_aIdleHandler.Add(pIdleHandler);
}
BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
{
return m_aIdleHandler.Remove(pIdleHandler);
}
#ifndef _ATL_NO_OLD_NAMES
// for compatilibility with old names only
BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
{
ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
return AddIdleHandler(pIdleHandler);
}
BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
{
ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
return RemoveIdleHandler(pIdleHandler);
}
#endif // !_ATL_NO_OLD_NAMES
// message loop
int Run()
{
BOOL bDoIdle = TRUE;
int nIdleCount = 0;
BOOL bRet;
for(;;)
{
while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
{
if(!OnIdle(nIdleCount++))
bDoIdle = FALSE;
}
bRet = ::GetMessage(&m_msg, NULL, 0, 0);
if(bRet == -1)
{
ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
continue; // error, don't process
}
else if(!bRet)
{
ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
break; // WM_QUIT, exit message loop
}
if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}
if(IsIdleMessage(&m_msg))
{
bDoIdle = TRUE;
nIdleCount = 0;
}
}
return (int)m_msg.wParam;
}
static BOOL IsIdleMessage(MSG* pMsg)
{
// These messages should NOT cause idle processing
switch(pMsg->message)
{
case WM_MOUSEMOVE:
#ifndef _WIN32_WCE
case WM_NCMOUSEMOVE:
#endif // !_WIN32_WCE
case WM_PAINT:
case 0x0118: // WM_SYSTIMER (caret blink)
return FALSE;
}
return TRUE;
}
// Overrideables
// Override to change message filtering
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
// loop backwards
for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
{
CMessageFilter* pMessageFilter = m_aMsgFilter[i];
if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
return TRUE;
}
return FALSE; // not translated
}
// override to change idle processing
virtual BOOL OnIdle(int /*nIdleCount*/)
{
for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
{
CIdleHandler* pIdleHandler = m_aIdleHandler[i];
if(pIdleHandler != NULL)
pIdleHandler->OnIdle();
}
return FALSE; // don't continue
}
};
///////////////////////////////////////////////////////////////////////////////
// CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock
// internal classes to manage critical sections for both ATL3 and ATL7
class CStaticDataInitCriticalSectionLock
{
public:
#if (_ATL_VER >= 0x0700)
ATL::CComCritSecLock m_cslock;
CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)
{ }
#endif // (_ATL_VER >= 0x0700)
HRESULT Lock()
{
#if (_ATL_VER >= 0x0700)
return m_cslock.Lock();
#else // !(_ATL_VER >= 0x0700)
::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit);
return S_OK;
#endif // !(_ATL_VER >= 0x0700)
}
void Unlock()
{
#if (_ATL_VER >= 0x0700)
m_cslock.Unlock();
#else // !(_ATL_VER >= 0x0700)
::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit);
#endif // !(_ATL_VER >= 0x0700)
}
};
class CWindowCreateCriticalSectionLock
{
public:
#if (_ATL_VER >= 0x0700)
ATL::CComCritSecLock m_cslock;
CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)
{ }
#endif // (_ATL_VER >= 0x0700)
HRESULT Lock()
{
#if (_ATL_VER >= 0x0700)
return m_cslock.Lock();
#else // !(_ATL_VER >= 0x0700)
::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate);
return S_OK;
#endif // !(_ATL_VER >= 0x0700)
}
void Unlock()
{
#if (_ATL_VER >= 0x0700)
m_cslock.Unlock();
#else // !(_ATL_VER >= 0x0700)
::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate);
#endif // !(_ATL_VER >= 0x0700)
}
};
///////////////////////////////////////////////////////////////////////////////
// CTempBuffer - helper class for stack allocations for ATL3
#ifndef _WTL_STACK_ALLOC_THRESHOLD
#define _WTL_STACK_ALLOC_THRESHOLD 512
#endif
#if (_ATL_VER >= 0x0700)
using ATL::CTempBuffer;
#else // !(_ATL_VER >= 0x0700)
#ifndef SIZE_MAX
#ifdef _WIN64
#define SIZE_MAX _UI64_MAX
#else
#define SIZE_MAX UINT_MAX
#endif
#endif
#pragma warning(push)
#pragma warning(disable: 4284) // warning for operator ->
template
class CTempBuffer
{
public:
CTempBuffer() : m_p(NULL)
{
}
CTempBuffer(size_t nElements) : m_p(NULL)
{
Allocate(nElements);
}
~CTempBuffer()
{
if(m_p != reinterpret_cast(m_abFixedBuffer))
free(m_p);
}
operator T*() const
{
return m_p;
}
T* operator ->() const
{
ATLASSERT(m_p != NULL);
return m_p;
}
T* Allocate(size_t nElements)
{
ATLASSERT(nElements <= (SIZE_MAX / sizeof(T)));
return AllocateBytes(nElements * sizeof(T));
}
T* AllocateBytes(size_t nBytes)
{
ATLASSERT(m_p == NULL);
if(nBytes > t_nFixedBytes)
m_p = static_cast(malloc(nBytes));
else
m_p = reinterpret_cast(m_abFixedBuffer);
return m_p;
}
private:
T* m_p;
BYTE m_abFixedBuffer[t_nFixedBytes];
};
#pragma warning(pop)
#endif // !(_ATL_VER >= 0x0700)
///////////////////////////////////////////////////////////////////////////////
// CAppModule - module class for an application
class CAppModule : public ATL::CComModule
{
public:
DWORD m_dwMainThreadID;
ATL::CSimpleMap* m_pMsgLoopMap;
ATL::CSimpleArray* m_pSettingChangeNotify;
// Overrides of CComModule::Init and Term
HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
{
HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
if(FAILED(hRet))
return hRet;
m_dwMainThreadID = ::GetCurrentThreadId();
typedef ATL::CSimpleMap _mapClass;
m_pMsgLoopMap = NULL;
ATLTRY(m_pMsgLoopMap = new _mapClass);
if(m_pMsgLoopMap == NULL)
return E_OUTOFMEMORY;
m_pSettingChangeNotify = NULL;
return hRet;
}
void Term()
{
TermSettingChangeNotify();
delete m_pMsgLoopMap;
CComModule::Term();
}
// Message loop map methods
BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
ATLASSERT(FALSE);
return FALSE;
}
ATLASSERT(pMsgLoop != NULL);
ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL); // not in map yet
BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);
lock.Unlock();
return bRet;
}
BOOL RemoveMessageLoop()
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));
ATLASSERT(FALSE);
return FALSE;
}
BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());
lock.Unlock();
return bRet;
}
CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));
ATLASSERT(FALSE);
return NULL;
}
CMessageLoop* pLoop = m_pMsgLoopMap->Lookup(dwThreadID);
lock.Unlock();
return pLoop;
}
// Setting change notify methods
// Note: Call this from the main thread for MSDI apps
BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
ATLASSERT(FALSE);
return FALSE;
}
if(m_pSettingChangeNotify == NULL)
{
typedef ATL::CSimpleArray _notifyClass;
ATLTRY(m_pSettingChangeNotify = new _notifyClass);
ATLASSERT(m_pSettingChangeNotify != NULL);
}
BOOL bRet = (m_pSettingChangeNotify != NULL);
if(bRet && m_pSettingChangeNotify->GetSize() == 0)
{
// init everything
_ATL_EMPTY_DLGTEMPLATE templ;
HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
ATLASSERT(::IsWindow(hNtfWnd));
if(::IsWindow(hNtfWnd))
{
// need conditional code because types don't match in winuser.h
#ifdef _WIN64
::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
#else
::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));
#endif
bRet = m_pSettingChangeNotify->Add(hNtfWnd);
}
else
{
bRet = FALSE;
}
}
lock.Unlock();
return bRet;
}
void TermSettingChangeNotify()
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
ATLASSERT(FALSE);
return;
}
if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)
::DestroyWindow((*m_pSettingChangeNotify)[0]);
delete m_pSettingChangeNotify;
m_pSettingChangeNotify = NULL;
lock.Unlock();
}
BOOL AddSettingChangeNotify(HWND hWnd)
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
ATLASSERT(FALSE);
return FALSE;
}
ATLASSERT(::IsWindow(hWnd));
BOOL bRet = FALSE;
if(InitSettingChangeNotify() != FALSE)
bRet = m_pSettingChangeNotify->Add(hWnd);
lock.Unlock();
return bRet;
}
BOOL RemoveSettingChangeNotify(HWND hWnd)
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
ATLASSERT(FALSE);
return FALSE;
}
BOOL bRet = FALSE;
if(m_pSettingChangeNotify != NULL)
bRet = m_pSettingChangeNotify->Remove(hWnd);
lock.Unlock();
return bRet;
}
// Implementation - setting change notify dialog template and dialog procedure
struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
{
_ATL_EMPTY_DLGTEMPLATE()
{
memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
style = WS_POPUP;
}
WORD wMenu, wClass, wTitle;
};
#ifdef _WIN64
static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#else
static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#endif
{
if(uMsg == WM_SETTINGCHANGE)
{
// need conditional code because types don't match in winuser.h
#ifdef _WIN64
CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
#else
CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
#endif
ATLASSERT(pModule != NULL);
ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
const UINT uTimeout = 1500; // ms
for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
{
#if !defined(_WIN32_WCE)
::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);
#elif(_WIN32_WCE >= 400) // CE specific
::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL);
#else // _WIN32_WCE < 400 specific
uTimeout;
::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam);
#endif
}
return TRUE;
}
return FALSE;
}
};
///////////////////////////////////////////////////////////////////////////////
// CServerAppModule - module class for a COM server application
class CServerAppModule : public CAppModule
{
public:
HANDLE m_hEventShutdown;
bool m_bActivity;
DWORD m_dwTimeOut;
DWORD m_dwPause;
// Override of CAppModule::Init
HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
{
m_dwTimeOut = 5000;
m_dwPause = 1000;
return CAppModule::Init(pObjMap, hInstance, pLibID);
}
void Term()
{
if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown))
m_hEventShutdown = NULL;
CAppModule::Term();
}
// COM Server methods
LONG Unlock()
{
LONG lRet = CComModule::Unlock();
if(lRet == 0)
{
m_bActivity = true;
::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
}
return lRet;
}
void MonitorShutdown()
{
for(;;)
{
::WaitForSingleObject(m_hEventShutdown, INFINITE);
DWORD dwWait = 0;
do
{
m_bActivity = false;
dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
}
while(dwWait == WAIT_OBJECT_0);
// timed out
if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail
{
#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE)
::CoSuspendClassObjects();
if(!m_bActivity && m_nLockCnt == 0)
#endif
break;
}
}
// This handle should be valid now. If it isn't,
// check if _Module.Term was called first (it shouldn't)
if(::CloseHandle(m_hEventShutdown))
m_hEventShutdown = NULL;
::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
}
bool StartMonitor()
{
m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
if(m_hEventShutdown == NULL)
return false;
DWORD dwThreadID = 0;
#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
#else
HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
#endif
bool bRet = (hThread != NULL);
if(bRet)
::CloseHandle(hThread);
return bRet;
}
static DWORD WINAPI MonitorProc(void* pv)
{
CServerAppModule* p = (CServerAppModule*)pv;
p->MonitorShutdown();
return 0;
}
#if (_ATL_VER < 0x0700)
// search for an occurence of string p2 in string p1
static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
{
while(p1 != NULL && *p1 != NULL)
{
LPCTSTR p = p2;
while(p != NULL && *p != NULL)
{
if(*p1 == *p)
return ::CharNext(p1);
p = ::CharNext(p);
}
p1 = ::CharNext(p1);
}
return NULL;
}
#endif // (_ATL_VER < 0x0700)
};
///////////////////////////////////////////////////////////////////////////////
// CRegKeyEx - adds type-specific methods to ATL3 CRegKey
#if (_ATL_VER < 0x0700)
class CRegKeyEx : public ATL::CRegKey
{
public:
// Constructors and operators
CRegKeyEx(HKEY hKey = NULL)
{
m_hKey = hKey;
}
CRegKeyEx(CRegKeyEx& key)
{
Attach(key.Detach());
}
CRegKeyEx& operator =(CRegKeyEx& key)
{
Close();
Attach(key.Detach());
return *this;
}
// Methods
LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes)
{
ATLASSERT(m_hKey != NULL);
return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, static_cast(pValue), nBytes);
}
LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue)
{
ATLASSERT(m_hKey != NULL);
OLECHAR szGUID[64] = { 0 };
::StringFromGUID2(guidValue, szGUID, 64);
USES_CONVERSION;
LPCTSTR lpstr = OLE2CT(szGUID);
#ifndef _UNICODE
if(lpstr == NULL)
return E_OUTOFMEMORY;
#endif
return SetStringValue(pszValueName, lpstr);
}
LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes)
{
ATLASSERT(m_hKey != NULL);
return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_BINARY, reinterpret_cast(pValue), nBytes);
}
LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue)
{
ATLASSERT(m_hKey != NULL);
return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_DWORD, reinterpret_cast(&dwValue), sizeof(DWORD));
}
#ifndef _WIN32_WCE
LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue)
{
ATLASSERT(m_hKey != NULL);
return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_QWORD, reinterpret_cast(&qwValue), sizeof(ULONGLONG));
}
#endif
LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ)
{
ATLASSERT(m_hKey != NULL);
if(pszValue == NULL)
{
ATLASSERT(FALSE);
return ERROR_INVALID_DATA;
}
ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ));
return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, reinterpret_cast(pszValue), (lstrlen(pszValue) + 1) * sizeof(TCHAR));
}
LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue)
{
ATLASSERT(m_hKey != NULL);
if(pszValue == NULL)
{
ATLASSERT(FALSE);
return ERROR_INVALID_DATA;
}
ULONG nBytes = 0;
ULONG nLength = 0;
LPCTSTR pszTemp = pszValue;
do
{
nLength = lstrlen(pszTemp) + 1;
pszTemp += nLength;
nBytes += nLength * sizeof(TCHAR);
} while (nLength != 1);
return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_MULTI_SZ, reinterpret_cast(pszValue), nBytes);
}
LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes)
{
ATLASSERT(m_hKey != NULL);
return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, static_cast(pData), pnBytes);
}
LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue)
{
ATLASSERT(m_hKey != NULL);
guidValue = GUID_NULL;
TCHAR szGUID[64] = { 0 };
ULONG nCount = 64;
LONG lRes = QueryStringValue(pszValueName, szGUID, &nCount);
if (lRes != ERROR_SUCCESS)
return lRes;
if(szGUID[0] != _T('{'))
return ERROR_INVALID_DATA;
USES_CONVERSION;
LPOLESTR lpstr = T2OLE(szGUID);
#ifndef _UNICODE
if(lpstr == NULL)
return E_OUTOFMEMORY;
#endif
HRESULT hr = ::CLSIDFromString(lpstr, &guidValue);
if (FAILED(hr))
return ERROR_INVALID_DATA;
return ERROR_SUCCESS;
}
LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes)
{
ATLASSERT(pnBytes != NULL);
ATLASSERT(m_hKey != NULL);
DWORD dwType = 0;
LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pValue), pnBytes);
if (lRes != ERROR_SUCCESS)
return lRes;
if (dwType != REG_BINARY)
return ERROR_INVALID_DATA;
return ERROR_SUCCESS;
}
LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue)
{
ATLASSERT(m_hKey != NULL);
ULONG nBytes = sizeof(DWORD);
DWORD dwType = 0;
LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&dwValue), &nBytes);
if (lRes != ERROR_SUCCESS)
return lRes;
if (dwType != REG_DWORD)
return ERROR_INVALID_DATA;
return ERROR_SUCCESS;
}
#ifndef _WIN32_WCE
LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue)
{
ATLASSERT(m_hKey != NULL);
ULONG nBytes = sizeof(ULONGLONG);
DWORD dwType = 0;
LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&qwValue), &nBytes);
if (lRes != ERROR_SUCCESS)
return lRes;
if (dwType != REG_QWORD)
return ERROR_INVALID_DATA;
return ERROR_SUCCESS;
}
#endif
LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars)
{
ATLASSERT(m_hKey != NULL);
ATLASSERT(pnChars != NULL);
ULONG nBytes = (*pnChars) * sizeof(TCHAR);
DWORD dwType = 0;
*pnChars = 0;
LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), &nBytes);
if (lRes != ERROR_SUCCESS)
{
return lRes;
}
if(dwType != REG_SZ && dwType != REG_EXPAND_SZ)
{
return ERROR_INVALID_DATA;
}
if (pszValue != NULL)
{
if(nBytes != 0)
{
if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) -1] != 0))
return ERROR_INVALID_DATA;
}
else
{
pszValue[0] = _T('\0');
}
}
*pnChars = nBytes / sizeof(TCHAR);
return ERROR_SUCCESS;
}
LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars)
{
ATLASSERT(m_hKey != NULL);
ATLASSERT(pnChars != NULL);
if (pszValue != NULL && *pnChars < 2)
return ERROR_INSUFFICIENT_BUFFER;
ULONG nBytes = (*pnChars) * sizeof(TCHAR);
DWORD dwType = 0;
*pnChars = 0;
LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), &nBytes);
if (lRes != ERROR_SUCCESS)
return lRes;
if (dwType != REG_MULTI_SZ)
return ERROR_INVALID_DATA;
if (pszValue != NULL && (nBytes % sizeof(TCHAR) != 0 || nBytes / sizeof(TCHAR) < 1 || pszValue[nBytes / sizeof(TCHAR) - 1] != 0 || ((nBytes / sizeof(TCHAR)) > 1 && pszValue[nBytes / sizeof(TCHAR) - 2] != 0)))
return ERROR_INVALID_DATA;
*pnChars = nBytes / sizeof(TCHAR);
return ERROR_SUCCESS;
}
};
#else // !(_ATL_VER < 0x0700)
typedef ATL::CRegKey CRegKeyEx;
#endif // !(_ATL_VER < 0x0700)
///////////////////////////////////////////////////////////////////////////////
// CString forward reference (enables CString use in atluser.h and atlgdi.h)
#if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
#define _WTL_USE_CSTRING
#endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
#ifdef _WTL_USE_CSTRING
class CString; // forward declaration (include atlmisc.h for the whole class)
#endif // _WTL_USE_CSTRING
// CString namespace
#ifndef _CSTRING_NS
#ifdef __ATLSTR_H__
#define _CSTRING_NS ATL
#else
#define _CSTRING_NS WTL
#endif
#endif // _CSTRING_NS
// Type classes namespace
#ifndef _WTYPES_NS
#ifdef __ATLTYPES_H__
#define _WTYPES_NS
#else
#define _WTYPES_NS WTL
#endif
#endif // _WTYPES_NS
}; // namespace WTL
///////////////////////////////////////////////////////////////////////////////
// General DLL version helpers
// (ATL3: excluded from atlbase.h if _ATL_DLL is defined; ATL11: removed)
#if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)
namespace ATL
{
inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)
{
ATLASSERT(pDllVersionInfo != NULL);
if(pDllVersionInfo == NULL)
return E_INVALIDARG;
// We must get this function explicitly because some DLLs don't implement it.
DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");
if(pfnDllGetVersion == NULL)
return E_NOTIMPL;
return (*pfnDllGetVersion)(pDllVersionInfo);
}
inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)
{
HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);
if(hInstDLL == NULL)
return E_FAIL;
HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);
::FreeLibrary(hInstDLL);
return hRet;
}
// Common Control Versions:
// Win95/WinNT 4.0 maj=4 min=00
// IE 3.x maj=4 min=70
// IE 4.0 maj=4 min=71
inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
{
ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
if(pdwMajor == NULL || pdwMinor == NULL)
return E_INVALIDARG;
DLLVERSIONINFO dvi;
::ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);
if(SUCCEEDED(hRet))
{
*pdwMajor = dvi.dwMajorVersion;
*pdwMinor = dvi.dwMinorVersion;
}
else if(hRet == E_NOTIMPL)
{
// If DllGetVersion is not there, then the DLL is a version
// previous to the one shipped with IE 3.x
*pdwMajor = 4;
*pdwMinor = 0;
hRet = S_OK;
}
return hRet;
}
// Shell Versions:
// Win95/WinNT 4.0 maj=4 min=00
// IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00
// IE 4.0 with Web Integrated Desktop maj=4 min=71
// IE 4.01 with Web Integrated Desktop maj=4 min=72
inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
{
ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
if(pdwMajor == NULL || pdwMinor == NULL)
return E_INVALIDARG;
DLLVERSIONINFO dvi;
::ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);
if(SUCCEEDED(hRet))
{
*pdwMajor = dvi.dwMajorVersion;
*pdwMinor = dvi.dwMinorVersion;
}
else if(hRet == E_NOTIMPL)
{
// If DllGetVersion is not there, then the DLL is a version
// previous to the one shipped with IE 4.x
*pdwMajor = 4;
*pdwMinor = 0;
hRet = S_OK;
}
return hRet;
}
}; // namespace ATL
#endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)
// These are always included
#include "atlwinx.h"
#include "atluser.h"
#include "atlgdi.h"
#ifndef _WTL_NO_AUTOMATIC_NAMESPACE
using namespace WTL;
#endif // !_WTL_NO_AUTOMATIC_NAMESPACE
#endif // __ATLAPP_H__
================================================
FILE: src/Setup/wtl90/atlcrack.h
================================================
// Windows Template Library - WTL version 9.0
// Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
//
// This file is a part of the Windows Template Library.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
#ifndef __ATLCRACK_H__
#define __ATLCRACK_H__
#pragma once
#ifndef __ATLAPP_H__
#error atlcrack.h requires atlapp.h to be included first
#endif
///////////////////////////////////////////////////////////////////////////////
// Message map macro for cracked handlers
// Note about message maps with cracked handlers:
// For ATL 3.0, a message map using cracked handlers MUST use BEGIN_MSG_MAP_EX.
// For ATL 7.0 or higher, you can use BEGIN_MSG_MAP for CWindowImpl/CDialogImpl derived classes,
// but must use BEGIN_MSG_MAP_EX for classes that don't derive from CWindowImpl/CDialogImpl.
#define BEGIN_MSG_MAP_EX(theClass) \
public: \
BOOL m_bMsgHandled; \
/* "handled" management for cracked handlers */ \
BOOL IsMsgHandled() const \
{ \
return m_bMsgHandled; \
} \
void SetMsgHandled(BOOL bHandled) \
{ \
m_bMsgHandled = bHandled; \
} \
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
{ \
BOOL bOldMsgHandled = m_bMsgHandled; \
BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \
m_bMsgHandled = bOldMsgHandled; \
return bRet; \
} \
BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \
{ \
BOOL bHandled = TRUE; \
hWnd; \
uMsg; \
wParam; \
lParam; \
lResult; \
bHandled; \
switch(dwMsgMapID) \
{ \
case 0:
///////////////////////////////////////////////////////////////////////////////
// Standard Windows message macros
// int OnCreate(LPCREATESTRUCT lpCreateStruct)
#define MSG_WM_CREATE(func) \
if (uMsg == WM_CREATE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
#define MSG_WM_INITDIALOG(func) \
if (uMsg == WM_INITDIALOG) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HWND)wParam, lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnCopyData(CWindow wnd, PCOPYDATASTRUCT pCopyDataStruct)
#define MSG_WM_COPYDATA(func) \
if (uMsg == WM_COPYDATA) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HWND)wParam, (PCOPYDATASTRUCT)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDestroy()
#define MSG_WM_DESTROY(func) \
if (uMsg == WM_DESTROY) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMove(CPoint ptPos)
#define MSG_WM_MOVE(func) \
if (uMsg == WM_MOVE) \
{ \
SetMsgHandled(TRUE); \
func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSize(UINT nType, CSize size)
#define MSG_WM_SIZE(func) \
if (uMsg == WM_SIZE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnActivate(UINT nState, BOOL bMinimized, CWindow wndOther)
#define MSG_WM_ACTIVATE(func) \
if (uMsg == WM_ACTIVATE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)LOWORD(wParam), (BOOL)HIWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSetFocus(CWindow wndOld)
#define MSG_WM_SETFOCUS(func) \
if (uMsg == WM_SETFOCUS) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnKillFocus(CWindow wndFocus)
#define MSG_WM_KILLFOCUS(func) \
if (uMsg == WM_KILLFOCUS) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnEnable(BOOL bEnable)
#define MSG_WM_ENABLE(func) \
if (uMsg == WM_ENABLE) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnPaint(CDCHandle dc)
#define MSG_WM_PAINT(func) \
if (uMsg == WM_PAINT) \
{ \
SetMsgHandled(TRUE); \
func((HDC)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnClose()
#define MSG_WM_CLOSE(func) \
if (uMsg == WM_CLOSE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnQueryEndSession(UINT nSource, UINT uLogOff)
#define MSG_WM_QUERYENDSESSION(func) \
if (uMsg == WM_QUERYENDSESSION) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)wParam, (UINT)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnQueryOpen()
#define MSG_WM_QUERYOPEN(func) \
if (uMsg == WM_QUERYOPEN) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func(); \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnEraseBkgnd(CDCHandle dc)
#define MSG_WM_ERASEBKGND(func) \
if (uMsg == WM_ERASEBKGND) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSysColorChange()
#define MSG_WM_SYSCOLORCHANGE(func) \
if (uMsg == WM_SYSCOLORCHANGE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnEndSession(BOOL bEnding, UINT uLogOff)
#define MSG_WM_ENDSESSION(func) \
if (uMsg == WM_ENDSESSION) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam, (UINT)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnShowWindow(BOOL bShow, UINT nStatus)
#define MSG_WM_SHOWWINDOW(func) \
if (uMsg == WM_SHOWWINDOW) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam, (int)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnCtlColorEdit(CDCHandle dc, CEdit edit)
#define MSG_WM_CTLCOLOREDIT(func) \
if (uMsg == WM_CTLCOLOREDIT) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnCtlColorListBox(CDCHandle dc, CListBox listBox)
#define MSG_WM_CTLCOLORLISTBOX(func) \
if (uMsg == WM_CTLCOLORLISTBOX) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnCtlColorBtn(CDCHandle dc, CButton button)
#define MSG_WM_CTLCOLORBTN(func) \
if (uMsg == WM_CTLCOLORBTN) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnCtlColorDlg(CDCHandle dc, CWindow wnd)
#define MSG_WM_CTLCOLORDLG(func) \
if (uMsg == WM_CTLCOLORDLG) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
#define MSG_WM_CTLCOLORSCROLLBAR(func) \
if (uMsg == WM_CTLCOLORSCROLLBAR) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic)
#define MSG_WM_CTLCOLORSTATIC(func) \
if (uMsg == WM_CTLCOLORSTATIC) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
#define MSG_WM_SETTINGCHANGE(func) \
if (uMsg == WM_SETTINGCHANGE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPCTSTR)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDevModeChange(LPCTSTR lpDeviceName)
#define MSG_WM_DEVMODECHANGE(func) \
if (uMsg == WM_DEVMODECHANGE) \
{ \
SetMsgHandled(TRUE); \
func((LPCTSTR)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnActivateApp(BOOL bActive, DWORD dwThreadID)
#define MSG_WM_ACTIVATEAPP(func) \
if (uMsg == WM_ACTIVATEAPP) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam, (DWORD)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnFontChange()
#define MSG_WM_FONTCHANGE(func) \
if (uMsg == WM_FONTCHANGE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnTimeChange()
#define MSG_WM_TIMECHANGE(func) \
if (uMsg == WM_TIMECHANGE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCancelMode()
#define MSG_WM_CANCELMODE(func) \
if (uMsg == WM_CANCELMODE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message)
#define MSG_WM_SETCURSOR(func) \
if (uMsg == WM_SETCURSOR) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnMouseActivate(CWindow wndTopLevel, UINT nHitTest, UINT message)
#define MSG_WM_MOUSEACTIVATE(func) \
if (uMsg == WM_MOUSEACTIVATE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnChildActivate()
#define MSG_WM_CHILDACTIVATE(func) \
if (uMsg == WM_CHILDACTIVATE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnGetMinMaxInfo(LPMINMAXINFO lpMMI)
#define MSG_WM_GETMINMAXINFO(func) \
if (uMsg == WM_GETMINMAXINFO) \
{ \
SetMsgHandled(TRUE); \
func((LPMINMAXINFO)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnIconEraseBkgnd(CDCHandle dc)
#define MSG_WM_ICONERASEBKGND(func) \
if (uMsg == WM_ICONERASEBKGND) \
{ \
SetMsgHandled(TRUE); \
func((HDC)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSpoolerStatus(UINT nStatus, UINT nJobs)
#define MSG_WM_SPOOLERSTATUS(func) \
if (uMsg == WM_SPOOLERSTATUS) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (UINT)LOWORD(lParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
#define MSG_WM_DRAWITEM(func) \
if (uMsg == WM_DRAWITEM) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
#define MSG_WM_MEASUREITEM(func) \
if (uMsg == WM_MEASUREITEM) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
#define MSG_WM_DELETEITEM(func) \
if (uMsg == WM_DELETEITEM) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
//int OnCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
#define MSG_WM_CHARTOITEM(func) \
if (uMsg == WM_CHARTOITEM) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
#define MSG_WM_VKEYTOITEM(func) \
if (uMsg == WM_VKEYTOITEM) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HCURSOR OnQueryDragIcon()
#define MSG_WM_QUERYDRAGICON(func) \
if (uMsg == WM_QUERYDRAGICON) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func(); \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
#define MSG_WM_COMPAREITEM(func) \
if (uMsg == WM_COMPAREITEM) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCompacting(UINT nCpuTime)
#define MSG_WM_COMPACTING(func) \
if (uMsg == WM_COMPACTING) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct)
#define MSG_WM_NCCREATE(func) \
if (uMsg == WM_NCCREATE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcDestroy()
#define MSG_WM_NCDESTROY(func) \
if (uMsg == WM_NCDESTROY) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)
#define MSG_WM_NCCALCSIZE(func) \
if (uMsg == WM_NCCALCSIZE) \
{ \
SetMsgHandled(TRUE); \
lResult = func((BOOL)wParam, lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// UINT OnNcHitTest(CPoint point)
#define MSG_WM_NCHITTEST(func) \
if (uMsg == WM_NCHITTEST) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcPaint(CRgnHandle rgn)
#define MSG_WM_NCPAINT(func) \
if (uMsg == WM_NCPAINT) \
{ \
SetMsgHandled(TRUE); \
func((HRGN)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnNcActivate(BOOL bActive)
#define MSG_WM_NCACTIVATE(func) \
if (uMsg == WM_NCACTIVATE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((BOOL)wParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// UINT OnGetDlgCode(LPMSG lpMsg)
#define MSG_WM_GETDLGCODE(func) \
if (uMsg == WM_GETDLGCODE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((LPMSG)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcMouseMove(UINT nHitTest, CPoint point)
#define MSG_WM_NCMOUSEMOVE(func) \
if (uMsg == WM_NCMOUSEMOVE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcLButtonDown(UINT nHitTest, CPoint point)
#define MSG_WM_NCLBUTTONDOWN(func) \
if (uMsg == WM_NCLBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcLButtonUp(UINT nHitTest, CPoint point)
#define MSG_WM_NCLBUTTONUP(func) \
if (uMsg == WM_NCLBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcLButtonDblClk(UINT nHitTest, CPoint point)
#define MSG_WM_NCLBUTTONDBLCLK(func) \
if (uMsg == WM_NCLBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcRButtonDown(UINT nHitTest, CPoint point)
#define MSG_WM_NCRBUTTONDOWN(func) \
if (uMsg == WM_NCRBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcRButtonUp(UINT nHitTest, CPoint point)
#define MSG_WM_NCRBUTTONUP(func) \
if (uMsg == WM_NCRBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcRButtonDblClk(UINT nHitTest, CPoint point)
#define MSG_WM_NCRBUTTONDBLCLK(func) \
if (uMsg == WM_NCRBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcMButtonDown(UINT nHitTest, CPoint point)
#define MSG_WM_NCMBUTTONDOWN(func) \
if (uMsg == WM_NCMBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcMButtonUp(UINT nHitTest, CPoint point)
#define MSG_WM_NCMBUTTONUP(func) \
if (uMsg == WM_NCMBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNcMButtonDblClk(UINT nHitTest, CPoint point)
#define MSG_WM_NCMBUTTONDBLCLK(func) \
if (uMsg == WM_NCMBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_KEYDOWN(func) \
if (uMsg == WM_KEYDOWN) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_KEYUP(func) \
if (uMsg == WM_KEYUP) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_CHAR(func) \
if (uMsg == WM_CHAR) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_DEADCHAR(func) \
if (uMsg == WM_DEADCHAR) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_SYSKEYDOWN(func) \
if (uMsg == WM_SYSKEYDOWN) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_SYSKEYUP(func) \
if (uMsg == WM_SYSKEYUP) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_SYSCHAR(func) \
if (uMsg == WM_SYSCHAR) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSysDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_SYSDEADCHAR(func) \
if (uMsg == WM_SYSDEADCHAR) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSysCommand(UINT nID, CPoint point)
#define MSG_WM_SYSCOMMAND(func) \
if (uMsg == WM_SYSCOMMAND) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnTCard(UINT idAction, DWORD dwActionData)
#define MSG_WM_TCARD(func) \
if (uMsg == WM_TCARD) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (DWORD)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnTimer(UINT_PTR nIDEvent)
#define MSG_WM_TIMER(func) \
if (uMsg == WM_TIMER) \
{ \
SetMsgHandled(TRUE); \
func((UINT_PTR)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
#define MSG_WM_HSCROLL(func) \
if (uMsg == WM_HSCROLL) \
{ \
SetMsgHandled(TRUE); \
func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
#define MSG_WM_VSCROLL(func) \
if (uMsg == WM_VSCROLL) \
{ \
SetMsgHandled(TRUE); \
func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnInitMenu(CMenuHandle menu)
#define MSG_WM_INITMENU(func) \
if (uMsg == WM_INITMENU) \
{ \
SetMsgHandled(TRUE); \
func((HMENU)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnInitMenuPopup(CMenuHandle menuPopup, UINT nIndex, BOOL bSysMenu)
#define MSG_WM_INITMENUPOPUP(func) \
if (uMsg == WM_INITMENUPOPUP) \
{ \
SetMsgHandled(TRUE); \
func((HMENU)wParam, (UINT)LOWORD(lParam), (BOOL)HIWORD(lParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMenuSelect(UINT nItemID, UINT nFlags, CMenuHandle menu)
#define MSG_WM_MENUSELECT(func) \
if (uMsg == WM_MENUSELECT) \
{ \
SetMsgHandled(TRUE); \
func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenuHandle menu)
#define MSG_WM_MENUCHAR(func) \
if (uMsg == WM_MENUCHAR) \
{ \
SetMsgHandled(TRUE); \
lResult = func((TCHAR)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnNotify(int idCtrl, LPNMHDR pnmh)
#define MSG_WM_NOTIFY(func) \
if (uMsg == WM_NOTIFY) \
{ \
SetMsgHandled(TRUE); \
lResult = func((int)wParam, (LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnEnterIdle(UINT nWhy, CWindow wndWho)
#define MSG_WM_ENTERIDLE(func) \
if (uMsg == WM_ENTERIDLE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMouseMove(UINT nFlags, CPoint point)
#define MSG_WM_MOUSEMOVE(func) \
if (uMsg == WM_MOUSEMOVE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
#define MSG_WM_MOUSEWHEEL(func) \
if (uMsg == WM_MOUSEWHEEL) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)LOWORD(wParam), (short)HIWORD(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnLButtonDown(UINT nFlags, CPoint point)
#define MSG_WM_LBUTTONDOWN(func) \
if (uMsg == WM_LBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnLButtonUp(UINT nFlags, CPoint point)
#define MSG_WM_LBUTTONUP(func) \
if (uMsg == WM_LBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnLButtonDblClk(UINT nFlags, CPoint point)
#define MSG_WM_LBUTTONDBLCLK(func) \
if (uMsg == WM_LBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnRButtonDown(UINT nFlags, CPoint point)
#define MSG_WM_RBUTTONDOWN(func) \
if (uMsg == WM_RBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnRButtonUp(UINT nFlags, CPoint point)
#define MSG_WM_RBUTTONUP(func) \
if (uMsg == WM_RBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnRButtonDblClk(UINT nFlags, CPoint point)
#define MSG_WM_RBUTTONDBLCLK(func) \
if (uMsg == WM_RBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMButtonDown(UINT nFlags, CPoint point)
#define MSG_WM_MBUTTONDOWN(func) \
if (uMsg == WM_MBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMButtonUp(UINT nFlags, CPoint point)
#define MSG_WM_MBUTTONUP(func) \
if (uMsg == WM_MBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMButtonDblClk(UINT nFlags, CPoint point)
#define MSG_WM_MBUTTONDBLCLK(func) \
if (uMsg == WM_MBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnParentNotify(UINT message, UINT nChildID, LPARAM lParam)
#define MSG_WM_PARENTNOTIFY(func) \
if (uMsg == WM_PARENTNOTIFY) \
{ \
SetMsgHandled(TRUE); \
func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMDIActivate(CWindow wndActivate, CWindow wndDeactivate)
#define MSG_WM_MDIACTIVATE(func) \
if (uMsg == WM_MDIACTIVATE) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam, (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnRenderFormat(UINT nFormat)
#define MSG_WM_RENDERFORMAT(func) \
if (uMsg == WM_RENDERFORMAT) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnRenderAllFormats()
#define MSG_WM_RENDERALLFORMATS(func) \
if (uMsg == WM_RENDERALLFORMATS) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDestroyClipboard()
#define MSG_WM_DESTROYCLIPBOARD(func) \
if (uMsg == WM_DESTROYCLIPBOARD) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDrawClipboard()
#define MSG_WM_DRAWCLIPBOARD(func) \
if (uMsg == WM_DRAWCLIPBOARD) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnPaintClipboard(CWindow wndViewer, const LPPAINTSTRUCT lpPaintStruct)
#define MSG_WM_PAINTCLIPBOARD(func) \
if (uMsg == WM_PAINTCLIPBOARD) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam, (const LPPAINTSTRUCT)::GlobalLock((HGLOBAL)lParam)); \
::GlobalUnlock((HGLOBAL)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnVScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
#define MSG_WM_VSCROLLCLIPBOARD(func) \
if (uMsg == WM_VSCROLLCLIPBOARD) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnContextMenu(CWindow wnd, CPoint point)
#define MSG_WM_CONTEXTMENU(func) \
if (uMsg == WM_CONTEXTMENU) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSizeClipboard(CWindow wndViewer, const LPRECT lpRect)
#define MSG_WM_SIZECLIPBOARD(func) \
if (uMsg == WM_SIZECLIPBOARD) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam, (const LPRECT)::GlobalLock((HGLOBAL)lParam)); \
::GlobalUnlock((HGLOBAL)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnAskCbFormatName(UINT nMaxCount, LPTSTR lpszString)
#define MSG_WM_ASKCBFORMATNAME(func) \
if (uMsg == WM_ASKCBFORMATNAME) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPTSTR)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnChangeCbChain(CWindow wndRemove, CWindow wndAfter)
#define MSG_WM_CHANGECBCHAIN(func) \
if (uMsg == WM_CHANGECBCHAIN) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam, (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnHScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
#define MSG_WM_HSCROLLCLIPBOARD(func) \
if (uMsg == WM_HSCROLLCLIPBOARD) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnQueryNewPalette()
#define MSG_WM_QUERYNEWPALETTE(func) \
if (uMsg == WM_QUERYNEWPALETTE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func(); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnPaletteChanged(CWindow wndFocus)
#define MSG_WM_PALETTECHANGED(func) \
if (uMsg == WM_PALETTECHANGED) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnPaletteIsChanging(CWindow wndPalChg)
#define MSG_WM_PALETTEISCHANGING(func) \
if (uMsg == WM_PALETTEISCHANGING) \
{ \
SetMsgHandled(TRUE); \
func((HWND)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDropFiles(HDROP hDropInfo)
#define MSG_WM_DROPFILES(func) \
if (uMsg == WM_DROPFILES) \
{ \
SetMsgHandled(TRUE); \
func((HDROP)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnWindowPosChanging(LPWINDOWPOS lpWndPos)
#define MSG_WM_WINDOWPOSCHANGING(func) \
if (uMsg == WM_WINDOWPOSCHANGING) \
{ \
SetMsgHandled(TRUE); \
func((LPWINDOWPOS)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnWindowPosChanged(LPWINDOWPOS lpWndPos)
#define MSG_WM_WINDOWPOSCHANGED(func) \
if (uMsg == WM_WINDOWPOSCHANGED) \
{ \
SetMsgHandled(TRUE); \
func((LPWINDOWPOS)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnExitMenuLoop(BOOL fIsTrackPopupMenu)
#define MSG_WM_EXITMENULOOP(func) \
if (uMsg == WM_EXITMENULOOP) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnEnterMenuLoop(BOOL fIsTrackPopupMenu)
#define MSG_WM_ENTERMENULOOP(func) \
if (uMsg == WM_ENTERMENULOOP) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
#define MSG_WM_STYLECHANGED(func) \
if (uMsg == WM_STYLECHANGED) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
#define MSG_WM_STYLECHANGING(func) \
if (uMsg == WM_STYLECHANGING) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSizing(UINT fwSide, LPRECT pRect)
#define MSG_WM_SIZING(func) \
if (uMsg == WM_SIZING) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPRECT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMoving(UINT fwSide, LPRECT pRect)
#define MSG_WM_MOVING(func) \
if (uMsg == WM_MOVING) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPRECT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCaptureChanged(CWindow wnd)
#define MSG_WM_CAPTURECHANGED(func) \
if (uMsg == WM_CAPTURECHANGED) \
{ \
SetMsgHandled(TRUE); \
func((HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnDeviceChange(UINT nEventType, DWORD_PTR dwData)
#define MSG_WM_DEVICECHANGE(func) \
if (uMsg == WM_DEVICECHANGE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)wParam, (DWORD_PTR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
#define MSG_WM_COMMAND(func) \
if (uMsg == WM_COMMAND) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDisplayChange(UINT uBitsPerPixel, CSize sizeScreen)
#define MSG_WM_DISPLAYCHANGE(func) \
if (uMsg == WM_DISPLAYCHANGE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnEnterSizeMove()
#define MSG_WM_ENTERSIZEMOVE(func) \
if (uMsg == WM_ENTERSIZEMOVE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnExitSizeMove()
#define MSG_WM_EXITSIZEMOVE(func) \
if (uMsg == WM_EXITSIZEMOVE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// HFONT OnGetFont()
#define MSG_WM_GETFONT(func) \
if (uMsg == WM_GETFONT) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func(); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnGetHotKey()
#define MSG_WM_GETHOTKEY(func) \
if (uMsg == WM_GETHOTKEY) \
{ \
SetMsgHandled(TRUE); \
lResult = func(); \
if(IsMsgHandled()) \
return TRUE; \
}
// HICON OnGetIcon()
#define MSG_WM_GETICON(func) \
if (uMsg == WM_GETICON) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)wParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnGetText(int cchTextMax, LPTSTR lpszText)
#define MSG_WM_GETTEXT(func) \
if (uMsg == WM_GETTEXT) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((int)wParam, (LPTSTR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnGetTextLength()
#define MSG_WM_GETTEXTLENGTH(func) \
if (uMsg == WM_GETTEXTLENGTH) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func(); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnHelp(LPHELPINFO lpHelpInfo)
#define MSG_WM_HELP(func) \
if (uMsg == WM_HELP) \
{ \
SetMsgHandled(TRUE); \
func((LPHELPINFO)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnHotKey(int nHotKeyID, UINT uModifiers, UINT uVirtKey)
#define MSG_WM_HOTKEY(func) \
if (uMsg == WM_HOTKEY) \
{ \
SetMsgHandled(TRUE); \
func((int)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnInputLangChange(DWORD dwCharSet, HKL hKbdLayout)
#define MSG_WM_INPUTLANGCHANGE(func) \
if (uMsg == WM_INPUTLANGCHANGE) \
{ \
SetMsgHandled(TRUE); \
func((DWORD)wParam, (HKL)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnInputLangChangeRequest(BOOL bSysCharSet, HKL hKbdLayout)
#define MSG_WM_INPUTLANGCHANGEREQUEST(func) \
if (uMsg == WM_INPUTLANGCHANGEREQUEST) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam, (HKL)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNextDlgCtl(BOOL bHandle, WPARAM wCtlFocus)
#define MSG_WM_NEXTDLGCTL(func) \
if (uMsg == WM_NEXTDLGCTL) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)LOWORD(lParam), wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNextMenu(int nVirtKey, LPMDINEXTMENU lpMdiNextMenu)
#define MSG_WM_NEXTMENU(func) \
if (uMsg == WM_NEXTMENU) \
{ \
SetMsgHandled(TRUE); \
func((int)wParam, (LPMDINEXTMENU)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnNotifyFormat(CWindow wndFrom, int nCommand)
#define MSG_WM_NOTIFYFORMAT(func) \
if (uMsg == WM_NOTIFYFORMAT) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HWND)wParam, (int)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// BOOL OnPowerBroadcast(DWORD dwPowerEvent, DWORD_PTR dwData)
#define MSG_WM_POWERBROADCAST(func) \
if (uMsg == WM_POWERBROADCAST) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((DWORD)wParam, (DWORD_PTR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnPrint(CDCHandle dc, UINT uFlags)
#define MSG_WM_PRINT(func) \
if (uMsg == WM_PRINT) \
{ \
SetMsgHandled(TRUE); \
func((HDC)wParam, (UINT)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnPrintClient(CDCHandle dc, UINT uFlags)
#define MSG_WM_PRINTCLIENT(func) \
if (uMsg == WM_PRINTCLIENT) \
{ \
SetMsgHandled(TRUE); \
func((HDC)wParam, (UINT)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnRasDialEvent(RASCONNSTATE rasconnstate, DWORD dwError)
#define MSG_WM_RASDIALEVENT(func) \
if (uMsg == WM_RASDIALEVENT) \
{ \
SetMsgHandled(TRUE); \
func((RASCONNSTATE)wParam, (DWORD)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSetFont(CFontHandle font, BOOL bRedraw)
#define MSG_WM_SETFONT(func) \
if (uMsg == WM_SETFONT) \
{ \
SetMsgHandled(TRUE); \
func((HFONT)wParam, (BOOL)LOWORD(lParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnSetHotKey(int nVirtKey, UINT uFlags)
#define MSG_WM_SETHOTKEY(func) \
if (uMsg == WM_SETHOTKEY) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((int)LOBYTE(LOWORD(wParam)), (UINT)HIBYTE(LOWORD(wParam))); \
if(IsMsgHandled()) \
return TRUE; \
}
// HICON OnSetIcon(UINT uType, HICON hIcon)
#define MSG_WM_SETICON(func) \
if (uMsg == WM_SETICON) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)wParam, (HICON)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnSetRedraw(BOOL bRedraw)
#define MSG_WM_SETREDRAW(func) \
if (uMsg == WM_SETREDRAW) \
{ \
SetMsgHandled(TRUE); \
func((BOOL)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnSetText(LPCTSTR lpstrText)
#define MSG_WM_SETTEXT(func) \
if (uMsg == WM_SETTEXT) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((LPCTSTR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnUserChanged()
#define MSG_WM_USERCHANGED(func) \
if (uMsg == WM_USERCHANGED) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
///////////////////////////////////////////////////////////////////////////////
// New NT4 & NT5 messages
#if (_WIN32_WINNT >= 0x0400)
// void OnMouseHover(WPARAM wParam, CPoint ptPos)
#define MSG_WM_MOUSEHOVER(func) \
if (uMsg == WM_MOUSEHOVER) \
{ \
SetMsgHandled(TRUE); \
func(wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMouseLeave()
#define MSG_WM_MOUSELEAVE(func) \
if (uMsg == WM_MOUSELEAVE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
#endif // _WIN32_WINNT >= 0x0400
#if (WINVER >= 0x0500)
// void OnMenuRButtonUp(WPARAM wParam, CMenuHandle menu)
#define MSG_WM_MENURBUTTONUP(func) \
if (uMsg == WM_MENURBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func(wParam, (HMENU)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnMenuDrag(WPARAM wParam, CMenuHandle menu)
#define MSG_WM_MENUDRAG(func) \
if (uMsg == WM_MENUDRAG) \
{ \
SetMsgHandled(TRUE); \
lResult = func(wParam, (HMENU)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnMenuGetObject(PMENUGETOBJECTINFO info)
#define MSG_WM_MENUGETOBJECT(func) \
if (uMsg == WM_MENUGETOBJECT) \
{ \
SetMsgHandled(TRUE); \
lResult = func((PMENUGETOBJECTINFO)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnUnInitMenuPopup(UINT nID, CMenuHandle menu)
#define MSG_WM_UNINITMENUPOPUP(func) \
if (uMsg == WM_UNINITMENUPOPUP) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(lParam), (HMENU)wParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnMenuCommand(WPARAM nIndex, CMenuHandle menu)
#define MSG_WM_MENUCOMMAND(func) \
if (uMsg == WM_MENUCOMMAND) \
{ \
SetMsgHandled(TRUE); \
func(wParam, (HMENU)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
#endif // WINVER >= 0x0500
#if (_WIN32_WINNT >= 0x0500)
// BOOL OnAppCommand(CWindow wndFocus, short cmd, WORD uDevice, int dwKeys)
#define MSG_WM_APPCOMMAND(func) \
if (uMsg == WM_APPCOMMAND) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HWND)wParam, GET_APPCOMMAND_LPARAM(lParam), GET_DEVICE_LPARAM(lParam), GET_KEYSTATE_LPARAM(lParam)); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNCXButtonDown(int fwButton, short nHittest, CPoint ptPos)
#define MSG_WM_NCXBUTTONDOWN(func) \
if (uMsg == WM_NCXBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNCXButtonUp(int fwButton, short nHittest, CPoint ptPos)
#define MSG_WM_NCXBUTTONUP(func) \
if (uMsg == WM_NCXBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnNCXButtonDblClk(int fwButton, short nHittest, CPoint ptPos)
#define MSG_WM_NCXBUTTONDBLCLK(func) \
if (uMsg == WM_NCXBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnXButtonDown(int fwButton, int dwKeys, CPoint ptPos)
#define MSG_WM_XBUTTONDOWN(func) \
if (uMsg == WM_XBUTTONDOWN) \
{ \
SetMsgHandled(TRUE); \
func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnXButtonUp(int fwButton, int dwKeys, CPoint ptPos)
#define MSG_WM_XBUTTONUP(func) \
if (uMsg == WM_XBUTTONUP) \
{ \
SetMsgHandled(TRUE); \
func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnXButtonDblClk(int fwButton, int dwKeys, CPoint ptPos)
#define MSG_WM_XBUTTONDBLCLK(func) \
if (uMsg == WM_XBUTTONDBLCLK) \
{ \
SetMsgHandled(TRUE); \
func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnChangeUIState(WORD nAction, WORD nState)
#define MSG_WM_CHANGEUISTATE(func) \
if (uMsg == WM_CHANGEUISTATE) \
{ \
SetMsgHandled(TRUE); \
func(LOWORD(wParam), HIWORD(wParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnUpdateUIState(WORD nAction, WORD nState)
#define MSG_WM_UPDATEUISTATE(func) \
if (uMsg == WM_UPDATEUISTATE) \
{ \
SetMsgHandled(TRUE); \
func(LOWORD(wParam), HIWORD(wParam)); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnQueryUIState()
#define MSG_WM_QUERYUISTATE(func) \
if (uMsg == WM_QUERYUISTATE) \
{ \
SetMsgHandled(TRUE); \
lResult = func(); \
if(IsMsgHandled()) \
return TRUE; \
}
#endif // (_WIN32_WINNT >= 0x0500)
#if(_WIN32_WINNT >= 0x0501)
// void OnInput(WPARAM RawInputCode, HRAWINPUT hRawInput)
#define MSG_WM_INPUT(func) \
if (uMsg == WM_INPUT) \
{ \
SetMsgHandled(TRUE); \
func(GET_RAWINPUT_CODE_WPARAM(wParam), (HRAWINPUT)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnUniChar(TCHAR nChar, UINT nRepCnt, UINT nFlags)
#define MSG_WM_UNICHAR(func) \
if (uMsg == WM_UNICHAR) \
{ \
SetMsgHandled(TRUE); \
func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
if(IsMsgHandled()) \
{ \
lResult = (wParam == UNICODE_NOCHAR) ? TRUE : FALSE; \
return TRUE; \
} \
}
// void OnWTSSessionChange(WPARAM nStatusCode, PWTSSESSION_NOTIFICATION nSessionID)
#define MSG_WM_WTSSESSION_CHANGE(func) \
if (uMsg == WM_WTSSESSION_CHANGE) \
{ \
SetMsgHandled(TRUE); \
func(wParam, (PWTSSESSION_NOTIFICATION)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnThemeChanged()
#define MSG_WM_THEMECHANGED(func) \
if (uMsg == WM_THEMECHANGED) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
#endif // _WIN32_WINNT >= 0x0501
#if (_WIN32_WINNT >= 0x0600)
// BOOL OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt)
#define MSG_WM_MOUSEHWHEEL(func) \
if (uMsg == WM_MOUSEHWHEEL) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)LOWORD(wParam), (short)HIWORD(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
if(IsMsgHandled()) \
return TRUE; \
}
#endif // (_WIN32_WINNT >= 0x0600)
///////////////////////////////////////////////////////////////////////////////
// ATL defined messages
// BOOL OnForwardMsg(LPMSG Msg, DWORD nUserData)
#define MSG_WM_FORWARDMSG(func) \
if (uMsg == WM_FORWARDMSG) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((LPMSG)lParam, (DWORD)wParam); \
if(IsMsgHandled()) \
return TRUE; \
}
///////////////////////////////////////////////////////////////////////////////
// Dialog specific messages
// LRESULT OnDMGetDefID()
#define MSG_DM_GETDEFID(func) \
if (uMsg == DM_GETDEFID) \
{ \
SetMsgHandled(TRUE); \
lResult = func(); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDMSetDefID(UINT DefID)
#define MSG_DM_SETDEFID(func) \
if (uMsg == DM_SETDEFID) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnDMReposition()
#define MSG_DM_REPOSITION(func) \
if (uMsg == DM_REPOSITION) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
///////////////////////////////////////////////////////////////////////////////
// Reflected messages
// void OnReflectedCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
#define MSG_OCM_COMMAND(func) \
if (uMsg == OCM_COMMAND) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedNotify(int idCtrl, LPNMHDR pnmh)
#define MSG_OCM_NOTIFY(func) \
if (uMsg == OCM_NOTIFY) \
{ \
SetMsgHandled(TRUE); \
lResult = func((int)wParam, (LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedParentNotify(UINT message, UINT nChildID, LPARAM lParam)
#define MSG_OCM_PARENTNOTIFY(func) \
if (uMsg == OCM_PARENTNOTIFY) \
{ \
SetMsgHandled(TRUE); \
func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
#define MSG_OCM_DRAWITEM(func) \
if (uMsg == OCM_DRAWITEM) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
#define MSG_OCM_MEASUREITEM(func) \
if (uMsg == OCM_MEASUREITEM) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnReflectedCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
#define MSG_OCM_COMPAREITEM(func) \
if (uMsg == OCM_COMPAREITEM) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
#define MSG_OCM_DELETEITEM(func) \
if (uMsg == OCM_DELETEITEM) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
lResult = TRUE; \
if(IsMsgHandled()) \
return TRUE; \
}
// int OnReflectedVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
#define MSG_OCM_VKEYTOITEM(func) \
if (uMsg == OCM_VKEYTOITEM) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
//int OnReflectedCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
#define MSG_OCM_CHARTOITEM(func) \
if (uMsg == OCM_CHARTOITEM) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
#define MSG_OCM_HSCROLL(func) \
if (uMsg == OCM_HSCROLL) \
{ \
SetMsgHandled(TRUE); \
func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
#define MSG_OCM_VSCROLL(func) \
if (uMsg == OCM_VSCROLL) \
{ \
SetMsgHandled(TRUE); \
func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnReflectedCtlColorEdit(CDCHandle dc, CEdit edit)
#define MSG_OCM_CTLCOLOREDIT(func) \
if (uMsg == OCM_CTLCOLOREDIT) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnReflectedCtlColorListBox(CDCHandle dc, CListBox listBox)
#define MSG_OCM_CTLCOLORLISTBOX(func) \
if (uMsg == OCM_CTLCOLORLISTBOX) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnReflectedCtlColorBtn(CDCHandle dc, CButton button)
#define MSG_OCM_CTLCOLORBTN(func) \
if (uMsg == OCM_CTLCOLORBTN) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnReflectedCtlColorDlg(CDCHandle dc, CWindow wnd)
#define MSG_OCM_CTLCOLORDLG(func) \
if (uMsg == OCM_CTLCOLORDLG) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnReflectedCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
#define MSG_OCM_CTLCOLORSCROLLBAR(func) \
if (uMsg == OCM_CTLCOLORSCROLLBAR) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// HBRUSH OnReflectedCtlColorStatic(CDCHandle dc, CStatic wndStatic)
#define MSG_OCM_CTLCOLORSTATIC(func) \
if (uMsg == OCM_CTLCOLORSTATIC) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
///////////////////////////////////////////////////////////////////////////////
// Edit specific messages
// void OnClear()
#define MSG_WM_CLEAR(func) \
if (uMsg == WM_CLEAR) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCopy()
#define MSG_WM_COPY(func) \
if (uMsg == WM_COPY) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCut()
#define MSG_WM_CUT(func) \
if (uMsg == WM_CUT) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnPaste()
#define MSG_WM_PASTE(func) \
if (uMsg == WM_PASTE) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnUndo()
#define MSG_WM_UNDO(func) \
if (uMsg == WM_UNDO) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
///////////////////////////////////////////////////////////////////////////////
// Generic message handlers
// LRESULT OnMessageHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
#define MESSAGE_HANDLER_EX(msg, func) \
if(uMsg == msg) \
{ \
SetMsgHandled(TRUE); \
lResult = func(uMsg, wParam, lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnMessageRangeHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
#define MESSAGE_RANGE_HANDLER_EX(msgFirst, msgLast, func) \
if(uMsg >= msgFirst && uMsg <= msgLast) \
{ \
SetMsgHandled(TRUE); \
lResult = func(uMsg, wParam, lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
///////////////////////////////////////////////////////////////////////////////
// Commands and notifications
// void OnCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define COMMAND_HANDLER_EX(id, code, func) \
if (uMsg == WM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define COMMAND_ID_HANDLER_EX(id, func) \
if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define COMMAND_CODE_HANDLER_EX(code, func) \
if (uMsg == WM_COMMAND && code == HIWORD(wParam)) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnNotifyHandlerEX(LPNMHDR pnmh)
#define NOTIFY_HANDLER_EX(id, cd, func) \
if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnNotifyIDHandlerEX(LPNMHDR pnmh)
#define NOTIFY_ID_HANDLER_EX(id, func) \
if (uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnNotifyCodeHandlerEX(LPNMHDR pnmh)
#define NOTIFY_CODE_HANDLER_EX(cd, func) \
if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \
if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \
if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnNotifyRangeHandlerEX(LPNMHDR pnmh)
#define NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \
if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
#define NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define REFLECTED_COMMAND_HANDLER_EX(id, code, func) \
if (uMsg == OCM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define REFLECTED_COMMAND_ID_HANDLER_EX(id, func) \
if (uMsg == OCM_COMMAND && id == LOWORD(wParam)) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define REFLECTED_COMMAND_CODE_HANDLER_EX(code, func) \
if (uMsg == OCM_COMMAND && code == HIWORD(wParam)) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedNotifyHandlerEX(LPNMHDR pnmh)
#define REFLECTED_NOTIFY_HANDLER_EX(id, cd, func) \
if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedNotifyIDHandlerEX(LPNMHDR pnmh)
#define REFLECTED_NOTIFY_ID_HANDLER_EX(id, func) \
if (uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedNotifyCodeHandlerEX(LPNMHDR pnmh)
#define REFLECTED_NOTIFY_CODE_HANDLER_EX(cd, func) \
if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define REFLECTED_COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \
if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// void OnReflectedCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
#define REFLECTED_COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \
if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedNotifyRangeHandlerEX(LPNMHDR pnmh)
#define REFLECTED_NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \
if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
// LRESULT OnReflectedNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
{ \
SetMsgHandled(TRUE); \
lResult = func((LPNMHDR)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
#endif // __ATLCRACK_H__
================================================
FILE: src/Setup/wtl90/atlctrls.h
================================================
// Windows Template Library - WTL version 9.0
// Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
//
// This file is a part of the Windows Template Library.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
#ifndef __ATLCTRLS_H__
#define __ATLCTRLS_H__
#pragma once
#ifndef __ATLAPP_H__
#error atlctrls.h requires atlapp.h to be included first
#endif
#ifndef __ATLWIN_H__
#error atlctrls.h requires atlwin.h to be included first
#endif
#ifndef _WIN32_WCE
#include
#include
#elif defined(WIN32_PLATFORM_WFSP) && !defined(_WINUSERM_H_)
#include
#endif // !_WIN32_WCE
// protect template members from windowsx.h macros
#ifdef _INC_WINDOWSX
#undef GetNextSibling
#undef GetPrevSibling
#endif // _INC_WINDOWSX
///////////////////////////////////////////////////////////////////////////////
// Classes in this file:
//
// CStaticT - CStatic
// CButtonT - CButton
// CListBoxT - CListBox
// CComboBoxT - CComboBox
// CEditT - CEdit
// CEditCommands
// CScrollBarT - CScrollBar
//
// CImageListT - CImageList, CImageListManaged
// CListViewCtrlT - CListViewCtrl
// CTreeViewCtrlT - CTreeViewCtrl
// CTreeItemT - CTreeItem
// CTreeViewCtrlExT - CTreeViewCtrlEx
// CHeaderCtrlT - CHeaderCtrl
// CToolBarCtrlT - CToolBarCtrl
// CStatusBarCtrlT - CStatusBarCtrl
// CTabCtrlT - CTabCtrl
// CToolInfo
// CToolTipCtrlT - CToolTipCtrl
// CTrackBarCtrlT - CTrackBarCtrl
// CUpDownCtrlT - CUpDownCtrl
// CProgressBarCtrlT - CProgressBarCtrl
// CHotKeyCtrlT - CHotKeyCtrl
// CAnimateCtrlT - CAnimateCtrl
// CRichEditCtrlT - CRichEditCtrl
// CRichEditCommands
// CDragListBoxT - CDragListBox
// CDragListNotifyImpl
// CReBarCtrlT - CReBarCtrl
// CComboBoxExT - CComboBoxEx
// CDateTimePickerCtrlT - CDateTimePickerCtrl
// CMonthCalendarCtrlT - CMonthCalendarCtrl
// CFlatScrollBarImpl
// CFlatScrollBarT - CFlatScrollBar
// CIPAddressCtrlT - CIPAddressCtrl
// CPagerCtrlT - CPagerCtrl
// CLinkCtrlT - CLinkCtrl
//
// CCustomDraw
//
// CCECommandBarCtrlT - CCECommandBarCtrl
// CCECommandBandsCtrlT - CCECommandBandsCtrl
namespace WTL
{
// These are wrapper classes for Windows standard and common controls.
// To implement a window based on a control, use following:
// Example: Implementing a window based on a list box
//
// class CMyListBox : CWindowImpl
// {
// public:
// BEGIN_MSG_MAP(CMyListBox)
// // put your message handler entries here
// END_MSG_MAP()
// };
// --- Standard Windows controls ---
///////////////////////////////////////////////////////////////////////////////
// CStatic - client side for a Windows STATIC control
template
class CStaticT : public TBase
{
public:
// Constructors
CStaticT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CStaticT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return _T("STATIC");
}
#ifndef _WIN32_WCE
HICON GetIcon() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HICON)::SendMessage(m_hWnd, STM_GETICON, 0, 0L);
}
HICON SetIcon(HICON hIcon)
{
ATLASSERT(::IsWindow(m_hWnd));
return (HICON)::SendMessage(m_hWnd, STM_SETICON, (WPARAM)hIcon, 0L);
}
HENHMETAFILE GetEnhMetaFile() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HENHMETAFILE)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ENHMETAFILE, 0L);
}
HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile)
{
ATLASSERT(::IsWindow(m_hWnd));
return (HENHMETAFILE)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile);
}
#else // CE specific
HICON GetIcon() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HICON)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ICON, 0L);
}
HICON SetIcon(HICON hIcon)
{
ATLASSERT(::IsWindow(m_hWnd));
return (HICON)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
}
#endif // _WIN32_WCE
CBitmapHandle GetBitmap() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_BITMAP, 0L));
}
CBitmapHandle SetBitmap(HBITMAP hBitmap)
{
ATLASSERT(::IsWindow(m_hWnd));
return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
}
HCURSOR GetCursor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HCURSOR)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_CURSOR, 0L);
}
HCURSOR SetCursor(HCURSOR hCursor)
{
ATLASSERT(::IsWindow(m_hWnd));
return (HCURSOR)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
}
};
typedef CStaticT CStatic;
///////////////////////////////////////////////////////////////////////////////
// CButton - client side for a Windows BUTTON control
template
class CButtonT : public TBase
{
public:
// Constructors
CButtonT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CButtonT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return _T("BUTTON");
}
UINT GetState() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, BM_GETSTATE, 0, 0L);
}
void SetState(BOOL bHighlight)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, BM_SETSTATE, bHighlight, 0L);
}
int GetCheck() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, BM_GETCHECK, 0, 0L);
}
void SetCheck(int nCheck)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, BM_SETCHECK, nCheck, 0L);
}
UINT GetButtonStyle() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::GetWindowLong(m_hWnd, GWL_STYLE) & 0xFFFF;
}
void SetButtonStyle(UINT nStyle, BOOL bRedraw = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, BM_SETSTYLE, nStyle, (LPARAM)bRedraw);
}
#ifndef _WIN32_WCE
HICON GetIcon() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HICON)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_ICON, 0L);
}
HICON SetIcon(HICON hIcon)
{
ATLASSERT(::IsWindow(m_hWnd));
return (HICON)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
}
CBitmapHandle GetBitmap() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0L));
}
CBitmapHandle SetBitmap(HBITMAP hBitmap)
{
ATLASSERT(::IsWindow(m_hWnd));
return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
}
#endif // !_WIN32_WCE
#if (_WIN32_WINNT >= 0x0501)
BOOL GetIdealSize(LPSIZE lpSize) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, BCM_GETIDEALSIZE, 0, (LPARAM)lpSize);
}
BOOL GetImageList(PBUTTON_IMAGELIST pButtonImagelist) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, BCM_GETIMAGELIST, 0, (LPARAM)pButtonImagelist);
}
BOOL SetImageList(PBUTTON_IMAGELIST pButtonImagelist)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, BCM_SETIMAGELIST, 0, (LPARAM)pButtonImagelist);
}
BOOL GetTextMargin(LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, BCM_GETTEXTMARGIN, 0, (LPARAM)lpRect);
}
BOOL SetTextMargin(LPRECT lpRect)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, BCM_SETTEXTMARGIN, 0, (LPARAM)lpRect);
}
#endif // (_WIN32_WINNT >= 0x0501)
#if (WINVER >= 0x0600)
void SetDontClick(BOOL bDontClick)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, BM_SETDONTCLICK, (WPARAM)bDontClick, 0L);
}
#endif // (WINVER >= 0x0600)
#if (_WIN32_WINNT >= 0x0600)
BOOL SetDropDownState(BOOL bDropDown)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
return (BOOL)::SendMessage(m_hWnd, BCM_SETDROPDOWNSTATE, (WPARAM)bDropDown, 0L);
}
BOOL GetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
return (BOOL)::SendMessage(m_hWnd, BCM_GETSPLITINFO, 0, (LPARAM)pSplitInfo);
}
BOOL SetSplitInfo(PBUTTON_SPLITINFO pSplitInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
return (BOOL)::SendMessage(m_hWnd, BCM_SETSPLITINFO, 0, (LPARAM)pSplitInfo);
}
int GetNoteLength() const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
return (int)::SendMessage(m_hWnd, BCM_GETNOTELENGTH, 0, 0L);
}
BOOL GetNote(LPWSTR lpstrNoteText, int cchNoteText) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
return (BOOL)::SendMessage(m_hWnd, BCM_GETNOTE, cchNoteText, (LPARAM)lpstrNoteText);
}
BOOL SetNote(LPCWSTR lpstrNoteText)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
return (BOOL)::SendMessage(m_hWnd, BCM_SETNOTE, 0, (LPARAM)lpstrNoteText);
}
LRESULT SetElevationRequiredState(BOOL bSet)
{
ATLASSERT(::IsWindow(m_hWnd));
return ::SendMessage(m_hWnd, BCM_SETSHIELD, 0, (LPARAM)bSet);
}
#endif // (_WIN32_WINNT >= 0x0600)
// Operations
void Click()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, BM_CLICK, 0, 0L);
}
};
typedef CButtonT CButton;
///////////////////////////////////////////////////////////////////////////////
// CListBox - client side for a Windows LISTBOX control
template
class CListBoxT : public TBase
{
public:
// Constructors
CListBoxT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CListBoxT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return _T("LISTBOX");
}
// for entire listbox
int GetCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETCOUNT, 0, 0L);
}
#ifndef _WIN32_WCE
int SetCount(int cItems)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(((GetStyle() & LBS_NODATA) != 0) && ((GetStyle() & LBS_HASSTRINGS) == 0));
return (int)::SendMessage(m_hWnd, LB_SETCOUNT, cItems, 0L);
}
#endif // !_WIN32_WCE
int GetHorizontalExtent() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETHORIZONTALEXTENT, 0, 0L);
}
void SetHorizontalExtent(int cxExtent)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LB_SETHORIZONTALEXTENT, cxExtent, 0L);
}
int GetTopIndex() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETTOPINDEX, 0, 0L);
}
int SetTopIndex(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_SETTOPINDEX, nIndex, 0L);
}
LCID GetLocale() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (LCID)::SendMessage(m_hWnd, LB_GETLOCALE, 0, 0L);
}
LCID SetLocale(LCID nNewLocale)
{
ATLASSERT(::IsWindow(m_hWnd));
return (LCID)::SendMessage(m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0L);
}
#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
DWORD GetListBoxInfo() const
{
ATLASSERT(::IsWindow(m_hWnd));
#if (_WIN32_WINNT >= 0x0501)
return (DWORD)::SendMessage(m_hWnd, LB_GETLISTBOXINFO, 0, 0L);
#else // !(_WIN32_WINNT >= 0x0501)
return ::GetListBoxInfo(m_hWnd);
#endif // !(_WIN32_WINNT >= 0x0501)
}
#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
// for single-selection listboxes
int GetCurSel() const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
return (int)::SendMessage(m_hWnd, LB_GETCURSEL, 0, 0L);
}
int SetCurSel(int nSelect)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
return (int)::SendMessage(m_hWnd, LB_SETCURSEL, nSelect, 0L);
}
// for multiple-selection listboxes
int GetSel(int nIndex) const // also works for single-selection
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETSEL, nIndex, 0L);
}
int SetSel(int nIndex, BOOL bSelect = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
return (int)::SendMessage(m_hWnd, LB_SETSEL, bSelect, nIndex);
}
int GetSelCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
return (int)::SendMessage(m_hWnd, LB_GETSELCOUNT, 0, 0L);
}
int GetSelItems(int nMaxItems, LPINT rgIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
return (int)::SendMessage(m_hWnd, LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex);
}
int GetAnchorIndex() const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
return (int)::SendMessage(m_hWnd, LB_GETANCHORINDEX, 0, 0L);
}
void SetAnchorIndex(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
::SendMessage(m_hWnd, LB_SETANCHORINDEX, nIndex, 0L);
}
int GetCaretIndex() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETCARETINDEX, 0, 0);
}
int SetCaretIndex(int nIndex, BOOL bScroll = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0));
}
// for listbox items
DWORD_PTR GetItemData(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD_PTR)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L);
}
int SetItemData(int nIndex, DWORD_PTR dwItemData)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
}
void* GetItemDataPtr(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (void*)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L);
}
int SetItemDataPtr(int nIndex, void* pData)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItemData(nIndex, (DWORD_PTR)pData);
}
int GetItemRect(int nIndex, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect);
}
int GetText(int nIndex, LPTSTR lpszBuffer) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer);
}
#ifndef _ATL_NO_COM
#ifdef _OLEAUTO_H_
BOOL GetTextBSTR(int nIndex, BSTR& bstrText) const
{
USES_CONVERSION;
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(bstrText == NULL);
int nLen = GetTextLen(nIndex);
if(nLen == LB_ERR)
return FALSE;
CTempBuffer buff;
LPTSTR lpstrText = buff.Allocate(nLen + 1);
if(lpstrText == NULL)
return FALSE;
if(GetText(nIndex, lpstrText) == LB_ERR)
return FALSE;
bstrText = ::SysAllocString(T2OLE(lpstrText));
return (bstrText != NULL) ? TRUE : FALSE;
}
#endif // _OLEAUTO_H_
#endif // !_ATL_NO_COM
#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
int GetText(int nIndex, _CSTRING_NS::CString& strText) const
{
ATLASSERT(::IsWindow(m_hWnd));
int cchLen = GetTextLen(nIndex);
if(cchLen == LB_ERR)
return LB_ERR;
int nRet = LB_ERR;
LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
if(lpstr != NULL)
{
nRet = GetText(nIndex, lpstr);
strText.ReleaseBuffer();
}
return nRet;
}
#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
int GetTextLen(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETTEXTLEN, nIndex, 0L);
}
int GetItemHeight(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_GETITEMHEIGHT, nIndex, 0L);
}
int SetItemHeight(int nIndex, UINT cyItemHeight)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
}
// Settable only attributes
void SetColumnWidth(int cxWidth)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LB_SETCOLUMNWIDTH, cxWidth, 0L);
}
BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
}
BOOL SetTabStops()
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 0, 0L);
}
BOOL SetTabStops(const int& cxEachStop) // takes an 'int'
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
}
// Operations
int InitStorage(int nItems, UINT nBytes)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_INITSTORAGE, (WPARAM)nItems, nBytes);
}
void ResetContent()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LB_RESETCONTENT, 0, 0L);
}
UINT ItemFromPoint(POINT pt, BOOL& bOutside) const
{
ATLASSERT(::IsWindow(m_hWnd));
DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
bOutside = (BOOL)HIWORD(dw);
return (UINT)LOWORD(dw);
}
// manipulating listbox items
int AddString(LPCTSTR lpszItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem);
}
int DeleteString(UINT nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_DELETESTRING, nIndex, 0L);
}
int InsertString(int nIndex, LPCTSTR lpszItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_INSERTSTRING, nIndex, (LPARAM)lpszItem);
}
#ifndef _WIN32_WCE
int Dir(UINT attr, LPCTSTR lpszWildCard)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_DIR, attr, (LPARAM)lpszWildCard);
}
int AddFile(LPCTSTR lpstrFileName)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_ADDFILE, 0, (LPARAM)lpstrFileName);
}
#endif // !_WIN32_WCE
// selection helpers
int FindString(int nStartAfter, LPCTSTR lpszItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem);
}
int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
}
int SelectString(int nStartAfter, LPCTSTR lpszItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem);
}
int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
ATLASSERT(nFirstItem <= nLastItem);
return bSelect ? (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nFirstItem, nLastItem) : (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nLastItem, nFirstItem);
}
#ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages
DWORD GetInputMode(BOOL bCurrentMode = TRUE)
{
return SendMessage(LB_GETINPUTMODE, 0, (LPARAM)bCurrentMode);
}
BOOL SetInputMode(DWORD dwMode)
{
return SendMessage(LB_SETINPUTMODE, 0, (LPARAM)dwMode);
}
#endif // WIN32_PLATFORM_WFSP
};
typedef CListBoxT CListBox;
///////////////////////////////////////////////////////////////////////////////
// CComboBox - client side for a Windows COMBOBOX control
#ifndef WIN32_PLATFORM_WFSP // No COMBOBOX on SmartPhones
template
class CComboBoxT : public TBase
{
public:
// Constructors
CComboBoxT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CComboBoxT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return _T("COMBOBOX");
}
// for entire combo box
int GetCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0L);
}
int GetCurSel() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0L);
}
int SetCurSel(int nSelect)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_SETCURSEL, nSelect, 0L);
}
LCID GetLocale() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (LCID)::SendMessage(m_hWnd, CB_GETLOCALE, 0, 0L);
}
LCID SetLocale(LCID nNewLocale)
{
ATLASSERT(::IsWindow(m_hWnd));
return (LCID)::SendMessage(m_hWnd, CB_SETLOCALE, (WPARAM)nNewLocale, 0L);
}
int GetTopIndex() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETTOPINDEX, 0, 0L);
}
int SetTopIndex(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_SETTOPINDEX, nIndex, 0L);
}
UINT GetHorizontalExtent() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, CB_GETHORIZONTALEXTENT, 0, 0L);
}
void SetHorizontalExtent(UINT nExtent)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, CB_SETHORIZONTALEXTENT, nExtent, 0L);
}
int GetDroppedWidth() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETDROPPEDWIDTH, 0, 0L);
}
int SetDroppedWidth(UINT nWidth)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_SETDROPPEDWIDTH, nWidth, 0L);
}
#if ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
BOOL GetComboBoxInfo(PCOMBOBOXINFO pComboBoxInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
#if ((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
return (BOOL)::SendMessage(m_hWnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)pComboBoxInfo);
#else // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
return ::GetComboBoxInfo(m_hWnd, pComboBoxInfo);
#endif // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
}
#endif // ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
// for edit control
DWORD GetEditSel() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, CB_GETEDITSEL, 0, 0L);
}
BOOL SetEditSel(int nStartChar, int nEndChar)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, CB_SETEDITSEL, 0, MAKELONG(nStartChar, nEndChar));
}
// for combobox item
DWORD_PTR GetItemData(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD_PTR)::SendMessage(m_hWnd, CB_GETITEMDATA, nIndex, 0L);
}
int SetItemData(int nIndex, DWORD_PTR dwItemData)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
}
void* GetItemDataPtr(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (void*)GetItemData(nIndex);
}
int SetItemDataPtr(int nIndex, void* pData)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItemData(nIndex, (DWORD_PTR)pData);
}
int GetLBText(int nIndex, LPTSTR lpszText) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETLBTEXT, nIndex, (LPARAM)lpszText);
}
#ifndef _ATL_NO_COM
BOOL GetLBTextBSTR(int nIndex, BSTR& bstrText) const
{
USES_CONVERSION;
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(bstrText == NULL);
int nLen = GetLBTextLen(nIndex);
if(nLen == CB_ERR)
return FALSE;
CTempBuffer buff;
LPTSTR lpstrText = buff.Allocate(nLen + 1);
if(lpstrText == NULL)
return FALSE;
if(GetLBText(nIndex, lpstrText) == CB_ERR)
return FALSE;
bstrText = ::SysAllocString(T2OLE(lpstrText));
return (bstrText != NULL) ? TRUE : FALSE;
}
#endif // !_ATL_NO_COM
#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
int GetLBText(int nIndex, _CSTRING_NS::CString& strText) const
{
ATLASSERT(::IsWindow(m_hWnd));
int cchLen = GetLBTextLen(nIndex);
if(cchLen == CB_ERR)
return CB_ERR;
int nRet = CB_ERR;
LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
if(lpstr != NULL)
{
nRet = GetLBText(nIndex, lpstr);
strText.ReleaseBuffer();
}
return nRet;
}
#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
int GetLBTextLen(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETLBTEXTLEN, nIndex, 0L);
}
int GetItemHeight(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETITEMHEIGHT, nIndex, 0L);
}
int SetItemHeight(int nIndex, UINT cyItemHeight)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
}
BOOL GetExtendedUI() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, CB_GETEXTENDEDUI, 0, 0L);
}
int SetExtendedUI(BOOL bExtended = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_SETEXTENDEDUI, bExtended, 0L);
}
void GetDroppedControlRect(LPRECT lprect) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)lprect);
}
BOOL GetDroppedState() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, CB_GETDROPPEDSTATE, 0, 0L);
}
#if (_WIN32_WINNT >= 0x0501)
int GetMinVisible() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_GETMINVISIBLE, 0, 0L);
}
BOOL SetMinVisible(int nMinVisible)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, CB_SETMINVISIBLE, nMinVisible, 0L);
}
// Vista only
BOOL GetCueBannerText(LPWSTR lpwText, int cchText) const
{
#ifndef CB_GETCUEBANNER
const UINT CB_GETCUEBANNER = (CBM_FIRST + 4);
#endif
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, CB_GETCUEBANNER, (WPARAM)lpwText, cchText);
}
// Vista only
BOOL SetCueBannerText(LPCWSTR lpcwText)
{
#ifndef CB_SETCUEBANNER
const UINT CB_SETCUEBANNER = (CBM_FIRST + 3);
#endif
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, CB_SETCUEBANNER, 0, (LPARAM)lpcwText);
}
#endif // (_WIN32_WINNT >= 0x0501)
// Operations
int InitStorage(int nItems, UINT nBytes)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_INITSTORAGE, (WPARAM)nItems, nBytes);
}
void ResetContent()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0L);
}
// for edit control
BOOL LimitText(int nMaxChars)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, CB_LIMITTEXT, nMaxChars, 0L);
}
// for drop-down combo boxes
void ShowDropDown(BOOL bShowIt = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, CB_SHOWDROPDOWN, bShowIt, 0L);
}
// manipulating listbox items
int AddString(LPCTSTR lpszString)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_ADDSTRING, 0, (LPARAM)lpszString);
}
int DeleteString(UINT nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_DELETESTRING, nIndex, 0L);
}
int InsertString(int nIndex, LPCTSTR lpszString)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_INSERTSTRING, nIndex, (LPARAM)lpszString);
}
#ifndef _WIN32_WCE
int Dir(UINT attr, LPCTSTR lpszWildCard)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_DIR, attr, (LPARAM)lpszWildCard);
}
#endif // !_WIN32_WCE
// selection helpers
int FindString(int nStartAfter, LPCTSTR lpszString) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_FINDSTRING, nStartAfter, (LPARAM)lpszString);
}
int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
}
int SelectString(int nStartAfter, LPCTSTR lpszString)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, CB_SELECTSTRING, nStartAfter, (LPARAM)lpszString);
}
// Clipboard operations
void Clear()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
}
void Copy()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_COPY, 0, 0L);
}
void Cut()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_CUT, 0, 0L);
}
void Paste()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
}
};
typedef CComboBoxT CComboBox;
#endif // !WIN32_PLATFORM_WFSP
///////////////////////////////////////////////////////////////////////////////
// CEdit - client side for a Windows EDIT control
template
class CEditT : public TBase
{
public:
// Constructors
CEditT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CEditT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return _T("EDIT");
}
BOOL CanUndo() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L);
}
int GetLineCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L);
}
BOOL GetModify() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L);
}
void SetModify(BOOL bModified = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L);
}
void GetRect(LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
}
DWORD GetSel() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L);
}
void GetSel(int& nStartChar, int& nEndChar) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
}
#ifndef _WIN32_WCE
HLOCAL GetHandle() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HLOCAL)::SendMessage(m_hWnd, EM_GETHANDLE, 0, 0L);
}
void SetHandle(HLOCAL hBuffer)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETHANDLE, (WPARAM)hBuffer, 0L);
}
#endif // !_WIN32_WCE
DWORD GetMargins() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, EM_GETMARGINS, 0, 0L);
}
void GetMargins(UINT& nLeft, UINT& nRight) const
{
ATLASSERT(::IsWindow(m_hWnd));
DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_GETMARGINS, 0, 0L);
nLeft = LOWORD(dwRet);
nRight = HIWORD(dwRet);
}
void SetMargins(UINT nLeft, UINT nRight, WORD wFlags = EC_LEFTMARGIN | EC_RIGHTMARGIN)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETMARGINS, wFlags, MAKELONG(nLeft, nRight));
}
UINT GetLimitText() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L);
}
void SetLimitText(UINT nMax)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETLIMITTEXT, nMax, 0L);
}
POINT PosFromChar(UINT nChar) const
{
ATLASSERT(::IsWindow(m_hWnd));
DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_POSFROMCHAR, nChar, 0);
POINT point = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
return point;
}
int CharFromPos(POINT pt, int* pLine = NULL) const
{
ATLASSERT(::IsWindow(m_hWnd));
DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
if(pLine != NULL)
*pLine = (int)(short)HIWORD(dwRet);
return (int)(short)LOWORD(dwRet);
}
// NOTE: first word in lpszBuffer must contain the size of the buffer!
int GetLine(int nIndex, LPTSTR lpszBuffer) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
}
int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
{
ATLASSERT(::IsWindow(m_hWnd));
*(LPWORD)lpszBuffer = (WORD)nMaxLength;
return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
}
TCHAR GetPasswordChar() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (TCHAR)::SendMessage(m_hWnd, EM_GETPASSWORDCHAR, 0, 0L);
}
void SetPasswordChar(TCHAR ch)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETPASSWORDCHAR, ch, 0L);
}
#ifndef _WIN32_WCE
EDITWORDBREAKPROC GetWordBreakProc() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (EDITWORDBREAKPROC)::SendMessage(m_hWnd, EM_GETWORDBREAKPROC, 0, 0L);
}
void SetWordBreakProc(EDITWORDBREAKPROC ewbprc)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc);
}
#endif // !_WIN32_WCE
int GetFirstVisibleLine() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
}
#ifndef _WIN32_WCE
int GetThumb() const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & ES_MULTILINE) != 0);
return (int)::SendMessage(m_hWnd, EM_GETTHUMB, 0, 0L);
}
#endif // !_WIN32_WCE
BOOL SetReadOnly(BOOL bReadOnly = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
}
#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
UINT GetImeStatus(UINT uStatus) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, EM_GETIMESTATUS, uStatus, 0L);
}
UINT SetImeStatus(UINT uStatus, UINT uData)
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, EM_SETIMESTATUS, uStatus, uData);
}
#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
#if (_WIN32_WINNT >= 0x0501)
BOOL GetCueBannerText(LPCWSTR lpstrText, int cchText) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_GETCUEBANNER, (WPARAM)lpstrText, cchText);
}
// bKeepWithFocus - Vista only
BOOL SetCueBannerText(LPCWSTR lpstrText, BOOL bKeepWithFocus = FALSE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_SETCUEBANNER, (WPARAM)bKeepWithFocus, (LPARAM)(lpstrText));
}
#endif // (_WIN32_WINNT >= 0x0501)
// Operations
void EmptyUndoBuffer()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L);
}
BOOL FmtLines(BOOL bAddEOL)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_FMTLINES, bAddEOL, 0L);
}
void LimitText(int nChars = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_LIMITTEXT, nChars, 0L);
}
int LineFromChar(int nIndex = -1) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, EM_LINEFROMCHAR, nIndex, 0L);
}
int LineIndex(int nLine = -1) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L);
}
int LineLength(int nLine = -1) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L);
}
void LineScroll(int nLines, int nChars = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines);
}
void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
}
void SetRect(LPCRECT lpRect)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
}
void SetRectNP(LPCRECT lpRect)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETRECTNP, 0, (LPARAM)lpRect);
}
void SetSel(DWORD dwSelection, BOOL bNoScroll = FALSE)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection));
if(!bNoScroll)
::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
}
void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll = FALSE)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar);
if(!bNoScroll)
::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
}
void SetSelAll(BOOL bNoScroll = FALSE)
{
SetSel(0, -1, bNoScroll);
}
void SetSelNone(BOOL bNoScroll = FALSE)
{
SetSel(-1, 0, bNoScroll);
}
BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
}
BOOL SetTabStops()
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L);
}
BOOL SetTabStops(const int& cxEachStop) // takes an 'int'
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
}
void ScrollCaret()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
}
int Scroll(int nScrollAction)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & ES_MULTILINE) != 0);
LRESULT lRet = ::SendMessage(m_hWnd, EM_SCROLL, nScrollAction, 0L);
if(!(BOOL)HIWORD(lRet))
return -1; // failed
return (int)(short)LOWORD(lRet);
}
void InsertText(int nInsertAfterChar, LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
{
SetSel(nInsertAfterChar, nInsertAfterChar, bNoScroll);
ReplaceSel(lpstrText, bCanUndo);
}
void AppendText(LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
{
InsertText(GetWindowTextLength(), lpstrText, bNoScroll, bCanUndo);
}
#if (_WIN32_WINNT >= 0x0501)
BOOL ShowBalloonTip(PEDITBALLOONTIP pEditBaloonTip)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_SHOWBALLOONTIP, 0, (LPARAM)pEditBaloonTip);
}
BOOL HideBalloonTip()
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_HIDEBALLOONTIP, 0, 0L);
}
#endif // (_WIN32_WINNT >= 0x0501)
#if (_WIN32_WINNT >= 0x0600)
DWORD GetHilite() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L);
}
void GetHilite(int& nStartChar, int& nEndChar) const
{
ATLASSERT(::IsWindow(m_hWnd));
DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L);
nStartChar = (int)(short)LOWORD(dwRet);
nEndChar = (int)(short)HIWORD(dwRet);
}
void SetHilite(int nStartChar, int nEndChar)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, EM_SETHILITE, nStartChar, nEndChar);
}
#endif // (_WIN32_WINNT >= 0x0600)
// Clipboard operations
BOOL Undo()
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L);
}
void Clear()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
}
void Copy()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_COPY, 0, 0L);
}
void Cut()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_CUT, 0, 0L);
}
void Paste()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
}
#ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages
DWORD GetExtendedStyle()
{
return SendMessage(EM_GETEXTENDEDSTYLE);
}
DWORD SetExtendedStyle(DWORD dwMask, DWORD dwExStyle)
{
return SendMessage(EM_SETEXTENDEDSTYLE, (WPARAM)dwMask, (LPARAM)dwExStyle);
}
DWORD GetInputMode(BOOL bCurrentMode = TRUE)
{
return SendMessage(EM_GETINPUTMODE, 0, (LPARAM)bCurrentMode);
}
BOOL SetInputMode(DWORD dwMode)
{
return SendMessage(EM_SETINPUTMODE, 0, (LPARAM)dwMode);
}
BOOL SetSymbols(LPCTSTR szSymbols)
{
return SendMessage(EM_SETSYMBOLS, 0, (LPARAM)szSymbols);
}
BOOL ResetSymbols()
{
return SendMessage(EM_SETSYMBOLS);
}
#endif // WIN32_PLATFORM_WFSP
};
typedef CEditT CEdit;
///////////////////////////////////////////////////////////////////////////////
// CEditCommands - message handlers for standard EDIT commands
// Chain to CEditCommands message map. Your class must also derive from CEdit.
// Example:
// class CMyEdit : public CWindowImpl,
// public CEditCommands
// {
// public:
// BEGIN_MSG_MAP(CMyEdit)
// // your handlers...
// CHAIN_MSG_MAP_ALT(CEditCommands, 1)
// END_MSG_MAP()
// // other stuff...
// };
template
class CEditCommands
{
public:
BEGIN_MSG_MAP(CEditCommands< T >)
ALT_MSG_MAP(1)
COMMAND_ID_HANDLER(ID_EDIT_CLEAR, OnEditClear)
COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, OnEditClearAll)
COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCopy)
COMMAND_ID_HANDLER(ID_EDIT_CUT, OnEditCut)
COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnEditPaste)
COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnEditSelectAll)
COMMAND_ID_HANDLER(ID_EDIT_UNDO, OnEditUndo)
END_MSG_MAP()
LRESULT OnEditClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
T* pT = static_cast(this);
pT->Clear();
return 0;
}
LRESULT OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
T* pT = static_cast(this);
pT->SetSel(0, -1);
pT->Clear();
return 0;
}
LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
T* pT = static_cast(this);
pT->Copy();
return 0;
}
LRESULT OnEditCut(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
T* pT = static_cast(this);
pT->Cut();
return 0;
}
LRESULT OnEditPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
T* pT = static_cast(this);
pT->Paste();
return 0;
}
LRESULT OnEditSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
T* pT = static_cast(this);
pT->SetSel(0, -1);
return 0;
}
LRESULT OnEditUndo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
T* pT = static_cast(this);
pT->Undo();
return 0;
}
// State (update UI) helpers
BOOL CanCut() const
{ return HasSelection(); }
BOOL CanCopy() const
{ return HasSelection(); }
BOOL CanClear() const
{ return HasSelection(); }
BOOL CanSelectAll() const
{ return HasText(); }
BOOL CanFind() const
{ return HasText(); }
BOOL CanRepeat() const
{ return HasText(); }
BOOL CanReplace() const
{ return HasText(); }
BOOL CanClearAll() const
{ return HasText(); }
// Implementation
BOOL HasSelection() const
{
const T* pT = static_cast(this);
int nMin, nMax;
::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nMin, (LPARAM)&nMax);
return (nMin != nMax);
}
BOOL HasText() const
{
const T* pT = static_cast(this);
return (pT->GetWindowTextLength() > 0);
}
};
///////////////////////////////////////////////////////////////////////////////
// CScrollBar - client side for a Windows SCROLLBAR control
template
class CScrollBarT : public TBase
{
public:
// Constructors
CScrollBarT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CScrollBarT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return _T("SCROLLBAR");
}
#ifndef _WIN32_WCE
int GetScrollPos() const
{
ATLASSERT(::IsWindow(m_hWnd));
return ::GetScrollPos(m_hWnd, SB_CTL);
}
#endif // !_WIN32_WCE
int SetScrollPos(int nPos, BOOL bRedraw = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return ::SetScrollPos(m_hWnd, SB_CTL, nPos, bRedraw);
}
#ifndef _WIN32_WCE
void GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos) const
{
ATLASSERT(::IsWindow(m_hWnd));
::GetScrollRange(m_hWnd, SB_CTL, lpMinPos, lpMaxPos);
}
#endif // !_WIN32_WCE
void SetScrollRange(int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
::SetScrollRange(m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw);
}
BOOL GetScrollInfo(LPSCROLLINFO lpScrollInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return ::GetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo);
}
int SetScrollInfo(LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return ::SetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo, bRedraw);
}
#ifndef _WIN32_WCE
int GetScrollLimit() const
{
int nMin = 0, nMax = 0;
::GetScrollRange(m_hWnd, SB_CTL, &nMin, &nMax);
SCROLLINFO info = { sizeof(SCROLLINFO), SIF_PAGE };
if(::GetScrollInfo(m_hWnd, SB_CTL, &info))
nMax -= ((info.nPage - 1) > 0) ? (info.nPage - 1) : 0;
return nMax;
}
#if (WINVER >= 0x0500)
BOOL GetScrollBarInfo(PSCROLLBARINFO pScrollBarInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
#if (_WIN32_WINNT >= 0x0501)
return (BOOL)::SendMessage(m_hWnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)pScrollBarInfo);
#else // !(_WIN32_WINNT >= 0x0501)
return ::GetScrollBarInfo(m_hWnd, OBJID_CLIENT, pScrollBarInfo);
#endif // !(_WIN32_WINNT >= 0x0501)
}
#endif // (WINVER >= 0x0500)
// Operations
void ShowScrollBar(BOOL bShow = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
::ShowScrollBar(m_hWnd, SB_CTL, bShow);
}
BOOL EnableScrollBar(UINT nArrowFlags = ESB_ENABLE_BOTH)
{
ATLASSERT(::IsWindow(m_hWnd));
return ::EnableScrollBar(m_hWnd, SB_CTL, nArrowFlags);
}
#endif // !_WIN32_WCE
};
typedef CScrollBarT CScrollBar;
// --- Windows Common Controls ---
///////////////////////////////////////////////////////////////////////////////
// CImageList
// forward declarations
template class CImageListT;
typedef CImageListT CImageList;
typedef CImageListT CImageListManaged;
template
class CImageListT
{
public:
// Data members
HIMAGELIST m_hImageList;
// Constructor/destructor/operators
CImageListT(HIMAGELIST hImageList = NULL) : m_hImageList(hImageList)
{ }
~CImageListT()
{
if(t_bManaged && (m_hImageList != NULL))
Destroy();
}
CImageListT& operator =(HIMAGELIST hImageList)
{
Attach(hImageList);
return *this;
}
void Attach(HIMAGELIST hImageList)
{
ATLASSERT(m_hImageList == NULL);
ATLASSERT(hImageList != NULL);
if(t_bManaged && (m_hImageList != NULL) && (m_hImageList != hImageList))
ImageList_Destroy(m_hImageList);
m_hImageList = hImageList;
}
HIMAGELIST Detach()
{
HIMAGELIST hImageList = m_hImageList;
m_hImageList = NULL;
return hImageList;
}
operator HIMAGELIST() const { return m_hImageList; }
bool IsNull() const { return (m_hImageList == NULL); }
// Attributes
int GetImageCount() const
{
ATLASSERT(m_hImageList != NULL);
return ImageList_GetImageCount(m_hImageList);
}
COLORREF GetBkColor() const
{
ATLASSERT(m_hImageList != NULL);
return ImageList_GetBkColor(m_hImageList);
}
COLORREF SetBkColor(COLORREF cr)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_SetBkColor(m_hImageList, cr);
}
BOOL GetImageInfo(int nImage, IMAGEINFO* pImageInfo) const
{
ATLASSERT(m_hImageList != NULL);
return ImageList_GetImageInfo(m_hImageList, nImage, pImageInfo);
}
HICON GetIcon(int nIndex, UINT uFlags = ILD_NORMAL) const
{
ATLASSERT(m_hImageList != NULL);
return ImageList_GetIcon(m_hImageList, nIndex, uFlags);
}
BOOL GetIconSize(int& cx, int& cy) const
{
ATLASSERT(m_hImageList != NULL);
return ImageList_GetIconSize(m_hImageList, &cx, &cy);
}
BOOL GetIconSize(SIZE& size) const
{
ATLASSERT(m_hImageList != NULL);
return ImageList_GetIconSize(m_hImageList, (int*)&size.cx, (int*)&size.cy);
}
BOOL SetIconSize(int cx, int cy)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_SetIconSize(m_hImageList, cx, cy);
}
BOOL SetIconSize(SIZE size)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_SetIconSize(m_hImageList, size.cx, size.cy);
}
BOOL SetImageCount(UINT uNewCount)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_SetImageCount(m_hImageList, uNewCount);
}
BOOL SetOverlayImage(int nImage, int nOverlay)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_SetOverlayImage(m_hImageList, nImage, nOverlay);
}
// Operations
BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow)
{
ATLASSERT(m_hImageList == NULL);
m_hImageList = ImageList_Create(cx, cy, nFlags, nInitial, nGrow);
return (m_hImageList != NULL) ? TRUE : FALSE;
}
BOOL Create(ATL::_U_STRINGorID bitmap, int cx, int nGrow, COLORREF crMask)
{
ATLASSERT(m_hImageList == NULL);
m_hImageList = ImageList_LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, cx, nGrow, crMask);
return (m_hImageList != NULL) ? TRUE : FALSE;
}
BOOL CreateFromImage(ATL::_U_STRINGorID image, int cx, int nGrow, COLORREF crMask, UINT uType, UINT uFlags = LR_DEFAULTCOLOR | LR_DEFAULTSIZE)
{
ATLASSERT(m_hImageList == NULL);
m_hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, cx, nGrow, crMask, uType, uFlags);
return (m_hImageList != NULL) ? TRUE : FALSE;
}
BOOL Merge(HIMAGELIST hImageList1, int nImage1, HIMAGELIST hImageList2, int nImage2, int dx, int dy)
{
ATLASSERT(m_hImageList == NULL);
m_hImageList = ImageList_Merge(hImageList1, nImage1, hImageList2, nImage2, dx, dy);
return (m_hImageList != NULL) ? TRUE : FALSE;
}
#ifndef _WIN32_WCE
#ifdef __IStream_INTERFACE_DEFINED__
BOOL CreateFromStream(LPSTREAM lpStream)
{
ATLASSERT(m_hImageList == NULL);
m_hImageList = ImageList_Read(lpStream);
return (m_hImageList != NULL) ? TRUE : FALSE;
}
#endif // __IStream_INTERFACE_DEFINED__
#endif // !_WIN32_WCE
BOOL Destroy()
{
if (m_hImageList == NULL)
return FALSE;
BOOL bRet = ImageList_Destroy(m_hImageList);
if(bRet)
m_hImageList = NULL;
return bRet;
}
int Add(HBITMAP hBitmap, HBITMAP hBitmapMask = NULL)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_Add(m_hImageList, hBitmap, hBitmapMask);
}
int Add(HBITMAP hBitmap, COLORREF crMask)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_AddMasked(m_hImageList, hBitmap, crMask);
}
BOOL Remove(int nImage)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_Remove(m_hImageList, nImage);
}
BOOL RemoveAll()
{
ATLASSERT(m_hImageList != NULL);
return ImageList_RemoveAll(m_hImageList);
}
BOOL Replace(int nImage, HBITMAP hBitmap, HBITMAP hBitmapMask)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_Replace(m_hImageList, nImage, hBitmap, hBitmapMask);
}
int AddIcon(HICON hIcon)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_AddIcon(m_hImageList, hIcon);
}
int ReplaceIcon(int nImage, HICON hIcon)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_ReplaceIcon(m_hImageList, nImage, hIcon);
}
HICON ExtractIcon(int nImage)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_ExtractIcon(NULL, m_hImageList, nImage);
}
BOOL Draw(HDC hDC, int nImage, int x, int y, UINT nStyle)
{
ATLASSERT(m_hImageList != NULL);
ATLASSERT(hDC != NULL);
return ImageList_Draw(m_hImageList, nImage, hDC, x, y, nStyle);
}
BOOL Draw(HDC hDC, int nImage, POINT pt, UINT nStyle)
{
ATLASSERT(m_hImageList != NULL);
ATLASSERT(hDC != NULL);
return ImageList_Draw(m_hImageList, nImage, hDC, pt.x, pt.y, nStyle);
}
BOOL DrawEx(int nImage, HDC hDC, int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
{
ATLASSERT(m_hImageList != NULL);
ATLASSERT(hDC != NULL);
return ImageList_DrawEx(m_hImageList, nImage, hDC, x, y, dx, dy, rgbBk, rgbFg, fStyle);
}
BOOL DrawEx(int nImage, HDC hDC, RECT& rect, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
{
ATLASSERT(m_hImageList != NULL);
ATLASSERT(hDC != NULL);
return ImageList_DrawEx(m_hImageList, nImage, hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rgbBk, rgbFg, fStyle);
}
static BOOL DrawIndirect(IMAGELISTDRAWPARAMS* pimldp)
{
return ImageList_DrawIndirect(pimldp);
}
BOOL Copy(int nSrc, int nDst, UINT uFlags = ILCF_MOVE)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_Copy(m_hImageList, nDst, m_hImageList, nSrc, uFlags);
}
#ifdef __IStream_INTERFACE_DEFINED__
#ifndef _WIN32_WCE
static HIMAGELIST Read(LPSTREAM lpStream)
{
return ImageList_Read(lpStream);
}
BOOL Write(LPSTREAM lpStream)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_Write(m_hImageList, lpStream);
}
#endif // !_WIN32_WCE
#if (_WIN32_WINNT >= 0x0501)
static HRESULT ReadEx(DWORD dwFlags, LPSTREAM lpStream, REFIID riid, PVOID* ppv)
{
return ImageList_ReadEx(dwFlags, lpStream, riid, ppv);
}
HRESULT WriteEx(DWORD dwFlags, LPSTREAM lpStream)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_WriteEx(m_hImageList, dwFlags, lpStream);
}
#endif // (_WIN32_WINNT >= 0x0501)
#endif // __IStream_INTERFACE_DEFINED__
// Drag operations
BOOL BeginDrag(int nImage, POINT ptHotSpot)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_BeginDrag(m_hImageList, nImage, ptHotSpot.x, ptHotSpot.y);
}
BOOL BeginDrag(int nImage, int xHotSpot, int yHotSpot)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_BeginDrag(m_hImageList, nImage, xHotSpot, yHotSpot);
}
static void EndDrag()
{
ImageList_EndDrag();
}
static BOOL DragMove(POINT pt)
{
return ImageList_DragMove(pt.x, pt.y);
}
static BOOL DragMove(int x, int y)
{
return ImageList_DragMove(x, y);
}
BOOL SetDragCursorImage(int nDrag, POINT ptHotSpot)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_SetDragCursorImage(m_hImageList, nDrag, ptHotSpot.x, ptHotSpot.y);
}
BOOL SetDragCursorImage(int nDrag, int xHotSpot, int yHotSpot)
{
ATLASSERT(m_hImageList != NULL);
return ImageList_SetDragCursorImage(m_hImageList, nDrag, xHotSpot, yHotSpot);
}
static BOOL DragShowNolock(BOOL bShow = TRUE)
{
return ImageList_DragShowNolock(bShow);
}
static CImageList GetDragImage(LPPOINT lpPoint, LPPOINT lpPointHotSpot)
{
return CImageList(ImageList_GetDragImage(lpPoint, lpPointHotSpot));
}
static BOOL DragEnter(HWND hWnd, POINT point)
{
return ImageList_DragEnter(hWnd, point.x, point.y);
}
static BOOL DragEnter(HWND hWnd, int x, int y)
{
return ImageList_DragEnter(hWnd, x, y);
}
static BOOL DragLeave(HWND hWnd)
{
return ImageList_DragLeave(hWnd);
}
#if (_WIN32_IE >= 0x0400)
CImageList Duplicate() const
{
ATLASSERT(m_hImageList != NULL);
return CImageList(ImageList_Duplicate(m_hImageList));
}
static CImageList Duplicate(HIMAGELIST hImageList)
{
ATLASSERT(hImageList != NULL);
return CImageList(ImageList_Duplicate(hImageList));
}
#endif // (_WIN32_IE >= 0x0400)
};
///////////////////////////////////////////////////////////////////////////////
// CToolTipCtrl
#ifndef _WIN32_WCE
class CToolInfo : public TOOLINFO
{
public:
CToolInfo(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
{
Init(nFlags, hWnd, nIDTool, lpRect, lpstrText, lUserParam);
}
operator LPTOOLINFO() { return this; }
operator LPARAM() { return (LPARAM)this; }
void Init(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
{
ATLASSERT(::IsWindow(hWnd));
memset(this, 0, sizeof(TOOLINFO));
cbSize = RunTimeHelper::SizeOf_TOOLINFO();
uFlags = nFlags;
if(nIDTool == 0)
{
hwnd = ::GetParent(hWnd);
uFlags |= TTF_IDISHWND;
uId = (UINT_PTR)hWnd;
}
else
{
hwnd = hWnd;
uId = nIDTool;
}
if(lpRect != NULL)
rect = *lpRect;
hinst = ModuleHelper::GetResourceInstance();
lpszText = lpstrText;
lParam = lUserParam;
}
};
template
class CToolTipCtrlT : public TBase
{
public:
// Constructors
CToolTipCtrlT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CToolTipCtrlT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return TOOLTIPS_CLASS;
}
void GetText(LPTOOLINFO lpToolInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_GETTEXT, 0, (LPARAM)&lpToolInfo);
}
void GetText(LPTSTR lpstrText, HWND hWnd, UINT nIDTool = 0) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
::SendMessage(m_hWnd, TTM_GETTEXT, 0, ti);
}
BOOL GetToolInfo(LPTOOLINFO lpToolInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, (LPARAM)lpToolInfo);
}
BOOL GetToolInfo(HWND hWnd, UINT nIDTool, UINT* puFlags, LPRECT lpRect, LPTSTR lpstrText) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
ATLASSERT(puFlags != NULL);
ATLASSERT(lpRect != NULL);
CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
BOOL bRet = (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, ti);
if(bRet != FALSE)
{
*puFlags = ti.uFlags;
*lpRect = ti.rect;
}
return bRet;
}
void SetToolInfo(LPTOOLINFO lpToolInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo);
}
void SetToolRect(LPTOOLINFO lpToolInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, (LPARAM)lpToolInfo);
}
void SetToolRect(HWND hWnd, UINT nIDTool, LPCRECT lpRect)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
ATLASSERT(nIDTool != 0);
CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRect, NULL);
::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, ti);
}
int GetToolCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TTM_GETTOOLCOUNT, 0, 0L);
}
int GetDelayTime(DWORD dwType) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TTM_GETDELAYTIME, dwType, 0L);
}
void SetDelayTime(DWORD dwType, int nTime)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_SETDELAYTIME, dwType, MAKELPARAM(nTime, 0));
}
void GetMargin(LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_GETMARGIN, 0, (LPARAM)lpRect);
}
void SetMargin(LPRECT lpRect)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_SETMARGIN, 0, (LPARAM)lpRect);
}
int GetMaxTipWidth() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TTM_GETMAXTIPWIDTH, 0, 0L);
}
int SetMaxTipWidth(int nWidth)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TTM_SETMAXTIPWIDTH, 0, nWidth);
}
COLORREF GetTipBkColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPBKCOLOR, 0, 0L);
}
void SetTipBkColor(COLORREF clr)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_SETTIPBKCOLOR, (WPARAM)clr, 0L);
}
COLORREF GetTipTextColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPTEXTCOLOR, 0, 0L);
}
void SetTipTextColor(COLORREF clr)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_SETTIPTEXTCOLOR, (WPARAM)clr, 0L);
}
BOOL GetCurrentTool(LPTOOLINFO lpToolInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TTM_GETCURRENTTOOL, 0, (LPARAM)lpToolInfo);
}
#if (_WIN32_IE >= 0x0500)
SIZE GetBubbleSize(LPTOOLINFO lpToolInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TTM_GETBUBBLESIZE, 0, (LPARAM)lpToolInfo);
SIZE size = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
return size;
}
BOOL SetTitle(UINT uIcon, LPCTSTR lpstrTitle)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle);
}
#endif // (_WIN32_IE >= 0x0500)
#if (_WIN32_WINNT >= 0x0501)
void GetTitle(PTTGETTITLE pTTGetTitle) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_GETTITLE, 0, (LPARAM)pTTGetTitle);
}
void SetWindowTheme(LPCWSTR lpstrTheme)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
}
#endif // (_WIN32_WINNT >= 0x0501)
// Operations
void Activate(BOOL bActivate)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_ACTIVATE, bActivate, 0L);
}
BOOL AddTool(LPTOOLINFO lpToolInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, (LPARAM)lpToolInfo);
}
BOOL AddTool(HWND hWnd, ATL::_U_STRINGorID text = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT nIDTool = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
// the toolrect and toolid must both be zero or both valid
ATLASSERT((lpRectTool != NULL && nIDTool != 0) || (lpRectTool == NULL && nIDTool == 0));
CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRectTool, (LPTSTR)text.m_lpstr);
return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, ti);
}
void DelTool(LPTOOLINFO lpToolInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_DELTOOL, 0, (LPARAM)lpToolInfo);
}
void DelTool(HWND hWnd, UINT nIDTool = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
CToolInfo ti(0, hWnd, nIDTool, NULL, NULL);
::SendMessage(m_hWnd, TTM_DELTOOL, 0, ti);
}
BOOL HitTest(LPTTHITTESTINFO lpHitTestInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)lpHitTestInfo);
}
BOOL HitTest(HWND hWnd, POINT pt, LPTOOLINFO lpToolInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
ATLASSERT(lpToolInfo != NULL);
TTHITTESTINFO hti = { 0 };
hti.ti.cbSize = RunTimeHelper::SizeOf_TOOLINFO();
hti.hwnd = hWnd;
hti.pt.x = pt.x;
hti.pt.y = pt.y;
if((BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)&hti) != FALSE)
{
*lpToolInfo = hti.ti;
return TRUE;
}
return FALSE;
}
void RelayEvent(LPMSG lpMsg)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_RELAYEVENT, 0, (LPARAM)lpMsg);
}
void UpdateTipText(LPTOOLINFO lpToolInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)lpToolInfo);
}
void UpdateTipText(ATL::_U_STRINGorID text, HWND hWnd, UINT nIDTool = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
CToolInfo ti(0, hWnd, nIDTool, NULL, (LPTSTR)text.m_lpstr);
::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, ti);
}
BOOL EnumTools(UINT nTool, LPTOOLINFO lpToolInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TTM_ENUMTOOLS, nTool, (LPARAM)lpToolInfo);
}
void Pop()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_POP, 0, 0L);
}
void TrackActivate(LPTOOLINFO lpToolInfo, BOOL bActivate)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_TRACKACTIVATE, bActivate, (LPARAM)lpToolInfo);
}
void TrackActivate(HWND hWnd, UINT nIDTool, BOOL bActivate)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hWnd != NULL);
CToolInfo ti(0, hWnd, nIDTool);
::SendMessage(m_hWnd, TTM_TRACKACTIVATE, bActivate, ti);
}
void TrackPosition(int xPos, int yPos)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos));
}
#if (_WIN32_IE >= 0x0400)
void Update()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_UPDATE, 0, 0L);
}
#endif // (_WIN32_IE >= 0x0400)
#if (_WIN32_IE >= 0x0500)
BOOL AdjustRect(LPRECT lpRect, BOOL bLarger /*= TRUE*/)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TTM_ADJUSTRECT, bLarger, (LPARAM)lpRect);
}
#endif // (_WIN32_IE >= 0x0500)
#if (_WIN32_WINNT >= 0x0501)
void Popup()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TTM_POPUP, 0, 0L);
}
#endif // (_WIN32_WINNT >= 0x0501)
};
typedef CToolTipCtrlT CToolTipCtrl;
#endif // !_WIN32_WCE
///////////////////////////////////////////////////////////////////////////////
// CHeaderCtrl
template
class CHeaderCtrlT : public TBase
{
public:
// Constructors
CHeaderCtrlT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CHeaderCtrlT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return WC_HEADER;
}
int GetItemCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_GETITEMCOUNT, 0, 0L);
}
BOOL GetItem(int nIndex, LPHDITEM pHeaderItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_GETITEM, nIndex, (LPARAM)pHeaderItem);
}
BOOL SetItem(int nIndex, LPHDITEM pHeaderItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_SETITEM, nIndex, (LPARAM)pHeaderItem);
}
CImageList GetImageList() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_GETIMAGELIST, 0, 0L));
}
CImageList SetImageList(HIMAGELIST hImageList)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_SETIMAGELIST, 0, (LPARAM)hImageList));
}
BOOL GetOrderArray(int nSize, int* lpnArray) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_GETORDERARRAY, nSize, (LPARAM)lpnArray);
}
BOOL SetOrderArray(int nSize, int* lpnArray)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_SETORDERARRAY, nSize, (LPARAM)lpnArray);
}
BOOL GetItemRect(int nIndex, LPRECT lpItemRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMRECT, nIndex, (LPARAM)lpItemRect);
}
int SetHotDivider(BOOL bPos, DWORD dwInputValue)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_SETHOTDIVIDER, bPos, dwInputValue);
}
#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
BOOL GetUnicodeFormat() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_GETUNICODEFORMAT, 0, 0L);
}
BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_SETUNICODEFORMAT, bUnicode, 0L);
}
#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
int GetBitmapMargin() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_GETBITMAPMARGIN, 0, 0L);
}
int SetBitmapMargin(int nWidth)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_SETBITMAPMARGIN, nWidth, 0L);
}
int SetFilterChangeTimeout(DWORD dwTimeOut)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_SETFILTERCHANGETIMEOUT, 0, dwTimeOut);
}
#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
#if (_WIN32_WINNT >= 0x0600)
BOOL GetItemDropDownRect(int nIndex, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect);
}
BOOL GetOverflowRect(LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_GETOVERFLOWRECT, 0, (LPARAM)lpRect);
}
int GetFocusedItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_GETFOCUSEDITEM, 0, 0L);
}
BOOL SetFocusedItem(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_SETFOCUSEDITEM, 0, nIndex);
}
#endif // (_WIN32_WINNT >= 0x0600)
// Operations
int InsertItem(int nIndex, LPHDITEM phdi)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_INSERTITEM, nIndex, (LPARAM)phdi);
}
int AddItem(LPHDITEM phdi)
{
return InsertItem(GetItemCount(), phdi);
}
BOOL DeleteItem(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_DELETEITEM, nIndex, 0L);
}
BOOL Layout(HD_LAYOUT* pHeaderLayout)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, HDM_LAYOUT, 0, (LPARAM)pHeaderLayout);
}
int HitTest(LPHDHITTESTINFO lpHitTestInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)lpHitTestInfo);
}
int OrderToIndex(int nOrder)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_ORDERTOINDEX, nOrder, 0L);
}
CImageList CreateDragImage(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_CREATEDRAGIMAGE, nIndex, 0L));
}
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
int EditFilter(int nColumn, BOOL bDiscardChanges)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_EDITFILTER, nColumn, MAKELPARAM(bDiscardChanges, 0));
}
int ClearFilter(int nColumn)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, nColumn, 0L);
}
int ClearAllFilters()
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, (WPARAM)-1, 0L);
}
#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
};
typedef CHeaderCtrlT CHeaderCtrl;
///////////////////////////////////////////////////////////////////////////////
// CListViewCtrl
template
class CListViewCtrlT : public TBase
{
public:
// Constructors
CListViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CListViewCtrlT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return WC_LISTVIEW;
}
COLORREF GetBkColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, LVM_GETBKCOLOR, 0, 0L);
}
BOOL SetBkColor(COLORREF cr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETBKCOLOR, 0, cr);
}
CImageList GetImageList(int nImageListType) const
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_GETIMAGELIST, nImageListType, 0L));
}
CImageList SetImageList(HIMAGELIST hImageList, int nImageList)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, nImageList, (LPARAM)hImageList));
}
int GetItemCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETITEMCOUNT, 0, 0L);
}
BOOL SetItemCount(int nItems)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, 0L);
}
BOOL GetItem(LPLVITEM pItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
}
BOOL SetItem(const LVITEM* pItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)pItem);
}
BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.mask = nMask;
lvi.iItem = nItem;
lvi.iSubItem = nSubItem;
lvi.stateMask = nStateMask;
lvi.state = nState;
lvi.pszText = (LPTSTR) lpszItem;
lvi.iImage = nImage;
lvi.lParam = lParam;
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)&lvi);
}
UINT GetItemState(int nItem, UINT nMask) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, LVM_GETITEMSTATE, nItem, nMask);
}
BOOL SetItemState(int nItem, UINT nState, UINT nStateMask)
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.state = nState;
lvi.stateMask = nStateMask;
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)&lvi);
}
BOOL SetItemState(int nItem, LPLVITEM pItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)pItem);
}
#ifndef _ATL_NO_COM
BOOL GetItemText(int nItem, int nSubItem, BSTR& bstrText) const
{
USES_CONVERSION;
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(bstrText == NULL);
LVITEM lvi = { 0 };
lvi.iSubItem = nSubItem;
LPTSTR lpstrText = NULL;
int nRes = 0;
for(int nLen = 256; ; nLen *= 2)
{
ATLTRY(lpstrText = new TCHAR[nLen]);
if(lpstrText == NULL)
break;
lpstrText[0] = NULL;
lvi.cchTextMax = nLen;
lvi.pszText = lpstrText;
nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
if(nRes < nLen - 1)
break;
delete [] lpstrText;
lpstrText = NULL;
}
if(lpstrText != NULL)
{
if(nRes != 0)
bstrText = ::SysAllocString(T2OLE(lpstrText));
delete [] lpstrText;
}
return (bstrText != NULL) ? TRUE : FALSE;
}
#endif // !_ATL_NO_COM
#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
int GetItemText(int nItem, int nSubItem, _CSTRING_NS::CString& strText) const
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.iSubItem = nSubItem;
strText.Empty();
int nRes = 0;
for(int nLen = 256; ; nLen *= 2)
{
lvi.cchTextMax = nLen;
lvi.pszText = strText.GetBufferSetLength(nLen);
if(lvi.pszText == NULL)
{
nRes = 0;
break;
}
nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
if(nRes < nLen - 1)
break;
}
strText.ReleaseBuffer();
return nRes;
}
#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
int GetItemText(int nItem, int nSubItem, LPTSTR lpszText, int nLen) const
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.iSubItem = nSubItem;
lvi.cchTextMax = nLen;
lvi.pszText = lpszText;
return (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
}
BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItem(nItem, nSubItem, LVIF_TEXT, lpszText, 0, 0, 0, 0);
}
DWORD_PTR GetItemData(int nItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.iItem = nItem;
lvi.mask = LVIF_PARAM;
BOOL bRet = (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)&lvi);
return (DWORD_PTR)(bRet ? lvi.lParam : NULL);
}
BOOL SetItemData(int nItem, DWORD_PTR dwData)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItem(nItem, 0, LVIF_PARAM, NULL, 0, 0, 0, (LPARAM)dwData);
}
UINT GetCallbackMask() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, LVM_GETCALLBACKMASK, 0, 0L);
}
BOOL SetCallbackMask(UINT nMask)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETCALLBACKMASK, nMask, 0L);
}
BOOL GetItemPosition(int nItem, LPPOINT lpPoint) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMPOSITION, nItem, (LPARAM)lpPoint);
}
BOOL SetItemPosition(int nItem, POINT pt)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
}
BOOL SetItemPosition(int nItem, int x, int y)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
POINT pt = { x, y };
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
}
int GetStringWidth(LPCTSTR lpsz) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETSTRINGWIDTH, 0, (LPARAM)lpsz);
}
CEdit GetEditControl() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CEdit((HWND)::SendMessage(m_hWnd, LVM_GETEDITCONTROL, 0, 0L));
}
BOOL GetColumn(int nCol, LVCOLUMN* pColumn) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMN, nCol, (LPARAM)pColumn);
}
BOOL SetColumn(int nCol, const LVCOLUMN* pColumn)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMN, nCol, (LPARAM)pColumn);
}
int GetColumnWidth(int nCol) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETCOLUMNWIDTH, nCol, 0L);
}
BOOL SetColumnWidth(int nCol, int cx)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNWIDTH, nCol, MAKELPARAM(cx, 0));
}
BOOL GetViewRect(LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETVIEWRECT, 0, (LPARAM)lpRect);
}
COLORREF GetTextColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTCOLOR, 0, 0L);
}
BOOL SetTextColor(COLORREF cr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTCOLOR, 0, cr);
}
COLORREF GetTextBkColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTBKCOLOR, 0, 0L);
}
BOOL SetTextBkColor(COLORREF cr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTBKCOLOR, 0, cr);
}
int GetTopIndex() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETTOPINDEX, 0, 0L);
}
int GetCountPerPage() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETCOUNTPERPAGE, 0, 0L);
}
BOOL GetOrigin(LPPOINT lpPoint) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETORIGIN, 0, (LPARAM)lpPoint);
}
UINT GetSelectedCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, LVM_GETSELECTEDCOUNT, 0, 0L);
}
BOOL GetItemRect(int nItem, LPRECT lpRect, UINT nCode) const
{
ATLASSERT(::IsWindow(m_hWnd));
lpRect->left = nCode;
return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect);
}
#ifndef _WIN32_WCE
HCURSOR GetHotCursor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HCURSOR)::SendMessage(m_hWnd, LVM_GETHOTCURSOR, 0, 0L);
}
HCURSOR SetHotCursor(HCURSOR hHotCursor)
{
ATLASSERT(::IsWindow(m_hWnd));
return (HCURSOR)::SendMessage(m_hWnd, LVM_SETHOTCURSOR, 0, (LPARAM)hHotCursor);
}
int GetHotItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETHOTITEM, 0, 0L);
}
int SetHotItem(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_SETHOTITEM, nIndex, 0L);
}
#endif // !_WIN32_WCE
BOOL GetColumnOrderArray(int nCount, int* lpnArray) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
}
BOOL SetColumnOrderArray(int nCount, int* lpnArray)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
}
CHeaderCtrl GetHeader() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CHeaderCtrl((HWND)::SendMessage(m_hWnd, LVM_GETHEADER, 0, 0L));
}
BOOL GetSubItemRect(int nItem, int nSubItem, int nFlag, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_REPORT);
ATLASSERT(lpRect != NULL);
lpRect->top = nSubItem;
lpRect->left = nFlag;
return (BOOL)::SendMessage(m_hWnd, LVM_GETSUBITEMRECT, nItem, (LPARAM)lpRect);
}
DWORD SetIconSpacing(int cx, int cy)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_ICON);
return (DWORD)::SendMessage(m_hWnd, LVM_SETICONSPACING, 0, MAKELPARAM(cx, cy));
}
int GetISearchString(LPTSTR lpstr) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
}
void GetItemSpacing(SIZE& sizeSpacing, BOOL bSmallIconView = FALSE) const
{
ATLASSERT(::IsWindow(m_hWnd));
DWORD dwRet = (DWORD)::SendMessage(m_hWnd, LVM_GETITEMSPACING, bSmallIconView, 0L);
sizeSpacing.cx = GET_X_LPARAM(dwRet);
sizeSpacing.cy = GET_Y_LPARAM(dwRet);
}
#if (_WIN32_WCE >= 410)
void SetItemSpacing(INT cySpacing)
{
ATLASSERT(::IsWindow(m_hWnd));
ListView_SetItemSpacing(m_hWnd, cySpacing);
}
#endif // (_WIN32_WCE >= 410)
// single-selection only
int GetSelectedIndex() const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0);
return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
}
BOOL GetSelectedItem(LPLVITEM pItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0);
ATLASSERT(pItem != NULL);
pItem->iItem = (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
if(pItem->iItem == -1)
return FALSE;
return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
}
// extended list view styles
DWORD GetExtendedListViewStyle() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L);
}
// dwExMask = 0 means all styles
DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle);
}
// checkboxes only
BOOL GetCheckState(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetExtendedListViewStyle() & LVS_EX_CHECKBOXES) != 0);
UINT uRet = GetItemState(nIndex, LVIS_STATEIMAGEMASK);
return (uRet >> 12) - 1;
}
BOOL SetCheckState(int nItem, BOOL bCheck)
{
int nCheck = bCheck ? 2 : 1; // one based index
return SetItemState(nItem, INDEXTOSTATEIMAGEMASK(nCheck), LVIS_STATEIMAGEMASK);
}
// view type
DWORD GetViewType() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (GetStyle() & LVS_TYPEMASK);
}
DWORD SetViewType(DWORD dwType)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(dwType == LVS_ICON || dwType == LVS_SMALLICON || dwType == LVS_LIST || dwType == LVS_REPORT);
DWORD dwOldType = GetViewType();
if(dwType != dwOldType)
ModifyStyle(LVS_TYPEMASK, (dwType & LVS_TYPEMASK));
return dwOldType;
}
#if (_WIN32_IE >= 0x0400)
#ifndef _WIN32_WCE
BOOL GetBkImage(LPLVBKIMAGE plvbki) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETBKIMAGE, 0, (LPARAM)plvbki);
}
BOOL SetBkImage(LPLVBKIMAGE plvbki)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETBKIMAGE, 0, (LPARAM)plvbki);
}
#endif // !_WIN32_WCE
int GetSelectionMark() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETSELECTIONMARK, 0, 0L);
}
int SetSelectionMark(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_SETSELECTIONMARK, 0, nIndex);
}
#ifndef _WIN32_WCE
BOOL GetWorkAreas(int nWorkAreas, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
}
BOOL SetWorkAreas(int nWorkAreas, LPRECT lpRect)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
}
DWORD GetHoverTime() const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
return (DWORD)::SendMessage(m_hWnd, LVM_GETHOVERTIME, 0, 0L);
}
DWORD SetHoverTime(DWORD dwHoverTime)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
return (DWORD)::SendMessage(m_hWnd, LVM_SETHOVERTIME, 0, dwHoverTime);
}
BOOL GetNumberOfWorkAreas(int* pnWorkAreas) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETNUMBEROFWORKAREAS, 0, (LPARAM)pnWorkAreas);
}
#endif // !_WIN32_WCE
BOOL SetItemCountEx(int nItems, DWORD dwFlags)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(((GetStyle() & LVS_OWNERDATA) != 0) && (((GetStyle() & LVS_TYPEMASK) == LVS_REPORT) || ((GetStyle() & LVS_TYPEMASK) == LVS_LIST)));
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, dwFlags);
}
#ifndef _WIN32_WCE
CToolTipCtrl GetToolTips() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_GETTOOLTIPS, 0, 0L));
}
CToolTipCtrl SetToolTips(HWND hWndTT)
{
ATLASSERT(::IsWindow(m_hWnd));
return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
}
BOOL GetUnicodeFormat() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETUNICODEFORMAT, 0, 0L);
}
BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETUNICODEFORMAT, bUnicode, 0L);
}
#endif // !_WIN32_WCE
#endif // (_WIN32_IE >= 0x0400)
#if (_WIN32_WINNT >= 0x0501)
int GetSelectedColumn() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETSELECTEDCOLUMN, 0, 0L);
}
void SetSelectedColumn(int nColumn)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_SETSELECTEDCOLUMN, nColumn, 0L);
}
DWORD GetView() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, LVM_GETVIEW, 0, 0L);
}
int SetView(DWORD dwView)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_SETVIEW, dwView, 0L);
}
BOOL IsGroupViewEnabled() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_ISGROUPVIEWENABLED, 0, 0L);
}
int GetGroupInfo(int nGroupID, PLVGROUP pGroup) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETGROUPINFO, nGroupID, (LPARAM)pGroup);
}
int SetGroupInfo(int nGroupID, PLVGROUP pGroup)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_SETGROUPINFO, nGroupID, (LPARAM)pGroup);
}
void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_GETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
}
void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_SETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
}
void GetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_GETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
}
BOOL SetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
}
void GetTileInfo(PLVTILEINFO pTileInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_GETTILEINFO, 0, (LPARAM)pTileInfo);
}
BOOL SetTileInfo(PLVTILEINFO pTileInfo)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEINFO, 0, (LPARAM)pTileInfo);
}
BOOL GetInsertMark(LPLVINSERTMARK pInsertMark) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETINSERTMARK, 0, (LPARAM)pInsertMark);
}
BOOL SetInsertMark(LPLVINSERTMARK pInsertMark)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETINSERTMARK, 0, (LPARAM)pInsertMark);
}
int GetInsertMarkRect(LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETINSERTMARKRECT, 0, (LPARAM)lpRect);
}
COLORREF GetInsertMarkColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, LVM_GETINSERTMARKCOLOR, 0, 0L);
}
COLORREF SetInsertMarkColor(COLORREF clr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, LVM_SETINSERTMARKCOLOR, 0, clr);
}
COLORREF GetOutlineColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, LVM_GETOUTLINECOLOR, 0, 0L);
}
COLORREF SetOutlineColor(COLORREF clr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, LVM_SETOUTLINECOLOR, 0, clr);
}
#endif // (_WIN32_WINNT >= 0x0501)
#if (_WIN32_WINNT >= 0x0600)
int GetGroupCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETGROUPCOUNT, 0, 0L);
}
BOOL GetGroupInfoByIndex(int nIndex, PLVGROUP pGroup) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPINFOBYINDEX, nIndex, (LPARAM)pGroup);
}
BOOL GetGroupRect(int nGroupID, int nType, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(lpRect != NULL);
if(lpRect != NULL)
lpRect->top = nType;
return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPRECT, nGroupID, (LPARAM)lpRect);
}
UINT GetGroupState(int nGroupID, UINT uMask) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, LVM_GETGROUPSTATE, nGroupID, (LPARAM)uMask);
}
int GetFocusedGroup() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETFOCUSEDGROUP, 0, 0L);
}
BOOL GetEmptyText(LPWSTR lpstrText, int cchText) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETEMPTYTEXT, cchText, (LPARAM)lpstrText);
}
BOOL GetFooterRect(LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERRECT, 0, (LPARAM)lpRect);
}
BOOL GetFooterInfo(LPLVFOOTERINFO lpFooterInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERINFO, 0, (LPARAM)lpFooterInfo);
}
BOOL GetFooterItemRect(int nItem, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEMRECT, nItem, (LPARAM)lpRect);
}
BOOL GetFooterItem(int nItem, LPLVFOOTERITEM lpFooterItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEM, nItem, (LPARAM)lpFooterItem);
}
BOOL GetItemIndexRect(PLVITEMINDEX pItemIndex, int nSubItem, int nType, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(pItemIndex != NULL);
ATLASSERT(lpRect != NULL);
if(lpRect != NULL)
{
lpRect->top = nSubItem;
lpRect->left = nType;
}
return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMINDEXRECT, (WPARAM)pItemIndex, (LPARAM)lpRect);
}
BOOL SetItemIndexState(PLVITEMINDEX pItemIndex, UINT uState, UINT dwMask)
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.state = uState;
lvi.stateMask = dwMask;
return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMINDEXSTATE, (WPARAM)pItemIndex, (LPARAM)&lvi);
}
BOOL GetNextItemIndex(PLVITEMINDEX pItemIndex, WORD wFlags) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_GETNEXTITEMINDEX, (WPARAM)pItemIndex, MAKELPARAM(wFlags, 0));
}
#endif // (_WIN32_WINNT >= 0x0600)
// Operations
int InsertColumn(int nCol, const LVCOLUMN* pColumn)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn);
}
int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT,
int nWidth = -1, int nSubItem = -1, int iImage = -1, int iOrder = -1)
{
LVCOLUMN column = { 0 };
column.mask = LVCF_TEXT|LVCF_FMT;
column.pszText = (LPTSTR)lpszColumnHeading;
column.fmt = nFormat;
if (nWidth != -1)
{
column.mask |= LVCF_WIDTH;
column.cx = nWidth;
}
if (nSubItem != -1)
{
column.mask |= LVCF_SUBITEM;
column.iSubItem = nSubItem;
}
if (iImage != -1)
{
column.mask |= LVCF_IMAGE;
column.iImage = iImage;
}
if (iOrder != -1)
{
column.mask |= LVCF_ORDER;
column.iOrder = iOrder;
}
return InsertColumn(nCol, &column);
}
BOOL DeleteColumn(int nCol)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_DELETECOLUMN, nCol, 0L);
}
int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM item = { 0 };
item.mask = nMask;
item.iItem = nItem;
item.iSubItem = 0;
item.pszText = (LPTSTR)lpszItem;
item.state = nState;
item.stateMask = nStateMask;
item.iImage = nImage;
item.lParam = lParam;
return InsertItem(&item);
}
int InsertItem(const LVITEM* pItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_INSERTITEM, 0, (LPARAM)pItem);
}
int InsertItem(int nItem, LPCTSTR lpszItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return InsertItem(LVIF_TEXT, nItem, lpszItem, 0, 0, 0, 0);
}
int InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
{
ATLASSERT(::IsWindow(m_hWnd));
return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0);
}
int GetNextItem(int nItem, int nFlags) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0));
}
BOOL DeleteItem(int nItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_DELETEITEM, nItem, 0L);
}
BOOL DeleteAllItems()
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_DELETEALLITEMS, 0, 0L);
}
int FindItem(LVFINDINFO* pFindInfo, int nStart = -1) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo);
}
int FindItem(LPCTSTR lpstrFind, bool bPartial = true, bool bWrap = false, int nStart = -1) const
{
ATLASSERT(::IsWindow(m_hWnd));
LVFINDINFO lvfi = { 0 };
lvfi.flags = LVFI_STRING | (bWrap ? LVFI_WRAP : 0) | (bPartial ? LVFI_PARTIAL : 0);
lvfi.psz = lpstrFind;
return (int)::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)&lvfi);
}
int HitTest(LVHITTESTINFO* pHitTestInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)pHitTestInfo);
}
int HitTest(POINT pt, UINT* pFlags) const
{
ATLASSERT(::IsWindow(m_hWnd));
LVHITTESTINFO hti = { 0 };
hti.pt = pt;
int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)&hti);
if (pFlags != NULL)
*pFlags = hti.flags;
return nRes;
}
BOOL EnsureVisible(int nItem, BOOL bPartialOK)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_ENSUREVISIBLE, nItem, MAKELPARAM(bPartialOK, 0));
}
BOOL Scroll(SIZE size)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SCROLL, size.cx, size.cy);
}
BOOL RedrawItems(int nFirst, int nLast)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_REDRAWITEMS, nFirst, nLast);
}
BOOL Arrange(UINT nCode)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_ARRANGE, nCode, 0L);
}
CEdit EditLabel(int nItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return CEdit((HWND)::SendMessage(m_hWnd, LVM_EDITLABEL, nItem, 0L));
}
BOOL Update(int nItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_UPDATE, nItem, 0L);
}
BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMS, (WPARAM)lParamSort, (LPARAM)pfnCompare);
}
CImageList RemoveImageList(int nImageList)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
}
CImageList CreateDragImage(int nItem, LPPOINT lpPoint)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_CREATEDRAGIMAGE, nItem, (LPARAM)lpPoint));
}
DWORD ApproximateViewRect(int cx = -1, int cy = -1, int nCount = -1)
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, LVM_APPROXIMATEVIEWRECT, nCount, MAKELPARAM(cx, cy));
}
int SubItemHitTest(LPLVHITTESTINFO lpInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, 0, (LPARAM)lpInfo);
}
int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1,
int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
int nFmt = LVCFMT_LEFT)
{
const int cxOffset = 15;
ATLASSERT(::IsWindow(m_hWnd));
LVCOLUMN lvc = { 0 };
lvc.mask = nMask;
lvc.fmt = nFmt;
lvc.pszText = (LPTSTR)strItem;
lvc.cx = GetStringWidth(lvc.pszText) + cxOffset;
if(nMask & LVCF_SUBITEM)
lvc.iSubItem = (nSubItem != -1) ? nSubItem : nItem;
return InsertColumn(nItem, &lvc);
}
int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -3)
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT;
lvItem.iItem = nItem;
lvItem.iSubItem = nSubItem;
lvItem.pszText = (LPTSTR)strItem;
if(nImageIndex != -3)
{
lvItem.mask |= LVIF_IMAGE;
lvItem.iImage = nImageIndex;
}
if(nSubItem == 0)
return InsertItem(&lvItem);
return SetItem(&lvItem) ? nItem : -1;
}
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMSEX, (WPARAM)lParamSort, (LPARAM)pfnCompare);
}
#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
#if (_WIN32_WINNT >= 0x0501)
int InsertGroup(int nItem, PLVGROUP pGroup)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_INSERTGROUP, nItem, (LPARAM)pGroup);
}
int AddGroup(PLVGROUP pGroup)
{
return InsertGroup(-1, pGroup);
}
int RemoveGroup(int nGroupID)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_REMOVEGROUP, nGroupID, 0L);
}
void MoveGroup(int nGroupID, int nItem)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_MOVEGROUP, nGroupID, nItem);
}
void MoveItemToGroup(int nItem, int nGroupID)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_MOVEITEMTOGROUP, nItem, nGroupID);
}
int EnableGroupView(BOOL bEnable)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_ENABLEGROUPVIEW, bEnable, 0L);
}
int SortGroups(PFNLVGROUPCOMPARE pCompareFunc, LPVOID lpVoid = NULL)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_SORTGROUPS, (WPARAM)pCompareFunc, (LPARAM)lpVoid);
}
void InsertGroupSorted(PLVINSERTGROUPSORTED pInsertGroupSorted)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_INSERTGROUPSORTED, (WPARAM)pInsertGroupSorted, 0L);
}
void RemoveAllGroups()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_REMOVEALLGROUPS, 0, 0L);
}
BOOL HasGroup(int nGroupID)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_HASGROUP, nGroupID, 0L);
}
BOOL InsertMarkHitTest(LPPOINT lpPoint, LPLVINSERTMARK pInsertMark) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)pInsertMark);
}
BOOL SetInfoTip(PLVSETINFOTIP pSetInfoTip)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, LVM_SETINFOTIP, 0, (LPARAM)pSetInfoTip);
}
void CancelEditLabel()
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, LVM_CANCELEDITLABEL, 0, 0L);
}
UINT MapIndexToID(int nIndex) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, LVM_MAPINDEXTOID, nIndex, 0L);
}
int MapIDToIndex(UINT uID) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_MAPIDTOINDEX, uID, 0L);
}
#endif // (_WIN32_WINNT >= 0x0501)
#if (_WIN32_WINNT >= 0x0600)
int HitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
}
int HitTestEx(POINT pt, UINT* pFlags) const
{
ATLASSERT(::IsWindow(m_hWnd));
LVHITTESTINFO hti = { 0 };
hti.pt = pt;
int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)&hti);
if (pFlags != NULL)
*pFlags = hti.flags;
return nRes;
}
int SubItemHitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
}
#endif // (_WIN32_WINNT >= 0x0600)
// Note: selects only one item
BOOL SelectItem(int nIndex)
{
ATLASSERT(::IsWindow(m_hWnd));
// multi-selection only: de-select all items
if((GetStyle() & LVS_SINGLESEL) == 0)
SetItemState(-1, 0, LVIS_SELECTED);
BOOL bRet = SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
if(bRet)
bRet = EnsureVisible(nIndex, FALSE);
return bRet;
}
};
typedef CListViewCtrlT CListViewCtrl;
///////////////////////////////////////////////////////////////////////////////
// CTreeViewCtrl
template
class CTreeViewCtrlT : public TBase
{
public:
// Constructors
CTreeViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
{ }
CTreeViewCtrlT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
// Attributes
static LPCTSTR GetWndClassName()
{
return WC_TREEVIEW;
}
UINT GetCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, TVM_GETCOUNT, 0, 0L);
}
UINT GetIndent() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, TVM_GETINDENT, 0, 0L);
}
void SetIndent(UINT nIndent)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TVM_SETINDENT, nIndent, 0L);
}
CImageList GetImageList(int nImageListType = TVSIL_NORMAL) const
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_GETIMAGELIST, (WPARAM)nImageListType, 0L));
}
CImageList SetImageList(HIMAGELIST hImageList, int nImageListType = TVSIL_NORMAL)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageListType, (LPARAM)hImageList));
}
BOOL GetItem(LPTVITEM pItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
}
BOOL SetItem(LPTVITEM pItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
}
BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage,
int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam)
{
ATLASSERT(::IsWindow(m_hWnd));
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = nMask;
item.pszText = (LPTSTR) lpszItem;
item.iImage = nImage;
item.iSelectedImage = nSelectedImage;
item.state = nState;
item.stateMask = nStateMask;
item.lParam = lParam;
return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)&item);
}
BOOL GetItemText(HTREEITEM hItem, LPTSTR lpstrText, int nLen) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(lpstrText != NULL);
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = TVIF_TEXT;
item.pszText = lpstrText;
item.cchTextMax = nLen;
return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
}
#ifndef _ATL_NO_COM
BOOL GetItemText(HTREEITEM hItem, BSTR& bstrText) const
{
USES_CONVERSION;
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(bstrText == NULL);
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = TVIF_TEXT;
LPTSTR lpstrText = NULL;
BOOL bRet = FALSE;
for(int nLen = 256; ; nLen *= 2)
{
ATLTRY(lpstrText = new TCHAR[nLen]);
if(lpstrText == NULL)
break;
lpstrText[0] = NULL;
item.pszText = lpstrText;
item.cchTextMax = nLen;
bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
if(!bRet || (lstrlen(item.pszText) < nLen - 1))
break;
delete [] lpstrText;
lpstrText = NULL;
}
if(lpstrText != NULL)
{
if(bRet)
bstrText = ::SysAllocString(T2OLE(lpstrText));
delete [] lpstrText;
}
return (bstrText != NULL) ? TRUE : FALSE;
}
#endif // !_ATL_NO_COM
#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
BOOL GetItemText(HTREEITEM hItem, _CSTRING_NS::CString& strText) const
{
ATLASSERT(::IsWindow(m_hWnd));
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = TVIF_TEXT;
strText.Empty();
BOOL bRet = FALSE;
for(int nLen = 256; ; nLen *= 2)
{
item.pszText = strText.GetBufferSetLength(nLen);
if(item.pszText == NULL)
{
bRet = FALSE;
break;
}
item.cchTextMax = nLen;
bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
if(!bRet || (lstrlen(item.pszText) < nLen - 1))
break;
}
strText.ReleaseBuffer();
return bRet;
}
#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
BOOL SetItemText(HTREEITEM hItem, LPCTSTR lpszItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItem(hItem, TVIF_TEXT, lpszItem, 0, 0, 0, 0, NULL);
}
BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage) const
{
ATLASSERT(::IsWindow(m_hWnd));
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE;
BOOL bRes = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
if (bRes)
{
nImage = item.iImage;
nSelectedImage = item.iSelectedImage;
}
return bRes;
}
BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItem(hItem, TVIF_IMAGE|TVIF_SELECTEDIMAGE, NULL, nImage, nSelectedImage, 0, 0, NULL);
}
UINT GetItemState(HTREEITEM hItem, UINT nStateMask) const
{
ATLASSERT(::IsWindow(m_hWnd));
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
return (((UINT)::SendMessage(m_hWnd, TVM_GETITEMSTATE, (WPARAM)hItem, (LPARAM)nStateMask)) & nStateMask);
#else // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE))
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = TVIF_STATE;
item.state = 0;
item.stateMask = nStateMask;
::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
return (item.state & nStateMask);
#endif // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE))
}
BOOL SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItem(hItem, TVIF_STATE, NULL, 0, 0, nState, nStateMask, NULL);
}
DWORD_PTR GetItemData(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = TVIF_PARAM;
BOOL bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
return (DWORD_PTR)(bRet ? item.lParam : NULL);
}
BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData)
{
ATLASSERT(::IsWindow(m_hWnd));
return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData);
}
CEdit GetEditControl() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CEdit((HWND)::SendMessage(m_hWnd, TVM_GETEDITCONTROL, 0, 0L));
}
UINT GetVisibleCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, TVM_GETVISIBLECOUNT, 0, 0L);
}
BOOL GetItemRect(HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly) const
{
ATLASSERT(::IsWindow(m_hWnd));
*(HTREEITEM*)lpRect = hItem;
return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMRECT, (WPARAM)bTextOnly, (LPARAM)lpRect);
}
BOOL ItemHasChildren(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
TVITEM item = { 0 };
item.hItem = hItem;
item.mask = TVIF_CHILDREN;
::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
return item.cChildren;
}
#ifndef _WIN32_WCE
CToolTipCtrl GetToolTips() const
{
ATLASSERT(::IsWindow(m_hWnd));
return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_GETTOOLTIPS, 0, 0L));
}
CToolTipCtrl SetToolTips(HWND hWndTT)
{
ATLASSERT(::IsWindow(m_hWnd));
return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
}
#endif // !_WIN32_WCE
int GetISearchString(LPTSTR lpstr) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
}
// checkboxes only
BOOL GetCheckState(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT((GetStyle() & TVS_CHECKBOXES) != 0);
UINT uRet = GetItemState(hItem, TVIS_STATEIMAGEMASK);
return (uRet >> 12) - 1;
}
BOOL SetCheckState(HTREEITEM hItem, BOOL bCheck)
{
int nCheck = bCheck ? 2 : 1; // one based index
return SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nCheck), TVIS_STATEIMAGEMASK);
}
#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
COLORREF GetBkColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_GETBKCOLOR, 0, 0L);
}
COLORREF SetBkColor(COLORREF clr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_SETBKCOLOR, 0, (LPARAM)clr);
}
COLORREF GetInsertMarkColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_GETINSERTMARKCOLOR, 0, 0L);
}
COLORREF SetInsertMarkColor(COLORREF clr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr);
}
int GetItemHeight() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TVM_GETITEMHEIGHT, 0, 0L);
}
int SetItemHeight(int cyHeight)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TVM_SETITEMHEIGHT, cyHeight, 0L);
}
int GetScrollTime() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TVM_GETSCROLLTIME, 0, 0L);
}
int SetScrollTime(int nScrollTime)
{
ATLASSERT(::IsWindow(m_hWnd));
return (int)::SendMessage(m_hWnd, TVM_SETSCROLLTIME, nScrollTime, 0L);
}
COLORREF GetTextColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_GETTEXTCOLOR, 0, 0L);
}
COLORREF SetTextColor(COLORREF clr)
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_SETTEXTCOLOR, 0, (LPARAM)clr);
}
BOOL GetUnicodeFormat() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_GETUNICODEFORMAT, 0, 0L);
}
BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SETUNICODEFORMAT, bUnicode, 0L);
}
#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
COLORREF GetLineColor() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_GETLINECOLOR, 0, 0L);
}
COLORREF SetLineColor(COLORREF clrNew /*= CLR_DEFAULT*/)
{
ATLASSERT(::IsWindow(m_hWnd));
return (COLORREF)::SendMessage(m_hWnd, TVM_SETLINECOLOR, 0, (LPARAM)clrNew);
}
#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
BOOL GetItem(LPTVITEMEX pItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
}
BOOL SetItem(LPTVITEMEX pItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
}
#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
DWORD GetExtendedStyle() const
{
#ifndef TVM_GETEXTENDEDSTYLE
const UINT TVM_GETEXTENDEDSTYLE = (TV_FIRST + 45);
#endif
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, TVM_GETEXTENDEDSTYLE, 0, 0L);
}
DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
{
#ifndef TVM_SETEXTENDEDSTYLE
const UINT TVM_SETEXTENDEDSTYLE = (TV_FIRST + 44);
#endif
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, TVM_SETEXTENDEDSTYLE, dwMask, dwStyle);
}
#if (_WIN32_WINNT >= 0x0600)
BOOL SetAutoScrollInfo(UINT uPixPerSec, UINT uUpdateTime)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SETAUTOSCROLLINFO, (WPARAM)uPixPerSec, (LPARAM)uUpdateTime);
}
DWORD GetSelectedCount() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (DWORD)::SendMessage(m_hWnd, TVM_GETSELECTEDCOUNT, 0, 0L);
}
BOOL GetItemPartRect(HTREEITEM hItem, TVITEMPART partID, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
TVGETITEMPARTRECTINFO gipri = { hItem, lpRect, partID };
return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMPARTRECT, 0, (LPARAM)&gipri);
}
#endif // (_WIN32_WINNT >= 0x0600)
// Operations
HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
}
HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage,
int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
{
ATLASSERT(::IsWindow(m_hWnd));
return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter);
}
HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
{
ATLASSERT(::IsWindow(m_hWnd));
return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
}
HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
HTREEITEM hParent, HTREEITEM hInsertAfter)
{
ATLASSERT(::IsWindow(m_hWnd));
TVINSERTSTRUCT tvis = { 0 };
tvis.hParent = hParent;
tvis.hInsertAfter = hInsertAfter;
tvis.item.mask = nMask;
tvis.item.pszText = (LPTSTR) lpszItem;
tvis.item.iImage = nImage;
tvis.item.iSelectedImage = nSelectedImage;
tvis.item.state = nState;
tvis.item.stateMask = nStateMask;
tvis.item.lParam = lParam;
return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
}
BOOL DeleteItem(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)hItem);
}
BOOL DeleteAllItems()
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
}
BOOL Expand(HTREEITEM hItem, UINT nCode = TVE_EXPAND)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_EXPAND, nCode, (LPARAM)hItem);
}
HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
}
HTREEITEM GetChildItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
}
HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
}
HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
}
HTREEITEM GetParentItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem);
}
HTREEITEM GetFirstVisibleItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
}
HTREEITEM GetNextVisibleItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
}
HTREEITEM GetPrevVisibleItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
}
HTREEITEM GetSelectedItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
}
HTREEITEM GetDropHilightItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
}
HTREEITEM GetRootItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
}
#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
HTREEITEM GetLastVisibleItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
}
#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
#if (_WIN32_IE >= 0x0600)
HTREEITEM GetNextSelectedItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L);
}
#endif // (_WIN32_IE >= 0x0600)
BOOL Select(HTREEITEM hItem, UINT nCode)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, nCode, (LPARAM)hItem);
}
BOOL SelectItem(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem);
}
BOOL SelectDropTarget(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItem);
}
BOOL SelectSetFirstVisible(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hItem);
}
CEdit EditLabel(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return CEdit((HWND)::SendMessage(m_hWnd, TVM_EDITLABEL, 0, (LPARAM)hItem));
}
BOOL EndEditLabelNow(BOOL bCancel)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_ENDEDITLABELNOW, bCancel, 0L);
}
HTREEITEM HitTest(TVHITTESTINFO* pHitTestInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
}
HTREEITEM HitTest(POINT pt, UINT* pFlags) const
{
ATLASSERT(::IsWindow(m_hWnd));
TVHITTESTINFO hti = { 0 };
hti.pt = pt;
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
if (pFlags != NULL)
*pFlags = hti.flags;
return hTreeItem;
}
BOOL SortChildren(HTREEITEM hItem, BOOL bRecurse = FALSE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDREN, (WPARAM)bRecurse, (LPARAM)hItem);
}
BOOL EnsureVisible(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem);
}
BOOL SortChildrenCB(LPTVSORTCB pSort, BOOL bRecurse = FALSE)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDRENCB, (WPARAM)bRecurse, (LPARAM)pSort);
}
CImageList RemoveImageList(int nImageList)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
}
CImageList CreateDragImage(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItem));
}
#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
BOOL SetInsertMark(HTREEITEM hTreeItem, BOOL bAfter)
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, bAfter, (LPARAM)hTreeItem);
}
BOOL RemoveInsertMark()
{
ATLASSERT(::IsWindow(m_hWnd));
return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, 0, 0L);
}
#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
#if (_WIN32_WINNT >= 0x0501)
HTREEITEM MapAccIDToHTREEITEM(UINT uID) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L);
}
UINT MapHTREEITEMToAccID(HTREEITEM hTreeItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
return (UINT)::SendMessage(m_hWnd, TVM_MAPHTREEITEMTOACCID, (WPARAM)hTreeItem, 0L);
}
#endif // (_WIN32_WINNT >= 0x0501)
#if (_WIN32_WINNT >= 0x0600)
void ShowInfoTip(HTREEITEM hItem)
{
ATLASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TVM_SHOWINFOTIP, 0, (LPARAM)hItem);
}
#endif // (_WIN32_WINNT >= 0x0600)
};
typedef CTreeViewCtrlT CTreeViewCtrl;
///////////////////////////////////////////////////////////////////////////////
// CTreeViewCtrlEx
// forward declaration
template class CTreeViewCtrlExT;
// Note: TBase here is for CTreeViewCtrlExT, and not for CTreeItemT itself
template
class CTreeItemT
{
public:
HTREEITEM m_hTreeItem;
CTreeViewCtrlExT* m_pTreeView;
// Construction
CTreeItemT(HTREEITEM hTreeItem = NULL, CTreeViewCtrlExT* pTreeView = NULL) : m_hTreeItem(hTreeItem), m_pTreeView(pTreeView)
{ }
CTreeItemT(const CTreeItemT& posSrc)
{
*this = posSrc;
}
operator HTREEITEM() { return m_hTreeItem; }
CTreeItemT& operator =(const CTreeItemT& itemSrc)
{
m_hTreeItem = itemSrc.m_hTreeItem;
m_pTreeView = itemSrc.m_pTreeView;
return *this;
}
// Attributes
CTreeViewCtrlExT* GetTreeView() const { return m_pTreeView; }
BOOL operator !() const { return m_hTreeItem == NULL; }
BOOL IsNull() const { return m_hTreeItem == NULL; }
BOOL GetRect(LPRECT lpRect, BOOL bTextOnly) const;
BOOL GetText(LPTSTR lpstrText, int nLen) const;
#ifndef _ATL_NO_COM
BOOL GetText(BSTR& bstrText) const;
#endif // !_ATL_NO_COM
#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
BOOL GetText(_CSTRING_NS::CString& strText) const;
#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
BOOL SetText(LPCTSTR lpszItem);
BOOL GetImage(int& nImage, int& nSelectedImage) const;
BOOL SetImage(int nImage, int nSelectedImage);
UINT GetState(UINT nStateMask) const;
BOOL SetState(UINT nState, UINT nStateMask);
DWORD_PTR GetData() const;
BOOL SetData(DWORD_PTR dwData);
BOOL SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam);
// Operations
CTreeItemT InsertAfter(LPCTSTR lpstrItem, HTREEITEM hItemAfter, int nImageIndex)
{
return _Insert(lpstrItem, nImageIndex, hItemAfter);
}
CTreeItemT AddHead(LPCTSTR lpstrItem, int nImageIndex)
{
return _Insert(lpstrItem, nImageIndex, TVI_FIRST);
}
CTreeItemT AddTail(LPCTSTR lpstrItem, int nImageIndex)
{
return _Insert(lpstrItem, nImageIndex, TVI_LAST);
}
CTreeItemT GetChild() const;
CTreeItemT GetNext(UINT nCode) const;
CTreeItemT GetNextSibling() const;
CTreeItemT GetPrevSibling() const;
CTreeItemT GetParent() const;
CTreeItemT GetFirstVisible() const;
CTreeItemT GetNextVisible() const;
CTreeItemT GetPrevVisible() const;
CTreeItemT GetSelected() const;
CTreeItemT GetDropHilight() const;
CTreeItemT GetRoot() const;
#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
CTreeItemT GetLastVisible() const;
#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
#if (_WIN32_IE >= 0x0600)
CTreeItemT GetNextSelected() const;
#endif // (_WIN32_IE >= 0x0600)
BOOL HasChildren() const;
BOOL Delete();
BOOL Expand(UINT nCode = TVE_EXPAND);
BOOL Select(UINT nCode);
BOOL Select();
BOOL SelectDropTarget();
BOOL SelectSetFirstVisible();
HWND EditLabel();
HIMAGELIST CreateDragImage();
BOOL SortChildren(BOOL bRecurse = FALSE);
BOOL EnsureVisible();
CTreeItemT _Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter);
int GetImageIndex() const;
#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
BOOL SetInsertMark(BOOL bAfter);
#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
#if (_WIN32_WINNT >= 0x0501)
UINT MapHTREEITEMToAccID() const;
#endif // (_WIN32_WINNT >= 0x0501)
#if (_WIN32_WINNT >= 0x0600)
void ShowInfoTip();
BOOL GetPartRect(TVITEMPART partID, LPRECT lpRect) const;
#endif // (_WIN32_WINNT >= 0x0600)
};
typedef CTreeItemT CTreeItem;
template
class CTreeViewCtrlExT : public CTreeViewCtrlT< TBase >
{
public:
// Constructors
CTreeViewCtrlExT(HWND hWnd = NULL) : CTreeViewCtrlT< TBase >(hWnd)
{ }
CTreeViewCtrlExT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
// Operations (overides that return CTreeItem)
CTreeItemT InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
return CTreeItemT(hTreeItem, this);
}
CTreeItemT InsertItem(LPCTSTR lpszItem, int nImage,
int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
{
ATLASSERT(::IsWindow(m_hWnd));
return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter);
}
CTreeItemT InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
{
ATLASSERT(::IsWindow(m_hWnd));
return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
}
CTreeItemT GetNextItem(HTREEITEM hItem, UINT nCode) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetChildItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetNextSiblingItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetPrevSiblingItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetParentItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetFirstVisibleItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetNextVisibleItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetPrevVisibleItem(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetSelectedItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetDropHilightItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT GetRootItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
CTreeItemT GetLastVisibleItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
#if (_WIN32_IE >= 0x0600)
CTreeItemT GetNextSelectedItem() const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
#endif // (_WIN32_IE >= 0x0600)
CTreeItemT HitTest(TVHITTESTINFO* pHitTestInfo) const
{
ATLASSERT(::IsWindow(m_hWnd));
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
CTreeItemT InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
HTREEITEM hParent, HTREEITEM hInsertAfter)
{
ATLASSERT(::IsWindow(m_hWnd));
TVINSERTSTRUCT tvis = { 0 };
tvis.hParent = hParent;
tvis.hInsertAfter = hInsertAfter;
tvis.item.mask = nMask;
tvis.item.pszText = (LPTSTR) lpszItem;
tvis.item.iImage = nImage;
tvis.item.iSelectedImage = nSelectedImage;
tvis.item.state = nState;
tvis.item.stateMask = nStateMask;
tvis.item.lParam = lParam;
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
return CTreeItemT(hTreeItem, this);
}
CTreeItemT HitTest(POINT pt, UINT* pFlags) const
{
ATLASSERT(::IsWindow(m_hWnd));
TVHITTESTINFO hti = { 0 };
hti.pt = pt;
HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
if (pFlags != NULL)
*pFlags = hti.flags;
return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this);
}
#if (_WIN32_WINNT >= 0x0501)
CTreeItemT