diff --git a/reactos/dll/win32/inetmib1/main.c b/reactos/dll/win32/inetmib1/main.c index 3b39174bf61..1093117b5ad 100644 --- a/reactos/dll/win32/inetmib1/main.c +++ b/reactos/dll/win32/inetmib1/main.c @@ -125,6 +125,7 @@ static BOOL mib2IfNumberQuery(BYTE bPduType, SnmpVarBind *pVarBind, AsnInteger32 *pErrorStatus) { AsnObjectIdentifier numberOid = DEFINE_OID(mib2IfNumber); + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -155,12 +156,13 @@ static BOOL mib2IfNumberQuery(BYTE bPduType, SnmpVarBind *pVarBind, break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static void copyOperStatus(AsnAny *value, void *src) @@ -431,45 +433,61 @@ static AsnInteger32 getItemAndInstanceFromTable(AsnObjectIdentifier *oid, return ret; } -static void setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, +static INT setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, UINT item) { UINT id; AsnObjectIdentifier oid; + INT ret; - SnmpUtilOidCpy(dst, base); - oid.idLength = 1; - oid.ids = &id; - id = item; - SnmpUtilOidAppend(dst, &oid); + ret = SnmpUtilOidCpy(dst, base); + if (ret) + { + oid.idLength = 1; + oid.ids = &id; + id = item; + ret = SnmpUtilOidAppend(dst, &oid); + } + return ret; } -static void setOidWithItemAndIpAddr(AsnObjectIdentifier *dst, +static INT setOidWithItemAndIpAddr(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, UINT item, DWORD addr) { UINT id; BYTE *ptr; AsnObjectIdentifier oid; + INT ret; - setOidWithItem(dst, base, item); - oid.idLength = 1; - oid.ids = &id; - for (ptr = (BYTE *)&addr; ptr < (BYTE *)&addr + sizeof(DWORD); ptr++) + ret = setOidWithItem(dst, base, item); + if (ret) { - id = *ptr; - SnmpUtilOidAppend(dst, &oid); + oid.idLength = 1; + oid.ids = &id; + for (ptr = (BYTE *)&addr; ret && ptr < (BYTE *)&addr + sizeof(DWORD); + ptr++) + { + id = *ptr; + ret = SnmpUtilOidAppend(dst, &oid); + } } + return ret; } -static void setOidWithItemAndInteger(AsnObjectIdentifier *dst, +static INT setOidWithItemAndInteger(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, UINT item, UINT instance) { AsnObjectIdentifier oid; + INT ret; - setOidWithItem(dst, base, item); - oid.idLength = 1; - oid.ids = &instance; - SnmpUtilOidAppend(dst, &oid); + ret = setOidWithItem(dst, base, item); + if (ret) + { + oid.idLength = 1; + oid.ids = &instance; + ret = SnmpUtilOidAppend(dst, &oid); + } + return ret; } static struct structToAsnValue mib2IfEntryMap[] = { @@ -502,6 +520,7 @@ static BOOL mib2IfEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind, AsnInteger32 *pErrorStatus) { AsnObjectIdentifier entryOid = DEFINE_OID(mib2IfEntry); + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -536,20 +555,21 @@ static BOOL mib2IfEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind, &ifTable->table[tableIndex - 1], item, bPduType, pVarBind); if (bPduType == SNMP_PDU_GETNEXT) - setOidWithItemAndInteger(&pVarBind->name, &entryOid, - item, tableIndex); + ret = setOidWithItemAndInteger(&pVarBind->name, + &entryOid, item, tableIndex); } } } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2Ip[] = { 1,3,6,1,2,1,4 }; @@ -591,6 +611,7 @@ static BOOL mib2IpStatsQuery(BYTE bPduType, SnmpVarBind *pVarBind, { AsnObjectIdentifier myOid = DEFINE_OID(mib2Ip); UINT item = 0; + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -606,17 +627,18 @@ static BOOL mib2IpStatsQuery(BYTE bPduType, SnmpVarBind *pVarBind, *pErrorStatus = mapStructEntryToValue(mib2IpMap, DEFINE_SIZEOF(mib2IpMap), &ipStats, item, bPduType, pVarBind); if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) - setOidWithItem(&pVarBind->name, &myOid, item); + ret = setOidWithItem(&pVarBind->name, &myOid, item); } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1 }; @@ -669,6 +691,7 @@ static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind, { AsnObjectIdentifier myOid = DEFINE_OID(mib2IpAddr); UINT tableIndex = 0, item = 0; + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -689,18 +712,19 @@ static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind, DEFINE_SIZEOF(mib2IpAddrMap), &ipAddrTable->table[tableIndex - 1], item, bPduType, pVarBind); if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) - setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, + ret = setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, ipAddrTable->table[tableIndex - 1].dwAddr); } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2IpRoute[] = { 1,3,6,1,2,1,4,21,1 }; @@ -760,6 +784,7 @@ static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind, { AsnObjectIdentifier myOid = DEFINE_OID(mib2IpRoute); UINT tableIndex = 0, item = 0; + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -780,18 +805,19 @@ static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind, DEFINE_SIZEOF(mib2IpRouteMap), &ipRouteTable->table[tableIndex - 1], item, bPduType, pVarBind); if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) - setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, + ret = setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, ipRouteTable->table[tableIndex - 1].dwForwardDest); } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2IpNet[] = { 1,3,6,1,2,1,4,22,1 }; @@ -828,6 +854,7 @@ static BOOL mib2IpNetQuery(BYTE bPduType, SnmpVarBind *pVarBind, AsnInteger32 *pErrorStatus) { AsnObjectIdentifier myOid = DEFINE_OID(mib2IpNet); + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -856,20 +883,21 @@ static BOOL mib2IpNetQuery(BYTE bPduType, SnmpVarBind *pVarBind, DEFINE_SIZEOF(mib2IpNetMap), &ipNetTable[tableIndex - 1], item, bPduType, pVarBind); if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) - setOidWithItemAndInteger(&pVarBind->name, &myOid, item, - tableIndex); + ret = setOidWithItemAndInteger(&pVarBind->name, &myOid, + item, tableIndex); } } } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2Icmp[] = { 1,3,6,1,2,1,5 }; @@ -914,6 +942,7 @@ static BOOL mib2IcmpQuery(BYTE bPduType, SnmpVarBind *pVarBind, { AsnObjectIdentifier myOid = DEFINE_OID(mib2Icmp); UINT item = 0; + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -930,17 +959,18 @@ static BOOL mib2IcmpQuery(BYTE bPduType, SnmpVarBind *pVarBind, DEFINE_SIZEOF(mib2IcmpMap), &icmpStats, item, bPduType, pVarBind); if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) - setOidWithItem(&pVarBind->name, &myOid, item); + ret = setOidWithItem(&pVarBind->name, &myOid, item); } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2Tcp[] = { 1,3,6,1,2,1,6 }; @@ -974,6 +1004,7 @@ static BOOL mib2TcpQuery(BYTE bPduType, SnmpVarBind *pVarBind, { AsnObjectIdentifier myOid = DEFINE_OID(mib2Tcp); UINT item = 0; + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -989,17 +1020,18 @@ static BOOL mib2TcpQuery(BYTE bPduType, SnmpVarBind *pVarBind, *pErrorStatus = mapStructEntryToValue(mib2TcpMap, DEFINE_SIZEOF(mib2TcpMap), &tcpStats, item, bPduType, pVarBind); if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) - setOidWithItem(&pVarBind->name, &myOid, item); + ret = setOidWithItem(&pVarBind->name, &myOid, item); } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2Udp[] = { 1,3,6,1,2,1,7 }; @@ -1022,6 +1054,7 @@ static BOOL mib2UdpQuery(BYTE bPduType, SnmpVarBind *pVarBind, { AsnObjectIdentifier myOid = DEFINE_OID(mib2Udp); UINT item; + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -1037,17 +1070,18 @@ static BOOL mib2UdpQuery(BYTE bPduType, SnmpVarBind *pVarBind, *pErrorStatus = mapStructEntryToValue(mib2UdpMap, DEFINE_SIZEOF(mib2UdpMap), &udpStats, item, bPduType, pVarBind); if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) - setOidWithItem(&pVarBind->name, &myOid, item); + ret = setOidWithItem(&pVarBind->name, &myOid, item); } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } static UINT mib2UdpEntry[] = { 1,3,6,1,2,1,7,5,1 }; @@ -1102,6 +1136,7 @@ static BOOL mib2UdpEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind, AsnInteger32 *pErrorStatus) { AsnObjectIdentifier myOid = DEFINE_OID(mib2UdpEntry); + BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); @@ -1131,23 +1166,27 @@ static BOOL mib2UdpEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind, { AsnObjectIdentifier oid; - setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, + ret = setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, udpTable->table[tableIndex - 1].dwLocalAddr); - oid.idLength = 1; - oid.ids = &udpTable->table[tableIndex - 1].dwLocalPort; - SnmpUtilOidAppend(&pVarBind->name, &oid); + if (ret) + { + oid.idLength = 1; + oid.ids = &udpTable->table[tableIndex - 1].dwLocalPort; + ret = SnmpUtilOidAppend(&pVarBind->name, &oid); + } } } } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } - return TRUE; + return ret; } /* This list MUST BE lexicographically sorted */ @@ -1240,6 +1279,7 @@ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, AsnObjectIdentifier mib2oid = DEFINE_OID(mib2); AsnInteger32 error = SNMP_ERRORSTATUS_NOERROR, errorIndex = 0; UINT i; + BOOL ret = TRUE; TRACE("(0x%02x, %p, %p, %p)\n", bPduType, pVarBindList, pErrorStatus, pErrorIndex); @@ -1261,7 +1301,7 @@ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, impl = findSupportedQuery(pVarBindList->list[i].name.ids, len, &matchingIndex); if (impl && impl->query) - impl->query(bPduType, &pVarBindList->list[i], &error); + ret = impl->query(bPduType, &pVarBindList->list[i], &error); else error = SNMP_ERRORSTATUS_NOSUCHNAME; if (error == SNMP_ERRORSTATUS_NOSUCHNAME && @@ -1278,7 +1318,8 @@ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, error = SNMP_ERRORSTATUS_NOERROR; impl = &supportedIDs[matchingIndex]; if (impl->query) - impl->query(bPduType, &pVarBindList->list[i], &error); + ret = impl->query(bPduType, &pVarBindList->list[i], + &error); else error = SNMP_ERRORSTATUS_NOSUCHNAME; } @@ -1288,7 +1329,7 @@ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, if (error == SNMP_ERRORSTATUS_NOSUCHNAME) { SnmpUtilOidFree(&pVarBindList->list[i].name); - SnmpUtilOidCpy(&pVarBindList->list[i].name, + ret = SnmpUtilOidCpy(&pVarBindList->list[i].name, &supportedIDs[matchingIndex - 1].name); pVarBindList->list[i].name.ids[ pVarBindList->list[i].name.idLength - 1] += 1; @@ -1300,7 +1341,7 @@ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, } *pErrorStatus = error; *pErrorIndex = errorIndex; - return TRUE; + return ret; } /***************************************************************************** diff --git a/reactos/dll/win32/localspl/localspl_private.h b/reactos/dll/win32/localspl/localspl_private.h index 0ac63697d03..5174a1a847e 100644 --- a/reactos/dll/win32/localspl/localspl_private.h +++ b/reactos/dll/win32/localspl/localspl_private.h @@ -62,6 +62,11 @@ static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero( size_t len ) return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ); } +static inline void * __WINE_ALLOC_SIZE(2) heap_realloc_zero( void * mem, size_t len ) +{ + return HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len ); +} + static inline BOOL heap_free( void *mem ) { return HeapFree( GetProcessHeap(), 0, mem ); diff --git a/reactos/dll/win32/localspl/provider.c b/reactos/dll/win32/localspl/provider.c index f308e36d7e9..79541db9937 100644 --- a/reactos/dll/win32/localspl/provider.c +++ b/reactos/dll/win32/localspl/provider.c @@ -80,6 +80,13 @@ typedef struct { LPCWSTR versionsubdir; } printenv_t; +typedef struct { + LPWSTR name; + LPWSTR printername; + monitor_t * pm; + HANDLE hXcv; +} printer_t; + /* ############################### */ static struct list monitor_handles = LIST_INIT( monitor_handles ); @@ -88,6 +95,7 @@ static monitor_t * pm_localport; static const PRINTPROVIDOR * pprovider = NULL; static const WCHAR backslashW[] = {'\\',0}; +static const WCHAR bs_ports_bsW[] = {'\\','P','o','r','t','s','\\',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}; @@ -118,20 +126,30 @@ 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 printersW[] = {'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','\\', + 'P','r','i','n','t','e','r','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 version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0}; +static const WCHAR version3_subdirW[] = {'\\','3',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 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 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 WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0}; +static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0}; static const printenv_t env_x86 = {x86_envnameW, x86_subdirW, 3, @@ -273,6 +291,32 @@ static LONG copy_servername_from_name(LPCWSTR name, LPWSTR target) return serverlen; } +/****************************************************************** + * get_basename_from_name (internal) + * + * skip over the serverpart from the full name + * + */ +static LPCWSTR get_basename_from_name(LPCWSTR name) +{ + if (name == NULL) return NULL; + if ((name[0] == '\\') && (name[1] == '\\')) { + /* skip over the servername and search for the following '\' */ + name = strchrW(&name[2], '\\'); + if ((name) && (name[1])) { + /* found a separator ('\') followed by a name: + skip over the separator and return the rest */ + name++; + } + else + { + /* no basename present (we found only a servername) */ + return NULL; + } + } + return name; +} + /****************************************************************** * monitor_unload [internal] * @@ -512,6 +556,65 @@ static DWORD monitor_loadall(void) return loaded; } +/****************************************************************** + * monitor_load_by_port [internal] + * + * load a printmonitor for a given port + * + * On failure, NULL is returned + */ + +static monitor_t * monitor_load_by_port(LPCWSTR portname) +{ + HKEY hroot; + HKEY hport; + LPWSTR buffer; + monitor_t * pm = NULL; + DWORD registered = 0; + DWORD id = 0; + DWORD len; + + TRACE("(%s)\n", debugstr_w(portname)); + + /* Try the Local Monitor first */ + if (RegOpenKeyW(HKEY_LOCAL_MACHINE, winnt_cv_portsW, &hroot) == ERROR_SUCCESS) { + if (RegQueryValueExW(hroot, portname, NULL, NULL, NULL, &len) == ERROR_SUCCESS) { + /* found the portname */ + RegCloseKey(hroot); + return monitor_load(localportW, NULL); + } + RegCloseKey(hroot); + } + + len = MAX_PATH + lstrlenW(bs_ports_bsW) + lstrlenW(portname) + 1; + buffer = heap_alloc(len * sizeof(WCHAR)); + if (buffer == NULL) return NULL; + + if (RegOpenKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) == ERROR_SUCCESS) { + EnterCriticalSection(&monitor_handles_cs); + RegQueryInfoKeyW(hroot, NULL, NULL, NULL, ®istered, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + while ((pm == NULL) && (id < registered)) { + buffer[0] = '\0'; + RegEnumKeyW(hroot, id, buffer, MAX_PATH); + TRACE("testing %s\n", debugstr_w(buffer)); + len = lstrlenW(buffer); + lstrcatW(buffer, bs_ports_bsW); + lstrcatW(buffer, portname); + if (RegOpenKeyW(hroot, buffer, &hport) == ERROR_SUCCESS) { + RegCloseKey(hport); + buffer[len] = '\0'; /* use only the Monitor-Name */ + pm = monitor_load(buffer, NULL); + } + id++; + } + LeaveCriticalSection(&monitor_handles_cs); + RegCloseKey(hroot); + } + heap_free(buffer); + return pm; +} + /****************************************************************** * Return the number of bytes for an multi_sz string. * The result includes all \0s @@ -907,6 +1010,139 @@ static HMODULE driver_load(const printenv_t * env, LPWSTR dllname) return hui; } +/****************************************************************** + * printer_free + * free the data pointer of an opened printer + */ +static VOID printer_free(printer_t * printer) +{ + if (printer->hXcv) + printer->pm->monitor->pfnXcvClosePort(printer->hXcv); + + monitor_unload(printer->pm); + + heap_free(printer->printername); + heap_free(printer->name); + heap_free(printer); +} + +/****************************************************************** + * printer_alloc_handle + * alloc a printer handle and remember the data pointer in the printer handle table + * + */ +static HANDLE printer_alloc_handle(LPCWSTR name, LPPRINTER_DEFAULTSW pDefault) +{ + WCHAR servername[MAX_COMPUTERNAME_LENGTH + 1]; + printer_t *printer = NULL; + LPCWSTR printername; + HKEY hkeyPrinters; + HKEY hkeyPrinter; + DWORD len; + + if (copy_servername_from_name(name, servername)) { + FIXME("server %s not supported\n", debugstr_w(servername)); + SetLastError(ERROR_INVALID_PRINTER_NAME); + return NULL; + } + + printername = get_basename_from_name(name); + if (name != printername) TRACE("converted %s to %s\n", debugstr_w(name), debugstr_w(printername)); + + /* an empty printername is invalid */ + if (printername && (!printername[0])) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + printer = heap_alloc_zero(sizeof(printer_t)); + if (!printer) goto end; + + /* clone the base name. This is NULL for the printserver */ + printer->printername = strdupW(printername); + + /* clone the full name */ + printer->name = strdupW(name); + if (name && (!printer->name)) { + printer_free(printer); + printer = NULL; + } + if (printername) { + len = sizeof(XcvMonitorW)/sizeof(WCHAR) - 1; + if (strncmpW(printername, XcvMonitorW, len) == 0) { + /* OpenPrinter(",XcvMonitor ", ...) detected */ + TRACE(",XcvMonitor: %s\n", debugstr_w(&printername[len])); + printer->pm = monitor_load(&printername[len], NULL); + if (printer->pm == NULL) { + printer_free(printer); + SetLastError(ERROR_UNKNOWN_PORT); + printer = NULL; + goto end; + } + } + else + { + len = sizeof(XcvPortW)/sizeof(WCHAR) - 1; + if (strncmpW( printername, XcvPortW, len) == 0) { + /* OpenPrinter(",XcvPort ", ...) detected */ + TRACE(",XcvPort: %s\n", debugstr_w(&printername[len])); + printer->pm = monitor_load_by_port(&printername[len]); + if (printer->pm == NULL) { + printer_free(printer); + SetLastError(ERROR_UNKNOWN_PORT); + printer = NULL; + goto end; + } + } + } + + if (printer->pm) { + if ((printer->pm->monitor) && (printer->pm->monitor->pfnXcvOpenPort)) { + printer->pm->monitor->pfnXcvOpenPort(&printername[len], + pDefault ? pDefault->DesiredAccess : 0, + &printer->hXcv); + } + if (printer->hXcv == NULL) { + printer_free(printer); + SetLastError(ERROR_INVALID_PARAMETER); + printer = NULL; + goto end; + } + } + else + { + /* Does the Printer exist? */ + if (RegCreateKeyW(HKEY_LOCAL_MACHINE, printersW, &hkeyPrinters) != ERROR_SUCCESS) { + ERR("Can't create Printers key\n"); + printer_free(printer); + SetLastError(ERROR_INVALID_PRINTER_NAME); + printer = NULL; + goto end; + } + if (RegOpenKeyW(hkeyPrinters, printername, &hkeyPrinter) != ERROR_SUCCESS) { + WARN("Printer not found in Registry: %s\n", debugstr_w(printername)); + RegCloseKey(hkeyPrinters); + printer_free(printer); + SetLastError(ERROR_INVALID_PRINTER_NAME); + printer = NULL; + goto end; + } + RegCloseKey(hkeyPrinter); + RegCloseKey(hkeyPrinters); + } + } + else + { + TRACE("using the local printserver\n"); + } + +end: + + TRACE("==> %p\n", printer); + return (HANDLE)printer; +} + + /****************************************************************************** * myAddPrinterDriverEx [internal] * @@ -1213,6 +1449,34 @@ static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDrive return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE); } + +/****************************************************************************** + * fpClosePrinter [exported through PRINTPROVIDOR] + * + * Close a printer handle and free associated resources + * + * PARAMS + * hPrinter [I] Printerhandle to close + * + * RESULTS + * Success: TRUE + * Failure: FALSE + * + */ +static BOOL WINAPI fpClosePrinter(HANDLE hPrinter) +{ + printer_t *printer = (printer_t *) hPrinter; + + TRACE("(%p)\n", hPrinter); + + if (printer) { + printer_free(printer); + return TRUE; + } + return FALSE; +} + + /****************************************************************** * fpDeleteMonitor [exported through PRINTPROVIDOR] * @@ -1425,13 +1689,115 @@ emP_cleanup: return (res); } +/****************************************************************************** + * fpOpenPrinter [exported through PRINTPROVIDOR] + * + * Open a Printer / Printserver or a Printer-Object + * + * PARAMS + * lpPrinterName [I] Name of Printserver, Printer, or Printer-Object + * pPrinter [O] The resulting Handle is stored here + * pDefaults [I] PTR to Default Printer Settings or NULL + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * lpPrinterName is one of: + *| Printserver (NT only): "Servername" or NULL for the local Printserver + *| Printer: "PrinterName" + *| Printer-Object: "PrinterName,Job xxx" + *| XcvMonitor: "Servername,XcvMonitor MonitorName" + *| XcvPort: "Servername,XcvPort PortName" + * + * + */ +static BOOL WINAPI fpOpenPrinter(LPWSTR lpPrinterName, HANDLE *pPrinter, + LPPRINTER_DEFAULTSW pDefaults) +{ + + TRACE("(%s, %p, %p)\n", debugstr_w(lpPrinterName), pPrinter, pDefaults); + + *pPrinter = printer_alloc_handle(lpPrinterName, pDefaults); + + return (*pPrinter != 0); +} + +/****************************************************************************** + * fpXcvData [exported through PRINTPROVIDOR] + * + * Execute commands in the Printmonitor DLL + * + * PARAMS + * hXcv [i] Handle from fpOpenPrinter (with XcvMonitor or XcvPort) + * 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 + * pdwStatus [o] PTR to receive the win32 error code from the Printmonitor DLL + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * Returning "TRUE" does mean, that the Printmonitor DLL was called successful. + * The execution of the command can still fail (check pdwStatus for ERROR_SUCCESS). + * + * Minimal List of commands, that a Printmonitor DLL should support: + * + *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData + *| "AddPort" : Add a Port + *| "DeletePort": Delete a Port + * + * Many Printmonitors support additional commands. Examples for localspl.dll: + * "GetDefaultCommConfig", "SetDefaultCommConfig", + * "GetTransmissionRetryTimeout", "ConfigureLPTPortCommandOK" + * + */ +static BOOL WINAPI fpXcvData(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, + DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, + PDWORD pcbOutputNeeded, PDWORD pdwStatus) +{ + printer_t *printer = (printer_t * ) hXcv; + + TRACE("(%p, %s, %p, %d, %p, %d, %p, %p)\n", hXcv, debugstr_w(pszDataName), + pInputData, cbInputData, pOutputData, + cbOutputData, pcbOutputNeeded, pdwStatus); + + if (!printer || (!printer->hXcv)) { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (!pcbOutputNeeded) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!pszDataName || !pdwStatus || (!pOutputData && (cbOutputData > 0))) { + SetLastError(RPC_X_NULL_REF_POINTER); + return FALSE; + } + + *pcbOutputNeeded = 0; + + *pdwStatus = printer->pm->monitor->pfnXcvDataPort(printer->hXcv, pszDataName, + pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); + + return TRUE; +} + /***************************************************** * setup_provider [internal] */ void setup_provider(void) { static const PRINTPROVIDOR backend = { - NULL, /* fpOpenPrinter */ + fpOpenPrinter, NULL, /* fpSetJob */ NULL, /* fpGetJob */ NULL, /* fpEnumJobs */ @@ -1462,7 +1828,7 @@ void setup_provider(void) NULL, /* fpGetPrinterData */ NULL, /* fpSetPrinterData */ NULL, /* fpWaitForPrinterChange */ - NULL, /* fpClosePrinter */ + fpClosePrinter, NULL, /* fpAddForm */ NULL, /* fpDeleteForm */ NULL, /* fpGetForm */ @@ -1507,7 +1873,7 @@ void setup_provider(void) NULL, /* fpAddPerMachineConnection */ NULL, /* fpDeletePerMachineConnection */ NULL, /* fpEnumPerMachineConnections */ - NULL, /* fpXcvData */ + fpXcvData, fpAddPrinterDriverEx, NULL, /* fpSplReadPrinter */ NULL, /* fpDriverUnloadComplete */ diff --git a/reactos/dll/win32/mciqtz32/mciqtz.c b/reactos/dll/win32/mciqtz32/mciqtz.c index 0435a11f07c..837122747c7 100644 --- a/reactos/dll/win32/mciqtz32/mciqtz.c +++ b/reactos/dll/win32/mciqtz32/mciqtz.c @@ -337,6 +337,110 @@ static DWORD MCIQTZ_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPa return 0; } +/*************************************************************************** + * MCIQTZ_mciGetDevCaps [internal] + */ +static DWORD MCIQTZ_mciGetDevCaps(UINT wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms) +{ + WINE_MCIQTZ* wma; + + TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); + + if (!lpParms) + return MCIERR_NULL_PARAMETER_BLOCK; + + wma = MCIQTZ_mciGetOpenDev(wDevID); + if (!wma) + return MCIERR_INVALID_DEVICE_ID; + + if (!(dwFlags & MCI_STATUS_ITEM)) { + WARN("No capability item specified\n"); + return MCIERR_UNRECOGNIZED_COMMAND; + } + + switch (lpParms->dwItem) { + case MCI_GETDEVCAPS_CAN_RECORD: + lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); + TRACE("MCI_GETDEVCAPS_CAN_RECORD = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_HAS_AUDIO: + lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); + TRACE("MCI_GETDEVCAPS_HAS_AUDIO = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_HAS_VIDEO: + lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); + TRACE("MCI_GETDEVCAPS_HAS_VIDEO = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_DEVICE_TYPE: + lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_DIGITAL_VIDEO, MCI_DEVTYPE_DIGITAL_VIDEO); + TRACE("MCI_GETDEVCAPS_DEVICE_TYPE = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_USES_FILES: + lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); + TRACE("MCI_GETDEVCAPS_USES_FILES = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_COMPOUND_DEVICE: + lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); + TRACE("MCI_GETDEVCAPS_COMPOUND_DEVICE = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_CAN_EJECT: + lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); + TRACE("MCI_GETDEVCAPS_EJECT = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_CAN_PLAY: + lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); + TRACE("MCI_GETDEVCAPS_CAN_PLAY = %08x\n", lpParms->dwReturn); + break; + case MCI_GETDEVCAPS_CAN_SAVE: + lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); + TRACE("MCI_GETDEVCAPS_CAN_SAVE = %08x\n", lpParms->dwReturn); + break; + default: + ERR("Unknown capability %08x\n", lpParms->dwItem); + return MCIERR_UNRECOGNIZED_COMMAND; + } + + return MCI_RESOURCE_RETURNED; +} + +/*************************************************************************** + * MCIQTZ_mciSet [internal] + */ +static DWORD MCIQTZ_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SET_PARMS lpParms) +{ + WINE_MCIQTZ* wma; + + TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); + + if (!lpParms) + return MCIERR_NULL_PARAMETER_BLOCK; + + wma = MCIQTZ_mciGetOpenDev(wDevID); + if (!wma) + return MCIERR_INVALID_DEVICE_ID; + + if (dwFlags & MCI_SET_TIME_FORMAT) { + switch (lpParms->dwTimeFormat) { + case MCI_FORMAT_MILLISECONDS: + TRACE("MCI_SET_TIME_FORMAT = MCI_FORMAT_MILLISECONDS\n"); + wma->time_format = MCI_FORMAT_MILLISECONDS; + break; + case MCI_FORMAT_FRAMES: + TRACE("MCI_SET_TIME_FORMAT = MCI_FORMAT_FRAMES\n"); + wma->time_format = MCI_FORMAT_FRAMES; + break; + default: + WARN("Bad time format %u\n", lpParms->dwTimeFormat); + return MCIERR_BAD_TIME_FORMAT; + } + } + + if (dwFlags & ~MCI_SET_TIME_FORMAT) + FIXME("Flags not supported yet %08lX\n", dwFlags & ~MCI_SET_TIME_FORMAT); + + return 0; +} + /*************************************************************************** * MCIQTZ_mciStatus [internal] */ @@ -415,6 +519,90 @@ static DWORD MCIQTZ_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMS return 0; } +/*************************************************************************** + * MCIQTZ_mciWhere [internal] + */ +static DWORD MCIQTZ_mciWhere(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms) +{ + WINE_MCIQTZ* wma; + IVideoWindow* pVideoWindow; + HRESULT hr; + HWND hWnd; + RECT rc; + + TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); + + if (!lpParms) + return MCIERR_NULL_PARAMETER_BLOCK; + + wma = MCIQTZ_mciGetOpenDev(wDevID); + if (!wma) + return MCIERR_INVALID_DEVICE_ID; + + /* Find if there is a video stream and get the display window */ + hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); + if (FAILED(hr)) { + ERR("Cannot get IVideoWindow interface (hr = %x)\n", hr); + return MCIERR_INTERNAL; + } + + hr = IVideoWindow_get_Owner(pVideoWindow, (OAHWND*)&hWnd); + IVideoWindow_Release(pVideoWindow); + if (FAILED(hr)) { + TRACE("No video stream, returning no window error\n"); + return MCIERR_NO_WINDOW; + } + + if (dwFlags & MCI_DGV_WHERE_SOURCE) { + if (dwFlags & MCI_DGV_WHERE_MAX) + FIXME("MCI_DGV_WHERE_SOURCE_MAX not supported yet\n"); + else + FIXME("MCI_DGV_WHERE_SOURCE not supported yet\n"); + return MCIERR_UNRECOGNIZED_COMMAND; + } + if (dwFlags & MCI_DGV_WHERE_DESTINATION) { + if (dwFlags & MCI_DGV_WHERE_MAX) { + GetClientRect(hWnd, &rc); + TRACE("MCI_DGV_WHERE_DESTINATION_MAX %s\n", wine_dbgstr_rect(&rc)); + } else { + FIXME("MCI_DGV_WHERE_DESTINATION not supported yet\n"); + return MCIERR_UNRECOGNIZED_COMMAND; + } + } + if (dwFlags & MCI_DGV_WHERE_FRAME) { + if (dwFlags & MCI_DGV_WHERE_MAX) + FIXME("MCI_DGV_WHERE_FRAME_MAX not supported yet\n"); + else + FIXME("MCI_DGV_WHERE_FRAME not supported yet\n"); + return MCIERR_UNRECOGNIZED_COMMAND; + } + if (dwFlags & MCI_DGV_WHERE_VIDEO) { + if (dwFlags & MCI_DGV_WHERE_MAX) + FIXME("MCI_DGV_WHERE_VIDEO_MAX not supported yet\n"); + else + FIXME("MCI_DGV_WHERE_VIDEO not supported yet\n"); + return MCIERR_UNRECOGNIZED_COMMAND; + } + if (dwFlags & MCI_DGV_WHERE_WINDOW) { + if (dwFlags & MCI_DGV_WHERE_MAX) { + GetWindowRect(GetDesktopWindow(), &rc); + TRACE("MCI_DGV_WHERE_WINDOW_MAX %s\n", wine_dbgstr_rect(&rc)); + } else { + GetWindowRect(hWnd, &rc); + TRACE("MCI_DGV_WHERE_WINDOW %s\n", wine_dbgstr_rect(&rc)); + } + } + + /* In MCI, RECT structure is used differently: rc.right = width & rc.bottom = height + * So convert the normal RECT into a MCI RECT before returning */ + lpParms->rc.left = rc.left; + lpParms->rc.top = rc.right; + lpParms->rc.right = rc.right - rc.left; + lpParms->rc.bottom = rc.bottom - rc.top; + + return 0; +} + /*======================================================================* * MCI QTZ entry points * *======================================================================*/ @@ -451,12 +639,13 @@ LRESULT CALLBACK MCIQTZ_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, case MCI_PLAY: return MCIQTZ_mciPlay (dwDevID, dwParam1, (LPMCI_PLAY_PARMS) dwParam2); case MCI_SEEK: return MCIQTZ_mciSeek (dwDevID, dwParam1, (LPMCI_SEEK_PARMS) dwParam2); case MCI_STOP: return MCIQTZ_mciStop (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); + case MCI_GETDEVCAPS: return MCIQTZ_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS) dwParam2); + case MCI_SET: return MCIQTZ_mciSet (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS) dwParam2); case MCI_STATUS: return MCIQTZ_mciStatus (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW) dwParam2); + case MCI_WHERE: return MCIQTZ_mciWhere (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2); case MCI_RECORD: - case MCI_SET: case MCI_PAUSE: case MCI_RESUME: - case MCI_GETDEVCAPS: case MCI_INFO: case MCI_PUT: case MCI_WINDOW: @@ -466,7 +655,6 @@ LRESULT CALLBACK MCIQTZ_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, case MCI_REALIZE: case MCI_UNFREEZE: case MCI_UPDATE: - case MCI_WHERE: case MCI_STEP: case MCI_COPY: case MCI_CUT: diff --git a/reactos/dll/win32/mciqtz32/mciqtz_private.h b/reactos/dll/win32/mciqtz32/mciqtz_private.h index 23945a4ff5c..dcfcad0eb4a 100644 --- a/reactos/dll/win32/mciqtz32/mciqtz_private.h +++ b/reactos/dll/win32/mciqtz32/mciqtz_private.h @@ -31,6 +31,7 @@ typedef struct { IGraphBuilder* pgraph; IMediaControl* pmctrl; BOOL started; + DWORD time_format; } WINE_MCIQTZ; #endif /* __WINE_PRIVATE_MCIQTZ_H */ diff --git a/reactos/dll/win32/mscoree/mscoree.spec b/reactos/dll/win32/mscoree/mscoree.spec index 03fbc1c532e..04b5e1cda9c 100644 --- a/reactos/dll/win32/mscoree/mscoree.spec +++ b/reactos/dll/win32/mscoree/mscoree.spec @@ -103,8 +103,8 @@ @ stub StrongNameSignatureGeneration @ stub StrongNameSignatureGenerationEx @ stub StrongNameSignatureSize -@ stub StrongNameSignatureVerification -@ stub StrongNameSignatureVerificationEx +@ stdcall StrongNameSignatureVerification(wstr long ptr) +@ stdcall StrongNameSignatureVerificationEx(wstr long ptr) @ stub StrongNameSignatureVerificationFromImage @ stub StrongNameTokenFromAssembly @ stub StrongNameTokenFromAssemblyEx diff --git a/reactos/dll/win32/mscoree/mscoree_main.c b/reactos/dll/win32/mscoree/mscoree_main.c index 386f4f76707..5b45adbe29a 100644 --- a/reactos/dll/win32/mscoree/mscoree_main.c +++ b/reactos/dll/win32/mscoree/mscoree_main.c @@ -324,6 +324,18 @@ HRESULT WINAPI CorBindToCurrentRuntime(LPCWSTR filename, REFCLSID rclsid, REFIID return E_NOTIMPL; } +BOOL WINAPI StrongNameSignatureVerification(LPCWSTR filename, DWORD inFlags, DWORD* pOutFlags) +{ + FIXME("(%s, 0x%X, %p): stub\n", debugstr_w(filename), inFlags, pOutFlags); + return FALSE; +} + +BOOL WINAPI StrongNameSignatureVerificationEx(LPCWSTR filename, BOOL forceVerification, BOOL* pVerified) +{ + FIXME("(%s, %u, %p): stub\n", debugstr_w(filename), forceVerification, pVerified); + return FALSE; +} + HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { FIXME("(%p, %p, %p): stub\n", rclsid, riid, ppv); diff --git a/reactos/dll/win32/msctf/categorymgr.c b/reactos/dll/win32/msctf/categorymgr.c index 648352af85a..b76bebbbd1e 100644 --- a/reactos/dll/win32/msctf/categorymgr.c +++ b/reactos/dll/win32/msctf/categorymgr.c @@ -144,9 +144,37 @@ static HRESULT WINAPI CategoryMgr_RegisterCategory ( ITfCategoryMgr *iface, static HRESULT WINAPI CategoryMgr_UnregisterCategory ( ITfCategoryMgr *iface, REFCLSID rclsid, REFGUID rcatid, REFGUID rguid) { + WCHAR fullkey[110]; + WCHAR buf[39]; + WCHAR buf2[39]; + HKEY tipkey; CategoryMgr *This = (CategoryMgr*)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + static const WCHAR ctg[] = {'C','a','t','e','g','o','r','y',0}; + static const WCHAR itm[] = {'I','t','e','m',0}; + static const WCHAR fmt[] = {'%','s','\\','%','s',0}; + static const WCHAR fmt2[] = {'%','s','\\','%','s','\\','%','s','\\','%','s',0}; + + TRACE("(%p) %s %s %s\n",This,debugstr_guid(rclsid), debugstr_guid(rcatid), debugstr_guid(rguid)); + + StringFromGUID2(rclsid, buf, 39); + sprintfW(fullkey,fmt,szwSystemTIPKey,buf); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE, + &tipkey ) != ERROR_SUCCESS) + return E_FAIL; + + StringFromGUID2(rcatid, buf, 39); + StringFromGUID2(rguid, buf2, 39); + sprintfW(fullkey,fmt2,ctg,ctg,buf,buf2); + + sprintfW(fullkey,fmt2,ctg,itm,buf2,buf); + RegDeleteTreeW(tipkey, fullkey); + sprintfW(fullkey,fmt2,ctg,itm,buf2,buf); + RegDeleteTreeW(tipkey, fullkey); + + RegCloseKey(tipkey); + return S_OK; } static HRESULT WINAPI CategoryMgr_EnumCategoriesInItem ( ITfCategoryMgr *iface, @@ -284,25 +312,77 @@ static HRESULT WINAPI CategoryMgr_RegisterGUID ( ITfCategoryMgr *iface, REFGUID rguid, TfGuidAtom *pguidatom ) { + DWORD index; + GUID *checkguid; + DWORD id; CategoryMgr *This = (CategoryMgr*)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + TRACE("(%p) %s %p\n",This,debugstr_guid(rguid),pguidatom); + + if (!pguidatom) + return E_INVALIDARG; + + index = 0; + do { + id = enumerate_Cookie(COOKIE_MAGIC_GUIDATOM,&index); + if (id && IsEqualGUID(rguid,get_Cookie_data(id))) + { + *pguidatom = id; + return S_OK; + } + } while(id); + + checkguid = HeapAlloc(GetProcessHeap(),0,sizeof(GUID)); + *checkguid = *rguid; + id = generate_Cookie(COOKIE_MAGIC_GUIDATOM,checkguid); + + if (!id) + { + HeapFree(GetProcessHeap(),0,checkguid); + return E_FAIL; + } + + *pguidatom = id; + + return S_OK; } static HRESULT WINAPI CategoryMgr_GetGUID ( ITfCategoryMgr *iface, TfGuidAtom guidatom, GUID *pguid) { CategoryMgr *This = (CategoryMgr*)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + TRACE("(%p) %i\n",This,guidatom); + + if (!pguid) + return E_INVALIDARG; + + *pguid = GUID_NULL; + + if (get_Cookie_magic(guidatom) == COOKIE_MAGIC_GUIDATOM) + *pguid = *((REFGUID)get_Cookie_data(guidatom)); + + return S_OK; } static HRESULT WINAPI CategoryMgr_IsEqualTfGuidAtom ( ITfCategoryMgr *iface, TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual) { CategoryMgr *This = (CategoryMgr*)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + TRACE("(%p) %i %s %p\n",This,guidatom,debugstr_guid(rguid),pfEqual); + + if (!pfEqual) + return E_INVALIDARG; + + *pfEqual = FALSE; + if (get_Cookie_magic(guidatom) == COOKIE_MAGIC_GUIDATOM) + { + if (IsEqualGUID(rguid,get_Cookie_data(guidatom))) + *pfEqual = TRUE; + } + + return S_OK; } diff --git a/reactos/dll/win32/msctf/inputprocessor.c b/reactos/dll/win32/msctf/inputprocessor.c index 7df55753360..38e93688596 100644 --- a/reactos/dll/win32/msctf/inputprocessor.c +++ b/reactos/dll/win32/msctf/inputprocessor.c @@ -288,18 +288,61 @@ static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile( ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, REFGUID guidProfiles) { + HRESULT hr; + BOOL enabled; + TF_LANGUAGEPROFILE LanguageProfile; InputProcessorProfiles *This = (InputProcessorProfiles*)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + TRACE("(%p) %s %x %s\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfiles)); + + if (langid != This->currentLanguage) return E_INVALIDARG; + + if (get_active_textservice(rclsid,NULL)) + { + TRACE("Already Active\n"); + return E_FAIL; + } + + hr = ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface, rclsid, + langid, guidProfiles, &enabled); + if (FAILED(hr) || !enabled) + { + TRACE("Not Enabled\n"); + return E_FAIL; + } + + LanguageProfile.clsid = *rclsid; + LanguageProfile.langid = langid; + LanguageProfile.guidProfile = *guidProfiles; + + hr = add_active_textservice(&LanguageProfile); + + return hr; } static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile( ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid, GUID *pguidProfile) { + TF_LANGUAGEPROFILE profile; InputProcessorProfiles *This = (InputProcessorProfiles*)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + TRACE("(%p) %s %p %p\n",This,debugstr_guid(rclsid),plangid,pguidProfile); + + if (!rclsid || !plangid || !pguidProfile) + return E_INVALIDARG; + + if (get_active_textservice(rclsid, &profile)) + { + *plangid = profile.langid; + *pguidProfile = profile.guidProfile; + return S_OK; + } + else + { + *pguidProfile = GUID_NULL; + return S_FALSE; + } } static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription( @@ -756,8 +799,7 @@ static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LA tflp->clsid = clsid; tflp->langid = This->langid; - /* FIXME */ - tflp->fActive = FALSE; + tflp->fActive = get_active_textservice(&clsid, NULL); tflp->guidProfile = profile; if (ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid, &tflp->catid, tipcats, 3) != S_OK) diff --git a/reactos/dll/win32/msctf/msctf.c b/reactos/dll/win32/msctf/msctf.c index fac0f9d90bb..c8dd486c63b 100644 --- a/reactos/dll/win32/msctf/msctf.c +++ b/reactos/dll/win32/msctf/msctf.c @@ -26,6 +26,7 @@ #define COBJMACROS #include "wine/debug.h" +#include "wine/list.h" #include "windef.h" #include "winbase.h" #include "winreg.h" @@ -50,11 +51,28 @@ typedef struct LPVOID data; } CookieInternal; +typedef struct { + TF_LANGUAGEPROFILE LanguageProfile; + ITfTextInputProcessor *pITfTextInputProcessor; + ITfThreadMgr *pITfThreadMgr; + TfClientId tid; +} ActivatedTextService; + +typedef struct +{ + struct list entry; + ActivatedTextService *ats; +} AtsEntry; + static CookieInternal *cookies; static UINT id_last; static UINT array_size; +static struct list AtsList = LIST_INIT(AtsList); +static UINT activated = 0; + DWORD tlsIndex = 0; +TfClientId processId = 0; const WCHAR szwSystemTIPKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F','\\','T','I','P',0}; @@ -252,6 +270,192 @@ LPVOID remove_Cookie(DWORD id) return cookies[index].data; } +DWORD enumerate_Cookie(DWORD magic, DWORD *index) +{ + int i; + for (i = *index; i < id_last; i++) + if (cookies[i].id != 0 && cookies[i].magic == magic) + { + *index = (i+1); + return cookies[i].id; + } + return 0x0; +} + +/***************************************************************************** + * Active Text Service Management + *****************************************************************************/ +static HRESULT activate_given_ts(ActivatedTextService *actsvr, ITfThreadMgr* tm) +{ + HRESULT hr; + + /* Already Active? */ + if (actsvr->pITfTextInputProcessor) + return S_OK; + + hr = CoCreateInstance (&actsvr->LanguageProfile.clsid, NULL, CLSCTX_INPROC_SERVER, + &IID_ITfTextInputProcessor, (void**)&actsvr->pITfTextInputProcessor); + if (FAILED(hr)) return hr; + + hr = ITfTextInputProcessor_Activate(actsvr->pITfTextInputProcessor, tm, actsvr->tid); + if (FAILED(hr)) + { + ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); + actsvr->pITfTextInputProcessor = NULL; + return hr; + } + + actsvr->pITfThreadMgr = tm; + ITfThreadMgr_AddRef(tm); + return hr; +} + +static HRESULT deactivate_given_ts(ActivatedTextService *actsvr) +{ + HRESULT hr = S_OK; + + if (actsvr->pITfTextInputProcessor) + { + hr = ITfTextInputProcessor_Deactivate(actsvr->pITfTextInputProcessor); + ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); + ITfThreadMgr_Release(actsvr->pITfThreadMgr); + actsvr->pITfTextInputProcessor = NULL; + actsvr->pITfThreadMgr = NULL; + } + + return hr; +} + +static void deactivate_remove_conflicting_ts(REFCLSID catid) +{ + AtsEntry *ats, *cursor2; + + LIST_FOR_EACH_ENTRY_SAFE(ats, cursor2, &AtsList, AtsEntry, entry) + { + if (IsEqualCLSID(catid,&ats->ats->LanguageProfile.catid)) + { + deactivate_given_ts(ats->ats); + list_remove(&ats->entry); + HeapFree(GetProcessHeap(),0,ats->ats); + HeapFree(GetProcessHeap(),0,ats); + /* we are guarenteeing there is only 1 */ + break; + } + } +} + +HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp) +{ + ActivatedTextService *actsvr; + ITfCategoryMgr *catmgr; + AtsEntry *entry; + ITfThreadMgr *tm = (ITfThreadMgr*)TlsGetValue(tlsIndex); + ITfClientId *clientid; + + if (!tm) return E_UNEXPECTED; + + actsvr = HeapAlloc(GetProcessHeap(),0,sizeof(ActivatedTextService)); + if (!actsvr) return E_OUTOFMEMORY; + + entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry)); + + if (!entry) + { + HeapFree(GetProcessHeap(),0,actsvr); + return E_OUTOFMEMORY; + } + + ITfThreadMgr_QueryInterface(tm,&IID_ITfClientId,(LPVOID)&clientid); + ITfClientId_GetClientId(clientid, &lp->clsid, &actsvr->tid); + ITfClientId_Release(clientid); + + if (!actsvr->tid) + { + HeapFree(GetProcessHeap(),0,actsvr); + return E_OUTOFMEMORY; + } + + actsvr->pITfTextInputProcessor = NULL; + actsvr->LanguageProfile = *lp; + actsvr->LanguageProfile.fActive = TRUE; + + /* get TIP category */ + if (SUCCEEDED(CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr))) + { + static const GUID *list[3] = {&GUID_TFCAT_TIP_SPEECH, &GUID_TFCAT_TIP_KEYBOARD, &GUID_TFCAT_TIP_HANDWRITING}; + + ITfCategoryMgr_FindClosestCategory(catmgr, + &actsvr->LanguageProfile.clsid, &actsvr->LanguageProfile.catid, + list, 3); + + ITfCategoryMgr_Release(catmgr); + } + else + { + ERR("CategoryMgr construction failed\n"); + actsvr->LanguageProfile.catid = GUID_NULL; + } + + if (!IsEqualGUID(&actsvr->LanguageProfile.catid,&GUID_NULL)) + deactivate_remove_conflicting_ts(&actsvr->LanguageProfile.catid); + + if (activated > 0) + activate_given_ts(actsvr, tm); + + entry->ats = actsvr; + list_add_head(&AtsList, &entry->entry); + + return S_OK; +} + +BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile) +{ + AtsEntry *ats; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + { + if (IsEqualCLSID(rclsid,&ats->ats->LanguageProfile.clsid)) + { + if (profile) + *profile = ats->ats->LanguageProfile; + return TRUE; + } + } + return FALSE; +} + +HRESULT activate_textservices(ITfThreadMgr *tm) +{ + HRESULT hr = S_OK; + AtsEntry *ats; + + activated ++; + if (activated > 1) + return S_OK; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + { + hr = activate_given_ts(ats->ats, tm); + if (FAILED(hr)) + FIXME("Failed to activate text service\n"); + } + return hr; +} + +HRESULT deactivate_textservices(void) +{ + AtsEntry *ats; + + if (activated > 0) + activated --; + + if (activated == 0) + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + deactivate_given_ts(ats->ats); + + return S_OK; +} + /************************************************************************* * MSCTF DllMain */ diff --git a/reactos/dll/win32/msctf/msctf_internal.h b/reactos/dll/win32/msctf/msctf_internal.h index a9f79827855..433b79ea6af 100644 --- a/reactos/dll/win32/msctf/msctf_internal.h +++ b/reactos/dll/win32/msctf/msctf_internal.h @@ -23,8 +23,10 @@ #define COOKIE_MAGIC_TMSINK 0x0010 #define COOKIE_MAGIC_CONTEXTSINK 0x0020 +#define COOKIE_MAGIC_GUIDATOM 0x0030 extern DWORD tlsIndex; +extern TfClientId processId; extern HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); extern HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink*, ITfDocumentMgr **ppOut); @@ -37,6 +39,13 @@ extern DWORD generate_Cookie(DWORD magic, LPVOID data); extern DWORD get_Cookie_magic(DWORD id); extern LPVOID get_Cookie_data(DWORD id); extern LPVOID remove_Cookie(DWORD id); +extern DWORD enumerate_Cookie(DWORD magic, DWORD *index); + +/* activated text services functions */ +extern HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp); +extern BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *lp); +extern HRESULT activate_textservices(ITfThreadMgr *tm); +extern HRESULT deactivate_textservices(void); extern const WCHAR szwSystemTIPKey[]; #endif /* __WINE_MSCTF_I_H */ diff --git a/reactos/dll/win32/msctf/threadmgr.c b/reactos/dll/win32/msctf/threadmgr.c index 2d43a198072..2afee3913bc 100644 --- a/reactos/dll/win32/msctf/threadmgr.c +++ b/reactos/dll/win32/msctf/threadmgr.c @@ -56,15 +56,29 @@ typedef struct tagThreadMgrSink { } interfaces; } ThreadMgrSink; +typedef struct tagPreservedKey +{ + struct list entry; + GUID guid; + TF_PRESERVEDKEY prekey; + LPWSTR description; + TfClientId tid; +} PreservedKey; + typedef struct tagACLMulti { const ITfThreadMgrVtbl *ThreadMgrVtbl; const ITfSourceVtbl *SourceVtbl; const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl; + const ITfMessagePumpVtbl *MessagePumpVtbl; + const ITfClientIdVtbl *ClientIdVtbl; LONG refCount; const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */ ITfDocumentMgr *focus; + LONG activationCount; + + struct list CurrentPreservedKeys; /* kept as separate lists to reduce unnecessary iterations */ struct list ActiveLanguageProfileNotifySink; @@ -85,6 +99,16 @@ static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface) return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl)); } +static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface) +{ + return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl)); +} + +static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface) +{ + return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl)); +} + static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface) { return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl)); @@ -143,6 +167,14 @@ static void ThreadMgr_Destructor(ThreadMgr *This) free_sink(sink); } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys) + { + PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry); + list_remove(cursor); + HeapFree(GetProcessHeap(),0,key->description); + HeapFree(GetProcessHeap(),0,key); + } + HeapFree(GetProcessHeap(),0,This); } @@ -163,6 +195,14 @@ static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, { *ppvOut = &This->KeystrokeMgrVtbl; } + else if (IsEqualIID(iid, &IID_ITfMessagePump)) + { + *ppvOut = &This->MessagePumpVtbl; + } + else if (IsEqualIID(iid, &IID_ITfClientId)) + { + *ppvOut = &This->ClientIdVtbl; + } if (*ppvOut) { @@ -198,23 +238,48 @@ static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface) static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid) { ThreadMgr *This = (ThreadMgr *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + TRACE("(%p) %p\n",This, ptid); + + if (!ptid) + return E_INVALIDARG; + + if (!processId) + { + GUID guid; + CoCreateGuid(&guid); + ITfClientId_GetClientId((ITfClientId*)&This->ClientIdVtbl,&guid,&processId); + } + + activate_textservices(iface); + This->activationCount++; + *ptid = processId; + return S_OK; } static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface) { ThreadMgr *This = (ThreadMgr *)iface; - FIXME("STUB:(%p)\n",This); + TRACE("(%p)\n",This); - if (This->focus) + if (This->activationCount == 0) + return E_UNEXPECTED; + + This->activationCount --; + + if (This->activationCount == 0) { - ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus); - ITfDocumentMgr_Release(This->focus); - This->focus = 0; + if (This->focus) + { + ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus); + ITfDocumentMgr_Release(This->focus); + This->focus = 0; + } } - return E_NOTIMPL; + deactivate_textservices(); + + return S_OK; } static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr @@ -508,8 +573,25 @@ static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface, REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered) { ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + struct list *cursor; + + TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered); + + if (!rguid || !pprekey || !pfRegistered) + return E_INVALIDARG; + + LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys) + { + PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry); + if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers) + { + *pfRegistered = TRUE; + return S_OK; + } + } + + *pfRegistered = FALSE; + return S_FALSE; } static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface, @@ -517,16 +599,71 @@ static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface, const WCHAR *pchDesc, ULONG cchDesc) { ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + struct list *cursor; + PreservedKey *newkey; + + TRACE("(%p) %x %s (%x,%x) %s\n",This,tid, debugstr_guid(rguid),(prekey)?prekey->uVKey:0,(prekey)?prekey->uModifiers:0,debugstr_wn(pchDesc,cchDesc)); + + if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc)) + return E_INVALIDARG; + + LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys) + { + PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry); + if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers) + return TF_E_ALREADY_EXISTS; + } + + newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey)); + if (!newkey) + return E_OUTOFMEMORY; + + newkey->guid = *rguid; + newkey->prekey = *prekey; + newkey->tid = tid; + if (cchDesc) + { + newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR)); + if (!newkey->description) + { + HeapFree(GetProcessHeap(),0,newkey); + return E_OUTOFMEMORY; + } + memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR)); + } + + list_add_head(&This->CurrentPreservedKeys,&newkey->entry); + + return S_OK; } static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface, REFGUID rguid, const TF_PRESERVEDKEY *pprekey) { ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + PreservedKey* key = NULL; + struct list *cursor; + TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0); + + if (!pprekey || !rguid) + return E_INVALIDARG; + + LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys) + { + key = LIST_ENTRY(cursor,PreservedKey,entry); + if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers) + break; + key = NULL; + } + + if (!key) + return CONNECT_E_NOCONNECTION; + + list_remove(&key->entry); + HeapFree(GetProcessHeap(),0,key->description); + HeapFree(GetProcessHeap(),0,key); + + return S_OK; } static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface, @@ -575,6 +712,128 @@ static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl = KeystrokeMgr_SimulatePreservedKey }; +/***************************************************** + * ITfMessagePump functions + *****************************************************/ + +static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut) +{ + ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface); + return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut); +} + +static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface) +{ + ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface); + return ThreadMgr_AddRef((ITfThreadMgr*)This); +} + +static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface) +{ + ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface); + return ThreadMgr_Release((ITfThreadMgr *)This); +} + +static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface, + LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, + UINT wRemoveMsg, BOOL *pfResult) +{ + if (!pfResult) + return E_INVALIDARG; + *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + return S_OK; +} + +static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface, + LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, + BOOL *pfResult) +{ + if (!pfResult) + return E_INVALIDARG; + *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax); + return S_OK; +} + +static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface, + LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, + UINT wRemoveMsg, BOOL *pfResult) +{ + if (!pfResult) + return E_INVALIDARG; + *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + return S_OK; +} + +static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface, + LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, + BOOL *pfResult) +{ + if (!pfResult) + return E_INVALIDARG; + *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax); + return S_OK; +} + +static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl = +{ + MessagePump_QueryInterface, + MessagePump_AddRef, + MessagePump_Release, + + MessagePump_PeekMessageA, + MessagePump_GetMessageA, + MessagePump_PeekMessageW, + MessagePump_GetMessageW +}; + +/***************************************************** + * ITfClientId functions + *****************************************************/ + +static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut) +{ + ThreadMgr *This = impl_from_ITfClientIdVtbl(iface); + return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut); +} + +static ULONG WINAPI ClientId_AddRef(ITfClientId *iface) +{ + ThreadMgr *This = impl_from_ITfClientIdVtbl(iface); + return ThreadMgr_AddRef((ITfThreadMgr*)This); +} + +static ULONG WINAPI ClientId_Release(ITfClientId *iface) +{ + ThreadMgr *This = impl_from_ITfClientIdVtbl(iface); + return ThreadMgr_Release((ITfThreadMgr *)This); +} + +static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface, + REFCLSID rclsid, TfClientId *ptid) + +{ + HRESULT hr; + ITfCategoryMgr *catmgr; + ThreadMgr *This = impl_from_ITfClientIdVtbl(iface); + + TRACE("(%p) %s\n",This,debugstr_guid(rclsid)); + + CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr); + hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid); + ITfCategoryMgr_Release(catmgr); + + return hr; +} + +static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl = +{ + ClientId_QueryInterface, + ClientId_AddRef, + ClientId_Release, + + ClientId_GetClientId +}; + /***************************************************** * ITfThreadMgrEventSink functions (internal) *****************************************************/ @@ -718,10 +977,14 @@ HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl; This->SourceVtbl = &ThreadMgr_SourceVtbl; This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl; + This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl; + This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl; This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl; This->refCount = 1; TlsSetValue(tlsIndex,This); + list_init(&This->CurrentPreservedKeys); + list_init(&This->ActiveLanguageProfileNotifySink); list_init(&This->DisplayAttributeNotifySink); list_init(&This->KeyTraceEventSink);