libwinpr-sspi: fix UNICODE build

This commit is contained in:
Marc-André Moreau 2012-07-26 18:35:39 -04:00
parent 984a8c97a3
commit 56db379571
4 changed files with 130 additions and 45 deletions

View File

@ -289,7 +289,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
#ifdef WITH_DEBUG_CREDSSP #ifdef WITH_DEBUG_CREDSSP
printf("Sending Authentication Token\n"); printf("Sending Authentication Token\n");
winpr_HexDump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); //winpr_HexDump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer);
#endif #endif
credssp_send(credssp); credssp_send(credssp);

View File

@ -22,6 +22,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <winpr/tchar.h>
#include <winpr/windows.h> #include <winpr/windows.h>
#include <freerdp/constants.h> #include <freerdp/constants.h>
#include <freerdp/utils/sleep.h> #include <freerdp/utils/sleep.h>
@ -50,6 +51,7 @@ void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
{ {
if (context) if (context)
{ {
} }
} }
@ -244,6 +246,11 @@ static void wf_server_main_loop(freerdp_listener* instance)
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
int port = 3389; int port = 3389;
WSADATA wsa_data; WSADATA wsa_data;
freerdp_listener* instance; freerdp_listener* instance;
@ -257,6 +264,16 @@ int main(int argc, char* argv[])
g_done_event = CreateEvent(0, 1, 0, 0); g_done_event = CreateEvent(0, 1, 0, 0);
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("DefaultPort"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
port = dwValue;
}
RegCloseKey(hKey);
if (argc == 2) if (argc == 2)
port = atoi(argv[1]); port = atoi(argv[1]);

View File

