283 lines
8.2 KiB
C++
283 lines
8.2 KiB
C++
|
/*
|
||
|
* Copyright (c) 2005 Alexander Gottwald
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
* DEALINGS IN THE SOFTWARE.
|
||
|
*
|
||
|
* Except as contained in this notice, the name(s) of the above copyright
|
||
|
* holders shall not be used in advertising or otherwise to promote the sale,
|
||
|
* use or other dealings in this Software without prior written authorization.
|
||
|
*/
|
||
|
#include "config.h"
|
||
|
#include "window/util.h"
|
||
|
#include <msxml2.h>
|
||
|
#include <stdexcept>
|
||
|
|
||
|
const CLSID CLSID_DOMDocument40 = {0x88d969c0,0xf192,0x11d4,0xa6,0x5f,0x00,0x40,0x96,0x32,0x51,0xe5};
|
||
|
const CLSID CLSID_DOMDocument30 = {0xf5078f32,0xc551,0x11d3,0x89,0xb9,0x00,0x00,0xf8,0x1f,0xe2,0x21};
|
||
|
const IID IID_IXMLDOMDocument2 = {0x2933BF95,0x7B36,0x11d2,0xB2,0x0E,0x00,0xC0,0x4F,0x98,0x3E,0x60};
|
||
|
|
||
|
#define HRCALL(x, msg) if (FAILED(x)) { throw std::runtime_error("OLE Error:" msg " failed"); };
|
||
|
|
||
|
char *wcconvert(const wchar_t *wstr)
|
||
|
{
|
||
|
int chars = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||
|
if (chars == 0)
|
||
|
throw win32_error("WideCharToMultiByte");
|
||
|
char *mbstr = new char[chars];
|
||
|
chars = WideCharToMultiByte(CP_ACP, 0, wstr, -1, mbstr, chars, NULL, NULL);
|
||
|
if (chars == 0)
|
||
|
throw win32_error("WideCharToMultiByte");
|
||
|
return mbstr;
|
||
|
}
|
||
|
|
||
|
wchar_t *mbconvert(const char *mbstr)
|
||
|
{
|
||
|
int chars = MultiByteToWideChar(CP_ACP, 0, mbstr, -1, NULL, 0);
|
||
|
if (chars == 0)
|
||
|
throw win32_error("MultiByteToWideChar");
|
||
|
wchar_t *wstr = new wchar_t[chars];
|
||
|
chars = MultiByteToWideChar(CP_ACP, 0, mbstr, -1, wstr, chars);
|
||
|
if (chars == 0)
|
||
|
throw win32_error("MultiByteToWideChar");
|
||
|
return wstr;
|
||
|
}
|
||
|
|
||
|
VARIANT VariantString(const char *filename)
|
||
|
{
|
||
|
|
||
|
wchar_t *str = mbconvert(filename);
|
||
|
|
||
|
VARIANT var;
|
||
|
VariantInit(&var);
|
||
|
V_BSTR(&var) = SysAllocString(str);
|
||
|
V_VT(&var) = VT_BSTR;
|
||
|
|
||
|
delete [] str;
|
||
|
return var;
|
||
|
}
|
||
|
|
||
|
VARIANT VariantString(const wchar_t *str)
|
||
|
{
|
||
|
VARIANT var;
|
||
|
VariantInit(&var);
|
||
|
V_BSTR(&var) = SysAllocString(str);
|
||
|
V_VT(&var) = VT_BSTR;
|
||
|
return var;
|
||
|
}
|
||
|
|
||
|
IXMLDOMDocument2 *CreateDocument()
|
||
|
{
|
||
|
IXMLDOMDocument2 *doc = NULL;
|
||
|
|
||
|
CoInitialize(NULL);
|
||
|
|
||
|
HRCALL(CoCreateInstance(CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER,
|
||
|
IID_IXMLDOMDocument2, (void**)&doc), "CoCreateInstance");
|
||
|
|
||
|
try {
|
||
|
HRCALL(doc->put_async(VARIANT_FALSE), "put_async");
|
||
|
HRCALL(doc->put_validateOnParse(VARIANT_FALSE), "put_validateOnParse");
|
||
|
HRCALL(doc->put_resolveExternals(VARIANT_FALSE), "put_resolveExternals");
|
||
|
|
||
|
IXMLDOMProcessingInstruction *pi = NULL;
|
||
|
IXMLDOMElement *root = NULL;
|
||
|
BSTR xml = SysAllocString(L"xml");
|
||
|
BSTR ver = SysAllocString(L"version='1.0'");
|
||
|
HRCALL(doc->createProcessingInstruction(xml,ver, &pi),
|
||
|
"createProcessingInstruction");
|
||
|
HRCALL(doc->appendChild(pi, NULL),
|
||
|
"appendChild");
|
||
|
pi->Release();
|
||
|
SysFreeString(xml);
|
||
|
SysFreeString(ver);
|
||
|
|
||
|
BSTR elemname = SysAllocString(L"XLaunch");
|
||
|
HRCALL(doc->createElement(elemname, &root), "createElement");
|
||
|
HRCALL(doc->appendChild(root, NULL), "appendChild");
|
||
|
SysFreeString(elemname);
|
||
|
} catch (...)
|
||
|
{
|
||
|
doc->Release();
|
||
|
throw;
|
||
|
}
|
||
|
return doc;
|
||
|
}
|
||
|
|
||
|
void setAttribute(IXMLDOMElement *elem, const wchar_t *name, const wchar_t *value)
|
||
|
{
|
||
|
BSTR str = SysAllocString(name);
|
||
|
VARIANT var = VariantString(value);
|
||
|
HRCALL(elem->setAttribute(str, var), "setAttribute");
|
||
|
VariantClear(&var);
|
||
|
SysFreeString(str);
|
||
|
}
|
||
|
|
||
|
void setAttribute(IXMLDOMElement *elem, const wchar_t *name, const char *value)
|
||
|
{
|
||
|
wchar_t *wstr = mbconvert(value);
|
||
|
setAttribute(elem, name, wstr);
|
||
|
delete [] wstr;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void CConfig::Save(const char *filename)
|
||
|
{
|
||
|
IXMLDOMDocument2 *doc = CreateDocument();
|
||
|
IXMLDOMElement *root = NULL;
|
||
|
|
||
|
HRCALL(doc->get_documentElement(&root), "get_documentElement");
|
||
|
|
||
|
switch (window)
|
||
|
{
|
||
|
case MultiWindow:
|
||
|
setAttribute(root, L"WindowMode", L"MultiWindow");
|
||
|
break;
|
||
|
case Fullscreen:
|
||
|
setAttribute(root, L"WindowMode", L"Fullscreen");
|
||
|
break;
|
||
|
default:
|
||
|
case Windowed:
|
||
|
setAttribute(root, L"WindowMode", L"Windowed");
|
||
|
break;
|
||
|
case Nodecoration:
|
||
|
setAttribute(root, L"WindowMode", L"Nodecoration");
|
||
|
break;
|
||
|
}
|
||
|
switch (client)
|
||
|
{
|
||
|
default:
|
||
|
case NoClient:
|
||
|
setAttribute(root, L"ClientMode", L"NoClient");
|
||
|
break;
|
||
|
case StartProgram:
|
||
|
setAttribute(root, L"ClientMode", L"StartProgram");
|
||
|
break;
|
||
|
case XDMCP:
|
||
|
setAttribute(root, L"ClientMode", L"XDMCP");
|
||
|
break;
|
||
|
}
|
||
|
setAttribute(root, L"LocalClient", local?L"True":L"False");
|
||
|
setAttribute(root, L"Display", display.c_str());
|
||
|
setAttribute(root, L"Program", program.c_str());
|
||
|
setAttribute(root, L"RemoteProtocol", protocol.c_str());
|
||
|
setAttribute(root, L"RemoteHost", host.c_str());
|
||
|
setAttribute(root, L"RemoteUser", user.c_str());
|
||
|
setAttribute(root, L"XDMCPHost", xdmcp_host.c_str());
|
||
|
setAttribute(root, L"XDMCPBroadcast", broadcast?L"True":L"False");
|
||
|
setAttribute(root, L"XDMCPIndirect", indirect?L"True":L"False");
|
||
|
setAttribute(root, L"Clipboard", clipboard?L"True":L"False");
|
||
|
setAttribute(root, L"ExtraParams", extra_params.c_str());
|
||
|
|
||
|
VARIANT var = VariantString(filename);
|
||
|
HRCALL(doc->save(var), "save");
|
||
|
VariantClear(&var);
|
||
|
|
||
|
|
||
|
root->Release();
|
||
|
doc->Release();
|
||
|
}
|
||
|
|
||
|
BOOL getAttribute(IXMLDOMElement *elem, const wchar_t *name, std::string &ret)
|
||
|
{
|
||
|
VARIANT var;
|
||
|
HRCALL(elem->getAttribute((OLECHAR*)name, &var), "getAttribute");
|
||
|
if (V_VT(&var) != VT_NULL && V_VT(&var) == VT_BSTR)
|
||
|
{
|
||
|
char *str = wcconvert(V_BSTR(&var));
|
||
|
ret = str;
|
||
|
delete [] str;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
BOOL getAttributeBool(IXMLDOMElement *elem, const wchar_t *name, bool &ret)
|
||
|
{
|
||
|
std::string str;
|
||
|
if (getAttribute(elem, name, str))
|
||
|
{
|
||
|
if (str == "True")
|
||
|
ret = true;
|
||
|
else
|
||
|
ret = false;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CConfig::Load(const char *filename)
|
||
|
{
|
||
|
IXMLDOMDocument2 *doc = CreateDocument();
|
||
|
IXMLDOMElement *root = NULL;
|
||
|
|
||
|
VARIANT var = VariantString(filename);
|
||
|
VARIANT_BOOL status;
|
||
|
HRCALL(doc->load(var, &status), "load");
|
||
|
VariantClear(&var);
|
||
|
|
||
|
if (status == VARIANT_FALSE)
|
||
|
{
|
||
|
doc->Release();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
HRCALL(doc->get_documentElement(&root), "get_documentElement");
|
||
|
|
||
|
std::string windowMode;
|
||
|
std::string clientMode;
|
||
|
|
||
|
if (getAttribute(root, L"WindowMode", windowMode))
|
||
|
{
|
||
|
if (windowMode == "MultiWindow")
|
||
|
window = MultiWindow;
|
||
|
else if (windowMode == "Fullscreen")
|
||
|
window = Fullscreen;
|
||
|
else if (windowMode == "Windowed")
|
||
|
window = Windowed;
|
||
|
else if (windowMode == "Nodecoration")
|
||
|
window = Nodecoration;
|
||
|
}
|
||
|
if (getAttribute(root, L"ClientMode", clientMode))
|
||
|
{
|
||
|
if (clientMode == "NoClient")
|
||
|
client = NoClient;
|
||
|
else if (clientMode == "StartProgram")
|
||
|
client = StartProgram;
|
||
|
else if (clientMode == "XDMCP")
|
||
|
client = XDMCP;
|
||
|
}
|
||
|
|
||
|
getAttributeBool(root, L"LocalClient", local);
|
||
|
getAttribute(root, L"Display", display);
|
||
|
getAttribute(root, L"Program", program);
|
||
|
getAttribute(root, L"RemoteProtocol", protocol);
|
||
|
getAttribute(root, L"RemoteHost", host);
|
||
|
getAttribute(root, L"RemoteUser", user);
|
||
|
getAttribute(root, L"XDMCPHost", xdmcp_host);
|
||
|
getAttributeBool(root, L"XDMCPBroadcast", broadcast);
|
||
|
getAttributeBool(root, L"XDMCPIndirect", indirect);
|
||
|
getAttributeBool(root, L"Clipboard", clipboard);
|
||
|
getAttribute(root, L"ExtraParams", extra_params);
|
||
|
|
||
|
|
||
|
doc->Release();
|
||
|
}
|
||
|
|