port crypt and trustee support from Wine. Patch by Steven Edwards.
authorThomas Bluemel <thomas@reactsoft.com>
Sat, 11 Dec 2004 00:21:33 +0000 (00:21 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Sat, 11 Dec 2004 00:21:33 +0000 (00:21 +0000)
svn path=/trunk/; revision=12007

14 files changed:
reactos/lib/advapi32/advapi32.def
reactos/lib/advapi32/advapi32.h
reactos/lib/advapi32/crypt/.cvsignore [new file with mode: 0644]
reactos/lib/advapi32/crypt/crypt.c [new file with mode: 0644]
reactos/lib/advapi32/crypt/crypt.h [new file with mode: 0644]
reactos/lib/advapi32/crypt/crypt_des.c [new file with mode: 0644]
reactos/lib/advapi32/crypt/crypt_lmhash.c [new file with mode: 0644]
reactos/lib/advapi32/crypt/crypt_md4.c [new file with mode: 0644]
reactos/lib/advapi32/crypt/crypt_md5.c [new file with mode: 0644]
reactos/lib/advapi32/crypt/crypt_sha.c [new file with mode: 0644]
reactos/lib/advapi32/makefile
reactos/lib/advapi32/misc/sysfunc.c
reactos/lib/advapi32/sec/trustee.c [new file with mode: 0644]
reactos/lib/advapi32/token/token.c

index 3580124..7d14858 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: advapi32.def,v 1.25 2004/11/21 20:14:36 gdalsnes Exp $
+; $Id: advapi32.def,v 1.26 2004/12/11 00:21:33 weiden Exp $
 ;
 ; advapi32.def
 ;
@@ -6,6 +6,9 @@
 ;
 LIBRARY advapi32.dll
 EXPORTS
+A_SHAFinal@8
+A_SHAInit@4
+A_SHAUpdate@12
 AbortSystemShutdownA@4
 AbortSystemShutdownW@4
 AccessCheck@32
@@ -36,10 +39,10 @@ BackupEventLogW@8
 ;BuildImpersonateTrusteeW@8
 ;BuildSecurityDescriptorA@36
 ;BuildSecurityDescriptorW@36
-;BuildTrusteeWithNameA@8
-;BuildTrusteeWithNameW@8
-;BuildTrusteeWithSidA@8
-;BuildTrusteeWithSidW@8
+BuildTrusteeWithNameA@8
+BuildTrusteeWithNameW@8
+BuildTrusteeWithSidA@8
+BuildTrusteeWithSidW@8
 ChangeServiceConfigA@44
 ChangeServiceConfigW@44
 ClearEventLogA@8
@@ -55,34 +58,34 @@ CreateProcessAsUserA@44
 CreateProcessAsUserW@44
 CreateServiceA@52
 CreateServiceW@52
-;CryptAcquireContextA@20
-;CryptAcquireContextW@20
-;CryptContextAddRef@12
-;CryptCreateHash@20
-;CryptDecrypt@24
-;CryptDeriveKey@20
-;CryptDestroyHash@4
-;CryptDestroyKey@4
-;CryptEncrypt@28
-;CryptExportKey@24
-;CryptGenKey@16
-;CryptGenRandom@12
-;CryptGetHashParam@20
-;CryptGetKeyParam@20
-;CryptGetProvParam@20
-;CryptGetUserKey@12
-;CryptHashData@16
-;CryptHashSessionKey@12
-;CryptImportKey@24
-;CryptReleaseContext@8
-;CryptSetHashParam@16
-;CryptSetKeyParam@16
-;CryptSetProvParam@16
-;CryptSetProviderA@8
-;CryptSetProviderW@8
-;CryptSignHashA@24
+CryptAcquireContextA@20
+CryptAcquireContextW@20
+CryptContextAddRef@12
+CryptCreateHash@20
+CryptDecrypt@24
+CryptDeriveKey@20
+CryptDestroyHash@4
+CryptDestroyKey@4
+CryptEncrypt@28
+CryptExportKey@24
+CryptGenKey@16
+CryptGenRandom@12
+CryptGetHashParam@20
+CryptGetKeyParam@20
+CryptGetProvParam@20
+CryptGetUserKey@12
+CryptHashData@16
+CryptHashSessionKey@12
+CryptImportKey@24
+CryptReleaseContext@8
+CryptSetHashParam@16
+CryptSetKeyParam@16
+CryptSetProvParam@16
+CryptSetProviderA@8
+CryptSetProviderW@8
+CryptSignHashA@24
 ;CryptSignHashW@24
-;CryptVerifySignatureA@24
+CryptVerifySignatureA@24
 ;CryptVerifySignatureW@24
 DeleteAce@8
 DeleteService@4
@@ -259,6 +262,12 @@ LsaQueryInformationPolicy@12
 MakeAbsoluteSD@44
 MakeSelfRelativeSD@12
 MapGenericMask@8
+MD4Final@4
+MD4Init@4
+MD4Update@12
+MD5Final@4
+MD5Init@4
+MD5Update@12
 ;NTAccessMaskToProvAccessRights@12
 ;NotifyBootConfigStatus@4
 NotifyChangeEventLog@8
index 2078201..b1cd151 100644 (file)
@@ -8,3 +8,4 @@
 #include <windows.h>
 #include <sddl.h>
 #include <rosrtl/string.h>
+#include <accctrl.h>
diff --git a/reactos/lib/advapi32/crypt/.cvsignore b/reactos/lib/advapi32/crypt/.cvsignore
new file mode 100644 (file)
index 0000000..c6ebd86
--- /dev/null
@@ -0,0 +1,2 @@
+*.o
+.*.d
diff --git a/reactos/lib/advapi32/crypt/crypt.c b/reactos/lib/advapi32/crypt/crypt.c
new file mode 100644 (file)
index 0000000..28a639f
--- /dev/null
@@ -0,0 +1,1922 @@
+/*
+ * Copyright 1999 Ian Schmidt
+ * Copyright 2001 Travis Michielsen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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
+ */
+
+/***********************************************************************
+ *
+ *  TODO:
+ *  - Reference counting
+ *  - Thread-safing
+ *  - Signature checking
+ */
+#include "wine/config.h"
+#include "wine/port.h"
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "wine/unicode.h"
+#include "crypt.h"
+#include "winnls.h"
+#include "wincrypt.h"
+#include "windef.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "winbase.h"
+//#include "winuser.h"
+#include "wine/debug.h"
+
+typedef LONG (CALLBACK *PVECTORED_EXCEPTION_HANDLER)(
+    struct _EXCEPTION_POINTERS *ExceptionInfo
+    );
+
+#include "wine/winternl.h"
+#include "wine/ntstatus.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(crypt);
+
+HWND crypt_hWindow = 0;
+
+#define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
+
+#define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
+#define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
+
+static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName)
+{
+       PCSTR KEYSTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
+       PSTR keyname;
+
+       keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1);
+       if (keyname)
+       {
+               strcpy(keyname, KEYSTR);
+               strcpy(keyname + strlen(KEYSTR), pProvName);
+       } else
+               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+       return keyname;
+}
+
+static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
+{
+       PCSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
+       PCSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
+       PSTR keyname;
+       PSTR ptr;
+
+       keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1);
+       if (keyname)
+       {
+               user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
+               ptr = keyname + strlen(keyname);
+               *(--ptr) = (dwType % 10) + '0';
+               *(--ptr) = ((dwType / 10) % 10) + '0';
+               *(--ptr) = (dwType / 100) + '0';
+       } else
+               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+       return keyname;
+}
+
+/* CRYPT_UnicodeTOANSI
+ * wstr - unicode string
+ * 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.
+ * 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)
+{
+       int count;
+
+       if (!wstr)
+       {
+               *str = NULL;
+               return TRUE;
+       }
+       count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
+       count = count < strsize ? count : strsize;
+       if (strsize == -1)
+               *str = CRYPT_Alloc(count * sizeof(CHAR));
+       if (*str)
+       {
+               WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
+               return TRUE;
+       }
+       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+       return FALSE;
+}
+
+/* CRYPT_ANSITOUnicode
+ * str - ANSI string
+ * wstr - pointer to unicode string
+ * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
+ */
+static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
+{
+       int wcount;
+
+       if (!str)
+       {
+               *wstr = NULL;
+               return TRUE;
+       }
+       wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+       wcount = wcount < wstrsize/sizeof(WCHAR) ? wcount : wstrsize/sizeof(WCHAR);
+       if (wstrsize == -1)
+               *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
+       if (*wstr)
+       {
+               MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
+               return TRUE;
+       }
+       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+       return FALSE;
+}
+
+/* These next 2 functions are used by the VTableProvStruc structure */
+static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
+{
+       if (!lpszImage || !pData)
+       {
+               SetLastError(ERROR_INVALID_PARAMETER);
+               return FALSE;
+       }
+
+       FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
+
+       return TRUE;
+}
+
+static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
+{
+       if (!phWnd)
+               return FALSE;
+       *phWnd = crypt_hWindow;
+       return TRUE;
+}
+
+#define CRYPT_GetProvFunc(name) \
+       if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
+#define CRYPT_GetProvFuncOpt(name) \
+       provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
+PCRYPTPROV CRYPT_LoadProvider(PSTR pImage)
+{
+       PCRYPTPROV provider;
+       DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
+
+       if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
+       if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
+       if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
+       if ( !(provider->hModule = LoadLibraryA(pImage)) )
+       {
+               errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
+               FIXME("Failed to load dll %s\n", debugstr_a(pImage));
+               goto error;
+       }
+       provider->refcount = 1;
+
+       errorcode = NTE_PROVIDER_DLL_FAIL;
+       CRYPT_GetProvFunc(CPAcquireContext);
+       CRYPT_GetProvFunc(CPCreateHash);
+       CRYPT_GetProvFunc(CPDecrypt);
+       CRYPT_GetProvFunc(CPDeriveKey);
+       CRYPT_GetProvFunc(CPDestroyHash);
+       CRYPT_GetProvFunc(CPDestroyKey);
+       CRYPT_GetProvFuncOpt(CPDuplicateHash);
+       CRYPT_GetProvFuncOpt(CPDuplicateKey);
+       CRYPT_GetProvFunc(CPEncrypt);
+       CRYPT_GetProvFunc(CPExportKey);
+       CRYPT_GetProvFunc(CPGenKey);
+       CRYPT_GetProvFunc(CPGenRandom);
+       CRYPT_GetProvFunc(CPGetHashParam);
+       CRYPT_GetProvFunc(CPGetKeyParam);
+       CRYPT_GetProvFunc(CPGetProvParam);
+       CRYPT_GetProvFunc(CPGetUserKey);
+       CRYPT_GetProvFunc(CPHashData);
+       CRYPT_GetProvFunc(CPHashSessionKey);
+       CRYPT_GetProvFunc(CPImportKey);
+       CRYPT_GetProvFunc(CPReleaseContext);
+       CRYPT_GetProvFunc(CPSetHashParam);
+       CRYPT_GetProvFunc(CPSetKeyParam);
+       CRYPT_GetProvFunc(CPSetProvParam);
+       CRYPT_GetProvFunc(CPSignHash);
+       CRYPT_GetProvFunc(CPVerifySignature);
+
+       /* FIXME: Not sure what the pbContextInfo field is for.
+        *        Does it need memory allocation?
+         */
+       provider->pVTable->Version = 3;
+       provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
+       provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
+       provider->pVTable->dwProvType = 0;
+       provider->pVTable->pbContextInfo = NULL;
+       provider->pVTable->cbContextInfo = 0;
+       provider->pVTable->pszProvName = NULL;
+       return provider;
+
+error:
+       SetLastError(errorcode);
+       if (provider)
+       {
+               if (provider->hModule)
+                       FreeLibrary(provider->hModule);
+               CRYPT_Free(provider->pVTable);
+               CRYPT_Free(provider->pFuncs);
+               CRYPT_Free(provider);
+       }
+       return NULL;
+}
+#undef CRYPT_GetProvFunc
+#undef CRYPT_GetProvFuncOpt
+
+
+/******************************************************************************
+ * CryptAcquireContextA (ADVAPI32.@)
+ * Acquire a crypto provider context handle.
+ *
+ * PARAMS
+ * phProv: Pointer to HCRYPTPROV for the output.
+ * pszContainer: Key Container Name
+ * pszProvider: Cryptographic Service Provider Name
+ * dwProvType: Crypto provider type to get a handle.
+ * dwFlags: flags for the operation
+ *
+ * RETURNS TRUE on success, FALSE on failure.
+ */
+BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
+               LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
+{
+       PCRYPTPROV pProv = NULL;
+       HKEY key;
+       PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
+       BYTE* signature;
+       DWORD keytype, type, len;
+       ULONG r;
+
+       TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
+               pszProvider, dwProvType, dwFlags);
+
+       if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
+       {
+               SetLastError(NTE_BAD_PROV_TYPE);
+               return FALSE;
+       }
+       
+       if (!phProv)
+       {
+               SetLastError(ERROR_INVALID_PARAMETER);
+               return FALSE;
+       }
+
+       if (!pszProvider || !*pszProvider)
+       {
+               /* No CSP name specified so try the user default CSP first
+                * then try the machine default CSP
+                */
+               if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
+                       TRACE("No provider registered for crypto provider type %ld.\n", dwProvType);
+                       SetLastError(NTE_PROV_TYPE_NOT_DEF);
+                       return FALSE;
+               }
+               if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
+               {
+                       CRYPT_Free(keyname);
+                       if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
+                               TRACE("No type registered for crypto provider type %ld.\n", dwProvType);
+                               RegCloseKey(key);
+                               SetLastError(NTE_PROV_TYPE_NOT_DEF);
+                               goto error;
+                       }
+                       if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) {
+                               TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname));
+                               CRYPT_Free(keyname);
+                               RegCloseKey(key);
+                               SetLastError(NTE_PROV_TYPE_NOT_DEF);
+                               goto error;
+                       }
+               }
+               CRYPT_Free(keyname);
+               r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
+               if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
+               {
+                       TRACE("error %ld reading size of 'Name' from registry\n", r );
+                       RegCloseKey(key);
+                       SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+                       goto error;
+               }
+               if(!(provname = CRYPT_Alloc(len)))
+               {
+                       RegCloseKey(key);
+                       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                       goto error;
+               }
+               r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
+               if( r != ERROR_SUCCESS )
+               {
+                       TRACE("error %ld reading 'Name' from registry\n", r );
+                       RegCloseKey(key);
+                       SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+                       goto error;
+               }
+               RegCloseKey(key);
+       } else {
+               if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
+               {
+                       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                       goto error;
+               }
+               strcpy(provname, pszProvider);
+       }
+
+       keyname = CRYPT_GetProvKeyName(provname);
+       r = RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key);
+       CRYPT_Free(keyname);
+       if (r != ERROR_SUCCESS)
+       {
+               SetLastError(NTE_KEYSET_NOT_DEF);
+               goto error;
+       }
+       len = sizeof(DWORD);
+       r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
+       if (r != ERROR_SUCCESS)
+       {
+               SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+               goto error;
+       }
+       if (type != dwProvType)
+       {
+               TRACE("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
+               SetLastError(NTE_PROV_TYPE_NO_MATCH);
+               goto error;
+       }
+
+       r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
+       if ( r != ERROR_SUCCESS || keytype != REG_SZ)
+       {
+               TRACE("error %ld reading size of 'Image Path' from registry\n", r );
+               RegCloseKey(key);
+               SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+               goto error;
+       }
+       if (!(temp = CRYPT_Alloc(len)))
+       {
+               RegCloseKey(key);
+               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+               goto error;
+       }
+       r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
+       if( r != ERROR_SUCCESS )
+       {
+               TRACE("error %ld reading 'Image Path' from registry\n", r );
+               RegCloseKey(key);
+               SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+               goto error;
+       }
+
+       r = RegQueryValueExA(key, "Signature", NULL, &keytype, NULL, &len);
+       if ( r == ERROR_SUCCESS && keytype == REG_BINARY )
+       {
+               if (!(signature = CRYPT_Alloc(len)))
+               {
+                       RegCloseKey(key);
+                       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                       goto error;
+               }
+               r = RegQueryValueExA(key, "Signature", NULL, NULL, signature, &len);
+               if ( r != ERROR_SUCCESS )
+               {
+                       TRACE("error %ld reading 'Signature'\n", r );
+                       CRYPT_Free(signature);
+                       RegCloseKey(key);
+                       SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+                       goto error;
+               }
+       }
+       else
+       {
+               r = RegQueryValueExA(key, "SigInFile", NULL, &keytype, NULL, &len);
+               if (r != ERROR_SUCCESS)
+               {
+                       TRACE("error %ld reading size of 'SigInFile'\n", r );
+                       RegCloseKey(key);
+                       SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+                       goto error;
+               }
+               else
+               {
+                       /* FIXME: The presence of the SigInFile value indicates the
+                        * provider's signature is in its resources, so need to read it.
+                        * But since CRYPT_VerifyImage is stubbed, provide any old thing
+                        * for now.
+                        */
+                       if (!(signature = CRYPT_Alloc(1)))
+                       {
+                               RegCloseKey(key);
+                               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                               goto error;
+                       }
+               }
+       }
+       RegCloseKey(key);
+       len = ExpandEnvironmentStringsA(temp, NULL, 0);
+       if ( !(imagepath = CRYPT_Alloc(len)) )
+       {
+               CRYPT_Free(signature);
+               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+               goto error;
+       }
+       if (!ExpandEnvironmentStringsA(temp, imagepath, len))
+       {
+               CRYPT_Free(signature);
+               /* ExpandEnvironmentStrings will call SetLastError */
+               goto error;
+       }
+
+       if (!CRYPT_VerifyImage(imagepath, signature))
+       {
+               CRYPT_Free(signature);
+               SetLastError(NTE_SIGNATURE_FILE_BAD);
+               goto error;
+       }
+       pProv = CRYPT_LoadProvider(imagepath);
+       CRYPT_Free(signature);
+       if (!pProv) {
+               /* CRYPT_LoadProvider calls SetLastError */
+               goto error;
+       }
+       pProv->pVTable->dwProvType = dwProvType;
+       pProv->pVTable->pszProvName = provname;
+       if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
+       {
+               /* MSDN: When this flag is set, the value returned in phProv is undefined,
+                *       and thus, the CryptReleaseContext function need not be called afterwards.
+                *       Therefore, we must clean up everything now.
+                 */
+               if (dwFlags & CRYPT_DELETEKEYSET)
+               {
+                       FreeLibrary(pProv->hModule);
+                       CRYPT_Free(provname);
+                       CRYPT_Free(pProv->pFuncs);
+                       CRYPT_Free(pProv);
+               } else {
+                       *phProv = (HCRYPTPROV)pProv;
+               }
+               CRYPT_Free(temp);
+               CRYPT_Free(imagepath);
+               return TRUE;
+       }
+       /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
+error:
+       if (pProv)
+       {
+               if (pProv->hModule)
+                       FreeLibrary(pProv->hModule);
+               if (pProv->pVTable)
+                       CRYPT_Free(pProv->pVTable);
+               if (pProv->pFuncs)
+                       CRYPT_Free(pProv->pFuncs);
+               CRYPT_Free(pProv);
+       }
+       if (provname)
+               CRYPT_Free(provname);
+       if (temp)
+               CRYPT_Free(temp);
+       if (imagepath)
+               CRYPT_Free(imagepath);
+       return FALSE;
+}
+
+/******************************************************************************
+ * CryptAcquireContextW (ADVAPI32.@)
+ *
+ * see CryptAcquireContextA
+ */
+BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
+               LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
+{
+       PSTR pProvider = NULL, pContainer = NULL;
+       BOOL ret = FALSE;
+
+       TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
+               debugstr_w(pszProvider), dwProvType, dwFlags);
+
+       if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+       if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
+       {
+               CRYPT_Free(pContainer);
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+       }
+
+       ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
+
+       if (pContainer)
+               CRYPT_Free(pContainer);
+       if (pProvider)
+               CRYPT_Free(pProvider);
+
+       return ret;
+}
+
+/******************************************************************************
+ * CryptContextAddRef (ADVAPI32.@)
+ *
+ * Increases reference count of a cryptographic service provider handle
+ * by one.
+ *
+ * PARAMS
+ *  hProv       [I] Handle to the CSP whose reference is being incremented.
+ *  pdwReserved [IN] Reserved for future use and must be NULL.
+ *  dwFlags     [I] Reserved for future use and must be NULL.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
+{
+       PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
+
+       TRACE("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
+
+       if (!pProv)
+       {
+               SetLastError(NTE_BAD_UID);
+               return FALSE;
+       }
+
+       pProv->refcount++;
+       return TRUE;
+}
+
+/******************************************************************************
+ * CryptReleaseContext (ADVAPI32.@)
+ *
+ * Releases the handle of a CSP.  Reference count is decreased.
+ *
+ * PARAMS
+ *  hProv   [I] Handle of a CSP.
+ *  dwFlags [I] Reserved for future use and must be NULL.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
+{
+       PCRYPTPROV pProv = (PCRYPTPROV)hProv;
+       BOOL ret = TRUE;
+
+       TRACE("(0x%lx, %08ld)\n", hProv, dwFlags);
+
+       if (!pProv)
+       {
+               SetLastError(NTE_BAD_UID);
+               return FALSE;
+       }
+
+       pProv->refcount--;
+       if (pProv->refcount <= 0) 
+       {
+               ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
+               FreeLibrary(pProv->hModule);
+#if 0
+               CRYPT_Free(pProv->pVTable->pContextInfo);
+#endif
+               CRYPT_Free(pProv->pVTable->pszProvName);
+               CRYPT_Free(pProv->pVTable);
+               CRYPT_Free(pProv->pFuncs);
+               CRYPT_Free(pProv);
+       }
+       return ret;
+}
+
+/******************************************************************************
+ * CryptGenRandom (ADVAPI32.@)
+ *
+ * Fills a buffer with cryptographically random bytes.
+ *
+ * PARAMS
+ *  hProv    [I] Handle of a CSP.
+ *  dwLen    [I] Number of bytes to generate.
+ *  pbBuffer [I/O] Buffer to contain random bytes.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  pdBuffer must be at least dwLen bytes long.
+ */
+BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+
+       TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
+
+       if (!hProv)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+
+       return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
+}
+
+/******************************************************************************
+ * CryptCreateHash (ADVAPI32.@)
+ *
+ * Initiates the hashing of a stream of data.
+ *
+ * PARAMS
+ *  hProv   [I] Handle of a CSP.
+ *  Algid   [I] Identifies the hash algorithm to use.
+ *  hKey    [I] Key for the hash (if required).
+ *  dwFlags [I] Reserved for future use and must be NULL.
+ *  phHash  [O] Address of the future handle to the new hash object.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  If the algorithm is a keyed hash, hKey is the key.
+ */
+BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
+               DWORD dwFlags, HCRYPTHASH *phHash)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+       PCRYPTKEY key = (PCRYPTKEY)hKey;
+       PCRYPTHASH hash;
+
+       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);
+       if (dwFlags)
+               CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+       if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+       hash->pProvider = prov;
+
+       if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
+                       key ? key->hPrivate : 0, 0, &hash->hPrivate))
+        {
+            *phHash = (HCRYPTHASH)hash;
+            return TRUE;
+        }
+
+       /* CSP error! */
+       CRYPT_Free(hash);
+       *phHash = 0;
+       return FALSE;
+}
+
+/******************************************************************************
+ * CryptDecrypt (ADVAPI32.@)
+ *
+ * Decrypts data encrypted by CryptEncrypt.
+ *
+ * PARAMS
+ *  hKey       [I] Handle to the decryption key.
+ *  hHash      [I] Handle to a hash object.
+ *  Final      [I] TRUE if this is the last section to be decrypted.
+ *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
+ *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
+ *                   data on return
+ *  pdwDataLen [I/O] Length of pbData before and after the call.
+ *
+ *  RETURNS
+ *   Success: TRUE
+ *   Failure: FALSE
+ */
+BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
+               DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
+{
+       PCRYPTPROV prov;
+       PCRYPTKEY key = (PCRYPTKEY)hKey;
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+
+       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);
+
+       prov = key->pProvider;
+       return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
+                       Final, dwFlags, pbData, pdwDataLen);
+}
+
+/******************************************************************************
+ * CryptDeriveKey (ADVAPI32.@)
+ *
+ * Generates session keys derived from a base data value.
+ *
+ * PARAMS
+ *  hProv     [I] Handle to a CSP.
+ *  Algid     [I] Identifies the symmetric encryption algorithm to use.
+ *  hBaseData [I] Handle to a hash object.
+ *  dwFlags   [I] Type of key to generate.
+ *  phKey     [I/O] Address of the newly generated key.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
+               DWORD dwFlags, HCRYPTKEY *phKey)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+       PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
+       PCRYPTKEY key;
+
+       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);
+       if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+       key->pProvider = prov;
+       if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
+        {
+            *phKey = (HCRYPTKEY)key;
+            return TRUE;
+        }
+
+       /* CSP error! */
+       CRYPT_Free(key);
+       *phKey = 0;
+       return FALSE;
+}
+
+/******************************************************************************
+ * CryptDestroyHash (ADVAPI32.@)
+ *
+ * Destroys the hash object referenced by hHash.
+ *
+ * PARAMS
+ *  hHash [I] Handle of the hash object to be destroyed.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
+{
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+       PCRYPTPROV prov;
+       BOOL ret;
+
+       TRACE("(0x%lx)\n", hHash);
+
+       if (!hash)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+
+       prov = hash->pProvider;
+       ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
+       CRYPT_Free(hash);
+       return ret;
+}
+
+/******************************************************************************
+ * CryptDestroyKey (ADVAPI32.@)
+ *
+ * Releases the handle referenced by hKey.
+ *
+ * PARAMS
+ *  hKey [I] Handle of the key to be destroyed.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
+{
+       PCRYPTKEY key = (PCRYPTKEY)hKey;
+       PCRYPTPROV prov;
+       BOOL ret;
+
+       TRACE("(0x%lx)\n", hKey);
+
+       if (!key)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+
+       prov = key->pProvider;
+       ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
+       CRYPT_Free(key);
+       return ret;
+}
+
+/******************************************************************************
+ * CryptDuplicateHash (ADVAPI32.@)
+ *
+ * Duplicates a hash.
+ *
+ * PARAMS
+ *  hHash       [I] Handle to the hash to be copied.
+ *  pdwReserved [I] Reserved for future use and must be zero.
+ *  dwFlags     [I] Reserved for future use and must be zero.
+ *  phHash      [O] Address of the handle to receive the copy.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
+               DWORD dwFlags, HCRYPTHASH *phHash)
+{
+       PCRYPTPROV prov;
+       PCRYPTHASH orghash, newhash;
+
+       TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
+
+       orghash = (PCRYPTHASH)hHash;
+       if (!orghash || pdwReserved || !phHash)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = orghash->pProvider;
+       if (!prov->pFuncs->pCPDuplicateHash)
+               CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
+
+       if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+       newhash->pProvider = prov;
+       if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
+       {
+               *phHash = (HCRYPTHASH)newhash;
+               return TRUE;
+       }
+       CRYPT_Free(newhash);
+       return FALSE;
+}
+
+/******************************************************************************
+ * CryptDuplicateKey (ADVAPI32.@)
+ *
+ * Duplicate a key and the key's state.
+ *
+ * PARAMS
+ *  hKey        [I] Handle of the key to copy.
+ *  pdwReserved [I] Reserved for future use and must be NULL.
+ *  dwFlags     [I] Reserved for future use and must be zero.
+ *  phKey       [I] Address of the handle to the duplicated key.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
+{
+       PCRYPTPROV prov;
+       PCRYPTKEY orgkey, newkey;
+
+       TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
+
+       orgkey = (PCRYPTKEY)hKey;
+       if (!orgkey || pdwReserved || !phKey)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = orgkey->pProvider;
+       if (!prov->pFuncs->pCPDuplicateKey)
+               CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
+
+       if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+       newkey->pProvider = prov;
+       if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
+       {
+               *phKey = (HCRYPTKEY)newkey;
+               return TRUE;
+       }
+       CRYPT_Free(newkey);
+       return FALSE;
+}
+
+/******************************************************************************
+ * CryptEncrypt (ADVAPI32.@)
+ *
+ * Encrypts data.
+ *
+ * PARAMS
+ *  hKey       [I] Handle to the enryption 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.
+ *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
+ *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
+ *                   encrypted data after call.
+ *  dwBufLen   [I] Length of the input pbData buffer.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ *  NOTES
+ *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
+ *   required for the returned data in pdwDataLen.
+ */
+BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
+               DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
+{
+       PCRYPTPROV prov;
+       PCRYPTKEY key = (PCRYPTKEY)hKey;
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+
+       TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
+
+       if (!key || !pdwDataLen)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = key->pProvider;
+       return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
+                       Final, dwFlags, pbData, pdwDataLen, dwBufLen);
+}
+
+/******************************************************************************
+ * CryptEnumProvidersW (ADVAPI32.@)
+ *
+ * Returns the next availabe CSP.
+ *
+ * PARAMS
+ *  dwIndex     [I] Index of the next provider to be enumerated.
+ *  pdwReserved [I] Reserved for future use and must be NULL.
+ *  dwFlags     [I] Reserved for future use and must be zero.
+ *  pdwProvType [O] DWORD designating the type of the provider.
+ *  pszProvName [O] Buffer that receives data from the provider.
+ *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
+ *                    of bytes stored in the buffer on return.
+ *
+ *  RETURNS
+ *   Success: TRUE
+ *   Failure: FALSE
+ *
+ *  NOTES
+ *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
+ *   for memory allocation purposes.
+ */
+BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
+               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};
+
+       TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
+                       pdwProvType, pszProvName, pcbProvName);
+
+       if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+       if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+
+       if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
+               CRYPT_ReturnLastError(NTE_FAIL);
+
+       if (!pszProvName)
+       {
+               DWORD numkeys;
+               WCHAR *provNameW;
+               
+               RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
+                                NULL, NULL, NULL, NULL, NULL, NULL);
+               
+               if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
+                       CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+               
+               RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
+               (*pcbProvName)++;
+               *pcbProvName *= sizeof(WCHAR);
+               
+               CRYPT_Free(provNameW);
+               
+               if (dwIndex >= numkeys)
+                       CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
+       } else {
+               DWORD size = sizeof(DWORD);
+               DWORD result;
+               HKEY subkey;
+               
+               result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
+               if (result)
+                       CRYPT_ReturnLastError(result);
+               if (RegOpenKeyW(hKey, pszProvName, &subkey))
+                       return FALSE;
+               if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
+                       return FALSE;
+               RegCloseKey(subkey);
+       }
+       RegCloseKey(hKey);
+       return TRUE;
+}
+
+/******************************************************************************
+ * CryptEnumProvidersA (ADVAPI32.@)
+ *
+ * see CryptEnumProvidersW
+ */
+BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
+               DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
+{
+       PWSTR str = NULL;
+       DWORD strlen;
+       BOOL ret; /* = FALSE; */
+
+       TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
+                       pdwProvType, pszProvName, pcbProvName);
+
+       strlen = *pcbProvName * sizeof(WCHAR);
+       if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+       ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
+       if (str)
+       {
+               CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
+               CRYPT_Free(str);
+       }
+       *pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
+       return ret;
+}
+
+/******************************************************************************
+ * CryptEnumProviderTypesA (ADVAPI32i.@)
+ *
+ * Retrieves the next type of CSP supported.
+ *
+ * PARAMS
+ *  dwIndex     [I] Index of the next provider to be enumerated.
+ *  pdwReserved [I] Reserved for future use and must be NULL.
+ *  dwFlags     [I] Reserved for future use and must be zero.
+ *  pdwProvType [O] DWORD designating the type of the provider.
+ *  pszTypeName [O] Buffer that receives data from the provider type.
+ *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
+ *                    of bytes stored in the buffer on return.
+ *
+ *  RETURNS
+ *   Success: TRUE
+ *   Failure: FALSE
+ *
+ *  NOTES
+ *   If pszTypeName is NULL, CryptEnumProviderTypesA 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)
+{
+       HKEY hKey, hSubkey;
+       DWORD keylen, numkeys, dwType;
+       PSTR keyname, ch;
+       DWORD result;
+
+       TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
+               dwFlags, pdwProvType, pszTypeName, pcbTypeName);
+
+       if (pdwReserved || !pdwProvType || !pcbTypeName)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+       if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+
+       if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
+               return FALSE;
+
+       RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
+       if (dwIndex >= numkeys)
+               CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
+       keylen++;
+       if ( !(keyname = CRYPT_Alloc(keylen)) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+       if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) {
+                CRYPT_Free(keyname);
+               return FALSE;
+        }
+       RegOpenKeyA(hKey, keyname, &hSubkey);
+       ch = keyname + strlen(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, pszTypeName, pcbTypeName);
+       if (result)
+               CRYPT_ReturnLastError(result);
+
+       RegCloseKey(hSubkey);
+       RegCloseKey(hKey);
+       return TRUE;
+}
+
+/******************************************************************************
+ * CryptEnumProviderTypesW (ADVAPI32.@)
+ *
+ * see CryptEnumProviderTypesA
+ */
+BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
+               DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
+{
+       PSTR str = NULL;
+       DWORD strlen;
+       BOOL ret;
+
+       TRACE("(%ld, %p, %08ld, %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 (str)
+       {
+               CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
+               CRYPT_Free(str);
+       }
+       *pcbTypeName = strlen * sizeof(WCHAR);
+       return ret;
+}
+
+/******************************************************************************
+ * CryptExportKey (ADVAPI32.@)
+ * 
+ * Exports a cryptographic key from a CSP.
+ *
+ * PARAMS
+ *  hKey       [I] Handle to the key to export.
+ *  hExpKey    [I] Handle to a cryptographic key of the end user.
+ *  dwBlobType [I] Type of BLOB to be exported.
+ *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
+ *  pbData     [O] Buffer to receive BLOB data.
+ *  pdwDataLen [I/O] Specifies the size of pbData.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
+ *  buffer needed to hold the BLOB.
+ */
+BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
+               DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
+{
+       PCRYPTPROV prov;
+       PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
+
+       TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
+
+       if (!key || !pdwDataLen)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = key->pProvider;
+       return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
+                       dwBlobType, dwFlags, pbData, pdwDataLen);
+}
+
+/******************************************************************************
+ * CryptGenKey (ADVAPI32.@)
+ *
+ * Generates a random cryptographic session key or a pub/priv key pair.
+ *
+ * PARAMS
+ *  hProv   [I] Handle to a CSP.
+ *  Algid   [I] Algorithm to use to make key.
+ *  dwFlags [I] Specifies type of key to make.
+ *  phKey   [I] Address of the handle to which the new key is copied.
+ *
+ *  RETURNS
+ *   Success: TRUE
+ *   Failure: FALSE
+ */
+BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+       PCRYPTKEY key;
+
+       TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
+
+       if (!prov)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+       if (!phKey)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+       if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+       key->pProvider = prov;
+
+       if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
+        {
+            *phKey = (HCRYPTKEY)key;
+            return TRUE;
+        }
+
+       /* CSP error! */
+       CRYPT_Free(key);
+       return FALSE;
+}
+
+/******************************************************************************
+ * CryptGetDefaultProviderA (ADVAPI32.@)
+ *
+ * Finds the default CSP of a certain provider type.
+ *
+ * PARAMS
+ *  dwProvType  [I] Provider type to look for.
+ *  pdwReserved [I] Reserved for future use and must be NULL.
+ *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
+ *  pszProvName [O] Name of the default CSP.
+ *  pcbProvName [I/O] Size of pszProvName
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
+ *  memory allocation purposes on return.
+ */
+BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
+               DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
+{
+       HKEY hKey;
+       PSTR keyname;
+       DWORD result;
+
+       if (pdwReserved || !pcbProvName)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+       if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
+               CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+       if (dwProvType > 999)
+               CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
+       if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+       if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
+       {
+               CRYPT_Free(keyname);
+               CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
+       }
+       CRYPT_Free(keyname);
+       
+       result = RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName); 
+       if (result)
+       {
+               if (result != ERROR_MORE_DATA)
+                       SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+               else
+                       SetLastError(result);
+               
+               return FALSE;
+       }
+       
+       RegCloseKey(hKey);
+       return TRUE;
+}
+
+/******************************************************************************
+ * CryptGetDefaultProviderW (ADVAPI32.@)
+ *
+ * see CryptGetDefaultProviderA
+ */
+BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
+               DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
+{
+       PSTR str = NULL;
+       DWORD strlen;
+       BOOL ret = FALSE;
+
+       TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
+
+       strlen = *pcbProvName / sizeof(WCHAR);
+       if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+       ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
+       if (str)
+       {
+               CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
+               CRYPT_Free(str);
+       }
+       *pcbProvName = strlen * sizeof(WCHAR);
+       return ret;
+}
+
+/******************************************************************************
+ * CryptGetHashParam (ADVAPI32.@)
+ *
+ * Retrieves data that controls the operations of a hash object.
+ *
+ * PARAMS
+ *  hHash      [I] Handle of the hash object to question.
+ *  dwParam    [I] Query type.
+ *  pbData     [O] Buffer that receives the value data.
+ *  pdwDataLen [I/O] Size of the pbData buffer.
+ *  dwFlags    [I] Reserved for future use and must be zero.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  If pbData is NULL, pdwDataLen will contain the length required.
+ */
+BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
+               DWORD *pdwDataLen, DWORD dwFlags)
+{
+       PCRYPTPROV prov;
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+
+       TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
+
+       if (!hash || !pdwDataLen)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = hash->pProvider;
+       return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
+                       pbData, pdwDataLen, dwFlags);
+}
+
+/******************************************************************************
+ * CryptGetKeyParam (ADVAPI32.@)
+ *
+ * Retrieves data that controls the operations of a key.
+ *
+ * PARAMS
+ *  hKey       [I] Handle to they key in question.
+ *  dwParam    [I] Specifies query type.
+ *  pbData     [O] Sequence of bytes to receive data.
+ *  pdwDataLen [I/O] Size of pbData.
+ *  dwFlags    [I] Reserved for future use and must be zero.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
+ */
+BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
+               DWORD *pdwDataLen, DWORD dwFlags)
+{
+       PCRYPTPROV prov;
+       PCRYPTKEY key = (PCRYPTKEY)hKey;
+
+       TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
+
+       if (!key || !pdwDataLen)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = key->pProvider;
+       return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
+                       pbData, pdwDataLen, dwFlags);
+}
+
+/******************************************************************************
+ * CryptGetProvParam (ADVAPI32.@)
+ *
+ * Retrieves parameters that control the operations of a CSP.
+ *
+ * PARAMS
+ *  hProv      [I] Handle of the CSP in question.
+ *  dwParam    [I] Specifies query type.
+ *  pbData     [O] Buffer to receive the data.
+ *  pdwDataLen [I/O] Size of pbData.
+ *  dwFlags    [I] see MSDN Docs.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
+ */
+BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
+               DWORD *pdwDataLen, DWORD dwFlags)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+
+       TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
+
+       return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
+}
+
+/******************************************************************************
+ * CryptGetUserKey (ADVAPI32.@)
+ *
+ * Gets a handle of one of a user's two public/private key pairs.
+ *
+ * PARAMS
+ *  hProv     [I] Handle of a CSP.
+ *  dwKeySpec [I] Private key to use.
+ *  phUserKey [O] Pointer to the handle of the retrieved keys.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+       PCRYPTKEY key;
+
+       TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
+
+       if (!prov)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+       if (!phUserKey)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+       if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+       key->pProvider = prov;
+
+       if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
+        {
+            *phUserKey = (HCRYPTKEY)key;
+            return TRUE;
+        }
+
+       /* CSP Error */
+       CRYPT_Free(key);
+       *phUserKey = 0;
+       return FALSE;
+}
+
+/******************************************************************************
+ * CryptHashData (ADVAPI32.@)
+ *
+ * Adds data to a hash object.
+ *
+ * PARAMS
+ *  hHash     [I] Handle of the hash object.
+ *  pbData    [I] Buffer of data to be hashed.
+ *  dwDataLen [I] Number of bytes to add.
+ *  dwFlags   [I] Can be CRYPT_USERDATA
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
+{
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+       PCRYPTPROV prov;
+
+       TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
+
+       if (!hash)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+       if (!pbData || !dwDataLen)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = hash->pProvider;
+       return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
+}
+
+/******************************************************************************
+ * CryptHashSessionKey (ADVAPI32.@)
+ *
+ * PARAMS 
+ *  hHash   [I] Handle to the hash object.
+ *  hKey    [I] Handle to the key to be hashed.
+ *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
+{
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+       PCRYPTKEY key = (PCRYPTKEY)hKey;
+       PCRYPTPROV prov;
+
+       TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
+
+       if (!hash || !key)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+
+       prov = hash->pProvider;
+       return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
+}
+
+/******************************************************************************
+ * CryptImportKey (ADVAPI32.@)
+ *
+ * PARAMS
+ *  hProv     [I] Handle of a CSP.
+ *  pbData    [I] Contains the key to be imported.
+ *  dwDataLen [I] Length of the key.
+ *  hPubKey   [I] Cryptographic key that decrypts pdData
+ *  dwFlags   [I] Used only with a public/private key pair.
+ *  phKey     [O] Imported key.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
+               HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+       PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
+
+       TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
+
+       if (!prov || !pbData || !dwDataLen || !phKey)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+       importkey->pProvider = prov;
+       if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
+                       pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
+       {
+               *phKey = (HCRYPTKEY)importkey;
+               return TRUE;
+       }
+
+       CRYPT_Free(importkey);
+       return FALSE;
+}
+
+/******************************************************************************
+ * 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.
+ *
+ * PARAMS
+ *  hHash        [I] Handle of the hash object to be signed.
+ *  dwKeySpec    [I] Private key to use.
+ *  sDescription [I] Must be NULL.
+ *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
+ *  pbSignature  [O] Buffer of the signature data.
+ *  pdwSigLen    [I/O] Size of the pbSignature buffer.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
+               DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
+{
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+       PCRYPTPROV prov;
+
+       TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
+       if (sDescription)
+               WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
+
+       if (!hash)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+       if (!pdwSigLen)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = hash->pProvider;
+       return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
+               dwFlags, pbSignature, pdwSigLen);
+}
+
+/******************************************************************************
+ * CryptSetHashParam (ADVAPI32.@)
+ *
+ * Customizes the operations of a hash object.
+ *
+ * PARAMS
+ *  hHash   [I] Handle of the hash object to set parameters.
+ *  dwParam [I] HP_HMAC_INFO/HASHVAL.
+ *  pbData  [I] Value data buffer.
+ *  dwFlags [I] Reserved for future use and must be zero.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
+{
+       PCRYPTPROV prov;
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+
+       TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
+
+       if (!hash || !pbData)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = hash->pProvider;
+       return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
+                       dwParam, pbData, dwFlags);
+}
+
+/******************************************************************************
+ * CryptSetKeyParam (ADVAPI32.@)
+ *
+ * Customizes a session key's operations.
+ *
+ * PARAMS
+ *  hKey    [I] Handle to the key to set values.
+ *  dwParam [I] See MSDN Doc.
+ *  pbData  [I] Buffer of values to set.
+ *  dwFlags [I] Only used when dwParam == KP_ALGID.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
+{
+       PCRYPTPROV prov;
+       PCRYPTKEY key = (PCRYPTKEY)hKey;
+
+       TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
+
+       if (!key || !pbData)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+
+       prov = key->pProvider;
+       return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
+                       dwParam, pbData, dwFlags);
+}
+
+/******************************************************************************
+ * CryptSetProviderA (ADVAPI32.@)
+ *
+ * Specifies the current user's default CSP.
+ *
+ * PARAMS
+ *  pszProvName [I] Name of the new default CSP.
+ *  dwProvType  [I] Provider type of the CSP.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
+{
+       TRACE("(%s, %ld)\n", pszProvName, dwProvType);
+       return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
+}
+
+/******************************************************************************
+ * CryptSetProviderW (ADVAPI32.@)
+ *
+ * See CryptSetProviderA
+ */
+BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
+{
+       TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
+       return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
+}
+
+/******************************************************************************
+ * CryptSetProviderExA (ADVAPI32.@)
+ *
+ * Specifies the default CSP.
+ *
+ * PARAMS
+ *  pszProvName [I] Name of the new default CSP.
+ *  dwProvType  [I] Provider type of the CSP.
+ *  pdwReserved [I] Reserved for future use and must be NULL.
+ *  dwFlags     [I] See MSDN Doc.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
+{
+       HKEY hProvKey, hTypeKey;
+       PSTR keyname;
+
+       TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
+
+       if (!pszProvName || pdwReserved)
+               CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
+       if (dwProvType > MAXPROVTYPES)
+               CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
+       if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
+                       || dwFlags == CRYPT_DELETE_DEFAULT)
+               CRYPT_ReturnLastError(NTE_BAD_FLAGS);
+       
+       if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
+               CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+       if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
+               keyname, &hTypeKey))
+       {
+               CRYPT_Free(keyname);
+               CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
+       }
+       CRYPT_Free(keyname);
+       
+       if (dwFlags & CRYPT_DELETE_DEFAULT)
+       {
+               RegDeleteValueA(hTypeKey, "Name");
+       }
+       else
+       {
+               if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
+               {
+                       RegCloseKey(hTypeKey);
+                       CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
+               }
+               if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
+                       keyname, &hProvKey))
+               {
+                       CRYPT_Free(keyname);
+                       RegCloseKey(hTypeKey);
+                       CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
+               }
+               CRYPT_Free(keyname);
+               
+               if (RegSetValueExA(hTypeKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) + 1))
+               {
+                       RegCloseKey(hTypeKey);
+                       RegCloseKey(hProvKey);
+                       return FALSE;
+               }
+               
+               RegCloseKey(hProvKey);
+       }
+       RegCloseKey(hTypeKey);
+
+       return TRUE;
+}
+
+/******************************************************************************
+ * CryptSetProviderExW (ADVAPI32.@)
+ *
+ * See CryptSetProviderExA
+ */
+BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
+{
+       BOOL ret = FALSE;
+       PSTR str = NULL;
+
+       TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
+
+       if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
+       {
+               ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
+               CRYPT_Free(str);
+       }
+       return ret;
+}
+
+/******************************************************************************
+ * CryptSetProvParam (ADVAPI32.@)
+ *
+ * Customizes the operations of a CSP.
+ *
+ * PARAMS
+ *  hProv   [I] Handle of a CSP.
+ *  dwParam [I] See MSDN Doc.
+ *  pbData  [I] Buffer that contains a value to set as a parameter.
+ *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
+{
+       PCRYPTPROV prov = (PCRYPTPROV)hProv;
+
+       TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
+
+       if (!prov)
+               CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
+       if (dwFlags & PP_USE_HARDWARE_RNG)
+       {
+               FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
+               FIXME("\tLetting the CSP decide.\n");
+       }
+       if (dwFlags & PP_CLIENT_HWND)
+       {
+               /* FIXME: Should verify the parameter */
+               if (pbData /* && IsWindow((HWND)pbData) */)
+               {
+                       crypt_hWindow = (HWND)(pbData);
+                       return TRUE;
+               } else {
+                       SetLastError(ERROR_INVALID_PARAMETER);
+                       return FALSE;
+               }
+       }
+       /* All other flags go to the CSP */
+       return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
+}
+
+/******************************************************************************
+ * 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.
+ *
+ * PARAMS
+ *  hHash        [I] Handle of the hash object to verify.
+ *  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.
+ *  dwFlags      [I] See MSDN doc.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
+               HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
+{
+       PCRYPTHASH hash = (PCRYPTHASH)hHash;
+       PCRYPTKEY key = (PCRYPTKEY)hPubKey;
+       PCRYPTPROV prov;
+
+       TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
+                       dwSigLen, hPubKey, dwFlags);
+       if (sDescription)
+               WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
+
+       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);
+}
+
+
+/*
+   These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
+   in crypt32.dll.
+ */
+
+/******************************************************************************
+ * 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
+ *            when decrypting the memory.
+ */
+NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)  /* RtlEncryptMemory */
+{
+       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.
+ */
+NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)  /* RtlDecryptMemory */
+{
+       FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
+       return STATUS_SUCCESS;
+}
diff --git a/reactos/lib/advapi32/crypt/crypt.h b/reactos/lib/advapi32/crypt/crypt.h
new file mode 100644 (file)
index 0000000..4a56363
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Driver routines
+ *
+ * Copyright 2001 - Travis Michielsen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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
+ */
+
+#ifndef __WINE_CRYPT_H
+#define __WINE_CRYPT_H
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wincrypt.h"
+
+typedef struct tagPROVFUNCS
+{
+       BOOL (WINAPI *pCPAcquireContext)(HCRYPTPROV *phProv, LPSTR pszContainer, DWORD dwFlags, PVTableProvStruc pVTable);
+       BOOL (WINAPI *pCPCreateHash)(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash);
+       BOOL (WINAPI *pCPDecrypt)(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen);
+       BOOL (WINAPI *pCPDeriveKey)(HCRYPTPROV hProv, ALG_ID     Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey);
+       BOOL (WINAPI *pCPDestroyHash)(HCRYPTPROV hProv, HCRYPTHASH hHash);
+       BOOL (WINAPI *pCPDestroyKey)(HCRYPTPROV hProv, HCRYPTKEY hKey);
+       BOOL (WINAPI *pCPDuplicateHash)(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved, DWORD dwFlags, HCRYPTHASH *phHash);
+       BOOL (WINAPI *pCPDuplicateKey)(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey);
+       BOOL (WINAPI *pCPEncrypt)(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen);
+       BOOL (WINAPI *pCPExportKey)(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey, DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen);
+       BOOL (WINAPI *pCPGenKey)(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey);
+       BOOL (WINAPI *pCPGenRandom)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer);
+       BOOL (WINAPI *pCPGetHashParam)(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags);
+       BOOL (WINAPI *pCPGetKeyParam)(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags);
+       BOOL (WINAPI *pCPGetProvParam)(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags);
+       BOOL (WINAPI *pCPGetUserKey)(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey);
+       BOOL (WINAPI *pCPHashData)(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData, DWORD dwDataLen, DWORD dwFlags);
+       BOOL (WINAPI *pCPHashSessionKey)(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags);
+       BOOL (WINAPI *pCPImportKey)(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey);
+       BOOL (WINAPI *pCPReleaseContext)(HCRYPTPROV hProv, DWORD dwFlags);
+       BOOL (WINAPI *pCPSetHashParam)(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags);
+       BOOL (WINAPI *pCPSetKeyParam)(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags);
+       BOOL (WINAPI *pCPSetProvParam)(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags);
+       BOOL (WINAPI *pCPSignHash)(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen);
+       BOOL (WINAPI *pCPVerifySignature)(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags);
+} PROVFUNCS, *PPROVFUNCS;
+
+typedef struct tagCRYPTPROV
+{
+       UINT refcount;
+       HMODULE hModule;
+       PPROVFUNCS pFuncs;
+        HCRYPTPROV hPrivate;  /*CSP's handle - Should not be given to application under any circumstances!*/
+       PVTableProvStruc pVTable;
+} CRYPTPROV, *PCRYPTPROV;
+
+typedef struct tagCRYPTKEY
+{
+       PCRYPTPROV pProvider;
+        HCRYPTKEY hPrivate;    /*CSP's handle - Should not be given to application under any circumstances!*/
+} CRYPTKEY, *PCRYPTKEY;
+
+typedef struct tagCRYPTHASH
+{
+       PCRYPTPROV pProvider;
+        HCRYPTHASH hPrivate;    /*CSP's handle - Should not be given to application under any circumstances!*/
+} CRYPTHASH, *PCRYPTHASH;
+
+#define MAXPROVTYPES 999
+
+extern unsigned char *CRYPT_DESkey8to7( unsigned char *dst, const unsigned char *key );
+extern unsigned char *CRYPT_DEShash( unsigned char *dst, const unsigned char *key,
+                                     const unsigned char *src );
+
+#endif /* __WINE_CRYPT_H_ */
diff --git a/reactos/lib/advapi32/crypt/crypt_des.c b/reactos/lib/advapi32/crypt/crypt_des.c
new file mode 100644 (file)
index 0000000..4b527dd
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ *  Copyright 2004 Hans Leidekker
+ *
+ *  Based on DES.c from libcifs
+ *
+ *  Copyright (C) 2003, 2004 by Christopher R. Hertel
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  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
+ */
+
+#include "windef.h"
+#include "crypt.h"
+
+static const unsigned char InitialPermuteMap[64] =
+{
+    57, 49, 41, 33, 25, 17,  9, 1,
+    59, 51, 43, 35, 27, 19, 11, 3,
+    61, 53, 45, 37, 29, 21, 13, 5,
+    63, 55, 47, 39, 31, 23, 15, 7,
+    56, 48, 40, 32, 24, 16,  8, 0,
+    58, 50, 42, 34, 26, 18, 10, 2,
+    60, 52, 44, 36, 28, 20, 12, 4,
+    62, 54, 46, 38, 30, 22, 14, 6
+ };
+
+static const unsigned char KeyPermuteMap[56] =
+{
+    49, 42, 35, 28, 21, 14,  7,  0,
+    50, 43, 36, 29, 22, 15,  8,  1,
+    51, 44, 37, 30, 23, 16,  9,  2,
+    52, 45, 38, 31, 55, 48, 41, 34,
+    27, 20, 13,  6, 54, 47, 40, 33,
+    26, 19, 12,  5, 53, 46, 39, 32,
+    25, 18, 11,  4, 24, 17, 10,  3,
+};
+
+static const unsigned char KeyRotation[16] =
+    { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
+
+static const unsigned char KeyCompression[48] =
+{
+    13, 16, 10, 23,  0,  4,  2, 27,
+    14,  5, 20,  9, 22, 18, 11,  3,
+    25,  7, 15,  6, 26, 19, 12,  1,
+    40, 51, 30, 36, 46, 54, 29, 39,
+    50, 44, 32, 47, 43, 48, 38, 55,
+    33, 52, 45, 41, 49, 35, 28, 31
+};
+
+static const unsigned char DataExpansion[48] =
+{
+    31,  0,  1,  2,  3,  4,  3,  4,
+     5,  6,  7,  8,  7,  8,  9, 10,
+    11, 12, 11, 12, 13, 14, 15, 16,
+    15, 16, 17, 18, 19, 20, 19, 20,
+    21, 22, 23, 24, 23, 24, 25, 26,
+    27, 28, 27, 28, 29, 30, 31,  0
+};
+
+static const unsigned char SBox[8][64] =
+{
+    {  /* S0 */
+        14,  0,  4, 15, 13,  7,  1,  4,  2, 14, 15,  2, 11, 13,  8,  1,
+         3, 10, 10,  6,  6, 12, 12, 11,  5,  9,  9,  5,  0,  3,  7,  8,
+         4, 15,  1, 12, 14,  8,  8,  2, 13,  4,  6,  9,  2,  1, 11,  7,
+        15,  5, 12, 11,  9,  3,  7, 14,  3, 10, 10,  0,  5,  6,  0, 13
+    },
+    {  /* S1 */
+        15,  3,  1, 13,  8,  4, 14,  7,  6, 15, 11,  2,  3,  8,  4, 14,
+         9, 12,  7,  0,  2,  1, 13, 10, 12,  6,  0,  9,  5, 11, 10,  5,
+         0, 13, 14,  8,  7, 10, 11,  1, 10,  3,  4, 15, 13,  4,  1,  2,
+         5, 11,  8,  6, 12,  7,  6, 12,  9,  0,  3,  5,  2, 14, 15,  9
+    },
+    {  /* S2 */
+        10, 13,  0,  7,  9,  0, 14,  9,  6,  3,  3,  4, 15,  6,  5, 10,
+         1,  2, 13,  8, 12,  5,  7, 14, 11, 12,  4, 11,  2, 15,  8,  1,
+        13,  1,  6, 10,  4, 13,  9,  0,  8,  6, 15,  9,  3,  8,  0,  7,
+        11,  4,  1, 15,  2, 14, 12,  3,  5, 11, 10,  5, 14,  2,  7, 12
+    },
+    {  /* S3 */
+         7, 13, 13,  8, 14, 11,  3,  5,  0,  6,  6, 15,  9,  0, 10,  3,
+         1,  4,  2,  7,  8,  2,  5, 12, 11,  1, 12, 10,  4, 14, 15,  9,
+        10,  3,  6, 15,  9,  0,  0,  6, 12, 10, 11,  1,  7, 13, 13,  8,
+        15,  9,  1,  4,  3,  5, 14, 11,  5, 12,  2,  7,  8,  2,  4, 14
+    },
+    {  /* S4 */
+         2, 14, 12, 11,  4,  2,  1, 12,  7,  4, 10,  7, 11, 13,  6,  1,
+         8,  5,  5,  0,  3, 15, 15, 10, 13,  3,  0,  9, 14,  8,  9,  6,
+         4, 11,  2,  8,  1, 12, 11,  7, 10,  1, 13, 14,  7,  2,  8, 13,
+        15,  6,  9, 15, 12,  0,  5,  9,  6, 10,  3,  4,  0,  5, 14,  3
+    },
+    {  /* S5 */
+        12, 10,  1, 15, 10,  4, 15,  2,  9,  7,  2, 12,  6,  9,  8,  5,
+         0,  6, 13,  1,  3, 13,  4, 14, 14,  0,  7, 11,  5,  3, 11,  8,
+         9,  4, 14,  3, 15,  2,  5, 12,  2,  9,  8,  5, 12, 15,  3, 10,
+         7, 11,  0, 14,  4,  1, 10,  7,  1,  6, 13,  0, 11,  8,  6, 13
+    },
+    {  /* S6 */
+         4, 13, 11,  0,  2, 11, 14,  7, 15,  4,  0,  9,  8,  1, 13, 10,
+         3, 14, 12,  3,  9,  5,  7, 12,  5,  2, 10, 15,  6,  8,  1,  6,
+         1,  6,  4, 11, 11, 13, 13,  8, 12,  1,  3,  4,  7, 10, 14,  7,
+        10,  9, 15,  5,  6,  0,  8, 15,  0, 14,  5,  2,  9,  3,  2, 12
+    },
+    {  /* S7 */
+        13,  1,  2, 15,  8, 13,  4,  8,  6, 10, 15,  3, 11,  7,  1,  4,
+        10, 12,  9,  5,  3,  6, 14, 11,  5,  0,  0, 14, 12,  9,  7,  2,
+         7,  2, 11,  1,  4, 14,  1,  7,  9,  4, 12, 10, 14,  8,  2, 13,
+         0, 15,  6, 12, 10,  9, 13,  0, 15,  3,  3,  5,  5,  6,  8, 11
+    }
+};
+
+static const unsigned char PBox[32] =
+{
+    15,  6, 19, 20, 28, 11, 27, 16,
+     0, 14, 22, 25,  4, 17, 30,  9,
+     1,  7, 23, 13, 31, 26,  2,  8,
+    18, 12, 29,  5, 21, 10,  3, 24
+};
+
+static const unsigned char FinalPermuteMap[64] =
+{
+     7, 39, 15, 47, 23, 55, 31, 63,
+     6, 38, 14, 46, 22, 54, 30, 62,
+     5, 37, 13, 45, 21, 53, 29, 61,
+     4, 36, 12, 44, 20, 52, 28, 60,
+     3, 35, 11, 43, 19, 51, 27, 59,
+     2, 34, 10, 42, 18, 50, 26, 58,
+     1, 33,  9, 41, 17, 49, 25, 57,
+     0, 32,  8, 40, 16, 48, 24, 56
+};
+
+#define CLRBIT( STR, IDX ) ( (STR)[(IDX)/8] &= ~(0x01 << (7 - ((IDX)%8))) )
+#define SETBIT( STR, IDX ) ( (STR)[(IDX)/8] |= (0x01 << (7 - ((IDX)%8))) )
+#define GETBIT( STR, IDX ) (( ((STR)[(IDX)/8]) >> (7 - ((IDX)%8)) ) & 0x01)
+
+static void Permute( unsigned char *dst, const unsigned char *src, const unsigned char *map, const int mapsize )
+{
+    int bitcount, i;
+
+    for (i = 0; i < mapsize; i++)
+        dst[i] = 0;
+
+    bitcount = mapsize * 8;
+
+    for (i = 0; i < bitcount; i++)
+    {
+        if (GETBIT( src, map[i] ))
+            SETBIT( dst, i );
+    }
+} 
+
+static void KeyShift( unsigned char *key, const int numbits )
+{
+    int i;
+    unsigned char keep = key[0];
+
+    for (i = 0; i < numbits; i++)
+    {
+        int j;
+
+        for (j = 0; j < 7; j++)
+        {
+            if (j && (key[j] & 0x80))
+                key[j-1] |=  0x01;
+            key[j] <<= 1;
+        }
+
+        if (GETBIT( key, 27 ))
+        {
+            CLRBIT( key, 27 );
+            SETBIT( key, 55 );
+        }
+
+        if (keep & 0x80)
+            SETBIT( key, 27 );
+
+        keep <<= 1;
+    }
+}
+
+static void sbox( unsigned char *dst, const unsigned char *src )
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+        dst[i] = 0;
+
+    for (i = 0; i < 8; i++)
+    {
+        int j, Snum, bitnum;
+
+        for (Snum = j = 0, bitnum = (i * 6); j < 6; j++, bitnum++)
+        {
+            Snum <<= 1;
+            Snum |= GETBIT( src, bitnum );
+        }
+
+        if (0 == (i%2))
+            dst[i/2] |= ((SBox[i][Snum]) << 4);
+        else
+            dst[i/2] |= SBox[i][Snum];
+    }
+}
+
+static void xor( unsigned char *dst, const unsigned char *a, const unsigned char *b, const int count )
+{
+    int i;
+
+    for (i = 0; i < count; i++)
+        dst[i] = a[i] ^ b[i];
+}
+
+unsigned char *CRYPT_DESkey8to7( unsigned char *dst, const unsigned char *key )
+{
+    int i;
+    unsigned char tmp[7];
+    static const unsigned char map8to7[56] =
+    {
+         0,  1,  2,  3,  4,  5,  6,
+         8,  9, 10, 11, 12, 13, 14,
+        16, 17, 18, 19, 20, 21, 22,
+        24, 25, 26, 27, 28, 29, 30,
+        32, 33, 34, 35, 36, 37, 38,
+        40, 41, 42, 43, 44, 45, 46,
+        48, 49, 50, 51, 52, 53, 54,
+        56, 57, 58, 59, 60, 61, 62
+    };
+
+    if ((dst == NULL) || (key == NULL))
+        return NULL;
+
+    Permute( tmp, key, map8to7, 7 );
+
+    for (i = 0; i < 7; i++)
+        dst[i] = tmp[i];
+
+    return dst;
+}
+
+unsigned char *CRYPT_DEShash( 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];
+
+        KeyShift( K, KeyRotation[i] );
+        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];
+        }
+    }
+
+    Permute( dst, D, FinalPermuteMap, 8 );
+
+    return dst;
+}
diff --git a/reactos/lib/advapi32/crypt/crypt_lmhash.c b/reactos/lib/advapi32/crypt/crypt_lmhash.c
new file mode 100644 (file)
index 0000000..4236768
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  Copyright 2004 Hans Leidekker
+ *
+ *  Based on LMHash.c from libcifs
+ *
+ *  Copyright (C) 2004 by Christopher R. Hertel
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  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
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+
+typedef LONG (CALLBACK *PVECTORED_EXCEPTION_HANDLER)(
+    struct _EXCEPTION_POINTERS *ExceptionInfo
+    );
+
+#include "wine/winternl.h"
+#include "wine/ntstatus.h"
+
+#include "crypt.h"
+
+static const unsigned char CRYPT_LMhash_Magic[8] =
+    { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
+
+static void CRYPT_LMhash( unsigned char *dst, const unsigned char *pwd, const int len )
+{
+    int i, max = 14;
+    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( 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) );
+
+    return STATUS_SUCCESS;
+}
diff --git a/reactos/lib/advapi32/crypt/crypt_md4.c b/reactos/lib/advapi32/crypt/crypt_md4.c
new file mode 100644 (file)
index 0000000..4c3f9bb
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Hans Leidekker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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
+ */
+
+/*
+ * This code implements the MD4 message-digest algorithm.
+ * It is based on code in the public domain written by Colin
+ * Plumb in 1993. The algorithm is due to Ron Rivest.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD4_CTX structure, pass it to MD4Init, call MD4Update as
+ * needed on buffers full of bytes, and then call MD4Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+typedef struct
+{
+    unsigned int buf[4];
+    unsigned int i[2];
+    unsigned char in[64];
+    unsigned char digest[16];
+} MD4_CTX;
+
+static void MD4Transform( unsigned int buf[4], unsigned int const in[16] );
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse( unsigned char *buf, unsigned longs )
+{
+    unsigned int t;
+
+    do {
+        t = (unsigned int)((unsigned)buf[3] << 8 | buf[2]) << 16 |
+            ((unsigned)buf[1] << 8 | buf[0]);
+        *(unsigned int *)buf = t;
+        buf += 4;
+    } while (--longs);
+}
+
+/*
+ * Start MD4 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+VOID WINAPI MD4Init( MD4_CTX *ctx )
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->i[0] = ctx->i[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len )
+{
+    register unsigned int t;
+
+    /* Update bitcount */
+    t = ctx->i[0];
+
+    if ((ctx->i[0] = t + ((unsigned int)len << 3)) < t)
+        ctx->i[1]++;        /* Carry from low to high */
+
+    ctx->i[1] += len >> 29;
+    t = (t >> 3) & 0x3f;
+
+    /* Handle any leading odd-sized chunks */
+    if (t)
+    {
+        unsigned char *p = (unsigned char *)ctx->in + t;
+        t = 64 - t;
+
+        if (len < t)
+        {
+            memcpy( p, buf, len );
+            return;
+        }
+
+        memcpy( p, buf, t );
+        byteReverse( ctx->in, 16 );
+
+        MD4Transform( ctx->buf, (unsigned int *)ctx->in );
+
+        buf += t;
+        len -= t;
+    }
+
+    /* Process data in 64-byte chunks */
+    while (len >= 64)
+    {
+        memcpy( ctx->in, buf, 64 );
+        byteReverse( ctx->in, 16 );
+
+        MD4Transform( ctx->buf, (unsigned int *)ctx->in );
+
+        buf += 64;
+        len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+    memcpy( ctx->in, buf, len );
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+VOID WINAPI MD4Final( MD4_CTX *ctx )
+{
+    unsigned int count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->i[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8)
+    {
+        /* Two lots of padding:  Pad the first block to 64 bytes */
+        memset( p, 0, count );
+        byteReverse( ctx->in, 16 );
+        MD4Transform( ctx->buf, (unsigned int *)ctx->in );
+
+        /* Now fill the next block with 56 bytes */
+        memset( ctx->in, 0, 56 );
+    }
+    else
+    {
+        /* Pad block to 56 bytes */
+        memset( p, 0, count - 8 );
+    }
+
+    byteReverse( ctx->in, 14 );
+
+    /* Append length in bits and transform */
+    ((unsigned int *)ctx->in)[14] = ctx->i[0];
+    ((unsigned int *)ctx->in)[15] = ctx->i[1];
+
+    MD4Transform( ctx->buf, (unsigned int *)ctx->in );
+    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;
+}
diff --git a/reactos/lib/advapi32/crypt/crypt_md5.c b/reactos/lib/advapi32/crypt/crypt_md5.c
new file mode 100644 (file)
index 0000000..96ff048
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Hans Leidekker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * It is based on code in the public domain written by Colin
+ * Plumb in 1993. The algorithm is due to Ron Rivest.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5_CTX structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+typedef struct
+{
+    unsigned int i[2];
+    unsigned int buf[4];
+    unsigned char in[64];
+    unsigned char digest[16];
+} MD5_CTX;
+
+static void MD5Transform( unsigned int buf[4], const unsigned int in[16] );
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse( unsigned char *buf, unsigned longs )
+{
+    unsigned int t;
+
+    do {
+        t = (unsigned int)((unsigned)buf[3] << 8 | buf[2]) << 16 |
+            ((unsigned)buf[1] << 8 | buf[0]);
+        *(unsigned int *)buf = t;
+        buf += 4;
+    } while (--longs);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+VOID WINAPI MD5Init( MD5_CTX *ctx )
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->i[0] = ctx->i[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+VOID WINAPI MD5Update( MD5_CTX *ctx, const unsigned char *buf, unsigned int len )
+{
+    register unsigned int t;
+
+    /* Update bitcount */
+    t = ctx->i[0];
+
+    if ((ctx->i[0] = t + ((unsigned int)len << 3)) < t)
+        ctx->i[1]++;        /* Carry from low to high */
+
+    ctx->i[1] += len >> 29;
+    t = (t >> 3) & 0x3f;
+
+    /* Handle any leading odd-sized chunks */
+    if (t)
+    {
+        unsigned char *p = (unsigned char *)ctx->in + t;
+        t = 64 - t;
+
+        if (len < t)
+        {
+            memcpy( p, buf, len );
+            return;
+        }
+
+        memcpy( p, buf, t );
+        byteReverse( ctx->in, 16 );
+
+        MD5Transform( ctx->buf, (unsigned int *)ctx->in );
+
+        buf += t;
+        len -= t;
+    }
+
+    /* Process data in 64-byte chunks */
+    while (len >= 64)
+    {
+        memcpy( ctx->in, buf, 64 );
+        byteReverse( ctx->in, 16 );
+
+        MD5Transform( ctx->buf, (unsigned int *)ctx->in );
+
+        buf += 64;
+        len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+    memcpy( ctx->in, buf, len );
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+VOID WINAPI MD5Final( MD5_CTX *ctx )
+{
+    unsigned int count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->i[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8)
+    {
+        /* Two lots of padding:  Pad the first block to 64 bytes */
+        memset( p, 0, count );
+        byteReverse( ctx->in, 16 );
+        MD5Transform( ctx->buf, (unsigned int *)ctx->in );
+
+        /* Now fill the next block with 56 bytes */
+        memset( ctx->in, 0, 56 );
+    }
+    else
+    {
+        /* Pad block to 56 bytes */
+        memset( p, 0, count - 8 );
+    }
+
+    byteReverse( ctx->in, 14 );
+
+    /* Append length in bits and transform */
+    ((unsigned int *)ctx->in)[14] = ctx->i[0];
+    ((unsigned int *)ctx->in)[15] = ctx->i[1];
+
+    MD5Transform( ctx->buf, (unsigned int *)ctx->in );
+    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;
+}
diff --git a/reactos/lib/advapi32/crypt/crypt_sha.c b/reactos/lib/advapi32/crypt/crypt_sha.c
new file mode 100644 (file)
index 0000000..e8f7715
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2004 Filip Navara
+ * Based on public domain SHA code by Steve Reid <steve@edmweb.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+
+/* SHA Context Structure Declaration */
+
+typedef struct {
+   ULONG Unknown[6];
+   ULONG State[5];
+   ULONG Count[2];
+   UCHAR Buffer[64];
+} SHA_CTX, *PSHA_CTX;
+
+/* SHA1 Helper Macros */
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+/* FIXME: This definition of DWORD2BE is little endian specific! */
+#define DWORD2BE(x) (((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000);
+/* FIXME: This definition of blk0 is little endian specific! */
+#define blk0(i) (Block[i] = (rol(Block[i],24)&0xFF00FF00)|(rol(Block[i],8)&0x00FF00FF))
+#define blk1(i) (Block[i&15] = rol(Block[(i+13)&15]^Block[(i+8)&15]^Block[(i+2)&15]^Block[i&15],1))
+#define f1(x,y,z) (z^(x&(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#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. */
+void SHA1Transform(ULONG State[5], CHAR Buffer[64])
+{
+   ULONG a, b, c, d, e;
+   ULONG *Block;
+
+   Block = (ULONG*)Buffer;
+
+   /* Copy Context->State[] to working variables */
+   a = State[0];
+   b = State[1];
+   c = State[2];
+   d = State[3];
+   e = State[4];
+
+   /* 4 rounds of 20 operations each. Loop unrolled. */
+   R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+   R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+   R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+   R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+   R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+   R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+   R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+   R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+   R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+   R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+   R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+   R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+   R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+   R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+   R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+   R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+   R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+   R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+   R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+   R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+   /* Add the working variables back into Context->State[] */
+   State[0] += a;
+   State[1] += b;
+   State[2] += c;
+   State[3] += d;
+   State[4] += e;
+
+   /* Wipe variables */
+   a = b = c = d = e = 0;
+}
+
+
+/******************************************************************************
+ * A_SHAInit [ADVAPI32.@]
+ *
+ * Initialize a SHA context structure.
+ */
+VOID WINAPI
+A_SHAInit(PSHA_CTX Context)
+{
+   /* SHA1 initialization constants */
+   Context->State[0] = 0x67452301;
+   Context->State[1] = 0xEFCDAB89;
+   Context->State[2] = 0x98BADCFE;
+   Context->State[3] = 0x10325476;
+   Context->State[4] = 0xC3D2E1F0;
+   Context->Count[0] =
+   Context->Count[1] = 0;
+}
+
+/******************************************************************************
+ * A_SHAUpdate [ADVAPI32.@]
+ *
+ * Update a SHA context with a hashed data from supplied buffer.
+ */
+VOID WINAPI
+A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize)
+{
+   ULONG BufferContentSize;
+
+   BufferContentSize = Context->Count[1] & 63;
+   Context->Count[1] += BufferSize;
+   if (Context->Count[1] < BufferSize)
+      Context->Count[0]++;
+   Context->Count[0] += (BufferSize >> 29);
+
+   if (BufferContentSize + BufferSize < 64)
+   {
+      RtlCopyMemory(&Context->Buffer[BufferContentSize], Buffer,
+                    BufferSize);
+   }
+   else
+   {
+      while (BufferContentSize + BufferSize >= 64)
+      {
+         RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer,
+                       64 - BufferContentSize);
+         Buffer += 64 - BufferContentSize;
+         BufferSize -= 64 - BufferContentSize;
+         SHA1Transform(Context->State, Context->Buffer);
+         BufferContentSize = 0;
+      }
+      RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer, BufferSize);
+   }
+}
+
+/******************************************************************************
+ * A_SHAFinal [ADVAPI32.@]
+ *
+ * Finalize SHA context and return the resulting hash.
+ */
+VOID WINAPI
+A_SHAFinal(PSHA_CTX Context, PULONG Result)
+{
+   INT Pad, Index;
+   UCHAR Buffer[72];
+   ULONG *Count;
+   ULONG BufferContentSize, LengthHi, LengthLo;
+
+   BufferContentSize = Context->Count[1] & 63;
+   if (BufferContentSize >= 56)
+      Pad = 56 + 64 - BufferContentSize;
+   else
+      Pad = 56 - BufferContentSize;
+
+   LengthHi = (Context->Count[0] << 3) | (Context->Count[1] >> (32 - 3));
+   LengthLo = (Context->Count[1] << 3);
+
+   RtlZeroMemory(Buffer + 1, Pad - 1);
+   Buffer[0] = 0x80;
+   Count = (ULONG*)(Buffer + Pad);
+   Count[0] = DWORD2BE(LengthHi);
+   Count[1] = DWORD2BE(LengthLo);
+   A_SHAUpdate(Context, Buffer, Pad + 8);
+
+   for (Index = 0; Index < 5; Index++)
+      Result[Index] = DWORD2BE(Context->State[Index]);
+
+   A_SHAInit(Context);
+}
index 574c29c..7120723 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: makefile,v 1.42 2004/08/15 17:03:14 chorns Exp $
+# $Id: makefile,v 1.43 2004/12/11 00:21:33 weiden Exp $
 
 PATH_TO_TOP = ../..
 
@@ -13,10 +13,18 @@ TARGET_CFLAGS = -Wall -Werror -fno-builtin -D__USE_W32API
 
 TARGET_LFLAGS = -nostartfiles -nostdlib
 
-TARGET_SDKLIBS = ntdll.a kernel32.a
+TARGET_SDKLIBS = wine.a ntdll.a kernel32.a
 
 TARGET_BASE = $(TARGET_BASE_LIB_ADVAPI32)
 
+CRYPT_OBJECTS = \
+       crypt/crypt_des.o \
+       crypt/crypt_lmhash.o \
+       crypt/crypt_md4.o \
+       crypt/crypt_md5.o \
+       crypt/crypt_sha.o \
+       crypt/crypt.o
+
 MISC_OBJECTS = \
        misc/dllmain.o \
        misc/hwprofiles.o \
@@ -33,7 +41,8 @@ SECURITY_OBJECTS = \
        sec/lsa.o \
        sec/misc.o \
        sec/sec.o \
-       sec/sid.o
+       sec/sid.o \
+       sec/trustee.o
 
 SERVICE_OBJECTS = \
        service/eventlog.o \
@@ -46,6 +55,7 @@ TOKEN_OBJECTS = \
        token/token.o
 
 TARGET_OBJECTS = \
+       $(CRYPT_OBJECTS) \
        $(MISC_OBJECTS) \
        $(REGISTRY_OBJECTS) \
        $(SECURITY_OBJECTS) \
index e6c09a5..bb2cb09 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sysfunc.c,v 1.8 2004/08/15 17:03:14 chorns Exp $
+/* $Id: sysfunc.c,v 1.9 2004/12/11 00:21:33 weiden Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -77,20 +77,6 @@ SystemFunction005(INT a, INT b, INT c)
        return 5;
 }
 
-
-/**********************************************************************
- *
- * @unimplemented
- */
-INT
-STDCALL
-SystemFunction006(INT a, INT b)
-{
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return 6;
-}
-
-
 /**********************************************************************
  *
  * @unimplemented
diff --git a/reactos/lib/advapi32/sec/trustee.c b/reactos/lib/advapi32/sec/trustee.c
new file mode 100644 (file)
index 0000000..61402fa
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id: trustee.c,v 1.1 2004/12/11 00:21:33 weiden Exp $
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * FILE:            lib/advapi32/sec/ac.c
+ * PURPOSE:         ACL/ACE functions
+ */
+
+#include "advapi32.h"
+
+#include "wine/debug.h"
+
+
+/******************************************************************************
+ * BuildTrusteeWithSidA [ADVAPI32.@]
+ */
+VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
+{
+    DPRINT("%p %p\n", pTrustee, pSid);
+
+    pTrustee->pMultipleTrustee = NULL;
+    pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+    pTrustee->TrusteeForm = TRUSTEE_IS_SID;
+    pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
+    pTrustee->ptstrName = (LPSTR) pSid;
+}
+
+/******************************************************************************
+ * BuildTrusteeWithSidW [ADVAPI32.@]
+ */
+VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
+{
+    DPRINT("%p %p\n", pTrustee, pSid);
+
+    pTrustee->pMultipleTrustee = NULL;
+    pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+    pTrustee->TrusteeForm = TRUSTEE_IS_SID;
+    pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
+    pTrustee->ptstrName = (LPWSTR) pSid;
+}
+
+/******************************************************************************
+ * BuildTrusteeWithNameA [ADVAPI32.@]
+ */
+VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
+{
+    DPRINT("%p %s\n", pTrustee, debugstr_a(name) );
+
+    pTrustee->pMultipleTrustee = NULL;
+    pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+    pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
+    pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
+    pTrustee->ptstrName = name;
+}
+
+/******************************************************************************
+ * BuildTrusteeWithNameW [ADVAPI32.@]
+ */
+VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
+{
+    DPRINT("%p %s\n", pTrustee, debugstr_w(name) );
+
+    pTrustee->pMultipleTrustee = NULL;
+    pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+    pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
+    pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
+    pTrustee->ptstrName = name;
+}
index 3374d02..42f6fee 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: token.c,v 1.15 2004/12/10 16:50:37 navaraf Exp $
+/* $Id: token.c,v 1.16 2004/12/11 00:21:33 weiden Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -259,15 +259,9 @@ DuplicateTokenEx (HANDLE ExistingTokenHandle,
                   PHANDLE DuplicateTokenHandle)
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
-  SECURITY_QUALITY_OF_SERVICE Qos;
   HANDLE NewToken;
   NTSTATUS Status;
 
-  Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
-  Qos.ImpersonationLevel = ImpersonationLevel;
-  Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
-  Qos.EffectiveOnly = FALSE;
-
   ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
   ObjectAttributes.RootDirectory = NULL;
   ObjectAttributes.ObjectName = NULL;
@@ -277,12 +271,12 @@ DuplicateTokenEx (HANDLE ExistingTokenHandle,
       ObjectAttributes.Attributes |= OBJ_INHERIT;
     }
   ObjectAttributes.SecurityDescriptor = lpTokenAttributes->lpSecurityDescriptor;
-  ObjectAttributes.SecurityQualityOfService = &Qos;
+  ObjectAttributes.SecurityQualityOfService = NULL;
 
   Status = NtDuplicateToken (ExistingTokenHandle,
                             dwDesiredAccess,
                             &ObjectAttributes,
-                            FALSE,
+                            ImpersonationLevel,
                             TokenType,
                             &NewToken);
   if (!NT_SUCCESS(Status))