Index: dll/win32/advapi32/crypt/crypt.c
===================================================================
--- dll/win32/advapi32/crypt/crypt.c	(Revision 31672)
+++ dll/win32/advapi32/crypt/crypt.c	(Arbeitskopie)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 /***********************************************************************
@@ -22,20 +22,22 @@
  *  TODO:
  *  - Reference counting
  *  - Thread-safing
- *  - Signature checking
  */
 
 #include <advapi32.h>
+#include <fcntl.h>
+
 #include "crypt.h"
 #include <winefs.h>
 
-#define NDEBUG
-#include <debug.h>
+#include "wine/debug.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(crypt);
+
 /*
  * Note: this code is harmless on little-endian machines.
  */
-VOID byteReverse(unsigned char *buf, unsigned longs)
+void byteReverse(unsigned char *buf, unsigned longs)
 {
     unsigned int t;
 
@@ -48,10 +50,8 @@
     } while (--longs);
 }
 
-HWND crypt_hWindow = 0;
+static HWND crypt_hWindow;
 
-#define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
-
 #define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
 
@@ -113,7 +113,7 @@
  * str - pointer to ANSI string
  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
  *
- * returns TRUE if unsuccessfull, FALSE otherwise.
+ * returns TRUE if unsuccessful, FALSE otherwise.
  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
  */
 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
@@ -145,7 +145,7 @@
  */
 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
 {
-	int wcount;
+	unsigned int wcount;
 
 	if (!str)
 	{
@@ -174,7 +174,7 @@
 		return FALSE;
 	}
 
-	DPRINT1("FIXME (%s, %p): not verifying image\n", lpszImage, pData);
+	FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
 
 	return TRUE;
 }
@@ -202,7 +202,7 @@
 	if ( !(provider->hModule = LoadLibraryW(pImage)) )
 	{
 		errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
-		DPRINT("Failed to load dll %S\n", pImage);
+		FIXME("Failed to load dll %S\n", pImage);
 		goto error;
 	}
 	provider->dwMagic = MAGIC_CRYPTPROV;
@@ -292,8 +292,8 @@
 	static const WCHAR typeW[] = {'T','y','p','e',0};
 	static const WCHAR imagepathW[] = {'I','m','a','g','e',' ','P','a','t','h',0};
 
-	DPRINT("(%p, %S, %S, %d, %08x)\n", phProv, pszContainer,
-		pszProvider, dwProvType, dwFlags); 
+	TRACE("(%p, %S, %S, %d, %08x)\n", phProv, pszContainer,
+		pszProvider, dwProvType, dwFlags);
 
 	if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
 	{
@@ -313,7 +313,7 @@
 		 * then try the machine default CSP
 		 */
 		if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
-			DPRINT("No provider registered for crypto provider type %d.\n", dwProvType);
+			TRACE("No provider registered for crypto provider type %d.\n", dwProvType);
 			SetLastError(NTE_PROV_TYPE_NOT_DEF);
 			return FALSE;
 		}
@@ -321,13 +321,13 @@
 		{
 			CRYPT_Free(keyname);
 			if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
-				DPRINT("No type registered for crypto provider type %d.\n", dwProvType);
+				TRACE("No type registered for crypto provider type %d.\n", dwProvType);
 				RegCloseKey(key);
 				SetLastError(NTE_PROV_TYPE_NOT_DEF);
 				goto error;
 			}
 			if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
-				DPRINT("Did not find registry entry of crypto provider for %S.\n", keyname);
+				TRACE("Did not find registry entry of crypto provider for %S.\n", keyname);
 				CRYPT_Free(keyname);
 				RegCloseKey(key);
 				SetLastError(NTE_PROV_TYPE_NOT_DEF);
