/* Copyright (C) 2004 Juan Lang * * This file implements thunks between wide char and multibyte functions for * SSPs that only provide one or the other. * * 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 "windef.h" #include "winbase.h" #include "winnls.h" #include "winternl.h" #include "sspi.h" #include "secur32_priv.h" #include "thunks.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(secur32); SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleA( SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%s %s %d %p %p %p %p %p %p\n", debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (pszPackage) { UNICODE_STRING principal, package; RtlCreateUnicodeStringFromAsciiz(&principal, pszPrincipal); RtlCreateUnicodeStringFromAsciiz(&package, pszPackage); ret = AcquireCredentialsHandleW(principal.Buffer, package.Buffer, fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); RtlFreeUnicodeString(&principal); RtlFreeUnicodeString(&package); } else ret = SEC_E_SECPKG_NOT_FOUND; return ret; } SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleW( SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%s %s %d %p %p %p %p %p %p\n", debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (pszPackage) { PSTR principal, package; principal = SECUR32_AllocMultiByteFromWide(pszPrincipal); package = SECUR32_AllocMultiByteFromWide(pszPackage); ret = AcquireCredentialsHandleA(principal, package, fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); heap_free(principal); heap_free(package); } else ret = SEC_E_SECPKG_NOT_FOUND; return ret; } /* thunking is pretty dicey for these--the output type depends on ulAttribute, * so we have to know about every type the caller does */ SECURITY_STATUS SEC_ENTRY thunk_QueryCredentialsAttributesA( PCredHandle phCredential, ULONG ulAttribute, void *pBuffer) { SECURITY_STATUS ret; TRACE("%p %d %p\n", phCredential, ulAttribute, pBuffer); if (phCredential) { SecurePackage *package = (SecurePackage *)phCredential->dwUpper; PCredHandle cred = (PCredHandle)phCredential->dwLower; if (package && package->provider) { if (package->provider->fnTableW.QueryCredentialsAttributesW) { ret = package->provider->fnTableW.QueryCredentialsAttributesW( cred, ulAttribute, pBuffer); if (ret == SEC_E_OK) { switch (ulAttribute) { case SECPKG_CRED_ATTR_NAMES: { PSecPkgCredentials_NamesW names = (PSecPkgCredentials_NamesW)pBuffer; SEC_WCHAR *oldUser = names->sUserName; if (oldUser) { names->sUserName = (PWSTR)SECUR32_AllocMultiByteFromWide(oldUser); package->provider->fnTableW.FreeContextBuffer( oldUser); } break; } default: WARN("attribute type %d unknown\n", ulAttribute); ret = SEC_E_INTERNAL_ERROR; } } } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_QueryCredentialsAttributesW( PCredHandle phCredential, ULONG ulAttribute, void *pBuffer) { SECURITY_STATUS ret; TRACE("%p %d %p\n", phCredential, ulAttribute, pBuffer); if (phCredential) { SecurePackage *package = (SecurePackage *)phCredential->dwUpper; PCredHandle cred = (PCredHandle)phCredential->dwLower; if (package && package->provider) { if (package->provider->fnTableA.QueryCredentialsAttributesA) { ret = package->provider->fnTableA.QueryCredentialsAttributesA( cred, ulAttribute, pBuffer); if (ret == SEC_E_OK) { switch (ulAttribute) { case SECPKG_CRED_ATTR_NAMES: { PSecPkgCredentials_NamesA names = (PSecPkgCredentials_NamesA)pBuffer; SEC_CHAR *oldUser = names->sUserName; if (oldUser) { names->sUserName = (PSTR)SECUR32_AllocWideFromMultiByte(oldUser); package->provider->fnTableA.FreeContextBuffer( oldUser); } break; } default: WARN("attribute type %d unknown\n", ulAttribute); ret = SEC_E_INTERNAL_ERROR; } } } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_InitializeSecurityContextA( PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext, debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry); if (phCredential) { SecurePackage *package = (SecurePackage *)phCredential->dwUpper; if (package && package->provider) { if (package->provider->fnTableW.InitializeSecurityContextW) { UNICODE_STRING target; RtlCreateUnicodeStringFromAsciiz(&target, pszTargetName); ret = package->provider->fnTableW.InitializeSecurityContextW( phCredential, phContext, target.Buffer, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); RtlFreeUnicodeString(&target); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_InitializeSecurityContextW( PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext, debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry); if (phCredential) { SecurePackage *package = (SecurePackage *)phCredential->dwUpper; if (package && package->provider) { if (package->provider->fnTableA.InitializeSecurityContextA) { PSTR target = SECUR32_AllocMultiByteFromWide(pszTargetName); ret = package->provider->fnTableA.InitializeSecurityContextA( phCredential, phContext, target, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); heap_free(target); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_AddCredentialsA(PCredHandle hCredentials, SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%p %s %s %d %p %p %p %p\n", hCredentials, debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse, pAuthData, pGetKeyFn, pvGetKeyArgument, ptsExpiry); if (hCredentials) { SecurePackage *package = (SecurePackage *)hCredentials->dwUpper; PCredHandle cred = (PCtxtHandle)hCredentials->dwLower; if (package && package->provider) { if (package->provider->fnTableW.AddCredentialsW) { UNICODE_STRING szPrincipal, szPackage; RtlCreateUnicodeStringFromAsciiz(&szPrincipal, pszPrincipal); RtlCreateUnicodeStringFromAsciiz(&szPackage, pszPackage); ret = package->provider->fnTableW.AddCredentialsW( cred, szPrincipal.Buffer, szPackage.Buffer, fCredentialUse, pAuthData, pGetKeyFn, pvGetKeyArgument, ptsExpiry); RtlFreeUnicodeString(&szPrincipal); RtlFreeUnicodeString(&szPackage); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_AddCredentialsW(PCredHandle hCredentials, SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%p %s %s %d %p %p %p %p\n", hCredentials, debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse, pAuthData, pGetKeyFn, pvGetKeyArgument, ptsExpiry); if (hCredentials) { SecurePackage *package = (SecurePackage *)hCredentials->dwUpper; PCredHandle cred = (PCtxtHandle)hCredentials->dwLower; if (package && package->provider) { if (package->provider->fnTableA.AddCredentialsA) { PSTR szPrincipal = SECUR32_AllocMultiByteFromWide(pszPrincipal); PSTR szPackage = SECUR32_AllocMultiByteFromWide(pszPackage); ret = package->provider->fnTableA.AddCredentialsA( cred, szPrincipal, szPackage, fCredentialUse, pAuthData, pGetKeyFn, pvGetKeyArgument, ptsExpiry); heap_free(szPrincipal); heap_free(szPackage); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } static PSecPkgInfoA _copyPackageInfoFlatWToA(const SecPkgInfoW *infoW) { PSecPkgInfoA ret; if (infoW) { size_t bytesNeeded = sizeof(SecPkgInfoA); int nameLen = 0, commentLen = 0; if (infoW->Name) { nameLen = WideCharToMultiByte(CP_ACP, 0, infoW->Name, -1, NULL, 0, NULL, NULL); bytesNeeded += nameLen; } if (infoW->Comment) { commentLen = WideCharToMultiByte(CP_ACP, 0, infoW->Comment, -1, NULL, 0, NULL, NULL); bytesNeeded += commentLen; } ret = heap_alloc(bytesNeeded); if (ret) { PSTR nextString = (PSTR)((PBYTE)ret + sizeof(SecPkgInfoA)); memcpy(ret, infoW, sizeof(SecPkgInfoA)); if (infoW->Name) { ret->Name = nextString; WideCharToMultiByte(CP_ACP, 0, infoW->Name, -1, nextString, nameLen, NULL, NULL); nextString += nameLen; } else ret->Name = NULL; if (infoW->Comment) { ret->Comment = nextString; WideCharToMultiByte(CP_ACP, 0, infoW->Comment, -1, nextString, nameLen, NULL, NULL); } else ret->Comment = NULL; } } else ret = NULL; return ret; } static SECURITY_STATUS thunk_ContextAttributesWToA(SecurePackage *package, ULONG ulAttribute, void *pBuffer) { SECURITY_STATUS ret = SEC_E_OK; if (package && pBuffer) { switch (ulAttribute) { case SECPKG_ATTR_NAMES: { PSecPkgContext_NamesW names = (PSecPkgContext_NamesW)pBuffer; SEC_WCHAR *oldUser = names->sUserName; if (oldUser) { names->sUserName = (PWSTR)SECUR32_AllocMultiByteFromWide(oldUser); package->provider->fnTableW.FreeContextBuffer(oldUser); } break; } case SECPKG_ATTR_AUTHORITY: { PSecPkgContext_AuthorityW names = (PSecPkgContext_AuthorityW)pBuffer; SEC_WCHAR *oldAuth = names->sAuthorityName; if (oldAuth) { names->sAuthorityName = (PWSTR)SECUR32_AllocMultiByteFromWide(oldAuth); package->provider->fnTableW.FreeContextBuffer(oldAuth); } break; } case SECPKG_ATTR_KEY_INFO: { PSecPkgContext_KeyInfoW info = (PSecPkgContext_KeyInfoW)pBuffer; SEC_WCHAR *oldSigAlgName = info->sSignatureAlgorithmName; SEC_WCHAR *oldEncAlgName = info->sEncryptAlgorithmName; if (oldSigAlgName) { info->sSignatureAlgorithmName = (PWSTR)SECUR32_AllocMultiByteFromWide(oldSigAlgName); package->provider->fnTableW.FreeContextBuffer( oldSigAlgName); } if (oldEncAlgName) { info->sEncryptAlgorithmName = (PWSTR)SECUR32_AllocMultiByteFromWide(oldEncAlgName); package->provider->fnTableW.FreeContextBuffer( oldEncAlgName); } break; } case SECPKG_ATTR_PACKAGE_INFO: { PSecPkgContext_PackageInfoW info = (PSecPkgContext_PackageInfoW)pBuffer; PSecPkgInfoW oldPkgInfo = info->PackageInfo; if (oldPkgInfo) { info->PackageInfo = (PSecPkgInfoW) _copyPackageInfoFlatWToA(oldPkgInfo); package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); } break; } case SECPKG_ATTR_NEGOTIATION_INFO: { PSecPkgContext_NegotiationInfoW info = (PSecPkgContext_NegotiationInfoW)pBuffer; PSecPkgInfoW oldPkgInfo = info->PackageInfo; if (oldPkgInfo) { info->PackageInfo = (PSecPkgInfoW) _copyPackageInfoFlatWToA(oldPkgInfo); package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); } break; } case SECPKG_ATTR_NATIVE_NAMES: { PSecPkgContext_NativeNamesW names = (PSecPkgContext_NativeNamesW)pBuffer; PWSTR oldClient = names->sClientName; PWSTR oldServer = names->sServerName; if (oldClient) { names->sClientName = (PWSTR)SECUR32_AllocMultiByteFromWide( oldClient); package->provider->fnTableW.FreeContextBuffer(oldClient); } if (oldServer) { names->sServerName = (PWSTR)SECUR32_AllocMultiByteFromWide( oldServer); package->provider->fnTableW.FreeContextBuffer(oldServer); } break; } case SECPKG_ATTR_CREDENTIAL_NAME: { PSecPkgContext_CredentialNameW name = (PSecPkgContext_CredentialNameW)pBuffer; PWSTR oldCred = name->sCredentialName; if (oldCred) { name->sCredentialName = (PWSTR)SECUR32_AllocMultiByteFromWide(oldCred); package->provider->fnTableW.FreeContextBuffer(oldCred); } break; } /* no thunking needed: */ case SECPKG_ATTR_ACCESS_TOKEN: case SECPKG_ATTR_DCE_INFO: case SECPKG_ATTR_FLAGS: case SECPKG_ATTR_LIFESPAN: case SECPKG_ATTR_PASSWORD_EXPIRY: case SECPKG_ATTR_SESSION_KEY: case SECPKG_ATTR_SIZES: case SECPKG_ATTR_STREAM_SIZES: case SECPKG_ATTR_TARGET_INFORMATION: break; default: WARN("attribute type %d unknown\n", ulAttribute); ret = SEC_E_INTERNAL_ERROR; } } else ret = SEC_E_INVALID_TOKEN; return ret; } SECURITY_STATUS SEC_ENTRY thunk_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer) { SECURITY_STATUS ret; TRACE("%p %d %p\n", phContext, ulAttribute, pBuffer); if (phContext) { SecurePackage *package = (SecurePackage *)phContext->dwUpper; PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; if (package && package->provider) { if (package->provider->fnTableW.QueryContextAttributesW) { ret = package->provider->fnTableW.QueryContextAttributesW( ctxt, ulAttribute, pBuffer); if (ret == SEC_E_OK) ret = thunk_ContextAttributesWToA(package, ulAttribute, pBuffer); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } static PSecPkgInfoW _copyPackageInfoFlatAToW(const SecPkgInfoA *infoA) { PSecPkgInfoW ret; if (infoA) { size_t bytesNeeded = sizeof(SecPkgInfoW); int nameLen = 0, commentLen = 0; if (infoA->Name) { nameLen = MultiByteToWideChar(CP_ACP, 0, infoA->Name, -1, NULL, 0); bytesNeeded += nameLen * sizeof(WCHAR); } if (infoA->Comment) { commentLen = MultiByteToWideChar(CP_ACP, 0, infoA->Comment, -1, NULL, 0); bytesNeeded += commentLen * sizeof(WCHAR); } ret = heap_alloc(bytesNeeded); if (ret) { PWSTR nextString = (PWSTR)((PBYTE)ret + sizeof(SecPkgInfoW)); memcpy(ret, infoA, sizeof(SecPkgInfoA)); if (infoA->Name) { ret->Name = nextString; MultiByteToWideChar(CP_ACP, 0, infoA->Name, -1, nextString, nameLen); nextString += nameLen; } else ret->Name = NULL; if (infoA->Comment) { ret->Comment = nextString; MultiByteToWideChar(CP_ACP, 0, infoA->Comment, -1, nextString, commentLen); } else ret->Comment = NULL; } } else ret = NULL; return ret; } static SECURITY_STATUS thunk_ContextAttributesAToW(SecurePackage *package, ULONG ulAttribute, void *pBuffer) { SECURITY_STATUS ret = SEC_E_OK; if (package && pBuffer) { switch (ulAttribute) { case SECPKG_ATTR_NAMES: { PSecPkgContext_NamesA names = (PSecPkgContext_NamesA)pBuffer; SEC_CHAR *oldUser = names->sUserName; if (oldUser) { names->sUserName = (PSTR)SECUR32_AllocWideFromMultiByte(oldUser); package->provider->fnTableW.FreeContextBuffer(oldUser); } break; } case SECPKG_ATTR_AUTHORITY: { PSecPkgContext_AuthorityA names = (PSecPkgContext_AuthorityA)pBuffer; SEC_CHAR *oldAuth = names->sAuthorityName; if (oldAuth) { names->sAuthorityName = (PSTR)SECUR32_AllocWideFromMultiByte(oldAuth); package->provider->fnTableW.FreeContextBuffer(oldAuth); } break; } case SECPKG_ATTR_KEY_INFO: { PSecPkgContext_KeyInfoA info = (PSecPkgContext_KeyInfoA)pBuffer; SEC_CHAR *oldSigAlgName = info->sSignatureAlgorithmName; SEC_CHAR *oldEncAlgName = info->sEncryptAlgorithmName; if (oldSigAlgName) { info->sSignatureAlgorithmName = (PSTR)SECUR32_AllocWideFromMultiByte(oldSigAlgName); package->provider->fnTableW.FreeContextBuffer( oldSigAlgName); } if (oldEncAlgName) { info->sEncryptAlgorithmName = (PSTR)SECUR32_AllocWideFromMultiByte( oldEncAlgName); package->provider->fnTableW.FreeContextBuffer( oldEncAlgName); } break; } case SECPKG_ATTR_PACKAGE_INFO: { PSecPkgContext_PackageInfoA info = (PSecPkgContext_PackageInfoA)pBuffer; PSecPkgInfoA oldPkgInfo = info->PackageInfo; if (oldPkgInfo) { info->PackageInfo = (PSecPkgInfoA) _copyPackageInfoFlatAToW(oldPkgInfo); package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); } break; } case SECPKG_ATTR_NEGOTIATION_INFO: { PSecPkgContext_NegotiationInfoA info = (PSecPkgContext_NegotiationInfoA)pBuffer; PSecPkgInfoA oldPkgInfo = info->PackageInfo; if (oldPkgInfo) { info->PackageInfo = (PSecPkgInfoA) _copyPackageInfoFlatAToW(oldPkgInfo); package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); } break; } case SECPKG_ATTR_NATIVE_NAMES: { PSecPkgContext_NativeNamesA names = (PSecPkgContext_NativeNamesA)pBuffer; PSTR oldClient = names->sClientName; PSTR oldServer = names->sServerName; if (oldClient) { names->sClientName = (PSTR)SECUR32_AllocWideFromMultiByte( oldClient); package->provider->fnTableW.FreeContextBuffer(oldClient); } if (oldServer) { names->sServerName = (PSTR)SECUR32_AllocWideFromMultiByte( oldServer); package->provider->fnTableW.FreeContextBuffer(oldServer); } break; } case SECPKG_ATTR_CREDENTIAL_NAME: { PSecPkgContext_CredentialNameA name = (PSecPkgContext_CredentialNameA)pBuffer; PSTR oldCred = name->sCredentialName; if (oldCred) { name->sCredentialName = (PSTR)SECUR32_AllocWideFromMultiByte(oldCred); package->provider->fnTableW.FreeContextBuffer(oldCred); } break; } /* no thunking needed: */ case SECPKG_ATTR_ACCESS_TOKEN: case SECPKG_ATTR_DCE_INFO: case SECPKG_ATTR_FLAGS: case SECPKG_ATTR_LIFESPAN: case SECPKG_ATTR_PASSWORD_EXPIRY: case SECPKG_ATTR_SESSION_KEY: case SECPKG_ATTR_SIZES: case SECPKG_ATTR_STREAM_SIZES: case SECPKG_ATTR_TARGET_INFORMATION: break; default: WARN("attribute type %d unknown\n", ulAttribute); ret = SEC_E_INTERNAL_ERROR; } } else ret = SEC_E_INVALID_TOKEN; return ret; } SECURITY_STATUS SEC_ENTRY thunk_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer) { SECURITY_STATUS ret; TRACE("%p %d %p\n", phContext, ulAttribute, pBuffer); if (phContext) { SecurePackage *package = (SecurePackage *)phContext->dwUpper; PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; if (package && package->provider) { if (package->provider->fnTableA.QueryContextAttributesA) { ret = package->provider->fnTableA.QueryContextAttributesA( ctxt, ulAttribute, pBuffer); if (ret == SEC_E_OK) ret = thunk_ContextAttributesAToW(package, ulAttribute, pBuffer); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer, ULONG cbBuffer) { SECURITY_STATUS ret; TRACE("%p %d %p %d\n", phContext, ulAttribute, pBuffer, cbBuffer); if (phContext) { SecurePackage *package = (SecurePackage *)phContext->dwUpper; PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; if (package && package->provider && pBuffer && cbBuffer) { if (package->provider->fnTableW.SetContextAttributesW) { /* TODO: gotta validate size too! */ ret = thunk_ContextAttributesWToA(package, ulAttribute, pBuffer); if (ret == SEC_E_OK) ret = package->provider->fnTableW.SetContextAttributesW( ctxt, ulAttribute, pBuffer, cbBuffer); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer, ULONG cbBuffer) { SECURITY_STATUS ret; TRACE("%p %d %p %d\n", phContext, ulAttribute, pBuffer, cbBuffer); if (phContext) { SecurePackage *package = (SecurePackage *)phContext->dwUpper; PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; if (package && package->provider && pBuffer && cbBuffer) { if (package->provider->fnTableA.SetContextAttributesA) { /* TODO: gotta validate size too! */ ret = thunk_ContextAttributesAToW(package, ulAttribute, pBuffer); if (ret == SEC_E_OK) ret = package->provider->fnTableA.SetContextAttributesA( ctxt, ulAttribute, pBuffer, cbBuffer); } else ret = SEC_E_UNSUPPORTED_FUNCTION; } else ret = SEC_E_INVALID_HANDLE; } else ret = SEC_E_INVALID_HANDLE; return ret; } SECURITY_STATUS SEC_ENTRY thunk_ImportSecurityContextA( SEC_CHAR *pszPackage, PSecBuffer pPackedContext, void *Token, PCtxtHandle phContext) { SECURITY_STATUS ret; UNICODE_STRING package; TRACE("%s %p %p %p\n", debugstr_a(pszPackage), pPackedContext, Token, phContext); RtlCreateUnicodeStringFromAsciiz(&package, pszPackage); ret = ImportSecurityContextW(package.Buffer, pPackedContext, Token, phContext); RtlFreeUnicodeString(&package); return ret; } SECURITY_STATUS SEC_ENTRY thunk_ImportSecurityContextW( SEC_WCHAR *pszPackage, PSecBuffer pPackedContext, void *Token, PCtxtHandle phContext) { SECURITY_STATUS ret; PSTR package = SECUR32_AllocMultiByteFromWide(pszPackage); TRACE("%s %p %p %p\n", debugstr_w(pszPackage), pPackedContext, Token, phContext); ret = ImportSecurityContextA(package, pPackedContext, Token, phContext); heap_free(package); return ret; }