Windows NT 4 Source Compiled! version 2

Discuss Windows 2000, NT, XP and Windows Server 2000, 2003, SBS 2003.
yourepicfailure
User avatar
Donator
Posts: 1232
Joined: Mon Jul 23, 2012 9:40 pm
Location: Flying high in a DC10

Re: Windows NT 4 Source Compiled! version 2

Post by yourepicfailure »

Progman.exe
I'm resetting my copy of the repo, but the one warning I recieved said "No resource version set on progman.exe" or something like that.
And when I start my computer, I get an error that says "Windows Resource Compiler has encountered an error and needs to close". Related? probably.
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
You will never tear me from the Pentium M.

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

yourepicfailure wrote:Progman.exe
I'm resetting my copy of the repo, but the one warning I recieved said "No resource version set on progman.exe" or something like that.
And when I start my computer, I get an error that says "Windows Resource Compiler has encountered an error and needs to close". Related? probably.
I recall progman.exe having resource file (.res) corruption issue if you keep building without -c. Never had rc.exe catastrophically failing though.
Either way, if it's a progman.exe res corruption issue, it can be simply solved by doing build -c on progman directory.

Also check out zTESTBUILD.cmd under nt\private. I added the compilation process for most working components and it also handles some minor issues (including progman.exe res corruption).

yourepicfailure
User avatar
Donator
Posts: 1232
Joined: Mon Jul 23, 2012 9:40 pm
Location: Flying high in a DC10

Re: Windows NT 4 Source Compiled! version 2

Post by yourepicfailure »

I did a -c. I recall errors from shell32.lib, progmn.tmp, and, progmn.res.
Like I said, I can't figure out how it worked with -z last week and now it won't.
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
You will never tear me from the Pentium M.

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

yourepicfailure wrote:I did a -c. I recall errors from shell32.lib, progmn.tmp, and, progmn.res.
Like I said, I can't figure out how it worked with -z last week and now it won't.
Try deleting all unrevisioned files in your repo and build using zTESTBUILD. There's nothing wrong with the source base. It's a problem with your repo. I just confirmed that everything builds successfully.

yourepicfailure
User avatar
Donator
Posts: 1232
Joined: Mon Jul 23, 2012 9:40 pm
Location: Flying high in a DC10

Re: Windows NT 4 Source Compiled! version 2

Post by yourepicfailure »

I just cleaned up W: drive. Re-downloading repo...
EDIT: After redownload, issue is still present.
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
You will never tear me from the Pentium M.

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

yourepicfailure wrote:I just cleaned up W: drive. Re-downloading repo...
EDIT: After redownload, issue is still present.
Come onto the IRC channel so that we can have more direct communication.

EDIT: I see that you came on the IRC channel and exited. Have you solved your build problem?

yourepicfailure
User avatar
Donator
Posts: 1232
Joined: Mon Jul 23, 2012 9:40 pm
Location: Flying high in a DC10

Re: Windows NT 4 Source Compiled! version 2

Post by yourepicfailure »

Stephanos wrote:
yourepicfailure wrote:EDIT: I see that you came on the IRC channel and exited. Have you solved your build problem?
Yes, and you may want to take a peek at the resource files in your repo. Make sure they're not corrupt. Replacing the progman folder with the one present on BA's FTP properly compiles and runs. More specifically, replacing the .rc file.
Image
Take a look at the timestamps, and my (incorrect) current time. Programs were compile 2 minutes before the snapshot was taken.
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
You will never tear me from the Pentium M.

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

yourepicfailure wrote:
Stephanos wrote:
yourepicfailure wrote:EDIT: I see that you came on the IRC channel and exited. Have you solved your build problem?
Yes, and you may want to take a peek at the resource files in your repo. Make sure they're not corrupt. Replacing the progman folder with the one present on BA's FTP properly compiles and runs. More specifically, replacing the .rc file.
Image
Take a look at the timestamps, and my (incorrect) current time. Programs were compile 2 minutes before the snapshot was taken.
I don't see why progman fails to compile on your VM. I have three separate VMs (IDW1, IDW2, IDW3) and progman successfully compiles on all three of them.

Image

Once again, there's nothing wrong with the files on the repository. Either your build environment is faulty or you're building it through unsupported methods. As you can see in the screenshot, I'm building progman in x86tst environment (and x86fre should also work just fine). What build conf were you using?

In addition, there has been no change to progmn.rc since the day 1 this repository was created.

Image

progmn.rc cannot be the problem.

Afterthought: Since you replaced your progman directory and it successfully compiled, the likely cause is because you deleted "obj" directory in the process; in particular, obj\i386\progmn.res. This file should be deleted if you perform build -c, but I suppose, for whatever reason, it failed to do so. For your reference, obj directory is not a part of the repo (it is created during the build process) and this is why I told you earlier to get rid of all unversioned files on your repo (which will delete all obj directories).
Last edited by Stephanos on Mon Jan 19, 2015 4:04 pm, edited 1 time in total.

yourepicfailure
User avatar
Donator
Posts: 1232
Joined: Mon Jul 23, 2012 9:40 pm
Location: Flying high in a DC10

Re: Windows NT 4 Source Compiled! version 2

Post by yourepicfailure »

First fre, then tst, then chk. All failed with different results. This isn't a VM, it's a real computer.
Somewhere along the line, the files got corrupt through transfer. I'll see about doing an MD5, SHA1 compare between the files in the repo and the ones from BA FTP.
I'll also check other files for issues as well.
Wait, look at the warning log or run progman.

EDIT: If it's not the .rc, then what is? And you shouldn't be getting a warning, as mine compiles warning and error free.
EDIT2: Only fre compile warning and error free. Chk and TST compile with an error related to vc40.pbd(not essential) and a warning related to cvpack(not essential either, related to the vc40 issue)
Image
Here's what the three look like when they compile a runnable excecutable.

EDIT3: .Res files don't match up, but the .rc files do.
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
You will never tear me from the Pentium M.

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

Update: nt\private\windows\shell\progman was missing icons\objects directory containing ico files required to produce the res file. For whatever reason, rc didn't report any explicit error messages and was "silently" failing, causing that warning during the binplace process. This issue is now resolved.

Code: Select all

[10:02:18] <yourepicfailure> Something whacky's with progman stephanos then
[10:17:08] <csrss> yourepicfailure: yea. I'm looking into it right now. the warning is "binplace() : warning BNP0000: no version resource detected for "W:\nt\private\windows\shell\progman\obj\i386\progman.exe"
[10:17:17] <csrss> and progman.exe doesn't run
[10:17:23] <yourepicfailure> Which is the error I revieved.
[10:17:30] <yourepicfailure> *recieved
[10:17:51] <yourepicfailure> Does progman run?
[10:17:53] <csrss> there's definitely something wrong with the build process of progman.exe (from the original src)
[10:18:10] <csrss> no. progman doesn't run. if I click it, it doesn't do anything.
[10:18:27] <csrss> I'm build -c-ing from windows\shell and trying to see if this solves anything
[10:18:36] <yourepicfailure> Doesn't solve anything
[10:18:46] <csrss> it might be some other components that progman.exe is dependent on is corrupted
[10:19:02] <yourepicfailure> The only errors you should be getting are vc errors, not binplace errors
[10:19:36] <csrss> vc40.pdb error is because you didn't compile that port1632 component
[10:19:47] <csrss> try "build" from private\windows
[10:20:32] <yourepicfailure> But progman still ran...
[10:20:43] <csrss> try build -c on that same repo again
[10:28:59] <yourepicfailure> just did a full compile on /private/windows. No errors or warnings on chk or tst.
[10:29:37] <csrss> yourepicfailure: does progman.exe on x86tst run?
[10:30:04] <yourepicfailure> yes
[10:30:25] <yourepicfailure> Using BA FTP's code, yes, yours, still no.
[10:31:10] <yourepicfailure> and so does chk
[10:31:16] <csrss> I don't know what BA's version is like, but I'll try replacing progman with my original and see if that solves anything
[10:32:21] <yourepicfailure> I still can't figure out how files are randomly corrupting, even though you haven't interacted with them.
[10:33:28] <csrss> yourepicfailure: ok, I've just confirmed that progman.exe compiles with 0 warning and runs fine with the original ver
[10:34:11] <csrss> this issue is specific to progman.exe. progman.exe had progmn.res corruption issue to begin with. never bothered identifying the problem though
[10:34:35] <csrss> I'm going to diff this original and current repo version and see what's different
[10:36:58] <csrss> yourepicfailure: nt\private\windows\shell\progman\icons directory was missing objects on the repository
[10:37:10] <csrss> while the original had objects directory.
[10:37:29] <csrss> with objects directory added to icons, it successfully compile
[10:37:30] <csrss> s
[10:38:00] <yourepicfailure> it does
[10:38:09] <yourepicfailure> and runs
[10:38:20] <csrss> it seems like rc failed to successfully compile without all the files in icons\objects (a bunch of ico files to be included into res). still strange why rc didn't report any explicit error msgs
[10:38:34] <csrss> either way, I'll commit the objects dir to the repo and it should be fine from now on
[10:39:21] <csrss> in terms of other files, nothing different. our current repo was just missing icons\objects directory.
[10:39:47] <yourepicfailure> Glad that's fixed. Anything you need me to work on?
[10:40:58] <csrss> SVN Update: progman.exe was missing icons\objects directory. It is now added
[10:41:24] <csrss> yourepicfailure: it would be great if you could look into \nt\private\net and inet compilation issues
[10:41:41] <yourepicfailure> Alright
[10:42:26] <csrss> thanks for reporting the issue :D

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

