Synchronize with trunk r58528.
[reactos.git] / dll / win32 / msisip / main.c
1 /*
2 * Copyright 2008 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
19 #define WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #include <config.h>
24 #include <stdarg.h>
25 #include <windef.h>
26 #include <winbase.h>
27 #include <wincrypt.h>
28 #include <mssip.h>
29 #define COBJMACROS
30 #include <objbase.h>
31 #include <initguid.h>
32 #include <wine/debug.h>
33
34 WINE_DEFAULT_DEBUG_CHANNEL(msisip);
35
36 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
37 {
38 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
39
40 switch (fdwReason)
41 {
42 case DLL_WINE_PREATTACH:
43 return FALSE; /* prefer native version */
44 case DLL_PROCESS_ATTACH:
45 DisableThreadLibraryCalls(hinstDLL);
46 break;
47 case DLL_PROCESS_DETACH:
48 break;
49 default:
50 break;
51 }
52
53 return TRUE;
54 }
55
56 static GUID mySubject = { 0x000c10f1, 0x0000, 0x0000,
57 { 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }};
58
59 /***********************************************************************
60 * DllRegisterServer (MSISIP.@)
61 */
62 HRESULT WINAPI DllRegisterServer(void)
63 {
64 static WCHAR msisip[] = { 'M','S','I','S','I','P','.','D','L','L',0 };
65 static WCHAR getSignedDataMsg[] = { 'M','s','i','S','I','P','G','e','t',
66 'S','i','g','n','e','d','D','a','t','a','M','s','g',0 };
67 static WCHAR putSignedDataMsg[] = { 'M','s','i','S','I','P','P','u','t',
68 'S','i','g','n','e','d','D','a','t','a','M','s','g',0 };
69 static WCHAR createIndirectData[] = { 'M','s','i','S','I','P',
70 'C','r','e','a','t','e','I','n','d','i','r','e','c','t','D','a','t','a',
71 0 };
72 static WCHAR verifyIndirectData[] = { 'M','s','i','S','I','P',
73 'V','e','r','i','f','y','I','n','d','i','r','e','c','t','D','a','t','a',
74 0 };
75 static WCHAR removeSignedDataMsg[] = { 'M','s','i','S','I','P','R','e','m',
76 'o','v','e','S','i','g','n','e','d','D','a','t','a','M','s','g', 0 };
77 static WCHAR isMyTypeOfFile[] = { 'M','s','i','S','I','P',
78 'I','s','M','y','T','y','p','e','O','f','F','i','l','e',0 };
79
80 SIP_ADD_NEWPROVIDER prov;
81
82 memset(&prov, 0, sizeof(prov));
83 prov.cbStruct = sizeof(prov);
84 prov.pwszDLLFileName = msisip;
85 prov.pgSubject = &mySubject;
86 prov.pwszGetFuncName = getSignedDataMsg;
87 prov.pwszPutFuncName = putSignedDataMsg;
88 prov.pwszCreateFuncName = createIndirectData;
89 prov.pwszVerifyFuncName = verifyIndirectData;
90 prov.pwszRemoveFuncName = removeSignedDataMsg;
91 prov.pwszIsFunctionNameFmt2 = isMyTypeOfFile;
92 return CryptSIPAddProvider(&prov) ? S_OK : S_FALSE;
93 }
94
95 /***********************************************************************
96 * DllUnregisterServer (MSISIP.@)
97 */
98 HRESULT WINAPI DllUnregisterServer(void)
99 {
100 CryptSIPRemoveProvider(&mySubject);
101 return S_OK;
102 }
103
104 /***********************************************************************
105 * MsiSIPGetSignedDataMsg (MSISIP.@)
106 */
107 BOOL WINAPI MsiSIPGetSignedDataMsg(SIP_SUBJECTINFO *pSubjectInfo,
108 DWORD *pdwEncodingType, DWORD dwIndex, DWORD *pcbSignedDataMsg,
109 BYTE *pbSignedDataMsg)
110 {
111 static const WCHAR digitalSig[] = { 5,'D','i','g','i','t','a','l',
112 'S','i','g','n','a','t','u','r','e',0 };
113 BOOL ret = FALSE;
114 IStorage *stg = NULL;
115 HRESULT r;
116 IStream *stm = NULL;
117 BYTE hdr[2], len[sizeof(DWORD)];
118 DWORD count, lenBytes, dataBytes;
119
120 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex,
121 pcbSignedDataMsg, pbSignedDataMsg);
122
123 r = StgOpenStorage(pSubjectInfo->pwsFileName, NULL,
124 STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
125 if (FAILED(r))
126 {
127 TRACE("couldn't open %s\n", debugstr_w(pSubjectInfo->pwsFileName));
128 goto end;
129 }
130
131 r = IStorage_OpenStream(stg, digitalSig, 0,
132 STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stm);
133 if (FAILED(r))
134 {
135 TRACE("couldn't find digital signature stream\n");
136 goto freestorage;
137 }
138
139 r = IStream_Read(stm, hdr, sizeof(hdr), &count);
140 if (FAILED(r) || count != sizeof(hdr))
141 goto freestream;
142 if (hdr[0] != 0x30)
143 {
144 WARN("unexpected data in digital sig: 0x%02x%02x\n", hdr[0], hdr[1]);
145 goto freestream;
146 }
147
148 /* Read the asn.1 length from the stream. Only supports definite-length
149 * values, which DER-encoded signatures should be.
150 */
151 if (hdr[1] == 0x80)
152 {
153 WARN("indefinite-length encoding not supported!\n");
154 goto freestream;
155 }
156 else if (hdr[1] & 0x80)
157 {
158 DWORD temp;
159 LPBYTE ptr;
160
161 lenBytes = hdr[1] & 0x7f;
162 if (lenBytes > sizeof(DWORD))
163 {
164 WARN("asn.1 length too long (%d)\n", lenBytes);
165 goto freestream;
166 }
167 r = IStream_Read(stm, len, lenBytes, &count);
168 if (FAILED(r) || count != lenBytes)
169 goto freestream;
170 dataBytes = 0;
171 temp = lenBytes;
172 ptr = len;
173 while (temp--)
174 {
175 dataBytes <<= 8;
176 dataBytes |= *ptr++;
177 }
178 }
179 else
180 {
181 lenBytes = 0;
182 dataBytes = hdr[1];
183 }
184
185 if (!pbSignedDataMsg)
186 {
187 *pcbSignedDataMsg = 2 + lenBytes + dataBytes;
188 ret = TRUE;
189 }
190 else if (*pcbSignedDataMsg < 2 + lenBytes + dataBytes)
191 {
192 SetLastError(ERROR_INSUFFICIENT_BUFFER);
193 *pcbSignedDataMsg = 2 + lenBytes + dataBytes;
194 }
195 else
196 {
197 LPBYTE ptr = pbSignedDataMsg;
198
199 memcpy(ptr, hdr, sizeof(hdr));
200 ptr += sizeof(hdr);
201 if (lenBytes)
202 {
203 memcpy(ptr, len, lenBytes);
204 ptr += lenBytes;
205 }
206 r = IStream_Read(stm, ptr, dataBytes, &count);
207 if (SUCCEEDED(r) && count == dataBytes)
208 {
209 *pdwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
210 *pcbSignedDataMsg = 2 + lenBytes + dataBytes;
211 ret = TRUE;
212 }
213 }
214
215 freestream:
216 IStream_Release(stm);
217 freestorage:
218 IStorage_Release(stg);
219 end:
220
221 TRACE("returning %d\n", ret);
222 return ret;
223 }
224
225 DEFINE_GUID(CLSID_MsiTransform, 0x000c1082,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
226 DEFINE_GUID(CLSID_MsiDatabase, 0x000c1084,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
227 DEFINE_GUID(CLSID_MsiPatch, 0x000c1086,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
228
229 /***********************************************************************
230 * MsiSIPIsMyTypeOfFile (MSISIP.@)
231 */
232 BOOL WINAPI MsiSIPIsMyTypeOfFile(WCHAR *name, GUID *subject)
233 {
234 BOOL ret = FALSE;
235 IStorage *stg = NULL;
236 HRESULT r;
237
238 TRACE("(%s, %p)\n", debugstr_w(name), subject);
239
240 r = StgOpenStorage(name, NULL, STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE,
241 NULL, 0, &stg);
242 if (SUCCEEDED(r))
243 {
244 STATSTG stat;
245
246 r = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
247 if (SUCCEEDED(r))
248 {
249 if (IsEqualGUID(&stat.clsid, &CLSID_MsiDatabase) ||
250 IsEqualGUID(&stat.clsid, &CLSID_MsiPatch) ||
251 IsEqualGUID(&stat.clsid, &CLSID_MsiTransform))
252 {
253 ret = TRUE;
254 *subject = mySubject;
255 }
256 }
257 IStorage_Release(stg);
258 }
259 return ret;
260 }