@@ -338,7 +338,7 @@
 		r = RegQueryValueExW(key, nameW, NULL, &keytype, NULL, &len);
 		if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
 		{
-			DPRINT("error %d reading size of 'Name' from registry\n", r );
+			TRACE("error %d reading size of 'Name' from registry\n", r );
 			RegCloseKey(key);
 			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
 			goto error;
@@ -352,7 +352,7 @@
 		r = RegQueryValueExW(key, nameW, NULL, NULL, (LPBYTE)provname, &len);
 		if( r != ERROR_SUCCESS )
 		{
-			DPRINT("error %d reading 'Name' from registry\n", r );
+			TRACE("error %d reading 'Name' from registry\n", r );
 			RegCloseKey(key);
 			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
 			goto error;
@@ -384,7 +384,7 @@
 	}
 	if (type != dwProvType)
 	{
-		DPRINT("Crypto provider has wrong type (%d vs expected %d).\n", type, dwProvType);
+		TRACE("Crypto provider has wrong type (%d vs expected %d).\n", type, dwProvType);
 		SetLastError(NTE_PROV_TYPE_NO_MATCH);
 		goto error;
 	}
@@ -392,7 +392,7 @@
 	r = RegQueryValueExW(key, imagepathW, NULL, &keytype, NULL, &len);
 	if ( r != ERROR_SUCCESS || keytype != REG_SZ)
 	{
-		DPRINT("error %d reading size of 'Image Path' from registry\n", r );
+		TRACE("error %d reading size of 'Image Path' from registry\n", r );
 		RegCloseKey(key);
 		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
 		goto error;
@@ -406,7 +406,7 @@
 	r = RegQueryValueExW(key, imagepathW, NULL, NULL, (LPBYTE)temp, &len);
 	if( r != ERROR_SUCCESS )
 	{
-		DPRINT("error %d reading 'Image Path' from registry\n", r );
+		TRACE("error %d reading 'Image Path' from registry\n", r );
 		RegCloseKey(key);
 		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
 		goto error;
@@ -493,7 +493,7 @@
 	PWSTR pProvider = NULL, pContainer = NULL;
 	BOOL ret = FALSE;
 
-	DPRINT("(%p, %s, %s, %d, %08x)\n", phProv, pszContainer,
+	TRACE("(%p, %s, %s, %d, %08x)\n", phProv, pszContainer,
 		pszProvider, dwProvType, dwFlags);
 
 	if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
@@ -535,7 +535,7 @@
 {
 	PCRYPTPROV pProv = (PCRYPTPROV)hProv;
 
-	DPRINT("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
+	TRACE("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
 
 	if (!pProv)
 	{
@@ -543,6 +543,12 @@
 		return FALSE;
 	}
 
+	if (pProv->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
+
 	pProv->refcount++;
 	return TRUE;
 }
@@ -565,7 +571,7 @@
 	PCRYPTPROV pProv = (PCRYPTPROV)hProv;
 	BOOL ret = TRUE;
 
-	DPRINT("(0x%lx, %08ld)\n", hProv, dwFlags);
+	TRACE("(0x%lx, %08lx)\n", hProv, dwFlags);
 
 	if (!pProv)
 	{
@@ -573,10 +579,17 @@
 		return FALSE;
 	}
 
+	if (pProv->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
+
 	pProv->refcount--;
 	if (pProv->refcount <= 0)
 	{
 		ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
+		pProv->dwMagic = 0;
 		FreeLibrary(pProv->hModule);
 #if 0
 		CRYPT_Free(pProv->pVTable->pContextInfo);
@@ -610,11 +623,20 @@
 {
 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
 
-	DPRINT("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
+	TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
 
 	if (!hProv)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
 
+	if (prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
+
 	return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
 }
 
@@ -644,16 +666,28 @@
 	PCRYPTKEY key = (PCRYPTKEY)hKey;
 	PCRYPTHASH hash;
 
-	DPRINT("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
+	TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
 
 	if (!prov)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
-	if (!phHash)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
+	if (!phHash || prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 	if (dwFlags)
-		CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+	{
+		SetLastError(NTE_BAD_FLAGS);
+		return FALSE;
+	}
 	if (!(hash = CRYPT_Alloc(sizeof(CRYPTHASH))))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 
 	hash->pProvider = prov;
 
@@ -695,10 +729,13 @@
 	PCRYPTKEY key = (PCRYPTKEY)hKey;
 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
 
-	DPRINT("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
+	TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
 
-	if (!key || !pbData || !pdwDataLen)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!key || !pbData || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = key->pProvider;
 	return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
@@ -728,14 +765,23 @@
 	PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
 	PCRYPTKEY key;
 
-	DPRINT("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
+	TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
 
 	if (!prov || !hash)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
-	if (!phKey)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
+	if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 	if (!(key = CRYPT_Alloc(sizeof(CRYPTKEY))))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 
 	key->pProvider = prov;
 	if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
@@ -768,11 +814,20 @@
 	PCRYPTPROV prov;
 	BOOL ret;
 
-	DPRINT("(0x%lx)\n", hHash);
+	TRACE("(0x%lx)\n", hHash);
 
 	if (!hash)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
 
+	if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
+
 	prov = hash->pProvider;
 	ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
 	CRYPT_Free(hash);
@@ -797,11 +852,20 @@
 	PCRYPTPROV prov;
 	BOOL ret;
 
-	DPRINT("(0x%lx)\n", hKey);
+	TRACE("(0x%lx)\n", hKey);
 
 	if (!key)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
 
+	if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
+
 	prov = key->pProvider;
 	ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
 	CRYPT_Free(key);
@@ -829,18 +893,28 @@
 	PCRYPTPROV prov;
 	PCRYPTHASH orghash, newhash;
 
-	DPRINT("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
+	TRACE("(0x%lx, %p, %08x, %p)\n", hHash, pdwReserved, dwFlags, phHash);
 
 	orghash = (PCRYPTHASH)hHash;
-	if (!orghash || pdwReserved || !phHash)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!orghash || pdwReserved || !phHash || !orghash->pProvider || 
+		orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = orghash->pProvider;
 	if (!prov->pFuncs->pCPDuplicateHash)
-		CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
+	{
+		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+		return FALSE;
+	}
 
 	if (!(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 
 	newhash->pProvider = prov;
 	if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
@@ -872,18 +946,28 @@
 	PCRYPTPROV prov;
 	PCRYPTKEY orgkey, newkey;
 
-	DPRINT("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
+	TRACE("(0x%lx, %p, %08lx, %p)\n", hKey, pdwReserved, dwFlags, phKey);
 
 	orgkey = (PCRYPTKEY)hKey;
-	if (!orgkey || pdwReserved || !phKey)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!orgkey || pdwReserved || !phKey || !orgkey->pProvider || 
+		orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = orgkey->pProvider;
 	if (!prov->pFuncs->pCPDuplicateKey)
-		CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
+	{
+		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+		return FALSE;
+	}
 
 	if (!(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 
 	newkey->pProvider = prov;
 	if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
@@ -901,7 +985,7 @@
  * Encrypts data.
  *
  * PARAMS
- *  hKey       [I] Handle to the enryption key.
+ *  hKey       [I] Handle to the encryption key.
  *  hHash      [I] Handle to a hash object.
  *  Final      [I] TRUE if this is the last section to encrypt.
  *  dwFlags    [I] Can be CRYPT_OAEP.
@@ -925,10 +1009,13 @@
 	PCRYPTKEY key = (PCRYPTKEY)hKey;
 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
 
-	DPRINT("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
+	TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
 
-	if (!key || !pdwDataLen)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = key->pProvider;
 	return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
@@ -938,7 +1025,7 @@
 /******************************************************************************
  * CryptEnumProvidersW (ADVAPI32.@)
  *
- * Returns the next availabe CSP.
+ * Returns the next available CSP.
  *
  * PARAMS
  *  dwIndex     [I] Index of the next provider to be enumerated.
@@ -961,19 +1048,34 @@
 		DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
 {
 	HKEY hKey;
+	static const WCHAR providerW[] = {
+                'S','o','f','t','w','a','r','e','\\',
+                'M','i','c','r','o','s','o','f','t','\\',
+                'C','r','y','p','t','o','g','r','a','p','h','y','\\',
+                'D','e','f','a','u','l','t','s','\\',
+                'P','r','o','v','i','d','e','r',0
+        };
+	static const WCHAR typeW[] = {'T','y','p','e',0};
 
-	DPRINT("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
+	TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
 		pdwProvType, pszProvName, pcbProvName);
 
 	if (pdwReserved || !pcbProvName)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 	if (dwFlags)
-		CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+	{
+		SetLastError(NTE_BAD_FLAGS);
+		return FALSE;
+	}
 
-	if (RegOpenKeyW(HKEY_LOCAL_MACHINE,
-			L"Software\\Microsoft\\Cryptography\\Defaults\\Provider",
-			&hKey))
-		CRYPT_ReturnLastError(NTE_FAIL);
+	if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
+	{
+		SetLastError(NTE_FAIL);
+		return FALSE;
+	}
 
 	if (!pszProvName)
 	{
@@ -984,29 +1086,35 @@
 				 NULL, NULL, NULL, NULL, NULL, NULL);
 
 		if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
-			CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+		{
+			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+			return FALSE;
+		}
 
 		RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
+		CRYPT_Free(provNameW);
 		(*pcbProvName)++;
 		*pcbProvName *= sizeof(WCHAR);
 
-		CRYPT_Free(provNameW);
-
 		if (dwIndex >= numkeys)
-			CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
-	}
-	else
-	{
+		{
+			SetLastError(ERROR_NO_MORE_ITEMS);
+			return FALSE;
+		}
+	} else {
 		DWORD size = sizeof(DWORD);
 		DWORD result;
 		HKEY subkey;
 
 		result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
 		if (result)
-			CRYPT_ReturnLastError(result);
+		{
+			SetLastError(result);
+			return FALSE;
+		}
 		if (RegOpenKeyW(hKey, pszProvName, &subkey))
 			return FALSE;
-		if (RegQueryValueExW(subkey, L"Type", NULL, NULL, (BYTE*)pdwProvType, &size))
+		if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
 			return FALSE;
 		RegCloseKey(subkey);
 	}
@@ -1017,7 +1125,7 @@
 /******************************************************************************
  * CryptEnumProvidersA (ADVAPI32.@)
  *
- * see CryptEnumProvidersW
+ * See CryptEnumProvidersW.
  */
 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
 		DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
@@ -1026,24 +1134,34 @@
 	DWORD strlen;
 	BOOL ret; /* = FALSE; */
 
-	DPRINT("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
+	TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
 			pdwProvType, pszProvName, pcbProvName);
 
-	strlen = *pcbProvName * sizeof(WCHAR);
+	if(!CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen))
+		return FALSE;
 	if (pszProvName && !(str = CRYPT_Alloc(strlen)))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 	ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
 	if (str)
+		CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
+	*pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
+	if (str)
 	{
-		CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
 		CRYPT_Free(str);
+		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+		{
+			SetLastError(ERROR_MORE_DATA);
+			return FALSE;
+	    }
 	}
-	*pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
 	return ret;
 }
 
 /******************************************************************************
- * CryptEnumProviderTypesA (ADVAPI32i.@)
+ * CryptEnumProviderTypesW (ADVAPI32.@)
  *
  * Retrieves the next type of CSP supported.
  *
@@ -1061,50 +1179,72 @@
  *   Failure: FALSE
  *
  *  NOTES
- *   If pszTypeName is NULL, CryptEnumProviderTypesA sets the size of the name
+ *   If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
  *   for memory allocation purposes.
  */
-BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
-		DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
+BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
+		DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
 {
 	HKEY hKey, hSubkey;
 	DWORD keylen, numkeys, dwType;
-	PSTR keyname, ch;
+	PWSTR keyname, ch;
 	DWORD result;
+	static const WCHAR KEYSTR[] = {
+                'S','o','f','t','w','a','r','e','\\',
+                'M','i','c','r','o','s','o','f','t','\\',
+                'C','r','y','p','t','o','g','r','a','p','h','y','\\',
+                'D','e','f','a','u','l','t','s','\\',
+                'P','r','o','v','i','d','e','r',' ','T','y','p','e','s',0
+	};
+	static const WCHAR typenameW[] = {'T','y','p','e','N','a','m','e',0};
 
-	DPRINT("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
+	TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved,
 		dwFlags, pdwProvType, pszTypeName, pcbTypeName);
 
 	if (pdwReserved || !pdwProvType || !pcbTypeName)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 	if (dwFlags)
-		CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+	{
+		SetLastError(NTE_BAD_FLAGS);
+		return FALSE;
+	}
 
-	if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
+	if (RegOpenKeyW(HKEY_LOCAL_MACHINE, KEYSTR, &hKey))
 		return FALSE;
 
-	RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
+	RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
 	if (dwIndex >= numkeys)
-		CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
+	{
+		SetLastError(ERROR_NO_MORE_ITEMS);
+		return FALSE;
+	}
 	keylen++;
-	if ( !(keyname = CRYPT_Alloc(keylen)) )
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
-	if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) )
+	if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
 	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
+	if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
 		CRYPT_Free(keyname);
 		return FALSE;
 	}
-	RegOpenKeyA(hKey, keyname, &hSubkey);
-	ch = keyname + strlen(keyname);
+	RegOpenKeyW(hKey, keyname, &hSubkey);
+	ch = keyname + wcslen(keyname);
 	/* Convert "Type 000" to 0, etc/ */
 	*pdwProvType = *(--ch) - '0';
 	*pdwProvType += (*(--ch) - '0') * 10;
 	*pdwProvType += (*(--ch) - '0') * 100;
 	CRYPT_Free(keyname);
 
-	result = RegQueryValueExA(hSubkey, "TypeName", NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
+	result = RegQueryValueExW(hSubkey, typenameW, NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
 	if (result)
-		CRYPT_ReturnLastError(result);
+	{
+		SetLastError(result);
+		return FALSE;
+	}
 
 	RegCloseKey(hSubkey);
 	RegCloseKey(hKey);
@@ -1112,29 +1252,40 @@
 }
 
 /******************************************************************************
- * CryptEnumProviderTypesW (ADVAPI32.@)
+ * CryptEnumProviderTypesA (ADVAPI32.@)
  *
- * see CryptEnumProviderTypesA
+ * See CryptEnumProviderTypesW.
  */
-BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
-		DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
+BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
+		DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
 {
-	PSTR str = NULL;
+	PWSTR str = NULL;
 	DWORD strlen;
 	BOOL ret;
 
-	DPRINT("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
+	TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
 			pdwProvType, pszTypeName, pcbTypeName);
-	strlen = *pcbTypeName / sizeof(WCHAR);
-	if (pszTypeName && !(str = CRYPT_Alloc(strlen)))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
-	ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
+
+	if(!CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen))
+		return FALSE;
+	if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) )
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
+	ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
 	if (str)
+		CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
+	*pcbTypeName = strlen / sizeof(WCHAR);
+	if (str)
 	{
-		CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
 		CRYPT_Free(str);
+		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+		{
+			SetLastError(ERROR_MORE_DATA);
+			return FALSE;
+		}
 	}
-	*pcbTypeName = strlen * sizeof(WCHAR);
 	return ret;
 }
 
@@ -1165,10 +1316,13 @@
 	PCRYPTPROV prov;
 	PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
 
-	DPRINT("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
+	TRACE("(0x%lx, 0x%lx, %ld, %08lx, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
 
-	if (!key || !pdwDataLen)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = key->pProvider;
 	return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
@@ -1195,14 +1349,23 @@
 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
 	PCRYPTKEY key;
 
-	DPRINT("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
+	TRACE("(0x%lx, %d, %08lx, %p)\n", hProv, Algid, dwFlags, phKey);
 
 	if (!prov)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
-	if (!phKey)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
+	if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 	if (!(key = CRYPT_Alloc(sizeof(CRYPTKEY))))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 
 	key->pProvider = prov;
 
@@ -1300,7 +1463,7 @@
 	DWORD strlen;
 	BOOL ret = FALSE;
 
-	DPRINT("(%d, %p, %08x, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
+	TRACE("(%d, %p, %08x, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
 
 	CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &strlen);
 	if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
@@ -1349,10 +1512,13 @@
 	PCRYPTPROV prov;
 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
 
-	DPRINT("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
+	TRACE("(0x%lx, %ld, %p, %p, %08lx)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
 
-	if (!hash || !pdwDataLen)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!hash || !pdwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = hash->pProvider;
 	return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
@@ -1384,10 +1550,13 @@
 	PCRYPTPROV prov;
 	PCRYPTKEY key = (PCRYPTKEY)hKey;
 
-	DPRINT("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
+	TRACE("(0x%lx, %ld, %p, %p, %08lx)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
 
-	if (!key || !pdwDataLen)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = key->pProvider;
 	return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
@@ -1418,8 +1587,14 @@
 {
 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
 
-	DPRINT("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
+	TRACE("(0x%lx, %ld, %p, %p, %08lx)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
 
+	if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
+
 	return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
 }
 
@@ -1442,14 +1617,23 @@
 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
 	PCRYPTKEY key;
 
-	DPRINT("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
+	TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
 
 	if (!prov)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
-	if (!phUserKey)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
+	if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 	if (!(key = CRYPT_Alloc(sizeof(CRYPTKEY))))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 
 	key->pProvider = prov;
 
@@ -1485,12 +1669,18 @@
 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
 	PCRYPTPROV prov;
 
-	DPRINT("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
+	TRACE("(0x%lx, %p, %ld, %08lx)\n", hHash, pbData, dwDataLen, dwFlags);
 
 	if (!hash)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
-	if (!pbData || !dwDataLen)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
+	if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = hash->pProvider;
 	return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
@@ -1499,6 +1689,8 @@
 /******************************************************************************
  * CryptHashSessionKey (ADVAPI32.@)
  *
+ * Compute the cryptographic hash of a session key object.
+ *
  * PARAMS
  *  hHash   [I] Handle to the hash object.
  *  hKey    [I] Handle to the key to be hashed.
@@ -1514,11 +1706,20 @@
 	PCRYPTKEY key = (PCRYPTKEY)hKey;
 	PCRYPTPROV prov;
 
-	DPRINT("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
+	TRACE("(0x%lx, 0x%lx, %08lx)\n", hHash, hKey, dwFlags);
 
 	if (!hash || !key)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
 
+	if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
+
 	prov = hash->pProvider;
 	return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
 }
@@ -1526,6 +1727,8 @@
 /******************************************************************************
  * CryptImportKey (ADVAPI32.@)
  *
+ * Transfer a cryptographic key from a key BLOB into a cryptographic service provider (CSP).
+ *
  * PARAMS
  *  hProv     [I] Handle of a CSP.
  *  pbData    [I] Contains the key to be imported.
@@ -1544,13 +1747,19 @@
 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
 	PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
 
-	DPRINT("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
+	TRACE("(0x%lx, %p, %ld, 0x%lx, %08lx, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
 
-	if (!prov || !pbData || !dwDataLen || !phKey)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!prov || !pbData || !dwDataLen || !phKey || prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	if (!(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))))
-		CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+	{
+		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+		return FALSE;
+	}
 
 	importkey->pProvider = prov;
 	if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
@@ -1565,14 +1774,6 @@
 }
 
 /******************************************************************************
- * CryptSignHashA
- *
- * Note: Since the sDesciption (string) is supposed to be NULL and
- *	is only retained for compatibility no string conversions are required
- *	and only one implementation is required for both ANSI and Unicode.
- *	We still need to export both:
- *
- * CryptSignHashA (ADVAPI32.@)
  * CryptSignHashW (ADVAPI32.@)
  *
  * Signs data.
@@ -1580,7 +1781,7 @@
  * PARAMS
  *  hHash        [I] Handle of the hash object to be signed.
  *  dwKeySpec    [I] Private key to use.
- *  sDescription [I] Must be NULL.
+ *  sDescription [I] Should be NULL.
  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
  *  pbSignature  [O] Buffer of the signature data.
  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
@@ -1588,38 +1789,58 @@
  * RETURNS
  *  Success: TRUE
  *  Failure: FALSE
+ *
+ * NOTES
+ *  Because of security flaws sDescription should not be used and should thus be
+ *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
+ *  Providers.
  */
-BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
-		DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
-{
-	/* Since sDescription is ignored we dont need to convert it, we just pass null */
-	return CryptSignHashW(hHash, dwKeySpec, NULL, dwFlags, pbSignature, pdwSigLen);
-}
-
 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
 		DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
 {
 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
 	PCRYPTPROV prov;
 
-	DPRINT("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
-	if (sDescription)
+	TRACE("(0x%lx, %ld, %S, %08lx, %p, %p)\n",
+		hHash, dwKeySpec, sDescription, dwFlags, pbSignature, pdwSigLen);
+
+	if (!hash)
 	{
-		/* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/cryptsignhash.asp */
-		DPRINT("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
 	}
+	if (!pdwSigLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
-	if (!hash)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
-	if (!pdwSigLen || !hash->pProvider)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
-
 	prov = hash->pProvider;
-	return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
+	return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
 		dwFlags, pbSignature, pdwSigLen);
 }
 
+/******************************************************************************
+ * CryptSignHashA (ADVAPI32.@)
+ *
+ * See CryptSignHashW.
+ */
+BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
+		DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
+{
+	LPWSTR wsDescription;
+	BOOL result;
 
+	TRACE("(0x%lx, %ld, %s, %08lx, %p, %p)\n", 
+		hHash, dwKeySpec, sDescription, dwFlags, pbSignature, pdwSigLen);
+
+	CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
+	result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
+	CRYPT_Free(wsDescription);
+
+	return result;
+}
+
 /******************************************************************************
  * CryptSetHashParam (ADVAPI32.@)
  *
@@ -1640,10 +1861,13 @@
 	PCRYPTPROV prov;
 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
 
-	DPRINT("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
+	TRACE("(0x%lx, %ld, %p, %08lx)\n", hHash, dwParam, pbData, dwFlags);
 
-	if (!hash || !pbData)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!hash || !pbData || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = hash->pProvider;
 	return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
@@ -1670,10 +1894,13 @@
 	PCRYPTPROV prov;
 	PCRYPTKEY key = (PCRYPTKEY)hKey;
 
-	DPRINT("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
+	TRACE("(0x%lx, %ld, %p, %08lx)\n", hKey, dwParam, pbData, dwFlags);
 
-	if (!key || !pbData)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+	if (!key || !pbData || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 
 	prov = key->pProvider;
 	return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
@@ -1695,18 +1922,18 @@
  */
 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
 {
-	DPRINT("(%s, %ld)\n", pszProvName, dwProvType);
+	TRACE("(%s, %ld)\n", pszProvName, dwProvType);
 	return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
 }
 
 /******************************************************************************
  * CryptSetProviderW (ADVAPI32.@)
  *
- * See CryptSetProviderA
+ * See CryptSetProviderA.
  */
 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
 {
-	DPRINT("(%S, %ld)\n", pszProvName, dwProvType);
+	TRACE("(%S, %ld)\n", pszProvName, dwProvType);
 	return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
 }
 
@@ -1731,7 +1958,7 @@
 	PWSTR keyname;
 	static const WCHAR nameW[] = {'N','a','m','e',0};
 
-	DPRINT("(%S, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
+	TRACE("(%S, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
 
 	if (!pszProvName || pdwReserved)
 	{
@@ -1811,7 +2038,7 @@
 	BOOL ret = FALSE;
 	PWSTR str = NULL;
 
-	DPRINT("(%s, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
+	TRACE("(%s, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
 
 	if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
 	{
@@ -1840,14 +2067,22 @@
 {
 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
 
-	DPRINT("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
+	TRACE("(0x%lx, %ld, %p, %08lx)\n", hProv, dwParam, pbData, dwFlags);
 
 	if (!prov)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+	{
+		SetLastError(ERROR_INVALID_HANDLE);
+		return FALSE;
+	}
+	if (prov->dwMagic != MAGIC_CRYPTPROV)
+	{
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
+	}
 	if (dwFlags & PP_USE_HARDWARE_RNG)
 	{
-		DPRINT1("PP_USE_HARDWARE_RNG: What do I do with this?\n");
-		DPRINT1("\tLetting the CSP decide.\n");
+		FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
+		FIXME("\tLetting the CSP decide.\n");
 	}
 	if (dwFlags & PP_CLIENT_HWND)
 	{
@@ -1866,14 +2101,6 @@
 }
 
 /******************************************************************************
- * CryptVerifySignatureA
- *
- * Note: Since the sDesciption (string) is supposed to be NULL and
- *	is only retained for compatibility no string conversions are required
- *	and only one implementation is required for both ANSI and Unicode.
- *	We still need to export both:
- *
- * CryptVerifySignatureA (ADVAPI32.@)
  * CryptVerifySignatureW (ADVAPI32.@)
  *
  * Verifies the signature of a hash object.
@@ -1883,49 +2110,116 @@
  *  pbSignature  [I] Signature data to verify.
  *  dwSigLen     [I] Size of pbSignature.
  *  hPubKey      [I] Handle to the public key to authenticate signature.
- *  sDescription [I] Must be set to NULL.
+ *  sDescription [I] Should be NULL.
  *  dwFlags      [I] See MSDN doc.
  *
  * RETURNS
  *  Success: TRUE
  *  Failure: FALSE
+ * 
+ * NOTES
+ *  Because of security flaws sDescription should not be used and should thus be
+ *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
+ *  Providers.
  */
-BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
-		HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
+BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
+		HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
 {
 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
 	PCRYPTKEY key = (PCRYPTKEY)hPubKey;
 	PCRYPTPROV prov;
 
-	DPRINT("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
-			dwSigLen, hPubKey, dwFlags);
-	if (sDescription)
+	TRACE("(0x%lx, %p, %ld, 0x%lx, %S, %08lx)\n", hHash, pbSignature,
+			dwSigLen, hPubKey, sDescription, dwFlags);
+
+	if (!hash || !key ||
+	    !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
+	    !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
 	{
-		DPRINT("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
+		SetLastError(ERROR_INVALID_PARAMETER);
+		return FALSE;
 	}
 
-	if (!hash || !key)
-		CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
-	if (!pbSignature || !dwSigLen)
-		CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
-
 	prov = hash->pProvider;
 	return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
-		key->hPrivate, NULL, dwFlags);
+		key->hPrivate, sDescription, dwFlags);
 }
 
-BOOL WINAPI
-CryptVerifySignatureW (HCRYPTHASH hHash,
-			CONST BYTE *pbSignature,
-			DWORD dwSigLen,
-			HCRYPTKEY hPubKey,
-			LPCWSTR sDescription,
-			DWORD dwFlags)
+/******************************************************************************
+ * CryptVerifySignatureA (ADVAPI32.@)
+ *
+ * See CryptVerifySignatureW.
+ */
+BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
+		HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
 {
-	OutputDebugStringA ("ADVAPI32!CryptVerifySignatureW not implemented!");
-	return FALSE;
+	LPWSTR wsDescription;
+	BOOL result;
+
+	TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
+			dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
+
+	CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
+	result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
+	CRYPT_Free(wsDescription);
+
+	return result;
 }
 
+/******************************************************************************
+ * SystemFunction030   (ADVAPI32.@)
+ *
+ * Tests if two blocks of 16 bytes are equal
+ *
+ * PARAMS
+ *  b1,b2   [I] block of 16 bytes
+ *
+ * RETURNS
+ *  TRUE  if blocks are the same
+ *  FALSE if blocks are different
+ */
+BOOL WINAPI SystemFunction030(PVOID b1, PVOID b2)
+{
+    return !memcmp(b1, b2, 0x10);
+}
+
+/******************************************************************************
+ * SystemFunction036   (ADVAPI32.@)
+ *
+ * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
+ *
+ * PARAMS
+ *  pbBufer [O] Pointer to memory to receive random bytes.
+ *  dwLen   [I] Number of random bytes to fetch.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+
+BOOL WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
+{
+    int dev_random;
+
+    /* FIXME: /dev/urandom does not provide random numbers of a sufficient
+     * quality for cryptographic applications. /dev/random is much better,  
+     * but it blocks if the kernel has not yet collected enough entropy for
+     * the request, which will suspend the calling thread for an indefinite
+     * amount of time. */
+    dev_random = open("/dev/urandom", O_RDONLY);
+    if (dev_random != -1)
+    {
+        if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
+        {
+            close(dev_random);
+            return TRUE;
+        }
+        close(dev_random);
+    }
+    SetLastError(NTE_FAIL);
+    return FALSE;
+}    
+    
 /*
    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
    in crypt32.dll.
@@ -1934,36 +2228,59 @@
 /******************************************************************************
  * SystemFunction040   (ADVAPI32.@)
  *
- * PARAMS:
- *   memory : pointer to memory to encrypt
- *   length : length of region to encrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
- *   flags  : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
- *            control whether other processes are able to decrypt the memory. The same value must be given
+ * MSDN documents this function as RtlEncryptMemory.
+ *
+ * PARAMS
+ *  memory [I/O] Pointer to memory to encrypt.
+ *  length [I] Length of region to encrypt in bytes.
+ *  flags  [I] Control whether other processes are able to decrypt the memory.
+ *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
+ *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
+ *    RTL_ENCRYPT_OPTION_SAME_LOGON
+ *    
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: NTSTATUS error code
+ *
+ * NOTES
+ *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
+ *  If flags are specified when encrypting, the same flag value must be given
  *            when decrypting the memory.
  */
-NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)  /* RtlEncryptMemory */
+NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
 {
-	DPRINT1("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
+	FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
 	return STATUS_SUCCESS;
 }
 
 /******************************************************************************
  * SystemFunction041  (ADVAPI32.@)
  *
- * PARAMS:
- *   memory : pointer to memory to decrypt
- *   length : length of region to decrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
- *   flags  : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
- *            control whether other processes are able to decrypt the memory. The same value must be given
- *            when encrypting the memory.
+ * MSDN documents this function as RtlDecryptMemory.
+ *
+ * PARAMS
+ *  memory [I/O] Pointer to memory to decrypt.
+ *  length [I] Length of region to decrypt in bytes.
+ *  flags  [I] Control whether other processes are able to decrypt the memory.
+ *    RTL_ENCRYPT_OPTION_SAME_PROCESS
+ *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
+ *    RTL_ENCRYPT_OPTION_SAME_LOGON
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: NTSTATUS error code
+ *
+ * NOTES
+ *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
+ *  If flags are specified when encrypting, the same flag value must be given
+ *  when decrypting the memory.
  */
-NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)  /* RtlDecryptMemory */
+NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
 {
-	DPRINT1("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
+	FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
 	return STATUS_SUCCESS;
 }
 
-
 /*
  * @unimplemented
  */
@@ -1972,7 +2289,7 @@
 	PENCRYPTION_CERTIFICATE_LIST pencryption_certificate_list
 	)
 {
-	DPRINT1("%s() not implemented!\n", __FUNCTION__);
+	FIXME("%s() not implemented!\n", __FUNCTION__);
 	return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
@@ -1984,7 +2301,7 @@
 	PENCRYPTION_CERTIFICATE_HASH_LIST pencryption_certificate_hash_list
 	)
 {
-	DPRINT1("%s() not implemented!\n", __FUNCTION__);
+	FIXME("%s() not implemented!\n", __FUNCTION__);
 	return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
@@ -1996,7 +2313,7 @@
 	LPDWORD lpStatus
 	)
 {
-	DPRINT1("%s(%S) not implemented!\n", __FUNCTION__, lpFileName);
+	FIXME("%s(%S) not implemented!\n", __FUNCTION__, lpFileName);
 	if (!lpStatus)
 		return FALSE;
 	*lpStatus = FILE_SYSTEM_NOT_SUPPORT;
@@ -2040,7 +2357,7 @@
 	PENCRYPTION_CERTIFICATE_HASH_LIST* pencryption_certificate_hash_list
 	)
 {
-	DPRINT1("%s() not implemented!\n", __FUNCTION__);
+	FIXME("%s() not implemented!\n", __FUNCTION__);
 	return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
@@ -2052,7 +2369,7 @@
 	PENCRYPTION_CERTIFICATE_HASH_LIST pencryption_certificate_hash_list
 	)
 {
-	DPRINT1("%s() not implemented!\n", __FUNCTION__);
+	FIXME("%s() not implemented!\n", __FUNCTION__);
 	return;
 }
 
@@ -2065,7 +2382,7 @@
 	PENCRYPTION_CERTIFICATE_HASH_LIST* pencryption_certificate_hash_list
 	)
 {
-	DPRINT1("%s() not implemented!\n", __FUNCTION__);
+	FIXME("%s() not implemented!\n", __FUNCTION__);
 	return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
@@ -2077,7 +2394,7 @@
     BOOL Disable
     )
 {
-	DPRINT1("%s() not implemented!\n", __FUNCTION__);
+	FIXME("%s() not implemented!\n", __FUNCTION__);
 	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
 	return FALSE;
 }
Index: dll/win32/advapi32/crypt/crypt_md4.c
===================================================================
--- dll/win32/advapi32/crypt/crypt_md4.c	(Revision 31672)
+++ dll/win32/advapi32/crypt/crypt_md4.c	(Arbeitskopie)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 /*
@@ -45,98 +45,9 @@
     unsigned char digest[16];
 } MD4_CTX;
 
+static void MD4Transform( unsigned int buf[4], unsigned int const in[16] );
 
-/* The three core functions */
-
-#define rotl32(x,n)  (((x) << ((unsigned int)(n))) | ((x) >> (32 - (unsigned int)(n))))
-
-#define F( x, y, z ) (((x) & (y)) | ((~x) & (z)))
-#define G( x, y, z ) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-#define H( x, y, z ) ((x) ^ (y) ^ (z))
-
-#define FF( a, b, c, d, x, s ) { \
-    (a) += F( (b), (c), (d) ) + (x); \
-    (a) = rotl32( (a), (s) ); \
-  }
-#define GG( a, b, c, d, x, s ) { \
-    (a) += G( (b), (c), (d) ) + (x) + (unsigned int)0x5a827999; \
-    (a) = rotl32( (a), (s) ); \
-  }
-#define HH( a, b, c, d, x, s ) { \
-    (a) += H( (b), (c), (d) ) + (x) + (unsigned int)0x6ed9eba1; \
-    (a) = rotl32( (a), (s) ); \
-  }
-
 /*
- * The core of the MD4 algorithm
- */
-static VOID MD4Transform(unsigned int buf[4], const unsigned int in[16])
-{
-    register unsigned int a, b, c, d;
-
-    a = buf[0];
-    b = buf[1];
-    c = buf[2];
-    d = buf[3];
-
-    FF( a, b, c, d, in[0], 3 );
-    FF( d, a, b, c, in[1], 7 );
-    FF( c, d, a, b, in[2], 11 );
-    FF( b, c, d, a, in[3], 19 );
-    FF( a, b, c, d, in[4], 3 );
-    FF( d, a, b, c, in[5], 7 );
-    FF( c, d, a, b, in[6], 11 );
-    FF( b, c, d, a, in[7], 19 );
-    FF( a, b, c, d, in[8], 3 );
-    FF( d, a, b, c, in[9], 7 );
-    FF( c, d, a, b, in[10], 11 );
-    FF( b, c, d, a, in[11], 19 );
-    FF( a, b, c, d, in[12], 3 );
-    FF( d, a, b, c, in[13], 7 );
-    FF( c, d, a, b, in[14], 11 );
-    FF( b, c, d, a, in[15], 19 );
-
-    GG( a, b, c, d, in[0], 3 );
-    GG( d, a, b, c, in[4], 5 );
-    GG( c, d, a, b, in[8], 9 );
-    GG( b, c, d, a, in[12], 13 );
-    GG( a, b, c, d, in[1], 3 );
-    GG( d, a, b, c, in[5], 5 );
-    GG( c, d, a, b, in[9], 9 );
-    GG( b, c, d, a, in[13], 13 );
-    GG( a, b, c, d, in[2], 3 );
-    GG( d, a, b, c, in[6], 5 );
-    GG( c, d, a, b, in[10], 9 );
-    GG( b, c, d, a, in[14], 13 );
-    GG( a, b, c, d, in[3], 3 );
-    GG( d, a, b, c, in[7], 5 );
-    GG( c, d, a, b, in[11], 9 );
-    GG( b, c, d, a, in[15], 13 );
-
-    HH( a, b, c, d, in[0], 3 );
-    HH( d, a, b, c, in[8], 9 );
-    HH( c, d, a, b, in[4], 11 );
-    HH( b, c, d, a, in[12], 15 );
-    HH( a, b, c, d, in[2], 3 );
-    HH( d, a, b, c, in[10], 9 );
-    HH( c, d, a, b, in[6], 11 );
-    HH( b, c, d, a, in[14], 15 );
-    HH( a, b, c, d, in[1], 3 );
-    HH( d, a, b, c, in[9], 9 );
-    HH( c, d, a, b, in[5], 11 );
-    HH( b, c, d, a, in[13], 15 );
-    HH( a, b, c, d, in[3], 3 );
-    HH( d, a, b, c, in[11], 9 );
-    HH( c, d, a, b, in[7], 11 );
-    HH( b, c, d, a, in[15], 15 );
-
-    buf[0] += a;
-    buf[1] += b;
-    buf[2] += c;
-    buf[3] += d;
-}
-
-/*
  * Start MD4 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
  */
@@ -251,3 +162,147 @@
     byteReverse( (unsigned char *)ctx->buf, 4 );
     memcpy(ctx->digest, ctx->buf, 16);
 }
+
+/* The three core functions */
+
+#define rotl32(x,n)  (((x) << ((unsigned int)(n))) | ((x) >> (32 - (unsigned int)(n))))
+
+#define F( x, y, z ) (((x) & (y)) | ((~x) & (z)))
+#define G( x, y, z ) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H( x, y, z ) ((x) ^ (y) ^ (z))
+
+#define FF( a, b, c, d, x, s ) { \
+    (a) += F( (b), (c), (d) ) + (x); \
+    (a) = rotl32( (a), (s) ); \
+  }
+#define GG( a, b, c, d, x, s ) { \
+    (a) += G( (b), (c), (d) ) + (x) + (unsigned int)0x5a827999; \
+    (a) = rotl32( (a), (s) ); \
+  }
+#define HH( a, b, c, d, x, s ) { \
+    (a) += H( (b), (c), (d) ) + (x) + (unsigned int)0x6ed9eba1; \
+    (a) = rotl32( (a), (s) ); \
+  }
+
+/*
+ * The core of the MD4 algorithm
+ */
+static void MD4Transform(unsigned int buf[4], const unsigned int in[16])
+{
+    register unsigned int a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    FF( a, b, c, d, in[0], 3 );
+    FF( d, a, b, c, in[1], 7 );
+    FF( c, d, a, b, in[2], 11 );
+    FF( b, c, d, a, in[3], 19 );
+    FF( a, b, c, d, in[4], 3 );
+    FF( d, a, b, c, in[5], 7 );
+    FF( c, d, a, b, in[6], 11 );
+    FF( b, c, d, a, in[7], 19 );
+    FF( a, b, c, d, in[8], 3 );
+    FF( d, a, b, c, in[9], 7 );
+    FF( c, d, a, b, in[10], 11 );
+    FF( b, c, d, a, in[11], 19 );
+    FF( a, b, c, d, in[12], 3 );
+    FF( d, a, b, c, in[13], 7 );
+    FF( c, d, a, b, in[14], 11 );
+    FF( b, c, d, a, in[15], 19 );
+
+    GG( a, b, c, d, in[0], 3 );
+    GG( d, a, b, c, in[4], 5 );
+    GG( c, d, a, b, in[8], 9 );
+    GG( b, c, d, a, in[12], 13 );
+    GG( a, b, c, d, in[1], 3 );
+    GG( d, a, b, c, in[5], 5 );
+    GG( c, d, a, b, in[9], 9 );
+    GG( b, c, d, a, in[13], 13 );
+    GG( a, b, c, d, in[2], 3 );
+    GG( d, a, b, c, in[6], 5 );
+    GG( c, d, a, b, in[10], 9 );
+    GG( b, c, d, a, in[14], 13 );
+    GG( a, b, c, d, in[3], 3 );
+    GG( d, a, b, c, in[7], 5 );
+    GG( c, d, a, b, in[11], 9 );
+    GG( b, c, d, a, in[15], 13 );
+
+    HH( a, b, c, d, in[0], 3 );
+    HH( d, a, b, c, in[8], 9 );
+    HH( c, d, a, b, in[4], 11 );
+    HH( b, c, d, a, in[12], 15 );
+    HH( a, b, c, d, in[2], 3 );
+    HH( d, a, b, c, in[10], 9 );
+    HH( c, d, a, b, in[6], 11 );
+    HH( b, c, d, a, in[14], 15 );
+    HH( a, b, c, d, in[1], 3 );
+    HH( d, a, b, c, in[9], 9 );
+    HH( c, d, a, b, in[5], 11 );
+    HH( b, c, d, a, in[13], 15 );
+    HH( a, b, c, d, in[3], 3 );
+    HH( d, a, b, c, in[11], 9 );
+    HH( c, d, a, b, in[7], 11 );
+    HH( b, c, d, a, in[15], 15 );
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+
+/******************************************************************************
+ * SystemFunction007  [ADVAPI32.@]
+ *
+ * MD4 hash a unicode string
+ *
+ * PARAMS
+ *   string  [I] the string to hash
+ *   output  [O] the md4 hash of the string (16 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL
+ *
+ */
+NTSTATUS WINAPI SystemFunction007(const UNICODE_STRING *string, LPBYTE hash)
+{
+    MD4_CTX ctx;
+
+    MD4Init( &ctx );
+    MD4Update( &ctx, (const BYTE *)string->Buffer, string->Length );
+    MD4Final( &ctx );
+    memcpy( hash, ctx.digest, 0x10 );
+
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction010  [ADVAPI32.@]
+ * SystemFunction011  [ADVAPI32.@]
+ *
+ * MD4 hashes 16 bytes of data
+ *
+ * PARAMS
+ *   unknown []  seems to have no effect on the output
+ *   data    [I] pointer to data to hash (16 bytes)
+ *   output  [O] the md4 hash of the data (16 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL
+ *
+ */
+NTSTATUS WINAPI SystemFunction010(LPVOID unknown, const BYTE *data, LPBYTE hash)
+{
+    MD4_CTX ctx;
+
+    MD4Init( &ctx );
+    MD4Update( &ctx, data, 0x10 );
+    MD4Final( &ctx );
+    memcpy( hash, ctx.digest, 0x10 );
+
+    return STATUS_SUCCESS;
+}
Index: dll/win32/advapi32/crypt/crypt.h
===================================================================
--- dll/win32/advapi32/crypt/crypt.h	(Revision 31672)
+++ dll/win32/advapi32/crypt/crypt.h	(Arbeitskopie)
@@ -88,7 +88,7 @@
 extern unsigned char *CRYPT_DESunhash( unsigned char *dst, const unsigned char *key,
                                        const unsigned char *src );
 
-extern VOID byteReverse(unsigned char *buf, unsigned longs);
+extern void byteReverse(unsigned char *buf, unsigned longs);
 
 struct ustring {
     DWORD Length;
Index: dll/win32/advapi32/crypt/crypt_md5.c
===================================================================
--- dll/win32/advapi32/crypt/crypt_md5.c	(Revision 31672)
+++ dll/win32/advapi32/crypt/crypt_md5.c	(Arbeitskopie)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 /*
@@ -45,108 +45,9 @@
     unsigned char digest[16];
 } MD5_CTX;
 
+static void MD5Transform( unsigned int buf[4], const unsigned int in[16] );
 
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1( x, y, z ) (x & y | ~x & z) */
-#define F1( x, y, z ) (z ^ (x & (y ^ z)))
-#define F2( x, y, z ) F1( z, x, y )
-#define F3( x, y, z ) (x ^ y ^ z)
-#define F4( x, y, z ) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP( f, w, x, y, z, data, s ) \
-        ( w += f( x, y, z ) + data,  w = w << s | w >> (32 - s),  w += x )
-
 /*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data.  MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(unsigned int buf[4], const unsigned int in[16])
-{
-    register unsigned int a, b, c, d;
-
-    a = buf[0];
-    b = buf[1];
-    c = buf[2];
-    d = buf[3];
-
-    MD5STEP( F1, a, b, c, d, in[0] + 0xd76aa478, 7 );
-    MD5STEP( F1, d, a, b, c, in[1] + 0xe8c7b756, 12 );
-    MD5STEP( F1, c, d, a, b, in[2] + 0x242070db, 17 );
-    MD5STEP( F1, b, c, d, a, in[3] + 0xc1bdceee, 22 );
-    MD5STEP( F1, a, b, c, d, in[4] + 0xf57c0faf, 7 );
-    MD5STEP( F1, d, a, b, c, in[5] + 0x4787c62a, 12 );
-    MD5STEP( F1, c, d, a, b, in[6] + 0xa8304613, 17 );
-    MD5STEP( F1, b, c, d, a, in[7] + 0xfd469501, 22 );
-    MD5STEP( F1, a, b, c, d, in[8] + 0x698098d8, 7 );
-    MD5STEP( F1, d, a, b, c, in[9] + 0x8b44f7af, 12 );
-    MD5STEP( F1, c, d, a, b, in[10] + 0xffff5bb1, 17 );
-    MD5STEP( F1, b, c, d, a, in[11] + 0x895cd7be, 22 );
-    MD5STEP( F1, a, b, c, d, in[12] + 0x6b901122, 7 );
-    MD5STEP( F1, d, a, b, c, in[13] + 0xfd987193, 12 );
-    MD5STEP( F1, c, d, a, b, in[14] + 0xa679438e, 17 );
-    MD5STEP( F1, b, c, d, a, in[15] + 0x49b40821, 22 );
-
-    MD5STEP( F2, a, b, c, d, in[1] + 0xf61e2562, 5 );
-    MD5STEP( F2, d, a, b, c, in[6] + 0xc040b340, 9 );
-    MD5STEP( F2, c, d, a, b, in[11] + 0x265e5a51, 14 );
-    MD5STEP( F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20 );
-    MD5STEP( F2, a, b, c, d, in[5] + 0xd62f105d, 5 );
-    MD5STEP( F2, d, a, b, c, in[10] + 0x02441453, 9 );
-    MD5STEP( F2, c, d, a, b, in[15] + 0xd8a1e681, 14 );
-    MD5STEP( F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20 );
-    MD5STEP( F2, a, b, c, d, in[9] + 0x21e1cde6, 5 );
-    MD5STEP( F2, d, a, b, c, in[14] + 0xc33707d6, 9 );
-    MD5STEP( F2, c, d, a, b, in[3] + 0xf4d50d87, 14 );
-    MD5STEP( F2, b, c, d, a, in[8] + 0x455a14ed, 20 );
-    MD5STEP( F2, a, b, c, d, in[13] + 0xa9e3e905, 5 );
-    MD5STEP( F2, d, a, b, c, in[2] + 0xfcefa3f8, 9 );
-    MD5STEP( F2, c, d, a, b, in[7] + 0x676f02d9, 14 );
-    MD5STEP( F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20 );
-
-    MD5STEP( F3, a, b, c, d, in[5] + 0xfffa3942, 4 );
-    MD5STEP( F3, d, a, b, c, in[8] + 0x8771f681, 11 );
-    MD5STEP( F3, c, d, a, b, in[11] + 0x6d9d6122, 16 );
-    MD5STEP( F3, b, c, d, a, in[14] + 0xfde5380c, 23 );
-    MD5STEP( F3, a, b, c, d, in[1] + 0xa4beea44, 4 );
-    MD5STEP( F3, d, a, b, c, in[4] + 0x4bdecfa9, 11 );
-    MD5STEP( F3, c, d, a, b, in[7] + 0xf6bb4b60, 16 );
-    MD5STEP( F3, b, c, d, a, in[10] + 0xbebfbc70, 23 );
-    MD5STEP( F3, a, b, c, d, in[13] + 0x289b7ec6, 4 );
-    MD5STEP( F3, d, a, b, c, in[0] + 0xeaa127fa, 11 );
-    MD5STEP( F3, c, d, a, b, in[3] + 0xd4ef3085, 16 );
-    MD5STEP( F3, b, c, d, a, in[6] + 0x04881d05, 23 );
-    MD5STEP( F3, a, b, c, d, in[9] + 0xd9d4d039, 4 );
-    MD5STEP( F3, d, a, b, c, in[12] + 0xe6db99e5, 11 );
-    MD5STEP( F3, c, d, a, b, in[15] + 0x1fa27cf8, 16 );
-    MD5STEP( F3, b, c, d, a, in[2] + 0xc4ac5665, 23 );
-
-    MD5STEP( F4, a, b, c, d, in[0] + 0xf4292244, 6 );
-    MD5STEP( F4, d, a, b, c, in[7] + 0x432aff97, 10 );
-    MD5STEP( F4, c, d, a, b, in[14] + 0xab9423a7, 15 );
-    MD5STEP( F4, b, c, d, a, in[5] + 0xfc93a039, 21 );
-    MD5STEP( F4, a, b, c, d, in[12] + 0x655b59c3, 6 );
-    MD5STEP( F4, d, a, b, c, in[3] + 0x8f0ccc92, 10 );
-    MD5STEP( F4, c, d, a, b, in[10] + 0xffeff47d, 15 );
-    MD5STEP( F4, b, c, d, a, in[1] + 0x85845dd1, 21 );
-    MD5STEP( F4, a, b, c, d, in[8] + 0x6fa87e4f, 6 );
-    MD5STEP( F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10 );
-    MD5STEP( F4, c, d, a, b, in[6] + 0xa3014314, 15 );
-    MD5STEP( F4, b, c, d, a, in[13] + 0x4e0811a1, 21 );
-    MD5STEP( F4, a, b, c, d, in[4] + 0xf7537e82, 6 );
-    MD5STEP( F4, d, a, b, c, in[11] + 0xbd3af235, 10 );
-    MD5STEP( F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15 );
-    MD5STEP( F4, b, c, d, a, in[9] + 0xeb86d391, 21 );
-
-    buf[0] += a;
-    buf[1] += b;
-    buf[2] += c;
-    buf[3] += d;
-}
-
-/*
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
  */
@@ -261,3 +162,103 @@
     byteReverse((unsigned char *)ctx->buf, 4);
     memcpy(ctx->digest, ctx->buf, 16);
 }
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1( x, y, z ) (x & y | ~x & z) */
+#define F1( x, y, z ) (z ^ (x & (y ^ z)))
+#define F2( x, y, z ) F1( z, x, y )
+#define F3( x, y, z ) (x ^ y ^ z)
+#define F4( x, y, z ) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP( f, w, x, y, z, data, s ) \
+        ( w += f( x, y, z ) + data,  w = w << s | w >> (32 - s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(unsigned int buf[4], const unsigned int in[16])
+{
+    register unsigned int a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP( F1, a, b, c, d, in[0] + 0xd76aa478, 7 );
+    MD5STEP( F1, d, a, b, c, in[1] + 0xe8c7b756, 12 );
+    MD5STEP( F1, c, d, a, b, in[2] + 0x242070db, 17 );
+    MD5STEP( F1, b, c, d, a, in[3] + 0xc1bdceee, 22 );
+    MD5STEP( F1, a, b, c, d, in[4] + 0xf57c0faf, 7 );
+    MD5STEP( F1, d, a, b, c, in[5] + 0x4787c62a, 12 );
+    MD5STEP( F1, c, d, a, b, in[6] + 0xa8304613, 17 );
+    MD5STEP( F1, b, c, d, a, in[7] + 0xfd469501, 22 );
+    MD5STEP( F1, a, b, c, d, in[8] + 0x698098d8, 7 );
+    MD5STEP( F1, d, a, b, c, in[9] + 0x8b44f7af, 12 );
+    MD5STEP( F1, c, d, a, b, in[10] + 0xffff5bb1, 17 );
+    MD5STEP( F1, b, c, d, a, in[11] + 0x895cd7be, 22 );
+    MD5STEP( F1, a, b, c, d, in[12] + 0x6b901122, 7 );
+    MD5STEP( F1, d, a, b, c, in[13] + 0xfd987193, 12 );
+    MD5STEP( F1, c, d, a, b, in[14] + 0xa679438e, 17 );
+    MD5STEP( F1, b, c, d, a, in[15] + 0x49b40821, 22 );
+
+    MD5STEP( F2, a, b, c, d, in[1] + 0xf61e2562, 5 );
+    MD5STEP( F2, d, a, b, c, in[6] + 0xc040b340, 9 );
+    MD5STEP( F2, c, d, a, b, in[11] + 0x265e5a51, 14 );
+    MD5STEP( F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20 );
+    MD5STEP( F2, a, b, c, d, in[5] + 0xd62f105d, 5 );
+    MD5STEP( F2, d, a, b, c, in[10] + 0x02441453, 9 );
+    MD5STEP( F2, c, d, a, b, in[15] + 0xd8a1e681, 14 );
+    MD5STEP( F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20 );
+    MD5STEP( F2, a, b, c, d, in[9] + 0x21e1cde6, 5 );
+    MD5STEP( F2, d, a, b, c, in[14] + 0xc33707d6, 9 );
+    MD5STEP( F2, c, d, a, b, in[3] + 0xf4d50d87, 14 );
+    MD5STEP( F2, b, c, d, a, in[8] + 0x455a14ed, 20 );
+    MD5STEP( F2, a, b, c, d, in[13] + 0xa9e3e905, 5 );
+    MD5STEP( F2, d, a, b, c, in[2] + 0xfcefa3f8, 9 );
+    MD5STEP( F2, c, d, a, b, in[7] + 0x676f02d9, 14 );
+    MD5STEP( F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20 );
+
+    MD5STEP( F3, a, b, c, d, in[5] + 0xfffa3942, 4 );
+    MD5STEP( F3, d, a, b, c, in[8] + 0x8771f681, 11 );
+    MD5STEP( F3, c, d, a, b, in[11] + 0x6d9d6122, 16 );
+    MD5STEP( F3, b, c, d, a, in[14] + 0xfde5380c, 23 );
+    MD5STEP( F3, a, b, c, d, in[1] + 0xa4beea44, 4 );
+    MD5STEP( F3, d, a, b, c, in[4] + 0x4bdecfa9, 11 );
+    MD5STEP( F3, c, d, a, b, in[7] + 0xf6bb4b60, 16 );
+    MD5STEP( F3, b, c, d, a, in[10] + 0xbebfbc70, 23 );
+    MD5STEP( F3, a, b, c, d, in[13] + 0x289b7ec6, 4 );
+    MD5STEP( F3, d, a, b, c, in[0] + 0xeaa127fa, 11 );
+    MD5STEP( F3, c, d, a, b, in[3] + 0xd4ef3085, 16 );
+    MD5STEP( F3, b, c, d, a, in[6] + 0x04881d05, 23 );
+    MD5STEP( F3, a, b, c, d, in[9] + 0xd9d4d039, 4 );
+    MD5STEP( F3, d, a, b, c, in[12] + 0xe6db99e5, 11 );
+    MD5STEP( F3, c, d, a, b, in[15] + 0x1fa27cf8, 16 );
+    MD5STEP( F3, b, c, d, a, in[2] + 0xc4ac5665, 23 );
+
+    MD5STEP( F4, a, b, c, d, in[0] + 0xf4292244, 6 );
+    MD5STEP( F4, d, a, b, c, in[7] + 0x432aff97, 10 );
+    MD5STEP( F4, c, d, a, b, in[14] + 0xab9423a7, 15 );
+    MD5STEP( F4, b, c, d, a, in[5] + 0xfc93a039, 21 );
+    MD5STEP( F4, a, b, c, d, in[12] + 0x655b59c3, 6 );
+    MD5STEP( F4, d, a, b, c, in[3] + 0x8f0ccc92, 10 );
+    MD5STEP( F4, c, d, a, b, in[10] + 0xffeff47d, 15 );
+    MD5STEP( F4, b, c, d, a, in[1] + 0x85845dd1, 21 );
+    MD5STEP( F4, a, b, c, d, in[8] + 0x6fa87e4f, 6 );
+    MD5STEP( F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10 );
+    MD5STEP( F4, c, d, a, b, in[6] + 0xa3014314, 15 );
+    MD5STEP( F4, b, c, d, a, in[13] + 0x4e0811a1, 21 );
+    MD5STEP( F4, a, b, c, d, in[4] + 0xf7537e82, 6 );
+    MD5STEP( F4, d, a, b, c, in[11] + 0xbd3af235, 10 );
+    MD5STEP( F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15 );
+    MD5STEP( F4, b, c, d, a, in[9] + 0xeb86d391, 21 );
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
Index: dll/win32/advapi32/crypt/crypt_des.c
===================================================================
--- dll/win32/advapi32/crypt/crypt_des.c	(Revision 31672)
+++ dll/win32/advapi32/crypt/crypt_des.c	(Arbeitskopie)
@@ -1,5 +1,6 @@
 /*
  *  Copyright 2004 Hans Leidekker
+ *  Copyright 2006 Mike McCormack
  *
  *  Based on DES.c from libcifs
  *
@@ -17,7 +18,7 @@
  *
  *  You should have received a copy of the GNU Lesser General Public
  *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include <advapi32.h>
@@ -161,7 +162,7 @@
     }
 }
 
-static void KeyShift(unsigned char *key, const int numbits)
+static void KeyShiftLeft( unsigned char *key, const int numbits )
 {
     int i;
     unsigned char keep = key[0];
@@ -190,6 +191,35 @@
     }
 }
 
+static void KeyShiftRight( unsigned char *key, const int numbits )
+{
+    int i;
+    unsigned char keep = key[6];
+
+    for (i = 0; i < numbits; i++)
+    {
+        int j;
+
+        for (j = 6; j >= 0; j--)
+        {
+            if (j!=6 && (key[j] & 0x01))
+                key[j+1] |=  0x80;
+            key[j] >>= 1;
+        }
+
+        if (GETBIT( key, 28 ))
+        {
+            CLRBIT( key, 28 );
+            SETBIT( key, 0 );
+        }
+
+        if (keep & 0x01)
+            SETBIT( key, 28 );
+
+        keep >>= 1;
+    }
+}
+
 static void sbox(unsigned char *dst, const unsigned char *src)
 {
     int i;
@@ -249,7 +279,6 @@
     return dst;
 }
 
-
 unsigned char *CRYPT_DEShash(unsigned char *dst, const unsigned char *key, const unsigned char *src)
 {
     int i;
@@ -268,7 +297,7 @@
         unsigned char  Rn[4];
         unsigned char  SubK[6];
 
-        KeyShift(K, KeyRotation[i]);
+        KeyShiftLeft( K, KeyRotation[i] );
         Permute(SubK, K, KeyCompression, 6);
 
         Permute(Rexp, R, DataExpansion, 6);
@@ -289,3 +318,44 @@
 
     return dst;
 }
+
+unsigned char *CRYPT_DESunhash( unsigned char *dst, const unsigned char *key, const unsigned char *src )
+{
+    int i;
+    unsigned char K[7];
+    unsigned char D[8];
+
+    Permute( K, key, KeyPermuteMap, 7 );
+    Permute( D, src, InitialPermuteMap, 8 );
+
+    for (i = 0; i < 16; i++)
+    {
+        int j;
+        unsigned char *L = D;
+        unsigned char *R = &(D[4]);
+        unsigned char  Rexp[6];
+        unsigned char  Rn[4];
+        unsigned char  SubK[6];
+
+        Permute( SubK, K, KeyCompression, 6 );
+
+        Permute( Rexp, R, DataExpansion, 6 );
+        xor( Rexp, Rexp, SubK, 6 );
+
+        sbox( Rn, Rexp );
+        Permute( Rexp, Rn, PBox, 4 );
+        xor( Rn, L, Rexp, 4 );
+
+        for (j = 0; j < 4; j++)
+        {
+            L[j] = R[j];
+            R[j] = Rn[j];
+        }
+
+        KeyShiftRight( K, KeyRotation[15 - i] );
+    }
+
+    Permute( dst, D, FinalPermuteMap, 8 );
+
+    return dst;
+}
Index: dll/win32/advapi32/crypt/crypt_sha.c
===================================================================
--- dll/win32/advapi32/crypt/crypt_sha.c	(Revision 31672)
+++ dll/win32/advapi32/crypt/crypt_sha.c	(Arbeitskopie)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include <advapi32.h>
@@ -50,8 +50,7 @@
 #define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
 
 /* Hash a single 512-bit block. This is the core of the algorithm. */
-static VOID
-SHA1Transform(ULONG State[5], UCHAR Buffer[64])
+static void SHA1Transform(ULONG State[5], UCHAR Buffer[64])
 {
    ULONG a, b, c, d, e;
    ULONG *Block;
@@ -103,6 +102,12 @@
  * A_SHAInit [ADVAPI32.@]
  *
  * Initialize a SHA context structure.
+ *
+ * PARAMS
+ *  Context [O] SHA context
+ *
+ * RETURNS
+ *  Nothing
  */
 VOID WINAPI
 A_SHAInit(PSHA_CTX Context)
@@ -121,9 +126,17 @@
  * A_SHAUpdate [ADVAPI32.@]
  *
  * Update a SHA context with a hashed data from supplied buffer.
+ *
+ * PARAMS
+ *  Context    [O] SHA context
+ *  Buffer     [I] hashed data
+ *  BufferSize [I] hashed data size
+ *
+ * RETURNS
+ *  Nothing
  */
 VOID WINAPI
-A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize)
+A_SHAUpdate(PSHA_CTX Context, const unsigned char *Buffer, UINT BufferSize)
 {
    ULONG BufferContentSize;
 
@@ -157,12 +170,19 @@
  * A_SHAFinal [ADVAPI32.@]
  *
  * Finalize SHA context and return the resulting hash.
+ *
+ * PARAMS
+ *  Context [I/O] SHA context
+ *  Result  [O] resulting hash
+ *
+ * RETURNS
+ *  Nothing
  */
 VOID WINAPI
 A_SHAFinal(PSHA_CTX Context, PULONG Result)
 {
    INT Pad, Index;
-   CHAR Buffer[72];
+   UCHAR Buffer[72];
    ULONG *Count;
    ULONG BufferContentSize, LengthHi, LengthLo;
 
Index: dll/win32/advapi32/crypt/crypt_lmhash.c
===================================================================
--- dll/win32/advapi32/crypt/crypt_lmhash.c	(Revision 31672)
+++ dll/win32/advapi32/crypt/crypt_lmhash.c	(Arbeitskopie)
@@ -17,33 +17,383 @@
  *
  *  You should have received a copy of the GNU Lesser General Public
  *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <stdarg.h>
 #include <advapi32.h>
 #include "crypt.h"
 
-
 static const unsigned char CRYPT_LMhash_Magic[8] =
     { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
 
-static void CRYPT_LMhash(LPSTR dst, LPCSTR pwd, const int len)
+static void CRYPT_LMhash( unsigned char *dst, const unsigned char *pwd, const int len )
 {
     int i, max = 14;
-    CHAR tmp_pwd[14] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+    unsigned char tmp_pwd[14] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
 
     max = len > max ? max : len;
 
     for (i = 0; i < max; i++)
         tmp_pwd[i] = pwd[i];
 
-    CRYPT_DEShash((PUCHAR)dst, (PUCHAR)tmp_pwd, CRYPT_LMhash_Magic);
-    CRYPT_DEShash((PUCHAR)&dst[8], (PUCHAR)&tmp_pwd[7], CRYPT_LMhash_Magic);
+    CRYPT_DEShash( dst, tmp_pwd, CRYPT_LMhash_Magic);
+    CRYPT_DEShash( &dst[8], &tmp_pwd[7], CRYPT_LMhash_Magic);
 }
 
 NTSTATUS WINAPI SystemFunction006(LPCSTR password, LPSTR hash)
 {
-    CRYPT_LMhash(hash, password, strlen(password));
+    CRYPT_LMhash( (unsigned char*)hash, (const unsigned char*)password, strlen(password) );
 
     return STATUS_SUCCESS;
 }
+
+/******************************************************************************
+ * SystemFunction008  [ADVAPI32.@]
+ *
+ * Creates a LM response from a challenge and a password hash
+ *
+ * PARAMS
+ *   challenge  [I] Challenge from authentication server
+ *   hash       [I] NTLM hash (from SystemFunction006)
+ *   response   [O] response to send back to the server
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL
+ *
+ * NOTES
+ *  see http://davenport.sourceforge.net/ntlm.html#theLmResponse
+ *
+ */
+NTSTATUS WINAPI SystemFunction008(const BYTE *challenge, const BYTE *hash, LPBYTE response)
+{
+    BYTE key[7*3];
+
+    if (!challenge || !response)
+        return STATUS_UNSUCCESSFUL;
+
+    memset(key, 0, sizeof key);
+    memcpy(key, hash, 0x10);
+
+    CRYPT_DEShash(response, key, challenge);
+    CRYPT_DEShash(response+8, key+7, challenge);
+    CRYPT_DEShash(response+16, key+14, challenge);
+
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction009  [ADVAPI32.@]
+ *
+ * Seems to do the same as SystemFunction008 ...
+ */
+NTSTATUS WINAPI SystemFunction009(const BYTE *challenge, const BYTE *hash, LPBYTE response)
+{
+    return SystemFunction008(challenge, hash, response);
+}
+
+/******************************************************************************
+ * SystemFunction001  [ADVAPI32.@]
+ *
+ * Encrypts a single block of data using DES
+ *
+ * PARAMS
+ *   data    [I] data to encrypt    (8 bytes)
+ *   key     [I] key data           (7 bytes)
+ *   output  [O] the encrypted data (8 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL
+ *
+ */
+NTSTATUS WINAPI SystemFunction001(const BYTE *data, const BYTE *key, LPBYTE output)
+{
+    if (!data || !output)
+        return STATUS_UNSUCCESSFUL;
+    CRYPT_DEShash(output, key, data);
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction002  [ADVAPI32.@]
+ *
+ * Decrypts a single block of data using DES
+ *
+ * PARAMS
+ *   data    [I] data to decrypt    (8 bytes)
+ *   key     [I] key data           (7 bytes)
+ *   output  [O] the decrypted data (8 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL
+ *
+ */
+NTSTATUS WINAPI SystemFunction002(const BYTE *data, const BYTE *key, LPBYTE output)
+{
+    if (!data || !output)
+        return STATUS_UNSUCCESSFUL;
+    CRYPT_DESunhash(output, key, data);
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction003  [ADVAPI32.@]
+ *
+ * Hashes a key using DES and a fixed datablock
+ *
+ * PARAMS
+ *   key     [I] key data    (7 bytes)
+ *   output  [O] hashed key  (8 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL
+ *
+ */
+NTSTATUS WINAPI SystemFunction003(const BYTE *key, LPBYTE output)
+{
+    if (!output)
+        return STATUS_UNSUCCESSFUL;
+    CRYPT_DEShash(output, key, CRYPT_LMhash_Magic);
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction004  [ADVAPI32.@]
+ *
+ * Encrypts a block of data with DES in ECB mode, preserving the length
+ *
+ * PARAMS
+ *   data    [I] data to encrypt
+ *   key     [I] key data (up to 7 bytes)
+ *   output  [O] buffer to receive encrypted data
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_BUFFER_TOO_SMALL     if the output buffer is too small
+ *  Failure: STATUS_INVALID_PARAMETER_2  if the key is zero length
+ *
+ * NOTES
+ *  Encrypt buffer size should be input size rounded up to 8 bytes
+ *   plus an extra 8 bytes.
+ */
+NTSTATUS WINAPI SystemFunction004(const struct ustring *in,
+                                  const struct ustring *key,
+                                  struct ustring *out)
+{
+    union {
+         unsigned char uc[8];
+         unsigned int  ui[2];
+    } data;
+    unsigned char deskey[7];
+    unsigned int crypt_len, ofs;
+
+    if (key->Length<=0)
+        return STATUS_INVALID_PARAMETER_2;
+
+    crypt_len = ((in->Length+7)&~7);
+    if (out->MaximumLength < (crypt_len+8))
+        return STATUS_BUFFER_TOO_SMALL;
+
+    data.ui[0] = in->Length;
+    data.ui[1] = 1;
+
+    if (key->Length<sizeof deskey)
+    {
+        memset(deskey, 0, sizeof deskey);
+        memcpy(deskey, key->Buffer, key->Length);
+    }
+    else
+        memcpy(deskey, key->Buffer, sizeof deskey);
+
+    CRYPT_DEShash(out->Buffer, deskey, data.uc);
+
+    for(ofs=0; ofs<(crypt_len-8); ofs+=8)
+        CRYPT_DEShash(out->Buffer+8+ofs, deskey, in->Buffer+ofs);
+
+    memset(data.uc, 0, sizeof data.uc);
+    memcpy(data.uc, in->Buffer+ofs, in->Length +8-crypt_len);
+    CRYPT_DEShash(out->Buffer+8+ofs, deskey, data.uc);
+
+    out->Length = crypt_len+8;
+
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction005  [ADVAPI32.@]
+ *
+ * Decrypts a block of data with DES in ECB mode
+ *
+ * PARAMS
+ *   data    [I] data to decrypt
+ *   key     [I] key data (up to 7 bytes)
+ *   output  [O] buffer to receive decrypted data
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_BUFFER_TOO_SMALL     if the output buffer is too small
+ *  Failure: STATUS_INVALID_PARAMETER_2  if the key is zero length
+ *
+ */
+NTSTATUS WINAPI SystemFunction005(const struct ustring *in,
+                                  const struct ustring *key,
+                                  struct ustring *out)
+{
+    union {
+         unsigned char uc[8];
+         unsigned int  ui[2];
+    } data;
+    unsigned char deskey[7];
+    unsigned int ofs, crypt_len;
+
+    if (key->Length<=0)
+        return STATUS_INVALID_PARAMETER_2;
+
+    if (key->Length<sizeof deskey)
+    {
+        memset(deskey, 0, sizeof deskey);
+        memcpy(deskey, key->Buffer, key->Length);
+    }
+    else
+        memcpy(deskey, key->Buffer, sizeof deskey);
+
+    CRYPT_DESunhash(data.uc, deskey, in->Buffer);
+
+    if (data.ui[1] != 1)
+        return STATUS_UNKNOWN_REVISION;
+
+    crypt_len = data.ui[0];
+    if (crypt_len > out->MaximumLength)
+        return STATUS_BUFFER_TOO_SMALL;
+
+    for (ofs=0; (ofs+8)<crypt_len; ofs+=8)
+        CRYPT_DESunhash(out->Buffer+ofs, deskey, in->Buffer+ofs+8);
+
+    if (ofs<crypt_len)
+    {
+        CRYPT_DESunhash(data.uc, deskey, in->Buffer+ofs+8);
+        memcpy(out->Buffer+ofs, data.uc, crypt_len-ofs);
+    }
+
+    out->Length = crypt_len;
+
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction012  [ADVAPI32.@]
+ * SystemFunction014  [ADVAPI32.@]
+ * SystemFunction016  [ADVAPI32.@]
+ * SystemFunction018  [ADVAPI32.@]
+ * SystemFunction020  [ADVAPI32.@]
+ * SystemFunction022  [ADVAPI32.@]
+ *
+ * Encrypts two DES blocks with two keys
+ *
+ * PARAMS
+ *   data    [I] data to encrypt (16 bytes)
+ *   key     [I] key data (two lots of 7 bytes)
+ *   output  [O] buffer to receive encrypted data (16 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL  if the input or output buffer is NULL
+ */
+NTSTATUS WINAPI SystemFunction012(const BYTE *in, const BYTE *key, LPBYTE out)
+{
+    if (!in || !out)
+        return STATUS_UNSUCCESSFUL;
+
+    CRYPT_DEShash(out, key, in);
+    CRYPT_DEShash(out+8, key+7, in+8);
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction013  [ADVAPI32.@]
+ * SystemFunction015  [ADVAPI32.@]
+ * SystemFunction017  [ADVAPI32.@]
+ * SystemFunction019  [ADVAPI32.@]
+ * SystemFunction021  [ADVAPI32.@]
+ * SystemFunction023  [ADVAPI32.@]
+ *
+ * Decrypts two DES blocks with two keys
+ *
+ * PARAMS
+ *   data    [I] data to decrypt (16 bytes)
+ *   key     [I] key data (two lots of 7 bytes)
+ *   output  [O] buffer to receive decrypted data (16 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: STATUS_UNSUCCESSFUL  if the input or output buffer is NULL
+ */
+NTSTATUS WINAPI SystemFunction013(const BYTE *in, const BYTE *key, LPBYTE out)
+{
+    if (!in || !out)
+        return STATUS_UNSUCCESSFUL;
+
+    CRYPT_DESunhash(out, key, in);
+    CRYPT_DESunhash(out+8, key+7, in+8);
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction024  [ADVAPI32.@]
+ *
+ * Encrypts two DES blocks with a 32 bit key...
+ *
+ * PARAMS
+ *   data    [I] data to encrypt (16 bytes)
+ *   key     [I] key data (4 bytes)
+ *   output  [O] buffer to receive encrypted data (16 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ */
+NTSTATUS WINAPI SystemFunction024(const BYTE *in, const BYTE *key, LPBYTE out)
+{
+    BYTE deskey[0x10];
+
+    memcpy(deskey, key, 4);
+    memcpy(deskey+4, key, 4);
+    memcpy(deskey+8, key, 4);
+    memcpy(deskey+12, key, 4);
+
+    CRYPT_DEShash(out, deskey, in);
+    CRYPT_DEShash(out+8, deskey+7, in+8);
+
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * SystemFunction025  [ADVAPI32.@]
+ *
+ * Decrypts two DES blocks with a 32 bit key...
+ *
+ * PARAMS
+ *   data    [I] data to encrypt (16 bytes)
+ *   key     [I] key data (4 bytes)
+ *   output  [O] buffer to receive encrypted data (16 bytes)
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ */
+NTSTATUS WINAPI SystemFunction025(const BYTE *in, const BYTE *key, LPBYTE out)
+{
+    BYTE deskey[0x10];
+
+    memcpy(deskey, key, 4);
+    memcpy(deskey+4, key, 4);
+    memcpy(deskey+8, key, 4);
+    memcpy(deskey+12, key, 4);
+
+    CRYPT_DESunhash(out, deskey, in);
+    CRYPT_DESunhash(out+8, deskey+7, in+8);
+
+    return STATUS_SUCCESS;
+}
Index: dll/win32/advapi32/advapi32.rbuild
===================================================================
--- dll/win32/advapi32/advapi32.rbuild	(Revision 31672)
+++ dll/win32/advapi32/advapi32.rbuild	(Arbeitskopie)
@@ -21,6 +21,7 @@
 	<pch>advapi32.h</pch>
 	<directory name="crypt">
 			<file>crypt.c</file>
+			<file>crypt_arc4.c</file>
 			<file>crypt_des.c</file>
 			<file>crypt_lmhash.c</file>
 			<file>crypt_md4.c</file>
Index: dll/win32/advapi32/misc/sysfunc.c
===================================================================
--- dll/win32/advapi32/misc/sysfunc.c	(Revision 31672)
+++ dll/win32/advapi32/misc/sysfunc.c	(Arbeitskopie)
@@ -12,129 +12,13 @@
 
 #include <advapi32.h>
 
-/**********************************************************************
- *	SystemFunction001
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction001(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 1;
-}
 
-
 /**********************************************************************
  *
  * @unimplemented
  */
 INT
 STDCALL
-SystemFunction002(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 2;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction003(INT a, INT b)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 3;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction004(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 4;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction005(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 5;
-}
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction007(INT a, INT b)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 7;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction008(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 8;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction009(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 9;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction010(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 10;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
 SystemFunction011(INT a, INT b, INT c)
 {
 	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -148,32 +32,6 @@
  */
 INT
 STDCALL
-SystemFunction012(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 12;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction013(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 13;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
 SystemFunction014(INT a, INT b, INT c)
 {
 	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -304,32 +162,6 @@
  */
 INT
 STDCALL
-SystemFunction024(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 24;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction025(INT a, INT b, INT c)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 25;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
 SystemFunction026(INT a, INT b, INT c)
 {
 	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -382,19 +214,6 @@
  */
 INT
 STDCALL
-SystemFunction030(INT a, INT b)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 30;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
 SystemFunction031(INT a, INT b)
 {
 	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -408,19 +227,6 @@
  */
 INT
 STDCALL
-SystemFunction032(INT a, INT b)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 32;
-}
-
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
 SystemFunction033(INT a, INT b)
 {
 	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -439,7 +245,6 @@
 	return 34;
 }
 
-
 /**********************************************************************
  *
  * @unimplemented
@@ -452,16 +257,4 @@
 	return 35;
 }
 
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction036(INT a, INT b)
-{
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 36;
-}
-
 /* EOF */
Index: dll/win32/kernel32/misc/lcformat.c
===================================================================
--- dll/win32/kernel32/misc/lcformat.c	(Revision 31672)
+++ dll/win32/kernel32/misc/lcformat.c	(Arbeitskopie)
@@ -754,7 +754,7 @@
   if (lpStr)
   {
     if (szOut[0])
-      WideCharToMultiByte(cp, 0, szOut, -1, lpStr, cchOut, 0, 0);
+      WideCharToMultiByte(cp, 0, szOut, iRet ? -1 : cchOut, lpStr, cchOut, 0, 0);
     else if (cchOut && iRet)
       *lpStr = '\0';
   }