OpenNT - NT 4.5 Project
opennt.net


SVN Repository Access (Guest):
- Address: https://svn.opennt.net/svn/NT45
- Username: SVNGuest
- Password: svnguest

FTP File Server Access (Guest):
- FTP Address: ftp://ftp.opennt.net
- Web Address: http://ftp.opennt.net
- Username/Password: Anonymous
* TLS/SSL supported

IRC Chat: Freenode ##NT4Dev

the_dj21
FTP Access
Posts: 111
Joined: Sun Jul 20, 2014 7:33 pm

Re: Windows NT 4 Source Compiled! version 2

Post by the_dj21 »

Amazing Stephanos
Windows 10 will be the last version of Windows and after we will have Midori or an another kernel... I'm sure.

So on this new kernel "classic win32 x86 software" can't be used but with some trick, we can use WinRT software on this new kernel ?

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

IMPORTANT NOTICE!

\nt\public\sdk is no longer a part of the main NT45 repository. It has been moved to a separate repository named NT45-sdk and will be separately versioned from now on. All developers must manually create an sdk directory under their local repository \nt\public directory and checkout NT45-sdk repository.


OltScript131
User avatar
FTP Access
Posts: 255
Joined: Sat Sep 10, 2011 9:46 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by OltScript131 »

I do not manage to compile.... :cry:
I have no feasible.....

Use Visual C++ 1.xx ??? :)

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

Jajan131 wrote:I do not manage to compile.... :cry:
I have no feasible.....

Use Visual C++ 1.xx ??? :)
You are supposed to initialise the Razzle environment with MSVC2k. This is done automatically if you properly set up the build environment as shown throughout this thread and launch zSH***.cmd. Test component builds can be performed using zTESTBUILD.cmd inside Razzle.

In short, in order to build,
1. check out the NT45 repository on your W drive (create one).
2. check out the NT45-sdk repository on W:\nt\public\sdk
3. launch W:\nt\private\zSH***.cmd
4. launch W:\nt\private\zTESTBUILD.cmd and follow instructions

Recommended build host OS is Windows Server 2003 (32-bit), but NT 4 and 2000 should also work just fine.

I will be publishing the full build guide soon (within a few days to weeks ... depending on how busy I am with other stuff). For now, if you cannot figure out how to build with the info I provided above, please wait until the full guide is published.

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

Update 2015-01-24:
ADVAPI32 Microsoft Cryptography API (nt\private\windows\base\advapi\cryptapi.c) implementation first phase complete- all version 1 API functions implemented except CryptSetProvider(W/A). The ADVAPI32.DLL built with the new cryptography API implementation is verified to be functional.

Code: Select all

/*++

Copyright (c) 2015  Microsoft Corporation

Module Name:

    cryptapi.c

Abstract:

    This module implements the Microsoft Cryptography API.

Author:

    Stephanos Io (Stephanos) 15-Jan-2015

Environment:

    User-mode only.

Revision History:

--*/

#pragma warning(disable:4245)

#ifndef UNICODE
#define UNICODE
#endif

#ifndef _UNICODE
#define _UNICODE
#endif

#include <windows.h>
#include <wincrypt.h>

//
// Constant Definition
//

#define REGPATH_CRYPTOGRAPHY    L"Software\\Microsoft\\Cryptography"
#define REGPATH_MACHINEDEFAULT  REGPATH_CRYPTOGRAPHY    \
                                L"\\Defaults\\Provider Types\\Type "
#define REGPATH_USERDEFAULT     REGPATH_CRYPTOGRAPHY    \
                                L"\\Provider Type "
#define REGPATH_PROVIDER        REGPATH_CRYPTOGRAPHY    \
                                L"\\Defaults\\Provider\\"

//
// Structure Definition
//

typedef struct _VTableStruc
{
    // Context Information
    HMODULE         hModule;        // Handle to loaded provider image module
    HCRYPTPROV      hProv;          // Handle to provider
    LONG            InUse;          // Concurrent usage count

    // Provider Functions
    BOOL (WINAPI *CPAcquireContext)(
        OUT     HCRYPTPROV *phUID,
        IN      CHAR *pUserID,
        IN      DWORD dwFlags,
        IN      PVTableProvStruc pVTable
        );

    BOOL (WINAPI *CPReleaseContext)(
        IN      HCRYPTPROV hProv,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPGenKey)(
        IN      HCRYPTPROV hProv,
        IN      ALG_ID Algid,
        IN      DWORD dwFlags,
        OUT     HCRYPTKEY *phKey
        );

    BOOL (WINAPI *CPDeriveKey)(
        IN      HCRYPTPROV hProv,
        IN      ALG_ID Algid,
        IN      HCRYPTHASH hBaseData,
        IN      DWORD dwFlags,
        OUT     HCRYPTKEY *phKey
        );

    BOOL (WINAPI *CPDestroyKey)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTKEY hKey
        );

    BOOL (WINAPI *CPSetKeyParam)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTKEY hKey,
        IN      DWORD dwParam,
        IN      BYTE *pbData,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPGetKeyParam)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTKEY hKey,
        IN      DWORD dwParam,
        OUT     BYTE *pbData,
        IN      DWORD *pdwDataLen,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPSetHashParam)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTHASH hHash,
        IN      DWORD dwParam,
        IN      BYTE *pbData,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPGetHashParam)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTHASH hHash,
        IN      DWORD dwParam,
        OUT     BYTE *pbData,
        IN      DWORD *pdwDataLen,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPSetProvParam)(
        IN      HCRYPTPROV hProv,
        IN      DWORD dwParam,
        IN      BYTE *pbData,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPGetProvParam)(
        IN      HCRYPTPROV hProv,
        IN      DWORD dwParam,
        OUT     BYTE *pbData,
        IN OUT  DWORD *pdwDataLen,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPGenRandom)(
        IN      HCRYPTPROV hProv,
        IN      DWORD dwLen,
        IN OUT  BYTE *pbBuffer
        );

    BOOL (WINAPI *CPGetUserKey)(
        IN      HCRYPTPROV hProv,
        IN      DWORD dwKeySpec,
        OUT     HCRYPTKEY *phUserKey
        );

    BOOL (WINAPI *CPExportKey)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTKEY hKey,
        IN      HCRYPTKEY hPubKey,
        IN      DWORD dwBlobType,
        IN      DWORD dwFlags,
        OUT     BYTE *pbData,
        IN OUT  DWORD *pdwDataLen
        );

    BOOL (WINAPI *CPImportKey)(
        IN      HCRYPTPROV hProv,
        IN      CONST BYTE *pbData,
        IN      DWORD dwDataLen,
        IN      HCRYPTKEY hPubKey,
        IN      DWORD dwFlags,
        OUT     HCRYPTKEY *phKey
        );

    BOOL (WINAPI *CPEncrypt)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTKEY hKey,
        IN      HCRYPTHASH hHash,
        IN      BOOL Final,
        IN      DWORD dwFlags,
        IN OUT  BYTE *pbData,
        IN OUT  DWORD *pdwDataLen,
        IN      DWORD dwBufLen
        );

    BOOL (WINAPI *CPDecrypt)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTKEY hKey,
        IN      HCRYPTHASH hHash,
        IN      BOOL Final,
        IN      DWORD dwFlags,
        IN OUT  BYTE *pbData,
        IN OUT  DWORD *pdwDataLen
        );

    BOOL (WINAPI *CPCreateHash)(
        IN      HCRYPTPROV hProv,
        IN      ALG_ID Algid,
        IN      HCRYPTKEY hKey,
        IN      DWORD dwFlags,
        OUT     HCRYPTHASH *phHash
        );

    BOOL (WINAPI *CPHashData)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTHASH hHash,
        IN      CONST BYTE *pbData,
        IN      DWORD dwDataLen,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPHashSessionKey)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTHASH hHash,
        IN      HCRYPTKEY hKey,
        IN      DWORD dwFlags
        );

    BOOL (WINAPI *CPDestroyHash)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTHASH hHash
        );

    BOOL (WINAPI *CPSignHash)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTHASH hHash,
        IN      DWORD dwKeySpec,
        IN      LPCWSTR sDescription,
        IN      DWORD dwFlags,
        OUT     BYTE *pbSignature,
        IN OUT  DWORD *pdwSigLen
        );

    BOOL (WINAPI *CPVerifySignature)(
        IN      HCRYPTPROV hProv,
        IN      HCRYPTHASH hHash,
        IN      CONST BYTE *pbSignature,
        IN      DWORD dwSigLen,
        IN      HCRYPTKEY hPubKey,
        IN      LPCWSTR sDescription,
        IN      DWORD dwFlags
        );
} VTableStruc, *PVTableStruc;

