diff --git a/reactos/baseaddress.rbuild b/reactos/baseaddress.rbuild
index 04965b3a154..18f2361ccfa 100644
--- a/reactos/baseaddress.rbuild
+++ b/reactos/baseaddress.rbuild
@@ -14,6 +14,7 @@
+
@@ -38,6 +39,7 @@
+
@@ -147,6 +149,7 @@
+
diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff
index 726c508bd76..8984bd9bc4c 100644
--- a/reactos/boot/bootdata/packages/reactos.dff
+++ b/reactos/boot/bootdata/packages/reactos.dff
@@ -281,11 +281,13 @@ dll\win32\imagehlp\imagehlp.dll 1
dll\win32\imm32\imm32.dll 1
dll\win32\inetcomm\inetcomm.dll 1
dll\win32\inetmib1\inetmib1.dll 1
+dll\win32\inseng\inseng.dll 1
dll\win32\iphlpapi\iphlpapi.dll 1
dll\win32\itss\itss.dll 1
dll\win32\jscript\jscript.dll 1
dll\win32\kernel32\kernel32.dll 1
dll\win32\loadperf\loadperf.dll 1
+dll\win32\localspl\localspl.dll 1
dll\win32\localui\localui.dll 1
dll\win32\lsasrv\lsasrv.dll 1
dll\win32\lz32\lz32.dll 1
@@ -406,6 +408,7 @@ dll\win32\wshirda\wshirda.dll 1
dll\win32\wshtcpip\wshtcpip.dll 1
dll\win32\wsock32\wsock32.dll 1
dll\win32\wtsapi32\wtsapi32.dll 1
+dll\win32\wuapi\wuapi.dll 1
dll\win32\winmm\midimap\midimap.dll 1
dll\win32\winmm\wavemap\msacm32.drv 1 optional
diff --git a/reactos/dll/win32/inseng/inseng.rbuild b/reactos/dll/win32/inseng/inseng.rbuild
new file mode 100644
index 00000000000..cfcef820d94
--- /dev/null
+++ b/reactos/dll/win32/inseng/inseng.rbuild
@@ -0,0 +1,16 @@
+
+
+
+ .
+ include/reactos/wine
+
+ 0x600
+ inseng_main.c
+ regsvr.c
+ wine
+ uuid
+ ole32
+ advapi32
+ kernel32
+ ntdll
+
diff --git a/reactos/dll/win32/inseng/inseng.spec b/reactos/dll/win32/inseng/inseng.spec
new file mode 100644
index 00000000000..b3a2ce2f7fb
--- /dev/null
+++ b/reactos/dll/win32/inseng/inseng.spec
@@ -0,0 +1,12 @@
+@ stub CheckForVersionConflict
+@ stub CheckTrust
+@ stdcall CheckTrustEx(ptr ptr ptr ptr ptr)
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stub DllInstall
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
+@ stub DownloadFile
+@ stub GetICifFileFromFile
+@ stub GetICifRWFileFromFile
+@ stub PurgeDownloadDirectory
diff --git a/reactos/dll/win32/inseng/inseng_main.c b/reactos/dll/win32/inseng/inseng_main.c
new file mode 100644
index 00000000000..8ceb252b511
--- /dev/null
+++ b/reactos/dll/win32/inseng/inseng_main.c
@@ -0,0 +1,72 @@
+/*
+ * INSENG Implementation
+ *
+ * Copyright 2006 Mike McCormack
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "initguid.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(inseng);
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+ switch(fdwReason)
+ {
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hInstDLL);
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+/***********************************************************************
+ * DllGetClassObject (INSENG.@)
+ */
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
+{
+ FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+ FIXME("\n");
+ return S_FALSE;
+}
+
+BOOL WINAPI CheckTrustEx( LPVOID a, LPVOID b, LPVOID c, LPVOID d, LPVOID e )
+{
+ FIXME("%p %p %p %p %p\n", a, b, c, d, e );
+ return TRUE;
+}
diff --git a/reactos/dll/win32/inseng/regsvr.c b/reactos/dll/win32/inseng/regsvr.c
new file mode 100644
index 00000000000..daa6a66da9b
--- /dev/null
+++ b/reactos/dll/win32/inseng/regsvr.c
@@ -0,0 +1,501 @@
+/*
+ * self-registerable dll functions for inseng.dll
+ *
+ * Copyright (C) 2003 John K. Hohm
+ * Copyright (C) 2004 Steven Edwards for ReactOS
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#include "objbase.h"
+#include "initguid.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(inseng);
+
+DEFINE_GUID(CLSID_ActiveSetupEng, 0x6e449686,0xc509,0x11cf,0xaa,0xfa,0x00,0xaa,0x00,0xb6,0x01,0x5c );
+DEFINE_GUID(CLSID_DLManager, 0xBFC880F1,0x7484,0x11D0,0x83,0x09,0x00,0xAA,0x00,0xB6,0x01,0x5C);
+
+/*
+ * Near the bottom of this file are the exported DllRegisterServer and
+ * DllUnregisterServer, which make all this worthwhile.
+ */
+
+/***********************************************************************
+ * interface for self-registering
+ */
+struct regsvr_interface
+{
+ IID const *iid; /* NULL for end of list */
+ LPCSTR name; /* can be NULL to omit */
+ IID const *base_iid; /* can be NULL to omit */
+ int num_methods; /* can be <0 to omit */
+ CLSID const *ps_clsid; /* can be NULL to omit */
+ CLSID const *ps_clsid32; /* can be NULL to omit */
+};
+
+static HRESULT register_interfaces(struct regsvr_interface const *list);
+static HRESULT unregister_interfaces(struct regsvr_interface const *list);
+
+struct regsvr_coclass
+{
+ CLSID const *clsid; /* NULL for end of list */
+ LPCSTR name; /* can be NULL to omit */
+ LPCSTR ips; /* can be NULL to omit */
+ LPCSTR ips32; /* can be NULL to omit */
+ LPCSTR ips32_tmodel; /* can be NULL to omit */
+ LPCSTR progid; /* can be NULL to omit */
+ LPCSTR viprogid; /* can be NULL to omit */
+ LPCSTR progid_extra; /* can be NULL to omit */
+};
+
+static HRESULT register_coclasses(struct regsvr_coclass const *list);
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
+
+/***********************************************************************
+ * static string constants
+ */
+static WCHAR const interface_keyname[10] = {
+ 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
+static WCHAR const base_ifa_keyname[14] = {
+ 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
+ 'e', 0 };
+static WCHAR const num_methods_keyname[11] = {
+ 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
+static WCHAR const ps_clsid_keyname[15] = {
+ 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
+ 'i', 'd', 0 };
+static WCHAR const ps_clsid32_keyname[17] = {
+ 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
+ 'i', 'd', '3', '2', 0 };
+static WCHAR const clsid_keyname[6] = {
+ 'C', 'L', 'S', 'I', 'D', 0 };
+static WCHAR const curver_keyname[7] = {
+ 'C', 'u', 'r', 'V', 'e', 'r', 0 };
+static WCHAR const ips_keyname[13] = {
+ 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+ 0 };
+static WCHAR const ips32_keyname[15] = {
+ 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+ '3', '2', 0 };
+static WCHAR const progid_keyname[7] = {
+ 'P', 'r', 'o', 'g', 'I', 'D', 0 };
+static WCHAR const viprogid_keyname[25] = {
+ 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
+ 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
+ 0 };
+static char const tmodel_valuename[] = "ThreadingModel";
+
+/***********************************************************************
+ * static helper functions
+ */
+static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
+static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
+ WCHAR const *value);
+static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
+ char const *value);
+static LONG register_progid(WCHAR const *clsid,
+ char const *progid, char const *curver_progid,
+ char const *name, char const *extra);
+
+/***********************************************************************
+ * register_interfaces
+ */
+static HRESULT register_interfaces(struct regsvr_interface const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY interface_key;
+
+ res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->iid; ++list) {
+ WCHAR buf[39];
+ HKEY iid_key;
+
+ StringFromGUID2(list->iid, buf, 39);
+ res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_interface_key;
+
+ if (list->name) {
+ res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)(list->name),
+ strlen(list->name) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (list->base_iid) {
+ res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (0 <= list->num_methods) {
+ static WCHAR const fmt[3] = { '%', 'd', 0 };
+ HKEY key;
+
+ res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+
+ sprintfW(buf, fmt, list->num_methods);
+ res = RegSetValueExW(key, NULL, 0, REG_SZ,
+ (CONST BYTE*)buf,
+ (lstrlenW(buf) + 1) * sizeof(WCHAR));
+ RegCloseKey(key);
+
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (list->ps_clsid) {
+ res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (list->ps_clsid32) {
+ res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ error_close_iid_key:
+ RegCloseKey(iid_key);
+ }
+
+error_close_interface_key:
+ RegCloseKey(interface_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * unregister_interfaces
+ */
+static HRESULT unregister_interfaces(struct regsvr_interface const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY interface_key;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
+ KEY_READ | KEY_WRITE, &interface_key);
+ if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->iid; ++list) {
+ WCHAR buf[39];
+
+ StringFromGUID2(list->iid, buf, 39);
+ res = RegDeleteTreeW(interface_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ }
+
+ RegCloseKey(interface_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * register_coclasses
+ */
+static HRESULT register_coclasses(struct regsvr_coclass const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+
+ res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ WCHAR buf[39];
+ HKEY clsid_key;
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ if (list->name) {
+ res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)(list->name),
+ strlen(list->name) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->ips) {
+ res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->ips32) {
+ HKEY ips32_key;
+
+ res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL,
+ &ips32_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)list->ips32,
+ lstrlenA(list->ips32) + 1);
+ if (res == ERROR_SUCCESS && list->ips32_tmodel)
+ res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
+ (CONST BYTE*)list->ips32_tmodel,
+ strlen(list->ips32_tmodel) + 1);
+ RegCloseKey(ips32_key);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->progid) {
+ res = register_key_defvalueA(clsid_key, progid_keyname,
+ list->progid);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = register_progid(buf, list->progid, NULL,
+ list->name, list->progid_extra);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->viprogid) {
+ res = register_key_defvalueA(clsid_key, viprogid_keyname,
+ list->viprogid);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = register_progid(buf, list->viprogid, list->progid,
+ list->name, list->progid_extra);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ error_close_clsid_key:
+ RegCloseKey(clsid_key);
+ }
+
+error_close_coclass_key:
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * unregister_coclasses
+ */
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
+ KEY_READ | KEY_WRITE, &coclass_key);
+ if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ WCHAR buf[39];
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegDeleteTreeW(coclass_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ if (list->progid) {
+ res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+
+ if (list->viprogid) {
+ res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+ }
+
+error_close_coclass_key:
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * regsvr_key_guid
+ */
+static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
+{
+ WCHAR buf[39];
+
+ StringFromGUID2(guid, buf, 39);
+ return register_key_defvalueW(base, name, buf);
+}
+
+/***********************************************************************
+ * regsvr_key_defvalueW
+ */
+static LONG register_key_defvalueW(
+ HKEY base,
+ WCHAR const *name,
+ WCHAR const *value)
+{
+ LONG res;
+ HKEY key;
+
+ res = RegCreateKeyExW(base, name, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+ res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+ (lstrlenW(value) + 1) * sizeof(WCHAR));
+ RegCloseKey(key);
+ return res;
+}
+
+/***********************************************************************
+ * regsvr_key_defvalueA
+ */
+static LONG register_key_defvalueA(
+ HKEY base,
+ WCHAR const *name,
+ char const *value)
+{
+ LONG res;
+ HKEY key;
+
+ res = RegCreateKeyExW(base, name, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+ res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+ lstrlenA(value) + 1);
+ RegCloseKey(key);
+ return res;
+}
+
+/***********************************************************************
+ * regsvr_progid
+ */
+static LONG register_progid(
+ WCHAR const *clsid,
+ char const *progid,
+ char const *curver_progid,
+ char const *name,
+ char const *extra)
+{
+ LONG res;
+ HKEY progid_key;
+
+ res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
+ NULL, 0, KEY_READ | KEY_WRITE, NULL,
+ &progid_key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+
+ if (name) {
+ res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)name, strlen(name) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_progid_key;
+ }
+
+ if (clsid) {
+ res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
+ if (res != ERROR_SUCCESS) goto error_close_progid_key;
+ }
+
+ if (curver_progid) {
+ res = register_key_defvalueA(progid_key, curver_keyname,
+ curver_progid);
+ if (res != ERROR_SUCCESS) goto error_close_progid_key;
+ }
+
+ if (extra) {
+ HKEY extra_key;
+
+ res = RegCreateKeyExA(progid_key, extra, 0,
+ NULL, 0, KEY_READ | KEY_WRITE, NULL,
+ &extra_key, NULL);
+ if (res == ERROR_SUCCESS)
+ RegCloseKey(extra_key);
+ }
+
+error_close_progid_key:
+ RegCloseKey(progid_key);
+ return res;
+}
+
+/***********************************************************************
+ * coclass list
+ */
+static struct regsvr_coclass const coclass_list[] = {
+ {
+ &CLSID_ActiveSetupEng,
+ "Microsoft Active Setup Engine",
+ NULL,
+ "inseng.dll",
+ "Apartment"
+ },
+ {
+ &CLSID_DLManager,
+ "Download Site Manager",
+ NULL,
+ "inseng.dll",
+ "Apartment"
+ },
+ { NULL } /* list terminator */
+};
+
+/***********************************************************************
+ * interface list
+ */
+
+static struct regsvr_interface const interface_list[] = {
+ { NULL } /* list terminator */
+};
+
+/***********************************************************************
+ * DllRegisterServer (INSENG.@)
+ */
+HRESULT WINAPI DllRegisterServer(void)
+{
+ HRESULT hr;
+
+ TRACE("\n");
+
+ hr = register_coclasses(coclass_list);
+ if (SUCCEEDED(hr))
+ hr = register_interfaces(interface_list);
+ return hr;
+}
+
+/***********************************************************************
+ * DllUnregisterServer (INSENG.@)
+ */
+HRESULT WINAPI DllUnregisterServer(void)
+{
+ HRESULT hr;
+
+ TRACE("\n");
+
+ hr = unregister_coclasses(coclass_list);
+ if (SUCCEEDED(hr))
+ hr = unregister_interfaces(interface_list);
+ return hr;
+}
diff --git a/reactos/dll/win32/localspl/localmon.c b/reactos/dll/win32/localspl/localmon.c
new file mode 100644
index 00000000000..f4e1739d5cb
--- /dev/null
+++ b/reactos/dll/win32/localspl/localmon.c
@@ -0,0 +1,815 @@
+/*
+ * Implementation of the Local Printmonitor
+ *
+ * Copyright 2006 Detlef Riekenberg
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+
+#define COBJMACROS
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winreg.h"
+
+#include "winspool.h"
+#include "ddk/winsplp.h"
+#include "localspl_private.h"
+
+#include "wine/debug.h"
+#include "wine/list.h"
+#include "wine/unicode.h"
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(localspl);
+
+/*****************************************************/
+
+static CRITICAL_SECTION port_handles_cs;
+static CRITICAL_SECTION_DEBUG port_handles_cs_debug =
+{
+ 0, 0, &port_handles_cs,
+ { &port_handles_cs_debug.ProcessLocksList, &port_handles_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": port_handles_cs") }
+};
+static CRITICAL_SECTION port_handles_cs = { &port_handles_cs_debug, -1, 0, 0, 0, 0 };
+
+
+static CRITICAL_SECTION xcv_handles_cs;
+static CRITICAL_SECTION_DEBUG xcv_handles_cs_debug =
+{
+ 0, 0, &xcv_handles_cs,
+ { &xcv_handles_cs_debug.ProcessLocksList, &xcv_handles_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": xcv_handles_cs") }
+};
+static CRITICAL_SECTION xcv_handles_cs = { &xcv_handles_cs_debug, -1, 0, 0, 0, 0 };
+
+/* ############################### */
+
+typedef struct {
+ struct list entry;
+ DWORD type;
+ WCHAR nameW[1];
+} port_t;
+
+typedef struct {
+ struct list entry;
+ ACCESS_MASK GrantedAccess;
+ WCHAR nameW[1];
+} xcv_t;
+
+static struct list port_handles = LIST_INIT( port_handles );
+static struct list xcv_handles = LIST_INIT( xcv_handles );
+
+/* ############################### */
+
+static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0};
+static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0};
+static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e',
+ 'L','P','T','P','o','r','t',
+ 'C','o','m','m','a','n','d','O','K',0};
+
+static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t',
+ 'D','e','f','a','u','l','t',
+ 'C','o','m','m','C','o','n','f','i','g',0};
+
+static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t',
+ 'T','r','a','n','s','m','i','s','s','i','o','n',
+ 'R','e','t','r','y','T','i','m','e','o','u','t',0};
+
+static const WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
+static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
+static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t',
+ 'D','e','f','a','u','l','t',
+ 'C','o','m','m','C','o','n','f','i','g',0};
+
+static const WCHAR dllnameuiW[] = {'l','o','c','a','l','u','i','.','d','l','l',0};
+static const WCHAR emptyW[] = {0};
+static const WCHAR LocalPortW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
+
+static const WCHAR portname_LPT[] = {'L','P','T',0};
+static const WCHAR portname_COM[] = {'C','O','M',0};
+static const WCHAR portname_FILE[] = {'F','I','L','E',':',0};
+static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0};
+static const WCHAR portname_LPR[] = {'L','P','R',':',0};
+
+static const WCHAR TransmissionRetryTimeoutW[] = {'T','r','a','n','s','m','i','s','s','i','o','n',
+ 'R','e','t','r','y','T','i','m','e','o','u','t',0};
+
+static const WCHAR WinNT_CV_PortsW[] = {'S','o','f','t','w','a','r','e','\\',
+ 'M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s',' ','N','T','\\',
+ 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'P','o','r','t','s',0};
+
+static const WCHAR WinNT_CV_WindowsW[] = {'S','o','f','t','w','a','r','e','\\',
+ 'M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s',' ','N','T','\\',
+ 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'W','i','n','d','o','w','s',0};
+
+
+/******************************************************************
+ * does_port_exist (internal)
+ *
+ * returns TRUE, when the Port already exists
+ *
+ */
+static BOOL does_port_exist(LPCWSTR myname)
+{
+
+ LPPORT_INFO_1W pi;
+ DWORD needed = 0;
+ DWORD returned;
+ DWORD id;
+
+ TRACE("(%s)\n", debugstr_w(myname));
+
+ id = EnumPortsW(NULL, 1, NULL, 0, &needed, &returned);
+ pi = heap_alloc(needed);
+ returned = 0;
+ if (pi)
+ id = EnumPortsW(NULL, 1, (LPBYTE) pi, needed, &needed, &returned);
+
+ if (id && returned > 0) {
+ /* we got a number of valid names. */
+ for (id = 0; id < returned; id++)
+ {
+ if (lstrcmpiW(myname, pi[id].pName) == 0) {
+ TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName));
+ heap_free(pi);
+ return TRUE;
+ }
+ }
+ }
+
+ heap_free(pi);
+ return FALSE;
+}
+
+/******************************************************************
+ * enumerate the local Ports from the Registry (internal)
+ *
+ * See localmon_EnumPortsW.
+ *
+ * NOTES
+ * returns the needed size (in bytes) for pPorts
+ * and *lpreturned is set to number of entries returned in pPorts
+ *
+ */
+
+static DWORD get_ports_from_reg(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned)
+{
+ HKEY hroot = 0;
+ LPWSTR ptr;
+ LPPORT_INFO_2W out;
+ WCHAR portname[MAX_PATH];
+ WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
+ WCHAR res_MonitorW[IDS_LOCALMONITOR_MAXLEN];
+ INT reslen_PortW;
+ INT reslen_MonitorW;
+ DWORD len;
+ DWORD res;
+ DWORD needed = 0;
+ DWORD numentries;
+ DWORD entrysize;
+ DWORD id = 0;
+
+ TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned);
+
+ entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
+
+ numentries = *lpreturned; /* this is 0, when we scan the registry */
+ needed = entrysize * numentries;
+ ptr = (LPWSTR) &pPorts[needed];
+
+ if (needed > cbBuf) pPorts = NULL; /* No buffer for the structs */
+
+ numentries = 0;
+ needed = 0;
+
+ /* we do not check more parameters as done in windows */
+ if ((level < 1) || (level > 2)) {
+ goto getports_cleanup;
+ }
+
+ /* "+1" for '\0' */
+ reslen_MonitorW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALMONITOR, res_MonitorW, IDS_LOCALMONITOR_MAXLEN) + 1;
+ reslen_PortW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN) + 1;
+
+ res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
+ if (res == ERROR_SUCCESS) {
+
+ /* Scan all Port-Names */
+ while (res == ERROR_SUCCESS) {
+ len = MAX_PATH;
+ portname[0] = '\0';
+ res = RegEnumValueW(hroot, id, portname, &len, NULL, NULL, NULL, NULL);
+
+ if ((res == ERROR_SUCCESS) && (portname[0])) {
+ numentries++;
+ /* calculate the required size */
+ needed += entrysize;
+ needed += (len + 1) * sizeof(WCHAR);
+ if (level > 1) {
+ needed += (reslen_MonitorW + reslen_PortW) * sizeof(WCHAR);
+ }
+
+ /* Now fill the user-buffer, if available */
+ if (pPorts && (cbBuf >= needed)){
+ out = (LPPORT_INFO_2W) pPorts;
+ pPorts += entrysize;
+ TRACE("%p: writing PORT_INFO_%dW #%d (%s)\n", out, level, numentries, debugstr_w(portname));
+ out->pPortName = ptr;
+ lstrcpyW(ptr, portname); /* Name of the Port */
+ ptr += (len + 1);
+ if (level > 1) {
+ out->pMonitorName = ptr;
+ lstrcpyW(ptr, res_MonitorW); /* Name of the Monitor */
+ ptr += reslen_MonitorW;
+
+ out->pDescription = ptr;
+ lstrcpyW(ptr, res_PortW); /* Port Description */
+ ptr += reslen_PortW;
+
+ out->fPortType = PORT_TYPE_WRITE;
+ out->Reserved = 0;
+ }
+ }
+ id++;
+ }
+ }
+ RegCloseKey(hroot);
+ }
+ else
+ {
+ ERR("failed with %d for %s\n", res, debugstr_w(WinNT_CV_PortsW));
+ SetLastError(res);
+ }
+
+getports_cleanup:
+ *lpreturned = numentries;
+ TRACE("need %d byte for %d entries (%d)\n", needed, numentries, GetLastError());
+ return needed;
+}
+
+/*****************************************************
+ * get_type_from_name (internal)
+ *
+ */
+
+static DWORD get_type_from_name(LPCWSTR name)
+{
+ HANDLE hfile;
+
+ if (!strncmpW(name, portname_LPT, sizeof(portname_LPT) / sizeof(WCHAR) -1))
+ return PORT_IS_LPT;
+
+ if (!strncmpW(name, portname_COM, sizeof(portname_COM) / sizeof(WCHAR) -1))
+ return PORT_IS_COM;
+
+ if (!strcmpW(name, portname_FILE))
+ return PORT_IS_FILE;
+
+ if (name[0] == '/')
+ return PORT_IS_UNIXNAME;
+
+ if (name[0] == '|')
+ return PORT_IS_PIPE;
+
+ if (!strncmpW(name, portname_CUPS, sizeof(portname_CUPS) / sizeof(WCHAR) -1))
+ return PORT_IS_CUPS;
+
+ if (!strncmpW(name, portname_LPR, sizeof(portname_LPR) / sizeof(WCHAR) -1))
+ return PORT_IS_LPR;
+
+ /* Must be a file or a directory. Does the file exist ? */
+ hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ TRACE("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name));
+ if (hfile == INVALID_HANDLE_VALUE) {
+ /* Can we create the file? */
+ hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ TRACE("%p for OPEN_ALWAYS\n", hfile);
+ }
+ if (hfile != INVALID_HANDLE_VALUE) {
+ CloseHandle(hfile);
+ return PORT_IS_FILENAME;
+ }
+ /* We can't use the name. use GetLastError() for the reason */
+ return PORT_IS_UNKNOWN;
+}
+
+/*****************************************************
+ * get_type_from_local_name (internal)
+ *
+ */
+
+static DWORD get_type_from_local_name(LPCWSTR nameW)
+{
+ LPPORT_INFO_1W pi;
+ LPWSTR myname = NULL;
+ DWORD needed = 0;
+ DWORD numentries = 0;
+ DWORD id = 0;
+
+ TRACE("(%s)\n", debugstr_w(myname));
+
+ needed = get_ports_from_reg(1, NULL, 0, &numentries);
+ pi = heap_alloc(needed);
+ if (pi)
+ needed = get_ports_from_reg(1, (LPBYTE) pi, needed, &numentries);
+
+ if (pi && needed && numentries > 0) {
+ /* we got a number of valid ports. */
+
+ while ((myname == NULL) && (id < numentries))
+ {
+ if (lstrcmpiW(nameW, pi[id].pName) == 0) {
+ TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName));
+ myname = pi[id].pName;
+ }
+ id++;
+ }
+ }
+
+ id = (myname) ? get_type_from_name(myname) : PORT_IS_UNKNOWN;
+
+ heap_free(pi);
+ return id;
+
+}
+/******************************************************************************
+ * localmon_AddPortExW [exported through MONITOREX]
+ *
+ * Add a Port, without presenting a user interface
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * level [I] Structure-Level (1) for pBuffer
+ * pBuffer [I] PTR to the Input-Data (PORT_INFO_1)
+ * pMonitorName [I] Name of the Monitor that manage the Port
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * Level 2 is documented on MSDN for Portmonitors, but not supported by the
+ * "Local Port" Portmonitor (localspl.dll / localmon.dll)
+ */
+static BOOL WINAPI localmon_AddPortExW(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR pMonitorName)
+{
+ PORT_INFO_1W * pi;
+ HKEY hroot;
+ DWORD res;
+
+ pi = (PORT_INFO_1W *) pBuffer;
+ TRACE("(%s, %d, %p, %s) => %s\n", debugstr_w(pName), level, pBuffer,
+ debugstr_w(pMonitorName), debugstr_w(pi ? pi->pName : NULL));
+
+
+ if ((pMonitorName == NULL) || (lstrcmpiW(pMonitorName, LocalPortW) != 0 ) ||
+ (pi == NULL) || (pi->pName == NULL) || (pi->pName[0] == '\0') ) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if (level != 1) {
+ SetLastError(ERROR_INVALID_LEVEL);
+ return FALSE;
+ }
+
+ res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
+ if (res == ERROR_SUCCESS) {
+ if (does_port_exist(pi->pName)) {
+ RegCloseKey(hroot);
+ TRACE("=> FALSE with %u\n", ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ res = RegSetValueExW(hroot, pi->pName, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW));
+ RegCloseKey(hroot);
+ }
+ if (res != ERROR_SUCCESS) SetLastError(ERROR_INVALID_PARAMETER);
+ TRACE("=> %u with %u\n", (res == ERROR_SUCCESS), GetLastError());
+ return (res == ERROR_SUCCESS);
+}
+
+/*****************************************************
+ * localmon_ClosePort [exported through MONITOREX]
+ *
+ * Close a
+ *
+ * PARAMS
+ * hPort [i] The Handle to close
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+static BOOL WINAPI localmon_ClosePort(HANDLE hPort)
+{
+ port_t * port = hPort;
+
+ TRACE("(%p)\n", port);
+ EnterCriticalSection(&port_handles_cs);
+ list_remove(&port->entry);
+ LeaveCriticalSection(&port_handles_cs);
+ heap_free(port);
+ return TRUE;
+}
+
+/*****************************************************
+ * localmon_EnumPortsW [exported through MONITOREX]
+ *
+ * Enumerate all local Ports
+ *
+ * PARAMS
+ * pName [I] Servername (ignored)
+ * level [I] Structure-Level (1 or 2)
+ * pPorts [O] PTR to Buffer that receives the Result
+ * cbBuf [I] Size of Buffer at pPorts
+ * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
+ * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
+ *
+ * NOTES
+ *| Windows ignores pName
+ *| Windows crash the app, when pPorts, pcbNeeded or pcReturned are NULL
+ *| Windows >NT4.0 does not check for illegal levels (TRUE is returned)
+ *
+ * ToDo
+ * "HCU\Software\Wine\Spooler\" - redirection
+ *
+ */
+static BOOL WINAPI localmon_EnumPortsW(LPWSTR pName, DWORD level, LPBYTE pPorts,
+ DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
+{
+ BOOL res = FALSE;
+ DWORD needed;
+ DWORD numentries;
+
+ TRACE("(%s, %d, %p, %d, %p, %p)\n",
+ debugstr_w(pName), level, pPorts, cbBuf, pcbNeeded, pcReturned);
+
+ numentries = 0;
+ needed = get_ports_from_reg(level, NULL, 0, &numentries);
+ /* we calculated the needed buffersize. now do the error-checks */
+ if (cbBuf < needed) {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto cleanup;
+ }
+
+ /* fill the buffer with the Port-Names */
+ needed = get_ports_from_reg(level, pPorts, cbBuf, &numentries);
+ res = TRUE;
+
+ if (pcReturned) *pcReturned = numentries;
+
+cleanup:
+ if (pcbNeeded) *pcbNeeded = needed;
+
+ TRACE("returning %d with %d (%d byte for %d entries)\n",
+ res, GetLastError(), needed, numentries);
+
+ return (res);
+}
+
+/*****************************************************
+ * localmon_OpenPort [exported through MONITOREX]
+ *
+ * Open a Data-Channel for a Port
+ *
+ * PARAMS
+ * pName [i] Name of selected Object
+ * phPort [o] The resulting Handle is stored here
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+static BOOL WINAPI localmon_OpenPortW(LPWSTR pName, PHANDLE phPort)
+{
+ port_t * port;
+ DWORD len;
+ DWORD type;
+
+ TRACE("%s, %p)\n", debugstr_w(pName), phPort);
+
+ /* an empty name is invalid */
+ if (!pName[0]) return FALSE;
+
+ /* does the port exist? */
+ type = get_type_from_local_name(pName);
+ if (!type) return FALSE;
+
+ len = (lstrlenW(pName) + 1) * sizeof(WCHAR);
+ port = heap_alloc(sizeof(port_t) + len);
+ if (!port) return FALSE;
+
+ port->type = type;
+ memcpy(port->nameW, pName, len);
+ *phPort = port;
+
+ EnterCriticalSection(&port_handles_cs);
+ list_add_tail(&port_handles, &port->entry);
+ LeaveCriticalSection(&port_handles_cs);
+
+ TRACE("=> %p\n", port);
+ return TRUE;
+}
+
+/*****************************************************
+ * localmon_XcvClosePort [exported through MONITOREX]
+ *
+ * Close a Communication-Channel
+ *
+ * PARAMS
+ * hXcv [i] The Handle to close
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+static BOOL WINAPI localmon_XcvClosePort(HANDLE hXcv)
+{
+ xcv_t * xcv = hXcv;
+
+ TRACE("(%p)\n", xcv);
+ /* No checks are done in Windows */
+ EnterCriticalSection(&xcv_handles_cs);
+ list_remove(&xcv->entry);
+ LeaveCriticalSection(&xcv_handles_cs);
+ heap_free(xcv);
+ return TRUE;
+}
+
+/*****************************************************
+ * localmon_XcvDataPort [exported through MONITOREX]
+ *
+ * Execute command through a Communication-Channel
+ *
+ * PARAMS
+ * hXcv [i] The Handle to work with
+ * pszDataName [i] Name of the command to execute
+ * pInputData [i] Buffer for extra Input Data (needed only for some commands)
+ * cbInputData [i] Size in Bytes of Buffer at pInputData
+ * pOutputData [o] Buffer to receive additional Data (needed only for some commands)
+ * cbOutputData [i] Size in Bytes of Buffer at pOutputData
+ * pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData
+ *
+ * RETURNS
+ * Success: ERROR_SUCCESS
+ * Failure: win32 error code
+ *
+ * NOTES
+ *
+ * Minimal List of commands, that every Printmonitor DLL should support:
+ *
+ *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData
+ *| "AddPort" : Add a Port (Name as WSTR in pInputData)
+ *| "DeletePort": Delete a Port (Name as WSTR in pInputData)
+ *
+ *
+ */
+static DWORD WINAPI localmon_XcvDataPort(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData,
+ PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
+{
+ WCHAR buffer[16]; /* buffer for a decimal number */
+ LPWSTR ptr;
+ DWORD res;
+ DWORD needed;
+ HKEY hroot;
+
+ TRACE("(%p, %s, %p, %d, %p, %d, %p)\n", hXcv, debugstr_w(pszDataName),
+ pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
+
+ if (!lstrcmpW(pszDataName, cmd_AddPortW)) {
+ TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
+ res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
+ if (res == ERROR_SUCCESS) {
+ if (does_port_exist((LPWSTR) pInputData)) {
+ RegCloseKey(hroot);
+ TRACE("=> %u\n", ERROR_ALREADY_EXISTS);
+ return ERROR_ALREADY_EXISTS;
+ }
+ res = RegSetValueExW(hroot, (LPWSTR) pInputData, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW));
+ RegCloseKey(hroot);
+ }
+ TRACE("=> %u\n", res);
+ return res;
+ }
+
+
+ if (!lstrcmpW(pszDataName, cmd_ConfigureLPTPortCommandOKW)) {
+ TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
+ res = RegCreateKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot);
+ if (res == ERROR_SUCCESS) {
+ res = RegSetValueExW(hroot, TransmissionRetryTimeoutW, 0, REG_SZ, pInputData, cbInputData);
+ RegCloseKey(hroot);
+ }
+ return res;
+ }
+
+ if (!lstrcmpW(pszDataName, cmd_DeletePortW)) {
+ TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
+ res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
+ if (res == ERROR_SUCCESS) {
+ res = RegDeleteValueW(hroot, (LPWSTR) pInputData);
+ RegCloseKey(hroot);
+ TRACE("=> %u with %u\n", res, GetLastError() );
+ return res;
+ }
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+ if (!lstrcmpW(pszDataName, cmd_GetDefaultCommConfigW)) {
+ TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
+ *pcbOutputNeeded = cbOutputData;
+ res = GetDefaultCommConfigW((LPWSTR) pInputData, (LPCOMMCONFIG) pOutputData, pcbOutputNeeded);
+ TRACE("got %u with %u\n", res, GetLastError() );
+ return res ? ERROR_SUCCESS : GetLastError();
+ }
+
+ if (!lstrcmpW(pszDataName, cmd_GetTransmissionRetryTimeoutW)) {
+ * pcbOutputNeeded = sizeof(DWORD);
+ if (cbOutputData >= sizeof(DWORD)) {
+ /* the w2k resource kit documented a default of 90, but that's wrong */
+ *((LPDWORD) pOutputData) = 45;
+
+ res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot);
+ if (res == ERROR_SUCCESS) {
+ needed = sizeof(buffer) - sizeof(WCHAR);
+ res = RegQueryValueExW(hroot, TransmissionRetryTimeoutW, NULL, NULL, (LPBYTE) buffer, &needed);
+ if ((res == ERROR_SUCCESS) && (buffer[0])) {
+ *((LPDWORD) pOutputData) = strtoulW(buffer, NULL, 0);
+ }
+ RegCloseKey(hroot);
+ }
+ return ERROR_SUCCESS;
+ }
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+
+ if (!lstrcmpW(pszDataName, cmd_MonitorUIW)) {
+ * pcbOutputNeeded = sizeof(dllnameuiW);
+ if (cbOutputData >= sizeof(dllnameuiW)) {
+ memcpy(pOutputData, dllnameuiW, sizeof(dllnameuiW));
+ return ERROR_SUCCESS;
+ }
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ if (!lstrcmpW(pszDataName, cmd_PortIsValidW)) {
+ TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
+ res = get_type_from_name((LPCWSTR) pInputData);
+ TRACE("detected as %u\n", res);
+ /* names, that we have recognized, are valid */
+ if (res) return ERROR_SUCCESS;
+
+ /* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */
+ TRACE("=> %u\n", GetLastError());
+ return GetLastError();
+ }
+
+ if (!lstrcmpW(pszDataName, cmd_SetDefaultCommConfigW)) {
+ /* get the portname from the Handle */
+ ptr = strchrW(((xcv_t *)hXcv)->nameW, ' ');
+ if (ptr) {
+ ptr++; /* skip the space */
+ }
+ else
+ {
+ ptr = ((xcv_t *)hXcv)->nameW;
+ }
+ lstrcpynW(buffer, ptr, sizeof(buffer)/sizeof(WCHAR));
+ if (buffer[0]) buffer[lstrlenW(buffer)-1] = '\0'; /* remove the ':' */
+ res = SetDefaultCommConfigW(buffer, (LPCOMMCONFIG) pInputData, cbInputData);
+ TRACE("got %u with %u\n", res, GetLastError() );
+ return res ? ERROR_SUCCESS : GetLastError();
+ }
+
+ FIXME("command not supported: %s\n", debugstr_w(pszDataName));
+ return ERROR_INVALID_PARAMETER;
+}
+
+/*****************************************************
+ * localmon_XcvOpenPort [exported through MONITOREX]
+ *
+ * Open a Communication-Channel
+ *
+ * PARAMS
+ * pName [i] Name of selected Object
+ * GrantedAccess [i] Access-Rights to use
+ * phXcv [o] The resulting Handle is stored here
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+static BOOL WINAPI localmon_XcvOpenPort(LPCWSTR pName, ACCESS_MASK GrantedAccess, PHANDLE phXcv)
+{
+ DWORD len;
+ xcv_t * xcv;
+
+ TRACE("%s, 0x%x, %p)\n", debugstr_w(pName), GrantedAccess, phXcv);
+ /* No checks for any field is done in Windows */
+ len = (lstrlenW(pName) + 1) * sizeof(WCHAR);
+ xcv = heap_alloc( sizeof(xcv_t) + len);
+ if (xcv) {
+ xcv->GrantedAccess = GrantedAccess;
+ memcpy(xcv->nameW, pName, len);
+ *phXcv = xcv;
+ EnterCriticalSection(&xcv_handles_cs);
+ list_add_tail(&xcv_handles, &xcv->entry);
+ LeaveCriticalSection(&xcv_handles_cs);
+ TRACE("=> %p\n", xcv);
+ return TRUE;
+ }
+ else
+ {
+ *phXcv = NULL;
+ return FALSE;
+ }
+}
+
+/*****************************************************
+ * InitializePrintMonitor (LOCALSPL.@)
+ *
+ * Initialize the Monitor for the Local Ports
+ *
+ * PARAMS
+ * regroot [I] Registry-Path, where the settings are stored
+ *
+ * RETURNS
+ * Success: Pointer to a MONITOREX Structure
+ * Failure: NULL
+ *
+ * NOTES
+ * The fixed location "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports"
+ * is used to store the Ports (IniFileMapping from "win.ini", Section "Ports").
+ * Native localspl.dll fails, when no valid Port-Entry is present.
+ *
+ */
+
+LPMONITOREX WINAPI InitializePrintMonitor(LPWSTR regroot)
+{
+ static MONITOREX mymonitorex =
+ {
+ sizeof(MONITOREX) - sizeof(DWORD),
+ {
+ localmon_EnumPortsW,
+ localmon_OpenPortW,
+ NULL, /* localmon_OpenPortExW */
+ NULL, /* localmon_StartDocPortW */
+ NULL, /* localmon_WritePortW */
+ NULL, /* localmon_ReadPortW */
+ NULL, /* localmon_EndDocPortW */
+ localmon_ClosePort,
+ NULL, /* Use AddPortUI in localui.dll */
+ localmon_AddPortExW,
+ NULL, /* Use ConfigurePortUI in localui.dll */
+ NULL, /* Use DeletePortUI in localui.dll */
+ NULL, /* localmon_GetPrinterDataFromPort */
+ NULL, /* localmon_SetPortTimeOuts */
+ localmon_XcvOpenPort,
+ localmon_XcvDataPort,
+ localmon_XcvClosePort
+ }
+ };
+
+ TRACE("(%s)\n", debugstr_w(regroot));
+ /* Parameter "regroot" is ignored on NT4.0 (localmon.dll) */
+ if (!regroot || !regroot[0]) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+ TRACE("=> %p\n", &mymonitorex);
+ /* Native windows returns always the same pointer on success */
+ return &mymonitorex;
+}
diff --git a/reactos/dll/win32/localspl/localspl.rbuild b/reactos/dll/win32/localspl/localspl.rbuild
new file mode 100644
index 00000000000..6c9ebeda826
--- /dev/null
+++ b/reactos/dll/win32/localspl/localspl.rbuild
@@ -0,0 +1,17 @@
+
+
+ .
+ include/reactos/wine
+
+ 0x600
+ localmon.c
+ localspl_main.c
+ provider.c
+ localspl.rc
+ wine
+ spoolss
+ user32
+ advapi32
+ kernel32
+ ntdll
+
diff --git a/reactos/dll/win32/localspl/localspl.rc b/reactos/dll/win32/localspl/localspl.rc
new file mode 100644
index 00000000000..71c1e4604b9
--- /dev/null
+++ b/reactos/dll/win32/localspl/localspl.rc
@@ -0,0 +1,52 @@
+/*
+ * Top level resource file for localspl
+ *
+ * Copyright 2006 Detlef Riekenberg
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+#include "windef.h"
+#include "winbase.h"
+#include "winver.h"
+#include "localspl_private.h"
+
+#define WINE_FILENAME_STR "localspl.dll"
+#define WINE_FILEDESCRIPTION_STR "Wine Printer spooler component"
+
+/* Same Version as WinXP_sp2 */
+#define WINE_FILEVERSION 5,1,2600,2180
+#define WINE_FILEVERSION_STR "5.1.2600.2180"
+
+#define WINE_PRODUCTVERSION 5,1,2600,2180
+#define WINE_PRODUCTVERSION_STR "5.1.2600.2180"
+
+#include "wine/wine_common_ver.rc"
+
+#include "spl_En.rc"
+#include "spl_Da.rc"
+#include "spl_De.rc"
+#include "spl_Fr.rc"
+#include "spl_Ko.rc"
+#include "spl_Nl.rc"
+#include "spl_No.rc"
+#include "spl_Pl.rc"
+#include "spl_Pt.rc"
+#include "spl_Ro.rc"
+#include "spl_Ru.rc"
+#include "spl_Si.rc"
+#include "spl_Sv.rc"
+#include "spl_Zh.rc"
diff --git a/reactos/dll/win32/localspl/localspl.spec b/reactos/dll/win32/localspl/localspl.spec
new file mode 100644
index 00000000000..651d20d07d0
--- /dev/null
+++ b/reactos/dll/win32/localspl/localspl.spec
@@ -0,0 +1,64 @@
+@ stub ClosePrintProcessor
+@ stub ControlPrintProcessor
+@ stub EnumPrintProcessorDatatypesW
+@ stub GetPrintProcessorCapabilities
+@ stdcall InitializePrintMonitor(wstr)
+# "Providor" is no typo here
+@ stdcall InitializePrintProvidor(ptr long wstr)
+@ stub OpenPrintProcessor
+@ stub PrintDocumentOnPrintProcessor
+@ stub PrintProcLogEvent
+@ stub SplAddForm
+@ stub SplAddMonitor
+@ stub SplAddPort
+@ stub SplAddPortEx
+@ stub SplAddPrinter
+@ stub SplAddPrinterDriverEx
+@ stub SplAddPrintProcessor
+@ stub SplBroadcastChange
+@ stub SplClosePrinter
+@ stub SplCloseSpooler
+@ stub SplConfigChange
+@ stub SplCopyFileEvent
+@ stub SplCopyNumberOfFiles
+@ stub SplCreateSpooler
+@ stub SplDeleteForm
+@ stub SplDeleteMonitor
+@ stub SplDeletePort
+@ stub SplDeletePrinter
+@ stub SplDeletePrinterDriverEx
+@ stub SplDeletePrinterKey
+@ stub SplDeletePrintProcessor
+@ stub SplDeleteSpooler
+@ stub SplDriverEvent
+@ stub SplEnumForms
+@ stub SplEnumMonitors
+@ stub SplEnumPorts
+@ stub SplEnumPrinterDataEx
+@ stub SplEnumPrinterKey
+@ stub SplEnumPrinters
+@ stub SplEnumPrintProcessorDatatypes
+@ stub SplEnumPrintProcessors
+@ stub SplGetDriverDir
+@ stub SplGetForm
+@ stub SplGetPrinter
+@ stub SplGetPrinterData
+@ stub SplGetPrinterDataEx
+@ stub SplGetPrinterDriver
+@ stub SplGetPrinterDriverDirectory
+@ stub SplGetPrinterDriverEx
+@ stub SplGetPrinterExtra
+@ stub SplGetPrinterExtraEx
+@ stub SplGetPrintProcessorDirectory
+@ stub SplLoadLibraryTheCopyFileModule
+@ stub SplMonitorIsInstalled
+@ stub SplOpenPrinter
+@ stub SplReenumeratePorts
+@ stub SplResetPrinter
+@ stub SplSetForm
+@ stub SplSetPrinter
+@ stub SplSetPrinterData
+@ stub SplSetPrinterDataEx
+@ stub SplSetPrinterExtra
+@ stub SplSetPrinterExtraEx
+@ stub SplXcvData
diff --git a/reactos/dll/win32/localspl/localspl_main.c b/reactos/dll/win32/localspl/localspl_main.c
new file mode 100644
index 00000000000..d4a3c33ca01
--- /dev/null
+++ b/reactos/dll/win32/localspl/localspl_main.c
@@ -0,0 +1,56 @@
+/*
+ * Implementation of the Local Printprovider/ Printmonitor/ Prontprocessor
+ *
+ * Copyright 2006-2009 Detlef Riekenberg
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+
+#define COBJMACROS
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "wine/debug.h"
+#include "localspl_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(localspl);
+
+
+HINSTANCE LOCALSPL_hInstance = NULL;
+
+/*****************************************************
+ * DllMain
+ */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved);
+
+ switch(fdwReason)
+ {
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
+
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls( hinstDLL );
+ LOCALSPL_hInstance = hinstDLL;
+ setup_provider();
+ break;
+ }
+ return TRUE;
+}
diff --git a/reactos/dll/win32/localspl/localspl_private.h b/reactos/dll/win32/localspl/localspl_private.h
new file mode 100644
index 00000000000..0ac63697d03
--- /dev/null
+++ b/reactos/dll/win32/localspl/localspl_private.h
@@ -0,0 +1,71 @@
+/*
+ * Implementation of the Local Printmonitor: internal include file
+ *
+ * Copyright 2006 Detlef Riekenberg
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_LOCALSPL_PRIVATE__
+#define __WINE_LOCALSPL_PRIVATE__
+
+
+/* ## DLL-wide Globals ## */
+extern HINSTANCE LOCALSPL_hInstance;
+void setup_provider(void);
+
+/* ## Resource-ID ## */
+#define IDS_LOCALPORT 500
+#define IDS_LOCALMONITOR 507
+
+/* ## Reserved memorysize for the strings (in WCHAR) ## */
+#define IDS_LOCALMONITOR_MAXLEN 64
+#define IDS_LOCALPORT_MAXLEN 32
+
+/* ## Type of Ports ## */
+/* windows types */
+#define PORT_IS_UNKNOWN 0
+#define PORT_IS_LPT 1
+#define PORT_IS_COM 2
+#define PORT_IS_FILE 3
+#define PORT_IS_FILENAME 4
+
+/* wine extensions */
+#define PORT_IS_WINE 5
+#define PORT_IS_UNIXNAME 5
+#define PORT_IS_PIPE 6
+#define PORT_IS_CUPS 7
+#define PORT_IS_LPR 8
+
+
+/* ## Memory allocation functions ## */
+
+static inline void * __WINE_ALLOC_SIZE(1) heap_alloc( size_t len )
+{
+ return HeapAlloc( GetProcessHeap(), 0, len );
+}
+
+static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero( size_t len )
+{
+ return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
+}
+
+static inline BOOL heap_free( void *mem )
+{
+ return HeapFree( GetProcessHeap(), 0, mem );
+}
+
+
+#endif /* __WINE_LOCALSPL_PRIVATE__ */
diff --git a/reactos/dll/win32/localspl/provider.c b/reactos/dll/win32/localspl/provider.c
new file mode 100644
index 00000000000..dcb8b088d37
--- /dev/null
+++ b/reactos/dll/win32/localspl/provider.c
@@ -0,0 +1,1554 @@
+/*
+ * Implementation of the Local Printprovider
+ *
+ * Copyright 2006-2009 Detlef Riekenberg
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+
+#define COBJMACROS
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winreg.h"
+#include "winspool.h"
+#include "winuser.h"
+#include "ddk/winddiui.h"
+#include "ddk/winsplp.h"
+
+#include "wine/list.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "localspl_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(localspl);
+
+/* ############################### */
+
+static CRITICAL_SECTION monitor_handles_cs;
+static CRITICAL_SECTION_DEBUG monitor_handles_cs_debug =
+{
+ 0, 0, &monitor_handles_cs,
+ { &monitor_handles_cs_debug.ProcessLocksList, &monitor_handles_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": monitor_handles_cs") }
+};
+static CRITICAL_SECTION monitor_handles_cs = { &monitor_handles_cs_debug, -1, 0, 0, 0, 0 };
+
+/* ############################### */
+
+typedef struct {
+ WCHAR src[MAX_PATH+MAX_PATH];
+ WCHAR dst[MAX_PATH+MAX_PATH];
+ DWORD srclen;
+ DWORD dstlen;
+ DWORD copyflags;
+ BOOL lazy;
+} apd_data_t;
+
+typedef struct {
+ struct list entry;
+ LPWSTR name;
+ LPWSTR dllname;
+ PMONITORUI monitorUI;
+ LPMONITOR monitor;
+ HMODULE hdll;
+ DWORD refcount;
+ DWORD dwMonitorSize;
+} monitor_t;
+
+typedef struct {
+ LPCWSTR envname;
+ LPCWSTR subdir;
+ DWORD driverversion;
+ LPCWSTR versionregpath;
+ LPCWSTR versionsubdir;
+} printenv_t;
+
+/* ############################### */
+
+static struct list monitor_handles = LIST_INIT( monitor_handles );
+static monitor_t * pm_localport;
+
+static const PRINTPROVIDOR * pprovider = NULL;
+
+static const WCHAR backslashW[] = {'\\',0};
+static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0};
+static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0};
+static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0};
+static const WCHAR default_devmodeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0};
+static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0};
+static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
+static const WCHAR driverW[] = {'D','r','i','v','e','r',0};
+static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\',
+ 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'c','o','n','t','r','o','l','\\',
+ 'P','r','i','n','t','\\',
+ 'E','n','v','i','r','o','n','m','e','n','t','s','\\',
+ '%','s','\\','D','r','i','v','e','r','s','%','s',0 };
+static const WCHAR hardwareidW[] = {'H','a','r','d','w','a','r','e','I','D',0};
+static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0};
+static const WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
+static const WCHAR locationW[] = {'L','o','c','a','t','i','o','n',0};
+static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
+static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0};
+static const WCHAR monitorsW[] = {'S','y','s','t','e','m','\\',
+ 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\',
+ 'P','r','i','n','t','\\',
+ 'M','o','n','i','t','o','r','s','\\',0};
+static const WCHAR monitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
+static const WCHAR nameW[] = {'N','a','m','e',0};
+static const WCHAR oem_urlW[] = {'O','E','M',' ','U','r','l',0};
+static const WCHAR parametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
+static const WCHAR portW[] = {'P','o','r','t',0};
+static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0};
+static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\',0};
+static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0};
+
+static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0};
+static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0};
+static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0};
+static const WCHAR version0_subdirW[] = {'\\','0',0};
+
+static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0};
+static const WCHAR x64_subdirW[] = {'x','6','4',0};
+static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0};
+static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0};
+static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0};
+static const WCHAR version3_subdirW[] = {'\\','3',0};
+
+
+static const printenv_t env_x86 = {x86_envnameW, x86_subdirW, 3,
+ version3_regpathW, version3_subdirW};
+
+static const printenv_t env_x64 = {x64_envnameW, x64_subdirW, 3,
+ version3_regpathW, version3_subdirW};
+
+static const printenv_t env_win40 = {win40_envnameW, win40_subdirW, 0,
+ version0_regpathW, version0_subdirW};
+
+static const printenv_t * const all_printenv[] = {&env_x86, &env_x64, &env_win40};
+
+
+static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W),
+ sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W),
+ sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W),
+ 0, sizeof(DRIVER_INFO_8W)};
+
+
+/******************************************************************
+ * strdupW [internal]
+ *
+ * create a copy of a unicode-string
+ *
+ */
+static LPWSTR strdupW(LPCWSTR p)
+{
+ LPWSTR ret;
+ DWORD len;
+
+ if(!p) return NULL;
+ len = (lstrlenW(p) + 1) * sizeof(WCHAR);
+ ret = heap_alloc(len);
+ memcpy(ret, p, len);
+ return ret;
+}
+
+/******************************************************************
+ * apd_copyfile [internal]
+ *
+ * Copy a file from the driverdirectory to the versioned directory
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+static BOOL apd_copyfile(LPWSTR filename, apd_data_t *apd)
+{
+ LPWSTR ptr;
+ LPWSTR srcname;
+ DWORD res;
+
+ apd->src[apd->srclen] = '\0';
+ apd->dst[apd->dstlen] = '\0';
+
+ if (!filename || !filename[0]) {
+ /* nothing to copy */
+ return TRUE;
+ }
+
+ ptr = strrchrW(filename, '\\');
+ if (ptr) {
+ ptr++;
+ }
+ else
+ {
+ ptr = filename;
+ }
+
+ if (apd->copyflags & APD_COPY_FROM_DIRECTORY) {
+ /* we have an absolute Path */
+ srcname = filename;
+ }
+ else
+ {
+ srcname = apd->src;
+ lstrcatW(srcname, ptr);
+ }
+ lstrcatW(apd->dst, ptr);
+
+ TRACE("%s => %s\n", debugstr_w(filename), debugstr_w(apd->dst));
+
+ /* FIXME: handle APD_COPY_NEW_FILES */
+ res = CopyFileW(srcname, apd->dst, FALSE);
+ TRACE("got %u with %u\n", res, GetLastError());
+
+ return (apd->lazy) ? TRUE : res;
+}
+
+/******************************************************************
+ * copy_servername_from_name (internal)
+ *
+ * for an external server, the serverpart from the name is copied.
+ *
+ * RETURNS
+ * the length (in WCHAR) of the serverpart (0 for the local computer)
+ * (-length), when the name is to long
+ *
+ */
+static LONG copy_servername_from_name(LPCWSTR name, LPWSTR target)
+{
+ LPCWSTR server;
+ LPWSTR ptr;
+ WCHAR buffer[MAX_COMPUTERNAME_LENGTH +1];
+ DWORD len;
+ DWORD serverlen;
+
+ if (target) *target = '\0';
+
+ if (name == NULL) return 0;
+ if ((name[0] != '\\') || (name[1] != '\\')) return 0;
+
+ server = &name[2];
+ /* skip over both backslash, find separator '\' */
+ ptr = strchrW(server, '\\');
+ serverlen = (ptr) ? ptr - server : lstrlenW(server);
+
+ /* servername is empty or to long */
+ if (serverlen == 0) return 0;
+
+ TRACE("found %s\n", debugstr_wn(server, serverlen));
+
+ if (serverlen > MAX_COMPUTERNAME_LENGTH) return -serverlen;
+
+ len = sizeof(buffer) / sizeof(buffer[0]);
+ if (GetComputerNameW(buffer, &len)) {
+ if ((serverlen == len) && (strncmpiW(server, buffer, len) == 0)) {
+ /* The requested Servername is our computername */
+ if (target) {
+ memcpy(target, server, serverlen * sizeof(WCHAR));
+ target[serverlen] = '\0';
+ }
+ return serverlen;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************
+ * monitor_unload [internal]
+ *
+ * release a printmonitor and unload it from memory, when needed
+ *
+ */
+static void monitor_unload(monitor_t * pm)
+{
+ if (pm == NULL) return;
+ TRACE("%p (refcount: %d) %s\n", pm, pm->refcount, debugstr_w(pm->name));
+
+ EnterCriticalSection(&monitor_handles_cs);
+
+ if (pm->refcount) pm->refcount--;
+
+ if (pm->refcount == 0) {
+ list_remove(&pm->entry);
+ FreeLibrary(pm->hdll);
+ heap_free(pm->name);
+ heap_free(pm->dllname);
+ heap_free(pm);
+ }
+ LeaveCriticalSection(&monitor_handles_cs);
+}
+
+/******************************************************************
+ * monitor_unloadall [internal]
+ *
+ * release all printmonitors and unload them from memory, when needed
+ *
+ */
+
+static void monitor_unloadall(void)
+{
+ monitor_t * pm;
+ monitor_t * next;
+
+ EnterCriticalSection(&monitor_handles_cs);
+ /* iterate through the list, with safety against removal */
+ LIST_FOR_EACH_ENTRY_SAFE(pm, next, &monitor_handles, monitor_t, entry)
+ {
+ monitor_unload(pm);
+ }
+ LeaveCriticalSection(&monitor_handles_cs);
+}
+
+/******************************************************************
+ * monitor_load [internal]
+ *
+ * load a printmonitor, get the dllname from the registry, when needed
+ * initialize the monitor and dump found function-pointers
+ *
+ * On failure, SetLastError() is called and NULL is returned
+ */
+
+static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
+{
+ LPMONITOR2 (WINAPI *pInitializePrintMonitor2) (PMONITORINIT, LPHANDLE);
+ PMONITORUI (WINAPI *pInitializePrintMonitorUI)(VOID);
+ LPMONITOREX (WINAPI *pInitializePrintMonitor) (LPWSTR);
+ DWORD (WINAPI *pInitializeMonitorEx)(LPWSTR, LPMONITOR);
+ DWORD (WINAPI *pInitializeMonitor) (LPWSTR);
+
+ monitor_t * pm = NULL;
+ monitor_t * cursor;
+ LPWSTR regroot = NULL;
+ LPWSTR driver = dllname;
+
+ TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname));
+ /* Is the Monitor already loaded? */
+ EnterCriticalSection(&monitor_handles_cs);
+
+ if (name) {
+ LIST_FOR_EACH_ENTRY(cursor, &monitor_handles, monitor_t, entry)
+ {
+ if (cursor->name && (lstrcmpW(name, cursor->name) == 0)) {
+ pm = cursor;
+ break;
+ }
+ }
+ }
+
+ if (pm == NULL) {
+ pm = heap_alloc_zero(sizeof(monitor_t));
+ if (pm == NULL) goto cleanup;
+ list_add_tail(&monitor_handles, &pm->entry);
+ }
+ pm->refcount++;
+
+ if (pm->name == NULL) {
+ /* Load the monitor */
+ LPMONITOREX pmonitorEx;
+ DWORD len;
+
+ if (name) {
+ len = lstrlenW(monitorsW) + lstrlenW(name) + 2;
+ regroot = heap_alloc(len * sizeof(WCHAR));
+ }
+
+ if (regroot) {
+ lstrcpyW(regroot, monitorsW);
+ lstrcatW(regroot, name);
+ /* Get the Driver from the Registry */
+ if (driver == NULL) {
+ HKEY hroot;
+ DWORD namesize;
+ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) {
+ if (RegQueryValueExW(hroot, driverW, NULL, NULL, NULL,
+ &namesize) == ERROR_SUCCESS) {
+ driver = heap_alloc(namesize);
+ RegQueryValueExW(hroot, driverW, NULL, NULL, (LPBYTE) driver, &namesize) ;
+ }
+ RegCloseKey(hroot);
+ }
+ }
+ }
+
+ pm->name = strdupW(name);
+ pm->dllname = strdupW(driver);
+
+ if ((name && (!regroot || !pm->name)) || !pm->dllname) {
+ monitor_unload(pm);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ pm = NULL;
+ goto cleanup;
+ }
+
+ pm->hdll = LoadLibraryW(driver);
+ TRACE("%p: LoadLibrary(%s) => %d\n", pm->hdll, debugstr_w(driver), GetLastError());
+
+ if (pm->hdll == NULL) {
+ monitor_unload(pm);
+ SetLastError(ERROR_MOD_NOT_FOUND);
+ pm = NULL;
+ goto cleanup;
+ }
+
+ pInitializePrintMonitor2 = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor2");
+ pInitializePrintMonitorUI = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitorUI");
+ pInitializePrintMonitor = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor");
+ pInitializeMonitorEx = (void *)GetProcAddress(pm->hdll, "InitializeMonitorEx");
+ pInitializeMonitor = (void *)GetProcAddress(pm->hdll, "InitializeMonitor");
+
+
+ TRACE("%p: %s,pInitializePrintMonitor2\n", pInitializePrintMonitor2, debugstr_w(driver));
+ TRACE("%p: %s,pInitializePrintMonitorUI\n", pInitializePrintMonitorUI, debugstr_w(driver));
+ TRACE("%p: %s,pInitializePrintMonitor\n", pInitializePrintMonitor, debugstr_w(driver));
+ TRACE("%p: %s,pInitializeMonitorEx\n", pInitializeMonitorEx, debugstr_w(driver));
+ TRACE("%p: %s,pInitializeMonitor\n", pInitializeMonitor, debugstr_w(driver));
+
+ if (pInitializePrintMonitorUI != NULL) {
+ pm->monitorUI = pInitializePrintMonitorUI();
+ TRACE("%p: MONITORUI from %s,InitializePrintMonitorUI()\n", pm->monitorUI, debugstr_w(driver));
+ if (pm->monitorUI) {
+ TRACE("0x%08x: dwMonitorSize (%d)\n",
+ pm->monitorUI->dwMonitorUISize, pm->monitorUI->dwMonitorUISize);
+
+ }
+ }
+
+ if (pInitializePrintMonitor && regroot) {
+ pmonitorEx = pInitializePrintMonitor(regroot);
+ TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n",
+ pmonitorEx, debugstr_w(driver), debugstr_w(regroot));
+
+ if (pmonitorEx) {
+ pm->dwMonitorSize = pmonitorEx->dwMonitorSize;
+ pm->monitor = &(pmonitorEx->Monitor);
+ }
+ }
+
+ if (pm->monitor) {
+ TRACE("0x%08x: dwMonitorSize (%d)\n", pm->dwMonitorSize, pm->dwMonitorSize);
+
+ }
+
+ if (!pm->monitor && regroot) {
+ if (pInitializePrintMonitor2 != NULL) {
+ FIXME("%s,InitializePrintMonitor2 not implemented\n", debugstr_w(driver));
+ }
+ if (pInitializeMonitorEx != NULL) {
+ FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver));
+ }
+ if (pInitializeMonitor != NULL) {
+ FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver));
+ }
+ }
+ if (!pm->monitor && !pm->monitorUI) {
+ monitor_unload(pm);
+ SetLastError(ERROR_PROC_NOT_FOUND);
+ pm = NULL;
+ }
+ }
+cleanup:
+ if ((pm_localport == NULL) && (pm != NULL) && (lstrcmpW(pm->name, localportW) == 0)) {
+ pm->refcount++;
+ pm_localport = pm;
+ }
+ LeaveCriticalSection(&monitor_handles_cs);
+ if (driver != dllname) heap_free(driver);
+ heap_free(regroot);
+ TRACE("=> %p\n", pm);
+ return pm;
+}
+
+/******************************************************************
+ * monitor_loadall [internal]
+ *
+ * Load all registered monitors
+ *
+ */
+static DWORD monitor_loadall(void)
+{
+ monitor_t * pm;
+ DWORD registered = 0;
+ DWORD loaded = 0;
+ HKEY hmonitors;
+ WCHAR buffer[MAX_PATH];
+ DWORD id = 0;
+
+ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hmonitors) == ERROR_SUCCESS) {
+ RegQueryInfoKeyW(hmonitors, NULL, NULL, NULL, ®istered, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+
+ TRACE("%d monitors registered\n", registered);
+
+ while (id < registered) {
+ buffer[0] = '\0';
+ RegEnumKeyW(hmonitors, id, buffer, MAX_PATH);
+ pm = monitor_load(buffer, NULL);
+ if (pm) loaded++;
+ id++;
+ }
+ RegCloseKey(hmonitors);
+ }
+ TRACE("%d monitors loaded\n", loaded);
+ return loaded;
+}
+
+/******************************************************************
+ * Return the number of bytes for an multi_sz string.
+ * The result includes all \0s
+ * (specifically the extra \0, that is needed as multi_sz terminator).
+ */
+static int multi_sz_lenW(const WCHAR *str)
+{
+ const WCHAR *ptr = str;
+ if (!str) return 0;
+ do
+ {
+ ptr += lstrlenW(ptr) + 1;
+ } while (*ptr);
+
+ return (ptr - str + 1) * sizeof(WCHAR);
+}
+
+/******************************************************************
+ * validate_envW [internal]
+ *
+ * validate the user-supplied printing-environment
+ *
+ * PARAMS
+ * env [I] PTR to Environment-String or NULL
+ *
+ * RETURNS
+ * Success: PTR to printenv_t
+ * Failure: NULL and ERROR_INVALID_ENVIRONMENT
+ *
+ * NOTES
+ * An empty string is handled the same way as NULL.
+ *
+ */
+
+static const printenv_t * validate_envW(LPCWSTR env)
+{
+ const printenv_t *result = NULL;
+ unsigned int i;
+
+ TRACE("(%s)\n", debugstr_w(env));
+ if (env && env[0])
+ {
+ for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++)
+ {
+ if (lstrcmpiW(env, all_printenv[i]->envname) == 0)
+ {
+ result = all_printenv[i];
+ break;
+ }
+ }
+ if (result == NULL) {
+ FIXME("unsupported Environment: %s\n", debugstr_w(env));
+ SetLastError(ERROR_INVALID_ENVIRONMENT);
+ }
+ /* on win9x, only "Windows 4.0" is allowed, but we ignore this */
+ }
+ else
+ {
+ result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86;
+ }
+
+ TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL));
+ return result;
+}
+
+/*****************************************************************************
+ * enumerate the local monitors (INTERNAL)
+ *
+ * returns the needed size (in bytes) for pMonitors
+ * and *lpreturned is set to number of entries returned in pMonitors
+ *
+ * Language-Monitors are also installed in the same Registry-Location but
+ * they are filtered in Windows (not returned by EnumMonitors).
+ * We do no filtering to simplify our Code.
+ *
+ */
+static DWORD get_local_monitors(DWORD level, LPBYTE pMonitors, DWORD cbBuf, LPDWORD lpreturned)
+{
+ HKEY hroot = NULL;
+ HKEY hentry = NULL;
+ LPWSTR ptr;
+ LPMONITOR_INFO_2W mi;
+ WCHAR buffer[MAX_PATH];
+ WCHAR dllname[MAX_PATH];
+ DWORD dllsize;
+ DWORD len;
+ DWORD index = 0;
+ DWORD needed = 0;
+ DWORD numentries;
+ DWORD entrysize;
+
+ entrysize = (level == 1) ? sizeof(MONITOR_INFO_1W) : sizeof(MONITOR_INFO_2W);
+
+ numentries = *lpreturned; /* this is 0, when we scan the registry */
+ len = entrysize * numentries;
+ ptr = (LPWSTR) &pMonitors[len];
+
+ numentries = 0;
+ len = sizeof(buffer)/sizeof(buffer[0]);
+ buffer[0] = '\0';
+
+ /* Windows creates the "Monitors"-Key on reboot / start "spooler" */
+ if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) == ERROR_SUCCESS) {
+ /* Scan all Monitor-Registry-Keys */
+ while (RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
+ TRACE("Monitor_%d: %s\n", numentries, debugstr_w(buffer));
+ dllsize = sizeof(dllname);
+ dllname[0] = '\0';
+
+ /* The Monitor must have a Driver-DLL */
+ if (RegOpenKeyExW(hroot, buffer, 0, KEY_READ, &hentry) == ERROR_SUCCESS) {
+ if (RegQueryValueExW(hentry, driverW, NULL, NULL, (LPBYTE) dllname, &dllsize) == ERROR_SUCCESS) {
+ /* We found a valid DLL for this Monitor. */
+ TRACE("using Driver: %s\n", debugstr_w(dllname));
+ }
+ RegCloseKey(hentry);
+ }
+
+ /* Windows returns only Port-Monitors here, but to simplify our code,
+ we do no filtering for Language-Monitors */
+ if (dllname[0]) {
+ numentries++;
+ needed += entrysize;
+ needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(monitorname) */
+ if (level > 1) {
+ /* we install and return only monitors for "Windows NT x86" */
+ needed += (lstrlenW(x86_envnameW) +1) * sizeof(WCHAR);
+ needed += dllsize;
+ }
+
+ /* required size is calculated. Now fill the user-buffer */
+ if (pMonitors && (cbBuf >= needed)){
+ mi = (LPMONITOR_INFO_2W) pMonitors;
+ pMonitors += entrysize;
+
+ TRACE("%p: writing MONITOR_INFO_%dW #%d\n", mi, level, numentries);
+ mi->pName = ptr;
+ lstrcpyW(ptr, buffer); /* Name of the Monitor */
+ ptr += (len+1); /* len is lstrlenW(monitorname) */
+ if (level > 1) {
+ mi->pEnvironment = ptr;
+ lstrcpyW(ptr, x86_envnameW); /* fixed to "Windows NT x86" */
+ ptr += (lstrlenW(x86_envnameW)+1);
+
+ mi->pDLLName = ptr;
+ lstrcpyW(ptr, dllname); /* Name of the Driver-DLL */
+ ptr += (dllsize / sizeof(WCHAR));
+ }
+ }
+ }
+ index++;
+ len = sizeof(buffer)/sizeof(buffer[0]);
+ buffer[0] = '\0';
+ }
+ RegCloseKey(hroot);
+ }
+ *lpreturned = numentries;
+ TRACE("need %d byte for %d entries\n", needed, numentries);
+ return needed;
+}
+
+/******************************************************************
+ * enumerate the local Ports from all loaded monitors (internal)
+ *
+ * returns the needed size (in bytes) for pPorts
+ * and *lpreturned is set to number of entries returned in pPorts
+ *
+ */
+static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned)
+{
+ monitor_t * pm;
+ LPWSTR ptr;
+ LPPORT_INFO_2W cache;
+ LPPORT_INFO_2W out;
+ LPBYTE pi_buffer = NULL;
+ DWORD pi_allocated = 0;
+ DWORD pi_needed;
+ DWORD pi_index;
+ DWORD pi_returned;
+ DWORD res;
+ DWORD outindex = 0;
+ DWORD needed;
+ DWORD numentries;
+ DWORD entrysize;
+
+
+ TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned);
+ entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
+
+ numentries = *lpreturned; /* this is 0, when we scan the registry */
+ needed = entrysize * numentries;
+ ptr = (LPWSTR) &pPorts[needed];
+
+ numentries = 0;
+ needed = 0;
+
+ LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry)
+ {
+ if ((pm->monitor) && (pm->monitor->pfnEnumPorts)) {
+ pi_needed = 0;
+ pi_returned = 0;
+ res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned);
+ if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
+ /* Do not use heap_realloc (we do not need the old data in the buffer) */
+ heap_free(pi_buffer);
+ pi_buffer = heap_alloc(pi_needed);
+ pi_allocated = (pi_buffer) ? pi_needed : 0;
+ res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned);
+ }
+ TRACE("(%s) got %d with %d (need %d byte for %d entries)\n",
+ debugstr_w(pm->name), res, GetLastError(), pi_needed, pi_returned);
+
+ numentries += pi_returned;
+ needed += pi_needed;
+
+ /* fill the output-buffer (pPorts), if we have one */
+ if (pPorts && (cbBuf >= needed ) && pi_buffer) {
+ pi_index = 0;
+ while (pi_returned > pi_index) {
+ cache = (LPPORT_INFO_2W) &pi_buffer[pi_index * entrysize];
+ out = (LPPORT_INFO_2W) &pPorts[outindex * entrysize];
+ out->pPortName = ptr;
+ lstrcpyW(ptr, cache->pPortName);
+ ptr += (lstrlenW(ptr)+1);
+ if (level > 1) {
+ out->pMonitorName = ptr;
+ lstrcpyW(ptr, cache->pMonitorName);
+ ptr += (lstrlenW(ptr)+1);
+
+ out->pDescription = ptr;
+ lstrcpyW(ptr, cache->pDescription);
+ ptr += (lstrlenW(ptr)+1);
+ out->fPortType = cache->fPortType;
+ out->Reserved = cache->Reserved;
+ }
+ pi_index++;
+ outindex++;
+ }
+ }
+ }
+ }
+ /* the temporary portinfo-buffer is no longer needed */
+ heap_free(pi_buffer);
+
+ *lpreturned = numentries;
+ TRACE("need %d byte for %d entries\n", needed, numentries);
+ return needed;
+}
+
+
+/*****************************************************************************
+ * open_driver_reg [internal]
+ *
+ * opens the registry for the printer drivers depending on the given input
+ * variable pEnvironment
+ *
+ * RETURNS:
+ * Success: the opened hkey
+ * Failure: NULL
+ */
+static HKEY open_driver_reg(LPCWSTR pEnvironment)
+{
+ HKEY retval = NULL;
+ LPWSTR buffer;
+ const printenv_t * env;
+
+ TRACE("(%s)\n", debugstr_w(pEnvironment));
+
+ env = validate_envW(pEnvironment);
+ if (!env) return NULL;
+
+ buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) +
+ (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR));
+
+ if (buffer) {
+ wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath);
+ RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ }
+ return retval;
+}
+
+/*****************************************************************************
+ * fpGetPrinterDriverDirectory [exported through PRINTPROVIDOR]
+ *
+ * Return the PATH for the Printer-Drivers
+ *
+ * PARAMS
+ * pName [I] Servername (NT only) or NULL (local Computer)
+ * pEnvironment [I] Printing-Environment (see below) or NULL (Default)
+ * Level [I] Structure-Level (must be 1)
+ * pDriverDirectory [O] PTR to Buffer that receives the Result
+ * cbBuf [I] Size of Buffer at pDriverDirectory
+ * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used /
+ * required for pDriverDirectory
+ *
+ * RETURNS
+ * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory
+ * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
+ * if cbBuf is too small
+ *
+ * Native Values returned in pDriverDirectory on Success:
+ *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86"
+ *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40"
+ *| win9x(Windows 4.0): "%winsysdir%"
+ *
+ * "%winsysdir%" is the Value from GetSystemDirectoryW()
+ *
+ */
+static BOOL WINAPI fpGetPrinterDriverDirectory(LPWSTR pName, LPWSTR pEnvironment,
+ DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded)
+{
+ DWORD needed;
+ const printenv_t * env;
+
+ TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName),
+ debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
+
+ if (pName != NULL && pName[0]) {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ env = validate_envW(pEnvironment);
+ if (!env) return FALSE; /* pEnvironment invalid or unsupported */
+
+
+ /* GetSystemDirectoryW returns number of WCHAR including the '\0' */
+ needed = GetSystemDirectoryW(NULL, 0);
+ /* add the Size for the Subdirectories */
+ needed += lstrlenW(spooldriversW);
+ needed += lstrlenW(env->subdir);
+ needed *= sizeof(WCHAR); /* return-value is size in Bytes */
+
+ *pcbNeeded = needed;
+
+ if (needed > cbBuf) {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ if (pDriverDirectory == NULL) {
+ /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ return FALSE;
+ }
+
+ GetSystemDirectoryW((LPWSTR) pDriverDirectory, cbBuf/sizeof(WCHAR));
+ /* add the Subdirectories */
+ lstrcatW((LPWSTR) pDriverDirectory, spooldriversW);
+ lstrcatW((LPWSTR) pDriverDirectory, env->subdir);
+
+ TRACE("=> %s\n", debugstr_w((LPWSTR) pDriverDirectory));
+ return TRUE;
+}
+
+/******************************************************************
+ * driver_load [internal]
+ *
+ * load a driver user interface dll
+ *
+ * On failure, NULL is returned
+ *
+ */
+
+static HMODULE driver_load(const printenv_t * env, LPWSTR dllname)
+{
+ WCHAR fullname[MAX_PATH];
+ HMODULE hui;
+ DWORD len;
+
+ TRACE("(%p, %s)\n", env, debugstr_w(dllname));
+
+ /* build the driverdir */
+ len = sizeof(fullname) -
+ (lstrlenW(env->versionsubdir) + 1 + lstrlenW(dllname) + 1) * sizeof(WCHAR);
+
+ if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1,
+ (LPBYTE) fullname, len, &len)) {
+ /* Should never Fail */
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return NULL;
+ }
+
+ lstrcatW(fullname, env->versionsubdir);
+ lstrcatW(fullname, backslashW);
+ lstrcatW(fullname, dllname);
+
+ hui = LoadLibraryW(fullname);
+ TRACE("%p: LoadLibrary(%s) %d\n", hui, debugstr_w(fullname), GetLastError());
+
+ return hui;
+}
+
+/******************************************************************************
+ * myAddPrinterDriverEx [internal]
+ *
+ * Install a Printer Driver with the Option to upgrade / downgrade the Files
+ * and a special mode with lazy error checking.
+ *
+ */
+static BOOL myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy)
+{
+ static const WCHAR emptyW[1];
+ const printenv_t *env;
+ apd_data_t apd;
+ DRIVER_INFO_8W di;
+ BOOL (WINAPI *pDrvDriverEvent)(DWORD, DWORD, LPBYTE, LPARAM);
+ HMODULE hui;
+ LPWSTR ptr;
+ HKEY hroot;
+ HKEY hdrv;
+ DWORD disposition;
+ DWORD len;
+ LONG lres;
+ BOOL res;
+
+ /* we need to set all entries in the Registry, independent from the Level of
+ DRIVER_INFO, that the caller supplied */
+
+ ZeroMemory(&di, sizeof(di));
+ if (pDriverInfo && (level < (sizeof(di_sizeof) / sizeof(di_sizeof[0])))) {
+ memcpy(&di, pDriverInfo, di_sizeof[level]);
+ }
+
+ /* dump the most used infos */
+ TRACE("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion);
+ TRACE("%p: .pName : %s\n", di.pName, debugstr_w(di.pName));
+ TRACE("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment));
+ TRACE("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath));
+ TRACE("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile));
+ TRACE("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile));
+ TRACE("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile));
+ /* dump only the first of the additional Files */
+ TRACE("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles));
+
+
+ /* check environment */
+ env = validate_envW(di.pEnvironment);
+ if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */
+
+ /* fill the copy-data / get the driverdir */
+ len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR);
+ if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1,
+ (LPBYTE) apd.src, len, &len)) {
+ /* Should never Fail */
+ return FALSE;
+ }
+ memcpy(apd.dst, apd.src, len);
+ lstrcatW(apd.src, backslashW);
+ apd.srclen = lstrlenW(apd.src);
+ lstrcatW(apd.dst, env->versionsubdir);
+ lstrcatW(apd.dst, backslashW);
+ apd.dstlen = lstrlenW(apd.dst);
+ apd.copyflags = dwFileCopyFlags;
+ apd.lazy = lazy;
+ CreateDirectoryW(apd.src, NULL);
+ CreateDirectoryW(apd.dst, NULL);
+
+ hroot = open_driver_reg(env->envname);
+ if (!hroot) {
+ ERR("Can't create Drivers key\n");
+ return FALSE;
+ }
+
+ /* Fill the Registry for the Driver */
+ if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_WRITE | KEY_QUERY_VALUE, NULL,
+ &hdrv, &disposition)) != ERROR_SUCCESS) {
+
+ ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres);
+ RegCloseKey(hroot);
+ SetLastError(lres);
+ return FALSE;
+ }
+ RegCloseKey(hroot);
+
+ if (disposition == REG_OPENED_EXISTING_KEY) {
+ TRACE("driver %s already installed\n", debugstr_w(di.pName));
+ RegCloseKey(hdrv);
+ SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
+ return FALSE;
+ }
+
+ /* Verified with the Adobe PS Driver, that w2k does not use di.Version */
+ RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (LPBYTE) &env->driverversion,
+ sizeof(DWORD));
+
+ RegSetValueExW(hdrv, driverW, 0, REG_SZ, (LPBYTE) di.pDriverPath,
+ (lstrlenW(di.pDriverPath)+1)* sizeof(WCHAR));
+ apd_copyfile(di.pDriverPath, &apd);
+
+ RegSetValueExW(hdrv, data_fileW, 0, REG_SZ, (LPBYTE) di.pDataFile,
+ (lstrlenW(di.pDataFile)+1)* sizeof(WCHAR));
+ apd_copyfile(di.pDataFile, &apd);
+
+ RegSetValueExW(hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE) di.pConfigFile,
+ (lstrlenW(di.pConfigFile)+1)* sizeof(WCHAR));
+ apd_copyfile(di.pConfigFile, &apd);
+
+ /* settings for level 3 */
+ if (di.pHelpFile)
+ RegSetValueExW(hdrv, help_fileW, 0, REG_SZ, (LPBYTE) di.pHelpFile,
+ (lstrlenW(di.pHelpFile)+1)* sizeof(WCHAR));
+ else
+ RegSetValueExW(hdrv, help_fileW, 0, REG_SZ, (LPBYTE)emptyW, sizeof(emptyW));
+ apd_copyfile(di.pHelpFile, &apd);
+
+
+ ptr = di.pDependentFiles;
+ if (ptr)
+ RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE) di.pDependentFiles,
+ multi_sz_lenW(di.pDependentFiles));
+ else
+ RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE)emptyW, sizeof(emptyW));
+ while ((ptr != NULL) && (ptr[0])) {
+ if (apd_copyfile(ptr, &apd)) {
+ ptr += lstrlenW(ptr) + 1;
+ }
+ else
+ {
+ WARN("Failed to copy %s\n", debugstr_w(ptr));
+ ptr = NULL;
+ }
+ }
+ /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */
+ if (di.pMonitorName)
+ RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName,
+ (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR));
+ else
+ RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE)emptyW, sizeof(emptyW));
+
+ if (di.pDefaultDataType)
+ RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType,
+ (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR));
+ else
+ RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE)emptyW, sizeof(emptyW));
+
+ /* settings for level 4 */
+ if (di.pszzPreviousNames)
+ RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames,
+ multi_sz_lenW(di.pszzPreviousNames));
+ else
+ RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE)emptyW, sizeof(emptyW));
+
+ if (level > 5) TRACE("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName));
+
+ RegCloseKey(hdrv);
+ hui = driver_load(env, di.pConfigFile);
+ pDrvDriverEvent = (void *)GetProcAddress(hui, "DrvDriverEvent");
+ if (hui && pDrvDriverEvent) {
+
+ /* Support for DrvDriverEvent is optional */
+ TRACE("DRIVER_EVENT_INITIALIZE for %s (%s)\n", debugstr_w(di.pName), debugstr_w(di.pConfigFile));
+ /* MSDN: level for DRIVER_INFO is 1 to 3 */
+ res = pDrvDriverEvent(DRIVER_EVENT_INITIALIZE, 3, (LPBYTE) &di, 0);
+ TRACE("got %d from DRIVER_EVENT_INITIALIZE\n", res);
+ }
+ FreeLibrary(hui);
+
+ TRACE("=> TRUE with %u\n", GetLastError());
+ return TRUE;
+
+}
+
+/******************************************************************************
+ * fpAddMonitor [exported through PRINTPROVIDOR]
+ *
+ * Install a Printmonitor
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * Level [I] Structure-Level (Must be 2)
+ * pMonitors [I] PTR to MONITOR_INFO_2
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
+ *
+ */
+static BOOL WINAPI fpAddMonitor(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
+{
+ monitor_t * pm = NULL;
+ LPMONITOR_INFO_2W mi2w;
+ HKEY hroot = NULL;
+ HKEY hentry = NULL;
+ DWORD disposition;
+ BOOL res = FALSE;
+
+ mi2w = (LPMONITOR_INFO_2W) pMonitors;
+ TRACE("(%s, %d, %p): %s %s %s\n", debugstr_w(pName), Level, pMonitors,
+ debugstr_w(mi2w ? mi2w->pName : NULL),
+ debugstr_w(mi2w ? mi2w->pEnvironment : NULL),
+ debugstr_w(mi2w ? mi2w->pDLLName : NULL));
+
+ if (copy_servername_from_name(pName, NULL)) {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ if (!mi2w->pName || (! mi2w->pName[0])) {
+ WARN("pName not valid : %s\n", debugstr_w(mi2w->pName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (!mi2w->pEnvironment || lstrcmpW(mi2w->pEnvironment, x86_envnameW)) {
+ WARN("Environment %s requested (we support only %s)\n",
+ debugstr_w(mi2w->pEnvironment), debugstr_w(x86_envnameW));
+ SetLastError(ERROR_INVALID_ENVIRONMENT);
+ return FALSE;
+ }
+
+ if (!mi2w->pDLLName || (! mi2w->pDLLName[0])) {
+ WARN("pDLLName not valid : %s\n", debugstr_w(mi2w->pDLLName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* Load and initialize the monitor. SetLastError() is called on failure */
+ if ((pm = monitor_load(mi2w->pName, mi2w->pDLLName)) == NULL) {
+ return FALSE;
+ }
+ monitor_unload(pm);
+
+ if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) {
+ ERR("unable to create key %s\n", debugstr_w(monitorsW));
+ return FALSE;
+ }
+
+ if (RegCreateKeyExW(hroot, mi2w->pName, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_WRITE | KEY_QUERY_VALUE, NULL, &hentry,
+ &disposition) == ERROR_SUCCESS) {
+
+ /* Some installers set options for the port before calling AddMonitor.
+ We query the "Driver" entry to verify that the monitor is installed,
+ before we return an error.
+ When a user installs two print monitors at the same time with the
+ same name, a race condition is possible but silently ignored. */
+
+ DWORD namesize = 0;
+
+ if ((disposition == REG_OPENED_EXISTING_KEY) &&
+ (RegQueryValueExW(hentry, driverW, NULL, NULL, NULL,
+ &namesize) == ERROR_SUCCESS)) {
+ TRACE("monitor %s already exists\n", debugstr_w(mi2w->pName));
+ /* 9x use ERROR_ALREADY_EXISTS */
+ SetLastError(ERROR_PRINT_MONITOR_ALREADY_INSTALLED);
+ }
+ else
+ {
+ INT len;
+ len = (lstrlenW(mi2w->pDLLName) +1) * sizeof(WCHAR);
+ res = (RegSetValueExW(hentry, driverW, 0, REG_SZ,
+ (LPBYTE) mi2w->pDLLName, len) == ERROR_SUCCESS);
+ }
+ RegCloseKey(hentry);
+ }
+
+ RegCloseKey(hroot);
+ return (res);
+}
+
+/******************************************************************************
+ * fpAddPrinterDriverEx [exported through PRINTPROVIDOR]
+ *
+ * Install a Printer Driver with the Option to upgrade / downgrade the Files
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * level [I] Level for the supplied DRIVER_INFO_*W struct
+ * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
+ * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
+ *
+ * RESULTS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
+{
+ LONG lres;
+
+ TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
+ lres = copy_servername_from_name(pName, NULL);
+ if (lres) {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES) {
+ TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY);
+ }
+
+ return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE);
+}
+/******************************************************************
+ * fpDeleteMonitor [exported through PRINTPROVIDOR]
+ *
+ * Delete a specific Printmonitor from a Printing-Environment
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default)
+ * pMonitorName [I] Name of the Monitor, that should be deleted
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * pEnvironment is ignored in Windows for the local Computer.
+ *
+ */
+
+static BOOL WINAPI fpDeleteMonitor(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName)
+{
+ HKEY hroot = NULL;
+ LONG lres;
+
+ TRACE("(%s, %s, %s)\n",debugstr_w(pName),debugstr_w(pEnvironment),
+ debugstr_w(pMonitorName));
+
+ lres = copy_servername_from_name(pName, NULL);
+ if (lres) {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_INVALID_NAME);
+ return FALSE;
+ }
+
+ /* pEnvironment is ignored in Windows for the local Computer */
+ if (!pMonitorName || !pMonitorName[0]) {
+ TRACE("pMonitorName %s is invalid\n", debugstr_w(pMonitorName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if(RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) {
+ ERR("unable to create key %s\n", debugstr_w(monitorsW));
+ return FALSE;
+ }
+
+ if(RegDeleteTreeW(hroot, pMonitorName) == ERROR_SUCCESS) {
+ TRACE("%s deleted\n", debugstr_w(pMonitorName));
+ RegCloseKey(hroot);
+ return TRUE;
+ }
+
+ TRACE("%s does not exist\n", debugstr_w(pMonitorName));
+ RegCloseKey(hroot);
+
+ /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */
+ SetLastError(ERROR_UNKNOWN_PRINT_MONITOR);
+ return FALSE;
+}
+
+/*****************************************************************************
+ * fpEnumMonitors [exported through PRINTPROVIDOR]
+ *
+ * Enumerate available Port-Monitors
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * Level [I] Structure-Level (1:Win9x+NT or 2:NT only)
+ * pMonitors [O] PTR to Buffer that receives the Result
+ * cbBuf [I] Size of Buffer at pMonitors
+ * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors
+ * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small
+ *
+ * NOTES
+ * Windows reads the Registry once and cache the Results.
+ *
+ */
+static BOOL WINAPI fpEnumMonitors(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf,
+ LPDWORD pcbNeeded, LPDWORD pcReturned)
+{
+ DWORD numentries = 0;
+ DWORD needed = 0;
+ LONG lres;
+ BOOL res = FALSE;
+
+ TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors,
+ cbBuf, pcbNeeded, pcReturned);
+
+ lres = copy_servername_from_name(pName, NULL);
+ if (lres) {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_INVALID_NAME);
+ goto em_cleanup;
+ }
+
+ if (!Level || (Level > 2)) {
+ WARN("level (%d) is ignored in win9x\n", Level);
+ SetLastError(ERROR_INVALID_LEVEL);
+ return FALSE;
+ }
+
+ /* Scan all Monitor-Keys */
+ numentries = 0;
+ needed = get_local_monitors(Level, NULL, 0, &numentries);
+
+ /* we calculated the needed buffersize. now do more error-checks */
+ if (cbBuf < needed) {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto em_cleanup;
+ }
+
+ /* fill the Buffer with the Monitor-Keys */
+ needed = get_local_monitors(Level, pMonitors, cbBuf, &numentries);
+ res = TRUE;
+
+em_cleanup:
+ if (pcbNeeded) *pcbNeeded = needed;
+ if (pcReturned) *pcReturned = numentries;
+
+ TRACE("returning %d with %d (%d byte for %d entries)\n",
+ res, GetLastError(), needed, numentries);
+
+ return (res);
+}
+
+/******************************************************************************
+ * fpEnumPorts [exported through PRINTPROVIDOR]
+ *
+ * Enumerate available Ports
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * Level [I] Structure-Level (1 or 2)
+ * pPorts [O] PTR to Buffer that receives the Result
+ * cbBuf [I] Size of Buffer at pPorts
+ * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
+ * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
+ *
+ */
+static BOOL WINAPI fpEnumPorts(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,
+ LPDWORD pcbNeeded, LPDWORD pcReturned)
+{
+ DWORD needed = 0;
+ DWORD numentries = 0;
+ LONG lres;
+ BOOL res = FALSE;
+
+ TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts,
+ cbBuf, pcbNeeded, pcReturned);
+
+ lres = copy_servername_from_name(pName, NULL);
+ if (lres) {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_INVALID_NAME);
+ goto emP_cleanup;
+ }
+
+ if (!Level || (Level > 2)) {
+ SetLastError(ERROR_INVALID_LEVEL);
+ goto emP_cleanup;
+ }
+
+ if (!pcbNeeded || (!pPorts && (cbBuf > 0))) {
+ SetLastError(RPC_X_NULL_REF_POINTER);
+ goto emP_cleanup;
+ }
+
+ EnterCriticalSection(&monitor_handles_cs);
+ monitor_loadall();
+
+ /* Scan all local Ports */
+ numentries = 0;
+ needed = get_ports_from_all_monitors(Level, NULL, 0, &numentries);
+
+ /* we calculated the needed buffersize. now do the error-checks */
+ if (cbBuf < needed) {
+ monitor_unloadall();
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto emP_cleanup_cs;
+ }
+ else if (!pPorts || !pcReturned) {
+ monitor_unloadall();
+ SetLastError(RPC_X_NULL_REF_POINTER);
+ goto emP_cleanup_cs;
+ }
+
+ /* Fill the Buffer */
+ needed = get_ports_from_all_monitors(Level, pPorts, cbBuf, &numentries);
+ res = TRUE;
+ monitor_unloadall();
+
+emP_cleanup_cs:
+ LeaveCriticalSection(&monitor_handles_cs);
+
+emP_cleanup:
+ if (pcbNeeded) *pcbNeeded = needed;
+ if (pcReturned) *pcReturned = (res) ? numentries : 0;
+
+ TRACE("returning %d with %d (%d byte for %d of %d entries)\n",
+ (res), GetLastError(), needed, (res) ? numentries : 0, numentries);
+
+ return (res);
+}
+
+/*****************************************************
+ * setup_provider [internal]
+ */
+void setup_provider(void)
+{
+ static const PRINTPROVIDOR backend = {
+ NULL, /* fpOpenPrinter */
+ NULL, /* fpSetJob */
+ NULL, /* fpGetJob */
+ NULL, /* fpEnumJobs */
+ NULL, /* fpAddPrinter */
+ NULL, /* fpDeletePrinter */
+ NULL, /* fpSetPrinter */
+ NULL, /* fpGetPrinter */
+ NULL, /* fpEnumPrinters */
+ NULL, /* fpAddPrinterDriver */
+ NULL, /* fpEnumPrinterDrivers */
+ NULL, /* fpGetPrinterDriver */
+ fpGetPrinterDriverDirectory,
+ NULL, /* fpDeletePrinterDriver */
+ NULL, /* fpAddPrintProcessor */
+ NULL, /* fpEnumPrintProcessors */
+ NULL, /* fpGetPrintProcessorDirectory */
+ NULL, /* fpDeletePrintProcessor */
+ NULL, /* fpEnumPrintProcessorDatatypes */
+ NULL, /* fpStartDocPrinter */
+ NULL, /* fpStartPagePrinter */
+ NULL, /* fpWritePrinter */
+ NULL, /* fpEndPagePrinter */
+ NULL, /* fpAbortPrinter */
+ NULL, /* fpReadPrinter */
+ NULL, /* fpEndDocPrinter */
+ NULL, /* fpAddJob */
+ NULL, /* fpScheduleJob */
+ NULL, /* fpGetPrinterData */
+ NULL, /* fpSetPrinterData */
+ NULL, /* fpWaitForPrinterChange */
+ NULL, /* fpClosePrinter */
+ NULL, /* fpAddForm */
+ NULL, /* fpDeleteForm */
+ NULL, /* fpGetForm */
+ NULL, /* fpSetForm */
+ NULL, /* fpEnumForms */
+ fpEnumMonitors,
+ fpEnumPorts,
+ NULL, /* fpAddPort */
+ NULL, /* fpConfigurePort */
+ NULL, /* fpDeletePort */
+ NULL, /* fpCreatePrinterIC */
+ NULL, /* fpPlayGdiScriptOnPrinterIC */
+ NULL, /* fpDeletePrinterIC */
+ NULL, /* fpAddPrinterConnection */
+ NULL, /* fpDeletePrinterConnection */
+ NULL, /* fpPrinterMessageBox */
+ fpAddMonitor,
+ fpDeleteMonitor,
+ NULL, /* fpResetPrinter */
+ NULL, /* fpGetPrinterDriverEx */
+ NULL, /* fpFindFirstPrinterChangeNotification */
+ NULL, /* fpFindClosePrinterChangeNotification */
+ NULL, /* fpAddPortEx */
+ NULL, /* fpShutDown */
+ NULL, /* fpRefreshPrinterChangeNotification */
+ NULL, /* fpOpenPrinterEx */
+ NULL, /* fpAddPrinterEx */
+ NULL, /* fpSetPort */
+ NULL, /* fpEnumPrinterData */
+ NULL, /* fpDeletePrinterData */
+ NULL, /* fpClusterSplOpen */
+ NULL, /* fpClusterSplClose */
+ NULL, /* fpClusterSplIsAlive */
+ NULL, /* fpSetPrinterDataEx */
+ NULL, /* fpGetPrinterDataEx */
+ NULL, /* fpEnumPrinterDataEx */
+ NULL, /* fpEnumPrinterKey */
+ NULL, /* fpDeletePrinterDataEx */
+ NULL, /* fpDeletePrinterKey */
+ NULL, /* fpSeekPrinter */
+ NULL, /* fpDeletePrinterDriverEx */
+ NULL, /* fpAddPerMachineConnection */
+ NULL, /* fpDeletePerMachineConnection */
+ NULL, /* fpEnumPerMachineConnections */
+ NULL, /* fpXcvData */
+ fpAddPrinterDriverEx,
+ NULL, /* fpSplReadPrinter */
+ NULL, /* fpDriverUnloadComplete */
+ NULL, /* fpGetSpoolFileInfo */
+ NULL, /* fpCommitSpoolData */
+ NULL, /* fpCloseSpoolFileHandle */
+ NULL, /* fpFlushPrinter */
+ NULL, /* fpSendRecvBidiData */
+ NULL /* fpAddDriverCatalog */
+ };
+ pprovider = &backend;
+
+}
+
+/*****************************************************
+ * InitializePrintProvidor (localspl.@)
+ *
+ * Initialize the Printprovider
+ *
+ * PARAMS
+ * pPrintProvidor [I] Buffer to fill with a struct PRINTPROVIDOR
+ * cbPrintProvidor [I] Size of Buffer in Bytes
+ * pFullRegistryPath [I] Registry-Path for the Printprovidor
+ *
+ * RETURNS
+ * Success: TRUE and pPrintProvidor filled
+ * Failure: FALSE
+ *
+ * NOTES
+ * The RegistryPath should be:
+ * "System\CurrentControlSet\Control\Print\Providers\",
+ * but this Parameter is ignored in "localspl.dll".
+ *
+ */
+
+BOOL WINAPI InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor,
+ DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
+{
+
+ TRACE("(%p, %u, %s)\n", pPrintProvidor, cbPrintProvidor, debugstr_w(pFullRegistryPath));
+ memcpy(pPrintProvidor, pprovider,
+ (cbPrintProvidor < sizeof(PRINTPROVIDOR)) ? cbPrintProvidor : sizeof(PRINTPROVIDOR));
+
+ return TRUE;
+}
diff --git a/reactos/dll/win32/localspl/spl_Da.rc b/reactos/dll/win32/localspl/spl_Da.rc
new file mode 100644
index 00000000000..a149cabc20a
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Da.rc
@@ -0,0 +1,27 @@
+/*
+ * Danish resources for localspl
+ *
+ * Copyright 2008 Jens Albretsen
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+ LANGUAGE LANG_DANISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Lokal port"
+ IDS_LOCALMONITOR "Lokal overvger"
+}
diff --git a/reactos/dll/win32/localspl/spl_De.rc b/reactos/dll/win32/localspl/spl_De.rc
new file mode 100644
index 00000000000..4c95e2bcfa5
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_De.rc
@@ -0,0 +1,28 @@
+/*
+ * German resources for localspl
+ *
+ * Copyright 2005 Henning Gerhardt
+ * Copyright 2006 Detlef Riekenberg
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Lokaler Anschluss"
+ IDS_LOCALMONITOR "Lokaler Monitor"
+}
diff --git a/reactos/dll/win32/localspl/spl_En.rc b/reactos/dll/win32/localspl/spl_En.rc
new file mode 100644
index 00000000000..c9d12f4f16a
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_En.rc
@@ -0,0 +1,28 @@
+/*
+ * English resources for localspl
+ *
+ * Copyright 2005 Huw Davies
+ * Copyright 2006 Detlef Riekenberg
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Local Port"
+ IDS_LOCALMONITOR "Local Monitor"
+}
diff --git a/reactos/dll/win32/localspl/spl_Fr.rc b/reactos/dll/win32/localspl/spl_Fr.rc
new file mode 100644
index 00000000000..95269727162
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Fr.rc
@@ -0,0 +1,27 @@
+/*
+ * French resources for localspl
+ *
+ * Copyright 2007 Jonathan Ernst
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Port local"
+ IDS_LOCALMONITOR "Moniteur local"
+}
diff --git a/reactos/dll/win32/localspl/spl_Ko.rc b/reactos/dll/win32/localspl/spl_Ko.rc
new file mode 100644
index 00000000000..fe2d5720a56
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Ko.rc
@@ -0,0 +1,29 @@
+/*
+ * Korean resources for localspl
+ *
+ * Copyright 2005 Huw Davies
+ * Copyright 2006 Detlef Riekenberg
+ * Copyright 2006 YunSong Hwang
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT " Ʈ"
+ IDS_LOCALMONITOR " "
+}
diff --git a/reactos/dll/win32/localspl/spl_Nl.rc b/reactos/dll/win32/localspl/spl_Nl.rc
new file mode 100644
index 00000000000..b9d4c5ca608
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Nl.rc
@@ -0,0 +1,27 @@
+/*
+ * Dutch resources for localspl
+ *
+ * Copyright 2008 Frans Kool
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Lokale Poort"
+ IDS_LOCALMONITOR "Lokale Monitor"
+}
diff --git a/reactos/dll/win32/localspl/spl_No.rc b/reactos/dll/win32/localspl/spl_No.rc
new file mode 100644
index 00000000000..5efa5631e9b
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_No.rc
@@ -0,0 +1,27 @@
+/*
+ * Norwegian Bokml resources for localspl
+ *
+ * Copyright 2006 Alexander N. Srnes
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Lokal port"
+ IDS_LOCALMONITOR "Lokal overvker"
+}
diff --git a/reactos/dll/win32/localspl/spl_Pl.rc b/reactos/dll/win32/localspl/spl_Pl.rc
new file mode 100644
index 00000000000..a0802088666
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Pl.rc
@@ -0,0 +1,29 @@
+/*
+ * Polish resources for localspl
+ *
+ * Copyright 2005 Huw Davies
+ * Copyright 2006 Detlef Riekenberg
+ * Copyright 2007 Mikolaj Zalewski
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Port lokalny"
+ IDS_LOCALMONITOR "Monitor lokalny"
+}
diff --git a/reactos/dll/win32/localspl/spl_Pt.rc b/reactos/dll/win32/localspl/spl_Pt.rc
new file mode 100644
index 00000000000..8ec66c55f36
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Pt.rc
@@ -0,0 +1,27 @@
+/*
+ * Portuguese resources for localspl
+ *
+ * Copyright 2008 Ricardo Filipe
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Porta local"
+ IDS_LOCALMONITOR "Monitor Local"
+}
diff --git a/reactos/dll/win32/localspl/spl_Ro.rc b/reactos/dll/win32/localspl/spl_Ro.rc
new file mode 100644
index 00000000000..44321957313
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Ro.rc
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2005 Huw Davies
+ * Copyright 2006 Detlef Riekenberg
+ * Copyright 2008 Michael Stefaniuc
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Port local"
+ IDS_LOCALMONITOR "Monitor local"
+}
diff --git a/reactos/dll/win32/localspl/spl_Ru.rc b/reactos/dll/win32/localspl/spl_Ru.rc
new file mode 100644
index 00000000000..1ee1e2f327b
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Ru.rc
@@ -0,0 +1,27 @@
+/*
+ * Russian resources for localspl
+ *
+ * Copyright 2008 Vitaliy Margolen
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT " "
+ IDS_LOCALMONITOR " "
+}
diff --git a/reactos/dll/win32/localspl/spl_Si.rc b/reactos/dll/win32/localspl/spl_Si.rc
new file mode 100644
index 00000000000..66ca2c4ce76
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Si.rc
@@ -0,0 +1,31 @@
+/*
+ * Slovenian resources for localspl
+ *
+ * Copyright 2008 Rok Mandeljc
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma code_page(65001)
+
+LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Lokalna vrata"
+ IDS_LOCALMONITOR "Lokalen monitor"
+}
+
+#pragma code_page(default)
diff --git a/reactos/dll/win32/localspl/spl_Sv.rc b/reactos/dll/win32/localspl/spl_Sv.rc
new file mode 100644
index 00000000000..fca0d6b0835
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Sv.rc
@@ -0,0 +1,27 @@
+/*
+ * English resources for localspl
+ *
+ * Copyright 2007 Daniel Nylander
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "Lokal port"
+ IDS_LOCALMONITOR "Lokal skrm"
+}
diff --git a/reactos/dll/win32/localspl/spl_Zh.rc b/reactos/dll/win32/localspl/spl_Zh.rc
new file mode 100644
index 00000000000..c5db382ffe3
--- /dev/null
+++ b/reactos/dll/win32/localspl/spl_Zh.rc
@@ -0,0 +1,40 @@
+/*
+ * localspl (Simplified and Traditional Chinese Resources)
+ *
+ * Copyright 2008 Hongbo Ni
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/* Chinese text is encoded in UTF-8 */
+#pragma code_page(65001)
+
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "本地端口"
+ IDS_LOCALMONITOR "本地监视器"
+}
+
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_LOCALPORT "本地端口"
+ IDS_LOCALMONITOR "本地監視器"
+}
+
+#pragma code_page(default)
diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild
index 17cb60f4dd1..f8d4f00deb1 100644
--- a/reactos/dll/win32/win32.rbuild
+++ b/reactos/dll/win32/win32.rbuild
@@ -139,6 +139,9 @@
+
+
+
@@ -154,6 +157,9 @@
+
+
+
@@ -523,4 +529,7 @@
+
+
+
diff --git a/reactos/dll/win32/wuapi/downloader.c b/reactos/dll/win32/wuapi/downloader.c
new file mode 100644
index 00000000000..72929661df5
--- /dev/null
+++ b/reactos/dll/win32/wuapi/downloader.c
@@ -0,0 +1,267 @@
+/*
+ * IUpdateDownloader implementation
+ *
+ * Copyright 2008 Hans Leidekker
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "initguid.h"
+#include "wuapi.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wuapi);
+
+typedef struct _update_downloader
+{
+ const struct IUpdateDownloaderVtbl *vtbl;
+ LONG refs;
+} update_downloader;
+
+static inline update_downloader *impl_from_IUpdateDownloader( IUpdateDownloader *iface )
+{
+ return (update_downloader *)((char *)iface - FIELD_OFFSET( update_downloader, vtbl ));
+}
+
+static ULONG WINAPI update_downloader_AddRef(
+ IUpdateDownloader *iface )
+{
+ update_downloader *update_downloader = impl_from_IUpdateDownloader( iface );
+ return InterlockedIncrement( &update_downloader->refs );
+}
+
+static ULONG WINAPI update_downloader_Release(
+ IUpdateDownloader *iface )
+{
+ update_downloader *update_downloader = impl_from_IUpdateDownloader( iface );
+ LONG refs = InterlockedDecrement( &update_downloader->refs );
+ if (!refs)
+ {
+ TRACE("destroying %p\n", update_downloader);
+ HeapFree( GetProcessHeap(), 0, update_downloader );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI update_downloader_QueryInterface(
+ IUpdateDownloader *iface,
+ REFIID riid,
+ void **ppvObject )
+{
+ update_downloader *This = impl_from_IUpdateDownloader( iface );
+
+ TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
+
+ if ( IsEqualGUID( riid, &IID_IUpdateDownloader ) ||
+ IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+ IUpdateDownloader_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI update_downloader_GetTypeInfoCount(
+ IUpdateDownloader *iface,
+ UINT *pctinfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_GetTypeInfo(
+ IUpdateDownloader *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo **ppTInfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_GetIDsOfNames(
+ IUpdateDownloader *iface,
+ REFIID riid,
+ LPOLESTR *rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID *rgDispId )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_Invoke(
+ IUpdateDownloader *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_get_IsForced(
+ IUpdateDownloader *This,
+ VARIANT_BOOL *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_put_IsForced(
+ IUpdateDownloader *This,
+ VARIANT_BOOL value )
+{
+ FIXME("%p, %d\n", This, value);
+ return S_OK;
+}
+
+static HRESULT WINAPI update_downloader_get_ClientApplicationID(
+ IUpdateDownloader *This,
+ BSTR *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_put_ClientApplicationID(
+ IUpdateDownloader *This,
+ BSTR value )
+{
+ FIXME("%p, %s\n", This, debugstr_w(value));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_get_Priority(
+ IUpdateDownloader *This,
+ DownloadPriority *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_put_Priority(
+ IUpdateDownloader *This,
+ DownloadPriority value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_get_Updates(
+ IUpdateDownloader *This,
+ IUpdateCollection **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_put_Updates(
+ IUpdateDownloader *This,
+ IUpdateCollection *value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_BeginDownload(
+ IUpdateDownloader *This,
+ IUnknown *onProgressChanged,
+ IUnknown *onCompleted,
+ VARIANT state,
+ IDownloadJob **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_Download(
+ IUpdateDownloader *This,
+ IDownloadResult **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_downloader_EndDownload(
+ IUpdateDownloader *This,
+ IDownloadJob *value,
+ IDownloadResult **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static const struct IUpdateDownloaderVtbl update_downloader_vtbl =
+{
+ update_downloader_QueryInterface,
+ update_downloader_AddRef,
+ update_downloader_Release,
+ update_downloader_GetTypeInfoCount,
+ update_downloader_GetTypeInfo,
+ update_downloader_GetIDsOfNames,
+ update_downloader_Invoke,
+ update_downloader_get_ClientApplicationID,
+ update_downloader_put_ClientApplicationID,
+ update_downloader_get_IsForced,
+ update_downloader_put_IsForced,
+ update_downloader_get_Priority,
+ update_downloader_put_Priority,
+ update_downloader_get_Updates,
+ update_downloader_put_Updates,
+ update_downloader_BeginDownload,
+ update_downloader_Download,
+ update_downloader_EndDownload
+};
+
+HRESULT UpdateDownloader_create( IUnknown *pUnkOuter, LPVOID *ppObj )
+{
+ update_downloader *downloader;
+
+ TRACE("(%p,%p)\n", pUnkOuter, ppObj);
+
+ downloader = HeapAlloc( GetProcessHeap(), 0, sizeof(*downloader) );
+ if (!downloader) return E_OUTOFMEMORY;
+
+ downloader->vtbl = &update_downloader_vtbl;
+ downloader->refs = 1;
+
+ *ppObj = &downloader->vtbl;
+
+ TRACE("returning iface %p\n", *ppObj);
+ return S_OK;
+}
diff --git a/reactos/dll/win32/wuapi/installer.c b/reactos/dll/win32/wuapi/installer.c
new file mode 100644
index 00000000000..1a2c5530a24
--- /dev/null
+++ b/reactos/dll/win32/wuapi/installer.c
@@ -0,0 +1,253 @@
+/*
+ * IUpdateInstaller implementation
+ *
+ * Copyright 2008 Hans Leidekker
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "wuapi.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wuapi);
+
+typedef struct _update_installer
+{
+ const struct IUpdateInstallerVtbl *vtbl;
+ LONG refs;
+} update_installer;
+
+static inline update_installer *impl_from_IUpdateInstaller( IUpdateInstaller *iface )
+{
+ return (update_installer *)((char *)iface - FIELD_OFFSET( update_installer, vtbl ));
+}
+
+static ULONG WINAPI update_installer_AddRef(
+ IUpdateInstaller *iface )
+{
+ update_installer *update_installer = impl_from_IUpdateInstaller( iface );
+ return InterlockedIncrement( &update_installer->refs );
+}
+
+static ULONG WINAPI update_installer_Release(
+ IUpdateInstaller *iface )
+{
+ update_installer *update_installer = impl_from_IUpdateInstaller( iface );
+ LONG refs = InterlockedDecrement( &update_installer->refs );
+ if (!refs)
+ {
+ TRACE("destroying %p\n", update_installer);
+ HeapFree( GetProcessHeap(), 0, update_installer );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI update_installer_QueryInterface(
+ IUpdateInstaller *iface,
+ REFIID riid,
+ void **ppvObject )
+{
+ update_installer *This = impl_from_IUpdateInstaller( iface );
+
+ TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
+
+ if ( IsEqualGUID( riid, &IID_IUpdateInstaller ) ||
+ IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+ IUpdateInstaller_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI update_installer_GetTypeInfoCount(
+ IUpdateInstaller *iface,
+ UINT *pctinfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_GetTypeInfo(
+ IUpdateInstaller *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo **ppTInfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_GetIDsOfNames(
+ IUpdateInstaller *iface,
+ REFIID riid,
+ LPOLESTR *rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID *rgDispId )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_Invoke(
+ IUpdateInstaller *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_get_ClientApplicationID(
+ IUpdateInstaller *This,
+ BSTR *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_put_ClientApplicationID(
+ IUpdateInstaller *This,
+ BSTR value )
+{
+ FIXME("%p, %s\n", This, debugstr_w(value));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_get_IsForced(
+ IUpdateInstaller *This,
+ VARIANT_BOOL *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_put_IsForced(
+ IUpdateInstaller *This,
+ VARIANT_BOOL value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_get_ParentHwnd(
+ IUpdateInstaller *This,
+ HWND *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_put_ParentHwnd(
+ IUpdateInstaller *This,
+ HWND value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_put_ParentWindow(
+ IUpdateInstaller *This,
+ IUnknown *value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_get_ParentWindow(
+ IUpdateInstaller *This,
+ IUnknown **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_get_Updates(
+ IUpdateInstaller *This,
+ IUpdateCollection **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_installer_put_Updates(
+ IUpdateInstaller *This,
+ IUpdateCollection *value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static const struct IUpdateInstallerVtbl update_installer_vtbl =
+{
+ update_installer_QueryInterface,
+ update_installer_AddRef,
+ update_installer_Release,
+ update_installer_GetTypeInfoCount,
+ update_installer_GetTypeInfo,
+ update_installer_GetIDsOfNames,
+ update_installer_Invoke,
+ update_installer_get_ClientApplicationID,
+ update_installer_put_ClientApplicationID,
+ update_installer_get_IsForced,
+ update_installer_put_IsForced,
+ update_installer_get_ParentHwnd,
+ update_installer_put_ParentHwnd,
+ update_installer_put_ParentWindow,
+ update_installer_get_ParentWindow,
+ update_installer_get_Updates,
+ update_installer_put_Updates,
+};
+
+HRESULT UpdateInstaller_create( IUnknown *pUnkOuter, LPVOID *ppObj )
+{
+ update_installer *installer;
+
+ TRACE("(%p,%p)\n", pUnkOuter, ppObj);
+
+ installer = HeapAlloc( GetProcessHeap(), 0, sizeof(*installer) );
+ if (!installer) return E_OUTOFMEMORY;
+
+ installer->vtbl = &update_installer_vtbl;
+ installer->refs = 1;
+
+ *ppObj = &installer->vtbl;
+
+ TRACE("returning iface %p\n", *ppObj);
+ return S_OK;
+}
diff --git a/reactos/dll/win32/wuapi/main.c b/reactos/dll/win32/wuapi/main.c
new file mode 100644
index 00000000000..d8d6fcb062c
--- /dev/null
+++ b/reactos/dll/win32/wuapi/main.c
@@ -0,0 +1,154 @@
+/*
+ * WUAPI implementation
+ *
+ * Copyright 2008 Hans Leidekker
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "wuapi.h"
+
+#include "wine/debug.h"
+#include "wuapi_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wuapi);
+
+typedef HRESULT (*fnCreateInstance)( IUnknown *pUnkOuter, LPVOID *ppObj );
+
+typedef struct _wucf
+{
+ const struct IClassFactoryVtbl *vtbl;
+ fnCreateInstance pfnCreateInstance;
+} wucf;
+
+static inline wucf *impl_from_IClassFactory( IClassFactory *iface )
+{
+ return (wucf *)((char *)iface - FIELD_OFFSET( wucf, vtbl ));
+}
+
+static HRESULT WINAPI wucf_QueryInterface( IClassFactory *iface, REFIID riid, LPVOID *ppobj )
+{
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IClassFactory))
+ {
+ IClassFactory_AddRef( iface );
+ *ppobj = iface;
+ return S_OK;
+ }
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI wucf_AddRef( IClassFactory *iface )
+{
+ return 2;
+}
+
+static ULONG WINAPI wucf_Release( IClassFactory *iface )
+{
+ return 1;
+}
+
+static HRESULT WINAPI wucf_CreateInstance( IClassFactory *iface, LPUNKNOWN pOuter,
+ REFIID riid, LPVOID *ppobj )
+{
+ wucf *This = impl_from_IClassFactory( iface );
+ HRESULT r;
+ IUnknown *punk;
+
+ TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj);
+
+ *ppobj = NULL;
+
+ if (pOuter)
+ return CLASS_E_NOAGGREGATION;
+
+ r = This->pfnCreateInstance( pOuter, (LPVOID *)&punk );
+ if (FAILED(r))
+ return r;
+
+ r = IUnknown_QueryInterface( punk, riid, ppobj );
+ if (FAILED(r))
+ return r;
+
+ IUnknown_Release( punk );
+ return r;
+}
+
+static HRESULT WINAPI wucf_LockServer( IClassFactory *iface, BOOL dolock )
+{
+ FIXME("(%p)->(%d)\n", iface, dolock);
+ return S_OK;
+}
+
+static const struct IClassFactoryVtbl wucf_vtbl =
+{
+ wucf_QueryInterface,
+ wucf_AddRef,
+ wucf_Release,
+ wucf_CreateInstance,
+ wucf_LockServer
+};
+
+static wucf sessioncf = { &wucf_vtbl, UpdateSession_create };
+static wucf updatescf = { &wucf_vtbl, AutomaticUpdates_create };
+
+BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID lpv )
+{
+ switch(reason)
+ {
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls( hinst );
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv )
+{
+ IClassFactory *cf = NULL;
+
+ TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
+
+ if (IsEqualGUID( rclsid, &CLSID_UpdateSession ))
+ {
+ cf = (IClassFactory *)&sessioncf.vtbl;
+ }
+ else if (IsEqualGUID( rclsid, &CLSID_AutomaticUpdates ))
+ {
+ cf = (IClassFactory *)&updatescf.vtbl;
+ }
+ if (!cf) return CLASS_E_CLASSNOTAVAILABLE;
+ return IClassFactory_QueryInterface( cf, iid, ppv );
+}
+
+HRESULT WINAPI DllCanUnloadNow( void )
+{
+ FIXME("\n");
+ return S_FALSE;
+}
diff --git a/reactos/dll/win32/wuapi/regsvr.c b/reactos/dll/win32/wuapi/regsvr.c
new file mode 100644
index 00000000000..10d3974d508
--- /dev/null
+++ b/reactos/dll/win32/wuapi/regsvr.c
@@ -0,0 +1,430 @@
+/*
+ * self-registerable dll functions for wuapi.dll
+ *
+ * Copyright (C) 2003 John K. Hohm
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#include
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "winerror.h"
+#include "objbase.h"
+#include "wuapi.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wuapi);
+
+/*
+ * Near the bottom of this file are the exported DllRegisterServer and
+ * DllUnregisterServer, which make all this worthwhile.
+ */
+
+/***********************************************************************
+ * interface for self-registering
+ */
+struct regsvr_interface
+{
+ IID const *iid; /* NULL for end of list */
+ LPCSTR name; /* can be NULL to omit */
+ IID const *base_iid; /* can be NULL to omit */
+ int num_methods; /* can be <0 to omit */
+ CLSID const *ps_clsid; /* can be NULL to omit */
+ CLSID const *ps_clsid32; /* can be NULL to omit */
+};
+
+static HRESULT register_interfaces(struct regsvr_interface const *list);
+static HRESULT unregister_interfaces(struct regsvr_interface const *list);
+
+struct regsvr_coclass
+{
+ CLSID const *clsid; /* NULL for end of list */
+ LPCSTR name; /* can be NULL to omit */
+ LPCSTR ips; /* can be NULL to omit */
+ LPCSTR ips32; /* can be NULL to omit */
+ LPCSTR ips32_tmodel; /* can be NULL to omit */
+ LPCSTR clsid_str; /* can be NULL to omit */
+ LPCSTR progid; /* can be NULL to omit */
+};
+
+static HRESULT register_coclasses(struct regsvr_coclass const *list);
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
+
+/***********************************************************************
+ * static string constants
+ */
+static WCHAR const interface_keyname[10] = {
+ 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
+static WCHAR const base_ifa_keyname[14] = {
+ 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
+ 'e', 0 };
+static WCHAR const num_methods_keyname[11] = {
+ 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
+static WCHAR const ps_clsid_keyname[15] = {
+ 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
+ 'i', 'd', 0 };
+static WCHAR const ps_clsid32_keyname[17] = {
+ 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
+ 'i', 'd', '3', '2', 0 };
+static WCHAR const clsid_keyname[6] = {
+ 'C', 'L', 'S', 'I', 'D', 0 };
+static WCHAR const ips_keyname[13] = {
+ 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+ 0 };
+static WCHAR const ips32_keyname[15] = {
+ 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+ '3', '2', 0 };
+static WCHAR const progid_keyname[7] = {
+ 'P', 'r', 'o', 'g', 'I', 'D', 0 };
+static char const tmodel_valuename[] = "ThreadingModel";
+
+/***********************************************************************
+ * static helper functions
+ */
+static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
+static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
+ WCHAR const *value);
+static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
+ char const *value);
+
+/***********************************************************************
+ * register_interfaces
+ */
+static HRESULT register_interfaces(struct regsvr_interface const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY interface_key;
+
+ res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->iid; ++list) {
+ WCHAR buf[39];
+ HKEY iid_key;
+
+ StringFromGUID2(list->iid, buf, 39);
+ res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_interface_key;
+
+ if (list->name) {
+ res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)(list->name),
+ strlen(list->name) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (list->base_iid) {
+ res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (0 <= list->num_methods) {
+ static WCHAR const fmt[3] = { '%', 'd', 0 };
+ HKEY key;
+
+ res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+
+ sprintfW(buf, fmt, list->num_methods);
+ res = RegSetValueExW(key, NULL, 0, REG_SZ,
+ (CONST BYTE*)buf,
+ (lstrlenW(buf) + 1) * sizeof(WCHAR));
+ RegCloseKey(key);
+
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (list->ps_clsid) {
+ res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ if (list->ps_clsid32) {
+ res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
+ if (res != ERROR_SUCCESS) goto error_close_iid_key;
+ }
+
+ error_close_iid_key:
+ RegCloseKey(iid_key);
+ }
+
+error_close_interface_key:
+ RegCloseKey(interface_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * unregister_interfaces
+ */
+static HRESULT unregister_interfaces(struct regsvr_interface const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY interface_key;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
+ KEY_READ | KEY_WRITE, &interface_key);
+ if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->iid; ++list) {
+ WCHAR buf[39];
+
+ StringFromGUID2(list->iid, buf, 39);
+ res = RegDeleteTreeW(interface_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ }
+
+ RegCloseKey(interface_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * register_coclasses
+ */
+static HRESULT register_coclasses(struct regsvr_coclass const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+
+ res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ WCHAR buf[39];
+ HKEY clsid_key;
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ if (list->name) {
+ res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)(list->name),
+ strlen(list->name) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->ips) {
+ res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->ips32) {
+ HKEY ips32_key;
+
+ res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL,
+ &ips32_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)list->ips32,
+ lstrlenA(list->ips32) + 1);
+ if (res == ERROR_SUCCESS && list->ips32_tmodel)
+ res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
+ (CONST BYTE*)list->ips32_tmodel,
+ strlen(list->ips32_tmodel) + 1);
+ RegCloseKey(ips32_key);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->clsid_str) {
+ res = register_key_defvalueA(clsid_key, clsid_keyname,
+ list->clsid_str);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->progid) {
+ HKEY progid_key;
+
+ res = register_key_defvalueA(clsid_key, progid_keyname,
+ list->progid);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = RegCreateKeyExA(HKEY_CLASSES_ROOT, list->progid, 0,
+ NULL, 0, KEY_READ | KEY_WRITE, NULL,
+ &progid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = register_key_defvalueW(progid_key, clsid_keyname, buf);
+ RegCloseKey(progid_key);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ error_close_clsid_key:
+ RegCloseKey(clsid_key);
+ }
+
+error_close_coclass_key:
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * unregister_coclasses
+ */
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
+ KEY_READ | KEY_WRITE, &coclass_key);
+ if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ WCHAR buf[39];
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegDeleteTreeW(coclass_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ if (list->progid) {
+ res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+ }
+
+error_close_coclass_key:
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * regsvr_key_guid
+ */
+static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
+{
+ WCHAR buf[39];
+
+ StringFromGUID2(guid, buf, 39);
+ return register_key_defvalueW(base, name, buf);
+}
+
+/***********************************************************************
+ * regsvr_key_defvalueW
+ */
+static LONG register_key_defvalueW(
+ HKEY base,
+ WCHAR const *name,
+ WCHAR const *value)
+{
+ LONG res;
+ HKEY key;
+
+ res = RegCreateKeyExW(base, name, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+ res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+ (lstrlenW(value) + 1) * sizeof(WCHAR));
+ RegCloseKey(key);
+ return res;
+}
+
+/***********************************************************************
+ * regsvr_key_defvalueA
+ */
+static LONG register_key_defvalueA(
+ HKEY base,
+ WCHAR const *name,
+ char const *value)
+{
+ LONG res;
+ HKEY key;
+
+ res = RegCreateKeyExW(base, name, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+ res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+ lstrlenA(value) + 1);
+ RegCloseKey(key);
+ return res;
+}
+
+/***********************************************************************
+ * coclass list
+ */
+static struct regsvr_coclass const coclass_list[] = {
+ { &CLSID_UpdateSession,
+ "CLSID_UpdateSession",
+ NULL,
+ "wuapi.dll",
+ "Both"
+ },
+ { &CLSID_AutomaticUpdates,
+ "CLSID_AutomaticUpdates",
+ NULL,
+ "wuapi.dll",
+ "Both"
+ },
+ { NULL } /* list terminator */
+};
+
+/***********************************************************************
+ * interface list
+ */
+static struct regsvr_interface const interface_list[] = {
+ { NULL } /* list terminator */
+};
+
+/***********************************************************************
+ * DllRegisterServer (INETCOMM.@)
+ */
+HRESULT WINAPI DllRegisterServer(void)
+{
+ HRESULT hr;
+
+ TRACE("\n");
+
+ hr = register_coclasses(coclass_list);
+ if (SUCCEEDED(hr))
+ hr = register_interfaces(interface_list);
+ return hr;
+}
+
+/***********************************************************************
+ * DllUnregisterServer (INETCOMM.@)
+ */
+HRESULT WINAPI DllUnregisterServer(void)
+{
+ HRESULT hr;
+
+ TRACE("\n");
+
+ hr = unregister_coclasses(coclass_list);
+ if (SUCCEEDED(hr))
+ hr = unregister_interfaces(interface_list);
+ return hr;
+}
diff --git a/reactos/dll/win32/wuapi/searcher.c b/reactos/dll/win32/wuapi/searcher.c
new file mode 100644
index 00000000000..8105681f7a1
--- /dev/null
+++ b/reactos/dll/win32/wuapi/searcher.c
@@ -0,0 +1,257 @@
+/*
+ * IUpdateSearcher implementation
+ *
+ * Copyright 2008 Hans Leidekker
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "wuapi.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wuapi);
+
+typedef struct _update_searcher
+{
+ const struct IUpdateSearcherVtbl *vtbl;
+ LONG refs;
+} update_searcher;
+
+static inline update_searcher *impl_from_IUpdateSearcher( IUpdateSearcher *iface )
+{
+ return (update_searcher *)((char *)iface - FIELD_OFFSET( update_searcher, vtbl ));
+}
+
+static ULONG WINAPI update_searcher_AddRef(
+ IUpdateSearcher *iface )
+{
+ update_searcher *update_searcher = impl_from_IUpdateSearcher( iface );
+ return InterlockedIncrement( &update_searcher->refs );
+}
+
+static ULONG WINAPI update_searcher_Release(
+ IUpdateSearcher *iface )
+{
+ update_searcher *update_searcher = impl_from_IUpdateSearcher( iface );
+ LONG refs = InterlockedDecrement( &update_searcher->refs );
+ if (!refs)
+ {
+ TRACE("destroying %p\n", update_searcher);
+ HeapFree( GetProcessHeap(), 0, update_searcher );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI update_searcher_QueryInterface(
+ IUpdateSearcher *iface,
+ REFIID riid,
+ void **ppvObject )
+{
+ update_searcher *This = impl_from_IUpdateSearcher( iface );
+
+ TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
+
+ if ( IsEqualGUID( riid, &IID_IUpdateSearcher ) ||
+ IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+ IUpdateSearcher_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI update_searcher_GetTypeInfoCount(
+ IUpdateSearcher *iface,
+ UINT *pctinfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_GetTypeInfo(
+ IUpdateSearcher *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo **ppTInfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_GetIDsOfNames(
+ IUpdateSearcher *iface,
+ REFIID riid,
+ LPOLESTR *rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID *rgDispId )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_Invoke(
+ IUpdateSearcher *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_get_CanAutomaticallyUpgradeService(
+ IUpdateSearcher *This,
+ VARIANT_BOOL *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_put_CanAutomaticallyUpgradeService(
+ IUpdateSearcher *This,
+ VARIANT_BOOL value )
+{
+ FIXME("%p, %d\n", This, value);
+ return S_OK;
+}
+
+static HRESULT WINAPI update_searcher_get_ClientApplicationID(
+ IUpdateSearcher *This,
+ BSTR *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_put_ClientApplicationID(
+ IUpdateSearcher *This,
+ BSTR value )
+{
+ FIXME("%p, %s\n", This, debugstr_w(value));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_get_IncludePotentiallySupersededUpdates(
+ IUpdateSearcher *This,
+ VARIANT_BOOL *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_put_IncludePotentiallySupersededUpdates(
+ IUpdateSearcher *This,
+ VARIANT_BOOL value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_get_ServerSelection(
+ IUpdateSearcher *This,
+ ServerSelection *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_put_ServerSelection(
+ IUpdateSearcher *This,
+ ServerSelection value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_BeginSearch(
+ IUpdateSearcher *This,
+ BSTR criteria,
+ IUnknown *onCompleted,
+ VARIANT state,
+ ISearchJob **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_searcher_EndSearch(
+ IUpdateSearcher *This,
+ ISearchJob *searchJob,
+ ISearchResult **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static const struct IUpdateSearcherVtbl update_searcher_vtbl =
+{
+ update_searcher_QueryInterface,
+ update_searcher_AddRef,
+ update_searcher_Release,
+ update_searcher_GetTypeInfoCount,
+ update_searcher_GetTypeInfo,
+ update_searcher_GetIDsOfNames,
+ update_searcher_Invoke,
+ update_searcher_get_CanAutomaticallyUpgradeService,
+ update_searcher_put_CanAutomaticallyUpgradeService,
+ update_searcher_get_ClientApplicationID,
+ update_searcher_put_ClientApplicationID,
+ update_searcher_get_IncludePotentiallySupersededUpdates,
+ update_searcher_put_IncludePotentiallySupersededUpdates,
+ update_searcher_get_ServerSelection,
+ update_searcher_put_ServerSelection,
+ update_searcher_BeginSearch,
+ update_searcher_EndSearch
+};
+
+HRESULT UpdateSearcher_create( IUnknown *pUnkOuter, LPVOID *ppObj )
+{
+ update_searcher *searcher;
+
+ TRACE("(%p,%p)\n", pUnkOuter, ppObj);
+
+ searcher = HeapAlloc( GetProcessHeap(), 0, sizeof(*searcher) );
+ if (!searcher) return E_OUTOFMEMORY;
+
+ searcher->vtbl = &update_searcher_vtbl;
+ searcher->refs = 1;
+
+ *ppObj = &searcher->vtbl;
+
+ TRACE("returning iface %p\n", *ppObj);
+ return S_OK;
+}
diff --git a/reactos/dll/win32/wuapi/session.c b/reactos/dll/win32/wuapi/session.c
new file mode 100644
index 00000000000..5f163c724c5
--- /dev/null
+++ b/reactos/dll/win32/wuapi/session.c
@@ -0,0 +1,236 @@
+/*
+ * IUpdateSession implementation
+ *
+ * Copyright 2008 Hans Leidekker
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "wuapi.h"
+
+#include "wine/debug.h"
+#include "wuapi_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wuapi);
+
+typedef struct _update_session
+{
+ const struct IUpdateSessionVtbl *vtbl;
+ LONG refs;
+} update_session;
+
+static inline update_session *impl_from_IUpdateSession( IUpdateSession *iface )
+{
+ return (update_session *)((char *)iface - FIELD_OFFSET( update_session, vtbl ));
+}
+
+static ULONG WINAPI update_session_AddRef(
+ IUpdateSession *iface )
+{
+ update_session *update_session = impl_from_IUpdateSession( iface );
+ return InterlockedIncrement( &update_session->refs );
+}
+
+static ULONG WINAPI update_session_Release(
+ IUpdateSession *iface )
+{
+ update_session *update_session = impl_from_IUpdateSession( iface );
+ LONG refs = InterlockedDecrement( &update_session->refs );
+ if (!refs)
+ {
+ TRACE("destroying %p\n", update_session);
+ HeapFree( GetProcessHeap(), 0, update_session );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI update_session_QueryInterface(
+ IUpdateSession *iface,
+ REFIID riid,
+ void **ppvObject )
+{
+ update_session *This = impl_from_IUpdateSession( iface );
+
+ TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
+
+ if ( IsEqualGUID( riid, &IID_IUpdateSession ) ||
+ IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+ IUpdateSession_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI update_session_GetTypeInfoCount(
+ IUpdateSession *iface,
+ UINT *pctinfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_GetTypeInfo(
+ IUpdateSession *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo **ppTInfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_GetIDsOfNames(
+ IUpdateSession *iface,
+ REFIID riid,
+ LPOLESTR *rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID *rgDispId )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_Invoke(
+ IUpdateSession *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_get_ClientApplicationID(
+ IUpdateSession *This,
+ BSTR *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_put_ClientApplicationID(
+ IUpdateSession *This,
+ BSTR value )
+{
+ FIXME("%p, %s\n", This, debugstr_w(value));
+ return S_OK;
+}
+
+static HRESULT WINAPI update_session_get_ReadOnly(
+ IUpdateSession *This,
+ VARIANT_BOOL *retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_get_WebProxy(
+ IUpdateSession *This,
+ IWebProxy **retval )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_put_WebProxy(
+ IUpdateSession *This,
+ IWebProxy *value )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI update_session_CreateUpdateSearcher(
+ IUpdateSession *This,
+ IUpdateSearcher **retval )
+{
+ TRACE("%p\n", This);
+ return UpdateSearcher_create( NULL, (LPVOID *)retval );
+}
+
+static HRESULT WINAPI update_session_CreateUpdateDownloader(
+ IUpdateSession *This,
+ IUpdateDownloader **retval )
+{
+ TRACE("%p\n", This);
+ return UpdateDownloader_create( NULL, (LPVOID *)retval );
+}
+
+static HRESULT WINAPI update_session_CreateUpdateInstaller(
+ IUpdateSession *This,
+ IUpdateInstaller **retval )
+{
+ TRACE("%p\n", This);
+ return UpdateInstaller_create( NULL, (LPVOID *)retval );
+}
+
+static const struct IUpdateSessionVtbl update_session_vtbl =
+{
+ update_session_QueryInterface,
+ update_session_AddRef,
+ update_session_Release,
+ update_session_GetTypeInfoCount,
+ update_session_GetTypeInfo,
+ update_session_GetIDsOfNames,
+ update_session_Invoke,
+ update_session_get_ClientApplicationID,
+ update_session_put_ClientApplicationID,
+ update_session_get_ReadOnly,
+ update_session_get_WebProxy,
+ update_session_put_WebProxy,
+ update_session_CreateUpdateSearcher,
+ update_session_CreateUpdateDownloader,
+ update_session_CreateUpdateInstaller
+};
+
+HRESULT UpdateSession_create( IUnknown *pUnkOuter, LPVOID *ppObj )
+{
+ update_session *session;
+
+ TRACE("(%p,%p)\n", pUnkOuter, ppObj);
+
+ session = HeapAlloc( GetProcessHeap(), 0, sizeof(*session) );
+ if (!session) return E_OUTOFMEMORY;
+
+ session->vtbl = &update_session_vtbl;
+ session->refs = 1;
+
+ *ppObj = &session->vtbl;
+
+ TRACE("returning iface %p\n", *ppObj);
+ return S_OK;
+}
diff --git a/reactos/dll/win32/wuapi/updates.c b/reactos/dll/win32/wuapi/updates.c
new file mode 100644
index 00000000000..1bf063b999f
--- /dev/null
+++ b/reactos/dll/win32/wuapi/updates.c
@@ -0,0 +1,221 @@
+/*
+ * IAutomaticUpdates implementation
+ *
+ * Copyright 2008 Hans Leidekker
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "wuapi.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wuapi);
+
+typedef struct _automatic_updates
+{
+ const struct IAutomaticUpdatesVtbl *vtbl;
+ LONG refs;
+} automatic_updates;
+
+static inline automatic_updates *impl_from_IAutomaticUpdates( IAutomaticUpdates *iface )
+{
+ return (automatic_updates *)((char*)iface - FIELD_OFFSET( automatic_updates, vtbl ));
+}
+
+static ULONG WINAPI automatic_updates_AddRef(
+ IAutomaticUpdates *iface )
+{
+ automatic_updates *automatic_updates = impl_from_IAutomaticUpdates( iface );
+ return InterlockedIncrement( &automatic_updates->refs );
+}
+
+static ULONG WINAPI automatic_updates_Release(
+ IAutomaticUpdates *iface )
+{
+ automatic_updates *automatic_updates = impl_from_IAutomaticUpdates( iface );
+ LONG refs = InterlockedDecrement( &automatic_updates->refs );
+ if (!refs)
+ {
+ TRACE("destroying %p\n", automatic_updates);
+ HeapFree( GetProcessHeap(), 0, automatic_updates );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI automatic_updates_QueryInterface(
+ IAutomaticUpdates *iface,
+ REFIID riid,
+ void **ppvObject )
+{
+ automatic_updates *This = impl_from_IAutomaticUpdates( iface );
+
+ TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
+
+ if ( IsEqualGUID( riid, &IID_IAutomaticUpdates ) ||
+ IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+ IAutomaticUpdates_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI automatic_updates_GetTypeInfoCount(
+ IAutomaticUpdates *iface,
+ UINT *pctinfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_GetTypeInfo(
+ IAutomaticUpdates *iface,
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo **ppTInfo )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_GetIDsOfNames(
+ IAutomaticUpdates *iface,
+ REFIID riid,
+ LPOLESTR *rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID *rgDispId )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_Invoke(
+ IAutomaticUpdates *iface,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_DetectNow(
+ IAutomaticUpdates *This )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_Pause(
+ IAutomaticUpdates *This )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_Resume(
+ IAutomaticUpdates *This )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_ShowSettingsDialog(
+ IAutomaticUpdates *This )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_EnableService(
+ IAutomaticUpdates *This )
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_get_ServiceEnabled(
+ IAutomaticUpdates *This,
+ VARIANT_BOOL *retval )
+{
+ FIXME("%p\n", retval);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI automatic_updates_get_Settings(
+ IAutomaticUpdates *This,
+ IAutomaticUpdatesSettings **retval )
+{
+ FIXME("%p\n", retval);
+ return E_NOTIMPL;
+}
+
+static const struct IAutomaticUpdatesVtbl automatic_updates_vtbl =
+{
+ automatic_updates_QueryInterface,
+ automatic_updates_AddRef,
+ automatic_updates_Release,
+ automatic_updates_GetTypeInfoCount,
+ automatic_updates_GetTypeInfo,
+ automatic_updates_GetIDsOfNames,
+ automatic_updates_Invoke,
+ automatic_updates_DetectNow,
+ automatic_updates_Pause,
+ automatic_updates_Resume,
+ automatic_updates_ShowSettingsDialog,
+ automatic_updates_get_Settings,
+ automatic_updates_get_ServiceEnabled,
+ automatic_updates_EnableService
+};
+
+HRESULT AutomaticUpdates_create( IUnknown *pUnkOuter, LPVOID *ppObj )
+{
+ automatic_updates *updates;
+
+ TRACE("(%p,%p)\n", pUnkOuter, ppObj);
+
+ updates = HeapAlloc( GetProcessHeap(), 0, sizeof(*updates) );
+ if (!updates) return E_OUTOFMEMORY;
+
+ updates->vtbl = &automatic_updates_vtbl;
+ updates->refs = 1;
+
+ *ppObj = &updates->vtbl;
+
+ TRACE("returning iface %p\n", *ppObj);
+ return S_OK;
+}
diff --git a/reactos/dll/win32/wuapi/wuapi.rbuild b/reactos/dll/win32/wuapi/wuapi.rbuild
new file mode 100644
index 00000000000..3b8510623e4
--- /dev/null
+++ b/reactos/dll/win32/wuapi/wuapi.rbuild
@@ -0,0 +1,21 @@
+
+
+
+ .
+ include/reactos/wine
+
+ 0x600
+ downloader.c
+ installer.c
+ main.c
+ regsvr.c
+ searcher.c
+ session.c
+ updates.c
+ wine
+ uuid
+ ole32
+ advapi32
+ kernel32
+ ntdll
+
diff --git a/reactos/dll/win32/wuapi/wuapi.spec b/reactos/dll/win32/wuapi/wuapi.spec
new file mode 100644
index 00000000000..b16365d0c9f
--- /dev/null
+++ b/reactos/dll/win32/wuapi/wuapi.spec
@@ -0,0 +1,4 @@
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
diff --git a/reactos/dll/win32/wuapi/wuapi_private.h b/reactos/dll/win32/wuapi/wuapi_private.h
new file mode 100644
index 00000000000..9c10daf0527
--- /dev/null
+++ b/reactos/dll/win32/wuapi/wuapi_private.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 Hans Leidekker for CodeWeavers
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern HRESULT AutomaticUpdates_create( IUnknown *pUnkOuter, LPVOID *ppObj );
+extern HRESULT UpdateSession_create( IUnknown *pUnkOuter, LPVOID *ppObj );
+extern HRESULT UpdateSearcher_create( IUnknown *pUnkOuter, LPVOID *ppObj );
+extern HRESULT UpdateDownloader_create( IUnknown *pUnkOuter, LPVOID *ppObj );
+extern HRESULT UpdateInstaller_create( IUnknown *pUnkOuter, LPVOID *ppObj );
diff --git a/reactos/include/psdk/psdk.rbuild b/reactos/include/psdk/psdk.rbuild
index 9b7610532be..9b57f3af7f8 100644
--- a/reactos/include/psdk/psdk.rbuild
+++ b/reactos/include/psdk/psdk.rbuild
@@ -52,6 +52,7 @@
mshtmhst.idl
exdisp.idl
wtypes.idl
+ wuapi.idl
comcat.idl
xmldso.idl
xmldom.idl
diff --git a/reactos/include/psdk/wuapi.idl b/reactos/include/psdk/wuapi.idl
new file mode 100644
index 00000000000..27a3d5f1c10
--- /dev/null
+++ b/reactos/include/psdk/wuapi.idl
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2008 Hans Leidekker for CodeWeavers
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+cpp_quote("DEFINE_GUID(CLSID_AutomaticUpdates, 0xbfe18e9c,0x6d87,0x4450,0xb3,0x7c,0xe0,0x2f,0x0b,0x37,0x38,0x03);")
+cpp_quote("DEFINE_GUID(CLSID_UpdateSession, 0x4cb43d7f,0x7eee,0x4906,0x86,0x98,0x60,0xda,0x1c,0x38,0xf2,0xfe);")
+
+import "oaidl.idl";
+
+interface IAutomaticUpdates;
+interface IAutomaticUpdatesSettings;
+interface IDownloadJob;
+interface IDownloadResult;
+interface IInstallationJob;
+interface IInstallationResult;
+interface ISearchJob;
+interface ISearchResult;
+interface IUpdateCollection;
+interface IUpdateDownloader;
+interface IUpdateHistoryEntryCollection;
+interface IUpdateInstaller;
+interface IUpdateSearcher;
+interface IUpdateSession;
+interface IWebProxy;
+
+typedef [public] enum tagDownloadPriority
+{
+ dpLow = 1,
+ dpNormal = 2,
+ dpHigh = 3,
+} DownloadPriority;
+
+typedef [public] enum tagServerSelection
+{
+ ssDefault = 0,
+ ssManagedServer = 1,
+ ssWindowsUpdate = 2,
+ ssOthers = 3,
+} ServerSelection;
+
+[
+ object,
+ uuid(673425bf-c082-4c7c-bdfd-569464b8e0ce),
+ oleautomation,
+ dual,
+ nonextensible,
+ pointer_default(unique),
+ hidden
+]
+interface IAutomaticUpdates : IDispatch
+{
+ HRESULT DetectNow();
+ HRESULT Pause();
+ HRESULT Resume();
+ HRESULT ShowSettingsDialog();
+
+ [propget]
+ HRESULT Settings(
+ [out, retval] IAutomaticUpdatesSettings **retval);
+
+ [propget]
+ HRESULT ServiceEnabled(
+ [out, retval] VARIANT_BOOL *retval);
+
+ HRESULT EnableService();
+}
+
+[
+ object,
+ uuid(816858a4-260d-4260-933a-2585f1abc76b),
+ oleautomation,
+ dual,
+ nonextensible,
+ pointer_default(unique),
+]
+interface IUpdateSession : IDispatch
+{
+ [propget]
+ HRESULT ClientApplicationID(
+ [out, retval] BSTR *retval);
+
+ [propput]
+ HRESULT ClientApplicationID(
+ [in] BSTR value);
+
+ [propget]
+ HRESULT ReadOnly(
+ [out, retval] VARIANT_BOOL *retval);
+
+ [propget]
+ HRESULT WebProxy(
+ [out, retval] IWebProxy **retval);
+
+ [propput]
+ HRESULT WebProxy(
+ [in, unique] IWebProxy *value);
+
+ HRESULT CreateUpdateSearcher(
+ [out, retval] IUpdateSearcher **retval);
+
+ HRESULT CreateUpdateDownloader(
+ [out, retval] IUpdateDownloader **retval);
+
+ HRESULT CreateUpdateInstaller(
+ [out, retval] IUpdateInstaller **retval);
+}
+
+[
+ object,
+ uuid(8f45abf1-f9ae-4b95-a933-f0f66e5056ea),
+ oleautomation,
+ dual,
+ nonextensible,
+ pointer_default(unique),
+]
+interface IUpdateSearcher : IDispatch
+{
+ [propget]
+ HRESULT CanAutomaticallyUpgradeService(
+ [out, retval] VARIANT_BOOL *retval);
+
+ [propput]
+ HRESULT CanAutomaticallyUpgradeService(
+ [in] VARIANT_BOOL value);
+
+ [propget]
+ HRESULT ClientApplicationID(
+ [out, retval] BSTR *retval);
+
+ [propput]
+ HRESULT ClientApplicationID(
+ [in] BSTR value);
+
+ [propget]
+ HRESULT IncludePotentiallySupersededUpdates(
+ [out, retval] VARIANT_BOOL *retval);
+
+ [propput]
+ HRESULT IncludePotentiallySupersededUpdates(
+ [in] VARIANT_BOOL value);
+
+ [propget]
+ HRESULT ServerSelection(
+ [out, retval] ServerSelection *retval);
+
+ [propput]
+ HRESULT ServerSelection(
+ [in] ServerSelection value);
+
+ HRESULT BeginSearch(
+ [in] BSTR criteria,
+ [in] IUnknown *onCompleted,
+ [in] VARIANT state,
+ [out, retval] ISearchJob **retval);
+
+ HRESULT EndSearch(
+ [in] ISearchJob *searchJob,
+ [out, retval] ISearchResult **retval);
+
+ HRESULT EscapeString(
+ [in] BSTR unescaped,
+ [out, retval] BSTR *retval);
+
+ HRESULT QueryHistory(
+ [in] LONG startIndex,
+ [in] LONG count,
+ [out, retval] IUpdateHistoryEntryCollection **retval);
+
+ HRESULT Search(
+ [in] BSTR criteria,
+ [out, retval] ISearchResult **retval);
+
+ [propget]
+ HRESULT Online(
+ [out, retval] VARIANT_BOOL *retval);
+
+ [propput]
+ HRESULT Online(
+ [in] VARIANT_BOOL value);
+
+ HRESULT GetTotalHistoryCount(
+ [out, retval] LONG *retval);
+
+ [propget]
+ HRESULT ServiceID(
+ [out, retval] BSTR *retval);
+
+ [propput]
+ HRESULT ServiceID(
+ [in] BSTR value);
+}
+
+[
+ object,
+ uuid(68f1c6f9-7ecc-4666-a464-247fe12496c3),
+ oleautomation,
+ dual,
+ nonextensible,
+ pointer_default(unique),
+ hidden
+]
+interface IUpdateDownloader : IDispatch
+{
+ [propget]
+ HRESULT ClientApplicationID(
+ [out, retval] BSTR *retval);
+
+ [propput]
+ HRESULT ClientApplicationID(
+ [in] BSTR value);
+
+ [propget]
+ HRESULT IsForced(
+ [out, retval] VARIANT_BOOL *retval);
+
+ [propput]
+ HRESULT IsForced(
+ [in] VARIANT_BOOL value);
+
+ [propget]
+ HRESULT Priority(
+ [out, retval] DownloadPriority *retval);
+
+ [propput]
+ HRESULT Priority(
+ [in] DownloadPriority value);
+
+ [propget]
+ HRESULT Updates(
+ [out, retval] IUpdateCollection **retval);
+
+ [propput]
+ HRESULT Updates(
+ [in] IUpdateCollection *value);
+
+ HRESULT BeginDownload(
+ [in] IUnknown *onProgressChanged,
+ [in] IUnknown *onCompleted,
+ [in] VARIANT state,
+ [out, retval] IDownloadJob **retval);
+
+ HRESULT Download(
+ [out, retval] IDownloadResult **retval);
+
+ HRESULT EndDownload(
+ [in] IDownloadJob *value,
+ [out, retval] IDownloadResult **retval);
+}
+
+[
+ object,
+ uuid(7b929c68-ccdc-4226-96b1-8724600b54c2),
+ oleautomation,
+ dual,
+ nonextensible,
+ pointer_default(unique),
+]
+interface IUpdateInstaller : IDispatch
+{
+ [propget]
+ HRESULT ClientApplicationID(
+ [out, retval] BSTR *retval);
+
+ [propput]
+ HRESULT ClientApplicationID(
+ [in] BSTR value);
+
+ [propget]
+ HRESULT IsForced(
+ [out, retval] VARIANT_BOOL *retval);
+
+ [propput]
+ HRESULT IsForced(
+ [in] VARIANT_BOOL value);
+
+ [propget, restricted]
+ HRESULT ParentHwnd(
+ [out, retval] HWND *retval);
+
+ [propput, restricted]
+ HRESULT ParentHwnd(
+ [in, unique] HWND value);
+
+ [propput]
+ HRESULT ParentWindow(
+ [in, unique] IUnknown *value);
+
+ [propget]
+ HRESULT ParentWindow(
+ [out, retval] IUnknown **retval);
+
+ [propget]
+ HRESULT Updates(
+ [out, retval] IUpdateCollection **retval);
+
+ [propput]
+ HRESULT Updates(
+ [in] IUpdateCollection *value);
+
+ HRESULT BeginInstall(
+ [in] IUnknown *onProgressChanged,
+ [in] IUnknown *onCompleted,
+ [in] VARIANT state,
+ [out, retval] IInstallationJob **retval);
+
+ HRESULT BeginUninstall(
+ [in] IUnknown *onProgressChanged,
+ [in] IUnknown *onCompleted,
+ [in] VARIANT state,
+ [out, retval] IInstallationJob **retval);
+
+ HRESULT EndInstall(
+ [in] IInstallationJob *value,
+ [out, retval] IInstallationResult **retval);
+
+ HRESULT EndUninstall(
+ [in] IInstallationJob *value,
+ [out, retval] IInstallationResult **retval);
+
+ HRESULT Install(
+ [out, retval] IInstallationResult **retval);
+
+ HRESULT RunWizard(
+ [in, defaultvalue("")] BSTR dialogTitle,
+ [out, retval] IInstallationResult **retval);
+
+ [propget]
+ HRESULT IsBusy(
+ [out, retval] VARIANT_BOOL *retval);
+
+ HRESULT Uninstall(
+ [out, retval] IInstallationResult **retval);
+
+ [propget]
+ HRESULT AllowSourcePrompts(
+ [out, retval] VARIANT_BOOL *retval);
+
+ [propput]
+ HRESULT AllowSourcePrompts(
+ [in] VARIANT_BOOL value);
+
+ [propget]
+ HRESULT RebootRequiredBeforeInstallation(
+ [out, retval] VARIANT_BOOL *retval);
+}
diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE
index 491e743fc2b..dcd9ec7c334 100644
--- a/reactos/media/doc/README.WINE
+++ b/reactos/media/doc/README.WINE
@@ -55,9 +55,11 @@ reactos/dll/win32/imm32 # Autosync
reactos/dll/win32/imagehlp # Patches for BindImage need review and submission to winehq.
reactos/dll/win32/inetcomm # Autosync
reactos/dll/win32/inetmib1 # Autosync
+reactos/dll/win32/inseng # Autosync
reactos/dll/win32/iphlpapi # Out of sync
reactos/dll/win32/itss # Autosync
reactos/dll/win32/jscript # Autosync
+reactos/dll/win32/localspl # Autosync
reactos/dll/win32/localui # Autosync
reactos/dll/win32/lz32 # Autosync
reactos/dll/win32/mapi32 # Autosync
@@ -129,6 +131,7 @@ reactos/dll/win32/winmm/wavemap # Forked at Wine-20050628
reactos/dll/win32/wldap32 # Autosync
reactos/dll/win32/wmi # Autosync
reactos/dll/win32/wtsapi32 # Autosync
+reactos/dll/win32/wuapi # Autosync
reactos/dll/directx/dinput # Synced to Wine-1_1_4
reactos/dll/directx/dinput8 # Synced to Wine-1_1_4
reactos/dll/directx/dplay # Synced to Wine-0_9_5