From eaa65d2024dd8d3a5890fd3d7098531cec85773a Mon Sep 17 00:00:00 2001 From: Dmitry Chapyshev Date: Wed, 25 Feb 2009 15:26:49 +0000 Subject: [PATCH] - Add inseng, localspl, wuapi from Wine svn path=/trunk/; revision=39751 --- reactos/baseaddress.rbuild | 3 + reactos/boot/bootdata/packages/reactos.dff | 3 + reactos/dll/win32/inseng/inseng.rbuild | 16 + reactos/dll/win32/inseng/inseng.spec | 12 + reactos/dll/win32/inseng/inseng_main.c | 72 + reactos/dll/win32/inseng/regsvr.c | 501 ++++++ reactos/dll/win32/localspl/localmon.c | 815 +++++++++ reactos/dll/win32/localspl/localspl.rbuild | 17 + reactos/dll/win32/localspl/localspl.rc | 52 + reactos/dll/win32/localspl/localspl.spec | 64 + reactos/dll/win32/localspl/localspl_main.c | 56 + reactos/dll/win32/localspl/localspl_private.h | 71 + reactos/dll/win32/localspl/provider.c | 1554 +++++++++++++++++ reactos/dll/win32/localspl/spl_Da.rc | 27 + reactos/dll/win32/localspl/spl_De.rc | 28 + reactos/dll/win32/localspl/spl_En.rc | 28 + reactos/dll/win32/localspl/spl_Fr.rc | 27 + reactos/dll/win32/localspl/spl_Ko.rc | 29 + reactos/dll/win32/localspl/spl_Nl.rc | 27 + reactos/dll/win32/localspl/spl_No.rc | 27 + reactos/dll/win32/localspl/spl_Pl.rc | 29 + reactos/dll/win32/localspl/spl_Pt.rc | 27 + reactos/dll/win32/localspl/spl_Ro.rc | 27 + reactos/dll/win32/localspl/spl_Ru.rc | 27 + reactos/dll/win32/localspl/spl_Si.rc | 31 + reactos/dll/win32/localspl/spl_Sv.rc | 27 + reactos/dll/win32/localspl/spl_Zh.rc | 40 + reactos/dll/win32/win32.rbuild | 9 + reactos/dll/win32/wuapi/downloader.c | 267 +++ reactos/dll/win32/wuapi/installer.c | 253 +++ reactos/dll/win32/wuapi/main.c | 154 ++ reactos/dll/win32/wuapi/regsvr.c | 430 +++++ reactos/dll/win32/wuapi/searcher.c | 257 +++ reactos/dll/win32/wuapi/session.c | 236 +++ reactos/dll/win32/wuapi/updates.c | 221 +++ reactos/dll/win32/wuapi/wuapi.rbuild | 21 + reactos/dll/win32/wuapi/wuapi.spec | 4 + reactos/dll/win32/wuapi/wuapi_private.h | 23 + reactos/include/psdk/psdk.rbuild | 1 + reactos/include/psdk/wuapi.idl | 359 ++++ reactos/media/doc/README.WINE | 3 + 41 files changed, 5875 insertions(+) create mode 100644 reactos/dll/win32/inseng/inseng.rbuild create mode 100644 reactos/dll/win32/inseng/inseng.spec create mode 100644 reactos/dll/win32/inseng/inseng_main.c create mode 100644 reactos/dll/win32/inseng/regsvr.c create mode 100644 reactos/dll/win32/localspl/localmon.c create mode 100644 reactos/dll/win32/localspl/localspl.rbuild create mode 100644 reactos/dll/win32/localspl/localspl.rc create mode 100644 reactos/dll/win32/localspl/localspl.spec create mode 100644 reactos/dll/win32/localspl/localspl_main.c create mode 100644 reactos/dll/win32/localspl/localspl_private.h create mode 100644 reactos/dll/win32/localspl/provider.c create mode 100644 reactos/dll/win32/localspl/spl_Da.rc create mode 100644 reactos/dll/win32/localspl/spl_De.rc create mode 100644 reactos/dll/win32/localspl/spl_En.rc create mode 100644 reactos/dll/win32/localspl/spl_Fr.rc create mode 100644 reactos/dll/win32/localspl/spl_Ko.rc create mode 100644 reactos/dll/win32/localspl/spl_Nl.rc create mode 100644 reactos/dll/win32/localspl/spl_No.rc create mode 100644 reactos/dll/win32/localspl/spl_Pl.rc create mode 100644 reactos/dll/win32/localspl/spl_Pt.rc create mode 100644 reactos/dll/win32/localspl/spl_Ro.rc create mode 100644 reactos/dll/win32/localspl/spl_Ru.rc create mode 100644 reactos/dll/win32/localspl/spl_Si.rc create mode 100644 reactos/dll/win32/localspl/spl_Sv.rc create mode 100644 reactos/dll/win32/localspl/spl_Zh.rc create mode 100644 reactos/dll/win32/wuapi/downloader.c create mode 100644 reactos/dll/win32/wuapi/installer.c create mode 100644 reactos/dll/win32/wuapi/main.c create mode 100644 reactos/dll/win32/wuapi/regsvr.c create mode 100644 reactos/dll/win32/wuapi/searcher.c create mode 100644 reactos/dll/win32/wuapi/session.c create mode 100644 reactos/dll/win32/wuapi/updates.c create mode 100644 reactos/dll/win32/wuapi/wuapi.rbuild create mode 100644 reactos/dll/win32/wuapi/wuapi.spec create mode 100644 reactos/dll/win32/wuapi/wuapi_private.h create mode 100644 reactos/include/psdk/wuapi.idl 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