typedef struct _VKeyStruc
{
    PVTableStruc    pVTable;        // Pointer to private handle struc
    HCRYPTKEY       hKey;           // Handle to key
} VKeyStruc, *PVKeyStruc;

typedef struct _VHashStruc
{
    PVTableStruc    pVTable;        // Pointer to private handle struc
    HCRYPTHASH      hHash;          // Handle to hash
} VHashStruc, *PVHashStruc;

//
// Private Function Prototype
//

PSTR
UnicodeToMultiByte(
    IN PCWSTR UnicodeString,
    IN UINT   Codepage
    );

PWSTR
MultiByteToUnicode(
    IN PCSTR String,
    IN UINT  Codepage
    );

//
// Public Interface Function
//

/*
 -  CryptAcquireContext
 -
 *  Purpose:
 *              The CryptAcquireContext function is used to acquire a handle
 *              to a particular key container within a particular Cryptographic
 *              Service Provider (CSP).
 *
 *
 *  Parameters:
 *              OUT     phProv       - A pointer to a handle of a CSP
 *              IN      pszContainer - The key container name
 *              IN      pszProvider  - A null-terminated string that contains
 *                                     the name of the CSP to be used
 *              IN      dwProvType   - Specifies the type of provider to acquire
 *              IN      dwFlags      - Flag values
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

#define GetProvProcAddress(ProcName)                                        \
    pVTable->##ProcName = (PVOID)                                           \
                          GetProcAddress(pVTable->hModule, #ProcName);      \
    if (pVTable->##ProcName == NULL)                                        \
    {                                                                       \
        FreeLibrary(pVTable->hModule);                                      \
        LocalFree(pVTable);                                                 \
        SetLastError(NTE_PROVIDER_DLL_FAIL);                                \
        return FALSE;                                                       \
    }

WINADVAPI
BOOL
WINAPI
CryptAcquireContextW(
    OUT  HCRYPTPROV *phProv,
    IN   LPCWSTR pszContainer,
    IN   LPCWSTR pszProvider,
    IN   DWORD dwProvType,
    IN   DWORD dwFlags)
{
    PVTableStruc    pVTable = NULL;
    VTableProvStruc TableForProvider;
    PSTR            pszContainerA;
    PWSTR           ProvName = NULL;
    DWORD           ProvType;
    PWSTR           ProvImagePath = NULL, ProvImageFullPath = NULL;
    DWORD           ProvImageFullPathLen;
    PWSTR           RegKeyPath = NULL;
    HKEY            hRegKey = NULL;
    DWORD           RegType, RegLen;
    LONG            Status = FALSE;
    BOOL            Ret;

    //
    // Verify parameters
    //
    
    if (phProv == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Resolve the cryptographic service provider name
    //
    
    if (pszProvider == NULL || pszProvider[0] == '\0')
    // No specific provider name is provided
    {
        //
        // Look for the user default CSP
        //
        
        RegKeyPath = LocalAlloc(
                        LMEM_FIXED,
                        sizeof(REGPATH_USERDEFAULT) +
                        3 * sizeof(WCHAR)
                        );
        
        if (RegKeyPath == NULL)
            return FALSE;

        wsprintf(
            RegKeyPath,
            L"%s%03u",
            REGPATH_USERDEFAULT,
            dwProvType
            );
        
        Status = RegOpenKeyW(
                    HKEY_CURRENT_USER,
                    RegKeyPath,
                    &hRegKey
                    );

        LocalFree(RegKeyPath);
        
        if (Status != ERROR_SUCCESS)
        // No user default CSP found
        {
            RegCloseKey(hRegKey);
            
            //
            // Look for the machine default CSP
            //
            
            RegKeyPath = LocalAlloc(
                            LMEM_FIXED,
                            sizeof(REGPATH_MACHINEDEFAULT) +
                            3 * sizeof(WCHAR)
                            );
            
            if (RegKeyPath == NULL)
                return FALSE;
            
            wsprintf(
                RegKeyPath,
                L"%s%03u",
                REGPATH_MACHINEDEFAULT,
                dwProvType
                );
            
            Status = RegOpenKeyW(
                        HKEY_LOCAL_MACHINE,
                        RegKeyPath,
                        &hRegKey
                        );

            LocalFree(RegKeyPath);
            
            if (Status != ERROR_SUCCESS)
            // No machine default CSP found
            {
                RegCloseKey(hRegKey);
                SetLastError(NTE_PROV_TYPE_NOT_DEF);
                return FALSE;
            }
        }
        
        //
        // Query and verify the provider Name value type
        //
        
        Status = RegQueryValueExW(
                            hRegKey,
                            L"Name",
                            NULL,
                            &RegType,
                            NULL,
                            &RegLen
                            );
        
        if (Status != ERROR_SUCCESS ||
            RegLen == 0 ||
            RegType != REG_SZ)
        // Query failed or invalid Name value type/length
        {
            RegCloseKey(hRegKey);
            SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
            return FALSE;
        }
        
        //
        // Query the provider Name value
        //
        
        ProvName = LocalAlloc(
                    LMEM_FIXED,
                    RegLen);
        
        if (ProvName == NULL)
        {
            RegCloseKey(hRegKey);
            return FALSE;
        }
        
        Status = RegQueryValueExW(
                            hRegKey,
                            L"Name",
                            NULL,
                            NULL,
                            (LPBYTE)ProvName,
                            &RegLen);
        
        if (Status != ERROR_SUCCESS)
        {
            RegCloseKey(hRegKey);
            LocalFree(ProvName);
            SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
            return FALSE;
        }
        
        RegCloseKey(hRegKey);
    }
    else
    // Provider name is provided
    {
        ProvName = LocalAlloc(
                            LMEM_FIXED,
                            (wcslen(pszProvider) + 1) * sizeof(WCHAR)
                            );
                            
        if (ProvName == NULL)
            return FALSE;
        
        wcscpy(ProvName, pszProvider);
    }

    //
    // Open the provider registry key
    //
    
    RegKeyPath = LocalAlloc(
                        LMEM_FIXED,
                        sizeof(REGPATH_PROVIDER) +
                        wcslen(ProvName) * sizeof(WCHAR)
                        );
    
    if (RegKeyPath == NULL)
    {
        LocalFree(ProvName);
        return FALSE;
    }

    wsprintf(
        RegKeyPath,
        L"%s%s",
        REGPATH_PROVIDER,
        ProvName
        );
    
    Status = RegOpenKeyW(
                HKEY_LOCAL_MACHINE,
                RegKeyPath,
                &hRegKey
                );
    
    LocalFree(ProvName);
    LocalFree(RegKeyPath);

    if (Status != ERROR_SUCCESS)
    {
        RegCloseKey(hRegKey);
        SetLastError(NTE_KEYSET_NOT_DEF);
        return FALSE;
    }

    //
    // Resolve and verify the cryptographic service provider type
    //

    RegLen = sizeof(ProvType);
    Status = RegQueryValueExW(
                        hRegKey,
                        L"Type",
                        NULL,
                        NULL,
                        (LPBYTE)&ProvType,
                        &RegLen
                        );
    
    if (Status != ERROR_SUCCESS)
    {
        RegCloseKey(hRegKey);
        return FALSE;
    }

    if (ProvType != dwProvType)
    {
        RegCloseKey(hRegKey);
        SetLastError(NTE_PROV_TYPE_NO_MATCH);
        return FALSE;
    }

    //
    // Resolve the cryptographic service provider image path
    //

    Status = RegQueryValueExW(
                        hRegKey,
                        L"Image Path",
                        NULL,
                        &RegType,
                        NULL,
                        &RegLen
                        );

    if (Status != ERROR_SUCCESS ||
        RegLen == 0 ||
        RegType != REG_SZ)
    {
        RegCloseKey(hRegKey);
        SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
        return FALSE;
    }

    ProvImagePath = LocalAlloc(
                        LMEM_FIXED,
                        RegLen
                        );

    if (ProvImagePath == NULL)
    {
        RegCloseKey(hRegKey);
        return FALSE;
    }

    Status = RegQueryValueExW(
                        hRegKey,
                        L"Image Path",
                        NULL,
                        NULL,
                        (LPBYTE)ProvImagePath,
                        &RegLen
                        );

    RegCloseKey(hRegKey);

    if (Status != ERROR_SUCCESS ||
        ProvImagePath[0] == '\0')
    {
        LocalFree(ProvImagePath);
        return FALSE;
    }

    //
    // Resolve any environment variable references in the cryptographic service
    // provider image path registry value
    //

    ProvImageFullPathLen =
        ExpandEnvironmentStringsW(
                            ProvImagePath,
                            NULL,
                            0
                            );

    ProvImageFullPath = LocalAlloc(
                            LMEM_FIXED,
                            ProvImageFullPathLen
                            );

    if (ProvImageFullPath == NULL)
    {
        LocalFree(ProvImagePath);
        return FALSE;
    }

    Status =
        ExpandEnvironmentStringsW(
                            ProvImagePath,
                            ProvImageFullPath,
                            ProvImageFullPathLen
                            );

    LocalFree(ProvImagePath);

    if (Status == 0)
    {
        LocalFree(ProvImageFullPath);
        return FALSE;
    }

    //
    // Allocate handle struct
    //
    
    pVTable = (PVTableStruc)LocalAlloc(
                                LMEM_ZEROINIT,
                                sizeof(VTableStruc)
                                );

    if (pVTable == NULL)
    {
        LocalFree(ProvImageFullPath);
        return FALSE;
    }

    //
    // Load the cryptographic service provider image
    //

    pVTable->hModule = LoadLibraryW(ProvImageFullPath);

    LocalFree(ProvImageFullPath);

    if (pVTable->hModule == NULL)
    // Failed to load the CSP image
    {
        LocalFree(pVTable);

        switch (GetLastError())
        // Translate the LoadLibrary error code to AcquireContext equivalent
        {
            case ERROR_FILE_NOT_FOUND:
                SetLastError(NTE_PROV_DLL_NOT_FOUND);
                break;
            default:
                SetLastError(NTE_PROVIDER_DLL_FAIL);
                break;
        }
        
        return FALSE;
    }

    //
    // Resolve the cryptographic service provider function addresses
    //

    GetProvProcAddress(CPAcquireContext);
    GetProvProcAddress(CPReleaseContext);
    GetProvProcAddress(CPGenKey);
    GetProvProcAddress(CPDeriveKey);
    GetProvProcAddress(CPDestroyKey);
    GetProvProcAddress(CPSetKeyParam);
    GetProvProcAddress(CPGetKeyParam);
    GetProvProcAddress(CPSetHashParam);
    GetProvProcAddress(CPGetHashParam);
    GetProvProcAddress(CPSetProvParam);
    GetProvProcAddress(CPGetProvParam);
    GetProvProcAddress(CPGenRandom);
    GetProvProcAddress(CPGetUserKey);
    GetProvProcAddress(CPExportKey);
    GetProvProcAddress(CPImportKey);
    GetProvProcAddress(CPEncrypt);
    GetProvProcAddress(CPDecrypt);
    GetProvProcAddress(CPCreateHash);
    GetProvProcAddress(CPHashData);
    GetProvProcAddress(CPHashSessionKey);
    GetProvProcAddress(CPDestroyHash);
    GetProvProcAddress(CPSignHash);
    GetProvProcAddress(CPVerifySignature);

    //
    // Convert the container string
    //

    if (pszContainer != NULL)
    // pszContainer is provided, convert it to ANSI string for the CSP  
    {
        pszContainerA = UnicodeToMultiByte(pszContainer, CP_ACP);

        if (pszContainerA == NULL)
        {
            FreeLibrary(pVTable->hModule);
            LocalFree(pVTable);
            return FALSE;
        }
    }
    else
    // No pszContainer is provided, simply pass NULL to the CSP    
        pszContainerA = NULL;

    //
    // Initialise the provider table
    //
    
    memset(&TableForProvider, 0, sizeof(TableForProvider));
    TableForProvider.Version = 1;
    TableForProvider.FuncVerifyImage = NULL;
    TableForProvider.FuncReturnhWnd = NULL;

    //
    // Call provider AcquireContext function
    //
    
    __try
    {
        Status = pVTable->CPAcquireContext(
                                &pVTable->hProv,
                                pszContainerA,
                                dwFlags,
                                &TableForProvider
                                );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Status = FALSE;
    }

    if (Status == FALSE)
    // CPAcquireContext function failed
    {
        FreeLibrary(pVTable->hModule);
        LocalFree(pVTable);
        LocalFree(pszContainerA);
        return FALSE;
    }

    //
    // Check if CRYPT_DELETEKEYSET is set; if set, the private handle is to be
    // deallocated and a NULL pointer is to be set on phProv
    //

    if (dwFlags & CRYPT_DELETEKEYSET)
    {
        FreeLibrary(pVTable->hModule);
        LocalFree(pVTable);
        pVTable = NULL;
    }
    else
        pVTable->InUse = 1;
    
    //
    // Update phProv
    //
    
    *phProv = (HCRYPTPROV)pVTable;

    //
    // Clean up
    //

    LocalFree(pszContainerA);

    return TRUE;
}

WINADVAPI
BOOL
WINAPI
CryptAcquireContextA(
    OUT  HCRYPTPROV *phProv,
    IN   LPCSTR pszContainer,
    IN   LPCSTR pszProvider,
    IN   DWORD dwProvType,
    IN   DWORD dwFlags)
{
    PWSTR   pszContainerW;
    PWSTR   pszProviderW;
    BOOL    Ret;

    //
    // Convert pszContainer
    //
    
    if (pszContainer != NULL)
    {
        pszContainerW = MultiByteToUnicode(pszContainer, CP_ACP);

        if (pszContainerW == NULL)
            return FALSE;
    }
    else
        pszContainerW = NULL;

    //
    // Convert pszProvider
    //

    if (pszProvider != NULL)
    {
        pszProviderW = MultiByteToUnicode(pszProvider, CP_ACP);

        if (pszProviderW == NULL)
        {
            LocalFree(pszContainerW);
            return FALSE;
        }
    }
    else
        pszProviderW = NULL;

    //
    // Call unicode function
    //

    Ret = CryptAcquireContextW(
                        phProv,
                        pszContainerW,
                        pszProviderW,
                        dwProvType,
                        dwFlags
                        );

    //
    // Clean up
    //

    LocalFree(pszContainerW);
    LocalFree(pszProviderW);

    return Ret;
}


/*
 -  CryptReleaseContext
 -
 *  Purpose:
 *              The CryptReleaseContext function releases the handle of a
 *              Cryptographic Service Provider (CSP) and a key container.
 *
 *
 *  Parameters:
 *              IN      hProv    -  Handle of a cryptographic service provider
 *              IN      dwFlags  -  Reserved for future use and must be zero
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptReleaseContext(
    IN  HCRYPTPROV hProv,
    IN  DWORD dwFlags)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    LONG            UseCount;
    BOOL            Ret;

    //
    // Verify that the handle is not being used by any other threads
    //
    
    UseCount = InterlockedDecrement(&pVTable->InUse);

    if (UseCount != 0)
    // Handle is in use by another thread
    {
        SetLastError(ERROR_BUSY);
        InterlockedIncrement(&pVTable->InUse);
        return FALSE;
    }

    //
    // Invoke the cryptographic service provider ReleaseContext function
    //

    __try
    {
        Ret = pVTable->CPReleaseContext(pVTable->hProv, dwFlags);
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Unload the cryptographic service provider library image
    //

    FreeLibrary(pVTable->hModule);

    //
    // Deallocate the private handle struct
    //
    
    LocalFree(pVTable);
    
    return Ret;
}


/*
 -  CryptGenKey
 -
 *  Purpose:
 *              The CryptGenKey function generates a random cryptographic
 *              session key or a public/private key pair.
 *
 *
 *  Parameters:
 *              IN      hProv    -  Handle to a cryptographic service provider
 *              IN      Algid    -  An ALG_ID value that identifies the
 *                                  target algorithm for key generation
 *              IN      dwFlags  -  Specifies the type of key generated
 *              OUT     phKey    -  Adress to which the function copies the
 *                                  handle of the newly generated key
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptGenKey(
    IN  HCRYPTPROV hProv,
    IN  ALG_ID Algid,
    IN  DWORD dwFlags,
    OUT HCRYPTKEY *phKey)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    PVKeyStruc      pVKey;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (phKey == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Create a private key struc
    //

    pVKey = LocalAlloc(
                LMEM_ZEROINIT,
                sizeof(VKeyStruc)
                );

    if (pVKey == NULL)
        return FALSE;

    pVKey->pVTable = pVTable;

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider GenKey function
    //

    __try
    {
        Ret = pVTable->CPGenKey(
                            pVTable->hProv,
                            Algid,
                            dwFlags,
                            &pVKey->hKey
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage count
    //

    InterlockedDecrement(&pVTable->InUse);

    //
    // Set the return key handle
    //

    if (Ret == TRUE)
        *phKey = (HCRYPTKEY)pVKey;
    else
        LocalFree(pVKey);

    return Ret;
}


/*
 -  CryptDeriveKey
 -
 *  Purpose:
 *              The CryptDeriveKey function generates cryptographic session keys
 *              derived from a base data value.
 *
 *
 *  Parameters:
 *              IN      hProv     -  Handle of a cryptographic service provider
 *              IN      Algid     -  An ALG_ID structure that identifies the
 *                                   symmetric encryption algorithm for which
 *                                   the key is to be generated
 *              IN      hBaseData -  A handle to a hash object that has been fed
 *                                   the exact base data
 *              IN      dwFlags   -  Specifies the type of key generated
 *              IN OUT  phKey     -  A pointer to a HCRYPTKEY variable to
 *                                   receive the address of the handle of the
 *                                   newly generated key
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptDeriveKey(
    IN      HCRYPTPROV hProv,
    IN      ALG_ID Algid,
    IN      HCRYPTHASH hBaseData,
    IN      DWORD dwFlags,
    IN OUT  HCRYPTKEY *phKey)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    PVHashStruc     pVHash = (PVHashStruc)hBaseData;
    PVKeyStruc      pVKey;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (phKey == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    else if (pVHash->pVTable != pVTable)
    // Hash handle is not associated with the supplied provider handle
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Create a private key struc
    //

    pVKey = LocalAlloc(
                LMEM_ZEROINIT,
                sizeof(VKeyStruc)
                );

    if (pVKey == NULL)
        return FALSE;

    pVKey->pVTable = pVTable;

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider DeriveKey function
    //

    __try
    {
        Ret = pVTable->CPDeriveKey(
                            pVTable->hProv,
                            Algid,
                            pVHash->hHash,
                            dwFlags,
                            &pVKey->hKey
                            );
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage count
    //

    InterlockedDecrement(&pVTable->InUse);

    //
    // Set the return key handle
    //

    if (Ret == TRUE)
        *phKey = (HCRYPTKEY)pVKey;
    else
        LocalFree(pVKey);

    return Ret;
}


/*
 -  CryptDestroyKey
 -
 *  Purpose:
 *              The CryptDestroyKey function releases the handle referenced by
 *              the hKey parameter.
 *
 *
 *  Parameters:
 *              IN      hKey  -  The handle of the key to be destroyed
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptDestroyKey(IN  HCRYPTKEY hKey)
{
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVKey->pVTable;

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider DestroyKey function
    //

    __try
    {
        Ret = pVTable->CPDestroyKey(
                            pVTable->hProv,
                            pVKey->hKey
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage count
    //

    InterlockedDecrement(&pVTable->InUse);

    //
    // Deallocate the private key struc
    //

    LocalFree(pVKey);

    return Ret;
}


/*
 -  CryptSetKeyParam
 -
 *  Purpose:
 *              The CryptSetKeyParam function customises various aspects of a
 *              session key's operations.
 *
 *
 *  Parameters:
 *              IN      hKey     -  A handle to the key
 *              IN      dwParam  -  Key parameter type
 *              IN      pbData   -  A pointer to a buffer initialised with the
 *                                  value to be set
 *              IN      dwFlags  -  Used only when dwParam is KP_ALGID
 *
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptSetKeyParam(
    IN  HCRYPTKEY hKey,
    IN  DWORD dwParam,
    IN  BYTE *pbData,
    IN  DWORD dwFlags)
{
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVKey->pVTable;

    //
    // Validate parameters
    //

    if (pbData == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider SetKeyParam function
    //

    __try
    {
        Ret = pVTable->CPSetKeyParam(
                            pVTable->hProv,
                            pVKey->hKey,
                            dwParam,
                            pbData,
                            dwFlags
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage count
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;

}


/*
 -  CryptGetKeyParam
 -
 *  Purpose:
 *              The CryptGetKeyParam function retrieves data that governs the
 *              operations of a key.
 *
 *
 *  Parameters:
 *              IN      hKey       -  The handle of the key being queried
 *              IN      dwParam    -  Specifies the type of query being made
 *              OUT     pbData     -  A pointer to a receiving buffer
 *              IN OUT  pdwDataLen -  A pointer to a DWORD value that, on entry,
 *                                    contains the size of the buffer pointed to
 *                                    by the pbData parameter. When the function
 *                                    returns, the DWORD value contains the
 *                                    number of bytes stored in the buffer
 *              IN      dwFlags  -  Used only when dwParam is KP_ALGID
 *
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptGetKeyParam(
    IN      HCRYPTKEY hKey,
    IN      DWORD dwParam,
    OUT     BYTE *pbData,
    IN OUT  DWORD *pdwDataLen,
    IN      DWORD dwFlags)
{
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVKey->pVTable;

    //
    // Validate parameters
    //

    if (pbData == NULL || pdwDataLen == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider GetKeyParam function
    //

    __try
    {
        Ret = pVTable->CPGetKeyParam(
                            pVTable->hProv,
                            pVKey->hKey,
                            dwParam,
                            pbData,
                            pdwDataLen,
                            dwFlags
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptSetHashParam
 -
 *  Purpose:
 *              The CryptSetHashParam function customises the operation of a
 *              hash object, including setting up initial hash contexts and
 *              selecting a specific hashing algorithm.
 *
 *
 *  Parameters:
 *              IN      hHash    -  A handle to the target hash object
 *              IN      dwParam  -  Hash parameter type
 *              IN      pbData   -  A value data buffer
 *              IN      dwFlags  -  This parameter is reserved for future use
 *                                  and must be zero
 *
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptSetHashParam(
    IN  HCRYPTHASH hHash,
    IN  DWORD dwParam,
    IN  BYTE *pbData,
    IN  DWORD dwFlags)
{
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVHash->pVTable;

    //
    // Validate parameters
    //

    if (pbData == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider SetHashParam function
    //

    __try
    {
        Ret = pVTable->CPSetHashParam(
                            pVTable->hProv,
                            pVHash->hHash,
                            dwParam,
                            pbData,
                            dwFlags
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptGetHashParam
 -
 *  Purpose:
 *              The CryptGetHashParam function retrieves data that governs the
 *              operations of a hash object.
 *
 *
 *  Parameters:
 *              IN      hHash      -  Handle of the hash object to be queried
 *              IN      dwParam    -  Query type
 *              OUT     pbData     -  A pointer to a buffer that receives the
 *                                    specified value data
 *              IN OUT  pdwDataLen -  A pointer to a DWORD value specifying the
 *                                    size of the pbData buffer. When the
 *                                    function returns, the DWORD value contains
 *                                    the number of bytes stored in the buffer
 *              IN      dwFlags    -  Reserved for future use and must be zero
 *
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptGetHashParam(
    IN      HCRYPTHASH hHash,
    IN      DWORD dwParam,
    OUT     BYTE *pbData,
    IN OUT  DWORD *pdwDataLen,
    IN      DWORD dwFlags)
{
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVHash->pVTable;

    //
    // Validate parameters
    //

    if (pbData == NULL || pdwDataLen == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider GetHashParam function
    //

    __try
    {
        Ret = pVTable->CPGetHashParam(
                            pVTable->hProv,
                            pVHash->hHash,
                            dwParam,
                            pbData,
                            pdwDataLen,
                            dwFlags
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptSetProvParam
 -
 *  Purpose:
 *              The CryptSetProvParam function customises the operations of a
 *              Cryptographic Service Provider (CSP).
 *
 *
 *  Parameters:
 *              IN      hProv   -  The handle of a CSP for which to set values
 *              IN      dwParam -  Specifies the parameter to set
 *              IN      pbData  -  A pointer to a data buffer that contains the
 *                                 value to be set as a provider parameter
 *              IN      dwFlags -  Specifies the parameter-dependent flags
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptSetProvParam(
    IN  HCRYPTPROV hProv,
    IN  DWORD dwParam,
    IN  BYTE *pbData,
    IN  DWORD dwFlags)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (pbData == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider SetProvParam function
    //

    __try
    {
        Ret = pVTable->CPSetProvParam(
                            pVTable->hProv,
                            dwParam,
                            pbData,
                            dwFlags
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptGetProvParam
 -
 *  Purpose:
 *              The CryptGetProvParam function retrieves parameters that govern
 *              the operations of a Cryptographic Service Provider (CSP).
 *
 *
 *  Parameters:
 *              IN      hProv      -  A handle of the CSP target of the query  
 *              IN      dwParam    -  The nature of the query
 *              OUT     pbData     -  A pointer to a buffer to receive the data
 *              IN OUT  pdwDataLen -  A pointer to a DWORD value that specifies
 *                                    the size of the buffer pointed to by the
 *                                    pbData parameter
 *              IN      dwFlags    -  Specifies the parameter-dependent flags
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptGetProvParam(
    IN      HCRYPTPROV hProv,
    IN      DWORD dwParam,
    OUT     BYTE *pbData,
    IN OUT  DWORD *pdwDataLen,
    IN      DWORD dwFlags)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (pbData == NULL || pdwDataLen == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider GetProvParam function
    //

    __try
    {
        Ret = pVTable->CPGetProvParam(
                            pVTable->hProv,
                            dwParam,
                            pbData,
                            pdwDataLen,
                            dwFlags
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;

}


/*
 -  CryptGenRandom
 -
 *  Purpose:
 *              The CryptGenRandom function fills a buffer with
 *              cryptographically random bytes.
 *
 *
 *  Parameters:
 *              IN      hProv    -  Handle of a cryptographic service provider
 *              IN      dwLen    -  Number of bytes of random data to be
 *                                  generated
 *              IN OUT  pbBuffer -  Buffer to receive the returned data
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptGenRandom(
    IN      HCRYPTPROV hProv,
    IN      DWORD dwLen,
    IN OUT  BYTE *pbBuffer)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (pbBuffer == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider GenRandom function
    //

    __try
    {
        Ret = pVTable->CPGenRandom(
                            pVTable->hProv,
                            dwLen,
                            pbBuffer
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptGetUserKey
 -
 *  Purpose:
 *              The CryptGetUserKey function retrieves a handle of one of a
 *              user's two public/private key pairs.
 *
 *
 *  Parameters:
 *              IN      hProv     -  HCRYPTPROV handle of a CSP
 *              IN      dwKeySpec -  Identifies the private key to use from the
 *                                   key container
 *              OUT     phUserKey -  A pointer to the HCRYPTKEY handle of the
 *                                   retrieved keys
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptGetUserKey(
    IN  HCRYPTPROV hProv,
    IN  DWORD dwKeySpec,
    OUT HCRYPTKEY *phUserKey)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    PVKeyStruc      pVKey;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (phUserKey == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Create a private key struc
    //

    pVKey = LocalAlloc(
                LMEM_ZEROINIT,
                sizeof(VKeyStruc)
                );

    if (pVKey == NULL)
        return FALSE;

    pVKey->pVTable = pVTable;

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider GetUserKey function
    //

    __try
    {
        Ret = pVTable->CPGetUserKey(
                            pVTable->hProv,
                            dwKeySpec,
                            &pVKey->hKey
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    //
    // Set the return key handle
    //

    if (Ret == TRUE)
        *phUserKey = (HCRYPTKEY)pVKey;
    else
        LocalFree(pVKey);

    return Ret;
}


/*
 -  CryptExportKey
 -
 *  Purpose:
 *              The CryptExportKey function exports a cryptographic key or a
 *              key pair from a Cryptographic Sservice Provider (CSP) in a
 *              secure manner.
 *
 *
 *  Parameters:
 *              IN      hKey       -  A handle to the key to be exported
 *              IN      hExpKey    -  A handle to a cryptographic key of the
 *                                    destination user
 *              IN      dwBlobType -  Specifies the type of key BLOB to be
 *                                    exported in pbData
 *              IN      dwFlags    -  Specifies additional options for the
 *                                    function
 *              OUT     pbData     -  A pointer to a buffer that receives the
 *                                    key BLOB data
 *              IN OUT  pdwDataLen -  A pointer to a DWORD value that, on entry,
 *                                    contains the size of the buffer pointed to
 *                                    by the pbData parameter. When the function
 *                                    returns, this value contains the number of
 *                                    bytes stored in the buffer
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptExportKey(
    IN      HCRYPTKEY hKey,
    IN      HCRYPTKEY hExpKey,
    IN      DWORD dwBlobType,
    IN      DWORD dwFlags,
    OUT     BYTE *pbData,
    IN OUT  DWORD *pdwDataLen)
{
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    PVTableStruc    pVTable;
    PVKeyStruc      pVExpKey = (PVKeyStruc)hExpKey;
    BOOL            Ret;

    pVTable = pVKey->pVTable;

    //
    // Validate parameters
    //

    if (pbData == NULL || pdwDataLen == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    else if (pVKey != NULL)
    {
        if (pVKey->pVTable != pVExpKey->pVTable)
        // pVKey and pVExpKey provider handle mismatch
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider ExportKey function
    //

    __try
    {
        Ret = pVTable->CPExportKey(
                            pVTable->hProv,
                            pVKey->hKey,
                            (pVExpKey != NULL) ? pVExpKey->hKey : 0,
                            dwBlobType,
                            dwFlags,
                            pbData,
                            pdwDataLen
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptImportKey
 -
 *  Purpose:
 *              The CryptImportKey function transfers a cryptographic key from a
 *              key BLOB into a Cryptographic Service Provider (CSP).
 *
 *
 *  Parameters:
 *              IN      hProv     -  The handle of a CSP
 *              IN      pbData    -  A BYTE array that contains PUBLICKEYSTRUC
 *                                   BLOB header followed by the encrypted key
 *              IN      dwDataLen -  Contains the length of the key BLOB
 *              IN      hPubKey   -  A handle to the cryptographic key that
 *                                   decrypts the key stored in pbData
 *              IN      dwFlags   -  Currently used only when a public/private
 *                                   key pair in the form of a PRIVATEKEYBLOB
 *                                   is imported into the CSP
 *              OUT     phKey     -  A pointer to a HCRYPTKEY value that
 *                                   receives the handle of the imported key
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptImportKey(
    IN  HCRYPTPROV hProv,
    IN  CONST BYTE *pbData,
    IN  DWORD dwDataLen,
    IN  HCRYPTKEY hPubKey,
    IN  DWORD dwFlags,
    OUT HCRYPTKEY *phKey)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    PVKeyStruc      pVKey;
    PVKeyStruc      pVPubKey = (PVKeyStruc)hPubKey;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (pbData == NULL || phKey == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    else if (pVPubKey != NULL)
    {
        if (pVTable != pVPubKey->pVTable)
        // pVPubKey and provider handle mismatch
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }
    }

    //
    // Create a private key struc
    //

    pVKey = LocalAlloc(
                LMEM_ZEROINIT,
                sizeof(VKeyStruc)
                );

    if (pVKey == NULL)
        return FALSE;

    pVKey->pVTable = pVTable;

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider ImportKey function
    //

    __try
    {
        Ret = pVTable->CPImportKey(
                            pVTable->hProv,
                            pbData,
                            dwDataLen,
                            (pVPubKey != NULL) ? pVPubKey->hKey : 0,
                            dwFlags,
                            &pVKey->hKey
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    //
    // Set the return key handle
    //

    if (Ret == TRUE)
        *phKey = (HCRYPTKEY)pVKey;
    else
        LocalFree(pVKey);

    return Ret;
}


/*
 -  CryptEncrypt
 -
 *  Purpose:
 *              The CryptEncrypt function encrypts data. The algorithm used to
 *              encrypt the data is designated by the key held by the CSP module
 *              and is referenced by the hKey parameter.
 *
 *
 *  Parameters:
 *              IN      hKey       -  A handle to the encryption key
 *              IN      hHash      -  A handle to a hash object
 *              IN      Final      -  A Boolean value that specifies whether
 *                                    this is the last section in a series being
 *                                    encrypted
 *              IN      dwFlags    -  Reserved for future use
 *              IN OUT  pbData     -  A pointer to a buffer that contains the
 *                                    plaintext to be encrypted
 *              IN OUT  pdwDataLen -  A pointer to a DWORD value that, on entry,
 *                                    contains the length of the plaintext in
 *                                    the pbData buffer. On exit, this DWORD
 *                                    contains the length of the ciphertext
 *                                    written to the pbData buffer
 *              IN      dwBufLen   -  Specifies the total size of the input
 *                                    pbData buffer
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptEncrypt(
    IN      HCRYPTKEY hKey,
    IN      HCRYPTHASH hHash,
    IN      BOOL Final,
    IN      DWORD dwFlags,
    IN OUT  BYTE *pbData,
    IN OUT  DWORD *pdwDataLen,
    IN      DWORD dwBufLen)
{
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    PVTableStruc    pVTable;
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    BOOL            Ret;

    pVTable = pVKey->pVTable;

    //
    // Validate parameters
    //

    if (pdwDataLen == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    else if (pVHash != NULL)
    {
        if (pVKey->pVTable != pVHash->pVTable)
        // pVKey and pVHash provider handle mismatch
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider CryptEncrypt function
    //

    __try
    {
        Ret = pVTable->CPEncrypt(
                            pVTable->hProv,
                            pVKey->hKey,
                            (pVHash != NULL) ? pVHash->hHash : 0,
                            Final,
                            dwFlags,
                            pbData,
                            pdwDataLen,
                            dwBufLen
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptDecrypt
 -
 *  Purpose:
 *              The CryptDecrypt function decrypts data previously encrypted by
 *              using the CryptEncrypt function.
 *
 *
 *  Parameters:
 *              IN      hKey       -  A handle to the key to use for the
 *                                    decryption
 *              IN      hHash      -  A handle to a hash object
 *              IN      Final      -  A Boolean value that specifies whether
 *                                    this is the last section in a series being
 *                                    decrypted
 *              IN      dwFlags    -  Specifies the flags for decryption
 *              IN OUT  pbData     -  A pointer to a buffer that contains the
 *                                    data to be decrypted
 *              IN OUT  pdwDataLen -  A pointer to a DWORD value that, on entry,
 *                                    indicates the length of the pbData buffer.
 *                                    Upon return, the DWORD value contains the
 *                                    number of bytes of the decrypted plaintext
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptDecrypt(
    IN      HCRYPTKEY hKey,
    IN      HCRYPTHASH hHash,
    IN      BOOL Final,
    IN      DWORD dwFlags,
    IN OUT  BYTE *pbData,
    IN OUT  DWORD *pdwDataLen)
{
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    PVTableStruc    pVTable;
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    BOOL            Ret;

    pVTable = pVKey->pVTable;

    //
    // Validate parameters
    //

    if (pbData == NULL || pdwDataLen == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    else if (pVHash != NULL)
    {
        if (pVKey->pVTable != pVHash->pVTable)
        // pVKey and pVHash provider handle mismatch    
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider CryptDecrypt function
    //

    __try
    {
        Ret = pVTable->CPDecrypt(
                            pVTable->hProv,
                            pVKey->hKey,
                            (pVHash != NULL) ? pVHash->hHash : 0,
                            Final,
                            dwFlags,
                            pbData,
                            pdwDataLen
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptCreateHash
 -
 *  Purpose:
 *              The CryptCreateHash function initiates the hashing of a stream
 *              of data. It creates and returns to the calling application a
 *              handle to a Cryptographic Service Provider (CSP) hash object.
 *
 *
 *  Parameters:
 *              IN      hProv    -  A handle to a CSP
 *              IN      Algid    -  An ALG_ID value that identifies the hash
 *                                  algorithm to use
 *              IN      hKey     -  If the type of hash algorithm is a keyed
 *                                  hash, the key for the hash is passed in this
 *                                  parameter. For non-keyed algorithms, this
 *                                  parameter must be zero
 *              IN      dwFlags  -  Specifies the flags for creating hash
 *              OUT     phHash   -  The address to which the function copies a
 *                                  handle to the new hash object
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptCreateHash(
    IN  HCRYPTPROV hProv,
    IN  ALG_ID Algid,
    IN  HCRYPTKEY hKey,
    IN  DWORD dwFlags,
    OUT HCRYPTHASH *phHash)
{
    PVTableStruc    pVTable = (PVTableStruc)hProv;
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    PVHashStruc     pVHash;
    BOOL            Ret;

    //
    // Validate parameters
    //

    if (phHash == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    else if (pVKey != NULL)
    {
        if (pVTable != pVKey->pVTable)
        // pVKey provider handle and supplied provider handle mismatch
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }
    }

    //
    // Create a private hash struc
    //

    pVHash = LocalAlloc(
                LMEM_ZEROINIT,
                sizeof(VHashStruc)
                );

    if (pVHash != NULL)
        return FALSE;

    pVHash->pVTable = pVTable;

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider CreateHash function
    //

    __try
    {
        Ret = pVTable->CPCreateHash(
                            pVTable->hProv,
                            Algid,
                            (pVKey != NULL) ? pVKey->hKey : 0,
                            dwFlags,
                            &pVHash->hHash
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    //
    // Set the return key handle
    //

    if (Ret == TRUE)
        *phHash = (HCRYPTHASH)pVHash;
    else
        LocalFree(pVHash);
    
    return Ret;
}


/*
 -  CryptHashData
 -
 *  Purpose:
 *              The CryptHashData function adds data to a specified hash object.
 *
 *
 *  Parameters:
 *              IN      hHash     -  Handle of the hash object
 *              IN      pbData    -  A pointer to a buffer that contains the
 *                                   data to be added to the hash object
 *              IN      dwDataLen -  Number of bytes of data to be added
 *              IN      dwFlags   -  Specifies the type of data to be added
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptHashData(
    IN  HCRYPTHASH hHash,
    IN  CONST BYTE *pbData,
    IN  DWORD dwDataLen,
    IN  DWORD dwFlags)
{
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVHash->pVTable;

    //
    // Validate parameters
    //

    if (pbData == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider HashData function
    //

    __try
    {
        Ret = pVTable->CPHashData(
                            pVTable->hProv,
                            pVHash->hHash,
                            pbData,
                            dwDataLen,
                            dwFlags
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptHashSessionKey
 -
 *  Purpose:
 *              The CryptHashSessionKey function computes the cryptographic
 *              hash of a session key object.
 *
 *
 *  Parameters:
 *              IN      hHash    -  A handle to the hash object
 *              IN      hKey     -  A handle to the key object to be hashed
 *              IN      dwFlags  -  Specifies the flags
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptHashSessionKey(
    IN  HCRYPTHASH hHash,
    IN  HCRYPTKEY hKey,
    IN  DWORD dwFlags)
{
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    PVTableStruc    pVTable;
    PVKeyStruc      pVKey = (PVKeyStruc)hKey;
    BOOL            Ret;

    pVTable = pVHash->pVTable;

    //
    // Validate parameters
    //

    if (pVHash->pVTable != pVKey->pVTable)
    // pVHash and pVKey provider handle mismatch
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider HashSessionKey function
    //

    __try
    {
        Ret = pVTable->CPHashSessionKey(
                                pVTable->hProv,
                                pVHash->hHash,
                                pVKey->hKey,
                                dwFlags
                                );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}


/*
 -  CryptDestroyHash
 -
 *  Purpose:
 *              The CryptDestroyHash function destroys the hash object
 *              referenced by the hHash parameter.
 *
 *
 *  Parameters:
 *              IN      hHash   -  The handle of the hash object to be destroyed
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptDestroyHash(IN HCRYPTHASH hHash)
{
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVHash->pVTable;

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider DestroyHash function
    //

    __try
    {
        Ret = pVTable->CPDestroyHash(
                            pVTable->hProv,
                            pVHash->hHash
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    //
    // Deallocate the private hash struc
    //

    LocalFree(pVHash);

    return Ret;
}


/*
 -  CryptSignHash
 -
 *  Purpose:
 *              The CryptSignHash function signs data.
 *
 *
 *  Parameters:
 *              IN      hHash        - Handle of the hash object to be signed
 *              IN      dwKeySpec    - Identifies the private key to use from
 *                                     the provider's container
 *              IN      sDescription - This parameter is no longer used and must
 *                                     be set to NULL to prevent security
 *                                     vulnerabilities
 *              IN      dwFlags      - Specifies the flags
 *              OUT     pbSignature  - A pointer to a buffer receiving the
 *                                     signature data
 *              IN OUT  pdwSigLen    - A pointer to a DWORD value that specifies
 *                                     the size of the pbSignature buffer. When
 *                                     the function returns, the DWORD value
 *                                     contains the number of bytes stored in
 *                                     the buffer
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptSignHashA(
    IN      HCRYPTHASH hHash,
    IN      DWORD dwKeySpec,
    IN      LPCSTR sDescription,
    IN      DWORD dwFlags,
    OUT     BYTE *pbSignature,
    IN OUT  DWORD *pdwSigLen)
{
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    PVTableStruc    pVTable;
    BOOL            Ret;

    pVTable = pVHash->pVTable;

    //
    // Validate parameters
    //

    if (pdwSigLen == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider SignHash function
    //

    __try
    {
        Ret = pVTable->CPSignHash(
                            pVTable->hProv,
                            pVHash->hHash,
                            dwKeySpec,
                            NULL,
                            dwFlags,
                            pbSignature,
                            pdwSigLen
                            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}



WINADVAPI
BOOL
WINAPI
CryptSignHashW(
    IN      HCRYPTHASH hHash,
    IN      DWORD dwKeySpec,
    IN      LPCWSTR sDescription,
    IN      DWORD dwFlags,
    OUT     BYTE *pbSignature,
    IN OUT  DWORD *pdwSigLen)
{
    // NOTE: This function does not exist on Windows 2000 or XP ADVAPI32.
    SetLastError(ERROR_NOT_SUPPORTED);
    return FALSE;
}


/*
 -  CryptVerifySignature
 -
 *  Purpose:
 *              The CryptVerifySignature function verifies the signature of a
 *              hash object.
 *
 *
 *  Parameters:
 *              IN      hHash        - Handle of the hash object to verify
 *              IN      pbSignature  - The address of the signature to be
 *                                     verified
 *              IN      dwSigLen     - The number of bytes in the pbSignature
 *                                     signature data
 *              IN      hPubKey      - A handle to the public key to use to
 *                                     authenticate the signature
 *              IN      sDescription - This parameter is no longer used and must
 *                                     be set to NULL to prevent security
 *                                     vulnerabilities
 *              IN      dwFlags      - Specifies the flags
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptVerifySignatureA(
    IN  HCRYPTHASH hHash,
    IN  CONST BYTE *pbSignature,
    IN  DWORD dwSigLen,
    IN  HCRYPTKEY hPubKey,
    IN  LPCSTR sDescription,
    IN  DWORD dwFlags)
{
    PVHashStruc     pVHash = (PVHashStruc)hHash;
    PVTableStruc    pVTable;
    PVKeyStruc      pVPubKey = (PVKeyStruc)hPubKey;
    BOOL            Ret;

    pVTable = pVHash->pVTable;

    //
    // Validate parameters
    //

    if (pbSignature == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    else if (pVPubKey != NULL)
    {
        if (pVHash->pVTable != pVPubKey->pVTable)
        // pVHash and pVPubKey provider handle mismatch    
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }
    }

    //
    // Increment the concurrent usage count
    //

    InterlockedIncrement(&pVTable->InUse);

    //
    // Invoke the cryptographic service provider GetProvParam function
    //

    __try
    {
        Ret = pVTable->CPVerifySignature(
                                pVTable->hProv,
                                pVHash->hHash,
                                pbSignature,
                                dwSigLen,
                                (pVPubKey != NULL) ? pVPubKey->hKey : 0,
                                NULL,
                                dwFlags
                                );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Ret = FALSE;
    }

    //
    // Decrement the concurrent usage counter
    //

    InterlockedDecrement(&pVTable->InUse);

    return Ret;
}



WINADVAPI
BOOL
WINAPI
CryptVerifySignatureW(
    IN  HCRYPTHASH hHash,
    IN  CONST BYTE *pbSignature,
    IN  DWORD dwSigLen,
    IN  HCRYPTKEY hPubKey,
    IN  LPCWSTR sDescription,
    IN  DWORD dwFlags)
{
    // NOTE: This function does not exist on Windows 2000 or XP ADVAPI32.
    SetLastError(ERROR_NOT_SUPPORTED);
    return FALSE;
}


/*
 -  CryptSetProvider
 -
 *  Purpose:
 *              The CryptSetProvider function specifies the current user's
 *              default Cryptographic Service Provider (CSP).
 *
 *
 *  Parameters:
 *              IN      pszProvName - Name of the new default CSP
 *              IN      dwProvName  - Provider type of the CSP specified by
 *                                    pszProvName
 *
 *  Returns:
 *              If the function succeeds, the function returns nonzero (TRUE)
 *              If the function fails, it returns zero (FALSE)
 */

