summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Fergeau <cfergeau@redhat.com>2013-10-23 15:35:10 +0200
committerChristophe Fergeau <cfergeau@redhat.com>2013-10-23 15:35:10 +0200
commit8098a6dd71c42c5276846cd5da8314e0f248b7ce (patch)
treea952d73fa8142e4e3ffa2c9bab9c8ee8d78dc45f
Initial import of SpiceXHEADmaster
This is the source code for an ActiveX plugin used to bridge the oVirt portal with remote-viewer.
-rw-r--r--AUTHORS5
-rw-r--r--BuildCab.bat35
-rw-r--r--COPYING339
-rw-r--r--OSpiceX.bmpbin0 -> 246 bytes
-rw-r--r--OSpiceX.cpp1485
-rw-r--r--OSpiceX.h454
-rw-r--r--OSpiceX.rgs.template34
-rw-r--r--OSpiceX_x64.htm443
-rw-r--r--OSpiceX_x86.htm443
-rw-r--r--PreBuild.bat21
-rw-r--r--ReadMe.txt71
-rw-r--r--Sign.bat11
-rw-r--r--SpiceX.cpp106
-rw-r--r--SpiceX.ddf8
-rw-r--r--SpiceX.def10
-rw-r--r--SpiceX.idl150
-rw-r--r--SpiceX.inf.template24
-rw-r--r--SpiceX.rc146
-rw-r--r--SpiceX.rgs11
-rw-r--r--SpiceX.sln26
-rw-r--r--SpiceX.vcproj634
-rw-r--r--SpiceXCommon.h47
-rw-r--r--SpiceXPS.vcproj189
-rw-r--r--SpiceXps.def9
-rw-r--r--_IOSpiceXEvents_CP.h72
-rw-r--r--debug.cpp137
-rw-r--r--debug.h55
-rw-r--r--resource.h26
-rw-r--r--security.h93
-rw-r--r--stdafx.cpp12
-rw-r--r--stdafx.h55
-rw-r--r--stdint.h396
-rw-r--r--virt-viewer.inf12
33 files changed, 5559 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..0853145
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,5 @@
+Arnon Gilboa
+Uri Lublin
+Christophe Fergeau
+Alon Levy
+Marc-Andre Lureau
diff --git a/BuildCab.bat b/BuildCab.bat
new file mode 100644
index 0000000..6bcba38
--- /dev/null
+++ b/BuildCab.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+REM
+REM Build SpiceX.cab file script.
+REM
+REM %1 = $(OutDir)
+REM %2 = $(ConfigurationName)
+REM %3 = $(PlatformName)
+REM
+
+if not defined REDC_BUILD_DIR set REDC_BUILD_DIR=..\red\windows
+
+if "%3" == "Win32" (
+set LIB=lib
+set CAB=SpiceX_x86.cab
+) else if "%3" == "x64" (
+set LIB=lib64
+set CAB=SpiceX_x64.cab
+)
+
+echo LIB=%LIB%
+echo CAB=%CAB%
+
+if "%2" == "Release" (
+set CELTDLL=%SPICE_LIBS%\%LIB%\libcelt_0_5_1.dll
+) else if "%2" == "Debug" (
+set CELTDLL=%SPICE_LIBS%\%LIB%\libcelt_0_5_1D.dll
+)
+echo %CELTDLL%
+
+del %1\%CAB%
+SignTool sign /s MY /n "Red Hat, Inc." /t http://timestamp.verisign.com/scripts/timstamp.dll %1\SpiceX.dll
+MakeCab /F SpiceX.ddf /D DiskDirectory1=%1 /D CabinetName1=%CAB% ^
+ /D file1=%1\SpiceX.dll /D file2=%CELTDLL% /D file3=%REDC_BUILD_DIR%\%1\spicec.exe /D file4=SpiceX.inf
+SignTool sign /s MY /n "Red Hat, Inc." /t http://timestamp.verisign.com/scripts/timstamp.dll %1\%CAB%
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/OSpiceX.bmp b/OSpiceX.bmp
new file mode 100644
index 0000000..6835498
--- /dev/null
+++ b/OSpiceX.bmp
Binary files differ
diff --git a/OSpiceX.cpp b/OSpiceX.cpp
new file mode 100644
index 0000000..869ef3b
--- /dev/null
+++ b/OSpiceX.cpp
@@ -0,0 +1,1485 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+// OSpiceX.cpp : Implementation of COSpiceX
+#include "stdafx.h"
+
+#pragma warning(disable: 4995) // 'gets' (and more): name was marked as #pragma deprecated
+#include <sstream>
+
+#include "OSpiceX.h"
+#include <spice/controller_prot.h>
+#include <spice/error_codes.h>
+#include <security.h>
+
+// MSDN: The maximum length of this string is 32K characters.
+// ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.WIN32COM.v10.en/dllproc/base/createprocess.htm
+#define CMDLINE_LENGTH 32768
+
+#define SPICE_X_DLL _T("SpiceX.DLL")
+
+// COSpiceX
+
+DWORD WINAPI COSpiceX::event_thread(PVOID pv)
+{
+ COSpiceX* spicex = (COSpiceX*)pv;
+ HANDLE events[2] = {spicex->m_OverlappedRead.hEvent, spicex->m_OverlappedWrite.hEvent};
+ bool running = true;
+ ControllerValue msg;
+ DWORD error_code;
+ DWORD exit_code;
+ DWORD wait_res;
+
+ //Handles only ControllerValue msgs
+ ReadFile(spicex->m_hClientPipe, &msg, sizeof(msg), NULL, &spicex->m_OverlappedRead);
+ while (running) {
+ wait_res = WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ switch (wait_res) {
+ case WAIT_OBJECT_0:
+ running = spicex->handle_in_msg(msg);
+ break;
+ case WAIT_OBJECT_0 + 1:
+ running = spicex->handle_out_msg();
+ break;
+ case WAIT_FAILED:
+ LOG_INFO("WaitForMultipleObjects failed, err=%lu", GetLastError());
+ running = false;
+ break;
+ }
+ }
+
+ //Wait for proccess to terminate
+ wait_res = WaitForSingleObject(spicex->m_hClientProcess, 3000);
+
+ //Handle errors
+ if (wait_res != WAIT_OBJECT_0 || !GetExitCodeProcess(spicex->m_hClientProcess, &exit_code) ||
+ exit_code == STILL_ACTIVE) {
+ TerminateProcess(spicex->m_hClientProcess, 0);
+ CloseHandle(spicex->m_hClientProcess);
+ spicex->m_hClientProcess = NULL;
+ exit_code = SPICEC_ERROR_CODE_ERROR;
+ }
+
+ switch (exit_code) {
+ case SPICEC_ERROR_CODE_SUCCESS:
+ error_code = RDP_ERROR_CODE_LOCAL_DISCONNECTION;
+ break;
+ case SPICEC_ERROR_CODE_GETHOSTBYNAME_FAILED:
+ error_code = RDP_ERROR_CODE_HOST_NOT_FOUND;
+ break;
+ case SPICEC_ERROR_CODE_CONNECT_FAILED:
+ error_code = RDP_ERROR_CODE_WINSOCK_CONNECT_FAILED;
+ break;
+ case SPICEC_ERROR_CODE_ERROR:
+ case SPICEC_ERROR_CODE_SOCKET_FAILED:
+ error_code = RDP_ERROR_CODE_INTERNAL_ERROR;
+ break;
+ case SPICEC_ERROR_CODE_RECV_FAILED:
+ error_code = RDP_ERROR_RECV_WINSOCK_FAILED;
+ break;
+ case SPICEC_ERROR_CODE_SEND_FAILED:
+ error_code = RDP_ERROR_SEND_WINSOCK_FAILED;
+ break;
+ case SPICEC_ERROR_CODE_NOT_ENOUGH_MEMORY:
+ error_code = RDP_ERROR_CODE_OUT_OF_MEMORY;
+ break;
+ case SPICEC_ERROR_CODE_AGENT_TIMEOUT:
+ error_code = RDP_ERROR_CODE_TIMEOUT;
+ break;
+ case SPICEC_ERROR_CODE_AGENT_ERROR:
+ default:
+ error_code = exit_code + SPICE_ERROR_BASE;
+ }
+
+ LOG_INFO("exit_code=%lu error_code=%lu", exit_code, error_code);
+ spicex->PostMessage(SPICEX_ON_DISCONNECTED_MSG, error_code, 0);
+ spicex->cleanup();
+ return 0;
+}
+
+bool COSpiceX::handle_in_msg(ControllerValue& msg)
+{
+ DWORD bytes_read;
+ bool res;
+
+ if (!GetOverlappedResult(m_hClientPipe, &m_OverlappedRead, &bytes_read, FALSE) ||
+ bytes_read != sizeof(msg) || msg.base.size != sizeof(msg)) {
+ return false;
+ }
+ switch(msg.base.id) {
+ case CONTROLLER_MENU_ITEM_CLICK:
+ DBG(3, "menu-item-click: value=%u", msg.value);
+ ((COSpiceX*)this)->PostMessage(SPICEX_ON_MENU_ITEM_SELECTED_MSG, msg.value, 0);
+ break;
+ default:
+ LOG_INFO("unknown message: %u", msg.base.id);
+ return false;
+ }
+ res = ReadFile(m_hClientPipe, &msg, sizeof(msg), NULL, &m_OverlappedRead) ||
+ GetLastError() == ERROR_IO_PENDING;
+ return res;
+}
+
+bool COSpiceX::handle_out_msg()
+{
+ bool res = true;
+ DWORD written;
+ size_t size;
+
+ EnterCriticalSection(&m_WriteLock);
+ if (!GetOverlappedResult(m_hClientPipe, &m_OverlappedWrite, &written, FALSE)) {
+ LeaveCriticalSection(&m_WriteLock);
+ return false;
+ }
+
+ m_WritePending = false;
+ m_WriteStart = m_WriteBuffer + (m_WriteStart - m_WriteBuffer + written) % PIPE_BUF_SIZE;
+ if (m_WriteStart <= m_WriteEnd) {
+ size = m_WriteEnd - m_WriteStart;
+ } else {
+ size = m_WriteBuffer + PIPE_BUF_SIZE - m_WriteStart;
+ }
+ if (size) {
+ if (WriteFile(m_hClientPipe, m_WriteStart, (DWORD)size, NULL, &m_OverlappedWrite) ||
+ GetLastError() == ERROR_IO_PENDING) {
+ m_WritePending = true;
+ } else {
+ res = false;
+ }
+ }
+ LeaveCriticalSection(&m_WriteLock);
+ return res;
+}
+
+DWORD WINAPI COSpiceX::UsbCtrlWatchDog(PVOID pv)
+{
+ COSpiceX *pThis = reinterpret_cast<COSpiceX*>(pv);
+
+ if (pThis != NULL)
+ {
+ if (::WaitForSingleObject(pThis->m_hUsbCtrlProcess, INFINITE) == WAIT_OBJECT_0)
+ {
+ DWORD dwExitCode;
+
+ ::CloseHandle(pThis->m_hUsbCtrlLog);
+ pThis->m_hUsbCtrlLog = INVALID_HANDLE_VALUE;
+
+ if (::GetExitCodeProcess(pThis->m_hUsbCtrlProcess, &dwExitCode) == TRUE)
+ {
+ pThis->m_hUsbCtrlProcess = NULL;
+
+ if (dwExitCode != 0)
+ {
+ LOG_INFO("Restarting USB controller");
+ // The USB controller was terminated, re-run it again.
+ pThis->ExecuteUsbCtrl();
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+STDMETHODIMP COSpiceX::Connect(void)
+{
+ wchar_t lpCommandLine[CMDLINE_LENGTH] = {0};
+ LPTSTR lpProcName;
+ DWORD dwRetVal;
+ HMODULE hModule;
+ STARTUPINFO si;
+ HKEY hkey;
+ LONG lret;
+
+
+ if (m_hClientProcess != NULL) {
+ return SPICEX_ERROR_CLIENT_PROCESS_ALREADY_CONNECTED;
+ }
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&m_pi, sizeof(m_pi));
+
+ // FIXME: do we need the GetModuleXXX calls?
+ // we assume the Spice client binary is located in the same dir as the ActiveX dll
+ if (hModule = GetModuleHandle(SPICE_X_DLL)) {
+ if (dwRetVal = GetModuleFileName(hModule, lpCommandLine, MAX_PATH)) {
+ // locate the 1st char of the ActiveX name (past the last '\')
+ lpProcName = (wcsrchr(lpCommandLine, L'\\') + 1);
+ // zero it so we can append the red client name
+ if (lpProcName) {
+ lpProcName[0] = 0;
+ }
+ }
+ }
+
+ lret = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\spice-space.org\\spicex", 0, KEY_READ, &hkey);
+ if (lret == ERROR_SUCCESS) {
+ DWORD dwType = REG_SZ;
+ DWORD dwSize = sizeof(lpCommandLine);
+ lret = RegQueryValueEx(hkey, L"client", NULL, &dwType, (LPBYTE)lpCommandLine, &dwSize);
+ RegCloseKey(hkey);
+ }
+
+ if (lret != ERROR_SUCCESS) {
+ lret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\spice-space.org\\spicex", 0, KEY_READ, &hkey);
+ if (lret == ERROR_SUCCESS) {
+ DWORD dwType = REG_SZ;
+ DWORD dwSize = sizeof(lpCommandLine);
+ lret = RegQueryValueEx(hkey, L"client", NULL, &dwType, (LPBYTE)lpCommandLine, &dwSize);
+ RegCloseKey(hkey);
+ }
+ }
+
+ if (lret != ERROR_SUCCESS) {
+ StringCchPrintf(lpCommandLine, CMDLINE_LENGTH, L"%s%s --controller",
+ lpCommandLine, RED_CLIENT_FILE_NAME);
+ }
+
+ DBG(0, "Running spicec (%S)", lpCommandLine);
+
+ if (!CreateProcess(NULL, lpCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &m_pi)) {
+ DWORD err = GetLastError();
+ LOG_ERROR("Failed to run spicec (%S) -- %lu", lpCommandLine, err);
+ return MAKE_HRESULT(1, FACILITY_CREATE_RED_PROCESS, err);
+ }
+ LOG_INFO("spicec pid %lu", ::GetProcessId(m_pi.hProcess));
+ m_hClientProcess = m_pi.hProcess;
+
+ if (WaitForInputIdle(m_hClientProcess, 5000) != 0)
+ LOG_WARN("Waiting for client idle failed, trying to connnect");
+
+ DBG(0, "connecting to spice client's pipe");
+ wchar_t lpszClientPipeName[RED_CLIENT_PIPE_NAME_MAX_LEN];
+ StringCchPrintf(lpszClientPipeName, RED_CLIENT_PIPE_NAME_MAX_LEN, RED_CLIENT_PIPE_NAME,
+ m_pi.dwProcessId);
+ for (int retry = 0; retry < 5; retry++) {
+ m_hClientPipe = CreateFile(lpszClientPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS |
+ FILE_FLAG_OVERLAPPED, NULL);
+ if (m_hClientPipe != INVALID_HANDLE_VALUE) {
+ break;
+ }
+ Sleep(1000);
+ }
+
+ // Verify the named-pipe-server owner is the current user.
+ // Do it here so upon failure use next condition cleanup code.
+ if (m_hClientPipe != INVALID_HANDLE_VALUE) {
+ if (!is_same_user(m_hClientPipe)) {
+ LOG_ERROR("Closing pipe to spicec -- it is not safe");
+ CloseHandle(m_hClientPipe);
+ m_hClientPipe = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ if (m_hClientPipe == INVALID_HANDLE_VALUE) {
+ LOG_ERROR("failed to connect to spice client pipe");
+ TerminateProcess(m_hClientProcess, 0);
+ CloseHandle(m_hClientProcess);
+ m_hClientProcess = NULL;
+ return MAKE_HRESULT(1, FACILITY_CREATE_RED_PIPE, GetLastError());
+ }
+
+ m_hEventThread = CreateThread(NULL, 0, event_thread, this, 0, NULL);
+ if (m_hEventThread == NULL) {
+ LOG_ERROR("failed to create event thread");
+ cleanup();
+ return MAKE_HRESULT(1, FACILITY_CREATE_RED_PIPE, GetLastError());
+ }
+
+
+ send_init();
+ send_wstr(CONTROLLER_HOST, m_HostIP, true);
+ send_value(CONTROLLER_PORT, m_Port);
+ send_value(CONTROLLER_SPORT, m_SecurePort);
+ send_wstr(CONTROLLER_PASSWORD, m_szPassword, true);
+ send_wstr(CONTROLLER_SET_TITLE, m_Title, true);
+ send_value(CONTROLLER_FULL_SCREEN, (m_FullScreen ? CONTROLLER_SET_FULL_SCREEN : 0) |
+ (m_AdminConsole ? 0 : CONTROLLER_AUTO_DISPLAY_RES));
+ send_wstr(CONTROLLER_HOTKEYS, m_HotKey.c_str(), true);
+ send_wstr(CONTROLLER_CREATE_MENU, m_strMenuResource, true);
+ send_wstr(CONTROLLER_SECURE_CHANNELS, m_szSSLChannels, true);
+ send_wstr(CONTROLLER_TLS_CIPHERS, m_szCipherSuite, true);
+ send_wstr(CONTROLLER_HOST_SUBJECT, m_HostSubject.c_str(), true);
+ send_wstr(CONTROLLER_PROXY, m_Proxy.c_str(), true);
+ if (!m_TrustStore.empty()) {
+ WCHAR szCAFileName[MAX_PATH];
+ if (SUCCEEDED(CreateCAFile(szCAFileName, sizeof(szCAFileName)))) {
+ send_wstr(CONTROLLER_CA_FILE, szCAFileName, true);
+ }
+ }
+ if (m_ColorDepth) {
+ send_value(CONTROLLER_COLOR_DEPTH, m_ColorDepth);
+ }
+ if (!m_DisableEffects.empty()) {
+ send_wstr(CONTROLLER_DISABLE_EFFECTS, m_DisableEffects.c_str(), true);
+ }
+ send_bool(CONTROLLER_ENABLE_SMARTCARD, !!m_SmartCard);
+ send_bool(CONTROLLER_SEND_CAD, !!m_SendCtrlAltDelete);
+ send_msg(CONTROLLER_CONNECT);
+ send_msg(CONTROLLER_SHOW);
+
+ if (m_UsbListenPort != 0) {
+ /* old USB, disable new USB solution */
+ send_value(CONTROLLER_ENABLE_USB, FALSE);
+ ExecuteUsbCtrl();
+ } else {
+ send_value(CONTROLLER_ENABLE_USB, TRUE);
+ send_bool(CONTROLLER_ENABLE_USB_AUTOSHARE, !!m_UsbAutoShare);
+ send_wstr(CONTROLLER_USB_FILTER, m_UsbFilter.c_str());
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::Disconnect(void)
+{
+ if (m_hClientProcess == NULL) {
+ return SPICEX_ERROR_CLIENT_PROCESS_NOT_CONNECTED;
+ }
+ cleanup();
+ return S_OK;
+}
+
+void COSpiceX::cleanup()
+{
+ if (m_hClientProcess) {
+ TerminateProcess(m_hClientProcess, 0);
+ CloseHandle(m_hClientProcess);
+ m_hClientProcess = NULL;
+ }
+ if (m_hClientPipe) {
+ CloseHandle(m_hClientPipe);
+ m_hClientPipe = NULL;
+ }
+ if (m_hEventThread) {
+ CloseHandle(m_hEventThread);
+ m_hEventThread = NULL;
+ }
+}
+
+STDMETHODIMP COSpiceX::SendCAD(void)
+{
+ // TODO: Add your implementation code here
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::Show(void)
+{
+ return send_msg(CONTROLLER_SHOW);
+}
+
+STDMETHODIMP COSpiceX::Hide(void)
+{
+ return send_msg(CONTROLLER_HIDE);
+}
+
+STDMETHODIMP COSpiceX::SetSecondaryAddress(void)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::Load(IPropertyBag *pPropBag, IErrorLog* pErrorLog)
+{
+ CComVariant pVar;
+ HRESULT hRes;
+
+ pVar.vt = VT_UI2;
+ hRes = pPropBag->Read(L"Port", &pVar, pErrorLog);
+ if (hRes == S_OK)
+ {
+ m_Port = pVar.uiVal;
+ }
+
+ pVar.vt = VT_UI2;
+ hRes = pPropBag->Read(L"SecurePort", &pVar, pErrorLog);
+ if (hRes == S_OK)
+ {
+ m_SecurePort = pVar.uiVal;
+ }
+
+ pVar.vt = VT_BSTR;
+ hRes = pPropBag->Read(L"HostIP", &pVar, pErrorLog);
+ if (hRes == S_OK)
+ {
+ StringCchCopyN(m_HostIP, MAX_PATH, pVar.bstrVal, MAX_PATH);
+ }
+
+ pVar.vt = VT_BSTR;
+ hRes = pPropBag->Read(L"Title", &pVar, pErrorLog);
+ if (hRes == S_OK)
+ {
+ StringCchCopyN(m_Title, RED_CLIENT_MAX_TITLE_SIZE, pVar.bstrVal, RED_CLIENT_MAX_TITLE_SIZE);
+ }
+
+ pVar.vt = VT_BSTR;
+ hRes = pPropBag->Read(L"CipherSuite", &pVar, pErrorLog);
+ if (hRes == S_OK && lstrlen(V_BSTR(&pVar)) > 0)
+ {
+ m_bIsSSL = true;
+ StringCchCopyN(m_szCipherSuite, MAX_PATH, V_BSTR(&pVar), MAX_PATH);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_CipherSuite(BSTR* pVal)
+{
+ *pVal=::SysAllocString(m_szCipherSuite);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_CipherSuite(BSTR newVal)
+{
+ if (newVal) {
+ wcscpy_s(m_szCipherSuite, MAX_PATH, newVal);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_SSLChannels(BSTR* pVal)
+{
+ *pVal=::SysAllocString(m_szSSLChannels);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_SSLChannels(BSTR newVal)
+{
+ ZeroMemory(m_szSSLChannels, sizeof(m_szSSLChannels));
+
+ // validate input arg
+ if (newVal != NULL && lstrlen(newVal) > 0)
+ {
+ m_bIsSSL = true;
+ StringCchCopyN(m_szSSLChannels, MAX_PATH, newVal, MAX_PATH);
+
+ /*
+ * Backward Compatibility:
+ * Remove leading 's' from m_ssl_channels, e.g. "main" not "smain"
+ * RHEL5 uses 'smain' and 'sinpusts
+ * RHEL6 uses 'main' and 'inputs'
+ */
+ const wchar_t* chan_names[] = {
+ L"smain", L"sdisplay", L"sinputs",
+ L"scursor", L"splayback", L"srecord",
+ L"susbredir", L"ssmartcard", L"stunnel"
+ };
+ const int nnames = sizeof(chan_names) / sizeof(chan_names[0]);
+ wchar_t *p;
+ const wchar_t *cn;
+ size_t len, n, i, j;
+
+ n = wcslen(m_szSSLChannels);
+ for (i=0 ; i<n ; i++) {
+ p = &m_szSSLChannels[i];
+ for (j = 0; j < nnames; j++) {
+ cn = chan_names[j];
+ len = wcslen(cn);
+ if (wcsncmp(cn, p, len) == 0) {
+ while ((*p) = *(p+1)) { /* copy is done in condition */
+ p++;
+ }
+ i+=len-1; /* no need to check copied name */
+ break; /* out of inner loop */
+ }
+ }
+ }
+ DBG(3, "New SSL Channels %S", m_szSSLChannels);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_HostIP(BSTR* pVal)
+{
+ *pVal=::SysAllocString(m_HostIP);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_HostIP(BSTR newVal)
+{
+ ZeroMemory(m_HostIP, sizeof(m_HostIP));
+
+ // validate input arg
+ if (newVal != NULL)
+ {
+ StringCchCopyN(m_HostIP, MAX_PATH, newVal, MAX_PATH);
+ DBG(3, "New HostIP %S", m_HostIP);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_GuestHostName(BSTR* pVal)
+{
+ *pVal = ::SysAllocString(m_GuestHostName);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_GuestHostName(BSTR newVal)
+{
+ if (newVal == NULL) {
+ return E_INVALIDARG;
+ }
+
+ ZeroMemory(m_GuestHostName, sizeof(m_GuestHostName));
+ StringCchCopyN(m_GuestHostName, MAX_PATH, newVal, MAX_PATH);
+ DBG(3, "New GuestHostName %S", m_GuestHostName);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_HotKey(BSTR* pVal)
+{
+ *pVal = ::SysAllocString(m_HotKey.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_HotKey(BSTR newVal)
+{
+ if (newVal == NULL) {
+ return E_INVALIDARG;
+ }
+
+ m_HotKey = newVal;
+ DBG(3, "New HotKey %S", m_HotKey.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_Port(USHORT* pVal)
+{
+ *pVal= m_Port;
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_SecurePort(USHORT newVal)
+{
+ m_SecurePort = newVal;
+ DBG(3, "New Secure Port %u", m_SecurePort);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_SecurePort(USHORT* pVal)
+{
+ *pVal= m_SecurePort;
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_Port(USHORT newVal)
+{
+ m_Port = newVal;
+ DBG(3, "New Port %u", m_Port);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_Password(BSTR* pVal)
+{
+ *pVal=::SysAllocString(m_szPassword);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_Password(BSTR newVal)
+{
+ if (newVal) {
+ wcscpy_s(m_szPassword, RED_MAX_PASSWORD_LENGTH, newVal);
+ DBG(3, "New Password");
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_ScaleEnable(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_ScaleEnable(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_ScaleNum(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_ScaleNum(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_ScaleDen(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_ScaleDen(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_FullScreen(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ *pVal = m_FullScreen;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_FullScreen(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ m_FullScreen = newVal;
+ LOG_INFO("New FullScreen request newVal=0x%lx", newVal);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_MsUser(BSTR* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_MsUser(BSTR newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_MSDomain(BSTR* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_MSDomain(BSTR newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_MSPassword(BSTR* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_MSPassword(BSTR newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_StretchMode(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_StretchMode(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_ScreenHeight(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_ScreenHeight(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_ConnectingText(BSTR* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_ConnectingText(BSTR newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_DisconnectingText(BSTR* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_DisconnectingText(BSTR newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_SwapMouseButtons(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_SwapMouseButtons(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_AudioRedirection(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_AudioRedirection(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_SecondaryHostIP(BSTR* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_SecondaryHostIP(BSTR newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_SecondaryPort(USHORT* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_SecondaryPort(USHORT newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_PollingInterval(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_PollingInterval(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_Title(BSTR* pVal)
+{
+ *pVal=::SysAllocString(m_Title);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_Title(BSTR newVal)
+{
+ if (!newVal || newVal[0] == '\0') {
+ return S_OK;
+ }
+ wcscpy_s(m_Title, RED_CLIENT_MAX_TITLE_SIZE, newVal);
+ DBG(3, "New Title %S", m_Title);
+ if (m_hClientPipe) {
+ return send_wstr(CONTROLLER_SET_TITLE, m_Title);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::ConnectAudio(void)
+{
+ // Still here to prevent web interface errors
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::DisconnectAudio(void)
+{
+ // Still here to prevent web interface errors
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_AudioGuestIP(BSTR* pVal)
+{
+ *pVal=::SysAllocString(m_AudioGuestIP);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_AudioGuestIP(BSTR newVal)
+{
+ ZeroMemory(m_AudioGuestIP, sizeof(m_AudioGuestIP));
+
+ // validate input arg
+ if (newVal != NULL)
+ {
+ StringCchCopyN(m_AudioGuestIP, MAX_PATH, newVal, MAX_PATH);
+ LOG_INFO("New AudioGuestIP %S", m_AudioGuestIP);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_AudioGuestPort(SHORT* pVal)
+{
+ *pVal= m_AudioPort;
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_AudioGuestPort(SHORT newVal)
+{
+ m_AudioPort = newVal;
+ DBG(3, "New AudioGuestPort %u", m_AudioPort);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::CreateMenu(BSTR MenuResourceString)
+{
+ if (!MenuResourceString || MenuResourceString[0] == '\0') {
+ return S_OK;
+ }
+ wcscpy_s(m_strMenuResource, RED_CLIENT_MAX_MENU_SIZE, MenuResourceString);
+ DBG(3, "New Menu '%S'", m_strMenuResource);
+ if (m_hClientPipe) {
+ return send_wstr(CONTROLLER_CREATE_MENU, m_strMenuResource);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::DeleteMenu(void)
+{
+ m_strMenuResource[0] = '\0';
+ return send_msg(CONTROLLER_DELETE_MENU);
+ DBG(3, "Menu Deleted");
+}
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+HRESULT COSpiceX::write_to_pipe(const void* data, uint32_t size)
+{
+ bool res = true;
+
+ EnterCriticalSection(&m_WriteLock);
+ size_t free_size = (PIPE_BUF_SIZE + m_WriteStart - m_WriteEnd - 1) % PIPE_BUF_SIZE;
+ if (size > free_size) {
+ res = false;
+ } else if (m_WriteEnd < m_WriteStart) {
+ memcpy(m_WriteEnd, data, size);
+ m_WriteEnd += size;
+ } else {
+ size_t n = MIN(size, (size_t)(m_WriteBuffer + PIPE_BUF_SIZE - m_WriteEnd));
+ memcpy(m_WriteEnd, data, n);
+ if (size > n) {
+ memcpy(m_WriteBuffer, (uint8_t*)data + n, size - n);
+ }
+ m_WriteEnd = m_WriteBuffer + (m_WriteEnd - m_WriteBuffer + size) % PIPE_BUF_SIZE;
+ }
+
+ if (res && !m_WritePending) {
+ if (WriteFile(m_hClientPipe, data, size, NULL, &m_OverlappedWrite) ||
+ GetLastError() == ERROR_IO_PENDING) {
+ res = m_WritePending = true;
+ }
+ }
+ LeaveCriticalSection(&m_WriteLock);
+
+ return (res ? S_OK : MAKE_HRESULT(SEVERITY_ERROR, FACILITY_PIPE_OPERATION, GetLastError()));
+}
+
+HRESULT COSpiceX::send_init()
+{
+ DBG(0, "sending init");
+ ControllerInit msg = {{CONTROLLER_MAGIC, CONTROLLER_VERSION, sizeof(msg)}, 0,
+ CONTROLLER_FLAG_EXCLUSIVE};
+ return write_to_pipe(&msg, sizeof(msg));
+}
+
+HRESULT COSpiceX::send_msg(uint32_t id)
+{
+ ControllerMsg msg = {id, sizeof(msg)};
+ DBG(0, "sending msg id %u", id);
+ return write_to_pipe(&msg, sizeof(msg));
+}
+
+HRESULT COSpiceX::send_value(uint32_t id, uint32_t value)
+{
+ if (!value) {
+ return S_OK;
+ }
+ DBG(0, "sending msg id %u value %u", id, value);
+ ControllerValue msg = {{id, sizeof(msg)}, value};
+ return write_to_pipe(&msg, sizeof(msg));
+}
+
+HRESULT COSpiceX::send_bool(uint32_t id, uint32_t value)
+{
+ DBG(0, "sending msg id %u bool %u", id, !!value);
+ ControllerValue msg = {{id, sizeof(msg)}, !!value};
+ return write_to_pipe(&msg, sizeof(msg));
+}
+
+HRESULT COSpiceX::send_wstr(uint32_t id, const wchar_t* str, bool use_mb_str)
+{
+ HRESULT res;
+
+ if (!str || !wcslen(str)) {
+ return S_OK;
+ }
+ if (id == CONTROLLER_PASSWORD) {
+ DBG(0, "sending password");
+ } else {
+ DBG(0, "sending msg id %u : str %S (%d)", id, str, (int)use_mb_str);
+ }
+ size_t size = sizeof(ControllerData) + (wcslen(str) + 1) * (use_mb_str ? 1 : sizeof(wchar_t));
+ ControllerData* msg = (ControllerData*)malloc(size);
+ msg->base.id = id;
+ msg->base.size = (uint32_t)size;
+ if (use_mb_str) {
+ sprintf_s((char*)msg->data, wcslen(str) + 1, "%S", str);
+ } else {
+ wcscpy_s((wchar_t*)msg->data, wcslen(str) + 1, str);
+ }
+ res = write_to_pipe(msg, (uint32_t)size);
+ free(msg);
+ return res;
+}
+
+STDMETHODIMP COSpiceX::get_multimediaPorts(BSTR* pVal)
+{
+ *pVal=::SysAllocString(m_AudioGuestPorts);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_multimediaPorts(BSTR newVal)
+{
+ ZeroMemory(m_AudioGuestPorts, sizeof(m_AudioGuestPorts));
+
+ // validate input arg
+ if (newVal != NULL)
+ {
+ StringCchCopyN(m_AudioGuestPorts, MAX_PATH, newVal, MAX_PATH);
+ DBG(3, "multi-media ports %S", m_AudioGuestPorts);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_DynamicMenu(BSTR* pVal)
+{
+ // TODO: Add your implementation code here
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_DynamicMenu(BSTR newVal)
+{
+ // TODO: Add your implementation code here
+ DBG(0, "DynamicMenu %S", newVal);
+ return CreateMenu(newVal);
+}
+
+STDMETHODIMP COSpiceX::get_NumberOfMonitors(ULONG* pVal)
+{
+ // TODO: Add your implementation code here
+ *pVal = m_ulNumberOfMonitors;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_NumberOfMonitors(ULONG newVal)
+{
+ // TODO: Add your implementation code here
+ if(newVal)
+ m_ulNumberOfMonitors = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_UsbListenPort(USHORT* pVal)
+{
+ if (pVal == NULL) {
+ return E_INVALIDARG;
+ }
+ *pVal = m_UsbListenPort;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_UsbListenPort(USHORT newVal)
+{
+ m_UsbListenPort = newVal;
+ DBG(3, "New USB listen port %u", m_UsbListenPort);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_AdminConsole(BOOL* pVal)
+{
+ if (pVal == NULL) {
+ return E_INVALIDARG;
+ }
+ *pVal = m_AdminConsole;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_AdminConsole(BOOL newVal)
+{
+ m_AdminConsole = newVal;
+ DBG(3, "New AdminConsole %u", (int)(!!m_AdminConsole));
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_SendCtrlAltDelete(BOOL* pVal)
+{
+ if (pVal == NULL) {
+ return E_INVALIDARG;
+ }
+ *pVal = m_SendCtrlAltDelete;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_SendCtrlAltDelete(BOOL newVal)
+{
+ m_SendCtrlAltDelete = newVal;
+ DBG(3, "New SendCtrlAltDelete %u", (int)(!!m_SendCtrlAltDelete));
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_NoTaskMgrExecution(BOOL* pVal)
+{
+ if (pVal == NULL) {
+ return E_INVALIDARG;
+ }
+ *pVal = m_NoTaskMgrExecution;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_NoTaskMgrExecution(BOOL newVal)
+{
+ m_NoTaskMgrExecution = newVal;
+ DBG(3, "New NoTaskMgr %u", (int)(!!m_NoTaskMgrExecution));
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::SetUsbFilter(BSTR newVal)
+{
+ if (newVal == NULL) {
+ return E_INVALIDARG;
+ }
+
+ m_UsbFilter = newVal;
+ DBG(3, "New UsbFilter %S", m_UsbFilter.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_Version(BSTR* pVal)
+{
+ DWORD dwDummy;
+ UINT nSize;
+
+ nSize = ::GetFileVersionInfoSize(SPICE_X_DLL, &dwDummy);
+ if (nSize == 0) {
+ // No version information available.
+ return HRESULT_FROM_WIN32(::GetLastError());
+ }
+
+ LPBYTE pVersionInfo = reinterpret_cast<LPBYTE>(_alloca(nSize));
+
+ if (!::GetFileVersionInfo(SPICE_X_DLL, 0L, nSize, pVersionInfo))
+ {
+ return HRESULT_FROM_WIN32(::GetLastError());
+ }
+
+ LPVOID pData;
+
+ if (!::VerQueryValue(pVersionInfo, _T("\\"), &pData, &nSize))
+ {
+ return HRESULT_FROM_WIN32(::GetLastError());
+ }
+
+ VS_FIXEDFILEINFO ffi;
+ ::CopyMemory(&ffi, pData, nSize);
+
+ WCHAR szVersion[16];
+ StringCchPrintf(szVersion, sizeof(szVersion), _T("%d.%d.%d.%d"),
+ HIWORD(ffi.dwFileVersionMS), LOWORD(ffi.dwFileVersionMS),
+ HIWORD(ffi.dwFileVersionLS), LOWORD(ffi.dwFileVersionLS));
+
+ *pVal = ::SysAllocString(szVersion);
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_UsbAutoShare(BOOL* pVal)
+{
+ if (pVal == NULL) {
+ return E_INVALIDARG;
+ }
+ *pVal = m_UsbAutoShare;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_UsbAutoShare(BOOL newVal)
+{
+ m_UsbAutoShare = newVal;
+ DBG(3, "New UsbAutoShare %u", (int)(!!m_UsbAutoShare));
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::SetLanguageStrings(BSTR bzSection, BSTR bzLangStr)
+{
+ if ((bzSection == NULL) || (bzLangStr == NULL)) {
+ return E_POINTER;
+ }
+
+ if ((lstrlen(bzSection) == 0) || (lstrlen(bzLangStr) == 0)) {
+ return E_INVALIDARG;
+ }
+
+ m_Language[bzSection] = bzLangStr;
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_TrustStore(BSTR* pVal)
+{
+ *pVal = ::SysAllocString(m_TrustStore.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_TrustStore(BSTR newVal)
+{
+ if (newVal == NULL) {
+ return E_INVALIDARG;
+ }
+
+ m_TrustStore = newVal;
+ DBG(3, "New TrustStore");
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_HostSubject(BSTR* pVal)
+{
+ *pVal = ::SysAllocString(m_HostSubject.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_HostSubject(BSTR newVal)
+{
+ if (newVal == NULL) {
+ return E_INVALIDARG;
+ }
+
+ m_HostSubject = newVal;
+ DBG(3, "New HostSubject %S", m_HostSubject.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_ColorDepth(USHORT* pVal)
+{
+ if (pVal == NULL) {
+ return E_INVALIDARG;
+ }
+ *pVal = m_ColorDepth;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_ColorDepth(USHORT newVal)
+{
+ m_ColorDepth = newVal;
+ DBG(3, "New ColorDepth %u", m_ColorDepth);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_DisableEffects(BSTR* pVal)
+{
+ *pVal = ::SysAllocString(m_DisableEffects.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_DisableEffects(BSTR newVal)
+{
+ if (newVal == NULL) {
+ return E_INVALIDARG;
+ }
+
+ m_DisableEffects= newVal;
+ DBG(3, "New DisableEffects %S", m_DisableEffects.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_SmartCard(BOOL* pVal)
+{
+ if (pVal == NULL) {
+ return E_INVALIDARG;
+ }
+ *pVal = m_SmartCard;
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_SmartCard(BOOL newVal)
+{
+ m_SmartCard = newVal;
+ DBG(3, "New SmartCard %u", !!m_SmartCard);
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::get_Proxy(BSTR* pVal)
+{
+ *pVal = ::SysAllocString(m_Proxy.c_str());
+
+ return S_OK;
+}
+
+STDMETHODIMP COSpiceX::put_Proxy(BSTR newVal)
+{
+ if (newVal == NULL) {
+ return E_INVALIDARG;
+ }
+
+ m_Proxy = newVal;
+ DBG(3, "New Proxy %S", m_Proxy.c_str());
+
+ return S_OK;
+}
+
+HRESULT COSpiceX::ExecuteUsbCtrl()
+{
+ if ((m_hClientProcess == NULL) || (m_UsbListenPort == 0)) {
+ LOG_INFO("USB sharing is not requested");
+ return S_OK;
+ }
+
+ // Find executable path.
+
+ CRegKey reg;
+ LONG result;
+ const wchar_t* const reg_key = \
+ L"SOFTWARE\\RedHat\\Red Hat Enterprise Virtualization Tools\\USB Controller";
+
+ /* first try the default registry */
+ result = reg.Open(HKEY_LOCAL_MACHINE, reg_key, KEY_READ);
+
+#ifdef _WIN64
+ if (result != ERROR_SUCCESS) {
+ /* For 64 bit machines, 64 bit SpiceX, look at 32 bit registry too */
+ LOG_INFO("Looking for USB path in 32 bit registry");
+ result = reg.Open(HKEY_LOCAL_MACHINE, reg_key, KEY_READ | KEY_WOW64_32KEY);
+ }
+#else
+ if (result != ERROR_SUCCESS) {
+ /* For 64 bit machines, 32 bit SpiceX, look at 64 bit registry too */
+ LOG_INFO("Looking for USB path in 64 bit registry");
+ result = reg.Open(HKEY_LOCAL_MACHINE, reg_key, KEY_READ | KEY_WOW64_64KEY);
+ }
+#endif
+
+ if (result != ERROR_SUCCESS) {
+ LOG_INFO("Could not find registry entry for USB Controller");
+ return HRESULT_FROM_WIN32(result);
+ }
+
+ WCHAR szCmdLine[MAX_PATH];
+ ULONG ulCmdLineLen = sizeof(szCmdLine) / sizeof(WCHAR);
+
+ result = reg.QueryStringValue(L"InstallDir", szCmdLine, &ulCmdLineLen);
+
+ if (result != ERROR_SUCCESS)
+ {
+ return HRESULT_FROM_WIN32(result);
+ }
+
+ reg.Close();
+
+ // Build command line.
+
+ std::wostringstream cmdline;
+
+ cmdline << szCmdLine << " "
+ << m_GuestHostName << L" " << m_UsbListenPort
+ << " -c \\\\.\\pipe\\SpiceForeignMenu-" << ::GetProcessId(m_hClientProcess);
+
+ if (!m_Language[L"USB"].empty()) {
+ cmdline << " -l \"" << m_Language[L"USB"].c_str() << "\"";
+ }
+
+ if (!m_UsbFilter.empty()) {
+ cmdline << " -f " << m_UsbFilter.c_str();
+ }
+
+ if (m_UsbAutoShare) {
+ cmdline << " -a";
+ }
+
+ // Prepare a log file.
+
+ WCHAR szLogFile[MAX_PATH];
+
+ if (::ExpandEnvironmentStrings(L"%TEMP%", szLogFile, sizeof(szLogFile)))
+ {
+ SECURITY_ATTRIBUTES sa;
+
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ // GetCurrentProcessId() return the IE process id and the usbrdrctrl
+ // is not executed. So we use the spice client process id.
+ StringCchPrintf((STRSAFE_LPWSTR)szLogFile, sizeof(szLogFile),
+ L"%s\\usbrdrctrl-%d.log", szLogFile, ::GetProcessId(m_hClientProcess));
+
+ m_hUsbCtrlLog = ::CreateFile(szLogFile, GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ, &sa, CREATE_ALWAYS, 0, NULL);
+ }
+
+ // Execute application.
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+
+ ZeroMemory(&pi, sizeof(pi));
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+
+ if (m_hUsbCtrlLog != INVALID_HANDLE_VALUE)
+ {
+ DBG(0, "redirecting usb out/err to logfile '%S'", szLogFile);
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ si.hStdError = m_hUsbCtrlLog;
+ si.hStdOutput = m_hUsbCtrlLog;
+ } else {
+ LOG_INFO("Failed to open log file (%S) -- %lu",
+ szLogFile, ::GetLastError());
+ }
+
+ DBG(0, "Running usbrdr (%S)", cmdline.str().c_str());
+
+ ::CreateProcess(NULL, const_cast<LPWSTR>(cmdline.str().c_str()),
+ NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
+
+ m_hUsbCtrlProcess = pi.hProcess;
+
+ if (m_hUsbCtrlProcess != NULL)
+ {
+ LOG_INFO("usbrdr pid %lu", ::GetProcessId(m_hUsbCtrlProcess));
+ ::CreateThread(NULL, 0, UsbCtrlWatchDog, this, 0, NULL);
+ }
+ else
+ {
+ LOG_ERROR("Failed to run usbrdr (%S) -- %lu",
+ cmdline.str().c_str(), ::GetLastError());
+ ::CloseHandle(m_hUsbCtrlLog);
+ m_hUsbCtrlLog = INVALID_HANDLE_VALUE;
+ }
+
+ return S_OK;
+}
+
+HRESULT COSpiceX::CreateCAFile(OUT LPWSTR szCAFileName, DWORD nSize)
+{
+ USES_CONVERSION;
+ SECURITY_ATTRIBUTES sa;
+ SECURITY_DESCRIPTOR sd;
+ PACL dacl = NULL;
+
+ // Allow access only to current user
+ if (DWORD err = get_security_attributes(&sa, &sd, &dacl))
+ {
+ return HRESULT_FROM_WIN32(err);
+ }
+
+ if (::ExpandEnvironmentStrings(L"%TEMP%\\truststore.pem",
+ szCAFileName, nSize) == 0)
+ {
+ LocalFree(dacl);
+ return HRESULT_FROM_WIN32(::GetLastError());
+ }
+
+ HANDLE hTrustStore = ::CreateFile(szCAFileName, GENERIC_WRITE,
+ 0, NULL, CREATE_ALWAYS, 0, &sa);
+ LocalFree(dacl);
+ if (hTrustStore == INVALID_HANDLE_VALUE)
+ {
+ return HRESULT_FROM_WIN32(::GetLastError());
+ }
+
+ std::string truststore = W2A(m_TrustStore.c_str());
+ DWORD dwBytesWritten;
+
+ if ((::WriteFile(hTrustStore, truststore.c_str(),
+ DWORD(truststore.length() + 1), &dwBytesWritten, NULL) == FALSE) ||
+ (dwBytesWritten != (truststore.length() + 1)))
+ {
+ ::CloseHandle(hTrustStore);
+ return HRESULT_FROM_WIN32(::GetLastError());
+ }
+
+ ::CloseHandle(hTrustStore);
+
+ return S_OK;
+}
diff --git a/OSpiceX.h b/OSpiceX.h
new file mode 100644
index 0000000..406435b
--- /dev/null
+++ b/OSpiceX.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+// OSpiceX.h : Declaration of the COSpiceX
+
+#pragma once
+
+#include "resource.h" // main symbols
+
+// atl uses the deprecate function wsprintfA, disable the C4995 warning
+#pragma warning(disable : 4995)
+#include <atlctl.h>
+#include <map>
+#include "stdint.h"
+
+#include "SpiceX.h"
+#include "SpiceXCommon.h"
+#include "_IOSpiceXEvents_CP.h"
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+// All SpiceX Windows Messages constants are offsets from SPICEX_WM_BASE
+#define SPICEX_WM_BASE WM_USER + 0x1000 // 0x0400 + 0x1000 = 0x1400 = 5120
+#define SPICEX_ON_DISCONNECTED_MSG (SPICEX_WM_BASE+0) // 5120
+#define SPICEX_ON_MENU_ITEM_SELECTED_MSG (SPICEX_WM_BASE+1) // 5120
+
+// http://msdn.microsoft.com/en-us/library/aa911976.aspx
+#define RDP_ERROR_CODE_LOCAL_DISCONNECTION 1
+#define RDP_ERROR_CODE_DNS_LOOKUP_FAILED 260
+#define RDP_ERROR_CODE_OUT_OF_MEMORY 262
+#define RDP_ERROR_CODE_WINSOCK_CONNECT_FAILED 516
+#define RDP_ERROR_CODE_HOST_NOT_FOUND 520
+#define RDP_ERROR_CODE_INTERNAL_ERROR 1032
+#define RDP_ERROR_RECV_WINSOCK_FAILED 1028
+#define RDP_ERROR_SEND_WINSOCK_FAILED 772
+#define RDP_ERROR_CODE_TIMEOUT 1796
+
+#define SPICE_ERROR_BASE 100
+
+#define PIPE_BUF_SIZE 16384
+
+struct ControllerValue;
+
+// COSpiceX
+class ATL_NO_VTABLE COSpiceX :
+ public CComObjectRootEx<CComSingleThreadModel>,
+ public IDispatchImpl<IOSpiceX, &IID_IOSpiceX, &LIBID_SpiceXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
+ public IPersistStreamInitImpl<COSpiceX>,
+ public IPersistPropertyBagImpl<COSpiceX>,
+ public IOleControlImpl<COSpiceX>,
+ public IOleObjectImpl<COSpiceX>,
+ public IOleInPlaceActiveObjectImpl<COSpiceX>,
+ public IViewObjectExImpl<COSpiceX>,
+ public IOleInPlaceObjectWindowlessImpl<COSpiceX>,
+ public ISupportErrorInfo,
+ public IConnectionPointContainerImpl<COSpiceX>,
+ public CProxy_IOSpiceXEvents<COSpiceX>,
+ public IPersistStorageImpl<COSpiceX>,
+ public ISpecifyPropertyPagesImpl<COSpiceX>,
+ public IQuickActivateImpl<COSpiceX>,
+#ifndef _WIN32_WCE
+ public IDataObjectImpl<COSpiceX>,
+#endif
+ public IProvideClassInfo2Impl<&CLSID_OSpiceX, &__uuidof(_IOSpiceXEvents), &LIBID_SpiceXLib>,
+#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
+ public IObjectSafetyImpl<COSpiceX, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
+#endif
+ public CComCoClass<COSpiceX, &CLSID_OSpiceX>,
+ public CComControl<COSpiceX>,
+ // added by itai 10/07/07 (IObjectSafetyImpl implementation (suppress unsafe AX msg)
+ public IObjectSafetyImpl<COSpiceX, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>
+{
+public:
+
+
+ COSpiceX()
+ {
+ // added by itai 01/07/07 (indicate the control should be windowed, used for calling html events
+ // from a non base thread using Windows Messages)
+ m_bWindowOnly = true;
+ m_hClientPipe = NULL;
+ m_hEventThread = NULL;
+ m_hClientProcess = NULL;
+ m_hUsbCtrlProcess = NULL;
+ m_hUsbCtrlLog = INVALID_HANDLE_VALUE;
+ m_pi.hProcess = NULL;
+ m_ulNumberOfMonitors = 1;
+ m_UsbListenPort = 32032;
+ m_AdminConsole = TRUE;
+ m_SendCtrlAltDelete = TRUE;
+ m_NoTaskMgrExecution = FALSE;
+ m_UsbAutoShare = FALSE;
+
+ ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead));
+ m_OverlappedRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
+ m_OverlappedWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ InitializeCriticalSection(&m_WriteLock);
+ m_WriteStart = m_WriteEnd = m_WriteBuffer;
+ m_WritePending = false;
+
+ // set object properties to their default values
+ StringCchCopyN(m_HostIP, MAX_PATH, L"255.255.255.255", MAX_PATH);
+ StringCchCopyN(m_GuestHostName, MAX_PATH, L"", MAX_PATH);
+ StringCchCopyN(m_AudioGuestIP, MAX_PATH, L"255.255.255.255", MAX_PATH);
+ StringCchCopyN(m_szCipherSuite, MAX_PATH, L"", MAX_PATH);
+ StringCchCopyN(m_szSSLChannels, MAX_PATH, L"", MAX_PATH);
+ m_bIsSSL = false;
+ m_Port = 0;
+ m_SecurePort = 0;
+ m_AudioPort = 0;
+ StringCchCopyN(m_Title, RED_CLIENT_MAX_TITLE_SIZE, RED_CLIENT_DEFAULT_TITLE,
+ RED_CLIENT_MAX_TITLE_SIZE);
+ StringCchCopyN(m_szPassword, RED_MAX_PASSWORD_LENGTH, L"", RED_MAX_PASSWORD_LENGTH);
+ StringCchCopyN(m_strMenuResource, RED_CLIENT_MAX_MENU_SIZE, L"", RED_CLIENT_MAX_MENU_SIZE);
+ }
+
+DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
+ OLEMISC_CANTLINKINSIDE |
+ OLEMISC_INSIDEOUT |
+ OLEMISC_ACTIVATEWHENVISIBLE |
+ OLEMISC_SETCLIENTSITEFIRST
+)
+
+DECLARE_REGISTRY_RESOURCEID(IDR_OSPICEX)
+
+
+BEGIN_COM_MAP(COSpiceX)
+ COM_INTERFACE_ENTRY(IOSpiceX)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(IViewObjectEx)
+ COM_INTERFACE_ENTRY(IViewObject2)
+ COM_INTERFACE_ENTRY(IViewObject)
+ COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
+ COM_INTERFACE_ENTRY(IOleInPlaceObject)
+ COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
+ COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
+ COM_INTERFACE_ENTRY(IOleControl)
+ COM_INTERFACE_ENTRY(IOleObject)
+ COM_INTERFACE_ENTRY(IPersistStreamInit)
+ COM_INTERFACE_ENTRY(IPersistPropertyBag)
+ COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+ COM_INTERFACE_ENTRY(IConnectionPointContainer)
+ COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
+ COM_INTERFACE_ENTRY(IQuickActivate)
+ COM_INTERFACE_ENTRY(IPersistStorage)
+#ifndef _WIN32_WCE
+ COM_INTERFACE_ENTRY(IDataObject)
+#endif
+ COM_INTERFACE_ENTRY(IProvideClassInfo)
+ COM_INTERFACE_ENTRY(IProvideClassInfo2)
+#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
+ COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
+#endif
+ // added by itai 10/07/07 (IObjectSafetyImpl implementation (suppress unsafe AX msg)
+ COM_INTERFACE_ENTRY(IObjectSafety)
+END_COM_MAP()
+
+BEGIN_PROP_MAP(COSpiceX)
+ PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
+ PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
+ // Example entries
+ // PROP_ENTRY("Property Description", dispid, clsid)
+ // PROP_PAGE(CLSID_StockColorPage)
+END_PROP_MAP()
+
+BEGIN_CONNECTION_POINT_MAP(COSpiceX)
+ CONNECTION_POINT_ENTRY(__uuidof(_IOSpiceXEvents))
+END_CONNECTION_POINT_MAP()
+
+BEGIN_MSG_MAP(COSpiceX)
+ CHAIN_MSG_MAP(CComControl<COSpiceX>)
+ DEFAULT_REFLECTION_HANDLER()
+ // added by itai 01/07/07 (using windows messages to fire events)
+ MESSAGE_HANDLER(SPICEX_ON_DISCONNECTED_MSG, OnDisconnectedMsg)
+ MESSAGE_HANDLER(SPICEX_ON_MENU_ITEM_SELECTED_MSG, OnMenuItemSelected)
+END_MSG_MAP()
+// Handler prototypes:
+// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
+
+// ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
+ {
+ static const IID* arr[] =
+ {
+ &IID_IOSpiceX,
+ };
+
+ for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i], riid))
+ return S_OK;
+ }
+ return S_FALSE;
+ }
+
+// IViewObjectEx
+ DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
+
+// IPersistPropertBag
+ STDMETHOD(Load)(IPropertyBag *pPropBag, IErrorLog* pErrorLog);
+
+ // IOSpiceX
+public:
+ HRESULT OnDraw(ATL_DRAWINFO& di)
+ {
+ RECT& rc = *(RECT*)di.prcBounds;
+ // Set Clip region to the rectangle specified by di.prcBounds
+ HRGN hRgnOld = NULL;
+ if (GetClipRgn(di.hdcDraw, hRgnOld) != 1)
+ hRgnOld = NULL;
+ bool bSelectOldRgn = false;
+
+ HRGN hRgnNew = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
+
+ if (hRgnNew != NULL)
+ {
+ bSelectOldRgn = (SelectClipRgn(di.hdcDraw, hRgnNew) != ERROR);
+ }
+
+ Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
+ SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
+ LPCTSTR pszText = _T("ATL 8.0 : OSpiceX");
+#ifndef _WIN32_WCE
+ TextOut(di.hdcDraw,
+ (rc.left + rc.right) / 2,
+ (rc.top + rc.bottom) / 2,
+ pszText,
+ lstrlen(pszText));
+#else
+ ExtTextOut(di.hdcDraw,
+ (rc.left + rc.right) / 2,
+ (rc.top + rc.bottom) / 2,
+ ETO_OPAQUE,
+ NULL,
+ pszText,
+ ATL::lstrlen(pszText),
+ NULL);
+#endif
+
+ if (bSelectOldRgn)
+ SelectClipRgn(di.hdcDraw, hRgnOld);
+
+ return S_OK;
+ }
+
+ LRESULT OnMenuItemSelected(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ {
+ Fire_OnMenuItemSelected((ULONG)wParam);
+ return ERROR_SUCCESS;
+ }
+
+ LRESULT OnDisconnectedMsg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ {
+ Fire_OnDisconnected((LONG)wParam);
+ return ERROR_SUCCESS;
+ }
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+ STDMETHOD(Connect)(void);
+ STDMETHOD(Disconnect)(void);
+ STDMETHOD(SendCAD)(void);
+ STDMETHOD(Show)(void);
+ STDMETHOD(Hide)(void);
+ STDMETHOD(SetSecondaryAddress)(void);
+ STDMETHOD(get_HostIP)(BSTR* pVal);
+ STDMETHOD(put_HostIP)(BSTR newVal);
+ STDMETHOD(get_Port)(USHORT* pVal);
+ STDMETHOD(put_Port)(USHORT newVal);
+ STDMETHOD(get_SecurePort)(USHORT* pVal);
+ STDMETHOD(put_SecurePort)(USHORT newVal);
+ STDMETHOD(get_ScaleEnable)(ULONG* pVal);
+ STDMETHOD(put_ScaleEnable)(ULONG newVal);
+ STDMETHOD(get_ScaleNum)(ULONG* pVal);
+ STDMETHOD(put_ScaleNum)(ULONG newVal);
+ STDMETHOD(get_ScaleDen)(ULONG* pVal);
+ STDMETHOD(put_ScaleDen)(ULONG newVal);
+ STDMETHOD(get_FullScreen)(ULONG* pVal);
+ STDMETHOD(put_FullScreen)(ULONG newVal);
+ STDMETHOD(get_MsUser)(BSTR* pVal);
+ STDMETHOD(put_MsUser)(BSTR newVal);
+ STDMETHOD(get_MSDomain)(BSTR* pVal);
+ STDMETHOD(put_MSDomain)(BSTR newVal);
+ STDMETHOD(get_MSPassword)(BSTR* pVal);
+ STDMETHOD(put_MSPassword)(BSTR newVal);
+ STDMETHOD(get_StretchMode)(ULONG* pVal);
+ STDMETHOD(put_StretchMode)(ULONG newVal);
+ STDMETHOD(get_ScreenHeight)(ULONG* pVal);
+ STDMETHOD(put_ScreenHeight)(ULONG newVal);
+ STDMETHOD(get_ConnectingText)(BSTR* pVal);
+ STDMETHOD(put_ConnectingText)(BSTR newVal);
+ STDMETHOD(get_DisconnectingText)(BSTR* pVal);
+ STDMETHOD(put_DisconnectingText)(BSTR newVal);
+ STDMETHOD(get_SwapMouseButtons)(ULONG* pVal);
+ STDMETHOD(put_SwapMouseButtons)(ULONG newVal);
+ STDMETHOD(get_AudioRedirection)(ULONG* pVal);
+ STDMETHOD(put_AudioRedirection)(ULONG newVal);
+ STDMETHOD(get_SecondaryHostIP)(BSTR* pVal);
+ STDMETHOD(put_SecondaryHostIP)(BSTR newVal);
+ STDMETHOD(get_SecondaryPort)(USHORT* pVal);
+ STDMETHOD(put_SecondaryPort)(USHORT newVal);
+ STDMETHOD(get_PollingInterval)(ULONG* pVal);
+ STDMETHOD(put_PollingInterval)(ULONG newVal);
+ STDMETHOD(get_Title)(BSTR* pVal);
+ STDMETHOD(put_Title)(BSTR newVal);
+ // Audio interface
+ STDMETHOD(ConnectAudio)(void);
+ STDMETHOD(DisconnectAudio)(void);
+ STDMETHOD(get_AudioGuestIP)(BSTR* pVal);
+ STDMETHOD(put_AudioGuestIP)(BSTR newVal);
+ STDMETHOD(get_AudioGuestPort)(SHORT* pVal);
+ STDMETHOD(put_AudioGuestPort)(SHORT newVal);
+ STDMETHOD(get_Password)(BSTR* pVal);
+ STDMETHOD(put_Password)(BSTR newVal);
+ STDMETHOD(get_CipherSuite)(BSTR* pVal);
+ STDMETHOD(put_CipherSuite)(BSTR newVal);
+ STDMETHOD(get_SSLChannels)(BSTR* pVal);
+ STDMETHOD(put_SSLChannels)(BSTR newVal);
+ STDMETHOD(get_multimediaPorts)(BSTR* pVal);
+ STDMETHOD(put_multimediaPorts)(BSTR newVal);
+ STDMETHOD(get_DynamicMenu)(BSTR* pVal);
+ STDMETHOD(put_DynamicMenu)(BSTR newVal);
+ STDMETHOD(get_NumberOfMonitors)(ULONG* pVal);
+ STDMETHOD(put_NumberOfMonitors)(ULONG newVal);
+ STDMETHOD(CreateMenu)(BSTR MenuResourceString);
+ STDMETHOD(DeleteMenu)(void);
+ STDMETHOD(get_UsbListenPort)(USHORT* pVal);
+ STDMETHOD(put_UsbListenPort)(USHORT newVal);
+ STDMETHOD(get_AdminConsole)(BOOL* pVal);
+ STDMETHOD(put_AdminConsole)(BOOL newVal);
+ STDMETHOD(get_SendCtrlAltDelete)(BOOL* pVal);
+ STDMETHOD(put_SendCtrlAltDelete)(BOOL newVal);
+ STDMETHOD(get_NoTaskMgrExecution)(BOOL* pVal);
+ STDMETHOD(put_NoTaskMgrExecution)(BOOL newVal);
+ STDMETHOD(get_GuestHostName)(BSTR* pVal);
+ STDMETHOD(put_GuestHostName)(BSTR newVal);
+ STDMETHOD(get_HotKey)(BSTR* pVal);
+ STDMETHOD(put_HotKey)(BSTR newVal);
+ STDMETHOD(SetUsbFilter)(BSTR newVal);
+ STDMETHOD(get_Version)(BSTR* pVal);
+ STDMETHOD(get_UsbAutoShare)(BOOL* pVal);
+ STDMETHOD(put_UsbAutoShare)(BOOL newVal);
+ STDMETHOD(SetLanguageStrings)(BSTR bzSection, BSTR bzLangStr);
+ STDMETHOD(get_TrustStore)(BSTR* pVal);
+ STDMETHOD(put_TrustStore)(BSTR newVal);
+ STDMETHOD(get_HostSubject)(BSTR* pVal);
+ STDMETHOD(put_HostSubject)(BSTR newVal);
+ STDMETHOD(get_ColorDepth)(USHORT* pVal);
+ STDMETHOD(put_ColorDepth)(USHORT newVal);
+ STDMETHOD(get_DisableEffects)(BSTR* pVal);
+ STDMETHOD(put_DisableEffects)(BSTR newVal);
+ STDMETHOD(get_SmartCard)(BOOL* pVal);
+ STDMETHOD(put_SmartCard)(BOOL newVal);
+ STDMETHOD(get_Proxy)(BSTR* pVal);
+ STDMETHOD(put_Proxy)(BSTR newVal);
+
+private:
+ UINT m_CurrentExecuterState;
+ HANDLE m_hClientPipe;
+ HANDLE m_hEventThread;
+ HANDLE m_hClientProcess;
+ HANDLE m_hUsbCtrlProcess;
+ HANDLE m_hUsbCtrlLog;
+ PROCESS_INFORMATION m_pi;
+
+ OVERLAPPED m_OverlappedRead;
+ OVERLAPPED m_OverlappedWrite;
+ CRITICAL_SECTION m_WriteLock;
+ int8_t m_WriteBuffer[PIPE_BUF_SIZE];
+ int8_t* m_WriteStart;
+ int8_t* m_WriteEnd;
+ bool m_WritePending;
+
+ bool m_bIsSSL;
+ wchar_t m_szPassword[RED_MAX_PASSWORD_LENGTH];
+ wchar_t m_szCipherSuite[MAX_PATH];
+ wchar_t m_szSSLChannels[MAX_PATH];
+ wchar_t m_HostIP[MAX_PATH];
+ wchar_t m_GuestHostName[MAX_PATH];
+ wchar_t m_AudioGuestIP[MAX_PATH];
+ wchar_t m_AudioGuestPorts[MAX_PATH];
+ wchar_t m_Title[RED_CLIENT_MAX_TITLE_SIZE];
+ wchar_t m_strMenuResource[RED_CLIENT_MAX_MENU_SIZE];
+ std::wstring m_UsbFilter;
+ std::map<std::wstring, std::wstring> m_Language;
+ std::wstring m_HotKey;
+ std::wstring m_TrustStore;
+ std::wstring m_HostSubject;
+ USHORT m_Port;
+ USHORT m_SecurePort;
+ USHORT m_AudioPort;
+ ULONG m_ulNumberOfMonitors;
+ ULONG m_ScaleEnable;
+ ULONG m_ScaleNum;
+ ULONG m_ScaleDen;
+ ULONG m_FullScreen;
+ BSTR m_MsUser;
+ BSTR m_MSDomain;
+ BSTR m_MSPassword;
+ ULONG m_StretchMode;
+ ULONG m_ScreenHeight;
+ BSTR m_ConnectingText;
+ BSTR m_DisconnectingText;
+ ULONG m_SwapMouseButtons;
+ ULONG m_AudioRedirection;
+ BSTR m_SecondaryHostIP;
+ USHORT m_SecondaryPort;
+ ULONG m_PollingInterval;
+ USHORT m_UsbListenPort;
+ BOOL m_AdminConsole;
+ BOOL m_SendCtrlAltDelete;
+ BOOL m_NoTaskMgrExecution;
+ BOOL m_UsbAutoShare;
+ USHORT m_ColorDepth;
+ std::wstring m_DisableEffects;
+ BOOL m_SmartCard;
+ std::wstring m_Proxy;
+
+private:
+ static DWORD WINAPI event_thread(PVOID param);
+ bool handle_in_msg(ControllerValue& msg);
+ bool handle_out_msg();
+ HRESULT write_to_pipe(const void* data, uint32_t size);
+ HRESULT send_init();
+ HRESULT send_msg(uint32_t id);
+ HRESULT send_value(uint32_t id, uint32_t value);
+ HRESULT send_bool(uint32_t id, uint32_t value);
+ HRESULT send_wstr(uint32_t id, const wchar_t* str, bool use_mb_str = false);
+ void cleanup();
+
+ static DWORD WINAPI UsbCtrlWatchDog(PVOID param);
+ HRESULT ExecuteUsbCtrl();
+ HRESULT CreateCAFile(OUT LPWSTR szCAFileName, DWORD nSize);
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(OSpiceX), COSpiceX)
diff --git a/OSpiceX.rgs.template b/OSpiceX.rgs.template
new file mode 100644
index 0000000..1d47489
--- /dev/null
+++ b/OSpiceX.rgs.template
@@ -0,0 +1,34 @@
+HKCR
+{
+ SpiceX.OSpiceX.1 = s 'OSpiceX Class'
+ {
+ CLSID = s '{CLASS_ID}'
+ }
+ SpiceX.OSpiceX = s 'OSpiceX Class'
+ {
+ CLSID = s '{CLASS_ID}'
+ CurVer = s 'SpiceX.OSpiceX.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {CLASS_ID} = s 'Red Hat SpiceX Client'
+ {
+ ProgID = s 'SpiceX.OSpiceX.1'
+ VersionIndependentProgID = s 'SpiceX.OSpiceX'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ ForceRemove 'Control'
+ ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 102'
+ 'MiscStatus' = s '0'
+ {
+ '1' = s '%OLEMISC%'
+ }
+ 'TypeLib' = s '{24280E9D-5DDB-4C31-84AA-D8E8010BAEB1}'
+ 'Version' = s '1.0'
+ }
+ }
+}
diff --git a/OSpiceX_x64.htm b/OSpiceX_x64.htm
new file mode 100644
index 0000000..0d8fd1a
--- /dev/null
+++ b/OSpiceX_x64.htm
@@ -0,0 +1,443 @@
+<HTML>
+<HEAD>
+<TITLE>ATL 8.0 test page for object OSpiceX</TITLE>
+
+<script id=clientEventHandlersJS language=javascript>
+<!--
+
+function OnPageLoad()
+{
+ document.all["HostIp1"].value = OSpiceX1.HostIP;
+ document.all["HostPort1"].value = OSpiceX1.Port;
+ document.all["Password1"].value = OSpiceX1.Password;
+ document.all["CipherSuite1"].value = OSpiceX1.CipherSuite;
+ document.all["NumberOfMonitors1"].value = OSpiceX1.NumberOfMonitors;
+
+ document.all["HostIp2"].value = OSpiceX2.HostIP;
+ document.all["HostPort2"].value = OSpiceX2.Port;
+ document.all["Password2"].value = OSpiceX2.Password;
+ document.all["CipherSuite2"].value = OSpiceX1.CipherSuite;
+
+ document.all["AudioGuestIp1"].value = OSpiceX1.AudioGuestIP;
+ document.all["AudioGuestPort1"].value = OSpiceX1.AudioGuestPort;
+}
+
+function SP1_Title()
+{
+ OSpiceX1.Title = "Test Title";
+}
+
+function SetAudioGuestIp1()
+{
+ OSpiceX1.AudioGuestIP = document.all["AudioGuestIp1"].value; //set property
+}
+
+function SetAudioGuestPort1()
+{
+ OSpiceX1.AudioGuestPort = document.all["AudioGuestPort1"].value; //set property
+}
+
+function SP1_AudioConnect()
+{
+ try
+ {
+ OSpiceX1.ConnectAudio();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP1_AudioDisconnect()
+{
+ try
+ {
+ OSpiceX1.DisconnectAudio();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function CreateMenu()
+{
+ //OSpiceX1.CreateMenu( document.all["MenuRes"].value);
+ OSpiceX1.DynamicMenu = document.all["MenuRes"].value;
+}
+
+function DeleteMenu()
+{
+ OSpiceX1.DeleteMenu();
+}
+
+function SetTitle1()
+{
+ OSpiceX1.Title = document.all["Title1"].value; //set property
+}
+
+function GetTitle1()
+{
+ alert(OSpiceX1.Title);
+}
+
+function SetHostIp1()
+{
+ OSpiceX1.HostIP = document.all["HostIp1"].value; //set property
+}
+
+function SetHostPort1()
+{
+ OSpiceX1.Port = document.all["HostPort1"].value; //set property
+}
+
+function SetSecurePort1()
+{
+ OSpiceX1.SecurePort = document.all["SecurePort1"].value; //set property
+}
+
+function SetPassword1()
+{
+ OSpiceX1.Password = document.all["Password1"].value; //set property
+}
+
+function SetCipherSuite1()
+{
+ OSpiceX1.CipherSuite = document.all["CipherSuite1"].value; //set property
+}
+
+function SetEncryptedChannels1()
+{
+ OSpiceX1.SSLChannels = document.all["EncryptedChannels1"].value; //set property
+}
+
+function SetNumberOfMonitors1()
+{
+ OSpiceX1.NumberOfMonitors = document.all["NumberOfMonitors1"].value; //set property
+}
+
+function SetColorDepth1()
+{
+ OSpiceX1.ColorDepth = document.all["ColorDepth1"].value; //set property
+}
+
+function SetDisableEffects1()
+{
+ OSpiceX1.DisableEffects = document.all["DisableEffects1"].value; //set property
+}
+
+function SP1_Connect()
+{
+ try
+ {
+ OSpiceX1.FullScreen = document.all["Checkbox1"].checked;
+
+ if (document.getElementById('NoUsb').checked) {
+ OSpiceX1.UsbListenPort = document.getElementById('UsbListenPort').value;
+ } else {
+ OSpiceX1.UsbListenPort = 0;
+ }
+
+ OSpiceX1.Connect();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP1_Disconnect()
+{
+ try
+ {
+ OSpiceX1.Disconnect();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP1_Show()
+{
+ try
+ {
+ OSpiceX1.Show();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+
+ // OSpiceX1.Port = 5; // set property
+ // alert(OSpiceX1.Port); //get property
+}
+
+function SP1_Hide()
+{
+ try
+ {
+ OSpiceX1.Hide();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SetTitle2()
+{
+ OSpiceX2.Title = document.all["Title2"].value; //set property
+}
+
+function SetHostIp2()
+{
+ OSpiceX2.HostIP = document.all["HostIp2"].value; //set property
+}
+
+function SetHostPort2()
+{
+ OSpiceX2.Port = document.all["HostPort2"].value; //set property
+}
+
+function SetPassword2()
+{
+ OSpiceX2.Password = document.all["Password2"].value; //set property
+}
+
+function SetCipherSuite2()
+{
+ OSpiceX1.CipherSuite = documet.all["CipherSuite2"].value; //set property
+}
+
+function SP2_Connect()
+{
+try
+ {
+ OSpiceX2.Connect();
+ }
+catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP2_Disconnect()
+{
+try
+ {
+ OSpiceX2.Disconnect();
+ }
+catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP2_Show()
+{
+ try
+ {
+ OSpiceX2.Show();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP2_Hide()
+{
+ try
+ {
+ OSpiceX2.Hide();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function OnDisconnected(ErrCode)
+{
+ alert("OnDisconnected =" + ErrCode);
+}
+
+function OnMenuItemSelected(ItemID)
+{
+ alert("OnMenuItemSelected =" + ItemID);
+}
+
+function translate_errnum(num)
+{
+ var errnum = (num & 268435455); // get rid of severity
+ var msg = "" + errnum.toString(16).toUpperCase();
+ while (msg.length < 6)
+ {
+ msg = "0" + msg;
+ }
+ return "0x80" + msg;
+}
+
+function Text2_onclick() {
+
+}
+
+//-->
+</script>
+
+<script language="javascript" event="OnDisconnected(ErrCode)" for="OSpiceX1">
+<!--
+ return OnDisconnected(ErrCode)
+//-->
+</script>
+
+<script language="javascript" event="OnMenuItemSelected(ItemID)" for="OSpiceX1">
+<!--
+ return OnMenuItemSelected(ItemID)
+//-->
+</script>
+
+
+</HEAD>
+<BODY>
+
+<body onLoad="OnPageLoad()">
+
+Current HostIp
+<input id="HostIp1" type="text" size="13"> </input>
+<INPUT id="SetHostIp1" type="button" value="SetHostIp" name="SetHostIp1" language=javascript
+onclick="return SetHostIp1()">
+Current HostPort
+<input id="HostPort1" type="text" size="3"> </input>
+<INPUT id="SetHostPort1" type="button" value="SetHostPort" name="SetHostPort1" language=javascript
+onclick="return SetHostPort1()">
+ &nbsp;SecurePort
+ <input id="SecurePort" type="text" size="3"></INPUT>
+ <INPUT id="SecurePort1" type="button" value="Set Secure Port" name="SecurePort1" language=javascript
+onclick="return SetSecurePort1()">
+ <br />
+ColorDepth
+<input id="ColorDepth1" type="text" size="3"> </input>
+<INPUT id="SetColorDepth1" type="button" value="SetColorDepth" name="SetColorDepth1" language=javascript
+onclick="return SetColorDepth1()">
+DisableEffects
+<input id="DisableEffects1" type="text" size="13"> </input>
+<INPUT id="SetDisableEffects1" type="button" value="SetDisableEffects" name="SetDisableEffects1" language=javascript
+onclick="return SetDisableEffects1()">
+<br />
+Current Password
+<input id="Password1" type="text" size="3"></input>
+<INPUT id="SetPassword1" type="button" value="SetPassword" name="SetPassword1" language=javascript
+onclick="return SetPassword1()">
+ &nbsp;&nbsp;
+ CipherSuite
+ <input id="CipherSuite1" type="text" size="13">
+ <INPUT id="SetCipherSuite1" type="button" value="Set Cipher Suite" name="Set Cipher suite" language=javascript
+onclick="return SetCipherSuite1()"><br />
+ Choose which channels to encrypt:
+ <input id="EncryptedChannels1" type="text" style="width: 476px">
+ <INPUT id="SetSSLChannels1" type="button" value="Set Encrypted Channels" name="Set Encrypted Channels" language=javascript
+onclick="return SetEncryptedChannels1()" style="width: 150px"><br />
+<br />
+ Number of monitors
+ <input id="NumberOfMonitors1" type="text" size="13">
+ <INPUT id="SetNumberOfMonitors1" type="button" value="Set number of monitors" name="Set number of monitors" language=javascript
+onclick="return SetNumberOfMonitors1()"><br />
+<br />
+<p>
+<input id="NoUsb" type="checkbox" checked onclick="document.getElementById('UsbListenPort').disabled = !document.getElementById('UsbListenPort').disabled">Enable USB
+USB Listen Port <input id="UsbListenPort" type="text" size="5" maxlegnth="5" value="32032">
+</p>
+<INPUT id="Button11" type="button" value="SP1_Connect" name="OSpiceX1Connect" language=javascript
+onclick="return SP1_Connect()">
+<INPUT id="Button12" type="button" value="SP1_Disconnect" name="OSpiceX1Disconnect" language=javascript
+onclick="return SP1_Disconnect()">
+ <input id="Checkbox1" type="checkbox" /><label for="Checkbox1">Full screen</label><br />
+
+<OBJECT codebase='SpiceX_x64.cab#version=1,0,0,1' ID="OSpiceX1" CLASSID="CLSID:ACD6D89C-938D-49B4-8E81-DDBD13F4B48B">
+<PARAM NAME="Port" VALUE= "">
+<PARAM NAME="SecurePort" VALUE= "">
+<PARAM NAME="HostIP" VALUE="">
+<PARAM NAME="Title" VALUE="Hello Spice">
+<PARAM NAME="Password" VALUE="test">
+<PARAM name="CipherSuite" VALUE="" >
+</OBJECT>
+<INPUT id="Button13" type="button" value="SP1_Show" name="OSpiceX1Show" language=javascript
+onclick="return SP1_Show()">
+<INPUT id="Button14" type="button" value="SP1_Hide" name="OSpiceX1Hide" language=javascript
+onclick="return SP1_Hide()">
+<INPUT id="SetTitle1" type="button" value="SetTitle1" name="SetTitle1" language=javascript
+onclick="return SetTitle1()">
+<input id="Title1" type="text" size="1024" value="Hello Spice"> </input>
+<INPUT id="GetTitle1" type="button" value="GetTitle1" name="GetTitle1" language=javascript
+onclick="return GetTitle1()">
+
+<br>
+Menu resource: <input id="MenuRes" type="text" size="100"> </input><br>
+<INPUT id="CreateMenu" type="button" value="CreateMenu" name="CreateMenu" language=javascript
+onclick="return CreateMenu()">
+<INPUT id="DeleteMenu" type="button" value="DeleteMenu" name="DeleteMenu" language=javascript
+onclick="return DeleteMenu()">
+
+
+<br />----------------------------------------------------------------------------------------------<br />
+Current HostIp
+<input id="HostIp2" type="text" size="13"> </input>
+<INPUT id="SetHostIp2" type="button" value="SetHostIp" name="SetHostIp2" language=javascript
+onclick="return SetHostIp2()">
+Current HostPort
+<input id="HostPort2" type="text" size="3"> </input>
+<INPUT id="SetHostPort2" type="button" value="SetHostPort" name="SetHostPort2" language=javascript
+onclick="return SetHostPort2()">
+Current Password
+<input id="Password2" type="text" size="3"></input>
+<INPUT id="SetPassword2" type="button" value="SetPassword" name="SetPassword2" language=javascript
+onclick="return SetPassword2()">
+ <br />
+ CipherSuite
+ <input id="CipherSuite2" type="text" size="13">
+ <INPUT id="SetCipherSuite2" type="button" value="Set Cipher Suite" name="Set Cipher suite" language=javascript
+onclick="return SetCipherSuite2()"><br />
+<br />
+
+<INPUT id="Button21" type="button" value="SP2_Connect" name="OSpiceX2Connect" language=javascript
+onclick="return SP2_Connect()">
+<INPUT id="Button22" type="button" value="SP2_Disconnect" name="OSpiceX2Disconnect" language=javascript
+onclick="return SP2_Disconnect()">
+<br />
+<OBJECT ID="OSpiceX2" CLASSID="CLSID:ACD6D89C-938D-49B4-8E81-DDBD13F4B48B"></OBJECT>
+</BODY>
+<INPUT id="Button23" type="button" value="SP2_Show" name="OSpiceX2Show" language=javascript
+onclick="return SP2_Show()">
+<INPUT id="Button24" type="button" value="SP2_Hide" name="OSpiceX2Hide" language=javascript
+onclick="return SP2_Hide()">
+<INPUT id="SetTitle2" type="button" value="SetTitle2" name="SetTitle2" language=javascript
+onclick="return SetTitle2()">
+<input id="Title2" type="text" size="20"> </input>
+
+<br />
+<br />
+<br />
+Audio:
+<br />
+Current GuestIp
+<input id="AudioGuestIp1" type="text"> </input>
+<INPUT id="SetAudioGuestIp1" type="button" value="SetAudioGuestIp" name="SetAudioGuestIp1" language=javascript
+onclick="return SetAudioGuestIp1()">
+<br />
+Current GuestPort
+<input id="AudioGuestPort1" type="text" size="13"> </input>
+<INPUT id="SetAudioGuestPort1" type="button" value="SetAudioGuestPort" name="SetAudioGuestPort1" language=javascript
+onclick="return SetAudioGuestPort1()">
+<br />
+<INPUT id="Button100" type="button" value="SP1_AudioConnect" name="OSpiceX1AudioConnect" language=javascript
+onclick="return SP1_AudioConnect()">
+<INPUT id="Button101" type="button" value="SP1_AudioDisconnect" name="OSpiceX1AudioDisconnect" language=javascript
+onclick="return SP1_AudioDisconnect()">
+
+<INPUT id="Button102" type="button" value="SP1_SpiceTitle" name="OSpiceX1SetTitle" language=javascript
+onclick="return SP1_Title()">
+
+</HTML>
diff --git a/OSpiceX_x86.htm b/OSpiceX_x86.htm
new file mode 100644
index 0000000..7423df7
--- /dev/null
+++ b/OSpiceX_x86.htm
@@ -0,0 +1,443 @@
+<HTML>
+<HEAD>
+<TITLE>ATL 8.0 test page for object OSpiceX</TITLE>
+
+<script id=clientEventHandlersJS language=javascript>
+<!--
+
+function OnPageLoad()
+{
+ document.all["HostIp1"].value = OSpiceX1.HostIP;
+ document.all["HostPort1"].value = OSpiceX1.Port;
+ document.all["Password1"].value = OSpiceX1.Password;
+ document.all["CipherSuite1"].value = OSpiceX1.CipherSuite;
+ document.all["NumberOfMonitors1"].value = OSpiceX1.NumberOfMonitors;
+
+ document.all["HostIp2"].value = OSpiceX2.HostIP;
+ document.all["HostPort2"].value = OSpiceX2.Port;
+ document.all["Password2"].value = OSpiceX2.Password;
+ document.all["CipherSuite2"].value = OSpiceX1.CipherSuite;
+
+ document.all["AudioGuestIp1"].value = OSpiceX1.AudioGuestIP;
+ document.all["AudioGuestPort1"].value = OSpiceX1.AudioGuestPort;
+}
+
+function SP1_Title()
+{
+ OSpiceX1.Title = "Test Title";
+}
+
+function SetAudioGuestIp1()
+{
+ OSpiceX1.AudioGuestIP = document.all["AudioGuestIp1"].value; //set property
+}
+
+function SetAudioGuestPort1()
+{
+ OSpiceX1.AudioGuestPort = document.all["AudioGuestPort1"].value; //set property
+}
+
+function SP1_AudioConnect()
+{
+ try
+ {
+ OSpiceX1.ConnectAudio();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP1_AudioDisconnect()
+{
+ try
+ {
+ OSpiceX1.DisconnectAudio();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function CreateMenu()
+{
+ //OSpiceX1.CreateMenu( document.all["MenuRes"].value);
+ OSpiceX1.DynamicMenu = document.all["MenuRes"].value;
+}
+
+function DeleteMenu()
+{
+ OSpiceX1.DeleteMenu();
+}
+
+function SetTitle1()
+{
+ OSpiceX1.Title = document.all["Title1"].value; //set property
+}
+
+function GetTitle1()
+{
+ alert(OSpiceX1.Title);
+}
+
+function SetHostIp1()
+{
+ OSpiceX1.HostIP = document.all["HostIp1"].value; //set property
+}
+
+function SetHostPort1()
+{
+ OSpiceX1.Port = document.all["HostPort1"].value; //set property
+}
+
+function SetSecurePort1()
+{
+ OSpiceX1.SecurePort = document.all["SecurePort1"].value; //set property
+}
+
+function SetPassword1()
+{
+ OSpiceX1.Password = document.all["Password1"].value; //set property
+}
+
+function SetCipherSuite1()
+{
+ OSpiceX1.CipherSuite = document.all["CipherSuite1"].value; //set property
+}
+
+function SetEncryptedChannels1()
+{
+ OSpiceX1.SSLChannels = document.all["EncryptedChannels1"].value; //set property
+}
+
+function SetNumberOfMonitors1()
+{
+ OSpiceX1.NumberOfMonitors = document.all["NumberOfMonitors1"].value; //set property
+}
+
+function SetColorDepth1()
+{
+ OSpiceX1.ColorDepth = document.all["ColorDepth1"].value; //set property
+}
+
+function SetDisableEffects1()
+{
+ OSpiceX1.DisableEffects = document.all["DisableEffects1"].value; //set property
+}
+
+function SP1_Connect()
+{
+ try
+ {
+ OSpiceX1.FullScreen = document.all["Checkbox1"].checked;
+
+ if (document.getElementById('NoUsb').checked) {
+ OSpiceX1.UsbListenPort = document.getElementById('UsbListenPort').value;
+ } else {
+ OSpiceX1.UsbListenPort = 0;
+ }
+
+ OSpiceX1.Connect();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP1_Disconnect()
+{
+ try
+ {
+ OSpiceX1.Disconnect();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP1_Show()
+{
+ try
+ {
+ OSpiceX1.Show();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+
+ // OSpiceX1.Port = 5; // set property
+ // alert(OSpiceX1.Port); //get property
+}
+
+function SP1_Hide()
+{
+ try
+ {
+ OSpiceX1.Hide();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SetTitle2()
+{
+ OSpiceX2.Title = document.all["Title2"].value; //set property
+}
+
+function SetHostIp2()
+{
+ OSpiceX2.HostIP = document.all["HostIp2"].value; //set property
+}
+
+function SetHostPort2()
+{
+ OSpiceX2.Port = document.all["HostPort2"].value; //set property
+}
+
+function SetPassword2()
+{
+ OSpiceX2.Password = document.all["Password2"].value; //set property
+}
+
+function SetCipherSuite2()
+{
+ OSpiceX1.CipherSuite = documet.all["CipherSuite2"].value; //set property
+}
+
+function SP2_Connect()
+{
+try
+ {
+ OSpiceX2.Connect();
+ }
+catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP2_Disconnect()
+{
+try
+ {
+ OSpiceX2.Disconnect();
+ }
+catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP2_Show()
+{
+ try
+ {
+ OSpiceX2.Show();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function SP2_Hide()
+{
+ try
+ {
+ OSpiceX2.Hide();
+ }
+ catch(e)
+ {
+ alert(translate_errnum(e.number));
+ }
+}
+
+function OnDisconnected(ErrCode)
+{
+ alert("OnDisconnected =" + ErrCode);
+}
+
+function OnMenuItemSelected(ItemID)
+{
+ alert("OnMenuItemSelected =" + ItemID);
+}
+
+function translate_errnum(num)
+{
+ var errnum = (num & 268435455); // get rid of severity
+ var msg = "" + errnum.toString(16).toUpperCase();
+ while (msg.length < 6)
+ {
+ msg = "0" + msg;
+ }
+ return "0x80" + msg;
+}
+
+function Text2_onclick() {
+
+}
+
+//-->
+</script>
+
+<script language="javascript" event="OnDisconnected(ErrCode)" for="OSpiceX1">
+<!--
+ return OnDisconnected(ErrCode)
+//-->
+</script>
+
+<script language="javascript" event="OnMenuItemSelected(ItemID)" for="OSpiceX1">
+<!--
+ return OnMenuItemSelected(ItemID)
+//-->
+</script>
+
+
+</HEAD>
+<BODY>
+
+<body onLoad="OnPageLoad()">
+
+Current HostIp
+<input id="HostIp1" type="text" size="13"> </input>
+<INPUT id="SetHostIp1" type="button" value="SetHostIp" name="SetHostIp1" language=javascript
+onclick="return SetHostIp1()">
+Current HostPort
+<input id="HostPort1" type="text" size="3"> </input>
+<INPUT id="SetHostPort1" type="button" value="SetHostPort" name="SetHostPort1" language=javascript
+onclick="return SetHostPort1()">
+ &nbsp;SecurePort
+ <input id="SecurePort" type="text" size="3"></INPUT>
+ <INPUT id="SecurePort1" type="button" value="Set Secure Port" name="SecurePort1" language=javascript
+onclick="return SetSecurePort1()">
+ <br />
+ColorDepth
+<input id="ColorDepth1" type="text" size="3"> </input>
+<INPUT id="SetColorDepth1" type="button" value="SetColorDepth" name="SetColorDepth1" language=javascript
+onclick="return SetColorDepth1()">
+DisableEffects
+<input id="DisableEffects1" type="text" size="13"> </input>
+<INPUT id="SetDisableEffects1" type="button" value="SetDisableEffects" name="SetDisableEffects1" language=javascript
+onclick="return SetDisableEffects1()">
+<br />
+Current Password
+<input id="Password1" type="text" size="3"></input>
+<INPUT id="SetPassword1" type="button" value="SetPassword" name="SetPassword1" language=javascript
+onclick="return SetPassword1()">
+ &nbsp;&nbsp;
+ CipherSuite
+ <input id="CipherSuite1" type="text" size="13">
+ <INPUT id="SetCipherSuite1" type="button" value="Set Cipher Suite" name="Set Cipher suite" language=javascript
+onclick="return SetCipherSuite1()"><br />
+ Choose which channels to encrypt:
+ <input id="EncryptedChannels1" type="text" style="width: 476px">
+ <INPUT id="SetSSLChannels1" type="button" value="Set Encrypted Channels" name="Set Encrypted Channels" language=javascript
+onclick="return SetEncryptedChannels1()" style="width: 150px"><br />
+<br />
+ Number of monitors
+ <input id="NumberOfMonitors1" type="text" size="13">
+ <INPUT id="SetNumberOfMonitors1" type="button" value="Set number of monitors" name="Set number of monitors" language=javascript
+onclick="return SetNumberOfMonitors1()"><br />
+<br />
+<p>
+<input id="NoUsb" type="checkbox" checked onclick="document.getElementById('UsbListenPort').disabled = !document.getElementById('UsbListenPort').disabled">Enable USB
+USB Listen Port <input id="UsbListenPort" type="text" size="5" maxlegnth="5" value="32032">
+</p>
+<INPUT id="Button11" type="button" value="SP1_Connect" name="OSpiceX1Connect" language=javascript
+onclick="return SP1_Connect()">
+<INPUT id="Button12" type="button" value="SP1_Disconnect" name="OSpiceX1Disconnect" language=javascript
+onclick="return SP1_Disconnect()">
+ <input id="Checkbox1" type="checkbox" /><label for="Checkbox1">Full screen</label><br />
+
+<OBJECT codebase='SpiceX_x86.cab#version=1,0,0,1' ID="OSpiceX1" CLASSID="CLSID:ACD6D89C-938D-49B4-8E81-DDBD13F4B48A">
+<PARAM NAME="Port" VALUE= "">
+<PARAM NAME="SecurePort" VALUE= "">
+<PARAM NAME="HostIP" VALUE="">
+<PARAM NAME="Title" VALUE="Hello Spice">
+<PARAM NAME="Password" VALUE="test">
+<PARAM name="CipherSuite" VALUE="" >
+</OBJECT>
+<INPUT id="Button13" type="button" value="SP1_Show" name="OSpiceX1Show" language=javascript
+onclick="return SP1_Show()">
+<INPUT id="Button14" type="button" value="SP1_Hide" name="OSpiceX1Hide" language=javascript
+onclick="return SP1_Hide()">
+<INPUT id="SetTitle1" type="button" value="SetTitle1" name="SetTitle1" language=javascript
+onclick="return SetTitle1()">
+<input id="Title1" type="text" size="1024" value="Hello Spice"> </input>
+<INPUT id="GetTitle1" type="button" value="GetTitle1" name="GetTitle1" language=javascript
+onclick="return GetTitle1()">
+
+<br>
+Menu resource: <input id="MenuRes" type="text" size="100"> </input><br>
+<INPUT id="CreateMenu" type="button" value="CreateMenu" name="CreateMenu" language=javascript
+onclick="return CreateMenu()">
+<INPUT id="DeleteMenu" type="button" value="DeleteMenu" name="DeleteMenu" language=javascript
+onclick="return DeleteMenu()">
+
+
+<br />----------------------------------------------------------------------------------------------<br />
+Current HostIp
+<input id="HostIp2" type="text" size="13"> </input>
+<INPUT id="SetHostIp2" type="button" value="SetHostIp" name="SetHostIp2" language=javascript
+onclick="return SetHostIp2()">
+Current HostPort
+<input id="HostPort2" type="text" size="3"> </input>
+<INPUT id="SetHostPort2" type="button" value="SetHostPort" name="SetHostPort2" language=javascript
+onclick="return SetHostPort2()">
+Current Password
+<input id="Password2" type="text" size="3"></input>
+<INPUT id="SetPassword2" type="button" value="SetPassword" name="SetPassword2" language=javascript
+onclick="return SetPassword2()">
+ <br />
+ CipherSuite
+ <input id="CipherSuite2" type="text" size="13">
+ <INPUT id="SetCipherSuite2" type="button" value="Set Cipher Suite" name="Set Cipher suite" language=javascript
+onclick="return SetCipherSuite2()"><br />
+<br />
+
+<INPUT id="Button21" type="button" value="SP2_Connect" name="OSpiceX2Connect" language=javascript
+onclick="return SP2_Connect()">
+<INPUT id="Button22" type="button" value="SP2_Disconnect" name="OSpiceX2Disconnect" language=javascript
+onclick="return SP2_Disconnect()">
+<br />
+<OBJECT ID="OSpiceX2" CLASSID="CLSID:ACD6D89C-938D-49B4-8E81-DDBD13F4B48A"></OBJECT>
+</BODY>
+<INPUT id="Button23" type="button" value="SP2_Show" name="OSpiceX2Show" language=javascript
+onclick="return SP2_Show()">
+<INPUT id="Button24" type="button" value="SP2_Hide" name="OSpiceX2Hide" language=javascript
+onclick="return SP2_Hide()">
+<INPUT id="SetTitle2" type="button" value="SetTitle2" name="SetTitle2" language=javascript
+onclick="return SetTitle2()">
+<input id="Title2" type="text" size="20"> </input>
+
+<br />
+<br />
+<br />
+Audio:
+<br />
+Current GuestIp
+<input id="AudioGuestIp1" type="text"> </input>
+<INPUT id="SetAudioGuestIp1" type="button" value="SetAudioGuestIp" name="SetAudioGuestIp1" language=javascript
+onclick="return SetAudioGuestIp1()">
+<br />
+Current GuestPort
+<input id="AudioGuestPort1" type="text" size="13"> </input>
+<INPUT id="SetAudioGuestPort1" type="button" value="SetAudioGuestPort" name="SetAudioGuestPort1" language=javascript
+onclick="return SetAudioGuestPort1()">
+<br />
+<INPUT id="Button100" type="button" value="SP1_AudioConnect" name="OSpiceX1AudioConnect" language=javascript
+onclick="return SP1_AudioConnect()">
+<INPUT id="Button101" type="button" value="SP1_AudioDisconnect" name="OSpiceX1AudioDisconnect" language=javascript
+onclick="return SP1_AudioDisconnect()">
+
+<INPUT id="Button102" type="button" value="SP1_SpiceTitle" name="OSpiceX1SetTitle" language=javascript
+onclick="return SP1_Title()">
+
+</HTML>
diff --git a/PreBuild.bat b/PreBuild.bat
new file mode 100644
index 0000000..50c1e03
--- /dev/null
+++ b/PreBuild.bat
@@ -0,0 +1,21 @@
+@ECHO OFF
+
+REM
+REM %1 = $(PlatformName)
+REM %2 = $(ConfigurationName)
+REM
+
+del SpiceX.inf
+del OSpiceX.rgs
+
+if "%1" == "Win32" (
+set CLSID=ACD6D89C-938D-49B4-8E81-DDBD13F4B48A
+) else if "%1" == "x64" (
+set CLSID=ACD6D89C-938D-49B4-8E81-DDBD13F4B48B
+) else (
+echo Wrong PlatformName %1
+exit /B 1
+)
+
+sed "s|CLASS_ID|%CLSID%|" SpiceX.inf.template > SpiceX.inf
+sed "s|CLASS_ID|%CLSID%|" OSpiceX.rgs.template > OSpiceX.rgs
diff --git a/ReadMe.txt b/ReadMe.txt
new file mode 100644
index 0000000..0d09759
--- /dev/null
+++ b/ReadMe.txt
@@ -0,0 +1,71 @@
+========================================================================
+ ACTIVE TEMPLATE LIBRARY : SpiceX Project Overview
+========================================================================
+
+AppWizard has created this SpiceX project for you to use as the starting point for
+writing your Dynamic Link Library (DLL).
+
+
+This file contains a summary of what you will find in each of the files that
+make up your project.
+
+SpiceX.vcproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+SpiceX.idl
+ This file contains the IDL definitions of the type library, the interfaces
+ and co-classes defined in your project.
+ This file will be processed by the MIDL compiler to generate:
+ C++ interface definitions and GUID declarations (SpiceX.h)
+ GUID definitions (SpiceX_i.c)
+ A type library (SpiceX.tlb)
+ Marshaling code (SpiceX_p.c and dlldata.c)
+
+SpiceX.h
+ This file contains the C++ interface definitions and GUID declarations of the
+ items defined in SpiceX.idl. It will be regenerated by MIDL during compilation.
+
+SpiceX.cpp
+ This file contains the object map and the implementation of your DLL's exports.
+
+SpiceX.rc
+ This is a listing of all of the Microsoft Windows resources that the
+ program uses.
+
+SpiceX.def
+ This module-definition file provides the linker with information about the exports
+ required by your DLL. It contains exports for:
+ DllGetClassObject
+ DllCanUnloadNow
+ GetProxyDllInfo
+ DllRegisterServer
+ DllUnregisterServer
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named SpiceX.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+ This is the standard header file that defines resource IDs.
+
+/////////////////////////////////////////////////////////////////////////////
+Proxy/stub DLL project and module definition file:
+
+SpiceXps.vcproj
+ This file is the project file for building a proxy/stub DLL if necessary.
+ The IDL file in the main project must contain at least one interface and you must
+ first compile the IDL file before building the proxy/stub DLL. This process generates
+ dlldata.c, SpiceX_i.c and SpiceX_p.c which are required
+ to build the proxy/stub DLL.
+
+SpiceXps.def
+ This module definition file provides the linker with information about the exports
+ required by the proxy/stub.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/Sign.bat b/Sign.bat
new file mode 100644
index 0000000..5aca6cb
--- /dev/null
+++ b/Sign.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+REM
+REM Spice SpiceX.dll file script.
+REM
+REM %1 = $(OutDir)
+REM %2 = $(ConfigurationName)
+REM %3 = $(PlatformName)
+REM
+
+SignTool sign /s MY /n "Red Hat, Inc." /t http://timestamp.verisign.com/scripts/timstamp.dll %1\SpiceX.dll
diff --git a/SpiceX.cpp b/SpiceX.cpp
new file mode 100644
index 0000000..1b1f826
--- /dev/null
+++ b/SpiceX.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+// SpiceX.cpp : Implementation of DLL Exports.
+
+
+#include "stdafx.h"
+#include "resource.h"
+#include "SpiceX.h"
+
+
+class CSpiceXModule : public CAtlDllModuleT< CSpiceXModule >
+{
+public :
+ DECLARE_LIBID(LIBID_SpiceXLib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SPICEX, "{E0D3BDEC-DF76-449B-9944-1935A6D73E72}")
+};
+
+CSpiceXModule _AtlModule;
+
+
+#ifdef _MANAGED
+#pragma managed(push, off)
+#endif
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ hInstance;
+ switch (dwReason) {
+ case DLL_PROCESS_ATTACH:
+ spicex_init_logger();
+ break;
+ case DLL_PROCESS_DETACH:
+ spicex_log_cleanup();
+ break;
+ };
+ return _AtlModule.DllMain(dwReason, lpReserved);
+}
+
+#ifdef _MANAGED
+#pragma managed(pop)
+#endif
+
+
+
+
+// Used to determine whether the DLL can be unloaded by OLE
+STDAPI DllCanUnloadNow(void)
+{
+ return _AtlModule.DllCanUnloadNow();
+}
+
+
+// Returns a class factory to create an object of the requested type
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+// DllRegisterServer - Adds entries to the system registry
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ HRESULT hr = _AtlModule.DllRegisterServer();
+ return hr;
+}
+
+
+// DllUnregisterServer - Removes entries from the system registry
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+ return hr;
+}
+
+STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
+{
+ HRESULT hr = E_FAIL;
+ static const wchar_t szUserSwitch[] = _T("user");
+ bool doPerUserRegistration = false;
+
+ if (pszCmdLine != NULL) {
+ if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0) {
+ doPerUserRegistration = true;
+ }
+ }
+
+ AtlSetPerUserRegistration(doPerUserRegistration);
+
+ if (bInstall) {
+ hr = DllRegisterServer();
+ if (FAILED(hr)) {
+ DllUnregisterServer();
+ }
+ } else {
+ hr = DllUnregisterServer();
+ }
+
+ return hr;
+}
diff --git a/SpiceX.ddf b/SpiceX.ddf
new file mode 100644
index 0000000..06ca478
--- /dev/null
+++ b/SpiceX.ddf
@@ -0,0 +1,8 @@
+.Set MaxDiskSize=CDROM
+.Set ReservePerCabinetSize=6144
+.Set Cabinet=on
+.Set Compress=on
+
+%file1%
+%file2%
+%file3%
diff --git a/SpiceX.def b/SpiceX.def
new file mode 100644
index 0000000..24390a5
--- /dev/null
+++ b/SpiceX.def
@@ -0,0 +1,10 @@
+; SpiceX.def : Declares the module parameters.
+
+LIBRARY "SpiceX.DLL"
+
+EXPORTS
+ DllInstall PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/SpiceX.idl b/SpiceX.idl
new file mode 100644
index 0000000..c8e82ac
--- /dev/null
+++ b/SpiceX.idl
@@ -0,0 +1,150 @@
+// SpiceX.idl : IDL source for SpiceX
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (SpiceX.tlb) and marshalling code.
+
+#include "olectl.h"
+import "oaidl.idl";
+import "ocidl.idl";
+
+[
+ object,
+ uuid(F5CAFE2A-DEB4-480C-ACC6-356A13B979A5),
+ dual,
+ nonextensible,
+ helpstring("IOSpiceX Interface"),
+ pointer_default(unique)
+]
+interface IOSpiceX : IDispatch{
+ [id(1), helpstring("method Connect")] HRESULT Connect(void);
+ [id(2), helpstring("method Disconnect")] HRESULT Disconnect(void);
+ [id(3), helpstring("method SendCAD")] HRESULT SendCAD(void);
+ [id(4), helpstring("method Show")] HRESULT Show(void);
+ [id(5), helpstring("method Hide")] HRESULT Hide(void);
+ [id(6), helpstring("method SetSecondaryAddress")] HRESULT SetSecondaryAddress(void);
+ [propget, id(7), helpstring("property HostIP")] HRESULT HostIP([out, retval] BSTR* pVal);
+ [propput, id(7), helpstring("property HostIP")] HRESULT HostIP([in] BSTR newVal);
+ [propget, id(8), helpstring("property Port")] HRESULT Port([out, retval] USHORT* pVal);
+ [propput, id(8), helpstring("property Port")] HRESULT Port([in] USHORT newVal);
+ [propget, id(9), helpstring("property ScaleEnable")] HRESULT ScaleEnable([out, retval] ULONG* pVal);
+ [propput, id(9), helpstring("property ScaleEnable")] HRESULT ScaleEnable([in] ULONG newVal);
+ [propget, id(10), helpstring("property ScaleNum")] HRESULT ScaleNum([out, retval] ULONG* pVal);
+ [propput, id(10), helpstring("property ScaleNum")] HRESULT ScaleNum([in] ULONG newVal);
+ [propget, id(11), helpstring("property ScaleDen")] HRESULT ScaleDen([out, retval] ULONG* pVal);
+ [propput, id(11), helpstring("property ScaleDen")] HRESULT ScaleDen([in] ULONG newVal);
+ [propget, id(12), helpstring("property FullScreen")] HRESULT FullScreen([out, retval] ULONG* pVal);
+ [propput, id(12), helpstring("property FullScreen")] HRESULT FullScreen([in] ULONG newVal);
+ [propget, id(13), helpstring("property MsUser")] HRESULT MsUser([out, retval] BSTR* pVal);
+ [propput, id(13), helpstring("property MsUser")] HRESULT MsUser([in] BSTR newVal);
+ [propget, id(14), helpstring("property MSDomain")] HRESULT MSDomain([out, retval] BSTR* pVal);
+ [propput, id(14), helpstring("property MSDomain")] HRESULT MSDomain([in] BSTR newVal);
+ [propget, id(15), helpstring("property MSPassword")] HRESULT MSPassword([out, retval] BSTR* pVal);
+ [propput, id(15), helpstring("property MSPassword")] HRESULT MSPassword([in] BSTR newVal);
+ [propget, id(16), helpstring("property StretchMode")] HRESULT StretchMode([out, retval] ULONG* pVal);
+ [propput, id(16), helpstring("property StretchMode")] HRESULT StretchMode([in] ULONG newVal);
+ [propget, id(17), helpstring("property ScreenHeight")] HRESULT ScreenHeight([out, retval] ULONG* pVal);
+ [propput, id(17), helpstring("property ScreenHeight")] HRESULT ScreenHeight([in] ULONG newVal);
+ [propget, id(18), helpstring("property ConnectingText")] HRESULT ConnectingText([out, retval] BSTR* pVal);
+ [propput, id(18), helpstring("property ConnectingText")] HRESULT ConnectingText([in] BSTR newVal);
+ [propget, id(19), helpstring("property DisconnectingText")] HRESULT DisconnectingText([out, retval] BSTR* pVal);
+ [propput, id(19), helpstring("property DisconnectingText")] HRESULT DisconnectingText([in] BSTR newVal);
+ [propget, id(20), helpstring("property SwapMouseButtons")] HRESULT SwapMouseButtons([out, retval] ULONG* pVal);
+ [propput, id(20), helpstring("property SwapMouseButtons")] HRESULT SwapMouseButtons([in] ULONG newVal);
+ [propget, id(21), helpstring("property AudioRedirection")] HRESULT AudioRedirection([out, retval] ULONG* pVal);
+ [propput, id(21), helpstring("property AudioRedirection")] HRESULT AudioRedirection([in] ULONG newVal);
+ [propget, id(22), helpstring("property SecondaryHostIP")] HRESULT SecondaryHostIP([out, retval] BSTR* pVal);
+ [propput, id(22), helpstring("property SecondaryHostIP")] HRESULT SecondaryHostIP([in] BSTR newVal);
+ [propget, id(23), helpstring("property SecondaryPort")] HRESULT SecondaryPort([out, retval] USHORT* pVal);
+ [propput, id(23), helpstring("property SecondaryPort")] HRESULT SecondaryPort([in] USHORT newVal);
+ [propget, id(24), helpstring("property PollingInterval")] HRESULT PollingInterval([out, retval] ULONG* pVal);
+ [propput, id(24), helpstring("property PollingInterval")] HRESULT PollingInterval([in] ULONG newVal);
+ [propget, id(25), helpstring("property Title")] HRESULT Title([out, retval] BSTR* pVal);
+ [propput, id(25), helpstring("property Title")] HRESULT Title([in] BSTR newVal);
+ [id(26), helpstring("method ConnectAudio")] HRESULT ConnectAudio(void);
+ [id(27), helpstring("method DisconnectAudio")] HRESULT DisconnectAudio(void);
+ [propget, id(28), helpstring("property AudioGuestIP")] HRESULT AudioGuestIP([out, retval] BSTR* pVal);
+ [propput, id(28), helpstring("property AudioGuestIP")] HRESULT AudioGuestIP([in] BSTR newVal);
+ [propget, id(29), helpstring("property AudioGuestPort")] HRESULT AudioGuestPort([out, retval] SHORT* pVal);
+ [propput, id(29), helpstring("property AudioGuestPort")] HRESULT AudioGuestPort([in] SHORT newVal);
+ [id(30), helpstring("method CreateMenu")] HRESULT CreateMenu([in] BSTR MenuResourceString);
+ [id(31), helpstring("method DeleteMenu")] HRESULT DeleteMenu(void);
+ [propget, id(32), helpstring("property multimediaPorts")] HRESULT multimediaPorts([out, retval] BSTR* pVal);
+ [propput, id(32), helpstring("property multimediaPorts")] HRESULT multimediaPorts([in] BSTR newVal);
+ [propget, id(33), helpstring("property DynamicMenu")] HRESULT DynamicMenu([out, retval] BSTR* pVal);
+ [propput, id(33), helpstring("property DynamicMenu")] HRESULT DynamicMenu([in] BSTR newVal);
+ [propget, id(34), helpstring("property Password")] HRESULT Password([out, retval] BSTR* pVal);
+ [propput, id(34), helpstring("property Password")] HRESULT Password([in] BSTR newVal);
+ [propget, id(35), helpstring("property CipherSuite")] HRESULT CipherSuite([out, retval] BSTR* pVal);
+ [propput, id(35), helpstring("property CipherSuite")] HRESULT CipherSuite([in] BSTR newVal);
+ [propget, id(36), helpstring("property NumberOfMonitors")] HRESULT NumberOfMonitors([out, retval] ULONG* pVal);
+ [propput, id(36), helpstring("property NumberOfMonitors")] HRESULT NumberOfMonitors([in] ULONG newVal);
+ [propget, id(37), helpstring("property UsbListenPort")] HRESULT UsbListenPort([out, retval] USHORT* pVal);
+ [propput, id(37), helpstring("property UsbListenPort")] HRESULT UsbListenPort([in] USHORT newVal);
+ [propget, id(38), helpstring("property AdminConsole")] HRESULT AdminConsole([out, retval] BOOL* pVal);
+ [propput, id(38), helpstring("property AdminConsole")] HRESULT AdminConsole([in] BOOL newVal);
+ [id(39), helpstring("method SetUsbFilter")] HRESULT SetUsbFilter([in] BSTR newVal);
+ [propget, id(40), helpstring("property SSLChannels")] HRESULT SSLChannels([out, retval] BSTR* pVal);
+ [propput, id(40), helpstring("property SSLChannels")] HRESULT SSLChannels([in] BSTR newVal);
+ [propget, id(41), helpstring("property SecurePort")] HRESULT SecurePort([out, retval] USHORT* pVal);
+ [propput, id(41), helpstring("property SecurePort")] HRESULT SecurePort([in] USHORT newVal);
+ [propget, id(42), helpstring("property SendCtrlAltDelete")] HRESULT SendCtrlAltDelete([out, retval] BOOL* pVal);
+ [propput, id(42), helpstring("property SendCtrlAltDelete")] HRESULT SendCtrlAltDelete([in] BOOL newVal);
+ [propget, id(43), helpstring("property NoTaskMgrExecution")] HRESULT NoTaskMgrExecution([out, retval] BOOL* pVal);
+ [propput, id(43), helpstring("property NoTaskMgrExecution")] HRESULT NoTaskMgrExecution([in] BOOL newVal);
+ [propget, id(44), helpstring("property GuestHostName")] HRESULT GuestHostName([out, retval] BSTR* pVal);
+ [propput, id(44), helpstring("property GuestHostName")] HRESULT GuestHostName([in] BSTR newVal);
+ [propget, id(45), helpstring("property HotKeys")] HRESULT HotKey([out, retval] BSTR* pVal);
+ [propput, id(45), helpstring("property HotKeys")] HRESULT HotKey([in] BSTR newVal);
+ [propget, id(46), helpstring("property Version")] HRESULT Version([out, retval] BSTR* pVal);
+ [propget, id(47), helpstring("property UsbAutoShare")] HRESULT UsbAutoShare([out, retval] BOOL* pVal);
+ [propput, id(47), helpstring("property UsbAutoShare")] HRESULT UsbAutoShare([in] BOOL newVal);
+ [id(48), helpstring("method SetLanguageStrings")] HRESULT SetLanguageStrings([in] BSTR bzSection, [in] BSTR bzLangStr);
+ [propget, id(49), helpstring("property TrustStore")] HRESULT TrustStore([out, retval] BSTR* pVal);
+ [propput, id(49), helpstring("property TrustStore")] HRESULT TrustStore([in] BSTR newVal);
+ [propget, id(50), helpstring("property HostSubject")] HRESULT HostSubject([out, retval] BSTR* pVal);
+ [propput, id(50), helpstring("property HostSubject")] HRESULT HostSubject([in] BSTR newVal);
+ [propget, id(51), helpstring("property ColorDepth")] HRESULT ColorDepth([out, retval] USHORT* pVal);
+ [propput, id(51), helpstring("property ColorDepth")] HRESULT ColorDepth([in] USHORT newVal);
+ [propget, id(52), helpstring("property DisableEffects")] HRESULT DisableEffects([out, retval] BSTR* pVal);
+ [propput, id(52), helpstring("property DisableEffects")] HRESULT DisableEffects([in] BSTR newVal);
+ [propget, id(53), helpstring("property SmartCard")] HRESULT SmartCard([out, retval] BOOL* pVal);
+ [propput, id(53), helpstring("property SmartCard")] HRESULT SmartCard([in] BOOL newVal);
+ [propget, id(54), helpstring("property Proxy")] HRESULT Proxy([out, retval] BSTR* pVal);
+ [propput, id(54), helpstring("property Proxy")] HRESULT Proxy([in] BSTR newVal);
+};
+
+[
+ uuid(24280E9D-5DDB-4C31-84AA-D8E8010BAEB1),
+ version(1.0),
+ helpstring("SpiceX 1.0 Type Library")
+]
+library SpiceXLib
+{
+ importlib("stdole2.tlb");
+ [
+ uuid(3C0CD01E-311F-4B9B-B347-C6E5D6611BE1),
+ helpstring("_IOSpiceXEvents Interface")
+ ]
+ dispinterface _IOSpiceXEvents
+ {
+ properties:
+ methods:
+ [id(1), helpstring("method OnDisconnected")] HRESULT OnDisconnected([in] LONG ErrCode);
+ [id(2), helpstring("method OnMenuItemSelected")] HRESULT OnMenuItemSelected([in] ULONG ulItemID);
+ };
+ [
+#ifdef _WIN64
+ uuid(ACD6D89C-938D-49B4-8E81-DDBD13F4B48B),
+#else
+ uuid(ACD6D89C-938D-49B4-8E81-DDBD13F4B48A),
+#endif
+ control,
+ helpstring("OSpiceX Class")
+ ]
+ coclass OSpiceX
+ {
+ [default] interface IOSpiceX;
+ [default, source] dispinterface _IOSpiceXEvents;
+ };
+};
diff --git a/SpiceX.inf.template b/SpiceX.inf.template
new file mode 100644
index 0000000..d2048ad
--- /dev/null
+++ b/SpiceX.inf.template
@@ -0,0 +1,24 @@
+[version]
+; version signature (same for both NT and Win95) do not remove
+signature="$CHICAGO$"
+AdvancedINF=2.0
+
+[Setup Hooks]
+hook1=hook1
+
+[hook1]
+Run="%EXTRACT_DIR%\VIRT_VIEWER_INSTALLER" /S
+
+[Add.Code]
+SpiceX.dll=SpiceX.dll
+
+[SpiceX.dll]
+File=thiscab
+FileVersion=VERSION
+clsid={CLASS_ID}
+RegisterServer=yes
+RedirectToHKCU=yes
+
+
+[Deployment]
+InstallScope=user|machine
diff --git a/SpiceX.rc b/SpiceX.rc
new file mode 100644
index 0000000..75cc4ed
--- /dev/null
+++ b/SpiceX.rc
@@ -0,0 +1,146 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.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
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_OSPICEX REGISTRY "OSpiceX.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_OSPICEX BITMAP "OSpiceX.bmp"
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Hebrew resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HEB)
+#ifdef _WIN32
+LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT
+#pragma code_page(1255)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_SPICEX REGISTRY "SpiceX.rgs"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "1 TYPELIB ""SpiceX.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 5,0,0,2
+ PRODUCTVERSION 5,0,0,2
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Red Hat Inc."
+ VALUE "FileDescription", "ActiveX for the Spice system"
+ VALUE "FileVersion", "5,0,0,2"
+ VALUE "InternalName", "SpiceX.dll"
+ VALUE "LegalCopyright", "Copyright (c) 2009 Red Hat, Inc. and/or its affiliates."
+ VALUE "OriginalFilename", "SpiceX.dll"
+ VALUE "ProductName", "Red Hat Spice"
+ VALUE "ProductVersion", "5,0,0,2"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PROJNAME "SpiceX"
+END
+
+#endif // Hebrew resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "SpiceX.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/SpiceX.rgs b/SpiceX.rgs
new file mode 100644
index 0000000..f369304
--- /dev/null
+++ b/SpiceX.rgs
@@ -0,0 +1,11 @@
+HKCR
+{
+ NoRemove AppID
+ {
+ '%APPID%' = s 'SpiceX'
+ 'SpiceX.DLL'
+ {
+ val AppID = s '%APPID%'
+ }
+ }
+}
diff --git a/SpiceX.sln b/SpiceX.sln
new file mode 100644
index 0000000..747d3d9
--- /dev/null
+++ b/SpiceX.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpiceX", "SpiceX.vcproj", "{4B0C8744-5078-4F94-BB96-963B5F6AAAE5}"
+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
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Debug|Win32.Build.0 = Debug|Win32
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Debug|x64.ActiveCfg = Debug|x64
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Debug|x64.Build.0 = Debug|x64
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Release|Win32.ActiveCfg = Release|Win32
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Release|Win32.Build.0 = Release|Win32
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Release|x64.ActiveCfg = Release|x64
+ {4B0C8744-5078-4F94-BB96-963B5F6AAAE5}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/SpiceX.vcproj b/SpiceX.vcproj
new file mode 100644
index 0000000..fd6a5ca
--- /dev/null
+++ b/SpiceX.vcproj
@@ -0,0 +1,634 @@
+<?xml version="1.0" encoding="windows-1255"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="SpiceX"
+ ProjectGUID="{4B0C8744-5078-4F94-BB96-963B5F6AAAE5}"
+ RootNamespace="SpiceX"
+ Keyword="AtlProj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ DeleteExtensionsOnClean="*.obj;*.ilk;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.cab;$(TargetPath)"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="PreBuild.bat $(PlatformName) $(ConfigurationName)"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="sign the SpiceX.dll file"
+ CommandLine="Sign.bat $(OutDir) $(ConfigurationName) $(PlatformName)&#x0D;&#x0A;"
+ Outputs=".\$(ConfigurationName)\SpiceX.dll"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="1"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/SpiceX.tlb"
+ HeaderFileName="SpiceX.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="SpiceX_i.c"
+ ProxyFileName="SpiceX_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="false"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="2"
+ ModuleDefinitionFile=".\SpiceX.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ 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"
+ UseOfATL="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ DeleteExtensionsOnClean="*.obj;*.ilk;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.cab;$(TargetPath)"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="PreBuild.bat $(PlatformName) $(ConfigurationName)"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="sign the SpiceX.dll file"
+ CommandLine="Sign.bat $(OutDir) $(ConfigurationName) $(PlatformName)&#x0D;&#x0A;"
+ Outputs=".\$(ConfigurationName)\SpiceX.dll"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="3"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/SpiceX.tlb"
+ HeaderFileName="SpiceX.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="SpiceX_i.c"
+ ProxyFileName="SpiceX_p.c"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="false"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="2"
+ ModuleDefinitionFile=".\SpiceX.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ 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|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ DeleteExtensionsOnClean="*.obj;*.ilk;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.cab;$(TargetPath)"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="PreBuild.bat $(PlatformName) $(ConfigurationName)"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="sign the SpiceX.dll file"
+ CommandLine="Sign.bat $(OutDir) $(ConfigurationName) $(PlatformName)&#x0D;&#x0A;"
+ Outputs=".\$(ConfigurationName)\SpiceX.dll"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="1"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/SpiceX.tlb"
+ HeaderFileName="SpiceX.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="SpiceX_i.c"
+ ProxyFileName="SpiceX_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=".;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="false"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="1"
+ ModuleDefinitionFile=".\SpiceX.def"
+ GenerateDebugInformation="true"
+ GenerateMapFile="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ 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|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ DeleteExtensionsOnClean="*.obj;*.ilk;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.cab;$(TargetPath)"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="PreBuild.bat $(PlatformName) $(ConfigurationName)"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="sign the SpiceX.dll file"
+ CommandLine="Sign.bat $(OutDir) $(ConfigurationName) $(PlatformName)&#x0D;&#x0A;"
+ Outputs=".\$(ConfigurationName)\SpiceX.dll"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="3"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/SpiceX.tlb"
+ HeaderFileName="SpiceX.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="SpiceX_i.c"
+ ProxyFileName="SpiceX_p.c"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=".;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="false"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="1"
+ ModuleDefinitionFile=".\SpiceX.def"
+ GenerateDebugInformation="true"
+ GenerateMapFile="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ 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="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\debug.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\OSpiceX.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX.def"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX.idl"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <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=".\_IOSpiceXEvents_CP.h"
+ >
+ </File>
+ <File
+ RelativePath=".\debug.h"
+ >
+ </File>
+ <File
+ RelativePath=".\OSpiceX.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\security.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceXCommon.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdint.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=".\OSpiceX.bmp"
+ >
+ </File>
+ <File
+ RelativePath=".\OSpiceX.rgs.template"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX.rgs"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Generated Files"
+ SourceControlFiles="false"
+ >
+ <File
+ RelativePath=".\SpiceX.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX_i.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Install"
+ >
+ <File
+ RelativePath=".\SpiceX.inf.template"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Build"
+ >
+ <File
+ RelativePath=".\Sign.bat"
+ >
+ </File>
+ <File
+ RelativePath=".\PreBuild.bat"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX.ddf"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Test"
+ >
+ <File
+ RelativePath=".\OSpiceX_x64.htm"
+ DeploymentContent="true"
+ >
+ </File>
+ <File
+ RelativePath=".\OSpiceX_x86.htm"
+ DeploymentContent="true"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/SpiceXCommon.h b/SpiceXCommon.h
new file mode 100644
index 0000000..be9d0dd
--- /dev/null
+++ b/SpiceXCommon.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+
+#ifndef _H_SPICE_X_COMMON
+#define _H_SPICE_X_COMMON
+
+#define RED_CLIENT_FILE_NAME L"spicec.exe"
+#define RED_CLIENT_PIPE_NAME TEXT("\\\\.\\pipe\\SpiceController-%lu")
+#define RED_CLIENT_PIPE_NAME_MAX_LEN 256
+#define RED_CLIENT_DEFAULT_TITLE L"Spice Client"
+#define RED_CLIENT_MAX_TITLE_SIZE MAX_PATH
+#define RED_CLIENT_MAX_MENU_SIZE 4096
+#define RED_CLIENT_MAX_USB_FILTER 2048
+#define RED_MAX_PASSWORD_LENGTH 60
+
+#define FACILITY_SPICEX 50
+#define FACILITY_CREATE_RED_PROCESS 51
+#define FACILITY_STRING_OPERATION 52
+#define FACILITY_CREATE_RED_EVENT 53
+#define FACILITY_CREATE_RED_PIPE 54
+#define FACILITY_PIPE_OPERATION 55
+#define FACILITY_CREATE_AUDIO_WRAPPER_PROCCESS 56
+
+//
+// MessageId: SPICEX_ERROR_CLIENT_PROCESS_NOT_CONNECTED
+//
+// MessageText:
+//
+// Client process not connected.
+// 0x80320001
+#define SPICEX_ERROR_CLIENT_PROCESS_NOT_CONNECTED MAKE_HRESULT(1, FACILITY_SPICEX, 1);
+
+//
+// MessageId: SPICEX_ERROR_CLIENT_PROCESS_ALREADY_CONNECTED
+//
+// MessageText:
+//
+// Client process not connected.
+// 0x80320001
+#define SPICEX_ERROR_CLIENT_PROCESS_ALREADY_CONNECTED MAKE_HRESULT(1, FACILITY_SPICEX, 2);
+
+#endif // _H_SPICE_X_COMMON
diff --git a/SpiceXPS.vcproj b/SpiceXPS.vcproj
new file mode 100644
index 0000000..f80d319
--- /dev/null
+++ b/SpiceXPS.vcproj
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="windows-1255"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="SpiceXPS"
+ ProjectGUID="{EB4C4F6A-3E87-48B6-8A60-86F9AC7494CF}"
+ Keyword="AtlPSProj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)PS"
+ IntermediateDirectory="$(ConfigurationName)PS"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ Description="Checking for required files"
+ CommandLine="if exist dlldata.c goto :END&#x0D;&#x0A;echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.&#x0D;&#x0A;Exit 1&#x0D;&#x0A;:END&#x0D;&#x0A;"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;_WIN32_WINNT=0x0500;REGISTER_PROXY_DLL;_DEBUG"
+ RuntimeLibrary="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="true"
+ AdditionalDependencies="kernel32.lib rpcndr.lib rpcns4.lib rpcrt4.lib oleaut32.lib uuid.lib"
+ ModuleDefinitionFile="SpiceXPS.def"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ />
+ <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="$(ConfigurationName)PS"
+ IntermediateDirectory="$(ConfigurationName)PS"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ Description="Checking for required files"
+ CommandLine="if exist dlldata.c goto :END&#x0D;&#x0A;echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.&#x0D;&#x0A;Exit 1&#x0D;&#x0A;:END&#x0D;&#x0A;"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions="WIN32;_WIN32_WINNT=0x0500;REGISTER_PROXY_DLL;NDEBUG"
+ RuntimeLibrary="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="true"
+ AdditionalDependencies="kernel32.lib rpcndr.lib rpcns4.lib rpcrt4.lib oleaut32.lib uuid.lib"
+ ModuleDefinitionFile="SpiceXPS.def"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ />
+ <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>
+ <Filter
+ Name="Generated Files"
+ SourceControlFiles="false"
+ >
+ <File
+ RelativePath=".\dlldata.c"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX_i.c"
+ >
+ </File>
+ <File
+ RelativePath=".\SpiceX_p.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\SpiceXps.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/SpiceXps.def b/SpiceXps.def
new file mode 100644
index 0000000..ff1978b
--- /dev/null
+++ b/SpiceXps.def
@@ -0,0 +1,9 @@
+
+LIBRARY "SpiceXPS"
+
+EXPORTS
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
+ GetProxyDllInfo PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/_IOSpiceXEvents_CP.h b/_IOSpiceXEvents_CP.h
new file mode 100644
index 0000000..7e3dd9c
--- /dev/null
+++ b/_IOSpiceXEvents_CP.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+#pragma once
+
+template<class T>
+class CProxy_IOSpiceXEvents :
+ public IConnectionPointImpl<T, &__uuidof(_IOSpiceXEvents)>
+{
+public:
+
+ HRESULT Fire_OnMenuItemSelected(ULONG ulItemID)
+ {
+ HRESULT hr = S_OK;
+ T * pThis = static_cast<T *>(this);
+ int cConnections = m_vec.GetSize();
+
+ for (int iConnection = 0; iConnection < cConnections; iConnection++)
+ {
+ pThis->Lock();
+ CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
+ pThis->Unlock();
+
+ IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
+
+ if (pConnection)
+ {
+ CComVariant avarParams[1];
+ avarParams[0] = ulItemID;
+ avarParams[0].vt = VT_I4;
+ CComVariant varResult;
+
+ DISPPARAMS params = { avarParams, NULL, 1, 0 };
+ hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
+ }
+ }
+ return hr;
+ }
+
+ HRESULT Fire_OnDisconnected( LONG ErrCode)
+ {
+ HRESULT hr = S_OK;
+ T * pThis = static_cast<T *>(this);
+ int cConnections = m_vec.GetSize();
+
+ for (int iConnection = 0; iConnection < cConnections; iConnection++)
+ {
+ pThis->Lock();
+ CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
+ pThis->Unlock();
+
+ IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
+
+ if (pConnection)
+ {
+ CComVariant avarParams[1];
+ avarParams[0] = ErrCode;
+ avarParams[0].vt = VT_I4;
+ CComVariant varResult;
+
+ DISPPARAMS params = { avarParams, NULL, 1, 0 };
+ hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
+ }
+ }
+ return hr;
+ }
+};
+
diff --git a/debug.cpp b/debug.cpp
new file mode 100644
index 0000000..7bff2a8
--- /dev/null
+++ b/debug.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+#include "stdafx.h"
+
+#define SPICEX_DEBUG_LEVEL "SPICEX_DEBUG_LEVEL"
+
+static FILE *log_file = NULL;
+static unsigned int log_level = LOG_DEBUG;
+
+void spicex_log_cleanup(void)
+{
+ if (log_file) {
+ LOG_INFO("done");
+ fclose(log_file);
+ log_file = NULL;
+ }
+}
+
+template<class T>
+class AutoArray {
+public:
+ AutoArray() : _array (NULL) {}
+ AutoArray(T* array) : _array (array) {}
+ ~AutoArray() { delete[] _array;}
+
+ void set(T* array) { delete[] _array; _array = array;}
+ T* get() {return _array;}
+ T* release() {T* tmp = _array; _array = NULL; return tmp; }
+ T& operator [] (int i) {return _array[i];}
+
+private:
+ T* _array;
+};
+
+void string_vprintf(std::string& str, const char* format, va_list ap)
+{
+ int buf_size = 256;
+ for (;;) {
+ AutoArray<char> buf(new char[buf_size]);
+ int r = vsnprintf_s(buf.get(), buf_size, buf_size - 1, format, ap);
+ if (r != -1) {
+ str = buf.get();
+ return;
+ }
+ buf_size *= 2;
+ }
+}
+
+const char *type_to_str(int type)
+{
+ switch (type) {
+ case LOG_INFO: return "INFO";
+ case LOG_WARN: return "WARN";
+ case LOG_ERROR: return "ERROR";
+ case LOG_FATAL: return "FATAL";
+ }
+ if (type >= LOG_DEBUG) {
+ return "DEBUG";
+ }
+ return "UNKNOWN";
+}
+
+
+void spicex_log(unsigned int type, const char *function, const char *format, ...)
+{
+ std::string formated_message;
+ va_list ap;
+ std::string function_name_copy = std::string(function);
+
+ if (type > log_level) {
+ return;
+ }
+
+ ASSERT(type <= LOG_FATAL);
+
+ va_start(ap, format);
+ string_vprintf(formated_message, format, ap);
+ va_end(ap);
+
+ if (type <= log_level && log_file != NULL) {
+ fprintf(log_file, "%ld %s [%lu:%lu] %s: %s\n", (long)time(NULL), type_to_str(type),
+ GetCurrentProcessId(), GetCurrentThreadId(),
+ function_name_copy.c_str(), formated_message.c_str());
+ fflush(log_file);
+ }
+}
+
+char *safe_getenv(const char *name)
+{
+ char *value;
+ size_t number_of_elements;
+
+ _dupenv_s(&value, &number_of_elements, name);
+ return value;
+}
+
+void spicex_init_logger(void)
+{
+ std::string log_file_name;
+ char *p;
+ long int env_log_level;
+ char *temp = safe_getenv("TEMP");
+ char *log_level_str = safe_getenv(SPICEX_DEBUG_LEVEL);
+
+ log_level = LOG_INFO;
+ // VVV Windows specific, assumes %TEMP% is defined.
+ log_file_name = std::string(temp) + "\\spicex.log";
+
+ log_file = _fsopen(log_file_name.c_str(), "a", _SH_DENYNO);
+ if (log_file == NULL) {
+ fprintf(stderr, "Failed to open log file %s\n", log_file_name.c_str());
+ goto cleanup;
+ }
+
+ if (log_level_str == NULL) {
+ goto cleanup;
+ }
+
+ env_log_level = strtol(log_level_str, &p, 10);
+ if (p - log_level_str == 0) {
+ LOG_INFO("%s environment variable doesn't contain a number", SPICEX_DEBUG_LEVEL);
+ } else {
+ log_level = LOG_DEBUG + env_log_level;
+ }
+
+cleanup:
+ free(temp);
+ free(log_level_str);
+ if (log_file != NULL) {
+ LOG_INFO("started");
+ }
+}
diff --git a/debug.h b/debug.h
new file mode 100644
index 0000000..8c226fd
--- /dev/null
+++ b/debug.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+void spicex_log(unsigned int type, const char *function, const char *format, ...);
+void spicex_init_logger(void);
+void spicex_log_cleanup(void);
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+#define ON_PANIC() ::abort()
+
+#ifdef SPICEX_DEBUG
+
+#define ASSERTBREAK DebugBreak()
+
+#define ASSERT(x) if (!(x)) { \
+ printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \
+ ASSERTBREAK; \
+}
+
+#else
+
+#define ASSERT(cond)
+
+#endif
+
+enum {
+ LOG_FATAL = 1,
+ LOG_ERROR,
+ LOG_WARN,
+ LOG_INFO,
+ LOG_DEBUG,
+};
+
+#define LOG(type, format, ...) spicex_log(type, __FUNCTION__, format, ## __VA_ARGS__)
+
+#define LOG_INFO(format, ...) LOG(LOG_INFO, format, ## __VA_ARGS__)
+#define LOG_WARN(format, ...) LOG(LOG_WARN, format, ## __VA_ARGS__)
+#define LOG_ERROR(format, ...) LOG(LOG_ERROR, format, ## __VA_ARGS__)
+
+#define DBG(level, format, ...) \
+ LOG(LOG_DEBUG + level, format, ## __VA_ARGS__)
+
+
+
+#endif // __DEBUG_H__
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..697c151
--- /dev/null
+++ b/resource.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by SpiceX.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_SPICEX 101
+#define IDB_OSPICEX 102
+#define IDR_OSPICEX 103
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 104
+#endif
+#endif
diff --git a/security.h b/security.h
new file mode 100644
index 0000000..842765c
--- /dev/null
+++ b/security.h
@@ -0,0 +1,93 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_SECURITY
+#define _H_SECURITY
+
+#include <aclapi.h>
+
+//gets user-only-access security attributes. returns 0 on success, error code on failure.
+//user is responsible to LocalFree(dacl).
+static DWORD get_security_attributes(SECURITY_ATTRIBUTES* psa, SECURITY_DESCRIPTOR* psd, PACL* ppdacl)
+{
+ EXPLICIT_ACCESS ea;
+ TRUSTEE trst;
+ DWORD ret = 0;
+
+ ZeroMemory(psa, sizeof(*psa));
+ ZeroMemory(psd, sizeof(*psd));
+ psa->nLength = sizeof(*psa);
+ psa->bInheritHandle = false;
+ psa->lpSecurityDescriptor = psd;
+
+ ZeroMemory(&trst, sizeof(trst));
+ trst.pMultipleTrustee = NULL;
+ trst.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+ trst.TrusteeForm = TRUSTEE_IS_NAME;
+ trst.TrusteeType = TRUSTEE_IS_USER;
+ trst.ptstrName = L"CURRENT_USER";
+
+ ZeroMemory(&ea, sizeof(ea));
+ ea.grfAccessPermissions = GENERIC_WRITE | GENERIC_READ;
+ ea.grfAccessMode = SET_ACCESS;
+ ea.grfInheritance = NO_INHERITANCE;
+ ea.Trustee = trst;
+
+ ret = SetEntriesInAcl(1, &ea, NULL, ppdacl);
+ if (ret != ERROR_SUCCESS) {
+ return ret;
+ }
+ if (!ret && !InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) {
+ ret = GetLastError();
+ }
+ if (!ret && !SetSecurityDescriptorDacl(psd, TRUE, *ppdacl, FALSE)) {
+ ret = GetLastError();
+ }
+ return ret;
+}
+
+static int get_sid(HANDLE handle, PSID* ppsid, PSECURITY_DESCRIPTOR* ppsec_desc)
+{
+ DWORD ret = GetSecurityInfo(handle, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION,
+ ppsid, NULL, NULL, NULL, ppsec_desc);
+ if (ret != ERROR_SUCCESS) {
+ return ret;
+ }
+ if (!IsValidSid(*ppsid)) {
+ return -1;
+ }
+ return 0;
+}
+
+//checks whether the handle owner is the current user.
+static bool is_same_user(HANDLE handle)
+{
+ PSECURITY_DESCRIPTOR psec_desc_handle = NULL;
+ PSECURITY_DESCRIPTOR psec_desc_user = NULL;
+ PSID psid_handle;
+ PSID psid_user;
+ bool ret;
+
+ ret = !get_sid(handle, &psid_handle, &psec_desc_handle) &&
+ !get_sid(GetCurrentProcess(), &psid_user, &psec_desc_user) &&
+ EqualSid(psid_handle, psid_user);
+ LocalFree(psec_desc_handle);
+ LocalFree(psec_desc_user);
+ return ret;
+}
+
+#endif
diff --git a/stdafx.cpp b/stdafx.cpp
new file mode 100644
index 0000000..5e49eea
--- /dev/null
+++ b/stdafx.cpp
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+// stdafx.cpp : source file that includes just the standard includes
+// SpiceX.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/stdafx.h b/stdafx.h
new file mode 100644
index 0000000..7e7e3c9
--- /dev/null
+++ b/stdafx.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the GNU General Public License, version 2 or any
+ * later version. See the file COPYING in the top-level directory of
+ * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
+ */
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+// 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 WINVER // Allow use of features specific to Windows XP or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#define _ATL_APARTMENT_THREADED
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+
+#include <cstdio>
+#include <ctime>
+#include <string>
+#include <iostream>
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <strsafe.h>
+#include <windows.h>
+
+#include "debug.h"
+#include "resource.h"
+
+using namespace ATL; \ No newline at end of file
diff --git a/stdint.h b/stdint.h
new file mode 100644
index 0000000..45b133e
--- /dev/null
+++ b/stdint.h
@@ -0,0 +1,396 @@
+/* ISO C9x 7.18 Integer types <stdint.h>
+
+ * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
+
+ *
+
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+
+ *
+
+ * Contributor: Danny Smith <danny_r_smith_2001@yahoo.co.nz>
+
+ *
+
+ * This source code is offered for use in the public domain. You may
+
+ * use, modify or distribute it freely.
+
+ *
+
+ * This code is distributed in the hope that it will be useful but
+
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+
+ * DISCLAIMED. This includes but is not limited to warranties of
+
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ *
+
+ * Date: 2000-12-02
+
+ */
+
+
+
+
+
+#ifndef _STDINT_H
+
+#define _STDINT_H
+
+#define __need_wint_t
+
+#define __need_wchar_t
+
+#include <stddef.h>
+
+
+
+#ifdef _WIN32_WCE
+
+typedef _int64 int64_t;
+
+typedef unsigned _int64 uint64_t;
+
+#else
+
+typedef long long int64_t;
+
+typedef unsigned long long uint64_t;
+
+#endif /* _WIN32_WCE */
+
+
+
+/* 7.18.1.1 Exact-width integer types */
+
+typedef signed char int8_t;
+
+typedef unsigned char uint8_t;
+
+typedef short int16_t;
+
+typedef unsigned short uint16_t;
+
+typedef int int32_t;
+
+typedef unsigned uint32_t;
+
+
+
+/* 7.18.1.2 Minimum-width integer types */
+
+typedef signed char int_least8_t;
+
+typedef unsigned char uint_least8_t;
+
+typedef short int_least16_t;
+
+typedef unsigned short uint_least16_t;
+
+typedef int int_least32_t;
+
+typedef unsigned uint_least32_t;
+
+#ifndef _WIN32_WCE
+
+typedef long long int_least64_t;
+
+typedef unsigned long long uint_least64_t;
+
+#endif
+
+
+
+/* 7.18.1.3 Fastest minimum-width integer types
+
+ * Not actually guaranteed to be fastest for all purposes
+
+ * Here we use the exact-width types for 8 and 16-bit ints.
+
+ */
+
+typedef char int_fast8_t;
+
+typedef unsigned char uint_fast8_t;
+
+typedef short int_fast16_t;
+
+typedef unsigned short uint_fast16_t;
+
+typedef int int_fast32_t;
+
+typedef unsigned int uint_fast32_t;
+
+#ifndef _WIN32_WCE
+
+typedef long long int_fast64_t;
+
+typedef unsigned long long uint_fast64_t;
+
+#endif
+
+
+
+/* 7.18.1.4 Integer types capable of holding object pointers */
+
+#ifndef _WIN64
+
+typedef int intptr_t;
+
+typedef unsigned uintptr_t;
+
+#endif
+
+/* 7.18.1.5 Greatest-width integer types */
+
+#ifndef _WIN32_WCE
+
+typedef long long intmax_t;
+
+typedef unsigned long long uintmax_t;
+
+#endif
+
+
+
+/* 7.18.2 Limits of specified-width integer types */
+
+#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS)
+
+
+
+/* 7.18.2.1 Limits of exact-width integer types */
+
+#define INT8_MIN (-128)
+
+#define INT16_MIN (-32768)
+
+#define INT32_MIN (-2147483647 - 1)
+
+#define INT64_MIN (-9223372036854775807LL - 1)
+
+
+
+#define INT8_MAX 127
+
+#define INT16_MAX 32767
+
+#define INT32_MAX 2147483647
+
+#define INT64_MAX 9223372036854775807LL
+
+
+
+#define UINT8_MAX 0xff /* 255U */
+
+#define UINT16_MAX 0xffff /* 65535U */
+
+#define UINT32_MAX 0xffffffff /* 4294967295U */
+
+#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */
+
+
+
+/* 7.18.2.2 Limits of minimum-width integer types */
+
+#define INT_LEAST8_MIN INT8_MIN
+
+#define INT_LEAST16_MIN INT16_MIN
+
+#define INT_LEAST32_MIN INT32_MIN
+
+#define INT_LEAST64_MIN INT64_MIN
+
+
+
+#define INT_LEAST8_MAX INT8_MAX
+
+#define INT_LEAST16_MAX INT16_MAX
+
+#define INT_LEAST32_MAX INT32_MAX
+
+#define INT_LEAST64_MAX INT64_MAX
+
+
+
+#define UINT_LEAST8_MAX UINT8_MAX
+
+#define UINT_LEAST16_MAX UINT16_MAX
+
+#define UINT_LEAST32_MAX UINT32_MAX
+
+#define UINT_LEAST64_MAX UINT64_MAX
+
+
+
+/* 7.18.2.3 Limits of fastest minimum-width integer types */
+
+#define INT_FAST8_MIN INT8_MIN
+
+#define INT_FAST16_MIN INT16_MIN
+
+#define INT_FAST32_MIN INT32_MIN
+
+#define INT_FAST64_MIN INT64_MIN
+
+
+
+#define INT_FAST8_MAX INT8_MAX
+
+#define INT_FAST16_MAX INT16_MAX
+
+#define INT_FAST32_MAX INT32_MAX
+
+#define INT_FAST64_MAX INT64_MAX
+
+
+
+#define UINT_FAST8_MAX UINT8_MAX
+
+#define UINT_FAST16_MAX UINT16_MAX
+
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define UINT_FAST64_MAX UINT64_MAX
+
+
+
+/* 7.18.2.4 Limits of integer types capable of holding
+
+ object pointers */
+
+#define INTPTR_MIN INT32_MIN
+
+#define INTPTR_MAX INT32_MAX
+
+#define UINTPTR_MAX UINT32_MAX
+
+
+
+/* 7.18.2.5 Limits of greatest-width integer types */
+
+#define INTMAX_MIN INT64_MIN
+
+#define INTMAX_MAX INT64_MAX
+
+#define UINTMAX_MAX UINT64_MAX
+
+
+
+/* 7.18.3 Limits of other integer types */
+
+#define PTRDIFF_MIN INT32_MIN
+
+#define PTRDIFF_MAX INT32_MAX
+
+
+
+#define SIG_ATOMIC_MIN INT32_MIN
+
+#define SIG_ATOMIC_MAX INT32_MAX
+
+
+
+#define SIZE_MAX UINT32_MAX
+
+
+
+#ifndef WCHAR_MIN /* also in wchar.h */
+
+#define WCHAR_MIN 0
+
+#define WCHAR_MAX 0xffff /* UINT16_MAX */
+
+#endif
+
+
+
+/*
+
+ * wint_t is unsigned short for compatibility with MS runtime
+
+ */
+
+#define WINT_MIN 0
+
+#define WINT_MAX 0xffff /* UINT16_MAX */
+
+
+
+#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */
+
+
+
+
+
+/* 7.18.4 Macros for integer constants */
+
+#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS)
+
+
+
+/* 7.18.4.1 Macros for minimum-width integer constants
+
+
+
+ Accoding to Douglas Gwyn <gwyn@arl.mil>:
+
+ "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
+
+ 9899:1999 as initially published, the expansion was required
+
+ to be an integer constant of precisely matching type, which
+
+ is impossible to accomplish for the shorter types on most
+
+ platforms, because C99 provides no standard way to designate
+
+ an integer constant with width less than that of type int.
+
+ TC1 changed this to require just an integer constant
+
+ *expression* with *promoted* type."
+
+*/
+
+
+
+#define INT8_C(val) ((int8_t) + (val))
+
+#define UINT8_C(val) ((uint8_t) + (val##U))
+
+#define INT16_C(val) ((int16_t) + (val))
+
+#define UINT16_C(val) ((uint16_t) + (val##U))
+
+
+
+#define INT32_C(val) val##L
+
+#define UINT32_C(val) val##UL
+
+#define INT64_C(val) val##LL
+
+#define UINT64_C(val) val##ULL
+
+
+
+/* 7.18.4.2 Macros for greatest-width integer constants */
+
+#define INTMAX_C(val) INT64_C(val)
+
+#define UINTMAX_C(val) UINT64_C(val)
+
+
+
+#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */
+
+
+
+#endif
+
+
+
diff --git a/virt-viewer.inf b/virt-viewer.inf
new file mode 100644
index 0000000..50b5bdf
--- /dev/null
+++ b/virt-viewer.inf
@@ -0,0 +1,12 @@
+[version]
+; version signature (same for both NT and Win95) do not remove
+signature="$CHICAGO$"
+AdvancedINF=2.0
+
+[Deployment]
+InstallScope=user|machine
+
+[Setup Hooks]
+hook1=hook1
+[hook1]
+run="%EXTRACT_DIR%\virt-viewer-VIRT_VIEWER_VERSION.exe" /S