Fix a memory leak.
[wine] / dlls / secur32 / thunks.c
1 /* Copyright (C) 2004 Juan Lang
2  *
3  * This file implements thunks between wide char and multibyte functions for
4  * SSPs that only provide one or the other.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "winreg.h"
25 #include "winternl.h"
26 #include "sspi.h"
27 #include "secur32_priv.h"
28 #include "thunks.h"
29
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
33
34 SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleA(
35  SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialsUse,
36  PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
37  PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
38 {
39     SECURITY_STATUS ret;
40
41     TRACE("%s %s %ld %p %p %p %p %p %p\n", debugstr_a(pszPrincipal),
42      debugstr_a(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn,
43      pvGetKeyArgument, phCredential, ptsExpiry);
44     if (pszPackage)
45     {
46         UNICODE_STRING principal, package;
47
48         RtlCreateUnicodeStringFromAsciiz(&principal, pszPrincipal);
49         RtlCreateUnicodeStringFromAsciiz(&package, pszPackage);
50         ret = AcquireCredentialsHandleW(principal.Buffer, package.Buffer,
51          fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument,
52          phCredential, ptsExpiry);
53         RtlFreeUnicodeString(&principal);
54         RtlFreeUnicodeString(&package);
55     }
56     else
57         ret = SEC_E_SECPKG_NOT_FOUND;
58     return ret;
59 }
60
61 SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleW(
62  SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse,
63  PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
64  PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
65 {
66     SECURITY_STATUS ret;
67
68     TRACE("%s %s %ld %p %p %p %p %p %p\n", debugstr_w(pszPrincipal),
69      debugstr_w(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn,
70      pvGetKeyArgument, phCredential, ptsExpiry);
71     if (pszPackage)
72     {
73         PSTR principal, package;
74
75         principal = SECUR32_AllocMultiByteFromWide(pszPrincipal);
76         package = SECUR32_AllocMultiByteFromWide(pszPackage);
77         ret = AcquireCredentialsHandleA(principal, package, fCredentialsUse,
78          pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
79          ptsExpiry);
80         if (principal)
81             SECUR32_FREE(principal);
82         if (package)
83             SECUR32_FREE(package);
84     }
85     else
86         ret = SEC_E_SECPKG_NOT_FOUND;
87     return ret;
88 }
89
90 /* thunking is pretty dicey for these--the output type depends on ulAttribute,
91  * so we have to know about every type the caller does
92  */
93 SECURITY_STATUS SEC_ENTRY thunk_QueryCredentialsAttributesA(
94  PCredHandle phCredential, unsigned long ulAttribute, void *pBuffer)
95 {
96     SECURITY_STATUS ret;
97
98     TRACE("%p %ld %p\n", phCredential, ulAttribute, pBuffer);
99     if (phCredential)
100     {
101         SecurePackage *package = (SecurePackage *)phCredential->dwUpper;
102         PCredHandle cred = (PCredHandle)phCredential->dwLower;
103
104         if (package && package->provider)
105         {
106             if (package->provider->fnTableW.QueryCredentialsAttributesW)
107             {
108                 ret = package->provider->fnTableW.QueryCredentialsAttributesW(
109                  cred, ulAttribute, pBuffer);
110                 if (ret == SEC_E_OK)
111                 {
112                     switch (ulAttribute)
113                     {
114                         case SECPKG_CRED_ATTR_NAMES:
115                         {
116                             PSecPkgCredentials_NamesW names =
117                              (PSecPkgCredentials_NamesW)pBuffer;
118                             SEC_WCHAR *oldUser = names->sUserName;
119
120                             if (oldUser)
121                             {
122                                 names->sUserName =
123                                  (PWSTR)SECUR32_AllocMultiByteFromWide(oldUser);
124                                 package->provider->fnTableW.FreeContextBuffer(
125                                  oldUser);
126                             }
127                             break;
128                         }
129                         default:
130                             WARN("attribute type %ld unknown\n", ulAttribute);
131                             ret = SEC_E_INTERNAL_ERROR;
132                     }
133                 }
134             }
135             else
136                 ret = SEC_E_UNSUPPORTED_FUNCTION;
137         }
138         else
139             ret = SEC_E_INVALID_HANDLE;
140     }
141     else
142         ret = SEC_E_INVALID_HANDLE;
143     return ret;
144 }
145
146 SECURITY_STATUS SEC_ENTRY thunk_QueryCredentialsAttributesW(
147  PCredHandle phCredential, unsigned long ulAttribute, void *pBuffer)
148 {
149     SECURITY_STATUS ret;
150
151     TRACE("%p %ld %p\n", phCredential, ulAttribute, pBuffer);
152     if (phCredential)
153     {
154         SecurePackage *package = (SecurePackage *)phCredential->dwUpper;
155         PCredHandle cred = (PCredHandle)phCredential->dwLower;
156
157         if (package && package->provider)
158         {
159             if (package->provider->fnTableA.QueryCredentialsAttributesA)
160             {
161                 ret = package->provider->fnTableA.QueryCredentialsAttributesA(
162                  cred, ulAttribute, pBuffer);
163                 if (ret == SEC_E_OK)
164                 {
165                     switch (ulAttribute)
166                     {
167                         case SECPKG_CRED_ATTR_NAMES:
168                         {
169                             PSecPkgCredentials_NamesA names =
170                              (PSecPkgCredentials_NamesA)pBuffer;
171                             SEC_CHAR *oldUser = names->sUserName;
172
173                             if (oldUser)
174                             {
175                                 names->sUserName =
176                                  (PSTR)SECUR32_AllocWideFromMultiByte(oldUser);
177                                 package->provider->fnTableA.FreeContextBuffer(
178                                  oldUser);
179                             }
180                             break;
181                         }
182                         default:
183                             WARN("attribute type %ld unknown\n", ulAttribute);
184                             ret = SEC_E_INTERNAL_ERROR;
185                     }
186                 }
187             }
188             else
189                 ret = SEC_E_UNSUPPORTED_FUNCTION;
190         }
191         else
192             ret = SEC_E_INVALID_HANDLE;
193     }
194     else
195         ret = SEC_E_INVALID_HANDLE;
196     return ret;
197 }
198
199 SECURITY_STATUS SEC_ENTRY thunk_InitializeSecurityContextA(
200  PCredHandle phCredential, PCtxtHandle phContext,
201  SEC_CHAR *pszTargetName, unsigned long fContextReq,
202  unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput,
203  unsigned long Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput,
204  unsigned long *pfContextAttr, PTimeStamp ptsExpiry)
205 {
206     SECURITY_STATUS ret;
207
208     TRACE("%p %p %s %ld %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext,
209      debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
210      Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
211     if (phCredential)
212     {
213         SecurePackage *package = (SecurePackage *)phCredential->dwUpper;
214
215         if (package && package->provider)
216         {
217             if (package->provider->fnTableW.InitializeSecurityContextW)
218             {
219                 UNICODE_STRING target;
220
221                 RtlCreateUnicodeStringFromAsciiz(&target, pszTargetName);
222                 ret = package->provider->fnTableW.InitializeSecurityContextW(
223                  phCredential, phContext, target.Buffer, fContextReq, Reserved1,
224                  TargetDataRep, pInput, Reserved2, phNewContext, pOutput,
225                  pfContextAttr, ptsExpiry);
226                 RtlFreeUnicodeString(&target);
227             }
228             else
229                 ret = SEC_E_UNSUPPORTED_FUNCTION;
230         }
231         else
232             ret = SEC_E_INVALID_HANDLE;
233     }
234     else
235         ret = SEC_E_INVALID_HANDLE;
236     return ret;
237 }
238
239 SECURITY_STATUS SEC_ENTRY thunk_InitializeSecurityContextW(
240  PCredHandle phCredential, PCtxtHandle phContext,
241  SEC_WCHAR *pszTargetName, unsigned long fContextReq,
242  unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput,
243  unsigned long Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput,
244  unsigned long *pfContextAttr, PTimeStamp ptsExpiry)
245 {
246     SECURITY_STATUS ret;
247
248     TRACE("%p %p %s %ld %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext,
249      debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
250      Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
251     if (phCredential)
252     {
253         SecurePackage *package = (SecurePackage *)phCredential->dwUpper;
254
255         if (package && package->provider)
256         {
257             if (package->provider->fnTableA.InitializeSecurityContextA)
258             {
259                 PSTR target = SECUR32_AllocMultiByteFromWide(pszTargetName);
260
261                 ret = package->provider->fnTableA.InitializeSecurityContextA(
262                  phCredential, phContext, target, fContextReq, Reserved1,
263                  TargetDataRep, pInput, Reserved2, phNewContext, pOutput,
264                  pfContextAttr, ptsExpiry);
265                 if (target)
266                     SECUR32_FREE(target);
267             }
268             else
269                 ret = SEC_E_UNSUPPORTED_FUNCTION;
270         }
271         else
272             ret = SEC_E_INVALID_HANDLE;
273     }
274     else
275         ret = SEC_E_INVALID_HANDLE;
276     return ret;
277 }
278
279 SECURITY_STATUS SEC_ENTRY thunk_AddCredentialsA(PCredHandle hCredentials,
280  SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, unsigned long fCredentialUse,
281  void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument,
282  PTimeStamp ptsExpiry)
283 {
284     SECURITY_STATUS ret;
285
286     TRACE("%p %s %s %ld %p %p %p %p\n", hCredentials, debugstr_a(pszPrincipal),
287      debugstr_a(pszPackage), fCredentialUse, pAuthData, pGetKeyFn,
288      pvGetKeyArgument, ptsExpiry);
289     if (hCredentials)
290     {
291         SecurePackage *package = (SecurePackage *)hCredentials->dwUpper;
292         PCredHandle cred = (PCtxtHandle)hCredentials->dwLower;
293
294         if (package && package->provider)
295         {
296             if (package->provider->fnTableW.AddCredentialsW)
297             {
298                 UNICODE_STRING szPrincipal, szPackage;
299
300                 RtlCreateUnicodeStringFromAsciiz(&szPrincipal, pszPrincipal);
301                 RtlCreateUnicodeStringFromAsciiz(&szPackage, pszPackage);
302                 ret = package->provider->fnTableW.AddCredentialsW(
303                  cred, szPrincipal.Buffer, szPackage.Buffer, fCredentialUse,
304                  pAuthData, pGetKeyFn, pvGetKeyArgument, ptsExpiry);
305                 RtlFreeUnicodeString(&szPrincipal);
306                 RtlFreeUnicodeString(&szPackage);
307             }
308             else
309                 ret = SEC_E_UNSUPPORTED_FUNCTION;
310         }
311         else
312             ret = SEC_E_INVALID_HANDLE;
313     }
314     else
315         ret = SEC_E_INVALID_HANDLE;
316     return ret;
317 }
318
319 SECURITY_STATUS SEC_ENTRY thunk_AddCredentialsW(PCredHandle hCredentials,
320  SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, unsigned long fCredentialUse,
321  void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument,
322  PTimeStamp ptsExpiry)
323 {
324     SECURITY_STATUS ret;
325
326     TRACE("%p %s %s %ld %p %p %p %p\n", hCredentials, debugstr_w(pszPrincipal),
327      debugstr_w(pszPackage), fCredentialUse, pAuthData, pGetKeyFn,
328      pvGetKeyArgument, ptsExpiry);
329     if (hCredentials)
330     {
331         SecurePackage *package = (SecurePackage *)hCredentials->dwUpper;
332         PCredHandle cred = (PCtxtHandle)hCredentials->dwLower;
333
334         if (package && package->provider)
335         {
336             if (package->provider->fnTableA.AddCredentialsA)
337             {
338                 PSTR szPrincipal = SECUR32_AllocMultiByteFromWide(pszPrincipal);
339                 PSTR szPackage = SECUR32_AllocMultiByteFromWide(pszPackage);
340
341                 ret = package->provider->fnTableA.AddCredentialsA(
342                  cred, szPrincipal, szPackage, fCredentialUse, pAuthData,
343                  pGetKeyFn, pvGetKeyArgument, ptsExpiry);
344                 SECUR32_FREE(szPrincipal);
345                 SECUR32_FREE(szPackage);
346             }
347             else
348                 ret = SEC_E_UNSUPPORTED_FUNCTION;
349         }
350         else
351             ret = SEC_E_INVALID_HANDLE;
352     }
353     else
354         ret = SEC_E_INVALID_HANDLE;
355     return ret;
356 }
357
358 static PSecPkgInfoA _copyPackageInfoFlatWToA(PSecPkgInfoW infoW)
359 {
360     PSecPkgInfoA ret;
361
362     if (infoW)
363     {
364         size_t bytesNeeded = sizeof(SecPkgInfoA);
365         int nameLen = 0, commentLen = 0;
366
367         if (infoW->Name)
368         {
369             nameLen = WideCharToMultiByte(CP_ACP, 0, infoW->Name, -1,
370              NULL, 0, NULL, NULL);
371             bytesNeeded += nameLen;
372         }
373         if (infoW->Comment)
374         {
375             commentLen = WideCharToMultiByte(CP_ACP, 0, infoW->Comment, -1,
376              NULL, 0, NULL, NULL);
377             bytesNeeded += commentLen;
378         }
379         ret = (PSecPkgInfoA)SECUR32_ALLOC(bytesNeeded);
380         if (ret)
381         {
382             PSTR nextString = (PSTR)((PBYTE)ret + sizeof(SecPkgInfoA));
383
384             memcpy(ret, infoW, sizeof(SecPkgInfoA));
385             if (infoW->Name)
386             {
387                 ret->Name = nextString;
388                 WideCharToMultiByte(CP_ACP, 0, infoW->Name, -1, nextString,
389                  nameLen, NULL, NULL);
390                 nextString += nameLen;
391             }
392             else
393                 ret->Name = NULL;
394             if (infoW->Comment)
395             {
396                 ret->Comment = nextString;
397                 WideCharToMultiByte(CP_ACP, 0, infoW->Comment, -1, nextString,
398                  nameLen, NULL, NULL);
399             }
400             else
401                 ret->Comment = NULL;
402         }
403     }
404     else
405         ret = NULL;
406     return ret;
407 }
408
409 static SECURITY_STATUS thunk_ContextAttributesWToA(SecurePackage *package,
410  unsigned long ulAttribute, void *pBuffer)
411 {
412     SECURITY_STATUS ret = SEC_E_OK;
413
414     if (package && pBuffer)
415     {
416         switch (ulAttribute)
417         {
418             case SECPKG_ATTR_NAMES:
419             {
420                 PSecPkgContext_NamesW names = (PSecPkgContext_NamesW)pBuffer;
421                 SEC_WCHAR *oldUser = names->sUserName;
422
423                 if (oldUser)
424                 {
425                     names->sUserName =
426                      (PWSTR)SECUR32_AllocMultiByteFromWide(oldUser);
427                     package->provider->fnTableW.FreeContextBuffer(oldUser);
428                 }
429                 break;
430             }
431             case SECPKG_ATTR_AUTHORITY:
432             {
433                 PSecPkgContext_AuthorityW names =
434                  (PSecPkgContext_AuthorityW)pBuffer;
435                 SEC_WCHAR *oldAuth = names->sAuthorityName;
436
437                 if (oldAuth)
438                 {
439                     names->sAuthorityName =
440                      (PWSTR)SECUR32_AllocMultiByteFromWide(oldAuth);
441                     package->provider->fnTableW.FreeContextBuffer(oldAuth);
442                 }
443                 break;
444             }
445             case SECPKG_ATTR_KEY_INFO:
446             {
447                 PSecPkgContext_KeyInfoW info = (PSecPkgContext_KeyInfoW)pBuffer;
448                 SEC_WCHAR *oldSigAlgName = info->sSignatureAlgorithmName;
449                 SEC_WCHAR *oldEncAlgName = info->sEncryptAlgorithmName;
450
451                 if (oldSigAlgName)
452                 {
453                     info->sSignatureAlgorithmName =
454                      (PWSTR)SECUR32_AllocMultiByteFromWide(oldSigAlgName);
455                     package->provider->fnTableW.FreeContextBuffer(
456                      oldSigAlgName);
457                 }
458                 if (oldEncAlgName)
459                 {
460                     info->sEncryptAlgorithmName =
461                      (PWSTR)SECUR32_AllocMultiByteFromWide(oldEncAlgName);
462                     package->provider->fnTableW.FreeContextBuffer(
463                      oldEncAlgName);
464                 }
465                 break;
466             }
467             case SECPKG_ATTR_PACKAGE_INFO:
468             {
469                 PSecPkgContext_PackageInfoW info =
470                  (PSecPkgContext_PackageInfoW)pBuffer;
471                 PSecPkgInfoW oldPkgInfo = info->PackageInfo;
472
473                 if (oldPkgInfo)
474                 {
475                     info->PackageInfo = (PSecPkgInfoW)
476                      _copyPackageInfoFlatWToA(oldPkgInfo);
477                     package->provider->fnTableW.FreeContextBuffer(oldPkgInfo);
478                 }
479                 break;
480             }
481             case SECPKG_ATTR_NEGOTIATION_INFO:
482             {
483                 PSecPkgContext_NegotiationInfoW info =
484                  (PSecPkgContext_NegotiationInfoW)pBuffer;
485                 PSecPkgInfoW oldPkgInfo = info->PackageInfo;
486
487                 if (oldPkgInfo)
488                 {
489                     info->PackageInfo = (PSecPkgInfoW)
490                      _copyPackageInfoFlatWToA(oldPkgInfo);
491                     package->provider->fnTableW.FreeContextBuffer(oldPkgInfo);
492                 }
493                 break;
494             }
495             case SECPKG_ATTR_NATIVE_NAMES:
496             {
497                 PSecPkgContext_NativeNamesW names =
498                  (PSecPkgContext_NativeNamesW)pBuffer;
499                 PWSTR oldClient = names->sClientName;
500                 PWSTR oldServer = names->sServerName;
501
502                 if (oldClient)
503                 {
504                     names->sClientName = (PWSTR)SECUR32_AllocMultiByteFromWide(
505                      oldClient);
506                     package->provider->fnTableW.FreeContextBuffer(oldClient);
507                 }
508                 if (oldServer)
509                 {
510                     names->sServerName = (PWSTR)SECUR32_AllocMultiByteFromWide(
511                      oldServer);
512                     package->provider->fnTableW.FreeContextBuffer(oldServer);
513                 }
514                 break;
515             }
516             case SECPKG_ATTR_CREDENTIAL_NAME:
517             {
518                 PSecPkgContext_CredentialNameW name =
519                  (PSecPkgContext_CredentialNameW)pBuffer;
520                 PWSTR oldCred = name->sCredentialName;
521
522                 if (oldCred)
523                 {
524                     name->sCredentialName =
525                      (PWSTR)SECUR32_AllocMultiByteFromWide(oldCred);
526                     package->provider->fnTableW.FreeContextBuffer(oldCred);
527                 }
528                 break;
529             }
530             /* no thunking needed: */
531             case SECPKG_ATTR_ACCESS_TOKEN:
532             case SECPKG_ATTR_DCE_INFO:
533             case SECPKG_ATTR_FLAGS:
534             case SECPKG_ATTR_LIFESPAN:
535             case SECPKG_ATTR_PASSWORD_EXPIRY:
536             case SECPKG_ATTR_SESSION_KEY:
537             case SECPKG_ATTR_SIZES:
538             case SECPKG_ATTR_STREAM_SIZES:
539             case SECPKG_ATTR_TARGET_INFORMATION:
540                 break;
541             default:
542                 WARN("attribute type %ld unknown\n", ulAttribute);
543                 ret = SEC_E_INTERNAL_ERROR;
544         }
545     }
546     else
547         ret = SEC_E_INVALID_TOKEN;
548     return ret;
549 }
550
551 SECURITY_STATUS SEC_ENTRY thunk_QueryContextAttributesA(PCtxtHandle phContext,
552  unsigned long ulAttribute, void *pBuffer)
553 {
554     SECURITY_STATUS ret;
555
556     TRACE("%p %ld %p\n", phContext, ulAttribute, pBuffer);
557     if (phContext)
558     {
559         SecurePackage *package = (SecurePackage *)phContext->dwUpper;
560         PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower;
561
562         if (package && package->provider)
563         {
564             if (package->provider->fnTableW.QueryContextAttributesW)
565             {
566                 ret = package->provider->fnTableW.QueryContextAttributesW(
567                  ctxt, ulAttribute, pBuffer);
568                 if (ret == SEC_E_OK)
569                     ret = thunk_ContextAttributesWToA(package, ulAttribute,
570                      pBuffer);
571             }
572             else
573                 ret = SEC_E_UNSUPPORTED_FUNCTION;
574         }
575         else
576             ret = SEC_E_INVALID_HANDLE;
577     }
578     else
579         ret = SEC_E_INVALID_HANDLE;
580     return ret;
581 }
582
583 static PSecPkgInfoW _copyPackageInfoFlatAToW(PSecPkgInfoA infoA)
584 {
585     PSecPkgInfoW ret;
586
587     if (infoA)
588     {
589         size_t bytesNeeded = sizeof(SecPkgInfoW);
590         int nameLen = 0, commentLen = 0;
591
592         if (infoA->Name)
593         {
594             nameLen = MultiByteToWideChar(CP_ACP, 0, infoA->Name, -1,
595              NULL, 0);
596             bytesNeeded += nameLen * sizeof(WCHAR);
597         }
598         if (infoA->Comment)
599         {
600             commentLen = MultiByteToWideChar(CP_ACP, 0, infoA->Comment, -1,
601              NULL, 0);
602             bytesNeeded += commentLen * sizeof(WCHAR);
603         }
604         ret = (PSecPkgInfoW)SECUR32_ALLOC(bytesNeeded);
605         if (ret)
606         {
607             PWSTR nextString = (PWSTR)((PBYTE)ret + sizeof(SecPkgInfoW));
608
609             memcpy(ret, infoA, sizeof(SecPkgInfoA));
610             if (infoA->Name)
611             {
612                 ret->Name = nextString;
613                 MultiByteToWideChar(CP_ACP, 0, infoA->Name, -1, nextString,
614                  nameLen);
615                 nextString += nameLen;
616             }
617             else
618                 ret->Name = NULL;
619             if (infoA->Comment)
620             {
621                 ret->Comment = nextString;
622                 MultiByteToWideChar(CP_ACP, 0, infoA->Comment, -1, nextString,
623                  commentLen);
624             }
625             else
626                 ret->Comment = NULL;
627         }
628     }
629     else
630         ret = NULL;
631     return ret;
632 }
633
634 static SECURITY_STATUS thunk_ContextAttributesAToW(SecurePackage *package,
635  unsigned long ulAttribute, void *pBuffer)
636 {
637     SECURITY_STATUS ret = SEC_E_OK;
638
639     if (package && pBuffer)
640     {
641         switch (ulAttribute)
642         {
643             case SECPKG_ATTR_NAMES:
644             {
645                 PSecPkgContext_NamesA names = (PSecPkgContext_NamesA)pBuffer;
646                 SEC_CHAR *oldUser = names->sUserName;
647
648                 if (oldUser)
649                 {
650                     names->sUserName =
651                      (PSTR)SECUR32_AllocWideFromMultiByte(oldUser);
652                     package->provider->fnTableW.FreeContextBuffer(oldUser);
653                 }
654                 break;
655             }
656             case SECPKG_ATTR_AUTHORITY:
657             {
658                 PSecPkgContext_AuthorityA names =
659                  (PSecPkgContext_AuthorityA)pBuffer;
660                 SEC_CHAR *oldAuth = names->sAuthorityName;
661
662                 if (oldAuth)
663                 {
664                     names->sAuthorityName =
665                      (PSTR)SECUR32_AllocWideFromMultiByte(oldAuth);
666                     package->provider->fnTableW.FreeContextBuffer(oldAuth);
667                 }
668                 break;
669             }
670             case SECPKG_ATTR_KEY_INFO:
671             {
672                 PSecPkgContext_KeyInfoA info = (PSecPkgContext_KeyInfoA)pBuffer;
673                 SEC_CHAR *oldSigAlgName = info->sSignatureAlgorithmName;
674                 SEC_CHAR *oldEncAlgName = info->sEncryptAlgorithmName;
675
676                 if (oldSigAlgName)
677                 {
678                     info->sSignatureAlgorithmName =
679                      (PSTR)SECUR32_AllocWideFromMultiByte(oldSigAlgName);
680                     package->provider->fnTableW.FreeContextBuffer(
681                      oldSigAlgName);
682                 }
683                 if (oldEncAlgName)
684                 {
685                     info->sEncryptAlgorithmName =
686                      (PSTR)SECUR32_AllocWideFromMultiByte(
687                      oldEncAlgName);
688                     package->provider->fnTableW.FreeContextBuffer(
689                      oldEncAlgName);
690                 }
691                 break;
692             }
693             case SECPKG_ATTR_PACKAGE_INFO:
694             {
695                 PSecPkgContext_PackageInfoA info =
696                  (PSecPkgContext_PackageInfoA)pBuffer;
697                 PSecPkgInfoA oldPkgInfo = info->PackageInfo;
698
699                 if (oldPkgInfo)
700                 {
701                     info->PackageInfo = (PSecPkgInfoA)
702                      _copyPackageInfoFlatAToW(oldPkgInfo);
703                     package->provider->fnTableW.FreeContextBuffer(oldPkgInfo);
704                 }
705                 break;
706             }
707             case SECPKG_ATTR_NEGOTIATION_INFO:
708             {
709                 PSecPkgContext_NegotiationInfoA info =
710                  (PSecPkgContext_NegotiationInfoA)pBuffer;
711                 PSecPkgInfoA oldPkgInfo = info->PackageInfo;
712
713                 if (oldPkgInfo)
714                 {
715                     info->PackageInfo = (PSecPkgInfoA)
716                      _copyPackageInfoFlatAToW(oldPkgInfo);
717                     package->provider->fnTableW.FreeContextBuffer(oldPkgInfo);
718                 }
719                 break;
720             }
721             case SECPKG_ATTR_NATIVE_NAMES:
722             {
723                 PSecPkgContext_NativeNamesA names =
724                  (PSecPkgContext_NativeNamesA)pBuffer;
725                 PSTR oldClient = names->sClientName;
726                 PSTR oldServer = names->sServerName;
727
728                 if (oldClient)
729                 {
730                     names->sClientName = (PSTR)SECUR32_AllocWideFromMultiByte(
731                      oldClient);
732                     package->provider->fnTableW.FreeContextBuffer(oldClient);
733                 }
734                 if (oldServer)
735                 {
736                     names->sServerName = (PSTR)SECUR32_AllocWideFromMultiByte(
737                      oldServer);
738                     package->provider->fnTableW.FreeContextBuffer(oldServer);
739                 }
740                 break;
741             }
742             case SECPKG_ATTR_CREDENTIAL_NAME:
743             {
744                 PSecPkgContext_CredentialNameA name =
745                  (PSecPkgContext_CredentialNameA)pBuffer;
746                 PSTR oldCred = name->sCredentialName;
747
748                 if (oldCred)
749                 {
750                     name->sCredentialName =
751                      (PSTR)SECUR32_AllocWideFromMultiByte(oldCred);
752                     package->provider->fnTableW.FreeContextBuffer(oldCred);
753                 }
754                 break;
755             }
756             /* no thunking needed: */
757             case SECPKG_ATTR_ACCESS_TOKEN:
758             case SECPKG_ATTR_DCE_INFO:
759             case SECPKG_ATTR_FLAGS:
760             case SECPKG_ATTR_LIFESPAN:
761             case SECPKG_ATTR_PASSWORD_EXPIRY:
762             case SECPKG_ATTR_SESSION_KEY:
763             case SECPKG_ATTR_SIZES:
764             case SECPKG_ATTR_STREAM_SIZES:
765             case SECPKG_ATTR_TARGET_INFORMATION:
766                 break;
767             default:
768                 WARN("attribute type %ld unknown\n", ulAttribute);
769                 ret = SEC_E_INTERNAL_ERROR;
770         }
771     }
772     else
773         ret = SEC_E_INVALID_TOKEN;
774     return ret;
775 }
776
777 SECURITY_STATUS SEC_ENTRY thunk_QueryContextAttributesW(PCtxtHandle phContext,
778  unsigned long ulAttribute, void *pBuffer)
779 {
780     SECURITY_STATUS ret;
781
782     TRACE("%p %ld %p\n", phContext, ulAttribute, pBuffer);
783     if (phContext)
784     {
785         SecurePackage *package = (SecurePackage *)phContext->dwUpper;
786         PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower;
787
788         if (package && package->provider)
789         {
790             if (package->provider->fnTableA.QueryContextAttributesA)
791             {
792                 ret = package->provider->fnTableA.QueryContextAttributesA(
793                  ctxt, ulAttribute, pBuffer);
794                 if (ret == SEC_E_OK)
795                     ret = thunk_ContextAttributesAToW(package, ulAttribute,
796                      pBuffer);
797             }
798             else
799                 ret = SEC_E_UNSUPPORTED_FUNCTION;
800         }
801         else
802             ret = SEC_E_INVALID_HANDLE;
803     }
804     else
805         ret = SEC_E_INVALID_HANDLE;
806     return ret;
807 }
808
809 SECURITY_STATUS SEC_ENTRY thunk_SetContextAttributesA(PCtxtHandle phContext,
810  unsigned long ulAttribute, void *pBuffer, unsigned long cbBuffer)
811 {
812     SECURITY_STATUS ret;
813
814     TRACE("%p %ld %p %ld\n", phContext, ulAttribute, pBuffer, cbBuffer);
815     if (phContext)
816     {
817         SecurePackage *package = (SecurePackage *)phContext->dwUpper;
818         PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower;
819
820         if (package && package->provider && pBuffer && cbBuffer)
821         {
822             if (package->provider->fnTableW.SetContextAttributesW)
823             {
824                 /* TODO: gotta validate size too! */
825                 ret = thunk_ContextAttributesWToA(package, ulAttribute,
826                  pBuffer);
827                 if (ret == SEC_E_OK)
828                     ret = package->provider->fnTableW.SetContextAttributesW(
829                      ctxt, ulAttribute, pBuffer, cbBuffer);
830             }
831             else
832                 ret = SEC_E_UNSUPPORTED_FUNCTION;
833         }
834         else
835             ret = SEC_E_INVALID_HANDLE;
836     }
837     else
838         ret = SEC_E_INVALID_HANDLE;
839     return ret;
840 }
841
842 SECURITY_STATUS SEC_ENTRY thunk_SetContextAttributesW(PCtxtHandle phContext,
843  unsigned long ulAttribute, void *pBuffer, unsigned long cbBuffer)
844 {
845     SECURITY_STATUS ret;
846
847     TRACE("%p %ld %p %ld\n", phContext, ulAttribute, pBuffer, cbBuffer);
848     if (phContext)
849     {
850         SecurePackage *package = (SecurePackage *)phContext->dwUpper;
851         PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower;
852
853         if (package && package->provider && pBuffer && cbBuffer)
854         {
855             if (package->provider->fnTableA.SetContextAttributesA)
856             {
857                 /* TODO: gotta validate size too! */
858                 ret = thunk_ContextAttributesAToW(package, ulAttribute,
859                  pBuffer);
860                 if (ret == SEC_E_OK)
861                     ret = package->provider->fnTableA.SetContextAttributesA(
862                      ctxt, ulAttribute, pBuffer, cbBuffer);
863             }
864             else
865                 ret = SEC_E_UNSUPPORTED_FUNCTION;
866         }
867         else
868             ret = SEC_E_INVALID_HANDLE;
869     }
870     else
871         ret = SEC_E_INVALID_HANDLE;
872     return ret;
873 }
874
875 SECURITY_STATUS SEC_ENTRY thunk_ImportSecurityContextA(
876  SEC_CHAR *pszPackage, PSecBuffer pPackedContext, void *Token,
877  PCtxtHandle phContext)
878 {
879     SECURITY_STATUS ret;
880     UNICODE_STRING package;
881
882     TRACE("%s %p %p %p\n", debugstr_a(pszPackage), pPackedContext, Token,
883      phContext);
884     RtlCreateUnicodeStringFromAsciiz(&package, pszPackage);
885     ret = ImportSecurityContextW(package.Buffer, pPackedContext, Token,
886      phContext);
887     RtlFreeUnicodeString(&package);
888     return ret;
889 }
890
891 SECURITY_STATUS SEC_ENTRY thunk_ImportSecurityContextW(
892  SEC_WCHAR *pszPackage, PSecBuffer pPackedContext, void *Token,
893  PCtxtHandle phContext)
894 {
895     SECURITY_STATUS ret;
896     PSTR package = SECUR32_AllocMultiByteFromWide(pszPackage);
897
898     TRACE("%s %p %p %p\n", debugstr_w(pszPackage), pPackedContext, Token,
899      phContext);
900     ret = ImportSecurityContextA(package, pPackedContext, Token, phContext);
901     if (package)
902         SECUR32_FREE(package);
903     return ret;
904 }