WINADVAPI
BOOL
WINAPI
CryptSetProviderA(
    IN  LPCSTR pszProvName,
    IN  DWORD dwProvType)
{
    // TOOD: Implement CryptSetProviderA
    return FALSE;
}


WINADVAPI
BOOL
WINAPI
CryptSetProviderW(
    IN  LPCWSTR pszProvName,
    IN  DWORD dwProvType)
{
    // TODO: Implement CryptSetProviderW
    return FALSE;
}

//
// Private Function
//

PSTR
UnicodeToMultiByte(
    IN PCWSTR UnicodeString,
    IN UINT   Codepage
    )

/*++

Routine Description:

    Convert a string from unicode to ansi.

Arguments:

    UnicodeString - supplies string to be converted.

    Codepage - supplies codepage to be used for the conversion.

Return Value:

    NULL if out of memory or invalid codepage.
    Caller can free buffer with MyFree().

--*/

{
    UINT WideCharCount;
    PSTR String;
    UINT StringBufferSize;
    UINT BytesInString;
    PSTR p;

    WideCharCount = lstrlenW(UnicodeString) + 1;

    //
    // Allocate maximally sized buffer.
    // If every unicode character is a double-byte
    // character, then the buffer needs to be the same size
    // as the unicode string. Otherwise it might be smaller,
    // as some unicode characters will translate to
    // single-byte characters.
    //
    StringBufferSize = WideCharCount * sizeof(WCHAR);
    String = (PSTR)LocalAlloc(LPTR, StringBufferSize);
    if(String == NULL) {
        return(NULL);
    }

    //
    // Perform the conversion.
    //
    BytesInString = WideCharToMultiByte(
                        Codepage,
                        0,                    // default composite char behavior
                        UnicodeString,
                        WideCharCount,
                        String,
                        StringBufferSize,
                        NULL,
                        NULL
                        );

    if(BytesInString == 0) {
        LocalFree(String);
        return(NULL);
    }

    //
    // Resize the string's buffer to its correct size.
    // If the realloc fails for some reason the original
    // buffer is not freed.
    //
    if(p = LocalReAlloc(String,BytesInString, LMEM_ZEROINIT)) {
        String = p;
    }

    return(String);

} // UnicodeToMultiByte

