Compare commits

...

26 Commits

Author SHA1 Message Date
43b2bf6c16 VERSION 0.7.0: fix two bugs reported on GitHub, public binaries now in the wild!
Version 0.7.0 commemorates public beta binaries now being in the wild for Mac
and Linux platforms, though this actually happened a few days ago with 0.6.14.

This version fixes two bugs. First, the Linux installer/updater now supports
both systemd and regular SysV init. It will detect which your distro uses at
install/update time and install the zerotier-one service accordingly.

Secondly, this fixes an issue that caused the service to always show ONLINE
in the GUI or 'zerotier-cli info' even if there was no net connection. The
online status should be more reliably reported now.
2014-02-14 22:22:19 -08:00
aceb938e07 Another Linux installer fix: do not clobber existing directory permissions! 2014-02-14 21:45:42 -08:00
68f44fb932 Another little Linux installer fix. 2014-02-15 00:29:32 -05:00
e38619dd02 Small fix to Linux installer. 2014-02-14 21:14:34 -08:00
4ec7cd2760 Fix for GitHub issue #38: compute whether we are ONLINE a little differently 2014-02-14 16:23:03 -08:00
b0277ab904 Clean up old init.d installation files on systemd systems if present. 2014-02-14 15:28:45 -08:00
87b26b0aaf Systemd support on Linux - GitHub issue #39 2014-02-14 15:18:59 -08:00
01d13c153d Fix compiler warnings in Linux build. 2014-02-14 13:08:54 -08:00
c17082a4f8 VERSION 0.6.14: bug fixes, Unix device persistence
This version adds persistence of *nix device names (where possible), and fixes
a possible crash in Topology.cpp that was introduced in a previous revision.

It also adds a new supernode located in Singapore!
2014-02-11 15:16:42 -08:00
9acfd3eb73 Build fix on Linux with G++. 2014-02-11 23:09:53 +00:00
0ad84b8723 Possible bug fix in Topology, have to test... 2014-02-11 15:02:21 -08:00
3f912eb4ad Fix for GitHub issue #37: remember *nix device names. 2014-02-11 14:21:59 -08:00
f1b45f7df0 A few little fixes in NodeConfig. 2014-02-11 13:20:51 -08:00
29c18d4bde Add new Singapore supernode! 2014-02-11 08:57:25 -08:00
33728840ec More local.conf stuff. 2014-02-10 16:46:53 -08:00
cd339486b7 local.conf in NodeConfig 2014-02-10 14:22:57 -08:00
e54a34d8dd Finally found a Windows installer option that doesn't cost $500 or require me to climb a huge learning curve just to do a basic software install. 2014-02-08 22:22:18 -08:00
d24b192f8c Remove old updates from updates.d on Node startup. 2014-02-07 09:13:08 -08:00
0442d7e2d6 Forgot to save solution file. 2014-02-06 23:14:41 -08:00
5b97bb247e More Windows service work... it builds! Now to do a new installer and test. Also fix a Windows compile warning in Switch.cpp. 2014-02-06 23:12:12 -08:00
8a7486577a Windows service work, remove old installer... not sure exactly what we're going to use. 2014-02-06 22:06:27 -08:00
6d17993eb6 Fix a possible infinite loop in netconf service... in the long term need to fix IP assignment logic period cause the current incarnation sucks. 2014-02-06 10:59:50 -08:00
d0e5da2884 Fix copyright notice. 2014-02-05 16:38:54 -08:00
d5b50ee466 C++ service base stuff taken from MS public domain example project and modified slightly. 2014-02-05 16:37:50 -08:00
8031fe00c7 Delete C# service... going C++, probably integrating with core. 2014-02-05 14:27:31 -08:00
3f6152806f Add security notice the first time a user joins a public network. 2014-02-05 12:38:37 -08:00
47 changed files with 2058 additions and 6809 deletions

View File

@ -45,7 +45,8 @@ SOURCES += main.cpp \
../ext/lz4/lz4hc.c \
networkwidget.cpp \
installdialog.cpp \
licensedialog.cpp
licensedialog.cpp \
onetimedialog.cpp
HEADERS += mainwindow.h \
aboutwindow.h \
@ -98,14 +99,16 @@ HEADERS += mainwindow.h \
installdialog.h \
mac_doprivileged.h \
licensedialog.h \
main.h
main.h \
onetimedialog.h
FORMS += mainwindow.ui \
aboutwindow.ui \
networkwidget.ui \
installdialog.ui \
licensedialog.ui \
quickstartdialog.ui
quickstartdialog.ui \
onetimedialog.ui
RESOURCES += \
resources.qrc

View File

@ -2,6 +2,7 @@
#define MAIN_H
#include <QSettings>
#include <QMainWindow>
extern QSettings *settings;

View File

@ -66,7 +66,7 @@
ZeroTier::Node::LocalClient *zeroTierClient = (ZeroTier::Node::LocalClient *)0;
// Main window instance for app
static MainWindow *mainWindow = (MainWindow *)0;
QMainWindow *mainWindow = (MainWindow *)0;
// Handles message from ZeroTier One service
static void handleZTMessage(void *arg,unsigned long id,const char *line)

View File

@ -51,6 +51,9 @@ class MainWindow;
// Can be null if not connected, or will point to current
extern ZeroTier::Node::LocalClient *zeroTierClient;
// Globally visible pointer to main app window
extern QMainWindow *mainWindow;
class MainWindow : public QMainWindow
{
Q_OBJECT

View File

@ -28,6 +28,8 @@
#include "networkwidget.h"
#include "mainwindow.h"
#include "ui_networkwidget.h"
#include "onetimedialog.h"
#include "main.h"
#include <QClipboard>
#include <QString>
@ -43,7 +45,8 @@
NetworkWidget::NetworkWidget(QWidget *parent,const std::string &nwid) :
QWidget(parent),
ui(new Ui::NetworkWidget),
networkIdStr(nwid)
networkIdStr(nwid),
publicWarningShown(false)
{
ui->setupUi(this);
ui->networkIdButton->setText(QString(nwid.c_str()));
@ -98,9 +101,15 @@ void NetworkWidget::setNetworkType(const std::string &type)
ui->networkTypeLabel->setText(QString(type.c_str()));
if (type == "?")
ui->networkTypeLabel->setStatusTip("Waiting for configuration...");
else if (type == "public")
else if (type == "public") {
if ((!publicWarningShown)&&(!settings->value("shown_publicWarning",false).toBool())) {
publicWarningShown = true;
OneTimeDialog *d = new OneTimeDialog(mainWindow,"shown_publicWarning","Security Notice","Security Notice:"ZT_EOL_S""ZT_EOL_S"You have joined a public network. Anyone can join these. We recommend making sure that your system's automatic software updates are enabled and turning off any shared network services that you do not want people to access.");
d->setModal(false);
d->show();
}
ui->networkTypeLabel->setStatusTip("This network can be joined by anyone in the world.");
else if (type == "private")
} else if (type == "private")
ui->networkTypeLabel->setStatusTip("This network is private; only authorized peers can join.");
else ui->networkTypeLabel->setStatusTip("Unknown network type.");
}

View File

@ -62,6 +62,7 @@ private slots:
private:
Ui::NetworkWidget *ui;
std::string networkIdStr;
bool publicWarningShown;
};
#endif // NETWORK_H

View File

@ -0,0 +1,37 @@
#include "onetimedialog.h"
#include "ui_onetimedialog.h"
#include "main.h"
OneTimeDialog::OneTimeDialog(QWidget *parent,const char *propName,const QString &title,const QString &message) :
QDialog(parent),
ui(new Ui::OneTimeDialog)
{
ui->setupUi(this);
ui->label->setText(message);
this->setWindowTitle(title);
_propName = propName;
#ifdef __WINDOWS__
QWidgetList widgets = this->findChildren<QWidget*>();
foreach(QWidget *widget, widgets) {
QFont font(widget->font());
font.setPointSizeF(font.pointSizeF() * 0.75);
widget->setFont(font);
}
#endif
}
OneTimeDialog::~OneTimeDialog()
{
delete ui;
}
void OneTimeDialog::on_pushButton_clicked()
{
if (_propName) {
settings->setValue(_propName,ui->checkBox->isChecked());
settings->sync();
}
this->close();
}

View File

@ -0,0 +1,26 @@
#ifndef ONETIMEDIALOG_H
#define ONETIMEDIALOG_H
#include <QDialog>
namespace Ui {
class OneTimeDialog;
}
class OneTimeDialog : public QDialog
{
Q_OBJECT
public:
explicit OneTimeDialog(QWidget *parent = 0,const char *propName = (const char *)0,const QString &title = QString(),const QString &message = QString());
~OneTimeDialog();
private slots:
void on_pushButton_clicked();
private:
Ui::OneTimeDialog *ui;
const char *_propName;
};
#endif // ONETIMEDIALOG_H

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OneTimeDialog</class>
<widget class="QDialog" name="OneTimeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>496</width>
<height>197</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>12</number>
</property>
<property name="textInteractionFlags">
<set>Qt::NoTextInteraction</set>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Don't Show This Message Again</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -48,8 +48,9 @@ case "$system" in
mkdir -p 'build-installer/var/lib/zerotier-one'
cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one'
cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one'
mkdir -p 'build-installer/etc/init.d'
cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/etc/init.d'
mkdir -p 'build-installer/tmp'
cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one'
cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service'
targ="ZeroTierOneInstaller-linux-${machine}-${vmajor}_${vminor}_${revision}"
# Use gzip in Linux since some minimal Linux systems do not have bunzip2

View File

@ -12,6 +12,22 @@ if [ "$UID" -ne 0 ]; then
dryRun=1
fi
# Detect systemd vs. regular init
SYSTEMDUNITDIR=
if [ -e /bin/systemctl -o -e /usr/bin/systemctl -o -e /usr/local/bin/systemctl -o -e /sbin/systemctl -o -e /usr/sbin/systemctl ]; then
if [ -e /usr/bin/pkg-config ]; then
SYSTEMDUNITDIR=`/usr/bin/pkg-config systemd --variable=systemdsystemunitdir`
fi
if [ -z "$SYSTEMDUNITDIR" -o ! -d "$SYSTEMDUNITDIR" ]; then
if [ -d /usr/lib/systemd/system ]; then
SYSTEMDUNITDIR=/usr/lib/systemd/system
fi
if [ -d /etc/systemd/system ]; then
SYSTEMDUNITDIR=/etc/systemd/system
fi
fi
fi
if [ $dryRun -gt 0 ]; then
alias ln="echo '>> dry run: ln'"
alias rm="echo '>> dry run: rm'"
@ -21,6 +37,7 @@ if [ $dryRun -gt 0 ]; then
alias chkconfig="echo '>> dry run: chkconfig'"
alias zerotier-cli="echo '>> dry run: zerotier-cli'"
alias service="echo '>> dry run: service'"
alias systemctl="echo '>> dry run: systemctl'"
fi
scriptPath="`dirname "$0"`/`basename "$0"`"
@ -47,7 +64,7 @@ echo 'Extracting files...'
if [ $dryRun -gt 0 ]; then
echo ">> dry run: tail -c +$blobStart \"$scriptPath\" | gunzip -c | tar -xvop -C / -f -"
else
tail -c +$blobStart "$scriptPath" | gunzip -c | tar -xvop -C / -f -
tail -c +$blobStart "$scriptPath" | gunzip -c | tar -xvop --no-overwrite-dir -C / -f -
fi
if [ $dryRun -eq 0 -a ! -d "/var/lib/zerotier-one" ]; then
@ -62,11 +79,34 @@ ln -sf /var/lib/zerotier-one/zerotier-one /usr/bin/zerotier-cli
echo 'Installing and (re-)starting zerotier-one daemon...'
chkconfig zerotier-one on
service zerotier-one restart
# Note: ensure that service restarts are the last thing this script actually
# does, since these may kill the script itself. Also note the & to allow
# them to finish independently.
if [ -n "$SYSTEMDUNITDIR" -a -d "$SYSTEMDUNITDIR" ]; then
# If this was updated or upgraded from an init.d based system, clean up the old
# init.d stuff before installing directly via systemd.
if [ -f /etc/init.d/zerotier-one ]; then
if [ -e /sbin/chkconfig -o -e /usr/sbin/chkconfig -o -e /bin/chkconfig -o -e /usr/bin/chkconfig ]; then
chkconfig zerotier-one off
fi
rm -f /etc/init.d/zerotier-one
fi
cp -f /tmp/systemd_zerotier-one.service "$SYSTEMDUNITDIR/zerotier-one.service"
rm -f /tmp/systemd_zerotier-one.service /tmp/init.d_zerotier-one
systemctl enable zerotier-one
systemctl restart zerotier-one &
else
cp -f /tmp/init.d_zerotier-one /etc/init.d/zerotier-one
chmod 0755 /etc/init.d/zerotier-one
rm -f /tmp/systemd_zerotier-one.service /tmp/init.d_zerotier-one
chkconfig zerotier-one on
service zerotier-one restart &
fi
sleep 1
zerotier-cli info
exit 0

View File

@ -0,0 +1,11 @@
[Unit]
Description=ZeroTier One
After=network.target
[Service]
ExecStart=/var/lib/zerotier-one/zerotier-one
Restart=always
KillMode=process
[Install]
WantedBy=multi-user.target

View File

