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