PWSTR
MultiByteToUnicode(
    IN PCSTR String,
    IN UINT  Codepage
    )

/*++

Routine Description:

    Convert a string to unicode.

Arguments:

    String - supplies string to be converted.

    Codepage - supplies codepage to be used for the conversion.

Return Value:

    NULL if string could not be converted (out of memory or invalid cp)
    Caller can free buffer with MyFree().

--*/

{
    UINT BytesIn8BitString;
    UINT CharsInUnicodeString;
    PWSTR UnicodeString;
    PWSTR p;

    BytesIn8BitString = lstrlenA(String) + 1;

    //
    // Allocate maximally sized buffer.
    // If every character is a single-byte character,
    // then the buffer needs to be twice the size
    // as the 8bit string. Otherwise it might be smaller,
    // as some characters are 2 bytes in their unicode and
    // 8bit representations.
    //
    UnicodeString = (PWSTR)LocalAlloc(LPTR, BytesIn8BitString * sizeof(WCHAR));
    if(UnicodeString == NULL) {
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return(NULL);
    }

    //
    // Perform the conversion.
    //
    CharsInUnicodeString = MultiByteToWideChar(
                                Codepage,
                                MB_PRECOMPOSED,
                                String,
                                BytesIn8BitString,
                                UnicodeString,
                                BytesIn8BitString
                                );

    if(CharsInUnicodeString == 0) {
        LocalFree(UnicodeString);
        return(NULL);
    }

    //
    // Resize the unicode string's buffer to its correct size.
    // If the realloc fails for some reason the original
    // buffer is not freed.
    //
    if(p = (PWSTR)LocalReAlloc(UnicodeString,CharsInUnicodeString*sizeof(WCHAR),
            LMEM_ZEROINIT)) {

        UnicodeString = p;
    }

    return(UnicodeString);

} // MultiByteToUnicode


Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

