1 /* Copyright (C) 2004 Juan Lang
3 * This file implements loading of SSP DLLs.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 WINE_DEFAULT_DEBUG_CHANNEL(schannel
);
26 typedef struct _SecurePackageTable
33 typedef struct _SecureProviderTable
38 } SecureProviderTable
;
44 static CRITICAL_SECTION cs
;
45 static CRITICAL_SECTION_DEBUG cs_debug
=
48 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
49 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
51 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
52 static SecurePackageTable
*packageTable
= NULL
;
53 static SecureProviderTable
*providerTable
= NULL
;
55 /***********************************************************************
56 * EnumerateSecurityPackagesW (SECUR32.@)
58 SECURITY_STATUS WINAPI
schan_EnumerateSecurityPackagesW(PULONG pcPackages
,
59 PSecPkgInfoW
*ppPackageInfo
)
61 SECURITY_STATUS ret
= SEC_E_OK
;
63 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
65 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
67 EnterCriticalSection(&cs
);
70 SecurePackage
*package
;
73 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
74 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
76 if (package
->infoW
.Name
)
77 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
78 if (package
->infoW
.Comment
)
79 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
83 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
89 *pcPackages
= packageTable
->numPackages
;
90 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
91 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
92 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
94 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
96 *pkgInfo
= package
->infoW
;
97 if (package
->infoW
.Name
)
99 TRACE("Name[%d] = %S\n", i
- 1, package
->infoW
.Name
);
100 pkgInfo
->Name
= nextString
;
101 lstrcpyW(nextString
, package
->infoW
.Name
);
102 nextString
+= lstrlenW(nextString
) + 1;
105 pkgInfo
->Name
= NULL
;
106 if (package
->infoW
.Comment
)
108 TRACE("Comment[%d] = %S\n", i
- 1, package
->infoW
.Comment
);
109 pkgInfo
->Comment
= nextString
;
110 lstrcpyW(nextString
, package
->infoW
.Comment
);
111 nextString
+= lstrlenW(nextString
) + 1;
114 pkgInfo
->Comment
= NULL
;
118 ret
= SEC_E_INSUFFICIENT_MEMORY
;
121 LeaveCriticalSection(&cs
);
122 TRACE("<-- 0x%08x\n", ret
);
126 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
127 * structures) into an array of SecPkgInfoA structures, which it returns.
129 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
130 const SecPkgInfoW
*info
)
136 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
139 for (i
= 0; i
< cPackages
; i
++)
142 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
143 -1, NULL
, 0, NULL
, NULL
);
145 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
146 -1, NULL
, 0, NULL
, NULL
);
148 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
153 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
154 for (i
= 0; i
< cPackages
; i
++)
156 PSecPkgInfoA pkgInfo
= ret
+ i
;
159 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
162 pkgInfo
->Name
= nextString
;
163 /* just repeat back to WideCharToMultiByte how many bytes
164 * it requires, since we asked it earlier
166 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
167 NULL
, 0, NULL
, NULL
);
168 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
169 pkgInfo
->Name
, bytes
, NULL
, NULL
);
170 nextString
+= lstrlenA(nextString
) + 1;
173 pkgInfo
->Name
= NULL
;
176 pkgInfo
->Comment
= nextString
;
177 /* just repeat back to WideCharToMultiByte how many bytes
178 * it requires, since we asked it earlier
180 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
181 NULL
, 0, NULL
, NULL
);
182 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
183 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
184 nextString
+= lstrlenA(nextString
) + 1;
187 pkgInfo
->Comment
= NULL
;
196 /***********************************************************************
197 * EnumerateSecurityPackagesA (SECUR32.@)
199 SECURITY_STATUS WINAPI
schan_EnumerateSecurityPackagesA(PULONG pcPackages
,
200 PSecPkgInfoA
*ppPackageInfo
)
205 ret
= schan_EnumerateSecurityPackagesW(pcPackages
, &info
);
206 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
208 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
209 if (*pcPackages
&& !*ppPackageInfo
)
212 ret
= SEC_E_INSUFFICIENT_MEMORY
;
214 schan_FreeContextBuffer(info
);
221 schan_FreeContextBuffer (
225 HeapFree(GetProcessHeap(), 0, pvoid
);
231 static PWSTR
SECUR32_strdupW(PCWSTR str
)
237 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
246 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
252 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
256 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
258 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
268 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
274 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
279 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
281 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
292 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
293 const SecPkgInfoW
*inInfoW
)
295 if (info
&& (inInfoA
|| inInfoW
))
297 /* odd, I know, but up until Name and Comment the structures are
300 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
303 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
304 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
308 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
309 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
314 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
315 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
319 EnterCriticalSection(&cs
);
323 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
326 LeaveCriticalSection(&cs
);
330 list_init(&providerTable
->table
);
333 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
336 LeaveCriticalSection(&cs
);
340 list_add_tail(&providerTable
->table
, &ret
->entry
);
344 if (fnTableA
|| fnTableW
)
346 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
347 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
348 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
349 ret
->loaded
= !moduleName
;
354 ret
->moduleName
= SECUR32_strdupW(moduleName
);
358 LeaveCriticalSection(&cs
);
362 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
363 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
368 assert(infoA
|| infoW
);
370 EnterCriticalSection(&cs
);
374 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
377 LeaveCriticalSection(&cs
);
381 packageTable
->numPackages
= 0;
382 list_init(&packageTable
->table
);
385 for (i
= 0; i
< toAdd
; i
++)
387 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
391 list_add_tail(&packageTable
->table
, &package
->entry
);
393 package
->provider
= provider
;
394 _copyPackageInfo(&package
->infoW
,
395 infoA
? &infoA
[i
] : NULL
,
396 infoW
? &infoW
[i
] : NULL
);
398 packageTable
->numPackages
+= toAdd
;
400 LeaveCriticalSection(&cs
);