Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
diff --git a/native/IdeaWin32/IdeaWin32.cpp b/native/IdeaWin32/IdeaWin32.cpp
new file mode 100644
index 0000000..5c32ec6
--- /dev/null
+++ b/native/IdeaWin32/IdeaWin32.cpp
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "IdeaWin32.h"
+#include <windows.h>
+
+typedef DWORD (WINAPI *GetFinalPathNameByHandlePtr) (HANDLE, LPCWSTR, DWORD, DWORD dwFlags);
+static GetFinalPathNameByHandlePtr __GetFinalPathNameByHandle = NULL;
+
+static jfieldID nameID = NULL;
+static jfieldID attributesID = NULL;
+static jfieldID timestampID = NULL;
+static jfieldID lengthID = NULL;
+
+#define FILE_INFO_CLASS "com/intellij/openapi/util/io/win32/FileInfo"
+#define BROKEN_SYMLINK_ATTR -1
+#define IS_SET(flags, flag) ((flags & flag) == flag)
+#define FILE_SHARE_ATTRIBUTES (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
+
+static wchar_t* ToWinPath(JNIEnv* env, jstring path, bool dirSuffix);
+static jobject CreateFileInfo(JNIEnv* env, wchar_t* path, bool isDirectory, LPWIN32_FIND_DATA lpData, jclass aClass);
+static jobjectArray CopyObjectArray(JNIEnv* env, jobjectArray src, jclass aClass, jsize count, jsize newSize);
+
+
+// interface methods
+
+JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs(JNIEnv* env, jclass cls) {
+ __GetFinalPathNameByHandle = (GetFinalPathNameByHandlePtr)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetFinalPathNameByHandleW");
+
+ jclass fileInfoClass = env->FindClass(FILE_INFO_CLASS);
+ if (fileInfoClass == NULL) {
+ return;
+ }
+
+ nameID = env->GetFieldID(fileInfoClass, "name", "Ljava/lang/String;");
+ attributesID = env->GetFieldID(fileInfoClass, "attributes", "I");
+ timestampID = env->GetFieldID(fileInfoClass, "timestamp", "J");
+ lengthID = env->GetFieldID(fileInfoClass, "length", "J");
+}
+
+JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo0(JNIEnv* env, jobject method, jstring path) {
+ wchar_t* winPath = ToWinPath(env, path, false);
+ if (winPath == NULL) {
+ return NULL;
+ }
+
+ WIN32_FILE_ATTRIBUTE_DATA attrData;
+ BOOL res = GetFileAttributesExW(winPath, GetFileExInfoStandard, &attrData);
+ if (!res) {
+ free(winPath);
+ return NULL;
+ }
+
+ jclass fileInfoClass = env->FindClass(FILE_INFO_CLASS);
+ if (fileInfoClass == NULL) {
+ return NULL;
+ }
+
+ jobject result = NULL;
+ if (IS_SET(attrData.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
+ // may be symlink
+ WIN32_FIND_DATA data;
+ HANDLE h = FindFirstFileW(winPath, &data);
+ if (h != INVALID_HANDLE_VALUE) {
+ FindClose(h);
+ result = CreateFileInfo(env, winPath, false, &data, fileInfoClass);
+ }
+ }
+ if (result == NULL) {
+ // either not a symlink or FindFirstFile() failed
+ WIN32_FIND_DATA data;
+ data.dwFileAttributes = attrData.dwFileAttributes;
+ data.dwReserved0 = 0;
+ data.ftLastWriteTime = attrData.ftLastWriteTime;
+ data.nFileSizeLow = attrData.nFileSizeLow;
+ data.nFileSizeHigh = attrData.nFileSizeHigh;
+ data.cFileName[0] = L'\0';
+ result = CreateFileInfo(env, winPath, false, &data, fileInfoClass);
+ }
+
+ free(winPath);
+ return result;
+}
+
+JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink0(JNIEnv* env, jobject method, jstring path) {
+ if (__GetFinalPathNameByHandle == NULL) {
+ return path; // links not supported
+ }
+
+ wchar_t* winPath = ToWinPath(env, path, false);
+ jstring result = path;
+
+ WIN32_FIND_DATA data;
+ HANDLE h = FindFirstFileW(winPath, &data);
+ if (h != INVALID_HANDLE_VALUE) {
+ FindClose(h);
+
+ if (IS_SET(data.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT) &&
+ (IS_SET(data.dwReserved0, IO_REPARSE_TAG_SYMLINK) || IS_SET(data.dwReserved0, IO_REPARSE_TAG_MOUNT_POINT))) {
+ HANDLE th = CreateFileW(winPath, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (th != INVALID_HANDLE_VALUE) {
+ wchar_t buff[MAX_PATH], * finalPath = buff;
+ DWORD len = __GetFinalPathNameByHandle(th, buff, MAX_PATH, 0);
+ if (len >= MAX_PATH) {
+ finalPath = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
+ len = finalPath != NULL ? __GetFinalPathNameByHandle(th, finalPath, len, 0) : 0;
+ }
+ if (len > 0) {
+ int prefix = (len > 4 && finalPath[0] == L'\\' && finalPath[1] == L'\\' && finalPath[2] == L'?' && finalPath[3] == L'\\') ? 4 : 0;
+ result = env->NewString((jchar*)finalPath + prefix, len - prefix);
+ if (finalPath != buff) {
+ free(finalPath);
+ }
+ }
+ CloseHandle(th);
+ }
+ else {
+ result = NULL;
+ }
+ }
+ }
+ else {
+ result = NULL;
+ }
+
+ free(winPath);
+ return result;
+}
+
+JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren0(JNIEnv* env, jobject method, jstring path) {
+ jclass fileInfoClass = env->FindClass(FILE_INFO_CLASS);
+ if (fileInfoClass == NULL) {
+ return NULL;
+ }
+
+ wchar_t* winPath = ToWinPath(env, path, true);
+ if (winPath == NULL) {
+ return NULL;
+ }
+
+ WIN32_FIND_DATA data;
+ HANDLE h = FindFirstFileW(winPath, &data);
+ if (h == INVALID_HANDLE_VALUE) {
+ free(winPath);
+ return NULL;
+ }
+
+ jsize len = 0, maxLen = 16;
+ jobjectArray result = env->NewObjectArray(maxLen, fileInfoClass, NULL);
+ if (result != NULL) {
+ do {
+ if (wcscmp(data.cFileName, L".") == 0 || wcscmp(data.cFileName, L"..") == 0) {
+ continue;
+ }
+
+ if (len == maxLen) {
+ result = CopyObjectArray(env, result, fileInfoClass, len, maxLen <<= 1);
+ if (result == NULL) {
+ goto exit;
+ }
+ }
+
+ jobject o = CreateFileInfo(env, winPath, true, &data, fileInfoClass);
+ env->SetObjectArrayElement(result, len++, o);
+ env->DeleteLocalRef(o);
+ }
+ while (FindNextFile(h, &data));
+
+ if (len != maxLen) {
+ result = CopyObjectArray(env, result, fileInfoClass, len, len);
+ }
+ }
+
+exit:
+ free(winPath);
+ FindClose(h);
+ return result;
+}
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
+ return TRUE;
+}
+
+
+// utility methods
+
+static inline LONGLONG pairToInt64(DWORD lowPart, DWORD highPart);
+
+static wchar_t* ToWinPath(JNIEnv* env, jstring path, bool dirSuffix) {
+ jsize len = env->GetStringLength(path), prefix = 0, suffix = 0;
+ const jchar* jstr = env->GetStringChars(path, NULL);
+ while (len > 0 && jstr[len - 1] == L'\\') --len; // trim trailing separators
+ if (len == 0) return NULL;
+ if (len >= MAX_PATH) prefix = 4; // prefix long paths by UNC marker
+ if (dirSuffix) suffix = 2;
+
+ wchar_t* pathBuf = (wchar_t*)malloc((prefix + len + suffix + 1) * sizeof(wchar_t));
+ if (pathBuf != NULL) {
+ if (prefix > 0) {
+ wcsncpy_s(pathBuf, prefix + 1, L"\\\\?\\", prefix);
+ }
+ wcsncpy_s(pathBuf + prefix, len + 1, (wchar_t*)jstr, len);
+ if (suffix > 0) {
+ wcsncpy_s(pathBuf + prefix + len, suffix + 1, L"\\*", suffix);
+ }
+ pathBuf[prefix + len + suffix] = L'\0';
+ }
+
+ env->ReleaseStringChars(path, jstr);
+
+ return pathBuf;
+}
+
+static jobject CreateFileInfo(JNIEnv* env, wchar_t* path, bool isDirectory, LPWIN32_FIND_DATA lpData, jclass aClass) {
+ DWORD attributes = lpData->dwFileAttributes;
+ LONGLONG timestamp = pairToInt64(lpData->ftLastWriteTime.dwLowDateTime, lpData->ftLastWriteTime.dwHighDateTime);
+ LONGLONG length = pairToInt64(lpData->nFileSizeLow, lpData->nFileSizeHigh);
+
+ if (IS_SET(attributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
+ if (IS_SET(lpData->dwReserved0, IO_REPARSE_TAG_SYMLINK)) {
+ attributes = BROKEN_SYMLINK_ATTR;
+ timestamp = 0;
+ length = 0;
+
+ wchar_t* fullPath = path;
+ if (isDirectory) {
+ // trim '*' and append file name
+ size_t dirLen = wcslen(path) - 1, nameLen = wcslen(lpData->cFileName), fullLen = dirLen + nameLen + 1;
+ fullPath = (wchar_t*)malloc(fullLen * sizeof(wchar_t));
+ if (fullPath == NULL) {
+ return NULL;
+ }
+ wcsncpy_s(fullPath, dirLen + 1, path, dirLen);
+ wcsncpy_s(fullPath + dirLen, nameLen + 1, lpData->cFileName, nameLen);
+ }
+
+ // read symlink target attributes
+ HANDLE h = CreateFileW(fullPath, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (h != INVALID_HANDLE_VALUE) {
+ BY_HANDLE_FILE_INFORMATION targetData;
+ if (GetFileInformationByHandle(h, &targetData)) {
+ attributes = targetData.dwFileAttributes | FILE_ATTRIBUTE_REPARSE_POINT;
+ timestamp = pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime);
+ length = pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh);
+ }
+ CloseHandle(h);
+ }
+
+ if (fullPath != path) {
+ free(fullPath);
+ }
+ }
+ else {
+ attributes &= (~ FILE_ATTRIBUTE_REPARSE_POINT); // keep reparse flag only for symlinks
+ }
+ }
+
+ jobject o = env->AllocObject(aClass);
+ if (o == NULL) {
+ return NULL;
+ }
+
+ jstring fileName = env->NewString((jchar*)lpData->cFileName, (jsize)wcslen(lpData->cFileName));
+ if (fileName == NULL) {
+ return NULL;
+ }
+
+ env->SetObjectField(o, nameID, fileName);
+ env->SetIntField(o, attributesID, attributes);
+ env->SetLongField(o, timestampID, timestamp);
+ env->SetLongField(o, lengthID, length);
+
+ return o;
+}
+
+static jobjectArray CopyObjectArray(JNIEnv* env, jobjectArray src, jclass aClass, jsize count, jsize newSize) {
+ jobjectArray dst = env->NewObjectArray(newSize, aClass, NULL);
+ if (dst != NULL) {
+ for (jsize i = 0; i < count; i++) {
+ jobject o = env->GetObjectArrayElement(src, i);
+ env->SetObjectArrayElement(dst, i, o);
+ env->DeleteLocalRef(o);
+ }
+ }
+ env->DeleteLocalRef(src);
+ return dst;
+}
+
+static inline LONGLONG pairToInt64(DWORD lowPart, DWORD highPart) {
+ ULARGE_INTEGER large;
+ large.LowPart = lowPart;
+ large.HighPart = highPart;
+ return large.QuadPart;
+}
diff --git a/native/IdeaWin32/IdeaWin32.h b/native/IdeaWin32/IdeaWin32.h
new file mode 100644
index 0000000..3f69378
--- /dev/null
+++ b/native/IdeaWin32/IdeaWin32.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+
+#ifndef _Included_com_intellij_openapi_util_io_win32_IdeaWin32
+#define _Included_com_intellij_openapi_util_io_win32_IdeaWin32
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs
+ (JNIEnv *, jclass);
+
+JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo0
+ (JNIEnv *, jobject, jstring);
+
+JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink0
+ (JNIEnv *, jobject, jstring);
+
+JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren0
+ (JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/native/IdeaWin32/IdeaWin32.props b/native/IdeaWin32/IdeaWin32.props
new file mode 100644
index 0000000..467d726
--- /dev/null
+++ b/native/IdeaWin32/IdeaWin32.props
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets" />
+ <PropertyGroup Label="UserMacros">
+ <JAVA_HOME>C:\Tools\JDK6</JAVA_HOME>
+ </PropertyGroup>
+ <PropertyGroup>
+ <IntDir>$(Configuration)$(Platform)\</IntDir>
+ <IncludePath>$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup />
+ <ItemGroup>
+ <BuildMacro Include="JAVA_HOME">
+ <Value>$(JAVA_HOME)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/native/IdeaWin32/IdeaWin32.sln b/native/IdeaWin32/IdeaWin32.sln
new file mode 100644
index 0000000..05286e5
--- /dev/null
+++ b/native/IdeaWin32/IdeaWin32.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IdeaWin32", "IdeaWin32.vcxproj", "{F68FFBFC-3437-4215-839A-563936B9A3CC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|Win32.Build.0 = Debug|Win32
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|x64.ActiveCfg = Debug|x64
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|x64.Build.0 = Debug|x64
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|Win32.ActiveCfg = Release|Win32
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|Win32.Build.0 = Release|Win32
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|x64.ActiveCfg = Release|x64
+ {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/native/IdeaWin32/IdeaWin32.vcxproj b/native/IdeaWin32/IdeaWin32.vcxproj
new file mode 100644
index 0000000..bdf7114
--- /dev/null
+++ b/native/IdeaWin32/IdeaWin32.vcxproj
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F68FFBFC-3437-4215-839A-563936B9A3CC}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>IdeaWin32</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="IdeaWin32.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="IdeaWin32.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="IdeaWin32.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="IdeaWin32.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(Configuration)$(Platform)\</OutDir>
+ <TargetName>IdeaWin32</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(Configuration)$(Platform)\</OutDir>
+ <TargetName>IdeaWin64</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(Configuration)$(Platform)\</OutDir>
+ <TargetName>IdeaWin32</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(Configuration)$(Platform)\</OutDir>
+ <TargetName>IdeaWin64</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="IdeaWin32.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="IdeaWin32.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/native/IdeaWin32/IdeaWin32.vcxproj.filters b/native/IdeaWin32/IdeaWin32.vcxproj.filters
new file mode 100644
index 0000000..cf3b94f
--- /dev/null
+++ b/native/IdeaWin32/IdeaWin32.vcxproj.filters
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="IdeaWin32.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="IdeaWin32.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/native/IdeaWin32/IdeaWin32.vcxproj.user b/native/IdeaWin32/IdeaWin32.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/native/IdeaWin32/IdeaWin32.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/native/IdeaWin32/readme.txt b/native/IdeaWin32/readme.txt
new file mode 100644
index 0000000..d3a99b3
--- /dev/null
+++ b/native/IdeaWin32/readme.txt
@@ -0,0 +1,9 @@
+Prerequisites:
+- Visual Studio C++ 2010 Express
+- Windows SDK 7.1 (native: Windows Headers, x86 Libraries, x64 Libraries, Tools, Visual C++ Compilers)
+- JDK 1.6+
+
+To build:
+- open Property Manager, expand any configuration, open IdeaWin32 property page, and edit JAVA_HOME user macro
+ to point to a valid JDK installation
+- build Release/Win32 and Release/x64 configurations
diff --git a/native/MacLauncher/.idea/.name b/native/MacLauncher/.idea/.name
new file mode 100644
index 0000000..dc9c257
--- /dev/null
+++ b/native/MacLauncher/.idea/.name
@@ -0,0 +1 @@
+MacLauncher
\ No newline at end of file
diff --git a/native/MacLauncher/.idea/AppLauncher.iml b/native/MacLauncher/.idea/AppLauncher.iml
new file mode 100644
index 0000000..f9b36de
--- /dev/null
+++ b/native/MacLauncher/.idea/AppLauncher.iml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="CIDR_MODULE" version="4">
+ <component name="NewModuleRootManager">
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/native/MacLauncher/.idea/dictionaries/max.xml b/native/MacLauncher/.idea/dictionaries/max.xml
new file mode 100644
index 0000000..81b3e8d
--- /dev/null
+++ b/native/MacLauncher/.idea/dictionaries/max.xml
@@ -0,0 +1,3 @@
+<component name="ProjectDictionaryState">
+ <dictionary name="max" />
+</component>
\ No newline at end of file
diff --git a/native/MacLauncher/.idea/encodings.xml b/native/MacLauncher/.idea/encodings.xml
new file mode 100644
index 0000000..e206d70
--- /dev/null
+++ b/native/MacLauncher/.idea/encodings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+</project>
+
diff --git a/native/MacLauncher/.idea/find.xml b/native/MacLauncher/.idea/find.xml
new file mode 100644
index 0000000..6892330
--- /dev/null
+++ b/native/MacLauncher/.idea/find.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="OCFindUsagesOptions" text="true" ivars="false" properties="true" derivedClasses="false" />
+</project>
+
diff --git a/native/MacLauncher/.idea/misc.xml b/native/MacLauncher/.idea/misc.xml
new file mode 100644
index 0000000..11e74ae
--- /dev/null
+++ b/native/MacLauncher/.idea/misc.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectResources">
+ <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
+ </component>
+ <component name="ProjectRootManager" version="2" />
+</project>
+
diff --git a/native/MacLauncher/.idea/modules.xml b/native/MacLauncher/.idea/modules.xml
new file mode 100644
index 0000000..e774462
--- /dev/null
+++ b/native/MacLauncher/.idea/modules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/AppLauncher.iml" filepath="$PROJECT_DIR$/.idea/AppLauncher.iml" />
+ </modules>
+ </component>
+</project>
+
diff --git a/native/MacLauncher/.idea/scopes/scope_settings.xml b/native/MacLauncher/.idea/scopes/scope_settings.xml
new file mode 100644
index 0000000..922003b
--- /dev/null
+++ b/native/MacLauncher/.idea/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+<component name="DependencyValidationManager">
+ <state>
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </state>
+</component>
\ No newline at end of file
diff --git a/native/MacLauncher/.idea/vcs.xml b/native/MacLauncher/.idea/vcs.xml
new file mode 100644
index 0000000..9ab281a
--- /dev/null
+++ b/native/MacLauncher/.idea/vcs.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
+ </component>
+</project>
+
diff --git a/native/MacLauncher/.idea/xcode.xml b/native/MacLauncher/.idea/xcode.xml
new file mode 100644
index 0000000..28f4cb3
--- /dev/null
+++ b/native/MacLauncher/.idea/xcode.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="XcodeMetaData" PROJECT_FILE="$PROJECT_DIR$/MacLauncher.xcodeproj" />
+</project>
+
diff --git a/native/MacLauncher/Info.plist b/native/MacLauncher/Info.plist
new file mode 100644
index 0000000..a189b85
--- /dev/null
+++ b/native/MacLauncher/Info.plist
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>JetBrains.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>Java</key>
+ <dict>
+ <key>ClassPath</key>
+ <string>$APP_PACKAGE</string>
+ <key>MainClass</key>
+ <string>com.intellij.idea.Main</string>
+ <key>Properties</key>
+ <dict>
+ <key>CVS_PASSFILE</key>
+ <string>~/.cvspass</string>
+ <key>apple.laf.useScreenMenuBar</key>
+ <string>true</string>
+ <key>com.apple.mrj.application.live-resize</key>
+ <string>false</string>
+ <key>idea.config.path</key>
+ <string>~/Library/Preferences/IntelliJIdea10CE/</string>
+ <key>idea.is.internal</key>
+ <string>true</string>
+ <key>idea.log.path</key>
+ <string>~/Library/Logs/IntelliJIdea10CE/</string>
+ <key>idea.platform.prefix</key>
+ <string>Idea</string>
+ <key>idea.plugins.path</key>
+ <string>~/Library/Application Support/IntelliJIdea10CE/</string>
+ <key>idea.system.path</key>
+ <string>~/Library/Caches/IntelliJIdea10CE/</string>
+ <key>idea.use.default.antialiasing.in.editor</key>
+ <string>true</string>
+ </dict>
+ <key>VMOptions</key>
+ <string>-ea</string>
+ <key>VMOptions.i386</key>
+ <string>-Xms128m -Xmx512m -XX:MaxPermSize=250m</string>
+ <key>VMOptions.x86_64</key>
+ <string>-Xms128m -Xmx800m -XX:MaxPermSize=350m -XX:+UseCompressedOops -XX:ReservedCodeCacheSize=256m</string>
+ <key>WorkingDirectory</key>
+ <string>$APP_PACKAGE/bin</string>
+ </dict>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2012 JetBrains inc. All rights reserved.</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/native/MacLauncher/Launcher.h b/native/MacLauncher/Launcher.h
new file mode 100644
index 0000000..ec34086
--- /dev/null
+++ b/native/MacLauncher/Launcher.h
@@ -0,0 +1,20 @@
+//
+// Created by max on 5/4/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+#import <JavaVM/jni.h>
+
+
+@interface Launcher : NSObject {
+ int argc;
+ char **argv;
+}
+- (id)initWithArgc:(int)anArgc argv:(char **)anArgv;
+
+
+- (void) launch;
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/Launcher.m b/native/MacLauncher/Launcher.m
new file mode 100644
index 0000000..f00945c
--- /dev/null
+++ b/native/MacLauncher/Launcher.m
@@ -0,0 +1,388 @@
+//
+// Created by max on 5/4/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "Launcher.h"
+#import "VMOptionsReader.h"
+#import "PropertyFileReader.h"
+#import "utils.h"
+#import <dlfcn.h>
+
+typedef jint (JNICALL *fun_ptr_t_CreateJavaVM)(JavaVM **pvm, void **env, void *args);
+
+
+@interface NSString (CustomReplacements)
+- (NSString *)replaceAll:(NSString *)pattern to:(NSString *)replacement;
+
+@end
+
+@implementation NSString (CustomReplacements)
+- (NSString *)replaceAll:(NSString *)pattern to:(NSString *)replacement {
+ if ([self rangeOfString:pattern].length == 0) return self;
+
+ NSMutableString *answer = [[self mutableCopy] autorelease];
+ [answer replaceOccurrencesOfString:pattern withString:replacement options:0 range:NSMakeRange(0, [self length])];
+ return answer;
+}
+@end
+
+@interface NSDictionary (TypedGetters)
+- (NSDictionary *)dictionaryForKey:(id)key;
+- (id)valueForKey:(NSString *)key inDictionary:(NSString *)dictKey defaultObject:(NSString *)defaultValue;
+@end
+
+@implementation NSDictionary (TypedGetters)
+- (NSDictionary *)dictionaryForKey:(id)key {
+ id answer = [self objectForKey:key];
+ if ([answer isKindOfClass:[NSDictionary class]]) {
+ return answer;
+ }
+ return nil;
+}
+
+- (id)valueForKey:(NSString *)key inDictionary:(NSString *)dictKey defaultObject: (NSString*) defaultValue {
+ NSDictionary *dict = [self dictionaryForKey:dictKey];
+ if (dict == nil) return nil;
+ id answer = [dict valueForKey:key];
+ return answer != nil ? answer : defaultValue;
+}
+@end
+
+@implementation Launcher
+
+- (id)initWithArgc:(int)anArgc argv:(char **)anArgv {
+ self = [super init];
+ if (self) {
+ argc = anArgc;
+ argv = anArgv;
+ }
+
+ return self;
+}
+
+
+void appendJvmBundlesAt(NSString *path, NSMutableArray *sink) {
+ NSError *error = nil;
+ NSArray *names = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
+
+ if (names != nil) {
+ for (NSString *name in names) {
+ if ([name hasSuffix:@".jdk"] || [name hasSuffix:@".jre"]) {
+ NSBundle *bundle = [NSBundle bundleWithPath:[path stringByAppendingPathComponent:name]];
+ if (bundle != nil) {
+ [sink addObject:bundle];
+ }
+ }
+ }
+ }
+}
+
+NSArray *allVms() {
+ NSMutableArray *jvmBundlePaths = [NSMutableArray array];
+
+ NSString *explicit = [[[NSProcessInfo processInfo] environment] objectForKey:@"IDEA_JDK"];
+
+ if (explicit != nil) {
+ appendJvmBundlesAt(explicit, jvmBundlePaths);
+ }
+ else {
+ NSBundle *bundle = [NSBundle mainBundle];
+ NSString *appDir = bundle.bundlePath;
+
+ appendJvmBundlesAt([appDir stringByAppendingPathComponent:@"jre"], jvmBundlePaths);
+ if (jvmBundlePaths.count > 0) return jvmBundlePaths;
+
+ appendJvmBundlesAt([NSHomeDirectory() stringByAppendingPathComponent:@"Library/Java/JavaVirtualMachines"], jvmBundlePaths);
+ appendJvmBundlesAt(@"/Library/Java/JavaVirtualMachines", jvmBundlePaths);
+ appendJvmBundlesAt(@"/System/Library/Java/JavaVirtualMachines", jvmBundlePaths);
+ }
+
+ return jvmBundlePaths;
+}
+
+NSString *jvmVersion(NSBundle *bundle) {
+ return [bundle.infoDictionary valueForKey:@"JVMVersion" inDictionary:@"JavaVM" defaultObject:@"0"];
+}
+
+NSString *requiredJvmVersion() {
+ return [[NSBundle mainBundle].infoDictionary valueForKey:@"JVMVersion" inDictionary:@"Java" defaultObject:@"1.7*"];
+}
+
+BOOL satisfies(NSString *vmVersion, NSString *requiredVersion) {
+ if ([requiredVersion hasSuffix:@"+"]) {
+ requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
+ return [requiredVersion compare:vmVersion options:NSNumericSearch] <= 0;
+ }
+
+ if ([requiredVersion hasSuffix:@"*"]) {
+ requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
+ }
+
+ return [vmVersion hasPrefix:requiredVersion];
+}
+
+NSComparisonResult compareVMVersions(id vm1, id vm2, void *context) {
+ return [jvmVersion(vm2) compare:jvmVersion(vm1) options:NSNumericSearch];
+}
+
+NSBundle *findMatchingVm() {
+ NSArray *vmBundles = [allVms() sortedArrayUsingFunction:compareVMVersions context:NULL];
+
+ if (isDebugEnabled()) {
+ debugLog(@"Found Java Virtual Machines:");
+ for (NSBundle *vm in vmBundles) {
+ debugLog([vm bundlePath]);
+ }
+ }
+
+ NSString *required = requiredJvmVersion();
+ debugLog([NSString stringWithFormat:@"Required VM: %@", required]);
+
+ for (NSBundle *vm in vmBundles) {
+ if (satisfies(jvmVersion(vm), required)) {
+ debugLog(@"Chosen VM:");
+ debugLog([vm bundlePath]);
+ return vm;
+ }
+ }
+
+ debugLog(@"No matching VM found");
+
+ return nil;
+}
+
+CFBundleRef NSBundle2CFBundle(NSBundle *bundle) {
+ CFURLRef bundleURL = (CFURLRef) ([NSURL fileURLWithPath:bundle.bundlePath]);
+ return CFBundleCreate(kCFAllocatorDefault, bundleURL);
+}
+
+- (NSString *)expandMacros:(NSString *)str {
+ return [[str
+ replaceAll:@"$APP_PACKAGE" to:[[NSBundle mainBundle] bundlePath]]
+ replaceAll:@"$USER_HOME" to:NSHomeDirectory()];
+}
+
+- (NSMutableString *)buildClasspath:(NSBundle *)jvm {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSMutableString *classpathOption = [NSMutableString stringWithString:@"-Djava.class.path="];
+ [classpathOption appendString:[jvmInfo objectForKey:@"ClassPath"]];
+
+ NSString *toolsJar = [[jvm bundlePath] stringByAppendingString:@"/Contents/Home/lib/tools.jar"];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:toolsJar]) {
+ [classpathOption appendString:@":"];
+ [classpathOption appendString:toolsJar];
+ }
+ return classpathOption;
+}
+
+
+NSString *getSelector() {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSDictionary *properties = [jvmInfo dictionaryForKey:@"Properties"];
+ if (properties != nil) {
+ return [properties objectForKey:@"idea.paths.selector"];
+ }
+ return nil;
+}
+
+NSString *getPreferencesFolderPath() {
+ return [NSString stringWithFormat:@"%@/Library/Preferences/%@", NSHomeDirectory(), getSelector()];
+}
+
+NSString *getPropertiesFilePath() {
+ return [getPreferencesFolderPath() stringByAppendingString:@"/idea.properites"];
+}
+
+NSString *getDefaultPropertiesFilePath() {
+ return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/bin/idea.properties"];
+}
+
+NSString *getDefaultVMOptionsFilePath() {
+ return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/bin/idea.vmoptions"];
+}
+
+NSString *getVMOptionsFilePath() {
+ return [getPreferencesFolderPath() stringByAppendingString:@"/idea.vmoptions"];
+}
+
+NSArray *parseVMOptions() {
+ NSArray *inConfig=[VMOptionsReader readFile:getVMOptionsFilePath()];
+ if (inConfig) return inConfig;
+ return [VMOptionsReader readFile:getDefaultVMOptionsFilePath()];
+}
+
+NSDictionary *parseProperties() {
+ NSDictionary *inConfig = [PropertyFileReader readFile:getPropertiesFilePath()];
+ if (inConfig) return inConfig;
+ return [PropertyFileReader readFile:getDefaultPropertiesFilePath()];
+}
+
+- (void)fillArgs:(NSMutableArray *)args_array fromProperties:(NSDictionary *)properties {
+ if (properties != nil) {
+ for (id key in properties) {
+ [args_array addObject:[NSString stringWithFormat:@"-D%@=%@", key, [properties objectForKey:key]]];
+ }
+ }
+}
+
+- (JavaVMInitArgs)buildArgsFor:(NSBundle *)jvm {
+ NSMutableString *classpathOption = [self buildClasspath:jvm];
+
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSMutableArray *args_array = [NSMutableArray array];
+
+ [args_array addObject:classpathOption];
+
+ [args_array addObjectsFromArray:[[jvmInfo objectForKey:@"VMOptions"] componentsSeparatedByString:@" "]];
+ [args_array addObjectsFromArray:parseVMOptions()];
+
+ [self fillArgs:args_array fromProperties:[jvmInfo dictionaryForKey:@"Properties"]];
+ [self fillArgs:args_array fromProperties:parseProperties()];
+
+ JavaVMInitArgs args;
+ args.version = JNI_VERSION_1_6;
+ args.ignoreUnrecognized = JNI_TRUE;
+
+ args.nOptions = (jint)[args_array count];
+ args.options = calloc((size_t) args.nOptions, sizeof(JavaVMOption));
+ for (NSUInteger idx = 0; idx < args.nOptions; idx++) {
+ id obj = [args_array objectAtIndex:idx];
+ args.options[idx].optionString = strdup([[self expandMacros:[obj description]] UTF8String]);
+ }
+ return args;
+}
+
+- (const char *)mainClassName {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ char *answer = strdup([[jvmInfo objectForKey:@"MainClass"] UTF8String]);
+
+ char *cur = answer;
+ while (*cur) {
+ if (*cur == '.') {
+ *cur = '/';
+ }
+ cur++;
+ }
+
+ return answer;
+}
+
+- (void)process_cwd {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSString *cwd = [jvmInfo objectForKey:@"WorkingDirectory"];
+ if (cwd != nil) {
+ cwd = [self expandMacros:cwd];
+ if (chdir([cwd UTF8String]) != 0) {
+ NSLog(@"Cannot chdir to working directory at %@", cwd);
+ }
+ }
+}
+
+- (void)launch {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSBundle *vm = findMatchingVm();
+ if (vm == nil) {
+ NSString *old_launcher = [self expandMacros:@"$APP_PACKAGE/Contents/MacOS/idea_appLauncher"];
+ execv([old_launcher fileSystemRepresentation], self->argv);
+
+ NSLog(@"Cannot find matching VM, aborting");
+ exit(-1);
+ }
+
+ NSError *error = nil;
+ BOOL ok = [vm loadAndReturnError:&error];
+ if (!ok) {
+ NSLog(@"Cannot load JVM bundle: %@", error);
+ exit(-1);
+ }
+
+ CFBundleRef cfvm = NSBundle2CFBundle(vm);
+
+ fun_ptr_t_CreateJavaVM create_vm = CFBundleGetFunctionPointerForName(cfvm, CFSTR("JNI_CreateJavaVM"));
+
+ if (create_vm == NULL) {
+ // We have Apple VM chosen here...
+/*
+ [self execCommandLineJava:vm];
+ return;
+*/
+
+ NSString *serverLibUrl = [vm.bundlePath stringByAppendingPathComponent:@"Contents/Libraries/libserver.dylib"];
+
+ void *libHandle = dlopen(serverLibUrl.UTF8String, RTLD_NOW + RTLD_GLOBAL);
+ if (libHandle) {
+ create_vm = dlsym(libHandle, "JNI_CreateJavaVM_Impl");
+ }
+ }
+
+ if (create_vm == NULL) {
+ NSLog(@"Cannot find JNI_CreateJavaVM in chosen JVM bundle at %@", vm.bundlePath);
+ exit(-1);
+ }
+
+ [self process_cwd];
+
+ JNIEnv *env;
+ JavaVM *jvm;
+
+ JavaVMInitArgs args = [self buildArgsFor:vm];
+
+ jint create_vm_rc = create_vm(&jvm, &env, &args);
+ if (create_vm_rc != JNI_OK || jvm == NULL) {
+ NSLog(@"JNI_CreateJavaVM (%@) failed: %d", vm.bundlePath, create_vm_rc);
+ exit(-1);
+ }
+
+ jclass string_class = (*env)->FindClass(env, "java/lang/String");
+ if (string_class == NULL) {
+ NSLog(@"No java.lang.String in classpath!");
+ exit(-1);
+ }
+
+ const char *mainClassName = [self mainClassName];
+ jclass mainClass = (*env)->FindClass(env, mainClassName);
+ if (mainClass == NULL || (*env)->ExceptionOccurred(env)) {
+ NSLog(@"Main class %s not found", mainClassName);
+ (*env)->ExceptionDescribe(env);
+ exit(-1);
+ }
+
+ jmethodID mainMethod = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V");
+ if (mainMethod == NULL || (*env)->ExceptionOccurred(env)) {
+ NSLog(@"Cant't find main() method");
+ (*env)->ExceptionDescribe(env);
+ exit(-1);
+ }
+
+ // See http://stackoverflow.com/questions/10242115/os-x-strange-psn-command-line-parameter-when-launched-from-finder
+ // about psn_ stuff
+ int arg_count = 0;
+ for (int i = 1; i < argc; i++) {
+ if (memcmp(argv[i], "-psn_", 4) != 0) arg_count++;
+ }
+
+ jobject jni_args = (*env)->NewObjectArray(env, arg_count, string_class, NULL);
+
+ arg_count = 0;
+ for (int i = 1; i < argc; i++) {
+ if (memcmp(argv[i], "-psn_", 4) != 0) {
+ jstring jni_arg = (*env)->NewStringUTF(env, argv[i]);
+ (*env)->SetObjectArrayElement(env, jni_args, arg_count, jni_arg);
+ arg_count++;
+ }
+ }
+
+ (*env)->CallStaticVoidMethod(env, mainClass, mainMethod, jni_args);
+
+ (*jvm)->DetachCurrentThread(jvm);
+ (*jvm)->DestroyJavaVM(jvm);
+
+ [pool release];
+}
+
+
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/Launcher.pch b/native/MacLauncher/Launcher.pch
new file mode 100644
index 0000000..7504e2d
--- /dev/null
+++ b/native/MacLauncher/Launcher.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'Launcher' target in the 'Launcher' project
+//
+
+#ifdef __OBJC__
+ #import <Cocoa/Cocoa.h>
+#endif
diff --git a/native/MacLauncher/MacLauncher.xcodeproj/project.pbxproj b/native/MacLauncher/MacLauncher.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..2e2d7d9
--- /dev/null
+++ b/native/MacLauncher/MacLauncher.xcodeproj/project.pbxproj
@@ -0,0 +1,263 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1A5645DB6F789D018FF4A4AF /* PropertyFileReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */; };
+ 1A564BCFE66693BF0B2DD4A9 /* VMOptionsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */; };
+ 1A564C27F0BA05F900F34907 /* utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A564EEF77B93DBD7FD23161 /* utils.m */; };
+ 50E17738155444B900E97451 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50E17737155444B900E97451 /* Cocoa.framework */; };
+ 50E1775715552D2900E97451 /* JavaVM.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B58A123544A15DA59B13E3 /* JavaVM.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+ C0B58A123544A15DA59B13E4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0B58A123544A15DA59B13DC /* main.m */; };
+ C0B58A123544A15DA59B13E5 /* Launcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C0B58A123544A15DA59B13E0 /* Launcher.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PropertyFileReader.m; sourceTree = "<group>"; };
+ 1A564A1031F4C91C464C1B75 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
+ 1A564D7CEEAA02F14A6D4F20 /* VMOptionsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMOptionsReader.h; sourceTree = "<group>"; };
+ 1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VMOptionsReader.m; sourceTree = "<group>"; };
+ 1A564EEF77B93DBD7FD23161 /* utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = utils.m; sourceTree = "<group>"; };
+ 1A564F6D5833A0B9CE6E2839 /* PropertyFileReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyFileReader.h; sourceTree = "<group>"; };
+ 50E17735155444B900E97451 /* Launcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Launcher.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 50E17737155444B900E97451 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ 50E1773F155444B900E97451 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 50E17745155444B900E97451 /* Launcher.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Launcher.pch; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13DC /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13DE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ C0B58A123544A15DA59B13E0 /* Launcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Launcher.m; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13E2 /* Launcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Launcher.h; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13E3 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = System/Library/Frameworks/JavaVM.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 50E17732155444B900E97451 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 50E1775715552D2900E97451 /* JavaVM.framework in Frameworks */,
+ 50E17738155444B900E97451 /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ C0B58A123544A15DA59B13CA = {
+ isa = PBXGroup;
+ children = (
+ C0B58A123544A15DA59B13DC /* main.m */,
+ C0B58A123544A15DA59B13E0 /* Launcher.m */,
+ C0B58A123544A15DA59B13E2 /* Launcher.h */,
+ 50E17745155444B900E97451 /* Launcher.pch */,
+ 50E1773F155444B900E97451 /* Info.plist */,
+ C0B58A123544A15DA59B13CB /* Products */,
+ C0B58A123544A15DA59B13D6 /* Frameworks */,
+ 1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */,
+ 1A564F6D5833A0B9CE6E2839 /* PropertyFileReader.h */,
+ 1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */,
+ 1A564D7CEEAA02F14A6D4F20 /* VMOptionsReader.h */,
+ 1A564A1031F4C91C464C1B75 /* utils.h */,
+ 1A564EEF77B93DBD7FD23161 /* utils.m */,
+ );
+ sourceTree = "<group>";
+ };
+ C0B58A123544A15DA59B13CB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 50E17735155444B900E97451 /* Launcher.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C0B58A123544A15DA59B13D6 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ C0B58A123544A15DA59B13E3 /* JavaVM.framework */,
+ C0B58A123544A15DA59B13DE /* Foundation.framework */,
+ 50E17737155444B900E97451 /* Cocoa.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 50E17734155444B900E97451 /* Launcher */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 50E17751155444BA00E97451 /* Build configuration list for PBXNativeTarget "Launcher" */;
+ buildPhases = (
+ 50E17731155444B900E97451 /* Sources */,
+ 50E17732155444B900E97451 /* Frameworks */,
+ 50E17733155444B900E97451 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Launcher;
+ productName = Launcher;
+ productReference = 50E17735155444B900E97451 /* Launcher.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ C0B58A123544A15DA59B13C8 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0450;
+ };
+ buildConfigurationList = C0B58A123544A15DA59B13C9 /* Build configuration list for PBXProject "MacLauncher" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = C0B58A123544A15DA59B13CA;
+ productRefGroup = C0B58A123544A15DA59B13CB /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 50E17734155444B900E97451 /* Launcher */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 50E17733155444B900E97451 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 50E17731155444B900E97451 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ C0B58A123544A15DA59B13E4 /* main.m in Sources */,
+ C0B58A123544A15DA59B13E5 /* Launcher.m in Sources */,
+ 1A5645DB6F789D018FF4A4AF /* PropertyFileReader.m in Sources */,
+ 1A564BCFE66693BF0B2DD4A9 /* VMOptionsReader.m in Sources */,
+ 1A564C27F0BA05F900F34907 /* utils.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 50E1774F155444BA00E97451 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Launcher.pch;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = Info.plist;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx10.7;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+ 50E17750155444BA00E97451 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Launcher.pch;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = Info.plist;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx10.7;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ C0B58A123544A15DA59B13CC /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ C0B58A123544A15DA59B13CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 50E17751155444BA00E97451 /* Build configuration list for PBXNativeTarget "Launcher" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 50E1774F155444BA00E97451 /* Release */,
+ 50E17750155444BA00E97451 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C0B58A123544A15DA59B13C9 /* Build configuration list for PBXProject "MacLauncher" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C0B58A123544A15DA59B13CC /* Release */,
+ C0B58A123544A15DA59B13CD /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = C0B58A123544A15DA59B13C8 /* Project object */;
+}
diff --git a/native/MacLauncher/PropertyFileReader.h b/native/MacLauncher/PropertyFileReader.h
new file mode 100644
index 0000000..44e46a9
--- /dev/null
+++ b/native/MacLauncher/PropertyFileReader.h
@@ -0,0 +1,13 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface PropertyFileReader : NSObject
++ (NSDictionary *)readFile:(NSString *)path;
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/PropertyFileReader.m b/native/MacLauncher/PropertyFileReader.m
new file mode 100644
index 0000000..43b0682
--- /dev/null
+++ b/native/MacLauncher/PropertyFileReader.m
@@ -0,0 +1,46 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "PropertyFileReader.h"
+#import "utils.h"
+
+
+@implementation PropertyFileReader {
+}
+
++ (void)parseProperty:(NSString *)string to:(NSMutableDictionary *)to {
+ NSRange delimiter = [string rangeOfString:@"="];
+ if (delimiter.length > 0 && delimiter.location + 1 <= string.length) {
+ NSString *key = [string substringToIndex:delimiter.location];
+ NSString *value=[string substringFromIndex:delimiter.location + 1];
+ [to setObject:value forKey:key];
+ }
+}
+
++ (NSDictionary *)readFile:(NSString *)path {
+ NSMutableDictionary *answer = [NSMutableDictionary dictionary];
+
+ NSString *contents = readFile(path);
+
+ if (contents) {
+ NSArray *lines = [contents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+ for (NSString *line in lines) {
+ NSString *trimmedLine = trim(line);
+ if ([trimmedLine length] > 0) {
+ if ([trimmedLine characterAtIndex:0] != '#') {
+ [self parseProperty:trimmedLine to:answer];
+ }
+ }
+ }
+
+ return answer;
+ }
+
+ return nil;
+}
+
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/VMOptionsReader.h b/native/MacLauncher/VMOptionsReader.h
new file mode 100644
index 0000000..bb4dbea
--- /dev/null
+++ b/native/MacLauncher/VMOptionsReader.h
@@ -0,0 +1,13 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface VMOptionsReader : NSObject
++ (NSArray *) readFile: (NSString *)path;
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/VMOptionsReader.m b/native/MacLauncher/VMOptionsReader.m
new file mode 100644
index 0000000..19237cb
--- /dev/null
+++ b/native/MacLauncher/VMOptionsReader.m
@@ -0,0 +1,36 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "VMOptionsReader.h"
+#import "utils.h"
+
+
+@implementation VMOptionsReader {
+
+}
++ (NSArray *)readFile:(NSString *)path {
+ NSMutableArray *answer = [NSMutableArray array];
+
+ NSString *contents = readFile(path);
+ if (contents) {
+ NSArray *lines = [contents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+ for (NSString *line in lines) {
+ NSString *trimmedLine = trim(line);
+ if ([trimmedLine length] > 0) {
+ if ([trimmedLine characterAtIndex:0] != '#') {
+ [answer addObject:trimmedLine];
+ }
+ }
+ }
+
+ return answer;
+ }
+
+ return nil;
+}
+
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/main.m b/native/MacLauncher/main.m
new file mode 100644
index 0000000..c9ef36a
--- /dev/null
+++ b/native/MacLauncher/main.m
@@ -0,0 +1,41 @@
+#import "Launcher.h"
+
+#define FOREVER ((CFTimeInterval) 1e20)
+
+static void timer_empty(CFRunLoopTimerRef timer, void *info) {
+}
+
+static void parkRunLoop() {
+ CFRunLoopTimerRef t = CFRunLoopTimerCreate(kCFAllocatorDefault, FOREVER, (CFTimeInterval)0.0, 0, 0, timer_empty, NULL);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), t, kCFRunLoopDefaultMode);
+ CFRelease(t);
+
+ SInt32 result;
+ do {
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, FOREVER, false);
+ } while (result != kCFRunLoopRunFinished);
+}
+
+static void makeSameStackSize(NSThread *thread) {
+ struct rlimit l;
+ int err = getrlimit(RLIMIT_STACK, &l);
+ if (err == ERR_SUCCESS && l.rlim_cur > 0) {
+ thread.stackSize = (NSUInteger) l.rlim_cur;
+ }
+}
+
+static void launchInNewThread(Launcher *launcher) {
+ NSThread *thread = [[[NSThread alloc] initWithTarget:launcher selector:@selector(launch) object:nil] autorelease];
+ makeSameStackSize(thread);
+ [thread start];
+}
+
+int main(int argc, char *argv[]) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ launchInNewThread([[[Launcher alloc] initWithArgc:argc argv:argv] autorelease]);
+ parkRunLoop();
+
+ [pool release];
+ return 0;
+}
diff --git a/native/MacLauncher/utils.h b/native/MacLauncher/utils.h
new file mode 100644
index 0000000..4c28b35
--- /dev/null
+++ b/native/MacLauncher/utils.h
@@ -0,0 +1,5 @@
+NSString *readFile(NSString *path);
+NSString *trim(NSString *line);
+
+void debugLog(NSString *message);
+BOOL isDebugEnabled();
diff --git a/native/MacLauncher/utils.m b/native/MacLauncher/utils.m
new file mode 100644
index 0000000..63c3922
--- /dev/null
+++ b/native/MacLauncher/utils.m
@@ -0,0 +1,30 @@
+#include "utils.h"
+
+NSString *readFile(NSString *path) {
+ NSError *err = nil;
+ NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
+ if (contents == nil) {
+ debugLog([NSString stringWithFormat:@"Reading at %@ failed, Error is: %@", path, err.localizedDescription]);
+ return nil;
+ }
+
+ debugLog([NSString stringWithFormat: @"Reading at %@ OK", path]);
+
+ return contents;
+}
+
+NSString *trim(NSString *line) {
+ return [line stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" \t"]];
+}
+
+BOOL isDebugEnabled() {
+ return getenv("IDEA_LAUNCHER_DEBUG") != NULL;
+}
+
+void debugLog(NSString *message) {
+ if (isDebugEnabled()) {
+ NSLog(@"%@", message);
+ }
+}
+
+
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher.sln b/native/VistaUpdaterLauncher/VistaUpdaterLauncher.sln
new file mode 100644
index 0000000..b52fb61
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VistaUpdaterLauncher", "VistaUpdaterLauncher\VistaUpdaterLauncher.vcproj", "{05040CA8-09AC-48F2-89BE-1A271F97FE58}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {05040CA8-09AC-48F2-89BE-1A271F97FE58}.Debug|Win32.ActiveCfg = Debug|Win32
+ {05040CA8-09AC-48F2-89BE-1A271F97FE58}.Debug|Win32.Build.0 = Debug|Win32
+ {05040CA8-09AC-48F2-89BE-1A271F97FE58}.Release|Win32.ActiveCfg = Release|Win32
+ {05040CA8-09AC-48F2-89BE-1A271F97FE58}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.cpp b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.cpp
new file mode 100644
index 0000000..b030fe9
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.cpp
@@ -0,0 +1,191 @@
+/*
+* Copyright 2000-2009 JetBrains s.r.o.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "stdafx.h"
+#include <windows.h>
+#include <process.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <conio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static const wchar_t* INSTALL_PARAM = L"install";
+static const wchar_t* SKIP_ELEVATION_PARAM = L"--skip-uac-elevation--";
+
+
+bool isWritable(wchar_t* path)
+{
+ wprintf(L"Trying to create temporary file in\"%s\"\n", path);
+ wchar_t fileName[32768] = L"";
+ wcscat_s(fileName, path);
+ wcscat_s(fileName, L"\\.jetbrains-uac-check");
+ HANDLE file = CreateFile(fileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ DWORD error = GetLastError();
+ if (error == ERROR_ACCESS_DENIED)
+ {
+ // looks like we need to request elevation
+ return false;
+ }
+ else
+ {
+ // there's no need to request elevaion since patcher will most likely fail anyway
+ wprintf(L"Unexpected error when creating temp file: %d\n", error);
+ fflush(stdout);
+ return true;
+ }
+ }
+
+ CloseHandle(file);
+ DeleteFile(fileName);
+ return true;
+}
+
+void appendArgument(wchar_t result[], wchar_t argument[])
+{
+ bool needsQuoting = wcschr(argument, L' ') != NULL;
+ if (needsQuoting)
+ {
+ wcscat_s(result, 32768, L"\"");
+ }
+ wcscat_s(result, 32768, argument);
+ if (needsQuoting)
+ {
+ wcscat_s(result, 32768, L"\"");
+ }
+ wcscat_s(result, 32768, L" ");
+}
+
+bool getElevationPath(int argc, _TCHAR* argv[], wchar_t result[])
+{
+ int start = -1;
+ for (int i = 1; i < argc; i++) {
+ if (wcscmp(argv[i], SKIP_ELEVATION_PARAM) == 0)
+ {
+ wprintf(L"Elevation suppressed\n");
+ fflush(stdout);
+ return false;
+ }
+
+ if (wcscmp(argv[i], INSTALL_PARAM) == 0)
+ {
+ start = i;
+ }
+ else if (start >= 0)
+ {
+ if (i > start + 1)
+ {
+ wcscat_s(result, 32768, L" ");
+ }
+ wcscat_s(result, 32768, argv[i]);
+ }
+ }
+ return start >= 0;
+}
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ wchar_t elevationPath[32768] = L"";
+ HANDLE processHandle = NULL;
+ if (getElevationPath(argc, argv, elevationPath) && !isWritable(elevationPath))
+ {
+ wchar_t paramsLine[32768] = L"";
+ wcscat_s(paramsLine, SKIP_ELEVATION_PARAM);
+
+ for (int i = 1; i < argc; i++)
+ {
+ wcscat_s(paramsLine, L" ");
+ appendArgument(paramsLine, argv[i]);
+ }
+
+ wprintf(L"Creating elevated process: %s %s\n", argv[0], paramsLine);
+ fflush(stdout);
+
+ SHELLEXECUTEINFO shExecInfo;
+ shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
+ shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
+ shExecInfo.hwnd = NULL;
+ shExecInfo.lpVerb = L"runas";
+ shExecInfo.lpFile = argv[0];
+ shExecInfo.lpParameters = paramsLine;
+ shExecInfo.lpDirectory = NULL;
+ shExecInfo.nShow = SW_HIDE;
+ shExecInfo.hInstApp = NULL;
+
+ if (ShellExecuteEx(&shExecInfo) == FALSE)
+ {
+ wprintf(L"ShellExecuteEx() failed with error code %d\n", GetLastError());
+ fflush(stdout);
+ return -1;
+ }
+ processHandle = shExecInfo.hProcess;
+ }
+ else
+ {
+ STARTUPINFO startupInfo = {0};
+ startupInfo.cb = sizeof(startupInfo);
+ PROCESS_INFORMATION processInformation = {0};
+
+ startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+ wchar_t commandLine[32768] = L"";
+
+ for (int i = 1; i < argc; i++) {
+ if (wcscmp(argv[i], SKIP_ELEVATION_PARAM) != 0)
+ {
+ // add only original parameters
+ appendArgument(commandLine, argv[i]);
+ }
+ }
+
+ wprintf(L"Creating new process: %s\n", commandLine);
+ fflush(stdout);
+
+ if (!CreateProcess(
+ NULL, /*LPCTSTR lpApplicationName*/
+ commandLine,/* LPTSTR lpCommandLine*/
+ NULL, /*LPSECURITY_ATTRIBUTES lpProcessAttributes*/
+ NULL, /*LPSECURITY_ATTRIBUTES lpThreadAttributes*/
+ TRUE, /*BOOL bInheritHandles,*/
+ 0, /*DWORD dwCreationFlags*/
+ NULL, /*LPVOID lpEnvironment*/
+ NULL, /*LPCTSTR lpCurrentDirectory*/
+ &startupInfo, /*LPSTARTUPINFO lpStartupInfo*/
+ &processInformation /*LPPROCESS_INFORMATION lpProcessInformation*/))
+ {
+ wprintf(L"Cannot create process: %d\n", GetLastError());
+ return -1;
+ }
+ processHandle = processInformation.hProcess;
+ }
+
+ WaitForSingleObject(processHandle, INFINITE);
+
+ DWORD exitCode = 0;
+ if (!GetExitCodeProcess(processHandle, &exitCode))
+ {
+ wprintf(L"Cannot retrieve process exit code: %d\n", GetLastError());
+ exitCode = -1;
+ }
+ CloseHandle(processHandle);
+
+ return exitCode;
+}
+
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.rc b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.rc
new file mode 100644
index 0000000..ec22af0
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.rc
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "windows.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""windows.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "041904b0"
+ BEGIN
+ VALUE "CompanyName", "JetBrains, Inc."
+ VALUE "FileDescription", "JetBrains Updater Launcher"
+ VALUE "FileVersion", "1, 0, 0, 1"
+ VALUE "InternalName", "vistalauncher"
+ VALUE "LegalCopyright", "Copyright (C) 2009-2011 JetBrains, Inc."
+ VALUE "OriginalFilename", "vistalauncher.exe"
+ VALUE "ProductName", "JetBrains Updater Launcher"
+ VALUE "ProductVersion", "1, 0, 0, 1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x419, 1200
+ END
+END
+
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.vcproj b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.vcproj
new file mode 100644
index 0000000..a62b1d2
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/VistaUpdaterLauncher.vcproj
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="VistaUpdaterLauncher"
+ ProjectGUID="{05040CA8-09AC-48F2-89BE-1A271F97FE58}"
+ RootNamespace="VistaUpdaterLauncher"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ UACExecutionLevel="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ UACExecutionLevel="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\VistaUpdaterLauncher.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\targetver.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\VistaUpdaterLauncher.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher/resource.h b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/resource.h
new file mode 100644
index 0000000..f678b50
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by VistaUpdaterLauncher.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher/stdafx.cpp b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/stdafx.cpp
new file mode 100644
index 0000000..ef12a27
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// VistaUpdaterLauncher.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher/stdafx.h b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/stdafx.h
new file mode 100644
index 0000000..b005a83
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/native/VistaUpdaterLauncher/VistaUpdaterLauncher/targetver.h b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/targetver.h
new file mode 100644
index 0000000..6fe8eb7
--- /dev/null
+++ b/native/VistaUpdaterLauncher/VistaUpdaterLauncher/targetver.h
@@ -0,0 +1,13 @@
+#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
diff --git a/native/breakgen/AppMain.c b/native/breakgen/AppMain.c
new file mode 100644
index 0000000..15b2831
--- /dev/null
+++ b/native/breakgen/AppMain.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#if defined(WIN32)
+#include <windows.h>
+#else
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int isKernel26OrHigher();
+#endif
+
+JNIEXPORT void JNICALL Java_com_intellij_rt_execution_application_AppMain_triggerControlBreak
+ (JNIEnv *env, jclass clazz) {
+#if defined(WIN32)
+ GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
+#else
+ if (isKernel26OrHigher()) {
+ kill (getpid(), SIGQUIT);
+ } else {
+ int ppid = getppid();
+ char buffer[1024];
+ sprintf(buffer, "/proc/%d/status", ppid);
+ FILE * fp;
+ if ( (fp = fopen(buffer, "r")) != NULL )
+ {
+ char s[124];
+ char * ppid_name = "PPid:";
+ while (fscanf (fp, "%s\n", s) > 0) {
+ if (strcmp(s, ppid_name) == 0) {
+ int pppid;
+ fscanf(fp, "%d", &pppid);
+ kill (pppid, SIGQUIT);
+ break;
+ }
+ }
+
+ fclose (fp);
+ }
+ }
+#endif
+}
+
+#ifndef WIN32
+
+int isKernel26OrHigher() {
+ char buffer[1024];
+ FILE * fp;
+ if ( (fp = fopen("/proc/version", "r")) != NULL )
+ {
+ int major;
+ int minor;
+ fscanf(fp, "Linux version %d.%d", &major, &minor);
+ fclose (fp);
+ if (major < 2) return 0;
+ if (major == 2) return minor >= 6;
+ return 1;
+ }
+
+ return 0;
+}
+#endif
\ No newline at end of file
diff --git a/native/breakgen/breakgen.sln b/native/breakgen/breakgen.sln
new file mode 100644
index 0000000..385ab27
--- /dev/null
+++ b/native/breakgen/breakgen.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "breakgen", "breakgen.vcproj", "{AE14C87F-E99B-4363-BE34-917FAF98258F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AE14C87F-E99B-4363-BE34-917FAF98258F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {AE14C87F-E99B-4363-BE34-917FAF98258F}.Debug|Win32.Build.0 = Debug|Win32
+ {AE14C87F-E99B-4363-BE34-917FAF98258F}.Debug|x64.ActiveCfg = Debug|x64
+ {AE14C87F-E99B-4363-BE34-917FAF98258F}.Release|Win32.ActiveCfg = Release|Win32
+ {AE14C87F-E99B-4363-BE34-917FAF98258F}.Release|Win32.Build.0 = Release|Win32
+ {AE14C87F-E99B-4363-BE34-917FAF98258F}.Release|x64.ActiveCfg = Release|x64
+ {AE14C87F-E99B-4363-BE34-917FAF98258F}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/native/breakgen/breakgen.vcproj b/native/breakgen/breakgen.vcproj
new file mode 100644
index 0000000..4f02b6a
--- /dev/null
+++ b/native/breakgen/breakgen.vcproj
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="breakgen"
+ ProjectGUID="{AE14C87F-E99B-4363-BE34-917FAF98258F}"
+ RootNamespace="breakgen"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;BREAKGEN_EXPORTS;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="C:\Java\jdk1.6.0_14\include;C:\Java\jdk1.6.0_14\include\win32"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;BREAKGEN_EXPORTS;"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;BREAKGEN_EXPORTS;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="C:\Java\jdk1.6.0_14\include;C:\Java\jdk1.6.0_14\include\win32"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;BREAKGEN_EXPORTS;"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\AppMain.c"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/native/breakgen/make.sh b/native/breakgen/make.sh
new file mode 100644
index 0000000..5ef8c5b
--- /dev/null
+++ b/native/breakgen/make.sh
@@ -0,0 +1 @@
+gcc -I/opt/jdk1.6.0_16_x64/include/ -I/opt/jdk1.6.0_16_x64/include/linux/ AppMain.c -shared -fPIC -o libbreakgen64.so
diff --git a/native/fileWatcher/fileWatcher3.cpp b/native/fileWatcher/fileWatcher3.cpp
new file mode 100644
index 0000000..9a0b3d8
--- /dev/null
+++ b/native/fileWatcher/fileWatcher3.cpp
@@ -0,0 +1,558 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+
+struct WatchRootInfo {
+ char driveLetter;
+ HANDLE hThread;
+ HANDLE hStopEvent;
+ bool bInitialized;
+ bool bUsed;
+ bool bFailed;
+};
+
+struct WatchRoot {
+ char *path;
+ WatchRoot *next;
+};
+
+const int ROOT_COUNT = 26;
+
+WatchRootInfo watchRootInfos[ROOT_COUNT];
+
+WatchRoot *firstWatchRoot = NULL;
+
+CRITICAL_SECTION csOutput;
+
+void NormalizeSlashes(char *path, char slash)
+{
+ for(char *p=path; *p; p++)
+ if (*p == '\\' || *p == '/')
+ *p = slash;
+}
+
+// -- Watchable root checks ---------------------------------------------------
+
+bool IsNetworkDrive(const char *name)
+{
+ const int BUF_SIZE = 1024;
+ char buffer[BUF_SIZE];
+ UNIVERSAL_NAME_INFO* uni = (UNIVERSAL_NAME_INFO*) buffer;
+ DWORD size = BUF_SIZE;
+
+ DWORD result = WNetGetUniversalNameA(
+ name, // path for network resource
+ UNIVERSAL_NAME_INFO_LEVEL, // level of information
+ buffer, // name buffer
+ &size // size of buffer
+ );
+
+ return result == NO_ERROR;
+}
+
+bool IsUnwatchableFS(const char *path)
+{
+ char volumeName[MAX_PATH];
+ char fsName[MAX_PATH];
+ DWORD fsFlags;
+ DWORD maxComponentLength;
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+ if (!GetVolumeInformationA(path, volumeName, MAX_PATH-1, NULL, &maxComponentLength, &fsFlags, fsName, MAX_PATH-1))
+ return false;
+ if (strcmp(fsName, "NTFS") && strcmp(fsName, "FAT") && strcmp(fsName, "FAT32"))
+ return true;
+
+ if (!strcmp(fsName, "NTFS") && maxComponentLength != 255 && !(fsFlags & FILE_SUPPORTS_REPARSE_POINTS))
+ {
+ // SAMBA reports itself as NTFS
+ return true;
+ }
+
+ return false;
+}
+
+bool IsWatchable(const char *path)
+{
+ if (IsNetworkDrive(path))
+ return false;
+ if (IsUnwatchableFS(path))
+ return false;
+ return true;
+}
+
+// -- Substed drive checks ----------------------------------------------------
+
+void PrintRemapForSubstDrive(char driveLetter)
+{
+ const int BUF_SIZE = 1024;
+ char targetPath[BUF_SIZE];
+
+ char rootPath[8];
+ sprintf_s(rootPath, 8, "%c:", driveLetter);
+
+ DWORD result = QueryDosDeviceA(rootPath, targetPath, BUF_SIZE);
+ if (result == 0) {
+ return;
+ }
+ else
+ {
+ if (targetPath[0] == '\\' && targetPath[1] == '?' && targetPath[2] == '?' && targetPath[3] == '\\')
+ {
+ // example path: \??\C:\jetbrains\idea
+ NormalizeSlashes(targetPath, '/');
+ printf("%c:\n%s\n", driveLetter, targetPath+4);
+ }
+ }
+}
+
+void PrintRemapForSubstDrives()
+{
+ for(int i=0; i<ROOT_COUNT; i++)
+ {
+ if (watchRootInfos [i].bUsed)
+ {
+ PrintRemapForSubstDrive(watchRootInfos [i].driveLetter);
+ }
+ }
+}
+
+// -- Mount point enumeration -------------------------------------------------
+
+const int BUFSIZE = 1024;
+
+void PrintDirectoryReparsePoint(const char *path)
+{
+ int size = strlen(path)+2;
+ char *directory = (char *) malloc(size);
+ strcpy_s(directory, size, path);
+ NormalizeSlashes(directory, '\\');
+ if (directory [strlen(directory)-1] != '\\')
+ strcat_s(directory, size, "\\");
+
+ char volumeName[_MAX_PATH];
+ int rc = GetVolumeNameForVolumeMountPointA(directory, volumeName, sizeof(volumeName));
+ if (rc)
+ {
+ char volumePathNames[_MAX_PATH];
+ DWORD returnLength;
+ rc = GetVolumePathNamesForVolumeNameA(volumeName, volumePathNames, sizeof(volumePathNames), &returnLength);
+ if (rc)
+ {
+ char *p = volumePathNames;
+ while(*p)
+ {
+ if (_stricmp(p, directory)) // if it's not the path we've already found
+ {
+ NormalizeSlashes(directory, '/');
+ NormalizeSlashes(p, '/');
+ puts(directory);
+ puts(p);
+ }
+ p += strlen(p)+1;
+ }
+ }
+ }
+ free(directory);
+}
+
+bool PrintMountPointsForVolume(HANDLE hVol, const char* volumePath, char *Buf)
+{
+ HANDLE hPt; // handle for mount point scan
+ char Path[BUFSIZE]; // string buffer for mount points
+ DWORD dwSysFlags; // flags that describe the file system
+ char FileSysNameBuf[BUFSIZE];
+
+ // Is this volume NTFS?
+ GetVolumeInformationA(Buf, NULL, 0, NULL, NULL, &dwSysFlags, FileSysNameBuf, BUFSIZE);
+
+ // Detect support for reparse points, and therefore for volume
+ // mount points, which are implemented using reparse points.
+
+ if (! (dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS)) {
+ return true;
+ }
+
+ // Start processing mount points on this volume.
+ hPt = FindFirstVolumeMountPointA(
+ Buf, // root path of volume to be scanned
+ Path, // pointer to output string
+ BUFSIZE // size of output buffer
+ );
+
+ // Shall we error out?
+ if (hPt == INVALID_HANDLE_VALUE) {
+ return GetLastError() != ERROR_ACCESS_DENIED;
+ }
+
+ // Process the volume mount point.
+ char *buf = new char[MAX_PATH];
+ do {
+ strcpy_s(buf, MAX_PATH, volumePath);
+ strcat_s(buf, MAX_PATH, Path);
+ PrintDirectoryReparsePoint(buf);
+ } while (FindNextVolumeMountPointA(hPt, Path, BUFSIZE));
+
+ FindVolumeMountPointClose(hPt);
+ return true;
+}
+
+bool PrintMountPoints(const char *path)
+{
+ char volumeUniqueName[128];
+ BOOL res = GetVolumeNameForVolumeMountPointA(path, volumeUniqueName, 128);
+ if (!res) {
+ return false;
+ }
+
+ char buf[BUFSIZE]; // buffer for unique volume identifiers
+ HANDLE hVol; // handle for the volume scan
+
+ // Open a scan for volumes.
+ hVol = FindFirstVolumeA(buf, BUFSIZE );
+
+ // Shall we error out?
+ if (hVol == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ bool success = true;
+ do {
+ if (!strcmp(buf, volumeUniqueName)) {
+ success = PrintMountPointsForVolume(hVol, path, buf);
+ if (!success) break;
+ }
+ } while (FindNextVolumeA(hVol, buf, BUFSIZE));
+
+ FindVolumeClose(hVol);
+ return success;
+}
+
+// -- Searching for mount points in watch roots (fallback) --------------------
+
+void PrintDirectoryReparsePoints(const char *path)
+{
+ char *const buf = _strdup(path);
+ while(strchr(buf, '/'))
+ {
+ DWORD attributes = GetFileAttributesA(buf);
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ break;
+ if (attributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ {
+ PrintDirectoryReparsePoint(buf);
+ }
+ char *pSlash = strrchr(buf, '/');
+ if (pSlash)
+ {
+ *pSlash = '\0';
+ }
+ }
+ free(buf);
+}
+
+// This is called if we got an ERROR_ACCESS_DENIED when trying to enumerate all mount points for volume.
+// In this case, we walk the directory tree up from each watch root, and look at each parent directory
+// to check whether it's a reparse point.
+void PrintWatchRootReparsePoints()
+{
+ WatchRoot *pWatchRoot = firstWatchRoot;
+ while(pWatchRoot)
+ {
+ PrintDirectoryReparsePoints(pWatchRoot->path);
+ pWatchRoot = pWatchRoot->next;
+ }
+}
+
+// -- Watcher thread ----------------------------------------------------------
+
+void PrintChangeInfo(char *rootPath, FILE_NOTIFY_INFORMATION *info)
+{
+ char FileNameBuffer[_MAX_PATH];
+ int converted = WideCharToMultiByte(CP_ACP, 0, info->FileName, info->FileNameLength/sizeof(WCHAR), FileNameBuffer, _MAX_PATH-1, NULL, NULL);
+ FileNameBuffer[converted] = '\0';
+ char *command;
+ if (info->Action == FILE_ACTION_ADDED || info->Action == FILE_ACTION_RENAMED_OLD_NAME)
+ {
+ command = "CREATE";
+ }
+ else if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME)
+ {
+ command = "DELETE";
+ }
+ else if (info->Action == FILE_ACTION_MODIFIED)
+ {
+ command = "CHANGE";
+ }
+ else
+ {
+ return; // unknown command
+ }
+
+ EnterCriticalSection(&csOutput);
+ puts(command);
+ printf("%s", rootPath);
+ puts(FileNameBuffer);
+ fflush(stdout);
+ LeaveCriticalSection(&csOutput);
+}
+
+void PrintEverythingChangedUnderRoot(char *rootPath)
+{
+ EnterCriticalSection(&csOutput);
+ puts("RECDIRTY");
+ puts(rootPath);
+ fflush(stdout);
+ LeaveCriticalSection(&csOutput);
+}
+
+DWORD WINAPI WatcherThread(void *param)
+{
+ WatchRootInfo *info = (WatchRootInfo *) param;
+
+ OVERLAPPED overlapped;
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ char rootPath[8];
+ sprintf_s(rootPath, 8, "%c:\\", info->driveLetter);
+ HANDLE hRootDir = CreateFileA(rootPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
+
+ int buffer_size = 10240;
+ char *buffer = new char[buffer_size];
+
+ HANDLE handles [2];
+ handles [0] = info->hStopEvent;
+ handles [1] = overlapped.hEvent;
+ while(true)
+ {
+ int rcDir = ReadDirectoryChangesW(hRootDir, buffer, buffer_size, TRUE,
+ FILE_NOTIFY_CHANGE_FILE_NAME |
+ FILE_NOTIFY_CHANGE_DIR_NAME |
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_SIZE |
+ FILE_NOTIFY_CHANGE_LAST_WRITE,
+ NULL,
+ &overlapped,
+ NULL);
+ if (rcDir == 0)
+ {
+ info->bFailed = true;
+ break;
+ }
+
+ int rc = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+ if (rc == WAIT_OBJECT_0)
+ {
+ break;
+ }
+ if (rc == WAIT_OBJECT_0+1)
+ {
+ DWORD dwBytesReturned;
+ if(!GetOverlappedResult(hRootDir, &overlapped, &dwBytesReturned, FALSE))
+ {
+ info->bFailed = true;
+ break;
+ }
+
+ if (dwBytesReturned == 0)
+ {
+ // don't send dirty too much, everything is changed anyway
+ if (WaitForSingleObject(info->hStopEvent, 500) == WAIT_OBJECT_0)
+ break;
+
+ // Got a buffer overflow => current changes lost => send RECDIRTY on root
+ PrintEverythingChangedUnderRoot(rootPath);
+ } else {
+ FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *) buffer;
+ while(true)
+ {
+ PrintChangeInfo(rootPath, info);
+ if (!info->NextEntryOffset)
+ break;
+ info = (FILE_NOTIFY_INFORMATION *) ((char *) info + info->NextEntryOffset);
+ }
+ }
+ }
+ }
+ CloseHandle(overlapped.hEvent);
+ CloseHandle(hRootDir);
+ delete[] buffer;
+ return 0;
+}
+
+// -- Roots update ------------------------------------------------------------
+
+void MarkAllRootsUnused()
+{
+ for(int i=0; i<ROOT_COUNT; i++)
+ {
+ watchRootInfos [i].bUsed = false;
+ }
+}
+
+void StartRoot(WatchRootInfo *info)
+{
+ info->hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ info->hThread = CreateThread(NULL, 0, &WatcherThread, info, 0, NULL);
+ info->bInitialized = true;
+}
+
+void StopRoot(WatchRootInfo *info)
+{
+ SetEvent(info->hStopEvent);
+ WaitForSingleObject(info->hThread, INFINITE);
+ CloseHandle(info->hThread);
+ CloseHandle(info->hStopEvent);
+ info->bInitialized = false;
+}
+
+void UpdateRoots()
+{
+ char infoBuffer [256];
+ strcpy_s(infoBuffer, "UNWATCHEABLE\n");
+ for(int i=0; i<ROOT_COUNT; i++)
+ {
+ if (watchRootInfos [i].bInitialized && (!watchRootInfos [i].bUsed || watchRootInfos [i].bFailed))
+ {
+ StopRoot(&watchRootInfos [i]);
+ watchRootInfos [i].bFailed = false;
+ }
+ if (watchRootInfos [i].bUsed)
+ {
+ char rootPath[8];
+ sprintf_s(rootPath, 8, "%c:\\", watchRootInfos [i].driveLetter);
+ if (!IsWatchable(rootPath))
+ {
+ strcat_s(infoBuffer, rootPath);
+ strcat_s(infoBuffer, "\n");
+ continue;
+ }
+ if (!watchRootInfos [i].bInitialized)
+ {
+ StartRoot(&watchRootInfos [i]);
+ }
+ }
+ }
+ EnterCriticalSection(&csOutput);
+ fprintf(stdout, "%s", infoBuffer);
+ puts("#\nREMAP");
+ PrintRemapForSubstDrives();
+ bool printedMountPoints = true;
+ for(int i=0; i<ROOT_COUNT; i++)
+ {
+ if (watchRootInfos [i].bUsed)
+ {
+ char rootPath[8];
+ sprintf_s(rootPath, 8, "%c:\\", watchRootInfos [i].driveLetter);
+ if (!PrintMountPoints(rootPath))
+ printedMountPoints = false;
+ }
+ }
+ if (!printedMountPoints)
+ {
+ PrintWatchRootReparsePoints();
+ }
+ puts("#");
+ fflush(stdout);
+ LeaveCriticalSection(&csOutput);
+}
+
+void AddWatchRoot(const char *path)
+{
+ WatchRoot *watchRoot = (WatchRoot *) malloc(sizeof(WatchRoot));
+ watchRoot->next = NULL;
+ watchRoot->path = _strdup(path);
+ watchRoot->next = firstWatchRoot;
+ firstWatchRoot = watchRoot;
+}
+
+void FreeWatchRootsList()
+{
+ WatchRoot *pWatchRoot = firstWatchRoot;
+ WatchRoot *pNext;
+ while(pWatchRoot)
+ {
+ pNext = pWatchRoot->next;
+ free(pWatchRoot->path);
+ free(pWatchRoot);
+ pWatchRoot=pNext;
+ }
+ firstWatchRoot = NULL;
+}
+
+// -- Main - filewatcher protocol ---------------------------------------------
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ InitializeCriticalSection(&csOutput);
+
+ for(int i=0; i<26; i++)
+ {
+ watchRootInfos [i].driveLetter = 'A' + i;
+ watchRootInfos [i].bInitialized = false;
+ watchRootInfos [i].bUsed = false;
+ }
+
+ char buffer[8192];
+ while(true)
+ {
+ if (!gets_s(buffer, sizeof(buffer)-1))
+ break;
+
+ if (!strcmp(buffer, "ROOTS"))
+ {
+ MarkAllRootsUnused();
+ FreeWatchRootsList();
+ bool failed = false;
+ while(true)
+ {
+ if (!gets_s(buffer, sizeof(buffer)-1))
+ {
+ failed = true;
+ break;
+ }
+ if (buffer [0] == '#')
+ break;
+ int driveLetterPos = 0;
+ char *pDriveLetter = buffer;
+ if (*pDriveLetter == '|')
+ pDriveLetter++;
+
+ AddWatchRoot(pDriveLetter);
+
+ _strupr_s(buffer, sizeof(buffer)-1);
+ char driveLetter = *pDriveLetter;
+ if (driveLetter >= 'A' && driveLetter <= 'Z')
+ {
+ watchRootInfos [driveLetter-'A'].bUsed = true;
+ }
+ }
+ if (failed)
+ break;
+
+ UpdateRoots();
+ }
+ if (!strcmp(buffer, "EXIT"))
+ break;
+ }
+
+ MarkAllRootsUnused();
+ UpdateRoots();
+
+ DeleteCriticalSection(&csOutput);
+}
diff --git a/native/fileWatcher/fileWatcher3.rc b/native/fileWatcher/fileWatcher3.rc
new file mode 100644
index 0000000..a2ed61e
--- /dev/null
+++ b/native/fileWatcher/fileWatcher3.rc
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "041904b0"
+ BEGIN
+ VALUE "CompanyName", "JetBrains, Inc."
+ VALUE "FileDescription", "File System Notification Processor"
+ VALUE "FileVersion", "1, 0, 0, 1"
+ VALUE "InternalName", "fsnotifier"
+ VALUE "LegalCopyright", "Copyright (C) 2008-09 JetBrains, Inc."
+ VALUE "OriginalFilename", "fsnotifier.exe"
+ VALUE "ProductName", "IntelliJ IDEA"
+ VALUE "ProductVersion", "1, 0, 0, 1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x419, 1200
+ END
+END
+
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/native/fileWatcher/fileWatcher3.sln b/native/fileWatcher/fileWatcher3.sln
new file mode 100644
index 0000000..821f143
--- /dev/null
+++ b/native/fileWatcher/fileWatcher3.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fileWatcher3", "fileWatcher3.vcproj", "{0EF2C2DB-0E16-4BC3-9927-9C51AF00EB57}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0EF2C2DB-0E16-4BC3-9927-9C51AF00EB57}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0EF2C2DB-0E16-4BC3-9927-9C51AF00EB57}.Debug|Win32.Build.0 = Debug|Win32
+ {0EF2C2DB-0E16-4BC3-9927-9C51AF00EB57}.Release|Win32.ActiveCfg = Release|Win32
+ {0EF2C2DB-0E16-4BC3-9927-9C51AF00EB57}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/native/fileWatcher/fileWatcher3.vcproj b/native/fileWatcher/fileWatcher3.vcproj
new file mode 100644
index 0000000..14ec211
--- /dev/null
+++ b/native/fileWatcher/fileWatcher3.vcproj
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="fileWatcher3"
+ ProjectGUID="{0EF2C2DB-0E16-4BC3-9927-9C51AF00EB57}"
+ RootNamespace="fileWatcher3"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="mpr.lib"
+ OutputFile="$(OutDir)\fsnotifier.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="mpr.lib"
+ OutputFile="$(OutDir)\fsnotifier.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\fileWatcher3.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\targetver.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\fileWatcher3.rc"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/native/fileWatcher/resource.h b/native/fileWatcher/resource.h
new file mode 100644
index 0000000..08209cb
--- /dev/null
+++ b/native/fileWatcher/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by fileWatcher3.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/native/fileWatcher/stdafx.cpp b/native/fileWatcher/stdafx.cpp
new file mode 100644
index 0000000..4303745
--- /dev/null
+++ b/native/fileWatcher/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// fileWatcher3.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/native/fileWatcher/stdafx.h b/native/fileWatcher/stdafx.h
new file mode 100644
index 0000000..624e518
--- /dev/null
+++ b/native/fileWatcher/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
+#include <process.h>
+
+// TODO: reference additional headers your program requires here
diff --git a/native/fileWatcher/targetver.h b/native/fileWatcher/targetver.h
new file mode 100644
index 0000000..7021c2a
--- /dev/null
+++ b/native/fileWatcher/targetver.h
@@ -0,0 +1,13 @@
+#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
diff --git a/native/focusKiller/HookImportFunction.cpp b/native/focusKiller/HookImportFunction.cpp
new file mode 100644
index 0000000..ab11935
--- /dev/null
+++ b/native/focusKiller/HookImportFunction.cpp
@@ -0,0 +1,338 @@
+/*
+Module : HookImportFunction.cpp
+Purpose: Defines the implementation for code to hook a call to any imported Win32 SDK
+Created: PJN / 23-10-1999
+History: PJN / 01-01-2001 1. Now includes copyright message in the source code and documentation.
+ 2. Fixed an access violation in where I was getting the name of the import
+ function but not checking for failure.
+ 3. Fixed a compiler error where I was incorrectly casting to a PDWORD instead
+ of a DWORD
+ PJN / 20-04-2002 1. Fixed a potential infinite loop in HookImportFunctionByName. Thanks to
+ David Defoort for spotting this problem.
+
+Copyright (c) 1996 - 2002 by PJ Naughter. (Web: www.naughter.com, Email: pjna@naughter.com)
+
+All rights reserved.
+
+Copyright / Usage Details:
+
+You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
+when your product is released in binary form. You are allowed to modify the source code in any way you want
+except you cannot modify the copyright details at the top of each module. If you want to distribute source
+code with your application, then you are only allowed to distribute versions released by the author. This is
+to maintain a single distribution point for the source code.
+
+*/
+
+
+////////////////// Includes ////////////////////////////////////
+
+#include <windows.h>
+#include "HookImportFunction.h"
+
+#define ASSERT(e)
+#define VERIFY(e) e
+#define TRACE0(s) OutputDebugString(s)
+#define _T(s) s
+
+////////////////// Defines / Locals ////////////////////////////
+
+#ifdef _DEBUG
+ #define new DEBUG_NEW
+ #undef THIS_FILE
+ static char THIS_FILE[] = __FILE__;
+#endif
+
+#define MakePtr(cast, ptr, AddValue) (cast)((DWORD)(ptr)+(DWORD)(AddValue))
+
+BOOL IsNT();
+
+
+
+////////////////// Implementation //////////////////////////////
+
+BOOL HookImportFunctionsByName(HMODULE hModule, LPCSTR szImportMod, UINT uiCount,
+ LPHOOKFUNCDESC paHookArray, PROC* paOrigFuncs, UINT* puiHooked)
+{
+ // Double check the parameters.
+ ASSERT(szImportMod);
+ ASSERT(uiCount);
+ ASSERT(!IsBadReadPtr(paHookArray, sizeof(HOOKFUNCDESC)*uiCount));
+
+#ifdef _DEBUG
+ if (paOrigFuncs)
+ ASSERT(!IsBadWritePtr(paOrigFuncs, sizeof(PROC)*uiCount));
+ if (puiHooked)
+ ASSERT(!IsBadWritePtr(puiHooked, sizeof(UINT)));
+
+ //Check each function name in the hook array.
+ for (UINT i = 0; i<uiCount; i++)
+ {
+ ASSERT(paHookArray[i].szFunc);
+ ASSERT(*paHookArray[i].szFunc != _T('\0'));
+
+ //If the proc is not NULL, then it is checked.
+ if (paHookArray[i].pProc)
+ ASSERT(!IsBadCodePtr(paHookArray[i].pProc));
+ }
+#endif
+
+ //Do the parameter validation for real.
+ if (uiCount == 0 || szImportMod == NULL || IsBadReadPtr(paHookArray, sizeof(HOOKFUNCDESC)* uiCount))
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_INVALID_ADDRESS, SLE_ERROR);
+ return FALSE;
+ }
+
+ if (paOrigFuncs && IsBadWritePtr(paOrigFuncs, sizeof(PROC)*uiCount))
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_INVALID_ADDRESS, SLE_ERROR);
+ return FALSE;
+ }
+
+ if (puiHooked && IsBadWritePtr(puiHooked, sizeof(UINT)))
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_INVALID_ADDRESS, SLE_ERROR );
+ return FALSE;
+ }
+
+ //Is this a system DLL, which Windows95 will not let you patch
+ //since it is above the 2GB line?
+ if (!IsNT() && ((DWORD)hModule >= 0x80000000))
+ {
+ #ifdef _DEBUG
+ CString sMsg;
+ sMsg.Format(_T("Could not hook module %x because we are on Win9x and it is in shared memory\n"), hModule);
+ OutputDebugString(sMsg);
+ #endif
+ SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);
+ return FALSE;
+ }
+
+ //TODO TODO
+ // Should each item in the hook array be checked in release builds?
+
+ if (puiHooked)
+ *puiHooked = 0; //Set the number of functions hooked to zero.
+
+ //Get the specific import descriptor.
+ PIMAGE_IMPORT_DESCRIPTOR pImportDesc = GetNamedImportDescriptor(hModule, szImportMod);
+ if (NULL == pImportDesc)
+ return FALSE; // The requested module was not imported.
+
+ HINSTANCE hImportMod = GetModuleHandle(szImportMod);
+ if (NULL == hImportMod)
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_HOOK_NEEDS_HMOD, SLE_ERROR);
+ return FALSE; // The requested module was not available.
+ }
+
+ //Set all the values in paOrigFuncs to NULL.
+ if (NULL != paOrigFuncs)
+ memset(paOrigFuncs, NULL, sizeof(PROC)*uiCount);
+
+ //Get the original thunk information for this DLL. I cannot use
+ // the thunk information stored in the pImportDesc->FirstThunk
+ // because the that is the array that the loader
+ // has already bashed to fix up all the imports.
+ // This pointer gives us acess to the function names.
+ PIMAGE_THUNK_DATA pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->OriginalFirstThunk);
+
+ //Get the array pointed to by the pImportDesc->FirstThunk.
+ // This is where I will do the actual bash.
+ PIMAGE_THUNK_DATA pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->FirstThunk);
+
+ //Loop through and look for the one that matches the name.
+ for (; NULL != pOrigThunk->u1.Function;
+ // Increment both tables.
+ pOrigThunk++, pRealThunk++)
+ {
+ //Only look at those that are imported by name, not ordinal.
+ if (IMAGE_ORDINAL_FLAG == (IMAGE_ORDINAL_FLAG & pOrigThunk->u1.Ordinal))
+ continue;
+
+ //Look get the name of this imported function.
+ PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pOrigThunk->u1.AddressOfData);
+
+ if (IsBadReadPtr(pByName, MAX_PATH+4))
+ {
+ SetLastErrorEx(ERROR_INVALID_ADDRESS, SLE_ERROR);
+ continue;
+ }
+
+ //If the name starts with NULL, then just skip to next.
+ if (_T('\0') == pByName->Name[0])
+ continue;
+
+ //Determines if we do the hook.
+ BOOL bDoHook = FALSE;
+
+ //TODO {
+ // Might want to consider bsearch here.
+ //TODO }
+ //See if the particular function name is in the import
+ // list. It might be good to consider requiring the
+ // paHookArray to be in sorted order so bsearch could be
+ // used so the lookup will be faster. However, the size of
+ // uiCount coming into this function should be rather small
+ // but it is called for each function imported by szImportMod.
+ for (UINT i = 0; i<uiCount; i++)
+ {
+ if ((paHookArray[i].szFunc[0] == pByName->Name[0]) &&
+ (strcmpi(paHookArray[i].szFunc, (char*)pByName->Name) == 0))
+ {
+ //If the proc is NULL, kick out, otherwise
+ // go ahead and hook it.
+ if (paHookArray[i].pProc)
+ bDoHook = TRUE;
+ break;
+ }
+ }
+
+ if (FALSE == bDoHook)
+ continue;
+
+ // I found it. Now I need to change the protection to
+ // writable before I do the blast. Note that I am now
+ // blasting into the real thunk area!
+ MEMORY_BASIC_INFORMATION mbi_thunk;
+ VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
+ VERIFY(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect));
+
+ // Get fast/simple pointer
+ PROC* pFunction = (PROC*) &(pRealThunk->u1.Function);
+ if (*pFunction == paHookArray[i].pProc)
+ {
+ SetLastErrorEx(ERROR_ALREADY_INITIALIZED, SLE_ERROR);
+ return FALSE;
+ }
+ if (IsBadCodePtr(*pFunction))
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_INVALID_ADDRESS, SLE_ERROR);
+ return FALSE;
+ }
+ //Save the original address if requested.
+ if (NULL != paOrigFuncs)
+ {
+ if ((DWORD)(*pFunction) < (DWORD)hImportMod && ((DWORD)(0x80000000) > (DWORD)hImportMod))
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_INVALID_ADDRESS, SLE_ERROR);
+ return FALSE;
+ }
+ if (*pFunction != paOrigFuncs[i])
+ {
+ if (NULL != paOrigFuncs[i])
+ {
+ if (paHookArray[i].pProc != paOrigFuncs[i])
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_INVALID_ADDRESS, SLE_ERROR);
+ return FALSE;
+ }
+ }
+ paOrigFuncs[i] = * pFunction;
+ }
+ }
+ //Do the actual hook.
+ *pFunction = paHookArray[i].pProc;
+
+ //Increment the total number hooked.
+ if (puiHooked)
+ *puiHooked += 1;
+
+ //Change the protection back to what it was before I blasted.
+ DWORD dwOldProtect;
+ VERIFY(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect));
+ }
+ //All OK, JumpMaster!
+ SetLastError(ERROR_SUCCESS);
+ return TRUE;
+}
+
+PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportMod)
+{
+ //Always check parameters.
+ ASSERT(szImportMod);
+ ASSERT(hModule);
+ if ((szImportMod == NULL) || (hModule == NULL))
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
+ return NULL;
+ }
+
+ //Get the Dos header.
+ PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule;
+
+ // Is this the MZ header?
+ if (IsBadReadPtr(pDOSHeader, sizeof(IMAGE_DOS_HEADER)) || (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE))
+ {
+ #ifdef _DEBUG
+ CString sMsg;
+ sMsg.Format(_T("Could not find the MZ Header for %x\n"), hModule);
+ OutputDebugString(sMsg);
+ #endif
+ SetLastErrorEx( ERROR_BAD_EXE_FORMAT, SLE_ERROR);
+ return NULL;
+ }
+
+ // Get the PE header.
+ PIMAGE_NT_HEADERS pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
+
+ //Is this a real PE image?
+ if (IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) || (pNTHeader->Signature != IMAGE_NT_SIGNATURE))
+ {
+ ASSERT(FALSE);
+ SetLastErrorEx( ERROR_INVALID_EXE_SIGNATURE, SLE_ERROR);
+ return NULL;
+ }
+
+ //If there is no imports section, leave now.
+ if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
+ return NULL;
+
+ // Get the pointer to the imports section.
+ PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDOSHeader, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+
+ //Loop through the import module descriptors looking for the module whose name matches szImportMod.
+ while (pImportDesc->Name)
+ {
+ PSTR szCurrMod = MakePtr(PSTR, pDOSHeader, pImportDesc->Name);
+ if (stricmp(szCurrMod, szImportMod) == 0)
+ break; // Found it.
+
+ //Look at the next one.
+ pImportDesc++;
+ }
+
+ //If the name is NULL, then the module is not imported.
+ if (pImportDesc->Name == NULL)
+ return NULL;
+
+ //All OK, Jumpmaster!
+ return pImportDesc;
+}
+
+BOOL IsNT()
+{
+ OSVERSIONINFO stOSVI;
+ memset(&stOSVI, NULL, sizeof(OSVERSIONINFO));
+ stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ BOOL bRet = GetVersionEx(&stOSVI);
+ ASSERT(TRUE == bRet);
+ if (FALSE == bRet)
+ {
+ TRACE0("GetVersionEx failed!\n");
+ return FALSE;
+ }
+
+ //Check the version and call the appropriate thing.
+ return (VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId);
+}
diff --git a/native/focusKiller/HookImportFunction.h b/native/focusKiller/HookImportFunction.h
new file mode 100644
index 0000000..325a71e
--- /dev/null
+++ b/native/focusKiller/HookImportFunction.h
@@ -0,0 +1,33 @@
+/*
+Module : HookImportFunction.h
+Purpose: Defines the interface for code to hook a call to any imported Win32 SDK
+Created: PJN / 23-10-1999
+
+Copyright (c) 1999 by PJ Naughter.
+All rights reserved.
+
+*/
+
+#ifndef __HOOKIMPORTFUNCTION_H__
+#define __HOOKIMPORTFUNCTION_H__
+
+
+
+////////////// Structures ///////////////////////////
+
+typedef struct tag_HOOKFUNCDESC
+{
+ LPCSTR szFunc; // The name of the function to hook.
+ PROC pProc; // The procedure to blast in.
+} HOOKFUNCDESC , * LPHOOKFUNCDESC;
+
+
+
+////////////// Functions ////////////////////////////
+
+PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportMod);
+BOOL HookImportFunctionsByName(HMODULE hModule, LPCSTR szImportMod, UINT uiCount,
+ LPHOOKFUNCDESC paHookArray, PROC* paOrigFuncs, UINT* puiHooked);
+
+
+#endif //__HOOKIMPORTEDFUNCTION_H__
\ No newline at end of file
diff --git a/native/focusKiller/focusKiller.sln b/native/focusKiller/focusKiller.sln
new file mode 100644
index 0000000..e58b43c
--- /dev/null
+++ b/native/focusKiller/focusKiller.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "focusKiller", "focusKiller.vcproj", "{6B40296D-5F50-4606-AB84-81FA874CC25A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Debug|Win32.Build.0 = Debug|Win32
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Debug|x64.ActiveCfg = Debug|x64
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Debug|x64.Build.0 = Debug|x64
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Release|Win32.ActiveCfg = Release|Win32
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Release|Win32.Build.0 = Release|Win32
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Release|x64.ActiveCfg = Release|x64
+ {6B40296D-5F50-4606-AB84-81FA874CC25A}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/native/focusKiller/focusKiller.vcproj b/native/focusKiller/focusKiller.vcproj
new file mode 100644
index 0000000..1946f82
--- /dev/null
+++ b/native/focusKiller/focusKiller.vcproj
@@ -0,0 +1,362 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="focusKiller"
+ ProjectGUID="{6B40296D-5F50-4606-AB84-81FA874CC25A}"
+ RootNamespace="focusKiller"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FOCUSKILLER_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FOCUSKILLER_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FOCUSKILLER_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FOCUSKILLER_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\focuskiller.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\HookImportFunction.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\HookImportFunction.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/native/focusKiller/focuskiller.cpp b/native/focusKiller/focuskiller.cpp
new file mode 100644
index 0000000..0d19a53
--- /dev/null
+++ b/native/focusKiller/focuskiller.cpp
@@ -0,0 +1,112 @@
+#include <windows.h>
+
+// NT 4 doesn't have FlashWindowEx.
+typedef BOOL (WINAPI *t_FlashWindowEx)(FLASHWINFO*);
+t_FlashWindowEx p_FlashWindowEx;
+#define FlashWindowEx p_FlashWindowEx
+
+#ifdef USE_DETOURS
+#include "detours.h" // see http://research.microsoft.com/sn/detours/
+extern "C" {
+ DETOUR_TRAMPOLINE(BOOL WINAPI Real_SetForegroundWindow(HWND hWnd), SetForegroundWindow);
+}
+#else
+// IAT patching hook method. See http://www.naughter.com/hookimportfunction.html
+// compile with cl /LD focuskiller.cpp HookImportFunction.cpp user32.lib
+#include "HookImportFunction.h"
+
+typedef BOOL (WINAPI *t_SetForegroundWindow)(HWND);
+t_SetForegroundWindow Real_SetForegroundWindow;
+#endif
+
+DWORD mypid;
+
+BOOL WINAPI Mine_SetForegroundWindow(HWND hWnd)
+{
+ DWORD pid;
+ HWND fg = GetForegroundWindow();
+ HWND owner = GetWindow(hWnd, GW_OWNER);
+ GetWindowThreadProcessId(fg, &pid);
+
+#ifdef _DEBUG
+ char buf[500];
+ wsprintf(buf, "SetForegroundWindow(%x): owner = %x, %d <-> %d", hWnd, owner, pid, mypid);
+ OutputDebugString(buf);
+#endif
+
+ // Disallow if
+ // a) another process' window is in the foreground
+ // b) the window to be put in front is a top-level window (should avoid putting one IDEA project in front of another one)
+ if (mypid != pid || owner == NULL) {
+ if (FlashWindowEx != NULL) {
+ FLASHWINFO fw;
+ fw.cbSize = sizeof(fw);
+ fw.hwnd = hWnd;
+ fw.uCount = 5;
+ fw.dwTimeout = 0;
+
+ fw.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
+ FlashWindowEx(&fw);
+ } else {
+ FlashWindow(hWnd, TRUE);
+ }
+ return TRUE; // fake success
+ }
+
+ return Real_SetForegroundWindow(hWnd);
+}
+
+void HookFunctions(HMODULE hModule)
+{
+#ifdef USE_DETOURS
+#ifdef _DEBUG
+ OutputDebugString("Using Detours hook...");
+#endif
+
+ DetourFunctionWithTrampoline((PBYTE)Real_SetForegroundWindow,
+ (PBYTE)Mine_SetForegroundWindow);
+#else
+#ifdef _DEBUG
+ OutputDebugString("Using IAT patching hook...");
+#endif
+
+ HOOKFUNCDESC hook;
+ hook.szFunc = "SetForegroundWindow";
+ hook.pProc = (PROC)Mine_SetForegroundWindow;
+
+ // hooking LoadLibrary and waiting until awt.dll is being loaded by java would be more correct but this works too
+ HMODULE awtModule = LoadLibrary("awt.dll");
+
+ BOOL b = HookImportFunctionsByName(awtModule, "user32.dll", 1, &hook, (PROC *)&Real_SetForegroundWindow, NULL);
+ if (!b) {
+ char buf[200];
+ wsprintf(buf, "Hooking SetForegroundWindow failed [0x%x]", GetLastError());
+ OutputDebugString(buf);
+ }
+#endif
+
+#ifdef _DEBUG
+ OutputDebugString("Functions hooked");
+#endif
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+{
+ if (fdwReason == DLL_PROCESS_ATTACH) {
+#ifdef _DEBUG
+ char buf[200];
+ wsprintf(buf, "DLL Attached");
+ OutputDebugString(buf);
+#endif
+
+ mypid = GetCurrentProcessId();
+ p_FlashWindowEx = (t_FlashWindowEx)GetProcAddress(GetModuleHandle("user32.dll"), "FlashWindowEx");
+
+ DisableThreadLibraryCalls((HMODULE)hinstDLL);
+
+ HookFunctions((HMODULE)hinstDLL);
+ }
+
+ return TRUE;
+}
+
diff --git a/native/fsNotifier/linux/fsnotifier.h b/native/fsNotifier/linux/fsnotifier.h
new file mode 100644
index 0000000..0b3e527
--- /dev/null
+++ b/native/fsNotifier/linux/fsnotifier.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FSNOTIFIER_H
+#define __FSNOTIFIER_H
+
+#include <stdbool.h>
+#include <stdio.h>
+
+
+// logging
+void userlog(int priority, const char* format, ...);
+
+#define CHECK_NULL(p, r) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return r; }
+
+
+// variable-length array
+typedef struct __array array;
+
+array* array_create(int initial_capacity);
+int array_size(array* a);
+void* array_push(array* a, void* element);
+void* array_pop(array* a);
+void array_put(array* a, int index, void* element);
+void* array_get(array* a, int index);
+void array_delete(array* a);
+void array_delete_vs_data(array* a);
+
+
+// poor man's hash table
+typedef struct __table table;
+
+table* table_create(int capacity);
+void* table_put(table* t, int key, void* value);
+void* table_get(table* t, int key);
+void table_delete(table* t);
+
+
+// inotify subsystem
+enum {
+ ERR_IGNORE = -1,
+ ERR_CONTINUE = -2,
+ ERR_ABORT = -3
+};
+
+bool init_inotify();
+void set_inotify_callback(void (* callback)(char*, int));
+int get_inotify_fd();
+int get_watch_count();
+bool watch_limit_reached();
+int watch(const char* root, array* mounts);
+void unwatch(int id);
+bool process_inotify_input();
+void close_inotify();
+
+
+// reads one line from stream, trims trailing carriage return if any
+// returns pointer to the internal buffer (will be overwritten on next call)
+char* read_line(FILE* stream);
+
+
+// path comparison
+bool is_parent_path(const char* parent_path, const char* child_path);
+
+
+#endif
diff --git a/native/fsNotifier/linux/inotify.c b/native/fsNotifier/linux/inotify.c
new file mode 100644
index 0000000..75a97ab
--- /dev/null
+++ b/native/fsNotifier/linux/inotify.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fsnotifier.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <unistd.h>
+
+
+#define WATCH_COUNT_NAME "/proc/sys/fs/inotify/max_user_watches"
+
+#define DEFAULT_SUBDIR_COUNT 5
+
+typedef struct __watch_node {
+ char* name;
+ int wd;
+ struct __watch_node* parent;
+ array* kids;
+} watch_node;
+
+static int inotify_fd = -1;
+static int watch_count = 0;
+static table* watches;
+static bool limit_reached = false;
+static void (* callback)(char*, int) = NULL;
+
+#define EVENT_SIZE (sizeof(struct inotify_event))
+#define EVENT_BUF_LEN (2048 * (EVENT_SIZE + 16))
+static char event_buf[EVENT_BUF_LEN];
+
+
+static void read_watch_descriptors_count() {
+ FILE* f = fopen(WATCH_COUNT_NAME, "r");
+ if (f == NULL) {
+ userlog(LOG_ERR, "can't open %s: %s", WATCH_COUNT_NAME, strerror(errno));
+ return;
+ }
+
+ char* str = read_line(f);
+ if (str == NULL) {
+ userlog(LOG_ERR, "can't read from %s", WATCH_COUNT_NAME);
+ }
+ else {
+ watch_count = atoi(str);
+ }
+
+ fclose(f);
+}
+
+
+bool init_inotify() {
+ inotify_fd = inotify_init();
+ if (inotify_fd < 0) {
+ userlog(LOG_ERR, "inotify_init: %s", strerror(errno));
+ return false;
+ }
+ userlog(LOG_DEBUG, "inotify fd: %d", get_inotify_fd());
+
+ read_watch_descriptors_count();
+ if (watch_count <= 0) {
+ close(inotify_fd);
+ inotify_fd = -1;
+ return false;
+ }
+ userlog(LOG_INFO, "inotify watch descriptors: %d", watch_count);
+
+ watches = table_create(watch_count);
+ if (watches == NULL) {
+ userlog(LOG_ERR, "out of memory");
+ close(inotify_fd);
+ inotify_fd = -1;
+ return false;
+ }
+
+ return true;
+}
+
+
+inline void set_inotify_callback(void (* _callback)(char*, int)) {
+ callback = _callback;
+}
+
+
+inline int get_inotify_fd() {
+ return inotify_fd;
+}
+
+
+inline int get_watch_count() {
+ return watch_count;
+}
+
+
+inline bool watch_limit_reached() {
+ return limit_reached;
+}
+
+
+#define EVENT_MASK IN_MODIFY | IN_ATTRIB | IN_CREATE | IN_DELETE | IN_MOVE | IN_DELETE_SELF
+
+static int add_watch(const char* path, watch_node* parent) {
+ int wd = inotify_add_watch(inotify_fd, path, EVENT_MASK);
+ if (wd < 0) {
+ if (errno == EACCES || errno == ENOENT) {
+ userlog(LOG_DEBUG, "inotify_add_watch(%s): %s", path, strerror(errno));
+ return ERR_IGNORE;
+ }
+ else if (errno == ENOSPC) {
+ userlog(LOG_WARNING, "inotify_add_watch(%s): %s", path, strerror(errno));
+ limit_reached = true;
+ return ERR_CONTINUE;
+ }
+ else {
+ userlog(LOG_ERR, "inotify_add_watch(%s): %s", path, strerror(errno));
+ return ERR_ABORT;
+ }
+ }
+ else {
+ userlog(LOG_DEBUG, "watching %s: %d", path, wd);
+ }
+
+ watch_node* node = table_get(watches, wd);
+ if (node != NULL) {
+ if (node->wd != wd) {
+ userlog(LOG_ERR, "table error: corruption at %d:%s / %d:%s)", wd, path, node->wd, node->name);
+ return ERR_ABORT;
+ }
+ else if (strcmp(node->name, path) != 0) {
+ char buf1[PATH_MAX], buf2[PATH_MAX];
+ const char* normalized1 = realpath(node->name, buf1);
+ const char* normalized2 = realpath(path, buf2);
+ if (normalized1 == NULL || normalized2 == NULL || strcmp(normalized1, normalized2) != 0) {
+ userlog(LOG_ERR, "table error: collision at %d (new %s, existing %s)", wd, path, node->name);
+ return ERR_ABORT;
+ }
+ else {
+ userlog(LOG_INFO, "intersection at %d: (new %s, existing %s, real %s)", wd, path, node->name, normalized1);
+ return ERR_IGNORE;
+ }
+ }
+
+ return wd;
+ }
+
+ node = malloc(sizeof(watch_node));
+
+ CHECK_NULL(node, ERR_ABORT);
+ node->name = strdup(path);
+ CHECK_NULL(node->name, ERR_ABORT);
+ node->wd = wd;
+ node->parent = parent;
+ node->kids = NULL;
+
+ if (parent != NULL) {
+ if (parent->kids == NULL) {
+ parent->kids = array_create(DEFAULT_SUBDIR_COUNT);
+ CHECK_NULL(parent->kids, ERR_ABORT);
+ }
+ CHECK_NULL(array_push(parent->kids, node), ERR_ABORT);
+ }
+
+ if (table_put(watches, wd, node) == NULL) {
+ userlog(LOG_ERR, "table error: unable to put (%d:%s)", wd, path);
+ return ERR_ABORT;
+ }
+
+ return wd;
+}
+
+
+static void rm_watch(int wd, bool update_parent) {
+ watch_node* node = table_get(watches, wd);
+ if (node == NULL) {
+ return;
+ }
+
+ userlog(LOG_DEBUG, "unwatching %s: %d (%p)", node->name, node->wd, node);
+
+ if (inotify_rm_watch(inotify_fd, node->wd) < 0) {
+ userlog(LOG_DEBUG, "inotify_rm_watch(%d:%s): %s", node->wd, node->name, strerror(errno));
+ }
+
+ for (int i=0; i<array_size(node->kids); i++) {
+ watch_node* kid = array_get(node->kids, i);
+ if (kid != NULL) {
+ rm_watch(kid->wd, false);
+ }
+ }
+
+ if (update_parent && node->parent != NULL) {
+ for (int i=0; i<array_size(node->parent->kids); i++) {
+ if (array_get(node->parent->kids, i) == node) {
+ array_put(node->parent->kids, i, NULL);
+ break;
+ }
+ }
+ }
+
+ free(node->name);
+ array_delete(node->kids);
+ free(node);
+ table_put(watches, wd, NULL);
+}
+
+
+static int walk_tree(const char* path, watch_node* parent, bool recursive, array* mounts) {
+ for (int j=0; j<array_size(mounts); j++) {
+ char* mount = array_get(mounts, j);
+ if (strncmp(path, mount, strlen(mount)) == 0) {
+ userlog(LOG_DEBUG, "watch path '%s' crossed mount point '%s' - skipping", path, mount);
+ return ERR_IGNORE;
+ }
+ }
+
+ DIR* dir = NULL;
+ if (recursive) {
+ if ((dir = opendir(path)) == NULL) {
+ if (errno == EACCES || errno == ENOENT || errno == ENOTDIR) {
+ userlog(LOG_DEBUG, "opendir(%s): %d", path, errno);
+ return ERR_IGNORE;
+ }
+ else {
+ userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno));
+ return ERR_CONTINUE;
+ }
+ }
+ }
+
+ int id = add_watch(path, parent);
+
+ if (dir == NULL) {
+ return id;
+ }
+ else if (id < 0) {
+ closedir(dir);
+ return id;
+ }
+
+ char subdir[PATH_MAX];
+ strcpy(subdir, path);
+ if (subdir[strlen(subdir) - 1] != '/') {
+ strcat(subdir, "/");
+ }
+ char* p = subdir + strlen(subdir);
+
+ struct dirent* entry;
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_type != DT_DIR ||
+ strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+ continue;
+ }
+
+ strcpy(p, entry->d_name);
+
+ int subdir_id = walk_tree(subdir, table_get(watches, id), recursive, mounts);
+ if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
+ rm_watch(id, true);
+ id = subdir_id;
+ break;
+ }
+ }
+
+ closedir(dir);
+ return id;
+}
+
+
+int watch(const char* root, array* mounts) {
+ bool recursive = true;
+ if (root[0] == '|') {
+ root++;
+ recursive = false;
+ }
+
+ struct stat st;
+ if (stat(root, &st) != 0) {
+ if (errno == EACCES) {
+ return ERR_IGNORE;
+ }
+ else if (errno == ENOENT) {
+ return ERR_CONTINUE;
+ }
+ userlog(LOG_ERR, "stat(%s): %s", root, strerror(errno));
+ return ERR_ABORT;
+ }
+
+ if (S_ISREG(st.st_mode)) {
+ recursive = false;
+ }
+ else if (!S_ISDIR(st.st_mode)) {
+ userlog(LOG_WARNING, "unexpected node type: %s, %d", root, st.st_mode);
+ return ERR_IGNORE;
+ }
+
+ return walk_tree(root, NULL, recursive, mounts);
+}
+
+
+void unwatch(int id) {
+ rm_watch(id, true);
+}
+
+
+static bool process_inotify_event(struct inotify_event* event) {
+ watch_node* node = table_get(watches, event->wd);
+ if (node == NULL) {
+ return true;
+ }
+
+ bool is_dir = (event->mask & IN_ISDIR) == IN_ISDIR;
+ userlog(LOG_DEBUG, "inotify: wd=%d mask=%d dir=%d name=%s", event->wd, event->mask & (~IN_ISDIR), is_dir, node->name);
+
+ char path[PATH_MAX];
+ strcpy(path, node->name);
+ if (event->len > 0) {
+ if (path[strlen(path) - 1] != '/') {
+ strcat(path, "/");
+ }
+ strcat(path, event->name);
+ }
+
+ if (is_dir && ((event->mask & IN_CREATE) == IN_CREATE || (event->mask & IN_MOVED_TO) == IN_MOVED_TO)) {
+ int result = walk_tree(path, node, true, NULL);
+ if (result < 0 && result != ERR_IGNORE && result != ERR_CONTINUE) {
+ return false;
+ }
+ }
+
+ if (is_dir && ((event->mask & IN_DELETE) == IN_DELETE || (event->mask & IN_MOVED_FROM) == IN_MOVED_FROM)) {
+ for (int i=0; i<array_size(node->kids); i++) {
+ watch_node* kid = array_get(node->kids, i);
+ if (kid != NULL && strcmp(kid->name, path) == 0) {
+ rm_watch(kid->wd, false);
+ array_put(node->kids, i, NULL);
+ break;
+ }
+ }
+ }
+
+ if (callback != NULL) {
+ (*callback)(path, event->mask);
+ }
+ return true;
+}
+
+
+bool process_inotify_input() {
+ ssize_t len = read(inotify_fd, event_buf, EVENT_BUF_LEN);
+ if (len < 0) {
+ userlog(LOG_ERR, "read: %s", strerror(errno));
+ return false;
+ }
+
+ int i = 0;
+ while (i < len) {
+ struct inotify_event* event = (struct inotify_event*) &event_buf[i];
+ i += EVENT_SIZE + event->len;
+
+ if (event->mask & IN_IGNORED) {
+ continue;
+ }
+ if (event->mask & IN_Q_OVERFLOW) {
+ userlog(LOG_ERR, "event queue overflow");
+ continue;
+ }
+
+ if (!process_inotify_event(event)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+void close_inotify() {
+ if (watches != NULL) {
+ table_delete(watches);
+ }
+
+ if (inotify_fd >= 0) {
+ close(inotify_fd);
+ }
+}
diff --git a/native/fsNotifier/linux/main.c b/native/fsNotifier/linux/main.c
new file mode 100644
index 0000000..606e914
--- /dev/null
+++ b/native/fsNotifier/linux/main.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fsnotifier.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <mntent.h>
+#include <paths.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <sys/select.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#define LOG_ENV "FSNOTIFIER_LOG_LEVEL"
+#define LOG_ENV_DEBUG "debug"
+#define LOG_ENV_INFO "info"
+#define LOG_ENV_WARNING "warning"
+#define LOG_ENV_ERROR "error"
+#define LOG_ENV_OFF "off"
+
+#define VERSION "1.2"
+#define VERSION_MSG "fsnotifier " VERSION "\n"
+
+#define USAGE_MSG \
+ "fsnotifier - IntelliJ IDEA companion program for watching and reporting file and directory structure modifications.\n\n" \
+ "fsnotifier utilizes \"user\" facility of syslog(3) - messages usually can be found in /var/log/user.log.\n" \
+ "Verbosity is regulated via " LOG_ENV " environment variable, possible values are: " \
+ LOG_ENV_DEBUG ", " LOG_ENV_INFO ", " LOG_ENV_WARNING ", " LOG_ENV_ERROR ", " LOG_ENV_OFF "; latter is the default.\n\n" \
+ "Use 'fsnotifier --selftest' to perform some self-diagnostics (output will be logged and printed to console).\n"
+
+#define HELP_MSG \
+ "Try 'fsnotifier --help' for more information.\n"
+
+#define INOTIFY_LIMIT_MSG \
+ "The current <b>inotify</b>(7) watch limit of %d is too low. " \
+ "<a href=\"http://confluence.jetbrains.net/display/IDEADEV/Inotify+Watches+Limit\">More details.</a>\n"
+
+typedef struct {
+ char* name;
+ int id;
+} watch_root;
+
+static array* roots = NULL;
+
+static bool show_warning = true;
+static bool self_test = false;
+
+static void init_log();
+static void run_self_test();
+static void main_loop();
+static bool read_input();
+static bool update_roots(array* new_roots);
+static void unregister_roots();
+static bool register_roots(array* new_roots, array* unwatchable, array* mounts);
+static array* unwatchable_mounts();
+static void inotify_callback(char* path, int event);
+static void output(const char* format, ...);
+
+
+int main(int argc, char** argv) {
+ if (argc > 1) {
+ if (strcmp(argv[1], "--help") == 0) {
+ printf(USAGE_MSG);
+ return 0;
+ }
+ else if (strcmp(argv[1], "--version") == 0) {
+ printf(VERSION_MSG);
+ return 0;
+ }
+ else if (strcmp(argv[1], "--selftest") == 0) {
+ self_test = true;
+ }
+ else {
+ printf("unrecognized option: %s\n", argv[1]);
+ printf(HELP_MSG);
+ return 1;
+ }
+ }
+
+ init_log();
+ if (!self_test) {
+ userlog(LOG_INFO, "started (v." VERSION ")");
+ }
+ else {
+ userlog(LOG_INFO, "started (self-test mode) (v." VERSION ")");
+ }
+
+ setvbuf(stdin, NULL, _IONBF, 0);
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ roots = array_create(20);
+ if (init_inotify() && roots != NULL) {
+ set_inotify_callback(&inotify_callback);
+
+ if (!self_test) {
+ main_loop();
+ }
+ else {
+ run_self_test();
+ }
+
+ unregister_roots();
+ }
+ else {
+ printf("GIVEUP\n");
+ }
+ close_inotify();
+ array_delete(roots);
+
+ userlog(LOG_INFO, "finished");
+ closelog();
+
+ return 0;
+}
+
+
+static void init_log() {
+ char* env_level = getenv(LOG_ENV);
+ int level = LOG_EMERG;
+ if (env_level != NULL) {
+ if (strcmp(env_level, LOG_ENV_DEBUG) == 0) level = LOG_DEBUG;
+ else if (strcmp(env_level, LOG_ENV_INFO) == 0) level = LOG_INFO;
+ else if (strcmp(env_level, LOG_ENV_WARNING) == 0) level = LOG_WARNING;
+ else if (strcmp(env_level, LOG_ENV_ERROR) == 0) level = LOG_ERR;
+ }
+
+ if (self_test) {
+ level = LOG_DEBUG;
+ }
+
+ char ident[32];
+ snprintf(ident, sizeof(ident), "fsnotifier[%d]", getpid());
+ openlog(ident, 0, LOG_USER);
+ setlogmask(LOG_UPTO(level));
+}
+
+
+void userlog(int priority, const char* format, ...) {
+ va_list ap;
+
+ va_start(ap, format);
+ vsyslog(priority, format, ap);
+ va_end(ap);
+
+ if (self_test) {
+ const char* level = "debug";
+ switch (priority) {
+ case LOG_ERR: level = "error"; break;
+ case LOG_WARNING: level = " warn"; break;
+ case LOG_INFO: level = " info"; break;
+ }
+ printf("fsnotifier[%d] %s: ", getpid(), level);
+
+ va_start(ap, format);
+ vprintf(format, ap);
+ va_end(ap);
+
+ printf("\n");
+ }
+}
+
+
+static void run_self_test() {
+ array* test_roots = array_create(1);
+ char* cwd = malloc(PATH_MAX);
+ if (getcwd(cwd, PATH_MAX) == NULL) {
+ strncpy(cwd, ".", PATH_MAX);
+ }
+ array_push(test_roots, cwd);
+ update_roots(test_roots);
+}
+
+
+static void main_loop() {
+ int input_fd = fileno(stdin), inotify_fd = get_inotify_fd();
+ int nfds = (inotify_fd > input_fd ? inotify_fd : input_fd) + 1;
+ fd_set rfds;
+ bool go_on = true;
+
+ while (go_on) {
+ FD_ZERO(&rfds);
+ FD_SET(input_fd, &rfds);
+ FD_SET(inotify_fd, &rfds);
+ if (select(nfds, &rfds, NULL, NULL, NULL) < 0) {
+ userlog(LOG_ERR, "select: %s", strerror(errno));
+ go_on = false;
+ }
+ else if (FD_ISSET(input_fd, &rfds)) {
+ go_on = read_input();
+ }
+ else if (FD_ISSET(inotify_fd, &rfds)) {
+ go_on = process_inotify_input();
+ }
+ }
+}
+
+
+static bool read_input() {
+ char* line = read_line(stdin);
+ userlog(LOG_DEBUG, "input: %s", (line ? line : "<null>"));
+
+ if (line == NULL || strcmp(line, "EXIT") == 0) {
+ userlog(LOG_INFO, "exiting: %s", line);
+ return false;
+ }
+
+ if (strcmp(line, "ROOTS") == 0) {
+ array* new_roots = array_create(20);
+ CHECK_NULL(new_roots, false);
+
+ while (1) {
+ line = read_line(stdin);
+ userlog(LOG_DEBUG, "input: %s", (line ? line : "<null>"));
+ if (line == NULL || strlen(line) == 0) {
+ return false;
+ }
+ else if (strcmp(line, "#") == 0) {
+ break;
+ }
+ else {
+ int l = strlen(line);
+ if (l > 1 && line[l-1] == '/') line[l-1] = '\0';
+ CHECK_NULL(array_push(new_roots, strdup(line)), false);
+ }
+ }
+
+ return update_roots(new_roots);
+ }
+
+ userlog(LOG_INFO, "unrecognised command: %s", line);
+ return true;
+}
+
+
+static bool update_roots(array* new_roots) {
+ userlog(LOG_INFO, "updating roots (curr:%d, new:%d)", array_size(roots), array_size(new_roots));
+
+ unregister_roots();
+
+ if (array_size(new_roots) == 0) {
+ output("UNWATCHEABLE\n#\n");
+ array_delete(new_roots);
+ return true;
+ }
+ else if (array_size(new_roots) == 1 && strcmp(array_get(new_roots, 0), "/") == 0) { // refuse to watch entire tree
+ output("UNWATCHEABLE\n/\n#\n");
+ userlog(LOG_INFO, "unwatchable: /");
+ array_delete_vs_data(new_roots);
+ return true;
+ }
+
+ array* mounts = unwatchable_mounts();
+ if (mounts == NULL) {
+ return false;
+ }
+
+ array* unwatchable = array_create(20);
+ if (!register_roots(new_roots, unwatchable, mounts)) {
+ return false;
+ }
+
+ output("UNWATCHEABLE\n");
+ for (int i=0; i<array_size(unwatchable); i++) {
+ char* s = array_get(unwatchable, i);
+ output("%s\n", s);
+ userlog(LOG_INFO, "unwatchable: %s", s);
+ }
+ output("#\n");
+
+ array_delete_vs_data(unwatchable);
+ array_delete_vs_data(mounts);
+ array_delete_vs_data(new_roots);
+
+ return true;
+}
+
+
+static void unregister_roots() {
+ watch_root* root;
+ while ((root = array_pop(roots)) != NULL) {
+ userlog(LOG_INFO, "unregistering root: %s", root->name);
+ unwatch(root->id);
+ free(root->name);
+ free(root);
+ };
+}
+
+
+static bool register_roots(array* new_roots, array* unwatchable, array* mounts) {
+ for (int i=0; i<array_size(new_roots); i++) {
+ char* new_root = array_get(new_roots, i);
+ char* unflattened = new_root;
+ if (unflattened[0] == '|') ++unflattened;
+ userlog(LOG_INFO, "registering root: %s", new_root);
+
+ if (unflattened[0] != '/') {
+ userlog(LOG_WARNING, " ... not valid, skipped");
+ continue;
+ }
+
+ array* inner_mounts = array_create(5);
+ CHECK_NULL(inner_mounts, false);
+
+ bool skip = false;
+ for (int j=0; j<array_size(mounts); j++) {
+ char* mount = array_get(mounts, j);
+ if (is_parent_path(mount, unflattened)) {
+ userlog(LOG_DEBUG, "watch root '%s' is under mount point '%s' - skipping", unflattened, mount);
+ CHECK_NULL(array_push(unwatchable, strdup(unflattened)), false);
+ skip = true;
+ break;
+ }
+ else if (is_parent_path(unflattened, mount)) {
+ userlog(LOG_DEBUG, "watch root '%s' contains mount point '%s' - partial watch", unflattened, mount);
+ char* copy = strdup(mount);
+ CHECK_NULL(array_push(unwatchable, copy), false);
+ CHECK_NULL(array_push(inner_mounts, copy), false);
+ }
+ }
+ if (skip) {
+ continue;
+ }
+
+ int id = watch(new_root, inner_mounts);
+ array_delete(inner_mounts);
+
+ if (id >= 0) {
+ watch_root* root = malloc(sizeof(watch_root));
+ CHECK_NULL(root, false);
+ root->id = id;
+ root->name = strdup(new_root);
+ CHECK_NULL(root->name, false);
+ CHECK_NULL(array_push(roots, root), false);
+ }
+ else if (id == ERR_ABORT) {
+ return false;
+ }
+ else if (id != ERR_IGNORE) {
+ if (show_warning && watch_limit_reached()) {
+ int limit = get_watch_count();
+ userlog(LOG_WARNING, "watch limit (%d) reached", limit);
+ output("MESSAGE\n" INOTIFY_LIMIT_MSG, limit);
+ show_warning = false; // warn only once
+ }
+ CHECK_NULL(array_push(unwatchable, strdup(unflattened)), false);
+ }
+ }
+
+ return true;
+}
+
+
+static bool is_watchable(const char* fs) {
+ // don't watch special and network filesystems
+ return !(strncmp(fs, "dev", 3) == 0 || strcmp(fs, "proc") == 0 || strcmp(fs, "sysfs") == 0 || strcmp(fs, MNTTYPE_SWAP) == 0 ||
+ strncmp(fs, "fuse", 4) == 0 || strcmp(fs, "cifs") == 0 || strcmp(fs, MNTTYPE_NFS) == 0);
+}
+
+static array* unwatchable_mounts() {
+ FILE* mtab = setmntent(_PATH_MOUNTED, "r");
+ if (mtab == NULL) {
+ userlog(LOG_ERR, "cannot open " _PATH_MOUNTED);
+ return NULL;
+ }
+
+ array* mounts = array_create(20);
+ CHECK_NULL(mounts, NULL);
+
+ struct mntent* ent;
+ while ((ent = getmntent(mtab)) != NULL) {
+ userlog(LOG_DEBUG, "mtab: %s : %s", ent->mnt_dir, ent->mnt_type);
+ if (strcmp(ent->mnt_type, MNTTYPE_IGNORE) != 0 && !is_watchable(ent->mnt_type)) {
+ CHECK_NULL(array_push(mounts, strdup(ent->mnt_dir)), NULL);
+ }
+ }
+
+ endmntent(mtab);
+ return mounts;
+}
+
+
+static void inotify_callback(char* path, int event) {
+ if (event & IN_CREATE || event & IN_MOVED_TO) {
+ output("CREATE\n%s\nCHANGE\n%s\n", path, path);
+ userlog(LOG_DEBUG, "CREATE: %s", path);
+ return;
+ }
+
+ if (event & IN_MODIFY) {
+ output("CHANGE\n%s\n", path);
+ userlog(LOG_DEBUG, "CHANGE: %s", path);
+ return;
+ }
+
+ if (event & IN_ATTRIB) {
+ output("STATS\n%s\n", path);
+ userlog(LOG_DEBUG, "STATS: %s", path);
+ return;
+ }
+
+ if (event & IN_DELETE || event & IN_MOVED_FROM) {
+ output("DELETE\n%s\n", path);
+ userlog(LOG_DEBUG, "DELETE: %s", path);
+ return;
+ }
+
+ if (event & IN_UNMOUNT) {
+ output("RESET\n");
+ userlog(LOG_DEBUG, "RESET");
+ return;
+ }
+}
+
+
+static void output(const char* format, ...) {
+ if (self_test) {
+ return;
+ }
+
+ va_list ap;
+ va_start(ap, format);
+ vprintf(format, ap);
+ va_end(ap);
+}
diff --git a/native/fsNotifier/linux/make.sh b/native/fsNotifier/linux/make.sh
new file mode 100755
index 0000000..4dc3657
--- /dev/null
+++ b/native/fsNotifier/linux/make.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+echo "compiling 32-bit version"
+clang -m32 -O2 -Wall -std=c99 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -o fsnotifier main.c inotify.c util.c
+if [ $? -eq 0 ] ; then
+ echo "compiling 64-bit version"
+ clang -m64 -O2 -Wall -std=c99 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -o fsnotifier64 main.c inotify.c util.c
+ if [ $? -eq 0 ] ; then
+ chmod 755 fsnotifier fsnotifier64
+ fi
+fi
diff --git a/native/fsNotifier/linux/util.c b/native/fsNotifier/linux/util.c
new file mode 100644
index 0000000..179b310
--- /dev/null
+++ b/native/fsNotifier/linux/util.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fsnotifier.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define REALLOC_FACTOR 2
+
+struct __array {
+ void** data;
+ int size;
+ int capacity;
+};
+
+static bool array_realloc(array* a) {
+ if (a->size == a->capacity) {
+ int new_cap = a->capacity * REALLOC_FACTOR;
+ void* new_ptr = realloc(a->data, sizeof(void*) * new_cap);
+ if (new_ptr == NULL) {
+ return false;
+ }
+ a->capacity = new_cap;
+ a->data = new_ptr;
+ }
+ return true;
+}
+
+array* array_create(int initial_capacity) {
+ array* a = (array*) malloc(sizeof(array));
+ if (a == NULL) {
+ return NULL;
+ }
+
+ a->data = calloc(sizeof(void*), initial_capacity);
+ if (a->data == NULL) {
+ free(a);
+ return NULL;
+ }
+
+ a->capacity = initial_capacity;
+ a->size = 0;
+
+ return a;
+}
+
+inline int array_size(array* a) {
+ return (a != NULL ? a->size : 0);
+}
+
+void* array_push(array* a, void* element) {
+ if (a == NULL || !array_realloc(a)) {
+ return NULL;
+ }
+ a->data[a->size++] = element;
+ return element;
+}
+
+void* array_pop(array* a) {
+ if (a != NULL && a->size > 0) {
+ return a->data[--a->size];
+ }
+ else {
+ return NULL;
+ }
+}
+
+void array_put(array* a, int index, void* element) {
+ if (a != NULL && index >=0 && index < a->capacity) {
+ a->data[index] = element;
+ if (a->size <= index) {
+ a->size = index + 1;
+ }
+ }
+}
+
+void* array_get(array* a, int index) {
+ if (a != NULL && index >= 0 && index < a->size) {
+ return a->data[index];
+ }
+ else {
+ return NULL;
+ }
+}
+
+void array_delete(array* a) {
+ if (a != NULL) {
+ free(a->data);
+ free(a);
+ }
+}
+
+void array_delete_vs_data(array* a) {
+ if (a != NULL) {
+ for (int i=0; i<a->size; i++) {
+ if (a->data[i] != NULL) {
+ free(a->data[i]);
+ }
+ }
+ array_delete(a);
+ }
+}
+
+
+struct __table {
+ void** data;
+ int capacity;
+};
+
+table* table_create(int capacity) {
+ table* t = malloc(sizeof(table));
+ if (t == NULL) {
+ return NULL;
+ }
+
+ t->data = calloc(sizeof(void*), capacity);
+ if (t->data == NULL) {
+ free(t);
+ return NULL;
+ }
+ memset(t->data, 0, sizeof(void*) * capacity);
+
+ t->capacity = capacity;
+
+ return t;
+}
+
+static inline int wrap(int key, table* t) {
+ return (t != NULL ? key % t->capacity : -1);
+}
+
+// todo: resolve collisions (?)
+void* table_put(table* t, int key, void* value) {
+ int k = wrap(key, t);
+ if (k < 0 || (value != NULL && t->data[k] != NULL)) {
+ return NULL;
+ }
+ else {
+ return t->data[k] = value;
+ }
+}
+
+void* table_get(table* t, int key) {
+ int k = wrap(key, t);
+ if (k < 0) {
+ return NULL;
+ }
+ else {
+ return t->data[k];
+ }
+}
+
+void table_delete(table* t) {
+ if (t != NULL) {
+ free(t->data);
+ free(t);
+ }
+}
+
+
+#define INPUT_BUF_LEN 2048
+static char input_buf[INPUT_BUF_LEN];
+
+char* read_line(FILE* stream) {
+ char* retval = fgets(input_buf, INPUT_BUF_LEN, stream);
+ if (retval == NULL || feof(stream)) {
+ return NULL;
+ }
+ int pos = strlen(input_buf) - 1;
+ if (input_buf[pos] == '\n') {
+ input_buf[pos] = '\0';
+ }
+ return input_buf;
+}
+
+
+bool is_parent_path(const char* parent_path, const char* child_path) {
+ size_t parent_len = strlen(parent_path);
+ return strncmp(parent_path, child_path, parent_len) == 0 &&
+ (parent_len == strlen(child_path) || child_path[parent_len] == '/');
+}
diff --git a/native/fsNotifier/mac/fsnotifier.c b/native/fsNotifier/mac/fsnotifier.c
new file mode 100644
index 0000000..df4a143
--- /dev/null
+++ b/native/fsNotifier/mac/fsnotifier.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <CoreServices/CoreServices.h>
+#include <pthread.h>
+#include <sys/mount.h>
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static void callback(ConstFSEventStreamRef streamRef,
+ void *clientCallBackInfo,
+ size_t numEvents,
+ void *eventPaths,
+ const FSEventStreamEventFlags eventFlags[],
+ const FSEventStreamEventId eventIds[]) {
+ char **paths = eventPaths;
+
+ for (int i = 0; i < numEvents; i++) {
+ // TODO[max] Lion has much more detailed flags we need accurately process. For now just reduce to SL events range.
+ FSEventStreamEventFlags flags = eventFlags[i] & 0xFF;
+ if ((flags & kFSEventStreamEventFlagMustScanSubDirs) != 0) {
+ pthread_mutex_lock(&lock);
+ printf("RECDIRTY\n%s\n", paths[i]);
+ fflush(stdout);
+ pthread_mutex_unlock(&lock);
+ }
+ else if (flags != kFSEventStreamEventFlagNone) {
+ pthread_mutex_lock(&lock);
+ printf("RESET\n");
+ fflush(stdout);
+ pthread_mutex_unlock(&lock);
+ }
+ else {
+ pthread_mutex_lock(&lock);
+ printf("DIRTY\n%s\n", paths[i]);
+ fflush(stdout);
+ pthread_mutex_unlock(&lock);
+ }
+ }
+}
+
+static void * EventProcessingThread(void *data) {
+ CFStringRef path = CFSTR("/");
+ CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&path, 1, NULL);
+ void *callbackInfo = NULL;
+ CFAbsoluteTime latency = 0.3; // Latency in seconds
+
+ FSEventStreamRef stream = FSEventStreamCreate(
+ NULL,
+ &callback,
+ callbackInfo,
+ pathsToWatch,
+ kFSEventStreamEventIdSinceNow,
+ latency,
+ kFSEventStreamCreateFlagNoDefer
+ );
+
+ FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ FSEventStreamStart(stream);
+
+ CFRunLoopRun();
+ return NULL;
+}
+
+#define FS_FLAGS (MNT_LOCAL|MNT_JOURNALED)
+
+static void PrintMountedFileSystems(CFArrayRef roots) {
+ int fsCount = getfsstat(NULL, 0, MNT_WAIT);
+ if (fsCount == -1) return;
+
+ struct statfs fs[fsCount];
+ fsCount = getfsstat(fs, sizeof(struct statfs) * fsCount, MNT_NOWAIT);
+ if (fsCount == -1) return;
+
+ CFMutableArrayRef mounts = CFArrayCreateMutable(NULL, 0, NULL);
+
+ for (int i = 0; i < fsCount; i++) {
+ if ((fs[i].f_flags & FS_FLAGS) != FS_FLAGS) {
+ char *mount = fs[i].f_mntonname;
+ int mountLen = strlen(mount);
+
+ for (int j = 0; j < CFArrayGetCount(roots); j++) {
+ char *root = (char *)CFArrayGetValueAtIndex(roots, j);
+ int rootLen = strlen(root);
+
+ if (rootLen >= mountLen && strncmp(root, mount, mountLen) == 0) {
+ // root under mount point
+ if (rootLen == mountLen || root[mountLen] == '/' || strcmp(mount, "/") == 0) {
+ CFArrayAppendValue(mounts, root);
+ }
+ }
+ else if (strncmp(root, mount, rootLen) == 0) {
+ // root over mount point
+ if (strcmp(root, "/") == 0 || mount[rootLen] == '/') {
+ CFArrayAppendValue(mounts, mount);
+ }
+ }
+ }
+ }
+ }
+
+ pthread_mutex_lock(&lock);
+ printf("UNWATCHEABLE\n");
+ for (int i = 0; i < CFArrayGetCount(mounts); i++) {
+ char *mount = (char *)CFArrayGetValueAtIndex(mounts, i);
+ printf("%s\n", mount);
+ }
+ printf("#\n");
+ fflush(stdout);
+ pthread_mutex_unlock(&lock);
+
+ CFRelease(mounts);
+}
+
+// Static buffer for fscanf. All of the are being performed from a single thread, so it's thread safe.
+static char command[2048];
+
+static void ParseRoots() {
+ CFMutableArrayRef roots = CFArrayCreateMutable(NULL, 0, NULL);
+
+ while (TRUE) {
+ fscanf(stdin, "%s", command);
+ if (strcmp(command, "#") == 0 || feof(stdin)) break;
+ char* path = command[0] == '|' ? command + 1 : command;
+ CFArrayAppendValue(roots, strdup(path));
+ }
+
+ PrintMountedFileSystems(roots);
+
+ for (int i = 0; i < CFArrayGetCount(roots); i++) {
+ void *value = (char *)CFArrayGetValueAtIndex(roots, i);
+ free(value);
+ }
+ CFRelease(roots);
+}
+
+int main(const int argc, const char* argv[]) {
+ // Checking if necessary API is available (need MacOS X 10.5 or later).
+ if (FSEventStreamCreate == NULL) {
+ printf("GIVEUP\n");
+ return 1;
+ }
+
+ pthread_t threadId;
+ if (pthread_create(&threadId, NULL, EventProcessingThread, NULL) != 0) {
+ // Give up if cannot create a thread.
+ printf("GIVEUP\n");
+ return 2;
+ }
+
+ while (TRUE) {
+ fscanf(stdin, "%s", command);
+ if (strcmp(command, "EXIT") == 0 || feof(stdin)) break;
+ if (strcmp(command, "ROOTS") == 0) ParseRoots();
+ }
+
+ return 0;
+}
diff --git a/native/fsNotifier/mac/make.sh b/native/fsNotifier/mac/make.sh
new file mode 100755
index 0000000..1810f1b
--- /dev/null
+++ b/native/fsNotifier/mac/make.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# Clang can be downloaded from from http://llvm.org/releases/download.html or found in XCode 4+
+clang -arch i386 -mmacosx-version-min=10.5 -framework CoreServices -o fsnotifier fsnotifier.c
diff --git a/native/macrestarter/relaunch.m b/native/macrestarter/relaunch.m
new file mode 100644
index 0000000..5d6a707
--- /dev/null
+++ b/native/macrestarter/relaunch.m
@@ -0,0 +1,21 @@
+// gcc -Wall -arch i386 -arch ppc -mmacosx-version-min=10.4 -Os -framework AppKit -o relaunch relaunch.m
+
+#import <AppKit/AppKit.h>
+
+int main(int argc, const char *argv[]) {
+ if (argc != 2) return EXIT_FAILURE;
+
+ unsigned int interval = 500; // check every 0.5 second
+ unsigned int slept = 0;
+ while (getppid() != 1) {
+ usleep(interval * 1000);
+
+ slept += interval;
+ // if (slept > 10 * 1000 /* wait for maximum 10 seconds */) return EXIT_FAILURE;
+ }
+
+ char const *pathToRelaunch = argv[1];
+ [[NSWorkspace sharedWorkspace] launchApplication:[NSString stringWithUTF8String:pathToRelaunch]];
+
+ return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/native/macrestarter/relaunch.xcodeproj/project.pbxproj b/native/macrestarter/relaunch.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..8cc758f
--- /dev/null
+++ b/native/macrestarter/relaunch.xcodeproj/project.pbxproj
@@ -0,0 +1,209 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 3A6C10B4148122790074811C /* relaunch.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A6C10B3148122790074811C /* relaunch.m */; };
+ 3A6C10B7148122940074811C /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6C10B6148122940074811C /* AppKit.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ CF2F99674C3F98D5739C1B44 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 3A6C10AE148122660074811C /* relaunch */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = relaunch; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3A6C10B3148122790074811C /* relaunch.m */ = {isa = PBXFileReference; fileEncoding = 11; lastKnownFileType = sourcecode.c.objc; path = relaunch.m; sourceTree = "<group>"; };
+ 3A6C10B6148122940074811C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ CF2F99674C3F98D5739C1B43 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3A6C10B7148122940074811C /* AppKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ CF2F99674C3F98D5739C1B39 = {
+ isa = PBXGroup;
+ children = (
+ 3A6C10B3148122790074811C /* relaunch.m */,
+ CF2F99674C3F98D5739C1B3A /* Products */,
+ CF2F99674C3F98D5739C1B45 /* Frameworks */,
+ 3A6C10B6148122940074811C /* AppKit.framework */,
+ );
+ sourceTree = "<group>";
+ };
+ CF2F99674C3F98D5739C1B3A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 3A6C10AE148122660074811C /* relaunch */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CF2F99674C3F98D5739C1B45 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ CF2F99674C3F98D5739C1B3E /* relaunch */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CF2F99674C3F98D5739C1B3F /* Build configuration list for PBXNativeTarget "relaunch" */;
+ buildPhases = (
+ CF2F99674C3F98D5739C1B42 /* Sources */,
+ CF2F99674C3F98D5739C1B43 /* Frameworks */,
+ CF2F99674C3F98D5739C1B44 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = relaunch;
+ productName = relaunch;
+ productReference = 3A6C10AE148122660074811C /* relaunch */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ CF2F99674C3F98D5739C1B37 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = CF2F99674C3F98D5739C1B38 /* Build configuration list for PBXProject "relaunch" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = CF2F99674C3F98D5739C1B39;
+ productRefGroup = CF2F99674C3F98D5739C1B3A /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ CF2F99674C3F98D5739C1B3E /* relaunch */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ CF2F99674C3F98D5739C1B42 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3A6C10B4148122790074811C /* relaunch.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ CF2F99674C3F98D5739C1B3B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_VERSION = 4.0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ ONLY_ACTIVE_ARCH = NO;
+ SDKROOT = macosx10.4;
+ };
+ name = Release;
+ };
+ CF2F99674C3F98D5739C1B3C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = 4.0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ ONLY_ACTIVE_ARCH = NO;
+ SDKROOT = macosx10.4;
+ };
+ name = Debug;
+ };
+ CF2F99674C3F98D5739C1B40 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ CF2F99674C3F98D5739C1B41 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ CF2F99674C3F98D5739C1B38 /* Build configuration list for PBXProject "relaunch" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CF2F99674C3F98D5739C1B3B /* Release */,
+ CF2F99674C3F98D5739C1B3C /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CF2F99674C3F98D5739C1B3F /* Build configuration list for PBXNativeTarget "relaunch" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CF2F99674C3F98D5739C1B40 /* Release */,
+ CF2F99674C3F98D5739C1B41 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = CF2F99674C3F98D5739C1B37 /* Project object */;
+}
diff --git a/native/restarter/.gitignore b/native/restarter/.gitignore
new file mode 100644
index 0000000..5f88d71
--- /dev/null
+++ b/native/restarter/.gitignore
@@ -0,0 +1,8 @@
+Debug
+Release
+_UpgradeReport_Files
+*.suo
+*.vcxproj.user
+UpgradeLog.xml
+ipch
+*.sdf
diff --git a/native/restarter/restarter.cpp b/native/restarter/restarter.cpp
new file mode 100644
index 0000000..aef7476
--- /dev/null
+++ b/native/restarter/restarter.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ if (argc < 3) return 0;
+ int ppid = _ttoi(argv [1]);
+ HANDLE parent_process = OpenProcess(SYNCHRONIZE, FALSE, ppid);
+ if (parent_process)
+ {
+ WaitForSingleObject(parent_process, INFINITE);
+ CloseHandle(parent_process);
+ }
+
+ int child_argc = argc-2;
+ _TCHAR** child_argv = new _TCHAR* [child_argc+1];
+ for(int i = 0; i < child_argc; i++)
+ {
+ if (_tcschr(argv[i+2], ' '))
+ {
+ int len = _tcslen(argv[i+2]) + 3;
+ TCHAR *arg = new TCHAR[len];
+ arg[0] = '\"';
+ _tcscpy_s(arg+1, len, argv[i+2]);
+ _tcscat_s(arg, len, _T("\""));
+ child_argv[i] = arg;
+ }
+ else
+ {
+ child_argv[i] = argv[i+2];
+ }
+ }
+ child_argv[child_argc] = '\0';
+
+ int rc = _texecv(argv [2], child_argv);
+ if (rc == -1)
+ {
+ _tprintf(_T("Error restarting process: errno is %d"), errno);
+ }
+
+ return 0;
+}
+
diff --git a/native/restarter/restarter.sln b/native/restarter/restarter.sln
new file mode 100644
index 0000000..359e70e
--- /dev/null
+++ b/native/restarter/restarter.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "restarter", "restarter.vcproj", "{1B2485B2-CFED-4B2F-8FFD-00F1C9E1BD0C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1B2485B2-CFED-4B2F-8FFD-00F1C9E1BD0C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1B2485B2-CFED-4B2F-8FFD-00F1C9E1BD0C}.Debug|Win32.Build.0 = Debug|Win32
+ {1B2485B2-CFED-4B2F-8FFD-00F1C9E1BD0C}.Release|Win32.ActiveCfg = Release|Win32
+ {1B2485B2-CFED-4B2F-8FFD-00F1C9E1BD0C}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/native/restarter/restarter.vcproj b/native/restarter/restarter.vcproj
new file mode 100644
index 0000000..00b1b62
--- /dev/null
+++ b/native/restarter/restarter.vcproj
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="restarter"
+ ProjectGUID="{1B2485B2-CFED-4B2F-8FFD-00F1C9E1BD0C}"
+ RootNamespace="restarter"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\restarter.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\targetver.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/native/restarter/stdafx.cpp b/native/restarter/stdafx.cpp
new file mode 100644
index 0000000..ba19d26
--- /dev/null
+++ b/native/restarter/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// restarter.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/native/restarter/stdafx.h b/native/restarter/stdafx.h
new file mode 100644
index 0000000..661cb26
--- /dev/null
+++ b/native/restarter/stdafx.h
@@ -0,0 +1,16 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/native/restarter/targetver.h b/native/restarter/targetver.h
new file mode 100644
index 0000000..6fe8eb7
--- /dev/null
+++ b/native/restarter/targetver.h
@@ -0,0 +1,13 @@
+#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
diff --git a/native/runner/runnerw/.cproject b/native/runner/runnerw/.cproject
new file mode 100644
index 0000000..88d813c
--- /dev/null
+++ b/native/runner/runnerw/.cproject
@@ -0,0 +1,930 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937" name="Debug" parent="cdt.managedbuild.config.gnu.mingw.exe.debug">
+ <folderInfo id="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937." name="/" resourcePath="">
+ <toolChain id="cdt.managedbuild.toolchain.gnu.mingw.exe.debug.76906450" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.exe.debug">
+ <targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.exe.debug.223609992" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.exe.debug"/>
+ <builder buildPath="${workspace_loc:/ctrl/Debug}" id="cdt.managedbuild.tool.gnu.builder.mingw.base.1573221942" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.assembler.mingw.exe.debug.1908513521" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.exe.debug">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.379051527" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.109174919" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug.1973769888" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug">
+ <option id="gnu.cpp.compiler.mingw.exe.debug.option.optimization.level.468688473" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.mingw.exe.debug.option.debugging.level.142197934" name="Debug Level" superClass="gnu.cpp.compiler.mingw.exe.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.653322780" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug.1116667420" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug">
+ <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.mingw.exe.debug.option.optimization.level.1061011190" name="Optimization Level" superClass="gnu.c.compiler.mingw.exe.debug.option.optimization.level" valueType="enumerated"/>
+ <option id="gnu.c.compiler.mingw.exe.debug.option.debugging.level.1308466604" name="Debug Level" superClass="gnu.c.compiler.mingw.exe.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.283876983" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug.1746764158" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.debug.1787210394" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.debug">
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.80319251" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937;cdt.managedbuild.config.gnu.mingw.exe.debug.997820937.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug.1116667420;cdt.managedbuild.tool.gnu.c.compiler.input.283876983">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937;cdt.managedbuild.config.gnu.mingw.exe.debug.997820937.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug.1973769888;cdt.managedbuild.tool.gnu.cpp.compiler.input.653322780">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543;cdt.managedbuild.config.gnu.mingw.exe.release.1721852543.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release.785866164;cdt.managedbuild.tool.gnu.c.compiler.input.329344628">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543;cdt.managedbuild.config.gnu.mingw.exe.release.1721852543.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release.365012512;cdt.managedbuild.tool.gnu.cpp.compiler.input.1002359615">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ <storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+ <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+ </cconfiguration>
+ <cconfiguration id="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543" moduleId="org.eclipse.cdt.core.settings" name="Release">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543" name="Release" parent="cdt.managedbuild.config.gnu.mingw.exe.release">
+ <folderInfo id="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543." name="/" resourcePath="">
+ <toolChain id="cdt.managedbuild.toolchain.gnu.mingw.exe.release.361025673" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.exe.release">
+ <targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.exe.release.468608892" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.exe.release"/>
+ <builder buildPath="${workspace_loc:/ctrl/Release}" id="cdt.managedbuild.tool.gnu.builder.mingw.base.1142893062" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.assembler.mingw.exe.release.1956491820" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.exe.release">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1756997610" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.1701497354" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release.365012512" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release">
+ <option id="gnu.cpp.compiler.mingw.exe.release.option.optimization.level.426853761" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.mingw.exe.release.option.debugging.level.413813393" name="Debug Level" superClass="gnu.cpp.compiler.mingw.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1002359615" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release.785866164" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release">
+ <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.mingw.exe.release.option.optimization.level.1885088619" name="Optimization Level" superClass="gnu.c.compiler.mingw.exe.release.option.optimization.level" valueType="enumerated"/>
+ <option id="gnu.c.compiler.mingw.exe.release.option.debugging.level.752474157" name="Debug Level" superClass="gnu.c.compiler.mingw.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.329344628" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.release.1810930910" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.release"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.release.50479936" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.release">
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.216386897" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937;cdt.managedbuild.config.gnu.mingw.exe.debug.997820937.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug.1116667420;cdt.managedbuild.tool.gnu.c.compiler.input.283876983">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.997820937;cdt.managedbuild.config.gnu.mingw.exe.debug.997820937.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug.1973769888;cdt.managedbuild.tool.gnu.cpp.compiler.input.653322780">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543;cdt.managedbuild.config.gnu.mingw.exe.release.1721852543.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release.785866164;cdt.managedbuild.tool.gnu.c.compiler.input.329344628">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.1721852543;cdt.managedbuild.config.gnu.mingw.exe.release.1721852543.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release.365012512;cdt.managedbuild.tool.gnu.cpp.compiler.input.1002359615">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="makefileGenerator">
+ <runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+ <buildOutputProvider>
+ <openAction enabled="true" filePath=""/>
+ <parser enabled="true"/>
+ </buildOutputProvider>
+ <scannerInfoProvider id="specsFile">
+ <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
+ <parser enabled="true"/>
+ </scannerInfoProvider>
+ </profile>
+ </scannerConfigBuildInfo>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ <storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+ <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="ctrl.cdt.managedbuild.target.gnu.mingw.exe.1910147551" name="Executable" projectType="cdt.managedbuild.target.gnu.mingw.exe"/>
+ </storageModule>
+</cproject>
diff --git a/native/runner/runnerw/.project b/native/runner/runnerw/.project
new file mode 100644
index 0000000..cc8212c
--- /dev/null
+++ b/native/runner/runnerw/.project
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>runnerw</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ <dictionary>
+ <key>?name?</key>
+ <value></value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.append_environment</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.buildArguments</key>
+ <value></value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.buildCommand</key>
+ <value>make</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.buildLocation</key>
+ <value>${workspace_loc:/ctrl/Debug}</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.contents</key>
+ <value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+ <value>false</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableFullBuild</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.stopOnError</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+ <value>true</value>
+ </dictionary>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.core.ccnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+</projectDescription>
diff --git a/native/runner/runnerw/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/native/runner/runnerw/.settings/org.eclipse.cdt.managedbuilder.core.prefs
new file mode 100644
index 0000000..0f163f7
--- /dev/null
+++ b/native/runner/runnerw/.settings/org.eclipse.cdt.managedbuilder.core.prefs
@@ -0,0 +1,14 @@
+#Fri Jul 16 15:25:34 MSD 2010
+eclipse.preferences.version=1
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/CPATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/CPATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/CPLUS_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/CPLUS_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/C_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/C_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/append=true
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/appendContributed=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/LIBRARY_PATH/delimiter=;
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/LIBRARY_PATH/operation=remove
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/append=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.997820937/appendContributed=true
diff --git a/native/runner/runnerw/.settings/org.eclipse.core.resources.prefs b/native/runner/runnerw/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..a3fdc8b
--- /dev/null
+++ b/native/runner/runnerw/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Sat Jul 17 17:27:10 MSD 2010
+eclipse.preferences.version=1
+encoding/runnerw.cpp=Cp1251
diff --git a/native/runner/runnerw/runnerw.cpp b/native/runner/runnerw/runnerw.cpp
new file mode 100644
index 0000000..a389ba5
--- /dev/null
+++ b/native/runner/runnerw/runnerw.cpp
@@ -0,0 +1,226 @@
+#include <windows.h>
+#include <stdio.h>
+#include <tlhelp32.h>
+#include <iostream>
+#include <string>
+
+void PrintUsage() {
+ printf("Usage: runnerw.exe <app> <args>\n");
+ printf("where <app> is console application and <args> it's arguments.\n");
+ printf("\n");
+ printf(
+ "Runner invokes console application as a process with inherited input and output streams.\n");
+ printf(
+ "Input stream is scanned for presence of 2 char 255(IAC) and 243(BRK) sequence and generates Ctrl-Break event in that case.\n");
+ printf(
+ "Also in case of all type of event(Ctrl-C, Close, Shutdown etc) Ctrl-Break event is generated.\n");
+
+ exit(0);
+}
+
+void ErrorMessage(char *str) {
+
+ LPVOID msg;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &msg, 0, NULL);
+
+ printf("%s: %s\n", str, msg);
+ LocalFree(msg);
+}
+
+void CtrlBreak() {
+ if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0)) {
+ ErrorMessage("GenerateConsoleCtrlEvent");
+ }
+}
+
+BOOL is_iac = FALSE;
+
+char IAC = 5;
+char BRK = 3;
+
+BOOL Scan(char buf[], int count) {
+ for (int i = 0; i < count; i++) {
+ if (is_iac) {
+ if (buf[i] == BRK) {
+ CtrlBreak();
+ return TRUE;
+ } else {
+ is_iac = FALSE;
+ }
+ }
+ if (buf[i] == IAC) {
+ is_iac = TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL CtrlHandler(DWORD fdwCtrlType) {
+ switch (fdwCtrlType) {
+ case CTRL_C_EVENT:
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ CtrlBreak();
+ return (TRUE);
+ case CTRL_BREAK_EVENT:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+struct StdInThreadParams {
+ HANDLE hEvent;
+ HANDLE write_stdin;
+};
+
+DWORD WINAPI StdInThread(void *param) {
+ StdInThreadParams *threadParams = (StdInThreadParams *) param;
+ char buf[1];
+ memset(buf, 0, sizeof(buf));
+
+ HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ while (true) {
+ DWORD cbRead = 0;
+ DWORD cbWrite = 0;
+
+ char c;
+ ReadFile(hStdin, &c, 1, &cbRead, NULL);
+ if (cbRead > 0) {
+ buf[0] = c;
+ bool ctrlBroken = Scan(buf, 1);
+ WriteFile(threadParams->write_stdin, buf, 1, &cbWrite, NULL);
+ if (ctrlBroken) {
+ SetEvent(threadParams->hEvent);
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+bool hasEnding(std::string const &fullString, std::string const &ending) {
+ if (fullString.length() > ending.length()) {
+ return (0 == fullString.compare(fullString.length() - ending.length(),
+ ending.length(), ending));
+ } else {
+ return false;
+ }
+}
+
+int main(int argc, char * argv[]) {
+ if (argc < 2) {
+ PrintUsage();
+ }
+
+ std::string app(argv[1]);
+ std::string args("");
+
+ for (int i = 1; i < argc; i++) {
+ if (i>1) {
+ args += " ";
+ }
+ if (strchr(argv[i], ' ')) {
+ args += "\"";
+ args += argv[i];
+ args += "\"";
+ } else {
+ args += argv[i];
+ }
+ }
+
+// if (app.length() == 0) {
+// PrintUsage();
+// }
+
+ STARTUPINFO si;
+ SECURITY_ATTRIBUTES sa;
+ PROCESS_INFORMATION pi;
+
+ HANDLE newstdin, write_stdin;
+
+ sa.lpSecurityDescriptor = NULL;
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = true;
+
+ if (!CreatePipe(&newstdin, &write_stdin, &sa, 0)) {
+ ErrorMessage("CreatePipe");
+ exit(0);
+ }
+
+ GetStartupInfo(&si);
+
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.wShowWindow = SW_HIDE;
+ si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.hStdInput = newstdin;
+
+ if (hasEnding(app, std::string(".bat"))) {
+// in MSDN it is said to do so, but actually that doesn't work
+// args = "/c " + args;
+// app = "cmd.exe";
+ } else {
+ app = "";
+ }
+
+
+ char* c_app = NULL;
+
+ if (app.size()>0) {
+ c_app = new char[app.size() + 1];
+ strcpy(c_app, app.c_str());
+ }
+
+
+ char* c_args = new char[args.size() + 1];
+ strcpy(c_args, args.c_str());
+
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
+
+ if (!CreateProcess(c_app, // Application name
+ c_args, // Application arguments
+ NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi)) {
+ ErrorMessage("CreateProcess");
+ CloseHandle(newstdin);
+ CloseHandle(write_stdin);
+ exit(0);
+ }
+
+ unsigned long exit = 0;
+ unsigned long b_read;
+ unsigned long avail;
+
+ HANDLE threadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ StdInThreadParams params;
+ params.hEvent = threadEvent;
+ params.write_stdin = write_stdin;
+
+ CreateThread(NULL, 0, &StdInThread, ¶ms, 0, NULL);
+
+ HANDLE objects_to_wait[2];
+ objects_to_wait[0] = threadEvent;
+ objects_to_wait[1] = pi.hProcess;
+
+ while (true) {
+ int rc = WaitForMultipleObjects(2, objects_to_wait, FALSE, INFINITE);
+ if (rc == WAIT_OBJECT_0 + 1) {
+ break;
+ }
+ }
+
+ GetExitCodeProcess(pi.hProcess, &exit);
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ CloseHandle(newstdin);
+ CloseHandle(write_stdin);
+ return exit;
+}