To those who are willing to contribute:

The new (public) issue tracker is located at http://opennt.net/projects/nt45/issues
To those who are interested, please go over them and try to implement fixes.

Make sure you register on the website so that I can provide you the write access to the issue tracker and repository.

OltScript131
User avatar
FTP Access
Posts: 255
Joined: Sat Sep 10, 2011 9:46 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by OltScript131 »

When I try to compile (I finally found!), he says that the makefile is incomplete....
Source codes of the programs of Windows NT 4.0... :beta:

yourepicfailure
User avatar
Donator
Posts: 1232
Joined: Mon Jul 23, 2012 9:40 pm
Location: Flying high in a DC10

Re: Windows NT 4 Source Compiled! version 2

Post by yourepicfailure »

You're probably messing up somewhere, or you probably didn't enter the right build environment. You just can't use MinGW or CyGwin to compile.
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
You will never tear me from the Pentium M.

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

Jajan131 wrote:When I try to compile (I finally found!), he says that the makefile is incomplete....
Source codes of the programs of Windows NT 4.0... :beta:
I've posted semi-complete build guides on the project site:
http://opennt.net/projects/nt45/wiki/Ho ... nvironment
http://opennt.net/projects/nt45/wiki/Ho ... ource_code

If this doesn't do, I don't know what will do ...

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