@ -7,6 +7,22 @@ if [ "$UID" -ne 0 ]; then
exit 1
fi
# Detect systemd vs. regular init
SYSTEMDUNITDIR=
if [ -e /bin/systemctl -o -e /usr/bin/systemctl -o -e /usr/local/bin/systemctl -o -e /sbin/systemctl -o -e /usr/sbin/systemctl ]; then
if [ -e /usr/bin/pkg-config ]; then
SYSTEMDUNITDIR=`/usr/bin/pkg-config systemd --variable=systemdsystemunitdir`
fi
if [ -z "$SYSTEMDUNITDIR" -o ! -d "$SYSTEMDUNITDIR" ]; then
if [ -d /usr/lib/systemd/system ]; then
SYSTEMDUNITDIR=/usr/lib/systemd/system
fi
if [ -d /etc/systemd/system ]; then
SYSTEMDUNITDIR=/etc/systemd/system
fi
fi
fi
echo
echo "This will uninstall ZeroTier One, hit CTRL+C to abort."
@ -14,20 +30,36 @@ echo "Waiting 5 seconds..."
sleep 5
echo "Killing any running zerotier-one service..."
if [ -n "$SYSTEMDUNITDIR" -a -d "$SYSTEMDUNITDIR" ]; then
systemctl stop zerotier-one
systemctl disable zerotier-one
else
service stop zerotier-one
fi
sleep 1
killall -q -TERM zerotier-one
sleep 2
sleep 1
killall -q -KILL zerotier-one
echo "Removing SysV init items..."
rm -fv /etc/init.d/zerotier-one
find /etc/rc*.d -name '???zerotier-one' -print0 | xargs -0 rm -fv
if [ -f /etc/init.d/zerotier-one ]; then
echo "Removing SysV init items..."
rm -f /etc/init.d/zerotier-one
find /etc/rc*.d -name '???zerotier-one' -print0 | xargs -0 rm -f
fi
if [ -n "$SYSTEMDUNITDIR" -a -d "$SYSTEMDUNITDIR" -a -f "$SYSTEMDUNITDIR/zerotier-one.service" ]; then
echo "Removing systemd service..."
rm -f "$SYSTEMDUNITDIR/zerotier-one.service"
fi
echo "Erasing binary and support files..."
cd /var/lib/zerotier-one
rm -rfv zerotier-one *.persist authtoken.secret identity.public *.log *.pid *.sh updates.d networks.d iddb.d
if [ -d /var/lib/zerotier-one ]; then
cd /var/lib/zerotier-one
rm -rf zerotier-one *.persist identity.public *.log *.pid *.sh updates.d networks.d iddb.d
fi
echo "Erasing anything installed into system bin directories..."
rm -fv /usr/local/bin/zerotier-* /usr/bin/zerotier-*
rm -f /usr/local/bin/zerotier-cli /usr/bin/zerotier-cli
echo "Done."
echo

View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT Type="Advanced Installer" CreateVersion="10.9" version="10.9" Modules="simple" RootPath="." Language="en" Id="{DC564647-6BF0-4550-87F4-89C938D0159C}">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
<ROW Property="ALLUSERS" Value="1"/>
<ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]." ValueLocId="*"/>
<ROW Property="ARPCONTACT" Value="contact@zerotier.com"/>
<ROW Property="ARPNOMODIFY" MultiBuildValue="DefaultBuild:1"/>
<ROW Property="ARPNOREPAIR" Value="1"/>
<ROW Property="ARPPRODUCTICON" Value="zt1icon.exe" Type="8"/>
<ROW Property="ARPURLINFOABOUT" Value="https://www.zerotier.com/"/>
<ROW Property="LIMITUI" MultiBuildValue="DefaultBuild:1"/>
<ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
<ROW Property="Manufacturer" Value="ZeroTier Networks LLC"/>
<ROW Property="ProductCode" Value="1033:{24DFCEE7-3AC9-4D39-BD53-974220C12043} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="ZeroTier One"/>
<ROW Property="ProductVersion" Value="0.7.0" Type="32"/>
<ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{B0E2A5F3-88B6-4E77-B922-CB4739B4C4C8}"/>
<ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
<ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
<ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows 2000, Windows 2000 Service Pack 1, Windows 2000 Service Pack 2, Windows 2000 Service Pack 3, Windows 2000 Service Pack 4, Windows XP x86, Windows XP x86 Service Pack 1, Windows XP x86 Service Pack 2, Windows XP x86 Service Pack 3" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40Display" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows XP x64, Windows XP x64 Service Pack 1, Windows XP x64 Service Pack 2" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows XP x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:Windows 2000, Windows XP x86" ValueLocId="-"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="ProductInformation" ComponentId="{DB078D04-EA8E-4A7C-9001-89BAD932F9D9}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="ProductInformation"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" Languages="en" InstallationType="4" UseLargeSchema="true"/>
<ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.CacheComponent">
<ATTRIBUTE name="Enable" value="false"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
<ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
<ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>
<ROW Fragment="MaintenanceTypeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceTypeDlg.aip"/>
<ROW Fragment="MaintenanceWelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceWelcomeDlg.aip"/>
<ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>
<ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>
<ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>
<ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>
<ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>
<ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>
<ROW Fragment="VerifyRepairDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRepairDlg.aip"/>
<ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
<ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">
<ROW Dialog_="WelcomeDlg" Control="WelcomeDlgDialogInitializer" Type="DialogInitializer" X="0" Y="0" Width="0" Height="0" Attributes="0" Order="-1" TextLocId="-" HelpLocId="-" ExtDataLocId="-"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="EndDialog" Argument="Return" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="99"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_MAINT" Ordering="198"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="202"/>
<ROW Dialog_="CustomizeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_MAINT" Ordering="101"/>
<ROW Dialog_="CustomizeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="1"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="ChangeButton" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="501"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceWelcomeDlg" Condition="AI_MAINT" Ordering="1"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="RemoveButton" Event="NewDialog" Argument="VerifyRemoveDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="601"/>
<ROW Dialog_="VerifyRemoveDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="1"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="RepairButton" Event="NewDialog" Argument="VerifyRepairDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="601"/>
<ROW Dialog_="VerifyRepairDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="1"/>
<ROW Dialog_="VerifyRepairDlg" Control_="Repair" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="399" Options="1"/>
<ROW Dialog_="VerifyRemoveDlg" Control_="Remove" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="299" Options="1"/>
<ROW Dialog_="PatchWelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_PATCH" Ordering="201"/>
<ROW Dialog_="ResumeDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_RESUME" Ordering="299"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="SpawnDialog" Argument="OutOfRbDiskDlg" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST=&quot;P&quot; OR NOT PROMPTROLLBACKCOST)" Ordering="2" Options="2"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="EnableRollback" Argument="False" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST=&quot;D&quot;" Ordering="3" Options="2"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="SpawnDialog" Argument="OutOfDiskDlg" Condition="AI_INSTALL AND ( (OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST=&quot;F&quot;) )" Ordering="4" Options="2"/>
<ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[AI_ButtonText_Next_Orig]" Argument="[ButtonText_Next]" Condition="AI_INSTALL" Ordering="0" Options="2"/>
<ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[ButtonText_Next]" Argument="[[AI_CommitButton]]" Condition="AI_INSTALL" Ordering="1" Options="2"/>
<ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[AI_Text_Next_Orig]" Argument="[Text_Next]" Condition="AI_INSTALL" Ordering="2" Options="2"/>
<ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[Text_Next]" Argument="[Text_Install]" Condition="AI_INSTALL" Ordering="3" Options="2"/>
<ROW Dialog_="WelcomeDlg" Control_="Back" Event="[ButtonText_Next]" Argument="[AI_ButtonText_Next_Orig]" Condition="AI_INSTALL" Ordering="0" Options="2"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>
<ROW Dialog_="WelcomeDlg" Control_="Back" Event="[Text_Next]" Argument="[AI_Text_Next_Orig]" Condition="AI_INSTALL" Ordering="1" Options="2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
<ROW Action="AI_DpiContentScale" Type="1" Source="aicustact.dll" Target="DpiContentScale"/>
<ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
<ROW Action="AI_ResolveLocalizedCredentials" Type="1" Source="aicustact.dll" Target="GetLocalizedCredentials"/>
<ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
<ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="zt1icon.exe" SourcePath="..\..\..\ZeroTierUI\zt1icon.ico" Index="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
<ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
<ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1501"/>
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1399"/>
<ROW Action="AI_ResolveKnownFolders" Sequence="52"/>
<ROW Action="AI_ResolveLocalizedCredentials" Sequence="51"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
<ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
<ROW Action="AI_ResolveLocalizedCredentials" Sequence="52"/>
<ROW Action="AI_DpiContentScale" Sequence="51"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
<ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &gt;= 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 2)) OR (MsiNTProductType &lt;&gt; 1))) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="( Version9X OR VersionNT64 OR ( VersionNT AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &gt;= 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 2))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 3))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 4))) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &gt;= 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 2))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 3))) OR VersionNT64) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNTDisplay]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT40Display]" DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]" DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
<ROW Registry="Version" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">
<ATTRIBUTE name="UsedTheme" value="classic"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="0.0.1" VersionMax="[|ProductVersion]" Attributes="257" ActionProperty="OLDPRODUCTS"/>
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>
</COMPONENT>
</DOCUMENT>

374
main.cpp
View File

