If a message was encrypted for a particular user, then the CryptGenKey function was used to create a random session key before the encryption was performed. This means that before the message can be decrypted, the key blob containing the session key needs to be imported into the CSP with the CryptImportKey function. This function will use your key exchange private key to decrypt the key blob. This means that the key blob must have been originally created by using the matching key exchange public key.
If the message was encrypted so that any password holder can access the data, the CryptImportKey function is not used. Instead, you create the decryption session key with the CryptDeriveKey function. You will also need to supply the function with the password (or other access token).
The session key's parameters need to be configured in the same way they were during encryption. These parameters can be specified by using the CryptSetKeyParam function. For example, if the salt value was changed one or more times during the encryption process, then it must also be changed during the decryption process in exactly the same manner.
The message is decrypted by using the CryptDecrypt function. If the message is too large to fit comfortably in memory, it can be decrypted in sections, through multiple calls to CryptDecrypt.
When the decryption is complete, be sure to destroy the session key by using the CryptDestroyKey function. In addition to destroying the key, this will free up CSP resources.