Project Roadmap, 2015-01-25

Phase 1 - x86
- Complete x86fre/x86tst build
- Complete x86chk build
- x86 build release

Phase 2 - MIPS
- Complete mipsfre/mipstst build
- Complete mipschk build
- MIPS build release

Phase 3 - Refactoring
- Source tree refactoring
-- Post NT 4 source tree structure (NT 5, NT 5.1)
-- Project reclassification
-- Build script clean-up
- Compiler change
-- compiler must support i386, MIPS, Alpha, PowerPC
-- support provision for Itanium, ARM
-- must support cross compiling from x86 environment to all of the above architectures

Phase 4 - Full Legacy System Support
- Full 64-bit Alpha port
- x86fre/x86tst/x86chk release for legacy systems
- mipsfre/mipstst/mipschk release for legacy systems
- alphafre/alphatst/alphachk release for legacy systems (this version might get dropped in favour of axp64 builds)
- axp64fre/axp64tst/axp64chk release for legacy systems
- ppcfre/ppctst/ppcchk release for legacy systems

Phase 5 - HAL Expansion
- Implement EFI support for all architectures, maintain ARC support alongside
- Support for modern PC (ACPI, x2APIC) x86 HAL
- Consider alternate options for MIPS and implement port fixes and HAL
- Implement PPC port HAL for PowerPC-based Mac systems