@ -56,7 +56,14 @@ void ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation)
free(Workstation); free(Workstation);
} }
void ntlm_SetContextServicePrincipalName(NTLM_CONTEXT* context, char* ServicePrincipalName) void ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName)
{
context->ServicePrincipalName.Length = lstrlenW(ServicePrincipalName) * 2;
context->ServicePrincipalName.Buffer = (PWSTR) malloc(context->ServicePrincipalName.Length);
CopyMemory(context->ServicePrincipalName.Buffer, ServicePrincipalName, context->ServicePrincipalName.Length);
}
void ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePrincipalName)
{ {
context->ServicePrincipalName.Length = strlen(ServicePrincipalName) * 2; context->ServicePrincipalName.Length = strlen(ServicePrincipalName) * 2;
context->ServicePrincipalName.Buffer = (PWSTR) malloc(context->ServicePrincipalName.Length); context->ServicePrincipalName.Buffer = (PWSTR) malloc(context->ServicePrincipalName.Length);
@ -94,10 +101,33 @@ NTLM_CONTEXT* ntlm_ContextNew()
if (context != NULL) if (context != NULL)
{ {
context->NTLMv2 = TRUE; HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
context->NTLMv2 = FALSE;
context->UseMIC = FALSE; context->UseMIC = FALSE;
context->NegotiateFlags = 0;
context->SendVersionInfo = TRUE; context->SendVersionInfo = TRUE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\WinPR\\NTLM"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("NTLMv2"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->NTLMv2 = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("UseMIC"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->UseMIC = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("SendVersionInfo"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendVersionInfo = dwValue ? 1 : 0;
RegCloseKey(hKey);
}
context->NegotiateFlags = 0;
context->LmCompatibilityLevel = 3; context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL; context->state = NTLM_STATE_INITIAL;
context->SuppressExtendedProtection = FALSE; context->SuppressExtendedProtection = FALSE;
@ -142,7 +172,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal
credentials = sspi_CredentialsNew(); credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
if (identity != NULL)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
@ -237,12 +269,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredent
SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{ {
if (ulAttribute == SECPKG_CRED_ATTR_NAMES) return ntlm_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
{
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
} }
/** /**
@ -355,17 +382,6 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
}
/**
* @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa375512%28v=vs.85%29.aspx
*/
SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{ {
NTLM_CONTEXT* context; NTLM_CONTEXT* context;
SECURITY_STATUS status; SECURITY_STATUS status;
@ -378,6 +394,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
if (!context) if (!context)
{ {
context = ntlm_ContextNew(); context = ntlm_ContextNew();
if (!context) if (!context)
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
@ -387,7 +404,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
ntlm_SetContextWorkstation(context, NULL); ntlm_SetContextWorkstation(context, NULL);
ntlm_SetContextServicePrincipalName(context, pszTargetName); ntlm_SetContextServicePrincipalNameW(context, pszTargetName);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity); sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetLowerPointer(phNewContext, context);
@ -459,6 +476,35 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
return SEC_E_OUT_OF_SEQUENCE; return SEC_E_OUT_OF_SEQUENCE;
} }
/**
* @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa375512%28v=vs.85%29.aspx
*/
SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
int length;
SECURITY_STATUS status;
SEC_WCHAR* pszTargetNameW = NULL;
if (pszTargetName != NULL)
{
length = strlen(pszTargetName);
pszTargetNameW = (PWSTR) malloc((length + 1) * 2);
MultiByteToWideChar(CP_ACP, 0, pszTargetName, length, pszTargetNameW, length);
pszTargetNameW[length] = 0;
}
status = ntlm_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq,
Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
if (pszTargetNameW != NULL)
free(pszTargetNameW);
return status;
}
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */
SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext) SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
@ -478,11 +524,6 @@ SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa379337/ */ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa379337/ */
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{ {
if (!phContext) if (!phContext)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
@ -505,6 +546,11 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, UL
return SEC_E_UNSUPPORTED_FUNCTION; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
}
SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext) SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
{ {
return SEC_E_OK; return SEC_E_OK;

View File

@ -353,7 +353,7 @@ void sspi_GlobalFinish()
#ifndef WITH_NATIVE_SSPI #ifndef WITH_NATIVE_SSPI
SecurityFunctionTableA* sspi_GetSecurityFunctionTableByNameA(const SEC_CHAR* Name) SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name)
{ {
int index; int index;
UINT32 cPackages; UINT32 cPackages;
@ -371,7 +371,12 @@ SecurityFunctionTableA* sspi_GetSecurityFunctionTableByNameA(const SEC_CHAR* Nam
return NULL; return NULL;
} }
SecurityFunctionTableW* sspi_GetSecurityFunctionTableByNameW(const SEC_WCHAR* Name) SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameW(const SEC_WCHAR* Name)
{
return NULL;
}
SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name)
{ {
int index; int index;
UINT32 cPackages; UINT32 cPackages;
@ -389,6 +394,23 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableByNameW(const SEC_WCHAR* Na
return NULL; return NULL;
} }
SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name)
{
int length;
SEC_WCHAR* NameW;
SecurityFunctionTableW* table;
length = strlen(Name);
NameW = (SEC_WCHAR*) malloc((length + 1) * 2);
MultiByteToWideChar(CP_ACP, 0, Name, length, (LPWSTR) NameW, length);
NameW[length] = 0;
table = sspi_GetSecurityFunctionTableWByNameW(NameW);
free(NameW);
return table;
}
void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer); void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer); void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
@ -599,7 +621,7 @@ SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{ {
SECURITY_STATUS status; SECURITY_STATUS status;
SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableByNameW(pszPackage); SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -618,7 +640,7 @@ SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{ {
SECURITY_STATUS status; SECURITY_STATUS status;
SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableByNameA(pszPackage); SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -648,7 +670,7 @@ SECURITY_STATUS SEC_ENTRY FreeCredentialsHandle(PCredHandle phCredential)
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -682,7 +704,7 @@ SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesW(PCredHandle phCredential,
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameW(Name); table = sspi_GetSecurityFunctionTableWByNameW(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -706,7 +728,7 @@ SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesA(PCredHandle phCredential,
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -734,7 +756,7 @@ SECURITY_STATUS SEC_ENTRY AcceptSecurityContext(PCredHandle phCredential, PCtxtH
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -769,7 +791,7 @@ SECURITY_STATUS SEC_ENTRY DeleteSecurityContext(PCtxtHandle phContext)
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -811,7 +833,7 @@ SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW(PCredHandle phCredential, P
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = (SecurityFunctionTableW*) sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -840,7 +862,7 @@ SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA(PCredHandle phCredential, P
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -866,7 +888,7 @@ SECURITY_STATUS SEC_ENTRY QueryContextAttributesW(PCtxtHandle phContext, ULONG u
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = (SecurityFunctionTableW*) sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -890,7 +912,7 @@ SECURITY_STATUS SEC_ENTRY QueryContextAttributesA(PCtxtHandle phContext, ULONG u
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -931,7 +953,7 @@ SECURITY_STATUS SEC_ENTRY DecryptMessage(PCtxtHandle phContext, PSecBufferDesc p
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -955,7 +977,7 @@ SECURITY_STATUS SEC_ENTRY EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSec
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -979,7 +1001,7 @@ SECURITY_STATUS SEC_ENTRY MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecB
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
@ -1003,7 +1025,7 @@ SECURITY_STATUS SEC_ENTRY VerifySignature(PCtxtHandle phContext, PSecBufferDesc
if (!Name) if (!Name)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableByNameA(Name); table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table) if (!table)
return SEC_E_SECPKG_NOT_FOUND; return SEC_E_SECPKG_NOT_FOUND;