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 typedef struct _SecurePackageTable
31 typedef struct _SecureProviderTable
36 } SecureProviderTable
;
42 static CRITICAL_SECTION cs
;
43 static CRITICAL_SECTION_DEBUG cs_debug
=
46 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
47 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
49 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
50 static SecurePackageTable
*packageTable
= NULL
;
51 static SecureProviderTable
*providerTable
= NULL
;
53 /***********************************************************************
54 * EnumerateSecurityPackagesW (SECUR32.@)
56 SECURITY_STATUS WINAPI
schan_EnumerateSecurityPackagesW(PULONG pcPackages
,
57 PSecPkgInfoW
*ppPackageInfo
)
59 SECURITY_STATUS ret
= SEC_E_OK
;
61 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
63 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
65 EnterCriticalSection(&cs
);
68 SecurePackage
*package
;
71 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
72 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
74 if (package
->infoW
.Name
)
75 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
76 if (package
->infoW
.Comment
)
77 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
81 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
87 *pcPackages
= packageTable
->numPackages
;
88 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
89 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
90 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
92 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
94 *pkgInfo
= package
->infoW
;
95 if (package
->infoW
.Name
)
97 TRACE("Name[%d] = %S\n", i
- 1, package
->infoW
.Name
);
98 pkgInfo
->Name
= nextString
;
99 lstrcpyW(nextString
, package
->infoW
.Name
);
100 nextString
+= lstrlenW(nextString
) + 1;
103 pkgInfo
->Name
= NULL
;
104 if (package
->infoW
.Comment
)
106 TRACE("Comment[%d] = %S\n", i
- 1, package
->infoW
.Comment
);
107 pkgInfo
->Comment
= nextString
;
108 lstrcpyW(nextString
, package
->infoW
.Comment
);
109 nextString
+= lstrlenW(nextString
) + 1;
112 pkgInfo
->Comment
= NULL
;
116 ret
= SEC_E_INSUFFICIENT_MEMORY
;
119 LeaveCriticalSection(&cs
);
120 TRACE("<-- 0x%08x\n", ret
);
124 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
125 * structures) into an array of SecPkgInfoA structures, which it returns.
127 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
128 const SecPkgInfoW
*info
)
134 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
137 for (i
= 0; i
< cPackages
; i
++)
140 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
141 -1, NULL
, 0, NULL
, NULL
);
143 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
144 -1, NULL
, 0, NULL
, NULL
);
146 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
151 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
152 for (i
= 0; i
< cPackages
; i
++)
154 PSecPkgInfoA pkgInfo
= ret
+ i
;
157 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
160 pkgInfo
->Name
= nextString
;
161 /* just repeat back to WideCharToMultiByte how many bytes
162 * it requires, since we asked it earlier
164 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
165 NULL
, 0, NULL
, NULL
);
166 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
167 pkgInfo
->Name
, bytes
, NULL
, NULL
);
168 nextString
+= lstrlenA(nextString
) + 1;
171 pkgInfo
->Name
= NULL
;
174 pkgInfo
->Comment
= nextString
;
175 /* just repeat back to WideCharToMultiByte how many bytes
176 * it requires, since we asked it earlier
178 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
179 NULL
, 0, NULL
, NULL
);
180 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
181 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
182 nextString
+= lstrlenA(nextString
) + 1;
185 pkgInfo
->Comment
= NULL
;
194 /***********************************************************************
195 * EnumerateSecurityPackagesA (SECUR32.@)
197 SECURITY_STATUS WINAPI
schan_EnumerateSecurityPackagesA(PULONG pcPackages
,
198 PSecPkgInfoA
*ppPackageInfo
)
203 ret
= schan_EnumerateSecurityPackagesW(pcPackages
, &info
);
204 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
206 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
207 if (*pcPackages
&& !*ppPackageInfo
)
210 ret
= SEC_E_INSUFFICIENT_MEMORY
;
212 schan_FreeContextBuffer(info
);
219 schan_FreeContextBuffer (
223 HeapFree(GetProcessHeap(), 0, pvoid
);
229 static PWSTR
SECUR32_strdupW(PCWSTR str
)
235 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
244 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
250 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
254 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
256 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
266 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
272 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
277 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
279 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
290 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
291 const SecPkgInfoW
*inInfoW
)
293 if (info
&& (inInfoA
|| inInfoW
))
295 /* odd, I know, but up until Name and Comment the structures are
298 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
301 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
302 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
306 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
307 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
312 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
313 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
317 EnterCriticalSection(&cs
);
321 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
324 LeaveCriticalSection(&cs
);
328 list_init(&providerTable
->table
);
331 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
334 LeaveCriticalSection(&cs
);
338 list_add_tail(&providerTable
->table
, &ret
->entry
);
342 if (fnTableA
|| fnTableW
)
344 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
345 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
346 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
347 ret
->loaded
= !moduleName
;
352 ret
->moduleName
= SECUR32_strdupW(moduleName
);
356 LeaveCriticalSection(&cs
);
360 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
361 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
366 assert(infoA
|| infoW
);
368 EnterCriticalSection(&cs
);
372 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
375 LeaveCriticalSection(&cs
);
379 packageTable
->numPackages
= 0;
380 list_init(&packageTable
->table
);
383 for (i
= 0; i
< toAdd
; i
++)
385 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
389 list_add_tail(&packageTable
->table
, &package
->entry
);
391 package
->provider
= provider
;
392 _copyPackageInfo(&package
->infoW
,
393 infoA
? &infoA
[i
] : NULL
,
394 infoW
? &infoW
[i
] : NULL
);
396 packageTable
->numPackages
+= toAdd
;
398 LeaveCriticalSection(&cs
);