Phase 6 - New System Port
- Itanium system port
-- Itanium base port
-- EFI based HAL
- ARM system port
-- ARM base port
-- Raspberry Pi system HAL

Side Projects
- Open source Alpha core and SoC implementation, replicating AlphaServer DS20 environment
-- Alpha 21264 Core
-- AlphaServer DS20 peripherals
-- FPGA implementation only

http://opennt.net/projects/nt45/wiki/Project_Roadmap

OltScript131
User avatar
FTP Access
Posts: 255
Joined: Sat Sep 10, 2011 9:46 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by OltScript131 »

Can we give these also own ideas ? :OD
And, it will become what finally ??
Is it possible to add MS-DOS 7.00 ???
It will have a code name ????

Stephanos
Posts: 297
Joined: Fri Dec 26, 2014 5:38 am
Contact:

Re: Windows NT 4 Source Compiled! version 2

Post by Stephanos »

Jajan131 wrote:Can we give these also own ideas ? :OD
And, it will become what finally ??
Is it possible to add MS-DOS 7.00 ???
It will have a code name ????
It will become what is described in the roadmap I posted earlier. I don't understand your question on MS-DOS 7.

Why would you add MS-DOS 7 to Windows NT 4? If you are talking about MS-DOS 7 compatibility in NTVDM, I don't have any plans for that nor do I see a need for it. Most DOS applications are more compatible with MS-DOS 5 (implemented in NTVDM) than MS-DOS 7 and it would do more harm to convert the NTVDM into MS-DOS 7 than to keep it at 5.

If you would like to add MS-DOS 7 for any reason, you can implement it and send the files to me so that I can add it to the repo (we will make it selectable between MS-DOS 5 and MS-DOS 7 compatibility modes).

No codename for now. I'm open to suggestions though.

Locked