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