crypt32: Store stream info in message.
[wine] / dlls / crypt32 / msg.c
1 /*
2  * Copyright 2007 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
22
23 #include "wine/debug.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
26
27 /* Called when a message's ref count reaches zero.  Free any message-specific
28  * data here.
29  */
30 typedef void (*CryptMsgCloseFunc)(HCRYPTMSG msg);
31
32 typedef BOOL (*CryptMsgGetParamFunc)(HCRYPTMSG hCryptMsg, DWORD dwParamType,
33  DWORD dwIndex, void *pvData, DWORD *pcbData);
34
35 typedef BOOL (*CryptMsgUpdateFunc)(HCRYPTMSG hCryptMsg, const BYTE *pbData,
36  DWORD cbData, BOOL fFinal);
37
38 typedef struct _CryptMsgBase
39 {
40     LONG                 ref;
41     DWORD                open_flags;
42     PCMSG_STREAM_INFO    stream_info;
43     CryptMsgCloseFunc    close;
44     CryptMsgUpdateFunc   update;
45     CryptMsgGetParamFunc get_param;
46 } CryptMsgBase;
47
48 static inline void CryptMsgBase_Init(CryptMsgBase *msg, DWORD dwFlags,
49  PCMSG_STREAM_INFO pStreamInfo)
50 {
51     msg->ref = 1;
52     msg->open_flags = dwFlags;
53     msg->stream_info = pStreamInfo;
54 }
55
56 typedef struct _CDataEncodeMsg
57 {
58     CryptMsgBase base;
59 } CDataEncodeMsg;
60
61 static HCRYPTMSG CDataEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
62  LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo)
63 {
64     CDataEncodeMsg *msg;
65
66     if (pvMsgEncodeInfo)
67     {
68         SetLastError(E_INVALIDARG);
69         return NULL;
70     }
71     FIXME("semi-stub\n");
72     msg = CryptMemAlloc(sizeof(CDataEncodeMsg));
73     if (msg)
74     {
75         CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo);
76     }
77     return (HCRYPTMSG)msg;
78 }
79
80 static inline const char *MSG_TYPE_STR(DWORD type)
81 {
82     switch (type)
83     {
84 #define _x(x) case (x): return #x
85         _x(CMSG_DATA);
86         _x(CMSG_SIGNED);
87         _x(CMSG_ENVELOPED);
88         _x(CMSG_SIGNED_AND_ENVELOPED);
89         _x(CMSG_HASHED);
90         _x(CMSG_ENCRYPTED);
91 #undef _x
92         default:
93             return wine_dbg_sprintf("unknown (%d)", type);
94     }
95 }
96
97 HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags,
98  DWORD dwMsgType, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID,
99  PCMSG_STREAM_INFO pStreamInfo)
100 {
101     HCRYPTMSG msg = NULL;
102
103     TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType, dwFlags,
104      dwMsgType, pvMsgEncodeInfo, debugstr_a(pszInnerContentObjID), pStreamInfo);
105
106     if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
107     {
108         SetLastError(E_INVALIDARG);
109         return NULL;
110     }
111     switch (dwMsgType)
112     {
113     case CMSG_DATA:
114         msg = CDataEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
115          pszInnerContentObjID, pStreamInfo);
116         break;
117     case CMSG_SIGNED:
118     case CMSG_ENVELOPED:
119     case CMSG_HASHED:
120         FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType));
121         break;
122     case CMSG_SIGNED_AND_ENVELOPED:
123     case CMSG_ENCRYPTED:
124         /* defined but invalid, fall through */
125     default:
126         SetLastError(CRYPT_E_INVALID_MSG_TYPE);
127     }
128     return msg;
129 }
130
131 HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags,
132  DWORD dwMsgType, HCRYPTPROV hCryptProv, PCERT_INFO pRecipientInfo,
133  PCMSG_STREAM_INFO pStreamInfo)
134 {
135     FIXME("(%08x, %08x, %08x, %08lx, %p, %p): stub\n", dwMsgEncodingType,
136      dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo);
137
138     if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
139     {
140         SetLastError(E_INVALIDARG);
141         return NULL;
142     }
143     return NULL;
144 }
145
146 HCRYPTMSG WINAPI CryptMsgDuplicate(HCRYPTMSG hCryptMsg)
147 {
148     TRACE("(%p)\n", hCryptMsg);
149
150     if (hCryptMsg)
151     {
152         CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
153
154         InterlockedIncrement(&msg->ref);
155     }
156     return hCryptMsg;
157 }
158
159 BOOL WINAPI CryptMsgClose(HCRYPTMSG hCryptMsg)
160 {
161     TRACE("(%p)\n", hCryptMsg);
162
163     if (hCryptMsg)
164     {
165         CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
166
167         if (InterlockedDecrement(&msg->ref) == 0)
168         {
169             TRACE("freeing %p\n", msg);
170             if (msg->close)
171                 msg->close(msg);
172             CryptMemFree(msg);
173         }
174     }
175     return TRUE;
176 }
177
178 BOOL WINAPI CryptMsgUpdate(HCRYPTMSG hCryptMsg, const BYTE *pbData,
179  DWORD cbData, BOOL fFinal)
180 {
181     CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
182     BOOL ret = FALSE;
183
184     TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal);
185     if (msg && msg->update)
186         ret = msg->update(hCryptMsg, pbData, cbData, fFinal);
187     return ret;
188 }
189
190 BOOL WINAPI CryptMsgGetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
191  DWORD dwIndex, void *pvData, DWORD *pcbData)
192 {
193     CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
194     BOOL ret = FALSE;
195
196     TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex,
197      pvData, pcbData);
198     if (msg && msg->get_param)
199         ret = msg->get_param(hCryptMsg, dwParamType, dwIndex, pvData, pcbData);
200     return ret;
201 }