summaryrefslogtreecommitdiff
path: root/plugins/CmdLine/executable/MimCmd
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-04 22:09:42 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-04 22:09:42 +0000
commit801367d0b94426c1160f05aeb6fea70938085894 (patch)
treec8f60e1988ae7e43d4addb8ba2138d8880dfdf9b /plugins/CmdLine/executable/MimCmd
parent65e002b63efdb00571d0ba4ec1a73b14e1d7d3a0 (diff)
CmdLine added, not adopted yet
git-svn-id: http://svn.miranda-ng.org/main/trunk@764 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/CmdLine/executable/MimCmd')
-rw-r--r--plugins/CmdLine/executable/MimCmd/MimCmd.cpp105
-rw-r--r--plugins/CmdLine/executable/MimCmd/MimCmd.vcproj404
-rw-r--r--plugins/CmdLine/executable/MimCmd/commands.cpp239
-rw-r--r--plugins/CmdLine/executable/MimCmd/commands.h44
-rw-r--r--plugins/CmdLine/executable/MimCmd/common.h30
-rw-r--r--plugins/CmdLine/executable/MimCmd/langpack.cpp377
-rw-r--r--plugins/CmdLine/executable/MimCmd/langpack.h92
-rw-r--r--plugins/CmdLine/executable/MimCmd/resource.h14
-rw-r--r--plugins/CmdLine/executable/MimCmd/version.rc100
9 files changed, 1405 insertions, 0 deletions
diff --git a/plugins/CmdLine/executable/MimCmd/MimCmd.cpp b/plugins/CmdLine/executable/MimCmd/MimCmd.cpp
new file mode 100644
index 0000000000..2709d6c034
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/MimCmd.cpp
@@ -0,0 +1,105 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+//why ??
+//Who's using it ?
+PLUGINLINK *pluginLink;
+
+char *GetProgramName(char *programName, int size)
+{
+ char name[512];
+ GetModuleFileName(GetModuleHandle(NULL), name, sizeof(name));
+ char *p = strrchr(name, '\\');
+ if (p)
+ {
+ STRNCPY(programName, p + 1, size);
+ }
+ else{
+ STRNCPY(programName, name, size);
+ }
+
+ return programName;
+}
+
+void PrintUsage()
+{
+ char name[128];
+ GetProgramName(name, sizeof(name));
+
+ lpprintf(Translate("%s usage:\n"), name);
+ lpprintf(Translate("%s <command> [<param> [, <param> ..]]\n"), name);
+ lpprintf(Translate("This will tell Miranda to run the specified command. The commands can have zero, one or more parameters. Use '%s help' to get a list of possible commands.\n"), name);
+ lpprintf(Translate("No command can have more than %d parameters\n"), MAX_ARGUMENTS - 1);
+}
+
+void ShowVersion()
+{
+ char name[128];
+ char message[1024];
+ GetProgramName(name, sizeof(name));
+ mir_snprintf(message, sizeof(message), Translate("%s version %s"), name, __VERSION_STRING);
+
+ lpprintf("%s\n", message);
+}
+
+int main(int argc, char *argv[])
+{
+ int error = 0;
+ if ((argc == 2) && (strcmp(argv[1], "-v") == 0))
+ {
+ ShowVersion();
+
+ return 0;
+ }
+
+ if ((InitClient()) || (ConnectToMiranda()) || (GetKnownCommands()) || (LoadLangPackModule(sdCmdLine->mimFolder)))
+ {
+ LoadLangPackModule(".");
+ lpprintf(Translate("Could not create connection with Miranda or could not retrieve list of known commands.\n"));
+ error = MIMRES_NOMIRANDA;
+ }
+ else{
+ if ((argc <= 1) || (argc > MAX_ARGUMENTS))
+ {
+ PrintUsage();
+ }
+ else{
+ PReply reply = ParseCommand(argv, argc);
+ if (reply)
+ {
+ error = reply->code;
+ lpprintf("%s\n", reply->message);
+ }
+ else{
+ lpprintf(Translate("Unknown command '%s'.\n"), argv[1]);
+ }
+
+ DestroyKnownCommands();
+ DisconnectFromMiranda();
+ DestroyClient();
+ LangPackShutdown();
+ }
+ }
+
+ return error;
+}
+
diff --git a/plugins/CmdLine/executable/MimCmd/MimCmd.vcproj b/plugins/CmdLine/executable/MimCmd/MimCmd.vcproj
new file mode 100644
index 0000000000..fb04bfb375
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/MimCmd.vcproj
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MimCmd"
+ ProjectGUID="{1E3BB48A-FFBC-4A03-8C43-9124A484BE51}"
+ RootNamespace="MimCmd"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\..\..\..\..\cvs\test miranda"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ 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="1"
+ 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="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ 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="1"
+ 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|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ 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="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="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ 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="1"
+ 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=".\commands.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\langpack.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MimCmd.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Detect64BitPortabilityProblems="false"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Detect64BitPortabilityProblems="false"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\CmdLine\mimcmd_ipc.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\commands.h"
+ >
+ </File>
+ <File
+ RelativePath=".\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\langpack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.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=".\version.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/plugins/CmdLine/executable/MimCmd/commands.cpp b/plugins/CmdLine/executable/MimCmd/commands.cpp
new file mode 100644
index 0000000000..b04b9ba7ba
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/commands.cpp
@@ -0,0 +1,239 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "commands.h"
+
+inline char *STRNCPY(char *output, const char *input, size_t size)
+{
+ char *res = strncpy(output, input, size);
+ output[size - 1] = 0;
+
+ return res;
+}
+
+LISTCOMMANDS ListCommands = NULL;
+
+PCommand knownCommands = NULL;
+int cKnownCommands = 0;
+
+HMODULE hCmdLineDLL = NULL;
+
+char *GetMirandaFolder(char *mimFolder, int size)
+{
+ STRNCPY(mimFolder, sdCmdLine->mimFolder, size);
+ mimFolder[size - 1] = 0;
+
+ return mimFolder;
+}
+
+
+int ConnectToMiranda()
+{
+ char pluginPath[1024];
+ GetMirandaFolder(pluginPath, sizeof(pluginPath));
+ strcat(pluginPath, "\\plugins\\cmdline.dll");
+
+ ListCommands = NULL;
+
+ hCmdLineDLL = LoadLibrary(pluginPath);
+
+ int failure = 1;
+ if (hCmdLineDLL)
+ {
+ ListCommands = (LISTCOMMANDS) GetProcAddress(hCmdLineDLL, "ListCommands");
+ }
+
+ if (ListCommands)
+ {
+ failure = 0;
+ }
+
+ return failure;
+}
+
+int DisconnectFromMiranda()
+{
+ return FreeLibrary(hCmdLineDLL);
+}
+
+int GetKnownCommands()
+{
+ ListCommands(&knownCommands, &cKnownCommands);
+
+ return (knownCommands == NULL);
+}
+
+int DestroyKnownCommands()
+{
+
+
+ return 0;
+}
+
+PCommand GetCommand(char *command)
+{
+ int i;
+ char lower[512];
+ STRNCPY(lower, command, sizeof(lower));
+ _strlwr(lower);
+
+ for (i = 0; i < cKnownCommands; i++)
+ {
+ if (strcmp(knownCommands[i].command, lower) == 0)
+ {
+ return &knownCommands[i];
+ }
+ }
+
+ //allow more parameters to trigger the help command - /h -h /? --help
+ if ((strcmp(lower, "/h") == 0) || (strcmp(lower, "-h") == 0) || (strcmp(lower, "/?") == 0) || (strcmp(lower, "--help") == 0))
+ {
+ for (i = 0; i < cKnownCommands; i++)
+ {
+ if (knownCommands[i].ID == MIMCMD_HELP)
+ {
+ return &knownCommands[i];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void HandleHelpCommand(PCommand helpCommand, char *argv[], int argc, PReply reply)
+{
+ const int size = REPLY_SIZE;
+ if (argc >= 3)
+ {
+ PCommand command = GetCommand(argv[2]);
+
+ if (command)
+ {
+ reply->code = MIMRES_SUCCESS;
+ STRNCPY(reply->message, Translate(command->help), size);
+ }
+ else{
+ reply->code = MIMRES_NOTFOUND;
+ _snprintf(reply->message, size, Translate("No help for '%s'."), argv[2]);
+ reply->message[size -1 ] = 0;
+ }
+ }
+ else{
+ reply->code = MIMRES_SUCCESS;
+ STRNCPY(reply->message, Translate("Available commands: "), size);
+
+ int i;
+ for (i = 0; i < cKnownCommands - 1; i++)
+ {
+ strncat(reply->message, knownCommands[i].command, size);
+ strncat(reply->message, ", ", size);
+ }
+ strncat(reply->message, knownCommands[cKnownCommands - 1].command, size);
+ strncat(reply->message, ".", size);
+ }
+}
+
+PReply ParseCommand(char *argv[], int argc)
+{
+ PCommand command = GetCommand(argv[1]);
+ if (command)
+ {
+ PReply reply = &sdCmdLine->reply;
+ if (command->ID == MIMCMD_HELP)
+ {
+ HandleHelpCommand(command, argv, argc, reply);
+ }
+ else{
+ ProcessConsoleCommand(command, argv, argc, reply);
+ }
+
+ return reply;
+ }
+ else{
+ return NULL;
+ }
+}
+
+void FillSharedDataStruct(PCommand command, char *arguments[], int count)
+{
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ STRNCPY(sdCmdLine->arguments[i], arguments[i], ARGUMENT_SIZE);
+ }
+
+ sdCmdLine->cArguments = count;
+ sdCmdLine->command = *command;
+ *sdCmdLine->reply.message = 0;
+ sdCmdLine->reply.code =-1;
+}
+
+void ProcessConsoleCommand(PCommand command, char *arguments[], int count, PReply reply)
+{
+ const HANDLE events[] = {heServerDone, heServerClose, heServerBufferFull};
+ const int cEvents = sizeof(events) / sizeof(events[0]);
+
+ if (WaitForSingleObject(hmClient, INFINITE) == WAIT_OBJECT_0)
+ {//got the mutex, we're the only one who can talk to miranda now
+ FillSharedDataStruct(command, arguments, count);
+ SetEvent(heServerExec); //tell Miranda to process the request
+
+ int done = FALSE;
+ while (!done)
+ {
+ switch (WaitForMultipleObjects(cEvents, events, FALSE, INFINITE)) //wait until server either finished processing or miranda was closed
+ {
+ case WAIT_OBJECT_0: //done event
+ {
+ done = TRUE;
+
+ break; //nothing to do
+ }
+
+ case WAIT_OBJECT_0 + 1: //close event
+ default:
+ {
+ strcpy(sdCmdLine->reply.message, Translate("Miranda has been closed or an error has occured while waiting for the result, could not process request."));
+ done = TRUE;
+
+ break;
+ }
+
+ case WAIT_OBJECT_0 + 2: //buffer full event
+ {
+ lpprintf("%s", reply->message);
+
+ break;
+ }
+ }
+ }
+
+ reply->code = sdCmdLine->reply.code;
+ STRNCPY(reply->message, sdCmdLine->reply.message, REPLY_SIZE);
+
+ ReleaseMutex(hmClient); //let other possible clients talk to the server
+ }
+ else{
+ int err = GetLastError();
+ reply->code = -1;
+ *reply->message = 0;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/commands.h b/plugins/CmdLine/executable/MimCmd/commands.h
new file mode 100644
index 0000000000..04cc640f48
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/commands.h
@@ -0,0 +1,44 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_MIMCMD_COMMANDS_H
+#define M_MIMCMD_COMMANDS_H
+
+#include "common.h"
+
+extern PCommand knownCommands;
+extern int cKnownCommands;
+
+typedef void (* LISTCOMMANDS)(PCommand *commands, int *count);
+
+extern LISTCOMMANDS ListCommands;
+
+char *GetMirandaFolder();
+
+int ConnectToMiranda();
+int DisconnectFromMiranda();
+int GetKnownCommands();
+int DestroyKnownCommands();
+
+PCommand GetCommand(char *command);
+PReply ParseCommand(char *argv[], int argc);
+void ProcessConsoleCommand(PCommand command, char *arguments[], int count, PReply reply);
+
+#endif \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/common.h b/plugins/CmdLine/executable/MimCmd/common.h
new file mode 100644
index 0000000000..8361cc24d4
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/common.h
@@ -0,0 +1,30 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <windows.h>
+#include <string.h>
+
+#define NO_MIMCMD_COMMANDS
+
+#include "../../cmdline/mimcmd_data.h"
+#include "../../cmdline/mimcmd_ipc.h"
+#include "commands.h"
+#include "langpack.h" \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/langpack.cpp b/plugins/CmdLine/executable/MimCmd/langpack.cpp
new file mode 100644
index 0000000000..096431f95b
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/langpack.cpp
@@ -0,0 +1,377 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//this code is mostly taken from Miranda's langpack module.
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2007 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "langpack.h"
+
+static __inline int mir_snprintf(char *buffer, size_t count, const char* fmt, ...) {
+ va_list va;
+ int len;
+
+ va_start(va, fmt);
+ len = _vsnprintf(buffer, count-1, fmt, va);
+ va_end(va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+int lpprintf(const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ const int MAX_SIZE = 16192;
+ char buffer[MAX_SIZE] = {0};
+ int len = _vsnprintf(buffer, MAX_SIZE - 1, format, va);
+ buffer[MAX_SIZE - 1] = 0;
+ va_end(va);
+ CharToOemBuff(buffer, buffer, len);
+ printf("%s", buffer);
+
+ return len;
+}
+
+static void TrimString(char *str)
+{
+ int len,start;
+ len=lstrlenA(str);
+ while(str[0] && (unsigned char)str[len-1]<=' ') str[--len]=0;
+ for(start=0;str[start] && (unsigned char)str[start]<=' ';start++);
+ MoveMemory(str,str+start,len-start+1);
+}
+
+static void TrimStringSimple(char *str)
+{
+ if (str[lstrlenA(str)-1] == '\n') str[lstrlenA(str)-1] = '\0';
+ if (str[lstrlenA(str)-1] == '\r') str[lstrlenA(str)-1] = '\0';
+}
+
+static int IsEmpty(char *str)
+{
+ int i = 0;
+
+ while (str[i])
+ {
+ if (str[i]!=' '&&str[i]!='\r'&&str[i]!='\n')
+ return 0;
+ i++;
+ }
+ return 1;
+}
+
+static void ConvertBackslashes(char *str)
+{
+ char *pstr;
+
+ for(pstr=str;*pstr;pstr=CharNextA(pstr)) {
+ if(*pstr=='\\') {
+ switch(pstr[1]) {
+case 'n': *pstr='\n'; break;
+case 't': *pstr='\t'; break;
+case 'r': *pstr='\r'; break;
+default: *pstr=pstr[1]; break;
+ }
+ MoveMemory(pstr+1,pstr+2,lstrlenA(pstr+2)+1);
+ }
+ }
+}
+
+static DWORD LangPackHash(const char *szStr)
+{
+#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined __GNUC__
+ __asm { //this is mediocrely optimised, but I'm sure it's good enough
+ xor edx,edx
+ mov esi,szStr
+ xor cl,cl
+lph_top:
+ xor eax,eax
+ and cl,31
+ mov al,[esi]
+ inc esi
+ test al,al
+ jz lph_end
+ rol eax,cl
+ add cl,5
+ xor edx,eax
+ jmp lph_top
+lph_end:
+ mov eax,edx
+ }
+#else
+ DWORD hash=0;
+ int i;
+ int shift=0;
+ for(i=0;szStr[i];i++) {
+ hash^=szStr[i]<<shift;
+ if(shift>24) hash^=(szStr[i]>>(32-shift))&0x7F;
+ shift=(shift+5)&0x1F;
+ }
+ return hash;
+#endif
+}
+
+static DWORD LangPackHashW(const char *szStr)
+{
+#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined __GNUC__
+ __asm { //this is mediocrely optimised, but I'm sure it's good enough
+ xor edx,edx
+ mov esi,szStr
+ xor cl,cl
+lph_top:
+ xor eax,eax
+ and cl,31
+ mov al,[esi]
+ inc esi
+ inc esi
+ test al,al
+ jz lph_end
+ rol eax,cl
+ add cl,5
+ xor edx,eax
+ jmp lph_top
+lph_end:
+ mov eax,edx
+ }
+#else
+ DWORD hash=0;
+ int i;
+ int shift=0;
+ for(i=0;szStr[i];i+=2) {
+ hash^=szStr[i]<<shift;
+ if(shift>24) hash^=(szStr[i]>>(32-shift))&0x7F;
+ shift=(shift+5)&0x1F;
+ }
+ return hash;
+#endif
+}
+
+static int SortLangPackHashesProc(struct LangPackEntry *arg1,struct LangPackEntry *arg2)
+{
+ if(arg1->englishHash<arg2->englishHash) return -1;
+ if(arg1->englishHash>arg2->englishHash) return 1;
+ /* both source strings of the same hash (may not be the same string thou) put
+ the one that was written first to be found first */
+ if(arg1->linePos<arg2->linePos) return -1;
+ if(arg1->linePos>arg2->linePos) return 1;
+ return 0;
+}
+
+
+static int SortLangPackHashesProc2(struct LangPackEntry *arg1,struct LangPackEntry *arg2)
+{
+ if(arg1->englishHash<arg2->englishHash) return -1;
+ if(arg1->englishHash>arg2->englishHash) return 1;
+ return 0;
+}
+
+static int LoadLangPack(const TCHAR *szLangPack)
+{
+ FILE *fp;
+ char line[4096];
+ char *pszColon;
+ char *pszLine;
+ int entriesAlloced;
+ int startOfLine=0;
+ unsigned int linePos=1;
+ USHORT langID;
+
+ lstrcpy(langPack.filename,szLangPack);
+ fp = _tfopen(szLangPack,_T("rt"));
+ if(fp==NULL) return 1;
+ fgets(line,SIZEOF(line),fp);
+ TrimString(line);
+ if(lstrcmpA(line,"Miranda Language Pack Version 1")) {fclose(fp); return 2;}
+ //headers
+ while(!feof(fp)) {
+ startOfLine=ftell(fp);
+ if(fgets(line,SIZEOF(line),fp)==NULL) break;
+ TrimString(line);
+ if(IsEmpty(line) || line[0]==';' || line[0]==0) continue;
+ if(line[0]=='[') break;
+ pszColon=strchr(line,':');
+ if(pszColon==NULL) {fclose(fp); return 3;}
+ *pszColon=0;
+ if(!lstrcmpA(line,"Language")) {mir_snprintf(langPack.language,sizeof(langPack.language),"%s",pszColon+1); TrimString(langPack.language);}
+ else if(!lstrcmpA(line,"Last-Modified-Using")) {mir_snprintf(langPack.lastModifiedUsing,sizeof(langPack.lastModifiedUsing),"%s",pszColon+1); TrimString(langPack.lastModifiedUsing);}
+ else if(!lstrcmpA(line,"Authors")) {mir_snprintf(langPack.authors,sizeof(langPack.authors),"%s",pszColon+1); TrimString(langPack.authors);}
+ else if(!lstrcmpA(line,"Author-email")) {mir_snprintf(langPack.authorEmail,sizeof(langPack.authorEmail),"%s",pszColon+1); TrimString(langPack.authorEmail);}
+ else if(!lstrcmpA(line, "Locale")) {
+ char szBuf[20], *stopped;
+
+ TrimString(pszColon + 1);
+ langID = (USHORT)strtol(pszColon + 1, &stopped, 16);
+ langPack.localeID = MAKELCID(langID, 0);
+ GetLocaleInfoA(langPack.localeID, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10);
+ szBuf[5] = 0; // codepages have max. 5 digits
+ langPack.defaultANSICp = atoi(szBuf);
+ }
+ }
+ //body
+ fseek(fp,startOfLine,SEEK_SET);
+ entriesAlloced=0;
+ while(!feof(fp)) {
+ if(fgets(line,SIZEOF(line),fp)==NULL) break;
+ if(IsEmpty(line) || line[0]==';' || line[0]==0) continue;
+ TrimStringSimple(line);
+ ConvertBackslashes(line);
+ if(line[0]=='[' && line[lstrlenA(line)-1]==']') {
+ if(langPack.entryCount && langPack.entry[langPack.entryCount-1].local==NULL) {
+ if(langPack.entry[langPack.entryCount-1].english!=NULL) free(langPack.entry[langPack.entryCount-1].english);
+ langPack.entryCount--;
+ }
+ pszLine = line+1;
+ line[lstrlenA(line)-1]='\0';
+ //TrimStringSimple(line);
+ if(++langPack.entryCount>entriesAlloced) {
+ entriesAlloced+=128;
+ langPack.entry=(struct LangPackEntry*)realloc(langPack.entry,sizeof(struct LangPackEntry)*entriesAlloced);
+ }
+ langPack.entry[langPack.entryCount-1].english=NULL;
+ langPack.entry[langPack.entryCount-1].englishHash=LangPackHash(pszLine);
+ langPack.entry[langPack.entryCount-1].local=NULL;
+ langPack.entry[langPack.entryCount-1].wlocal = NULL;
+ langPack.entry[langPack.entryCount-1].linePos=linePos++;
+ }
+ else if(langPack.entryCount) {
+ struct LangPackEntry* E = &langPack.entry[langPack.entryCount-1];
+
+ if(E->local==NULL) {
+ E->local=_strdup(line);
+ {
+ size_t iNeeded = MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, 0, 0);
+ E->wlocal = (wchar_t *)malloc((int) ((iNeeded+1) * sizeof(wchar_t)));
+ MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, E->wlocal, (int) iNeeded);
+ }
+ }
+ else {
+ E->local=(char*)realloc(E->local,lstrlenA(E->local)+lstrlenA(line)+2);
+ lstrcatA(E->local,"\n");
+ lstrcatA(E->local,line);
+ {
+ size_t iNeeded = MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, 0, 0);
+ size_t iOldLen = wcslen(E->wlocal);
+ E->wlocal = (wchar_t*)realloc(E->wlocal, ( sizeof(wchar_t) * ( iOldLen + iNeeded + 2)));
+ wcscat(E->wlocal, L"\n");
+ MultiByteToWideChar( langPack.defaultANSICp, 0, line, -1, E->wlocal + iOldLen+1, (int) iNeeded);
+ }
+ }
+ }
+ }
+ qsort(langPack.entry,langPack.entryCount,sizeof(struct LangPackEntry),(int(*)(const void*,const void*))SortLangPackHashesProc);
+ fclose(fp);
+ return 0;
+}
+
+char *LangPackTranslateString(const char *szEnglish, const int W)
+{
+ struct LangPackEntry key,*entry;
+
+ if ( langPack.entryCount == 0 || szEnglish == NULL ) return (char*)szEnglish;
+
+
+ key.englishHash = W ? LangPackHashW(szEnglish) : LangPackHash(szEnglish);
+ entry=(struct LangPackEntry*)bsearch(&key,langPack.entry,langPack.entryCount,sizeof(struct LangPackEntry),(int(*)(const void*,const void*))SortLangPackHashesProc2);
+ if(entry==NULL) return (char*)szEnglish;
+ while(entry>langPack.entry)
+ {
+ entry--;
+ if(entry->englishHash!=key.englishHash) {
+ entry++;
+ return W ? (char *)entry->wlocal : entry->local;
+ }
+ }
+ return W ? (char *)entry->wlocal : entry->local;
+}
+
+int LangPackGetDefaultCodePage()
+{
+ return (langPack.defaultANSICp == 0) ? CP_ACP : langPack.defaultANSICp;
+}
+
+int LangPackGetDefaultLocale()
+{
+ return (langPack.localeID == 0) ? LOCALE_USER_DEFAULT : langPack.localeID;
+}
+
+int LangPackShutdown()
+{
+ int i;
+ for(i=0;i<langPack.entryCount;i++) {
+ if(langPack.entry[i].english!=NULL) free(langPack.entry[i].english);
+ if(langPack.entry[i].local!=NULL) { free(langPack.entry[i].local); }
+ if(langPack.entry[i].wlocal!=NULL) { free(langPack.entry[i].wlocal); }
+ }
+ if(langPack.entryCount) {
+ free(langPack.entry);
+ langPack.entry=0;
+ langPack.entryCount=0;
+ }
+
+ return 0;
+}
+
+int LoadLangPackModule(char *mirandaPath)
+{
+ HANDLE hFind;
+ TCHAR szSearch[MAX_PATH],*str2,szLangPack[MAX_PATH];
+ WIN32_FIND_DATA fd;
+
+ ZeroMemory(&langPack,sizeof(langPack));
+
+ strncpy(szSearch, mirandaPath, SIZEOF(szSearch));
+ szSearch[SIZEOF(szSearch) - 1] = 0;
+ strcat(szSearch, "\\");
+
+ str2=_tcsrchr(szSearch,'\\');
+ if(str2!=NULL) *str2=0;
+ else str2=szSearch;
+ lstrcat( szSearch, _T("\\langpack_*.txt"));
+ hFind = FindFirstFile( szSearch, &fd );
+ if( hFind != INVALID_HANDLE_VALUE ) {
+ lstrcpy(str2+1,fd.cFileName);
+ lstrcpy(szLangPack,szSearch);
+ FindClose(hFind);
+ LoadLangPack(szLangPack);
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/langpack.h b/plugins/CmdLine/executable/MimCmd/langpack.h
new file mode 100644
index 0000000000..15d6b301b5
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/langpack.h
@@ -0,0 +1,92 @@
+/*
+CmdLine plugin for Miranda IM
+
+Copyright © 2007 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//this code is mostly taken from Miranda's langpack module.
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2007 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_MIMCMD_LANGPACK_H
+#define M_MIMCMD_LANGPACK_H
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <tchar.h>
+#include <locale.h>
+
+
+#define SIZEOF(X) (sizeof(X)/sizeof(X[0]))
+
+struct LangPackEntry {
+ unsigned linePos;
+ DWORD englishHash;
+ char *english; //not currently used, the hash does everything
+ char *local;
+ wchar_t *wlocal;
+};
+
+struct LangPackStruct {
+ TCHAR filename[MAX_PATH];
+ char language[64];
+ char lastModifiedUsing[64];
+ char authors[256];
+ char authorEmail[128];
+ struct LangPackEntry *entry;
+ int entryCount;
+ LCID localeID;
+ DWORD defaultANSICp;
+} static langPack = {0};
+
+#ifdef Translate
+#undef Translate
+#define Translate(s) LangPackTranslateString(s, 0)
+#endif
+
+char *LangPackTranslateString(const char *szEnglish, const int W);
+int LangPackGetDefaultCodePage();
+int LangPackGetDefaultLocale();
+
+int LangPackShutdown();
+int LoadLangPackModule(char *mirandaPath);
+
+int lpprintf(const char *format, ...);
+
+#endif \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/resource.h b/plugins/CmdLine/executable/MimCmd/resource.h
new file mode 100644
index 0000000000..c3bc570152
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by version.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/plugins/CmdLine/executable/MimCmd/version.rc b/plugins/CmdLine/executable/MimCmd/version.rc
new file mode 100644
index 0000000000..67a109eebf
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/version.rc
@@ -0,0 +1,100 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+#include "..\..\CmdLine\version.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#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 __PLUGINVERSION_STRING
+ PRODUCTVERSION __PLUGINVERSION_STRING
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Author", __AUTHOR
+ VALUE "FileDescription", __DESC
+ VALUE "FileVersion", __VERSION_STRING
+ VALUE "InternalName", __PLUGIN_DISPLAY_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+