@ -42,6 +42,9 @@
#include <tchar.h>
#include <wchar.h>
#include <lmcons.h>
#include "windows/ZeroTierOne/ServiceInstaller.h"
#include "windows/ZeroTierOne/ServiceBase.h"
#include "windows/ZeroTierOne/ZeroTierOneService.h"
#else
#include <unistd.h>
#include <pwd.h>
@ -93,6 +96,11 @@ static void printHelp(const char *cn,FILE *out)
fprintf(out," -c<port> - Bind to this port for local control packets"ZT_EOL_S);
fprintf(out," -q - Send a query to a running service (zerotier-cli)"ZT_EOL_S);
fprintf(out," -i - Run idtool command (zerotier-idtool)"ZT_EOL_S);
#ifdef __WINDOWS__
fprintf(out," -C - Run from command line instead of as service (Windows)"ZT_EOL_S);
fprintf(out," -I - Install Windows service (Windows)"ZT_EOL_S);
fprintf(out," -R - Uninstall Windows service (Windows)"ZT_EOL_S);
#endif
}
namespace ZeroTierCLI { // ---------------------------------------------------
@ -373,6 +381,7 @@ static void sighandlerQuit(int sig)
#endif
#ifdef __WINDOWS__
// Console signal handler routine to allow CTRL+C to work, mostly for testing
static BOOL WINAPI _handlerRoutine(DWORD dwCtrlType)
{
switch(dwCtrlType) {
@ -388,183 +397,94 @@ static BOOL WINAPI _handlerRoutine(DWORD dwCtrlType)
return FALSE;
}
// Returns true if this is running as the local administrator
static BOOL IsCurrentUserLocalAdministrator(void)
{
BOOL fReturn = FALSE;
DWORD dwStatus;
DWORD dwAccessMask;
DWORD dwAccessDesired;
DWORD dwACLSize;
DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
PACL pACL = NULL;
PSID psidAdmin = NULL;
BOOL fReturn = FALSE;
DWORD dwStatus;
DWORD dwAccessMask;
DWORD dwAccessDesired;
DWORD dwACLSize;
DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
PACL pACL = NULL;
PSID psidAdmin = NULL;
HANDLE hToken = NULL;
HANDLE hImpersonationToken = NULL;
HANDLE hToken = NULL;
HANDLE hImpersonationToken = NULL;
PRIVILEGE_SET ps;
GENERIC_MAPPING GenericMapping;
PRIVILEGE_SET ps;
GENERIC_MAPPING GenericMapping;
PSECURITY_DESCRIPTOR psdAdmin = NULL;
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
PSECURITY_DESCRIPTOR psdAdmin = NULL;
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
const DWORD ACCESS_READ = 1;
const DWORD ACCESS_WRITE = 2;
/*
Determine if the current thread is running as a user that is a member
__try
{
if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY,TRUE,&hToken))
{
if (GetLastError() != ERROR_NO_TOKEN)
__leave;
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
__leave;
}
if (!DuplicateToken (hToken, SecurityImpersonation,&hImpersonationToken))
__leave;
if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &psidAdmin))
__leave;
psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (psdAdmin == NULL)
__leave;
if (!InitializeSecurityDescriptor(psdAdmin,SECURITY_DESCRIPTOR_REVISION))
__leave;
dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD);
pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
if (pACL == NULL)
__leave;
if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
__leave;
dwAccessMask= ACCESS_READ | ACCESS_WRITE;
if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin))
__leave;
if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
__leave;
of
the local admins group. To do this, create a security descriptor
SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);
that
has a DACL which has an ACE that allows only local aministrators
if (!IsValidSecurityDescriptor(psdAdmin))
__leave;
dwAccessDesired = ACCESS_READ;
access.
Then, call AccessCheck with the current thread's token and the
GenericMapping.GenericRead = ACCESS_READ;
GenericMapping.GenericWrite = ACCESS_WRITE;
GenericMapping.GenericExecute = 0;
GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;
security
descriptor. It will say whether the user could access an object if
if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
&GenericMapping, &ps, &dwStructureSize, &dwStatus,
&fReturn))
{
fReturn = FALSE;
__leave;
}
}
__finally
{
// Clean up.
if (pACL) LocalFree(pACL);
if (psdAdmin) LocalFree(psdAdmin);
if (psidAdmin) FreeSid(psidAdmin);
if (hImpersonationToken) CloseHandle (hImpersonationToken);
if (hToken) CloseHandle (hToken);
}
it
had that security descriptor. Note: you do not need to actually
create
the object. Just checking access against the security descriptor
alone
will be sufficient.
*/
const DWORD ACCESS_READ = 1;
const DWORD ACCESS_WRITE = 2;
__try
{
/*
AccessCheck() requires an impersonation token. We first get a
primary
token and then create a duplicate impersonation token. The
impersonation token is not actually assigned to the thread, but is
used in the call to AccessCheck. Thus, this function itself never
impersonates, but does use the identity of the thread. If the
thread
was impersonating already, this function uses that impersonation
context.
*/
if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY,
TRUE, &hToken))
{
if (GetLastError() != ERROR_NO_TOKEN)
__leave;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
__leave;
}
if (!DuplicateToken (hToken, SecurityImpersonation,
&hImpersonationToken))
__leave;
/*
Create the binary representation of the well-known SID that
represents the local administrators group. Then create the
security
descriptor and DACL with an ACE that allows only local admins
access.
After that, perform the access check. This will determine whether
the current user is a local admin.
*/
if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &psidAdmin))
__leave;
psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (psdAdmin == NULL)
__leave;
if (!InitializeSecurityDescriptor(psdAdmin,
SECURITY_DESCRIPTOR_REVISION))
__leave;
// Compute size needed for the ACL.
dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psidAdmin) - sizeof(DWORD);
pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
if (pACL == NULL)
__leave;
if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
__leave;
dwAccessMask= ACCESS_READ | ACCESS_WRITE;
if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask,
psidAdmin))
__leave;
if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
__leave;
/*
AccessCheck validates a security descriptor somewhat; set the
group
and owner so that enough of the security descriptor is filled out
to
make AccessCheck happy.
*/
SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);
if (!IsValidSecurityDescriptor(psdAdmin))
__leave;
dwAccessDesired = ACCESS_READ;
/*
Initialize GenericMapping structure even though you
do not use generic rights.
*/
GenericMapping.GenericRead = ACCESS_READ;
GenericMapping.GenericWrite = ACCESS_WRITE;
GenericMapping.GenericExecute = 0;
GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;
if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
&GenericMapping, &ps, &dwStructureSize, &dwStatus,
&fReturn))
{
fReturn = FALSE;
__leave;
}
}
__finally
{
// Clean up.
if (pACL) LocalFree(pACL);
if (psdAdmin) LocalFree(psdAdmin);
if (psidAdmin) FreeSid(psidAdmin);
if (hImpersonationToken) CloseHandle (hImpersonationToken);
if (hToken) CloseHandle (hToken);
}
return fReturn;
return fReturn;
}
#endif // __WINDOWS__
@ -599,6 +519,9 @@ int main(int argc,char **argv)
const char *homeDir = (const char *)0;
unsigned int port = 0;
unsigned int controlPort = 0;
#ifdef __WINDOWS__
bool winRunFromCommandLine = false;
#endif
for(int i=1;i<argc;++i) {
if (argv[i][0] == '-') {
switch(argv[i][1]) {
@ -629,6 +552,35 @@ int main(int argc,char **argv)
printHelp(argv[0],stderr);
return 0;
} else return ZeroTierIdTool::main(argc,argv);
#ifdef __WINDOWS__
case 'C':
winRunFromCommandLine = true;
break;
case 'I': { // install self as service
if (IsCurrentUserLocalAdministrator() != TRUE) {
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
return 1;
}
std::string ret(InstallService(ZT_SERVICE_NAME,ZT_SERVICE_DISPLAY_NAME,ZT_SERVICE_START_TYPE,ZT_SERVICE_DEPENDENCIES,ZT_SERVICE_ACCOUNT,ZT_SERVICE_PASSWORD));
if (ret.length()) {
fprintf(stderr,"%s: unable to install service: %s"ZT_EOL_S,argv[0],ret.c_str());
return 3;
}
return 0;
} break;
case 'R': { // uninstall self as service
if (IsCurrentUserLocalAdministrator() != TRUE) {
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
return 1;
}
std::string ret(UninstallService(ZT_SERVICE_NAME));
if (ret.length()) {
fprintf(stderr,"%s: unable to uninstall service: %s"ZT_EOL_S,argv[0],ret.c_str());
return 3;
}
return 0;
} break;
#endif
case 'h':
case '?':
default:
@ -672,52 +624,54 @@ int main(int argc,char **argv)
#endif
#endif
int exitCode = 0;
try {
node = new Node(homeDir,port,controlPort);
switch(node->run()) {
case Node::NODE_RESTART_FOR_UPGRADE: {
const char *upgPath = node->reasonForTermination();
#ifdef __UNIX_LIKE__
// On Unix-type OSes we exec() right into the upgrade. This in turn will
// end with us being re-launched either via the upgrade itself or something
// like OSX's launchd.
if (upgPath) {
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
::execl(upgPath,upgPath,(char *)0);
}
exitCode = 2;
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
#else // not __UNIX_LIKE
#ifdef __WINDOWS__
// On Windows the service checks updates.d and invokes updates if they are
// found there. This only happens after exit code 4. The Windows service
// will listen to stdout as well to catch the filename.
if (upgPath) {
printf("[[[ UPDATE AVAILABLE: \"%s\" ]]]\r\n",upgPath);
exitCode = 4;
} else {
exitCode = 2;
}
#endif // __WINDOWS__
#endif // not __UNIX_LIKE__
} break;
case Node::NODE_UNRECOVERABLE_ERROR: {
exitCode = 3;
const char *termReason = node->reasonForTermination();
fprintf(stderr,"%s: abnormal termination: %s\n",argv[0],(termReason) ? termReason : "(unknown reason)");
} break;
default:
break;
if (!winRunFromCommandLine) {
ZeroTierOneService zt1Service;
if (CServiceBase::Run(zt1Service) == TRUE) {
// Normal termination of service process
return 0;
} else {
fprintf(stderr,"%s: unable to start service (try -h for help)"ZT_EOL_S,argv[0]);
return 1;
}
delete node;
node = (Node *)0;
} catch ( ... ) {}
#ifdef __UNIX_LIKE__
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
} else
#endif
return exitCode;
{
int exitCode = 0;
try {
node = new Node(homeDir,port,controlPort);
switch(node->run()) {
#ifndef __WINDOWS__
case Node::NODE_RESTART_FOR_UPGRADE: {
const char *upgPath = node->reasonForTermination();
// On Unix-type OSes we exec() right into the upgrade. This in turn will
// end with us being re-launched either via the upgrade itself or something
// like OSX's launchd.
if (upgPath) {
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
::execl(upgPath,upgPath,(char *)0);
}
exitCode = 3;
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
} break;
#endif
case Node::NODE_UNRECOVERABLE_ERROR: {
exitCode = 3;
const char *termReason = node->reasonForTermination();
fprintf(stderr,"%s: abnormal termination: %s\n",argv[0],(termReason) ? termReason : "(unknown reason)");
} break;
default:
break;
}
delete node;
node = (Node *)0;
} catch ( ... ) {
fprintf(stderr,"%s: unexpected exception!"ZT_EOL_S,argv[0]);
exitCode = 3;
}
#ifdef __UNIX_LIKE__
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
#endif
return exitCode;
}
}

View File

@ -277,7 +277,7 @@ int main(int argc,char **argv)
std::string desc;
{
Query q = dbCon->query();
q << "SELECT name,`desc`,isOpen,multicastPrefixBits,multicastDepth,emulateArp,emulateNdp,arpCacheTtl,ndpCacheTtl FROM Network WHERE id = " << nwid;
q << "SELECT * FROM Network WHERE id = " << nwid;
StoreQueryResult rs = q.store();
if (rs.num_rows() > 0) {
name = rs[0]["name"].c_str();
@ -411,36 +411,38 @@ int main(int argc,char **argv)
uint32_t ipNet = (uint32_t)((unsigned long)rs[aaRow]["ipNet"]);
unsigned int netmaskBits = (unsigned int)rs[aaRow]["netmaskBits"];
uint32_t tryIp = (((uint32_t)addressBytes[1]) << 24) |
(((uint32_t)addressBytes[2]) << 16) |
(((uint32_t)addressBytes[3]) << 8) |
((((uint32_t)addressBytes[4]) % 254) + 1);
tryIp &= (0xffffffff >> netmaskBits);
tryIp |= ipNet;
if ((netmaskBits > 0)&&(ipNet)) {
uint32_t tryIp = (((uint32_t)addressBytes[1]) << 24) |
(((uint32_t)addressBytes[2]) << 16) |
(((uint32_t)addressBytes[3]) << 8) |
((((uint32_t)addressBytes[4]) % 254) + 1);
tryIp &= (0xffffffff >> netmaskBits);
tryIp |= ipNet;
for(int k=0;k<100000;++k) {
Query q2 = dbCon->query();
q2 << "INSERT INTO IPv4Static (Network_id,Node_id,ip,netmaskBits) VALUES (" << nwid << "," << peerIdentity.address().toInt() << "," << tryIp << "," << netmaskBits << ")";
if (q2.exec()) {
sprintf(buf,"%u.%u.%u.%u",(unsigned int)((tryIp >> 24) & 0xff),(unsigned int)((tryIp >> 16) & 0xff),(unsigned int)((tryIp >> 8) & 0xff),(unsigned int)(tryIp & 0xff));
if (ipv4Static.length())
ipv4Static.push_back(',');
ipv4Static.append(buf);
ipv4Static.push_back('/');
sprintf(buf,"%u",netmaskBits);
ipv4Static.append(buf);
break;
} else { // insert will fail if IP is in use due to uniqueness constraints in DB
++tryIp;
if ((tryIp & 0xff) == 0)
tryIp |= 1;
tryIp &= (0xffffffff >> netmaskBits);
tryIp |= ipNet;
for(int k=0;k<100000;++k) {
Query q2 = dbCon->query();
q2 << "INSERT INTO IPv4Static (Network_id,Node_id,ip,netmaskBits) VALUES (" << nwid << "," << peerIdentity.address().toInt() << "," << tryIp << "," << netmaskBits << ")";
if (q2.exec()) {
sprintf(buf,"%u.%u.%u.%u",(unsigned int)((tryIp >> 24) & 0xff),(unsigned int)((tryIp >> 16) & 0xff),(unsigned int)((tryIp >> 8) & 0xff),(unsigned int)(tryIp & 0xff));
if (ipv4Static.length())
ipv4Static.push_back(',');
ipv4Static.append(buf);
ipv4Static.push_back('/');
sprintf(buf,"%u",netmaskBits);
ipv4Static.append(buf);
break;
} else { // insert will fail if IP is in use due to uniqueness constraints in DB
++tryIp;
if ((tryIp & 0xff) == 0)
tryIp |= 1;
tryIp &= (0xffffffff >> netmaskBits);
tryIp |= ipNet;
}
}
}
if (ipv4Static.length())
break;
if (ipv4Static.length())
break;
}
}
}
}

View File

@ -73,6 +73,13 @@ static inline std::map< Identity,std::vector<InetAddress> > _mkSupernodeMap()
addrs.push_back(InetAddress("198.211.127.172",ZT_DEFAULT_UDP_PORT));
sn[id] = addrs;
// mi-go.zerotier.com - Singapore
addrs.clear();
if (!id.fromString("abbb7f4622:0:89d2c6b2062b10f4ce314dfcb914c082566247090a6f74c8ba1c15c63b205f540758f0abae85287397152c9d8cf463cfe51e7a480946cd6a31495b24ca13253c"))
throw std::runtime_error("invalid identity in Defaults");
addrs.push_back(InetAddress("128.199.254.204",ZT_DEFAULT_UDP_PORT));
sn[id] = addrs;
return sn;
}

View File

@ -234,6 +234,7 @@ EthernetTap::EthernetTap(
_fd(0)
{
char procpath[128];
struct stat sbuf;
Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally
if (mtu > 4096)
@ -246,13 +247,19 @@ EthernetTap::EthernetTap(
struct ifreq ifr;
memset(&ifr,0,sizeof(ifr));
{ // pick an unused device name
// Try to recall our last device name, or pick an unused one if that fails.
bool recalledDevice = false;
if ((tag)&&(tag[0])) {
Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),tag);
Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
recalledDevice = (stat(procpath,&sbuf) != 0);
}
if (!recalledDevice) {
int devno = 0;
struct stat sbuf;
do {
Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"zt%d",devno++);
Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
} while (stat(procpath,&sbuf) == 0);
} while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist
}
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
@ -359,17 +366,33 @@ EthernetTap::EthernetTap(
if (stat("/dev/zt0",&stattmp))
throw std::runtime_error("/dev/zt# tap devices do not exist and unable to load kernel extension");
// Open the first available device (ones in use will fail with resource busy)
for(int i=0;i<256;++i) {
Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
if (stat(devpath,&stattmp))
throw std::runtime_error("no more TAP devices available");
_fd = ::open(devpath,O_RDWR);
if (_fd > 0) {
Utils::snprintf(_dev,sizeof(_dev),"zt%d",i);
break;
// Try to reopen the last device we had, if we had one and it's still unused.
bool recalledDevice = false;
if ((tag)&&(tag[0])) {
Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tag);
if (stat(devpath,&stattmp) == 0) {
_fd = ::open(devpath,O_RDWR);
if (_fd > 0) {
Utils::scopy(_dev,sizeof(_dev),tag);
recalledDevice = true;
}
}
}
// Open the first unused tap device if we didn't recall a previous one.
if (!recalledDevice) {
for(int i=0;i<256;++i) {
Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
if (stat(devpath,&stattmp))
throw std::runtime_error("no more TAP devices available");
_fd = ::open(devpath,O_RDWR);
if (_fd > 0) {
Utils::snprintf(_dev,sizeof(_dev),"zt%d",i);
break;
}
}
}
if (_fd <= 0)
throw std::runtime_error("unable to open TAP device or no more devices available");
@ -590,11 +613,9 @@ std::set<InetAddress> EthernetTap::ips() const
case AF_INET6: {
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr;
struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask;
r.insert(InetAddress(sin->sin6_addr.s6_addr,16,
Utils::countBits(((const uint32_t *)(nm->sin6_addr.s6_addr))[0]) +
Utils::countBits(((const uint32_t *)(nm->sin6_addr.s6_addr))[1]) +
Utils::countBits(((const uint32_t *)(nm->sin6_addr.s6_addr))[2]) +
Utils::countBits(((const uint32_t *)(nm->sin6_addr.s6_addr))[3])));
uint32_t b[4];
memcpy(b,nm->sin6_addr.s6_addr,sizeof(b));
r.insert(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
} break;
}
}

View File

@ -75,7 +75,7 @@ Network::~Network()
}
}
SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,uint64_t id)
SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,NodeConfig *nc,uint64_t id)
{
/* We construct Network via a static method to ensure that it is immediately
* wrapped in a SharedPtr<>. Otherwise if there is traffic on the Ethernet
@ -85,6 +85,7 @@ SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,uint64_t
SharedPtr<Network> nw(new Network());
nw->_id = id;
nw->_nc = nc;
nw->_mac = renv->identity.address().toMAC();
nw->_r = renv;
nw->_tap = (EthernetTap *)0;
@ -269,12 +270,31 @@ void Network::_pushMembershipCertificate(const Address &peer,bool force,uint64_t
void Network::threadMain()
throw()
{
// Setup thread -- this exits when tap is constructed. It's here
// because opening the tap can take some time on some platforms.
try {
// Setup thread -- this exits when tap is constructed. It's here
// because opening the tap can take some time on some platforms.
char tag[32];
#ifdef __WINDOWS__
// Windows tags interfaces by their network IDs, which are shoved into the
// registry to mark persistent instance of the tap device.
char tag[24];
Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)_id);
#else
// Unix tries to get the same device name next time, if possible.
std::string tagstr;
char lcentry[128];
Utils::snprintf(lcentry,sizeof(lcentry),"_dev_for_%.16llx",(unsigned long long)_id);
tagstr = _nc->getLocalConfig(lcentry);
const char *tag = (tagstr.length() > 0) ? tagstr.c_str() : (const char *)0;
#endif
_tap = new EthernetTap(_r,tag,_mac,ZT_IF_MTU,&_CBhandleTapData,this);
#ifndef __WINDOWS__
std::string dn(_tap->deviceName());
if ((!tag)||(dn != tag))
_nc->putLocalConfig(lcentry,dn);
#endif
} catch (std::exception &exc) {
LOG("network %.16llx failed to initialize: %s",_id,exc.what());
_netconfFailure = NETCONF_FAILURE_INIT_FAILED;

View File

@ -82,8 +82,7 @@ private:
// Only NodeConfig can create, only SharedPtr can delete
// Actual construction happens in newInstance()
Network() throw() : _tap((EthernetTap *)0) {}
Network() throw() {}
~Network();
/**
@ -96,11 +95,12 @@ private:
* cough).
*
* @param renv Runtime environment
* @param nc Parent NodeConfig
* @param id Network ID
* @return Reference counted pointer to new network
* @throws std::runtime_error Unable to create tap device or other fatal error
*/
static SharedPtr<Network> newInstance(const RuntimeEnvironment *renv,uint64_t id);
static SharedPtr<Network> newInstance(const RuntimeEnvironment *renv,NodeConfig *nc,uint64_t id);
/**
* Causes all persistent disk presence to be erased on delete
@ -406,6 +406,7 @@ private:
void _dumpMulticastCerts();
uint64_t _id;
NodeConfig *_nc;
MAC _mac;
const RuntimeEnvironment *_r;
EthernetTap *volatile _tap;

View File

@ -461,6 +461,7 @@ Node::ReasonForTermination Node::run()
#ifdef ZT_AUTO_UPDATE
if (ZT_DEFAULTS.updateLatestNfoURL.length()) {
_r->updater = new SoftwareUpdater(_r);
_r->updater->cleanOldUpdates(); // clean out updates.d on startup
} else {
LOG("WARNING: unable to enable software updates: latest .nfo URL from ZT_DEFAULTS is empty (does this platform actually support software updates?)");
}
@ -510,8 +511,7 @@ Node::ReasonForTermination Node::run()
* in the natural Mac way. */
std::string shutdownIfUnreadablePath(_r->homePath + ZT_PATH_SEPARATOR_S + "shutdownIfUnreadable");
// TODO: persist some of this stuff between restarts
uint64_t lastNetworkAutoconfCheck = Utils::now() - 5000; // check autoconf again after 5s for startup
uint64_t lastNetworkAutoconfCheck = Utils::now() - 5000ULL; // check autoconf again after 5s for startup
uint64_t lastPingCheck = 0;
uint64_t lastSupernodePing = 0;
uint64_t lastClean = Utils::now(); // don't need to do this immediately
@ -519,6 +519,7 @@ Node::ReasonForTermination Node::run()
uint64_t lastMulticastCheck = 0;
uint64_t networkConfigurationFingerprint = _r->sysEnv->getNetworkConfigurationFingerprint(_r->nc->networkTapDeviceNames());
_r->timeOfLastNetworkEnvironmentChange = Utils::now();
long lastDelayDelta = 0;
while (impl->reasonForTermination == NODE_RUNNING) {
@ -550,6 +551,7 @@ Node::ReasonForTermination Node::run()
if (fp != networkConfigurationFingerprint) {
LOG("netconf fingerprint change: %.16llx != %.16llx, resyncing with network",networkConfigurationFingerprint,fp);
networkConfigurationFingerprint = fp;
_r->timeOfLastNetworkEnvironmentChange = now;
resynchronize = true;
}
}

View File

@ -70,49 +70,62 @@ NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken,unsi
memcpy(_controlSocketKey,csk,32);
}
{
Mutex::Lock _llc(_localConfig_m);
_readLocalConfig();
}
std::string networksFolder(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d");
std::map<std::string,bool> networksDotD(Utils::listDirectory(networksFolder.c_str()));
std::set<uint64_t> nwids;
std::vector<uint64_t> configuredNets;
for(std::map<std::string,bool>::iterator d(networksDotD.begin());d!=networksDotD.end();++d) {
if (!d->second) {
std::string::size_type dot = d->first.rfind(".conf");
if (dot != std::string::npos) {
uint64_t nwid = Utils::hexStrToU64(d->first.substr(0,dot).c_str());
// TODO: remove legacy code once out of beta
if (nwid == 0x6c92786fee000001ULL) {
nwid = 0xbc8f9a8ee3000001ULL;
Utils::rm((networksFolder + ZT_PATH_SEPARATOR_S + d->first).c_str());
}
if (nwid == 0xbc8f9a8ee3000001ULL) {
nwid = 0x8D93FBE886000001ULL;
Utils::rm((networksFolder + ZT_PATH_SEPARATOR_S + d->first).c_str());
}
if (nwid == 0x8D93FBE886000001ULL) {
nwid = 0x8056c2e21c000001ULL;
Utils::rm((networksFolder + ZT_PATH_SEPARATOR_S + d->first).c_str());
}
if (nwid > 0)
nwids.insert(nwid);
if ((nwid > 0)&&(std::find(configuredNets.begin(),configuredNets.end(),nwid) == configuredNets.end()))
configuredNets.push_back(nwid);
}
}
}
for(std::set<uint64_t>::iterator nwid(nwids.begin());nwid!=nwids.end();++nwid) {
for(std::vector<uint64_t>::iterator n(configuredNets.begin());n!=configuredNets.end();++n) {
try {
SharedPtr<Network> nw(Network::newInstance(_r,*nwid));
_networks[*nwid] = nw;
_networks[*n] = Network::newInstance(_r,this,*n);
} catch (std::exception &exc) {
LOG("unable to create network %.16llx: %s",(unsigned long long)*nwid,exc.what());
LOG("unable to create network %.16llx: %s",(unsigned long long)*n,exc.what());
} catch ( ... ) {
LOG("unable to create network %.16llx: (unknown exception)",(unsigned long long)*nwid);
LOG("unable to create network %.16llx: (unknown exception)",(unsigned long long)*n);
}
}
}
NodeConfig::~NodeConfig()
{
_writeLocalConfig();
}
void NodeConfig::putLocalConfig(const std::string &key,const char *value)
{
Mutex::Lock _l(_localConfig_m);
_localConfig[key] = value;
_writeLocalConfig();
}
void NodeConfig::putLocalConfig(const std::string &key,const std::string &value)
{
Mutex::Lock _l(_localConfig_m);
_localConfig[key] = value;
_writeLocalConfig();
}
std::string NodeConfig::getLocalConfig(const std::string &key) const
{
Mutex::Lock _l(_localConfig_m);
Dictionary::const_iterator i(_localConfig.find(key));
if (i == _localConfig.end())
return std::string();
return i->second;
}
void NodeConfig::clean()
@ -122,6 +135,9 @@ void NodeConfig::clean()
n->second->clean();
}
/////////////////////////////////////////////////////////////////////////////
// UDP localhost control bus
// Macro used in execute() to push lines onto the return packet
#undef _P
#define _P(f,...) { r.push_back(std::string()); Utils::stdsprintf(r.back(),(f),##__VA_ARGS__); }
@ -179,15 +195,20 @@ std::vector<std::string> NodeConfig::execute(const char *command)
_P("200 help terminate [<reason>]");
_P("200 help updatecheck");
} else if (cmd[0] == "info") {
// We are online if at least one supernode has spoken to us since the last time our
// network environment changed and also less than ZT_PEER_LINK_ACTIVITY_TIMEOUT ago.
bool isOnline = false;
uint64_t now = Utils::now();
uint64_t since = _r->timeOfLastNetworkEnvironmentChange;
std::vector< SharedPtr<Peer> > snp(_r->topology->supernodePeers());
for(std::vector< SharedPtr<Peer> >::const_iterator sn(snp.begin());sn!=snp.end();++sn) {
if ((*sn)->hasActiveDirectPath(now)) {
uint64_t lastRec = (*sn)->lastDirectReceive();
if ((lastRec)&&(lastRec > since)&&((now - lastRec) < ZT_PEER_LINK_ACTIVITY_TIMEOUT)) {
isOnline = true;
break;
}
}
_P("200 info %s %s %s",_r->identity.address().toString().c_str(),(isOnline ? "ONLINE" : "OFFLINE"),Node::versionString());
} else if (cmd[0] == "listpeers") {
_P("200 listpeers <ztaddr> <ipv4> <ipv6> <latency> <version>");
@ -230,7 +251,7 @@ std::vector<std::string> NodeConfig::execute(const char *command)
_P("409 already a member of %.16llx",(unsigned long long)nwid);
} else {
try {
SharedPtr<Network> nw(Network::newInstance(_r,nwid));
SharedPtr<Network> nw(Network::newInstance(_r,this,nwid));
_networks[nwid] = nw;
_P("200 join %.16llx OK",(unsigned long long)nwid);
} catch (std::exception &exc) {
@ -389,4 +410,21 @@ void NodeConfig::_CBcontrolPacketHandler(UdpSocket *sock,void *arg,const InetAdd
}
}
/////////////////////////////////////////////////////////////////////////////
void NodeConfig::_readLocalConfig()
{
// assumes _localConfig_m is locked
std::string localDotConf(_r->homePath + ZT_PATH_SEPARATOR_S + "local.conf");
std::string buf;
if (Utils::readFile(localDotConf.c_str(),buf))
_localConfig.fromString(buf.c_str());
}
void NodeConfig::_writeLocalConfig()
{
// assumes _localConfig_m is locked
Utils::writeFile(((_r->homePath + ZT_PATH_SEPARATOR_S + "local.conf")).c_str(),_localConfig.toString());
}
} // namespace ZeroTier

View File

@ -41,6 +41,7 @@
#include "Utils.hpp"
#include "UdpSocket.hpp"
#include "Buffer.hpp"
#include "Dictionary.hpp"
namespace ZeroTier {
@ -67,6 +68,24 @@ public:
~NodeConfig();
/**
* Store something in local configuration cache
*
* By convention, keys starting with _ will not be shown in the command bus
* local config functions.
*
* @param key Configuration key
* @param value Configuration value
*/
void putLocalConfig(const std::string &key,const char *value);
void putLocalConfig(const std::string &key,const std::string &value);
/**
* @param key Configuration key
* @return Value or empty string if not found
*/
std::string getLocalConfig(const std::string &key) const;
/**
* @param nwid Network ID
* @return Network or NULL if no network for that ID
@ -121,7 +140,7 @@ public:
}
/**
* Execute a command
* Execute a control command (called when stuff comes in via control bus)
*
* @param command Command and arguments separated by whitespace (must already be trimmed of CR+LF, etc.)
* @return One or more command results (lines of output)
@ -159,12 +178,18 @@ public:
private:
static void _CBcontrolPacketHandler(UdpSocket *sock,void *arg,const InetAddress &remoteAddr,const void *data,unsigned int len);
void _readLocalConfig();
void _writeLocalConfig();
const RuntimeEnvironment *_r;
unsigned char _controlSocketKey[32];
UdpSocket _controlSocket;
std::map< uint64_t,SharedPtr<Network> > _networks;
Dictionary _localConfig; // persisted as local.conf
Mutex _localConfig_m;
std::map< uint64_t,SharedPtr<Network> > _networks; // persisted in networks.d/
Mutex _networks_m;
};

View File

@ -65,6 +65,7 @@ class RuntimeEnvironment
public:
RuntimeEnvironment() :
shutdownInProgress(false),
timeOfLastNetworkEnvironmentChange(0),
log((Logger *)0),
prng((CMWC4096 *)0),
mc((Multicaster *)0),
@ -93,6 +94,9 @@ public:
// Indicates that we are shutting down -- this is hacky, want to factor out
volatile bool shutdownInProgress;
// Time network environment (e.g. fingerprint) last changed -- used to determine online-ness
volatile uint64_t timeOfLastNetworkEnvironmentChange;
/*
* Order matters a bit here. These are constructed in this order
* and then deleted in the opposite order on Node exit. The order ensures

View File

@ -41,6 +41,7 @@
#include "RuntimeEnvironment.hpp"
#include "Thread.hpp"
#include "Node.hpp"
#include "Utils.hpp"
#ifdef __UNIX_LIKE__
#include <unistd.h>
@ -74,6 +75,16 @@ SoftwareUpdater::~SoftwareUpdater()
}
}
void SoftwareUpdater::cleanOldUpdates()
{
std::string updatesDir(_r->homePath + ZT_PATH_SEPARATOR_S + "updates.d");
std::map<std::string,bool> dl(Utils::listDirectory(updatesDir.c_str()));
for(std::map<std::string,bool>::iterator i(dl.begin());i!=dl.end();++i) {
if (!i->second)
Utils::rm(i->first.c_str());
}
}
const char *SoftwareUpdater::parseNfo(
const char *nfoText,
unsigned int &vMajor,

View File

@ -52,6 +52,11 @@ public:
SoftwareUpdater(const RuntimeEnvironment *renv);
~SoftwareUpdater();
/**
* Remove old updates in updates.d
*/
void cleanOldUpdates();
/**
* Called on each version message from a peer
*

View File

@ -218,7 +218,7 @@ bool Switch::sendHELLO(const SharedPtr<Peer> &dest,Demarc::Port localPort,const
outp.append(now);
_r->identity.serialize(outp,false);
outp.armor(dest->key(),false);
return _r->demarc->send(localPort,remoteAddr,outp.data(),outp.size(),-1);
return (_r->demarc->send(localPort,remoteAddr,outp.data(),outp.size(),-1) != Demarc::NULL_PORT);
}
bool Switch::unite(const Address &p1,const Address &p2,bool force)

View File

@ -134,33 +134,30 @@ void Topology::saveIdentity(const Identity &id)
SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const
{
SharedPtr<Peer> bestSupernode;
unsigned int bestSupernodeLatency = 65536;
unsigned int l,bestSupernodeLatency = 65536;
uint64_t now = Utils::now();
uint64_t lds,ldr;
Mutex::Lock _l(_supernodes_m);
// First look for a best supernode by comparing latencies, but exclude
// supernodes that have not responded to direct messages in order to
// try to exclude any that are dead or unreachable.
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();) {
for(std::vector< SharedPtr<Peer> >::const_iterator sn(_supernodePeers.begin());sn!=_supernodePeers.end();) {
// Skip explicitly avoided relays
for(unsigned int i=0;i<avoidCount;++i) {
if (avoid[i] == (*sn)->address()) {
++sn;
continue;
}
if (avoid[i] == (*sn)->address())
goto keep_searching_for_supernodes;
}
// Skip possibly comatose or unreachable relays
uint64_t lds = (*sn)->lastDirectSend();
uint64_t ldr = (*sn)->lastDirectReceive();
if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD)) {
++sn;
continue;
}
lds = (*sn)->lastDirectSend();
ldr = (*sn)->lastDirectReceive();
if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD))
goto keep_searching_for_supernodes;
if ((*sn)->hasActiveDirectPath(now)) {
unsigned int l = (*sn)->latency();
l = (*sn)->latency();
if (bestSupernode) {
if ((l)&&(l < bestSupernodeLatency)) {
bestSupernodeLatency = l;
@ -173,6 +170,7 @@ SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avo
}
}
keep_searching_for_supernodes:
++sn;
}

View File

@ -36,11 +36,11 @@
/**
* Minor version
*/
#define ZEROTIER_ONE_VERSION_MINOR 6
#define ZEROTIER_ONE_VERSION_MINOR 7
/**
* Revision
*/
#define ZEROTIER_ONE_VERSION_REVISION 13
#define ZEROTIER_ONE_VERSION_REVISION 0
#endif

View File

@ -12,59 +12,63 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TapDriver Package", "TapDri
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroTierOne", "ZeroTierOne\ZeroTierOne.vcxproj", "{B00A4957-5977-4AC1-9EF4-571DC27EADA2}"
EndProject
Project("{6141683F-8A12-4E36-9623-2EB02B2C2303}") = "ZeroTierOneInstaller", "ZeroTierOneInstaller\ZeroTierOneInstaller.isproj", "{C4424647-0581-47D1-918B-575BFF735CAA}"
ProjectSection(ProjectDependencies) = postProject
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3} = {63D28112-9A56-42FA-9C3E-EF6C58AF09B3}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroTierOneService", "ZeroTierOneService\ZeroTierOneService.csproj", "{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU
CD_ROM|Mixed Platforms = CD_ROM|Mixed Platforms
CD_ROM|Win32 = CD_ROM|Win32
CD_ROM|x64 = CD_ROM|x64
CD_ROM|x86 = CD_ROM|x86
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
DVD-5|Any CPU = DVD-5|Any CPU
DVD-5|Mixed Platforms = DVD-5|Mixed Platforms
DVD-5|Win32 = DVD-5|Win32
DVD-5|x64 = DVD-5|x64
DVD-5|x86 = DVD-5|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
Release|x64 = Release|x64
Release|x86 = Release|x86
SingleImage|Any CPU = SingleImage|Any CPU
SingleImage|Mixed Platforms = SingleImage|Mixed Platforms
SingleImage|Win32 = SingleImage|Win32
SingleImage|x64 = SingleImage|x64
SingleImage|x86 = SingleImage|x86
Vista Debug|Any CPU = Vista Debug|Any CPU
Vista Debug|Mixed Platforms = Vista Debug|Mixed Platforms
Vista Debug|Win32 = Vista Debug|Win32
Vista Debug|x64 = Vista Debug|x64
Vista Debug|x86 = Vista Debug|x86
Vista Release|Any CPU = Vista Release|Any CPU
Vista Release|Mixed Platforms = Vista Release|Mixed Platforms
Vista Release|Win32 = Vista Release|Win32
Vista Release|x64 = Vista Release|x64
Vista Release|x86 = Vista Release|x86
Win7 Debug|Any CPU = Win7 Debug|Any CPU
Win7 Debug|Mixed Platforms = Win7 Debug|Mixed Platforms
Win7 Debug|Win32 = Win7 Debug|Win32
Win7 Debug|x64 = Win7 Debug|x64
Win7 Debug|x86 = Win7 Debug|x86
Win7 Release|Any CPU = Win7 Release|Any CPU
Win7 Release|Mixed Platforms = Win7 Release|Mixed Platforms
Win7 Release|Win32 = Win7 Release|Win32
Win7 Release|x64 = Win7 Release|x64
Win7 Release|x86 = Win7 Release|x86
Win8 Debug|Any CPU = Win8 Debug|Any CPU
Win8 Debug|Mixed Platforms = Win8 Debug|Mixed Platforms
Win8 Debug|Win32 = Win8 Debug|Win32
Win8 Debug|x64 = Win8 Debug|x64
Win8 Debug|x86 = Win8 Debug|x86
Win8 Release|Any CPU = Win8 Release|Any CPU
Win8 Release|Mixed Platforms = Win8 Release|Mixed Platforms
Win8 Release|Win32 = Win8 Release|Win32
Win8 Release|x64 = Win8 Release|x64
Win8 Release|x86 = Win8 Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.CD_ROM|Any CPU.ActiveCfg = Release|Win32
@ -77,12 +81,18 @@ Global
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.CD_ROM|x64.ActiveCfg = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.CD_ROM|x64.Build.0 = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.CD_ROM|x64.Deploy.0 = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.CD_ROM|x86.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.CD_ROM|x86.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.CD_ROM|x86.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|Win32.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|Win32.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|x64.ActiveCfg = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|x64.Build.0 = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|x86.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|x86.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Debug|x86.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|Any CPU.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|Mixed Platforms.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|Mixed Platforms.Build.0 = Debug|Win32
@ -93,11 +103,17 @@ Global
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|x64.ActiveCfg = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|x64.Build.0 = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|x64.Deploy.0 = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|x86.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|x86.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.DVD-5|x86.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|Any CPU.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|Win32.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|Win32.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|x64.ActiveCfg = Release|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|x86.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|x86.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Release|x86.Deploy.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|Any CPU.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|Mixed Platforms.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|Mixed Platforms.Build.0 = Release|Win32
@ -108,42 +124,63 @@ Global
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|x64.ActiveCfg = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|x64.Build.0 = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|x64.Deploy.0 = Debug|x64
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|x86.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|x86.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.SingleImage|x86.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|Any CPU.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|Win32.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|Win32.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|Win32.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|x64.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|x86.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|x86.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Debug|x86.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|Any CPU.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|Mixed Platforms.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|Win32.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|Win32.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|Win32.Deploy.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|x64.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|x86.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|x86.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Vista Release|x86.Deploy.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|Any CPU.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|Win32.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|Win32.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|Win32.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|x64.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|x86.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|x86.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Debug|x86.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|Any CPU.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|Mixed Platforms.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|Win32.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|Win32.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|Win32.Deploy.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|x64.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|x86.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|x86.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win7 Release|x86.Deploy.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|Any CPU.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|Win32.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|Win32.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|Win32.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|x64.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|x86.ActiveCfg = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|x86.Build.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Debug|x86.Deploy.0 = Debug|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|Any CPU.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|Mixed Platforms.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|Win32.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|Win32.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|Win32.Deploy.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|x64.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|x86.ActiveCfg = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|x86.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|x86.Deploy.0 = Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Any CPU.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Mixed Platforms.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Mixed Platforms.Build.0 = Vista Release|Win32
@ -154,6 +191,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x64.ActiveCfg = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x64.Build.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x64.Deploy.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x86.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Any CPU.ActiveCfg = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Mixed Platforms.ActiveCfg = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Win32.ActiveCfg = Win7 Debug|Win32
@ -162,6 +200,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.ActiveCfg = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.Build.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.Deploy.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x86.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Any CPU.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Mixed Platforms.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Mixed Platforms.Build.0 = Vista Release|Win32
@ -172,6 +211,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x64.ActiveCfg = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x64.Build.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x64.Deploy.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x86.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Any CPU.ActiveCfg = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Mixed Platforms.ActiveCfg = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Win32.ActiveCfg = Win8 Release|Win32
@ -180,6 +220,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.ActiveCfg = Win7 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.Build.0 = Win7 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.Deploy.0 = Win7 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x86.ActiveCfg = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Any CPU.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Mixed Platforms.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Mixed Platforms.Build.0 = Vista Release|Win32
@ -190,6 +231,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x64.ActiveCfg = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x64.Build.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x64.Deploy.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x86.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Any CPU.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Mixed Platforms.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Win32.ActiveCfg = Vista Debug|Win32
@ -198,6 +240,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.ActiveCfg = Vista Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.Build.0 = Vista Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.Deploy.0 = Vista Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x86.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Any CPU.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Mixed Platforms.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Win32.ActiveCfg = Vista Release|Win32
@ -206,6 +249,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.ActiveCfg = Vista Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.Build.0 = Vista Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.Deploy.0 = Vista Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x86.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Any CPU.ActiveCfg = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Mixed Platforms.ActiveCfg = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32
@ -214,12 +258,14 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.Build.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x86.ActiveCfg = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Any CPU.ActiveCfg = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Mixed Platforms.ActiveCfg = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.Build.0 = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|x64.ActiveCfg = Win7 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|x86.ActiveCfg = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Any CPU.ActiveCfg = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Mixed Platforms.ActiveCfg = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
@ -228,6 +274,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x86.ActiveCfg = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Any CPU.ActiveCfg = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Mixed Platforms.ActiveCfg = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
@ -236,6 +283,7 @@ Global
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.Build.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.Deploy.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x86.ActiveCfg = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.CD_ROM|Any CPU.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.CD_ROM|Mixed Platforms.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.CD_ROM|Mixed Platforms.Build.0 = Vista Release|Win32
@ -246,6 +294,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.CD_ROM|x64.ActiveCfg = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.CD_ROM|x64.Build.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.CD_ROM|x64.Deploy.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.CD_ROM|x86.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|Any CPU.ActiveCfg = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|Mixed Platforms.ActiveCfg = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|Win32.ActiveCfg = Win7 Debug|Win32
@ -254,6 +303,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|x64.ActiveCfg = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|x64.Build.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|x64.Deploy.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|x86.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.DVD-5|Any CPU.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.DVD-5|Mixed Platforms.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.DVD-5|Mixed Platforms.Build.0 = Vista Release|Win32
@ -264,6 +314,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.DVD-5|x64.ActiveCfg = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.DVD-5|x64.Build.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.DVD-5|x64.Deploy.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.DVD-5|x86.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|Any CPU.ActiveCfg = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|Mixed Platforms.ActiveCfg = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|Win32.ActiveCfg = Win8 Release|Win32
@ -272,6 +323,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|x64.ActiveCfg = Win7 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|x64.Build.0 = Win7 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|x64.Deploy.0 = Win7 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|x86.ActiveCfg = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.SingleImage|Any CPU.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.SingleImage|Mixed Platforms.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.SingleImage|Mixed Platforms.Build.0 = Vista Release|Win32
@ -282,6 +334,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.SingleImage|x64.ActiveCfg = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.SingleImage|x64.Build.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.SingleImage|x64.Deploy.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.SingleImage|x86.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|Any CPU.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|Mixed Platforms.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|Win32.ActiveCfg = Vista Debug|Win32
@ -290,6 +343,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|x64.ActiveCfg = Vista Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|x64.Build.0 = Vista Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|x64.Deploy.0 = Vista Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|x86.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|Any CPU.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|Mixed Platforms.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|Win32.ActiveCfg = Vista Release|Win32
@ -298,6 +352,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|x64.ActiveCfg = Vista Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|x64.Build.0 = Vista Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|x64.Deploy.0 = Vista Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|x86.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|Any CPU.ActiveCfg = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|Mixed Platforms.ActiveCfg = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32
@ -306,12 +361,14 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|x64.Build.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|x86.ActiveCfg = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Any CPU.ActiveCfg = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Mixed Platforms.ActiveCfg = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Win32.Build.0 = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|x64.ActiveCfg = Win7 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|x86.ActiveCfg = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|Any CPU.ActiveCfg = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|Mixed Platforms.ActiveCfg = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
@ -320,6 +377,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|x86.ActiveCfg = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|Any CPU.ActiveCfg = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|Mixed Platforms.ActiveCfg = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
@ -328,6 +386,7 @@ Global
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.Build.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.Deploy.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x86.ActiveCfg = Win8 Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|Any CPU.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|Mixed Platforms.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|Mixed Platforms.Build.0 = Release|Win32
@ -338,6 +397,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|x64.ActiveCfg = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|x64.Build.0 = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|x64.Deploy.0 = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|x86.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|x86.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|x86.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|Any CPU.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|Mixed Platforms.Build.0 = Debug|Win32
@ -347,6 +409,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|Win32.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|x64.ActiveCfg = Debug|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|x64.Build.0 = Debug|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|x86.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|x86.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|x86.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|Any CPU.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|Mixed Platforms.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|Mixed Platforms.Build.0 = Debug|Win32
@ -357,6 +422,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|x64.ActiveCfg = Debug|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|x64.Build.0 = Debug|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|x64.Deploy.0 = Debug|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|x86.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|x86.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.DVD-5|x86.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Any CPU.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Mixed Platforms.Build.0 = Release|Win32
@ -365,6 +433,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Deploy.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|x64.ActiveCfg = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|x86.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|x86.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|x86.Deploy.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|Any CPU.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|Mixed Platforms.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|Mixed Platforms.Build.0 = Release|Win32
@ -375,6 +446,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|x64.ActiveCfg = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|x64.Build.0 = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|x64.Deploy.0 = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|x86.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|x86.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|x86.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Any CPU.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Mixed Platforms.Build.0 = Debug|Win32
@ -383,6 +457,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Win32.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Win32.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|x64.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|x86.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|x86.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|x86.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Any CPU.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Mixed Platforms.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Mixed Platforms.Build.0 = Release|Win32
@ -391,6 +468,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Win32.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Win32.Deploy.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|x64.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|x86.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|x86.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|x86.Deploy.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Any CPU.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Mixed Platforms.Build.0 = Debug|Win32
@ -399,6 +479,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Win32.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Win32.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|x64.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|x86.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|x86.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|x86.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Any CPU.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Mixed Platforms.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Mixed Platforms.Build.0 = Release|Win32
@ -407,6 +490,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Win32.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Win32.Deploy.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|x64.ActiveCfg = Release|x64
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|x86.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|x86.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|x86.Deploy.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Any CPU.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Mixed Platforms.Build.0 = Debug|Win32
@ -415,6 +501,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Win32.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Win32.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|x64.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|x86.ActiveCfg = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|x86.Build.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|x86.Deploy.0 = Debug|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Any CPU.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Mixed Platforms.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Mixed Platforms.Build.0 = Release|Win32
@ -423,160 +512,9 @@ Global
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Win32.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Win32.Deploy.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|x64.ActiveCfg = Release|Win32
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|Any CPU.ActiveCfg = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|Any CPU.Build.0 = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|Mixed Platforms.ActiveCfg = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|Mixed Platforms.Build.0 = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|Win32.ActiveCfg = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|Win32.Build.0 = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|x64.ActiveCfg = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.CD_ROM|x64.Build.0 = CD_ROM
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|Any CPU.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|Any CPU.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|Mixed Platforms.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|Mixed Platforms.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|Win32.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|Win32.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|x64.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Debug|x64.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|Any CPU.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|Any CPU.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|Mixed Platforms.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|Mixed Platforms.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|Win32.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|Win32.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|x64.ActiveCfg = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.DVD-5|x64.Build.0 = DVD-5
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Release|x64.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.SingleImage|x64.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Debug|x64.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Vista Release|x64.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Debug|x64.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win7 Release|x64.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Debug|x64.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|Any CPU.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|Any CPU.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|Mixed Platforms.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|Mixed Platforms.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|Win32.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|Win32.Build.0 = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|x64.ActiveCfg = SingleImage
{C4424647-0581-47D1-918B-575BFF735CAA}.Win8 Release|x64.Build.0 = SingleImage
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.CD_ROM|Mixed Platforms.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.CD_ROM|Mixed Platforms.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.CD_ROM|Win32.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.CD_ROM|x64.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Debug|Win32.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Debug|x64.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.DVD-5|Any CPU.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.DVD-5|Mixed Platforms.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.DVD-5|Mixed Platforms.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.DVD-5|Win32.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.DVD-5|x64.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Release|Any CPU.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Release|Win32.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Release|x64.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.SingleImage|Any CPU.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.SingleImage|Mixed Platforms.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.SingleImage|Mixed Platforms.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.SingleImage|Win32.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.SingleImage|x64.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Debug|Any CPU.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Debug|Win32.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Debug|x64.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Release|Any CPU.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Release|Any CPU.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Release|Mixed Platforms.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Release|Win32.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Vista Release|x64.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Debug|Any CPU.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Debug|Win32.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Debug|x64.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Release|Any CPU.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Release|Any CPU.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Release|Mixed Platforms.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Release|Win32.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win7 Release|x64.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Debug|Any CPU.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Debug|Win32.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Debug|x64.ActiveCfg = Debug|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Release|Any CPU.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Release|Any CPU.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Release|Mixed Platforms.Build.0 = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Release|Win32.ActiveCfg = Release|Any CPU
{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}.Win8 Release|x64.ActiveCfg = Release|Any CPU
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|x86.ActiveCfg = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|x86.Build.0 = Release|Win32
{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,563 @@
/****************************** Module Header ******************************\
* Module Name: ServiceBase.cpp
* Project: CppWindowsService
* Copyright (c) Microsoft Corporation.
*
* Provides a base class for a service that will exist as part of a service
* application. CServiceBase must be derived from when creating a new service
* class.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma region Includes
#include "ServiceBase.h"
#include <assert.h>
#include <strsafe.h>
#include <string>
#pragma endregion
#pragma region Static Members
// Initialize the singleton service instance.
CServiceBase *CServiceBase::s_service = NULL;
//
// FUNCTION: CServiceBase::Run(CServiceBase &)
//
// PURPOSE: Register the executable for a service with the Service Control
// Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start
// command, which results in a call to the OnStart method in the service.
// This method blocks until the service has stopped.
//
// PARAMETERS:
// * service - the reference to a CServiceBase object. It will become the
// singleton service instance of this service application.
//
// RETURN VALUE: If the function succeeds, the return value is TRUE. If the
// function fails, the return value is FALSE. To get extended error
// information, call GetLastError.
//
BOOL CServiceBase::Run(CServiceBase &service)
{
s_service = &service;
SERVICE_TABLE_ENTRYA serviceTable[] =
{
{ service.m_name, ServiceMain },
{ NULL, NULL }
};
// Connects the main thread of a service process to the service control
// manager, which causes the thread to be the service control dispatcher
// thread for the calling process. This call returns when the service has
// stopped. The process should simply terminate when the call returns.
return StartServiceCtrlDispatcher(serviceTable);
}
//
// FUNCTION: CServiceBase::ServiceMain(DWORD, PWSTR *)
//
// PURPOSE: Entry point for the service. It registers the handler function
// for the service and starts the service.
//
// PARAMETERS:
// * dwArgc - number of command line arguments
// * lpszArgv - array of command line arguments
//
void WINAPI CServiceBase::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
{
assert(s_service != NULL);
// Register the handler function for the service
s_service->m_statusHandle = RegisterServiceCtrlHandler(
s_service->m_name, ServiceCtrlHandler);
if (s_service->m_statusHandle == NULL)
{
throw GetLastError();
}
// Start the service.
s_service->Start(dwArgc, pszArgv);
}
//
// FUNCTION: CServiceBase::ServiceCtrlHandler(DWORD)
//
// PURPOSE: The function is called by the SCM whenever a control code is
// sent to the service.
//
// PARAMETERS:
// * dwCtrlCode - the control code. This parameter can be one of the
// following values:
//
// SERVICE_CONTROL_CONTINUE
// SERVICE_CONTROL_INTERROGATE
// SERVICE_CONTROL_NETBINDADD
// SERVICE_CONTROL_NETBINDDISABLE
// SERVICE_CONTROL_NETBINDREMOVE
// SERVICE_CONTROL_PARAMCHANGE
// SERVICE_CONTROL_PAUSE
// SERVICE_CONTROL_SHUTDOWN
// SERVICE_CONTROL_STOP
//
// This parameter can also be a user-defined control code ranges from 128
// to 255.
//
void WINAPI CServiceBase::ServiceCtrlHandler(DWORD dwCtrl)
{
switch (dwCtrl)
{
case SERVICE_CONTROL_STOP: s_service->Stop(); break;
case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: break;
}
}
#pragma endregion
#pragma region Service Constructor and Destructor
//
// FUNCTION: CServiceBase::CServiceBase(PWSTR, BOOL, BOOL, BOOL)
//
// PURPOSE: The constructor of CServiceBase. It initializes a new instance
// of the CServiceBase class. The optional parameters (fCanStop,
/// fCanShutdown and fCanPauseContinue) allow you to specify whether the
// service can be stopped, paused and continued, or be notified when system
// shutdown occurs.
//
// PARAMETERS:
// * pszServiceName - the name of the service
// * fCanStop - the service can be stopped
// * fCanShutdown - the service is notified when system shutdown occurs
// * fCanPauseContinue - the service can be paused and continued
//
CServiceBase::CServiceBase(PSTR pszServiceName,
BOOL fCanStop,
BOOL fCanShutdown,
BOOL fCanPauseContinue)
{
// Service name must be a valid string and cannot be NULL.
m_name = (pszServiceName == NULL) ? "" : pszServiceName;
m_statusHandle = NULL;
// The service runs in its own process.
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
// The service is starting.
m_status.dwCurrentState = SERVICE_START_PENDING;
// The accepted commands of the service.
DWORD dwControlsAccepted = 0;
if (fCanStop)
dwControlsAccepted |= SERVICE_ACCEPT_STOP;
if (fCanShutdown)
dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
if (fCanPauseContinue)
dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
m_status.dwControlsAccepted = dwControlsAccepted;
m_status.dwWin32ExitCode = NO_ERROR;
m_status.dwServiceSpecificExitCode = 0;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;
}
//
// FUNCTION: CServiceBase::~CServiceBase()
//
// PURPOSE: The virtual destructor of CServiceBase.
//
CServiceBase::~CServiceBase(void)
{
}
#pragma endregion
#pragma region Service Start, Stop, Pause, Continue, and Shutdown
//
// FUNCTION: CServiceBase::Start(DWORD, PWSTR *)
//
// PURPOSE: The function starts the service. It calls the OnStart virtual
// function in which you can specify the actions to take when the service
// starts. If an error occurs during the startup, the error will be logged
// in the Application event log, and the service will be stopped.
//
// PARAMETERS:
// * dwArgc - number of command line arguments
// * lpszArgv - array of command line arguments
//
void CServiceBase::Start(DWORD dwArgc, PSTR *pszArgv)
{
try
{
// Tell SCM that the service is starting.
SetServiceStatus(SERVICE_START_PENDING);
// Perform service-specific initialization.
OnStart(dwArgc, pszArgv);
// Tell SCM that the service is started.
SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
// Log the error.
WriteErrorLogEntry("Service Start", dwError);
// Set the service status to be stopped.
SetServiceStatus(SERVICE_STOPPED, dwError);
}
catch (...)
{
// Log the error.
WriteEventLogEntry("Service failed to start.", EVENTLOG_ERROR_TYPE);
// Set the service status to be stopped.
SetServiceStatus(SERVICE_STOPPED);
}
}
//
// FUNCTION: CServiceBase::OnStart(DWORD, PWSTR *)
//
// PURPOSE: When implemented in a derived class, executes when a Start
// command is sent to the service by the SCM or when the operating system
// starts (for a service that starts automatically). Specifies actions to
// take when the service starts. Be sure to periodically call
// CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the
// procedure is going to take long time. You may also consider spawning a
// new thread in OnStart to perform time-consuming initialization tasks.
//
// PARAMETERS:
// * dwArgc - number of command line arguments
// * lpszArgv - array of command line arguments
//
void CServiceBase::OnStart(DWORD dwArgc, PSTR *pszArgv)
{
}
//
// FUNCTION: CServiceBase::Stop()
//
// PURPOSE: The function stops the service. It calls the OnStop virtual
// function in which you can specify the actions to take when the service
// stops. If an error occurs, the error will be logged in the Application
// event log, and the service will be restored to the original state.
//
void CServiceBase::Stop()
{
DWORD dwOriginalState = m_status.dwCurrentState;
try
{
// Tell SCM that the service is stopping.
SetServiceStatus(SERVICE_STOP_PENDING);
// Perform service-specific stop operations.
OnStop();
// Tell SCM that the service is stopped.
SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
// Log the error.
WriteErrorLogEntry("Service Stop", dwError);
// Set the orginal service status.
SetServiceStatus(dwOriginalState);
}
catch (...)
{
// Log the error.
WriteEventLogEntry("Service failed to stop.", EVENTLOG_ERROR_TYPE);
// Set the orginal service status.
SetServiceStatus(dwOriginalState);
}
}
//
// FUNCTION: CServiceBase::OnStop()
//
// PURPOSE: When implemented in a derived class, executes when a Stop
// command is sent to the service by the SCM. Specifies actions to take
// when a service stops running. Be sure to periodically call
// CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the
// procedure is going to take long time.
//
void CServiceBase::OnStop()
{
}
//
// FUNCTION: CServiceBase::Pause()
//
// PURPOSE: The function pauses the service if the service supports pause
// and continue. It calls the OnPause virtual function in which you can
// specify the actions to take when the service pauses. If an error occurs,
// the error will be logged in the Application event log, and the service
// will become running.
//
void CServiceBase::Pause()
{
try
{
// Tell SCM that the service is pausing.
SetServiceStatus(SERVICE_PAUSE_PENDING);
// Perform service-specific pause operations.
OnPause();
// Tell SCM that the service is paused.
SetServiceStatus(SERVICE_PAUSED);
}
catch (DWORD dwError)
{
// Log the error.
WriteErrorLogEntry("Service Pause", dwError);
// Tell SCM that the service is still running.
SetServiceStatus(SERVICE_RUNNING);
}
catch (...)
{
// Log the error.
WriteEventLogEntry("Service failed to pause.", EVENTLOG_ERROR_TYPE);
// Tell SCM that the service is still running.
SetServiceStatus(SERVICE_RUNNING);
}
}
//
// FUNCTION: CServiceBase::OnPause()
//
// PURPOSE: When implemented in a derived class, executes when a Pause
// command is sent to the service by the SCM. Specifies actions to take
// when a service pauses.
//
void CServiceBase::OnPause()
{
}
//
// FUNCTION: CServiceBase::Continue()
//
// PURPOSE: The function resumes normal functioning after being paused if
// the service supports pause and continue. It calls the OnContinue virtual
// function in which you can specify the actions to take when the service
// continues. If an error occurs, the error will be logged in the
// Application event log, and the service will still be paused.
//
void CServiceBase::Continue()
{
try
{
// Tell SCM that the service is resuming.
SetServiceStatus(SERVICE_CONTINUE_PENDING);
// Perform service-specific continue operations.
OnContinue();
// Tell SCM that the service is running.
SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
// Log the error.
WriteErrorLogEntry("Service Continue", dwError);
// Tell SCM that the service is still paused.
SetServiceStatus(SERVICE_PAUSED);
}
catch (...)
{
// Log the error.
WriteEventLogEntry("Service failed to resume.", EVENTLOG_ERROR_TYPE);
// Tell SCM that the service is still paused.
SetServiceStatus(SERVICE_PAUSED);
}
}
//
// FUNCTION: CServiceBase::OnContinue()
//
// PURPOSE: When implemented in a derived class, OnContinue runs when a
// Continue command is sent to the service by the SCM. Specifies actions to
// take when a service resumes normal functioning after being paused.
//
void CServiceBase::OnContinue()
{
}
//
// FUNCTION: CServiceBase::Shutdown()
//
// PURPOSE: The function executes when the system is shutting down. It
// calls the OnShutdown virtual function in which you can specify what
// should occur immediately prior to the system shutting down. If an error
// occurs, the error will be logged in the Application event log.
//
void CServiceBase::Shutdown()
{
try
{
// Perform service-specific shutdown operations.
OnShutdown();
// Tell SCM that the service is stopped.
SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
// Log the error.
WriteErrorLogEntry("Service Shutdown", dwError);
}
catch (...)
{
// Log the error.
WriteEventLogEntry("Service failed to shut down.", EVENTLOG_ERROR_TYPE);
}
}
//
// FUNCTION: CServiceBase::OnShutdown()
//
// PURPOSE: When implemented in a derived class, executes when the system
// is shutting down. Specifies what should occur immediately prior to the
// system shutting down.
//
void CServiceBase::OnShutdown()
{
}
#pragma endregion
#pragma region Helper Functions
//
// FUNCTION: CServiceBase::SetServiceStatus(DWORD, DWORD, DWORD)
//
// PURPOSE: The function sets the service status and reports the status to
// the SCM.
//
// PARAMETERS:
// * dwCurrentState - the state of the service
// * dwWin32ExitCode - error code to report
// * dwWaitHint - estimated time for pending operation, in milliseconds
//
void CServiceBase::SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
// Fill in the SERVICE_STATUS structure of the service.
m_status.dwCurrentState = dwCurrentState;
m_status.dwWin32ExitCode = dwWin32ExitCode;
m_status.dwWaitHint = dwWaitHint;
m_status.dwCheckPoint =
((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED)) ?
0 : dwCheckPoint++;
// Report the status of the service to the SCM.
::SetServiceStatus(m_statusHandle, &m_status);
}
//
// FUNCTION: CServiceBase::WriteEventLogEntry(PWSTR, WORD)
//
// PURPOSE: Log a message to the Application event log.
//
// PARAMETERS:
// * pszMessage - string message to be logged.
// * wType - the type of event to be logged. The parameter can be one of
// the following values.
//
// EVENTLOG_SUCCESS
// EVENTLOG_AUDIT_FAILURE
// EVENTLOG_AUDIT_SUCCESS
// EVENTLOG_ERROR_TYPE
// EVENTLOG_INFORMATION_TYPE
// EVENTLOG_WARNING_TYPE
//
void CServiceBase::WriteEventLogEntry(PSTR pszMessage, WORD wType)
{
HANDLE hEventSource = NULL;
LPCSTR lpszStrings[2] = { NULL, NULL };
hEventSource = RegisterEventSource(NULL, m_name);
if (hEventSource)
{
lpszStrings[0] = m_name;
lpszStrings[1] = pszMessage;
ReportEvent(hEventSource, // Event log handle
wType, // Event type
0, // Event category
0, // Event identifier
NULL, // No security identifier
2, // Size of lpszStrings array
0, // No binary data
lpszStrings, // Array of strings
NULL // No binary data
);
DeregisterEventSource(hEventSource);
}
}
//
// FUNCTION: CServiceBase::WriteErrorLogEntry(PWSTR, DWORD)
//
// PURPOSE: Log an error message to the Application event log.
//
// PARAMETERS:
// * pszFunction - the function that gives the error
// * dwError - the error code
//
void CServiceBase::WriteErrorLogEntry(PSTR pszFunction, DWORD dwError)
{
char szMessage[260];
StringCchPrintf(szMessage, ARRAYSIZE(szMessage),
"%s failed w/err 0x%08lx", pszFunction, dwError);
WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE);
}
#pragma endregion

View File

@ -0,0 +1,122 @@
/****************************** Module Header ******************************\
* Module Name: ServiceBase.h
* Project: CppWindowsService
* Copyright (c) Microsoft Corporation.
*
* Provides a base class for a service that will exist as part of a service
* application. CServiceBase must be derived from when creating a new service
* class.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma once
#include <WinSock2.h>
#include <windows.h>
class CServiceBase
{
public:
// Register the executable for a service with the Service Control Manager
// (SCM). After you call Run(ServiceBase), the SCM issues a Start command,
// which results in a call to the OnStart method in the service. This
// method blocks until the service has stopped.
static BOOL Run(CServiceBase &service);
// Service object constructor. The optional parameters (fCanStop,
// fCanShutdown and fCanPauseContinue) allow you to specify whether the
// service can be stopped, paused and continued, or be notified when
// system shutdown occurs.
CServiceBase(LPSTR pszServiceName,
BOOL fCanStop = TRUE,
BOOL fCanShutdown = TRUE,
BOOL fCanPauseContinue = FALSE);
// Service object destructor.
virtual ~CServiceBase(void);
// Stop the service.
void Stop();
protected:
// When implemented in a derived class, executes when a Start command is
// sent to the service by the SCM or when the operating system starts
// (for a service that starts automatically). Specifies actions to take
// when the service starts.
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
// When implemented in a derived class, executes when a Stop command is
// sent to the service by the SCM. Specifies actions to take when a
// service stops running.
virtual void OnStop();
// When implemented in a derived class, executes when a Pause command is
// sent to the service by the SCM. Specifies actions to take when a
// service pauses.
virtual void OnPause();
// When implemented in a derived class, OnContinue runs when a Continue
// command is sent to the service by the SCM. Specifies actions to take
// when a service resumes normal functioning after being paused.
virtual void OnContinue();
// When implemented in a derived class, executes when the system is
// shutting down. Specifies what should occur immediately prior to the
// system shutting down.
virtual void OnShutdown();
// Set the service status and report the status to the SCM.
void SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode = NO_ERROR,
DWORD dwWaitHint = 0);
// Log a message to the Application event log.
void WriteEventLogEntry(PSTR pszMessage, WORD wType);
// Log an error message to the Application event log.
void WriteErrorLogEntry(PSTR pszFunction,
DWORD dwError = GetLastError());
private:
// Entry point for the service. It registers the handler function for the
// service and starts the service.
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
// The function is called by the SCM whenever a control code is sent to
// the service.
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
// Start the service.
void Start(DWORD dwArgc, PSTR *pszArgv);
// Pause the service.
void Pause();
// Resume the service after being paused.
void Continue();
// Execute when the system is shutting down.
void Shutdown();
// The singleton service instance.
static CServiceBase *s_service;
// The name of the service
LPSTR m_name;
// The status of the service
SERVICE_STATUS m_status;
// The service status handle
SERVICE_STATUS_HANDLE m_statusHandle;
};

View File

@ -0,0 +1,183 @@
/****************************** Module Header ******************************\
* Module Name: ServiceInstaller.cpp
* Project: CppWindowsService
* Copyright (c) Microsoft Corporation.
*
* The file implements functions that install and uninstall the service.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma region "Includes"
#include <stdio.h>
#include <windows.h>
#include "ServiceInstaller.h"
#pragma endregion
//
// FUNCTION: InstallService
//
// PURPOSE: Install the current application as a service to the local
// service control manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be installed
// * pszDisplayName - the display name of the service
// * dwStartType - the service start option. This parameter can be one of
// the following values: SERVICE_AUTO_START, SERVICE_BOOT_START,
// SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START.
// * pszDependencies - a pointer to a double null-terminated array of null-
// separated names of services or load ordering groups that the system
// must start before this service.
// * pszAccount - the name of the account under which the service runs.
// * pszPassword - the password to the account name.
//
// NOTE: If the function fails to install the service, it prints the error
// in the standard output stream for users to diagnose the problem.
//
std::string InstallService(PSTR pszServiceName,
PSTR pszDisplayName,
DWORD dwStartType,
PSTR pszDependencies,
PSTR pszAccount,
PSTR pszPassword)
{
std::string ret;
char szPath[MAX_PATH];
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
{
ret = "GetModuleFileName failed, unable to get path to self";
goto Cleanup;
}
// Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL)
{
ret = "OpenSCManager failed";
goto Cleanup;
}
// Install the service into SCM by calling CreateService
schService = CreateService(
schSCManager, // SCManager database
pszServiceName, // Name of service
pszDisplayName, // Name to display
SERVICE_QUERY_STATUS, // Desired access
SERVICE_WIN32_OWN_PROCESS, // Service type
dwStartType, // Service start type
SERVICE_ERROR_NORMAL, // Error control type
szPath, // Service's binary
NULL, // No load ordering group
NULL, // No tag identifier
pszDependencies, // Dependencies
pszAccount, // Service running account
pszPassword // Password of the account
);
if (schService == NULL)
{
ret = "CreateService failed";
goto Cleanup;
}
Cleanup:
// Centralized cleanup for all allocated resources.
if (schSCManager)
{
CloseServiceHandle(schSCManager);
schSCManager = NULL;
}
if (schService)
{
CloseServiceHandle(schService);
schService = NULL;
}
return ret;
}
//
// FUNCTION: UninstallService
//
// PURPOSE: Stop and remove the service from the local service control
// manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be removed.
//
// NOTE: If the function fails to uninstall the service, it prints the
// error in the standard output stream for users to diagnose the problem.
//
std::string UninstallService(PSTR pszServiceName)
{
std::string ret;
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
SERVICE_STATUS ssSvcStatus = {};
// Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schSCManager == NULL)
{
ret = "OpenSCManager failed";
goto Cleanup;
}
// Open the service with delete, stop, and query status permissions
schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP |
SERVICE_QUERY_STATUS | DELETE);
if (schService == NULL)
{
ret = "OpenService failed (is service installed?)";
goto Cleanup;
}
// Try to stop the service
if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
{
Sleep(500);
while (QueryServiceStatus(schService, &ssSvcStatus))
{
if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
Sleep(500);
}
else break;
}
}
// Now remove the service by calling DeleteService.
if (!DeleteService(schService))
{
ret = "DeleteService failed (is service running?)";
goto Cleanup;
}
Cleanup:
// Centralized cleanup for all allocated resources.
if (schSCManager)
{
CloseServiceHandle(schSCManager);
schSCManager = NULL;
}
if (schService)
{
CloseServiceHandle(schService);
schService = NULL;
}
return ret;
}

View File

@ -0,0 +1,64 @@
/****************************** Module Header ******************************\
* Module Name: ServiceInstaller.h
* Project: CppWindowsService
* Copyright (c) Microsoft Corporation.
*
* The file declares functions that install and uninstall the service.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma once
#include <string>
//
// FUNCTION: InstallService
//
// PURPOSE: Install the current application as a service to the local
// service control manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be installed
// * pszDisplayName - the display name of the service
// * dwStartType - the service start option. This parameter can be one of
// the following values: SERVICE_AUTO_START, SERVICE_BOOT_START,
// SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START.
// * pszDependencies - a pointer to a double null-terminated array of null-
// separated names of services or load ordering groups that the system
// must start before this service.
// * pszAccount - the name of the account under which the service runs.
// * pszPassword - the password to the account name.
//
// NOTE: If the function fails to install the service, it prints the error
// in the standard output stream for users to diagnose the problem.
//
// modified for ZT1 to return an error or empty string on success
std::string InstallService(PSTR pszServiceName,
PSTR pszDisplayName,
DWORD dwStartType,
PSTR pszDependencies,
PSTR pszAccount,
PSTR pszPassword);
//
// FUNCTION: UninstallService
//
// PURPOSE: Stop and remove the service from the local service control
// manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be removed.
//
// NOTE: If the function fails to uninstall the service, it prints the
// error in the standard output stream for users to diagnose the problem.
//
// Also modified to return rather than print errors
std::string UninstallService(PSTR pszServiceName);

View File

@ -49,6 +49,9 @@
<ClCompile Include="..\..\node\Topology.cpp" />
<ClCompile Include="..\..\node\UdpSocket.cpp" />
<ClCompile Include="..\..\node\Utils.cpp" />
<ClCompile Include="ServiceBase.cpp" />
<ClCompile Include="ServiceInstaller.cpp" />
<ClCompile Include="ZeroTierOneService.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\ext\lz4\lz4.h" />
@ -97,6 +100,9 @@
<ClInclude Include="..\..\node\UdpSocket.hpp" />
<ClInclude Include="..\..\node\Utils.hpp" />
<ClInclude Include="resource.h" />
<ClInclude Include="ServiceBase.h" />
<ClInclude Include="ServiceInstaller.h" />
<ClInclude Include="ZeroTierOneService.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ZeroTierOne.rc" />

View File

@ -105,6 +105,15 @@
<ClCompile Include="..\..\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ServiceBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ServiceInstaller.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZeroTierOneService.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\ext\lz4\lz4.h">
@ -245,6 +254,15 @@
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ServiceBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ServiceInstaller.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZeroTierOneService.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ZeroTierOne.rc">

View File

@ -0,0 +1,110 @@
/*
* ZeroTier One - Global Peer to Peer Ethernet
* Copyright (C) 2012-2013 ZeroTier Networks LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*
* ZeroTier may be used and distributed under the terms of the GPLv3, which
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form, please contact ZeroTier Networks
* LLC. Start here: http://www.zerotier.com/
*/
#pragma region Includes
#include "ZeroTierOneService.h"
#pragma endregion
ZeroTierOneService::ZeroTierOneService() :
CServiceBase(ZT_SERVICE_NAME,TRUE,TRUE,FALSE),
_node((ZeroTier::Node *)0)
{
}
ZeroTierOneService::~ZeroTierOneService(void)
{
}
void ZeroTierOneService::threadMain()
throw()
{
restart_node:
try {
{
// start or restart
ZeroTier::Mutex::Lock _l(_lock);
delete _node;
_node = new ZeroTier::Node(ZeroTier::ZT_DEFAULTS.defaultHomePath.c_str(),0,0);
}
switch(_node->run()) {
case ZeroTier::Node::NODE_RESTART_FOR_UPGRADE: {
} break;
case ZeroTier::Node::NODE_UNRECOVERABLE_ERROR: {
std::string err("ZeroTier node encountered an unrecoverable error: ");
const char *r = _node->reasonForTermination();
if (r)
err.append(r);
else err.append("(unknown error)");
err.append(" (restarting in 5 seconds)");
WriteEventLogEntry(const_cast <PSTR>(err.c_str()),EVENTLOG_ERROR_TYPE);
Sleep(5000);
goto restart_node;
} break;
default: // includes normal termination, which will terminate thread
break;
}
} catch ( ... ) {
// sanity check, shouldn't happen since Node::run() should catch all its own errors
// could also happen if we're out of memory though!
WriteEventLogEntry("unexpected exception (out of memory?) (trying again in 5 seconds)",EVENTLOG_ERROR_TYPE);
Sleep(5000);
goto restart_node;
}
_lock.lock();
delete _node;
_node = (ZeroTier::Node *)0;
_lock.unlock();
}
void ZeroTierOneService::OnStart(DWORD dwArgc, LPSTR *lpszArgv)
{
if (_node)
return; // sanity check
try {
_thread = ZeroTier::Thread::start(this);
} catch ( ... ) {
throw (DWORD)ERROR_EXCEPTION_IN_SERVICE;
}
}
void ZeroTierOneService::OnStop()
{
_lock.lock();
ZeroTier::Node *n = _node;
_lock.unlock();
if (n) {
n->terminate(ZeroTier::Node::NODE_NORMAL_TERMINATION,"Windows service stopped");
ZeroTier::Thread::join(_thread);
}
}
void ZeroTierOneService::OnShutdown()
{
// stop thread on system shutdown (if it hasn't happened already)
OnStop();
}

View File

@ -0,0 +1,66 @@
/*
* ZeroTier One - Global Peer to Peer Ethernet
* Copyright (C) 2012-2013 ZeroTier Networks LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*
* ZeroTier may be used and distributed under the terms of the GPLv3, which
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form, please contact ZeroTier Networks
* LLC. Start here: http://www.zerotier.com/
*/
#pragma once
#include "ServiceBase.h"
#include "../../node/Node.hpp"
#include "../../node/Defaults.hpp"
#include "../../node/Thread.hpp"
#include "../../node/Mutex.hpp"
#include "../../node/Utils.hpp"
#define ZT_SERVICE_NAME "ZeroTierOneService"
#define ZT_SERVICE_DISPLAY_NAME "ZeroTier One"
#define ZT_SERVICE_START_TYPE SERVICE_AUTO_START
#define ZT_SERVICE_DEPENDENCIES ""
#define ZT_SERVICE_ACCOUNT "NT AUTHORITY\\LocalService"
#define ZT_SERVICE_PASSWORD NULL
class ZeroTierOneService : public CServiceBase
{
public:
ZeroTierOneService();
virtual ~ZeroTierOneService(void);
/**
* Thread main method; do not call elsewhere
*/
void threadMain()
throw();
protected:
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
virtual void OnStop();
virtual void OnShutdown();
private:
ZeroTier::Node *volatile _node;
ZeroTier::Mutex _lock;
ZeroTier::Thread _thread;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- Select a Product Configuration -->
<InstallShieldProductConfiguration>Express</InstallShieldProductConfiguration>
<!-- Select a Visual Studio Configuration / InstallShield Release -->
<Configuration>Debug</Configuration>
<InstallShieldRelease>$(Configuration)</InstallShieldRelease>
</PropertyGroup>
<ItemGroup>
<!-- The InstallShieldProject item selects the project to build -->
<InstallShieldProject Include="$(MSBuildProjectDirectory)\$(MSBuildProjectName).isl"/>
<!-- The InstallShieldReleaseFlags sets Release Flags -->
<!--<InstallShieldReleaseFlags Include=""/>-->
<!-- The InstallShieldMergeModulePath specifies what directories are
searched for Merge Modules -->
<!--<InstallShieldMergeModulePath Include=""/>-->
</ItemGroup>
<ItemGroup>
<!-- The ProjectReference items refer to any Visual Studio solutions you want to automatically probe for Project Output Groups. -->
</ItemGroup>
<ItemGroup>
<!-- The TaggedOutputs items allow you to explicitly add extra files to output groups. Each item must include both Name and OutputGroup, as well as TargetPath metadata values. -->
<!--<TaggedOutputs Include="C:\My Test Exe.exe">
<Name>My Test Project</Name>
<OutputGroup>Primary output</OutputGroup>
<TargetPath>My Test Exe.exe</TargetPath>
</TaggedOutputs> -->
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\InstallShield\2013Limited\InstallShield.targets"/>
<ItemGroup>
<ProjectReference Include="..\ZeroTierOneService\ZeroTierOneService.csproj">
<Name>ZeroTierOneService</Name>
<Project>{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}</Project>
</ProjectReference>
</ItemGroup>
</Project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

View File

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace ZeroTierOneService
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service()
};
ServiceBase.Run(ServicesToRun);
}
}
}

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ZeroTierOneService")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZeroTierOneService")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("540d1a89-f952-4927-a99a-cb0fb4d9d619")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,41 +0,0 @@
namespace ZeroTierOneService
{
partial class Service
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// Service
//
this.ServiceName = "Service1";
}
#endregion
}
}

