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