View File

@ -1,110 +0,0 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
namespace ZeroTierOneService
{
public partial class Service : ServiceBase
{
public Service()
{
InitializeComponent();
this.ztHome = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + Path.DirectorySeparatorChar + "ZeroTier" + Path.DirectorySeparatorChar + "One";
this.ztUpdatesFolder = this.ztHome + Path.DirectorySeparatorChar + "updates.d";
this.ztBinary = this.ztHome + Path.DirectorySeparatorChar + (Environment.Is64BitOperatingSystem ? "zerotier-one_x64.exe" : "zerotier-one_x86.exe");
this.ztService = null;
this.ztKiller = null;
}
protected override void OnStart(string[] args)
{
startZeroTierDaemon();
}
protected override void OnStop()
{
stopZeroTierDaemon();
}
private void startZeroTierDaemon()
{
if (ztService != null)
return;
ztService = new Process();
try
{
ztService.StartInfo.UseShellExecute = false;
ztService.StartInfo.FileName = ztBinary;
ztService.StartInfo.Arguments = "";
ztService.StartInfo.CreateNoWindow = true;
ztService.Exited += ztService_Exited;
ztService.Start();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
ztService = null;
}
}
private void stopZeroTierDaemon()
{
while (ztKiller != null)
Thread.Sleep(250);
ztKiller = new Process();
try
{
ztKiller.StartInfo.UseShellExecute = false;
ztKiller.StartInfo.FileName = ztBinary;
ztKiller.StartInfo.Arguments = "-q terminate ServiceShutdown";
ztKiller.StartInfo.CreateNoWindow = true;
ztKiller.Exited += ztKiller_Exited;
ztKiller.Start();
}
catch (Exception e)
{
ztKiller = null;
}
int waited = 0;
while (ztKiller != null)
{
Thread.Sleep(250);
if (++waited > 100)
break;
}
if (ztService != null)
{
ztService.Kill();
ztService = null;
}
}
// Event generated when ztService exits
private void ztService_Exited(object sender, System.EventArgs e)
{
ztService = null;
}
// Event generated when ztKiller is done
private void ztKiller_Exited(object sender, System.EventArgs e)
{
ztKiller = null;
}
private string ztHome;
private string ztUpdatesFolder;
private string ztBinary;
private volatile Process ztService;
private volatile Process ztKiller;
}
}

View File

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@ -1,116 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{63D28112-9A56-42FA-9C3E-EF6C58AF09B3}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ZeroTierOneService</RootNamespace>
<AssemblyName>ZeroTierOneService</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<StartupObject>ZeroTierOneService.Program</StartupObject>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<SignManifests>false</SignManifests>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>5809BB3255B4F32DD93619C1CF26A7DF6C282A89</ManifestCertificateThumbprint>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Service.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Service.Designer.cs">
<DependentUpon>Service.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Service.resx">
<DependentUpon>Service.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>