ole32/tests: Fix DVTARGETDEVICE offsets.
[wine] / dlls / jscript / date.c
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
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 <limits.h>
20 #include <math.h>
21
22 #include "jscript.h"
23
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
27
28 typedef struct {
29     DispatchEx dispex;
30
31     /* ECMA-262 3rd Edition    15.9.1.1 */
32     DOUBLE time;
33 } DateInstance;
34
35 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
36 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
37 static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
38 static const WCHAR propertyIsEnumerableW[] =
39     {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
40 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
41 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
42 static const WCHAR toUTCStringW[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
43 static const WCHAR toDateStringW[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
44 static const WCHAR toTimeStringW[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
45 static const WCHAR toLocaleDateStringW[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
46 static const WCHAR toLocaleTimeStringW[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
47 static const WCHAR getTimeW[] = {'g','e','t','T','i','m','e',0};
48 static const WCHAR getFullYearW[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
49 static const WCHAR getUTCFullYearW[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
50 static const WCHAR getMonthW[] = {'g','e','t','M','o','n','t','h',0};
51 static const WCHAR getUTCMonthW[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
52 static const WCHAR getDateW[] = {'g','e','t','D','a','t','e',0};
53 static const WCHAR getUTCDateW[] = {'g','e','t','U','T','C','D','a','t','e',0};
54 static const WCHAR getDayW[] = {'g','e','t','D','a','y',0};
55 static const WCHAR getUTCDayW[] = {'g','e','t','U','T','C','D','a','y',0};
56 static const WCHAR getHoursW[] = {'g','e','t','H','o','u','r','s',0};
57 static const WCHAR getUTCHoursW[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
58 static const WCHAR getMinutesW[] = {'g','e','t','M','i','n','u','t','e','s',0};
59 static const WCHAR getUTCMinutesW[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
60 static const WCHAR getSecondsW[] = {'g','e','t','S','e','c','o','n','d','s',0};
61 static const WCHAR getUTCSecondsW[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
62 static const WCHAR getMilisecondsW[] = {'g','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
63 static const WCHAR getUTCMilisecondsW[] = {'g','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
64 static const WCHAR getTimezoneOffsetW[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
65 static const WCHAR setTimeW[] = {'s','e','t','T','i','m','e',0};
66 static const WCHAR setMilisecondsW[] = {'s','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
67 static const WCHAR setUTCMilisecondsW[] = {'s','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
68 static const WCHAR setSecondsW[] = {'s','e','t','S','e','c','o','n','d','s',0};
69 static const WCHAR setUTCSecondsW[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
70 static const WCHAR setMinutesW[] = {'s','e','t','M','i','n','u','t','e','s',0};
71 static const WCHAR setUTCMinutesW[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
72 static const WCHAR setHoursW[] = {'s','e','t','H','o','u','r','s',0};
73 static const WCHAR setUTCHoursW[] = {'s','e','t','H','o','u','r','s',0};
74 static const WCHAR setDateW[] = {'s','e','t','D','a','t','e',0};
75 static const WCHAR setUTCDateW[] = {'s','e','t','U','T','C','D','a','t','e',0};
76 static const WCHAR setMonthW[] = {'s','e','t','M','o','n','t','h',0};
77 static const WCHAR setUTCMonthW[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
78 static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
79 static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
80
81 /* ECMA-262 3rd Edition    15.9.1.14 */
82 static inline DOUBLE time_clip(DOUBLE time)
83 {
84     /* FIXME: Handle inf */
85
86     if(8.64e15 < time || time < -8.64e15) {
87         FIXME("return NaN\n");
88         return 0.0;
89     }
90
91     return floor(time);
92 }
93
94 static HRESULT Date_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
95         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
96 {
97     FIXME("\n");
98     return E_NOTIMPL;
99 }
100
101 static HRESULT Date_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
102         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
103 {
104     FIXME("\n");
105     return E_NOTIMPL;
106 }
107
108 static HRESULT Date_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
109         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
110 {
111     FIXME("\n");
112     return E_NOTIMPL;
113 }
114
115 static HRESULT Date_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
116         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
117 {
118     FIXME("\n");
119     return E_NOTIMPL;
120 }
121
122 static HRESULT Date_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
123         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
124 {
125     FIXME("\n");
126     return E_NOTIMPL;
127 }
128
129 static HRESULT Date_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
130         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
131 {
132     FIXME("\n");
133     return E_NOTIMPL;
134 }
135
136 static HRESULT Date_toUTCString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
137         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
138 {
139     FIXME("\n");
140     return E_NOTIMPL;
141 }
142
143 static HRESULT Date_toDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
144         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
145 {
146     FIXME("\n");
147     return E_NOTIMPL;
148 }
149
150 static HRESULT Date_toTimeString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
151         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
152 {
153     FIXME("\n");
154     return E_NOTIMPL;
155 }
156
157 static HRESULT Date_toLocaleDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
158         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
159 {
160     FIXME("\n");
161     return E_NOTIMPL;
162 }
163
164 static HRESULT Date_toLocaleTimeString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
165         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
166 {
167     FIXME("\n");
168     return E_NOTIMPL;
169 }
170
171 /* ECMA-262 3rd Edition    15.9.5.9 */
172 static HRESULT Date_getTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
173         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
174 {
175     TRACE("\n");
176
177     if(!is_class(dispex, JSCLASS_DATE)) {
178         FIXME("throw TypeError\n");
179         return E_FAIL;
180     }
181
182     if(retv) {
183         DateInstance *date = (DateInstance*)dispex;
184         num_set_val(retv, date->time);
185     }
186     return S_OK;
187 }
188
189 static HRESULT Date_getFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
190         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
191 {
192     FIXME("\n");
193     return E_NOTIMPL;
194 }
195
196 static HRESULT Date_getUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
197         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
198 {
199     FIXME("\n");
200     return E_NOTIMPL;
201 }
202
203 static HRESULT Date_getMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
204         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
205 {
206     FIXME("\n");
207     return E_NOTIMPL;
208 }
209
210 static HRESULT Date_getUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
211         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
212 {
213     FIXME("\n");
214     return E_NOTIMPL;
215 }
216
217 static HRESULT Date_getDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
218         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
219 {
220     FIXME("\n");
221     return E_NOTIMPL;
222 }
223
224 static HRESULT Date_getUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
225         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
226 {
227     FIXME("\n");
228     return E_NOTIMPL;
229 }
230
231 static HRESULT Date_getDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
232         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
233 {
234     FIXME("\n");
235     return E_NOTIMPL;
236 }
237
238 static HRESULT Date_getUTCDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
239         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
240 {
241     FIXME("\n");
242     return E_NOTIMPL;
243 }
244
245 static HRESULT Date_getHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
246         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
247 {
248     FIXME("\n");
249     return E_NOTIMPL;
250 }
251
252 static HRESULT Date_getUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
253         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
254 {
255     FIXME("\n");
256     return E_NOTIMPL;
257 }
258
259 static HRESULT Date_getMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
260         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
261 {
262     FIXME("\n");
263     return E_NOTIMPL;
264 }
265
266 static HRESULT Date_getUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
267         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
268 {
269     FIXME("\n");
270     return E_NOTIMPL;
271 }
272
273 static HRESULT Date_getSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
274         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
275 {
276     FIXME("\n");
277     return E_NOTIMPL;
278 }
279
280 static HRESULT Date_getUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
281         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
282 {
283     FIXME("\n");
284     return E_NOTIMPL;
285 }
286
287 static HRESULT Date_getMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
288         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
289 {
290     FIXME("\n");
291     return E_NOTIMPL;
292 }
293
294 static HRESULT Date_getUTCMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
295         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
296 {
297     FIXME("\n");
298     return E_NOTIMPL;
299 }
300
301 static HRESULT Date_getTimezoneOffset(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
302         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
303 {
304     FIXME("\n");
305     return E_NOTIMPL;
306 }
307
308 static HRESULT Date_setTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
309         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
310 {
311     FIXME("\n");
312     return E_NOTIMPL;
313 }
314
315 static HRESULT Date_setMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
316         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
317 {
318     FIXME("\n");
319     return E_NOTIMPL;
320 }
321
322 static HRESULT Date_setUTCMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
323         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
324 {
325     FIXME("\n");
326     return E_NOTIMPL;
327 }
328
329 static HRESULT Date_setSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
330         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
331 {
332     FIXME("\n");
333     return E_NOTIMPL;
334 }
335
336 static HRESULT Date_setUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
337         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
338 {
339     FIXME("\n");
340     return E_NOTIMPL;
341 }
342
343 static HRESULT Date_setMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
344         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
345 {
346     FIXME("\n");
347     return E_NOTIMPL;
348 }
349
350 static HRESULT Date_setUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
351         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
352 {
353     FIXME("\n");
354     return E_NOTIMPL;
355 }
356
357 static HRESULT Date_setHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
358         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
359 {
360     FIXME("\n");
361     return E_NOTIMPL;
362 }
363
364 static HRESULT Date_setUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
365         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
366 {
367     FIXME("\n");
368     return E_NOTIMPL;
369 }
370
371 static HRESULT Date_setDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
372         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
373 {
374     FIXME("\n");
375     return E_NOTIMPL;
376 }
377
378 static HRESULT Date_setUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
379         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
380 {
381     FIXME("\n");
382     return E_NOTIMPL;
383 }
384
385 static HRESULT Date_setMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
386         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
387 {
388     FIXME("\n");
389     return E_NOTIMPL;
390 }
391
392 static HRESULT Date_setUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
393         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
394 {
395     FIXME("\n");
396     return E_NOTIMPL;
397 }
398
399 static HRESULT Date_setFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
400         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
401 {
402     FIXME("\n");
403     return E_NOTIMPL;
404 }
405
406 static HRESULT Date_setUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
407         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
408 {
409     FIXME("\n");
410     return E_NOTIMPL;
411 }
412
413 static HRESULT Date_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
414         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
415 {
416     FIXME("\n");
417     return E_NOTIMPL;
418 }
419
420 static const builtin_prop_t Date_props[] = {
421     {getDateW,               Date_getDate,               PROPF_METHOD},
422     {getDayW,                Date_getDay,                PROPF_METHOD},
423     {getFullYearW,           Date_getFullYear,           PROPF_METHOD},
424     {getHoursW,              Date_getHours,              PROPF_METHOD},
425     {getMilisecondsW,        Date_getMiliseconds,        PROPF_METHOD},
426     {getMinutesW,            Date_getMinutes,            PROPF_METHOD},
427     {getMonthW,              Date_getMonth,              PROPF_METHOD},
428     {getSecondsW,            Date_getSeconds,            PROPF_METHOD},
429     {getTimeW,               Date_getTime,               PROPF_METHOD},
430     {getTimezoneOffsetW,     Date_getTimezoneOffset,     PROPF_METHOD},
431     {getUTCDateW,            Date_getUTCDate,            PROPF_METHOD},
432     {getUTCDayW,             Date_getUTCDay,             PROPF_METHOD},
433     {getUTCFullYearW,        Date_getUTCFullYear,        PROPF_METHOD},
434     {getUTCHoursW,           Date_getUTCHours,           PROPF_METHOD},
435     {getUTCMilisecondsW,     Date_getUTCMiliseconds,     PROPF_METHOD},
436     {getUTCMinutesW,         Date_getUTCMinutes,         PROPF_METHOD},
437     {getUTCMonthW,           Date_getUTCMonth,           PROPF_METHOD},
438     {getUTCSecondsW,         Date_getUTCSeconds,         PROPF_METHOD},
439     {hasOwnPropertyW,        Date_hasOwnProperty,        PROPF_METHOD},
440     {isPrototypeOfW,         Date_isPrototypeOf,         PROPF_METHOD},
441     {propertyIsEnumerableW,  Date_propertyIsEnumerable,  PROPF_METHOD},
442     {setDateW,               Date_setDate,               PROPF_METHOD},
443     {setFullYearW,           Date_setFullYear,           PROPF_METHOD},
444     {setHoursW,              Date_setHours,              PROPF_METHOD},
445     {setMilisecondsW,        Date_setMiliseconds,        PROPF_METHOD},
446     {setMinutesW,            Date_setMinutes,            PROPF_METHOD},
447     {setMonthW,              Date_setMonth,              PROPF_METHOD},
448     {setSecondsW,            Date_setSeconds,            PROPF_METHOD},
449     {setTimeW,               Date_setTime,               PROPF_METHOD},
450     {setUTCDateW,            Date_setUTCDate,            PROPF_METHOD},
451     {setUTCFullYearW,        Date_setUTCFullYear,        PROPF_METHOD},
452     {setUTCHoursW,           Date_setUTCHours,           PROPF_METHOD},
453     {setUTCMilisecondsW,     Date_setUTCMiliseconds,     PROPF_METHOD},
454     {setUTCMinutesW,         Date_setUTCMinutes,         PROPF_METHOD},
455     {setUTCMonthW,           Date_setUTCMonth,           PROPF_METHOD},
456     {setUTCSecondsW,         Date_setUTCSeconds,         PROPF_METHOD},
457     {toDateStringW,          Date_toDateString,          PROPF_METHOD},
458     {toLocaleDateStringW,    Date_toLocaleDateString,    PROPF_METHOD},
459     {toLocaleStringW,        Date_toLocaleString,        PROPF_METHOD},
460     {toLocaleTimeStringW,    Date_toLocaleTimeString,    PROPF_METHOD},
461     {toStringW,              Date_toString,              PROPF_METHOD},
462     {toTimeStringW,          Date_toTimeString,          PROPF_METHOD},
463     {toUTCStringW,           Date_toUTCString,           PROPF_METHOD},
464     {valueOfW,               Date_valueOf,               PROPF_METHOD},
465 };
466
467 static const builtin_info_t Date_info = {
468     JSCLASS_DATE,
469     {NULL, Date_value, 0},
470     sizeof(Date_props)/sizeof(*Date_props),
471     Date_props,
472     NULL,
473     NULL
474 };
475
476 static HRESULT create_date(script_ctx_t *ctx, BOOL use_constr, DOUBLE time, DispatchEx **ret)
477 {
478     DateInstance *date;
479     HRESULT hres;
480
481     date = heap_alloc_zero(sizeof(DateInstance));
482     if(!date)
483         return E_OUTOFMEMORY;
484
485     if(use_constr)
486         hres = init_dispex_from_constr(&date->dispex, ctx, &Date_info, ctx->date_constr);
487     else
488         hres = init_dispex(&date->dispex, ctx, &Date_info, NULL);
489     if(FAILED(hres)) {
490         heap_free(date);
491         return hres;
492     }
493
494     date->time = time;
495
496     *ret = &date->dispex;
497     return S_OK;
498 }
499
500 static HRESULT DateConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
501         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
502 {
503     DispatchEx *date;
504     HRESULT hres;
505
506     TRACE("\n");
507
508     switch(flags) {
509     case DISPATCH_CONSTRUCT:
510         switch(arg_cnt(dp)) {
511         /* ECMA-262 3rd Edition    15.9.3.3 */
512         case 0: {
513             FILETIME time;
514
515             GetSystemTimeAsFileTime(&time);
516
517             hres = create_date(dispex->ctx, TRUE,
518                    floor((DOUBLE)(time.dwLowDateTime/1e6) + (DOUBLE)time.dwHighDateTime*((DOUBLE)UINT_MAX+1.0)/1.e6),
519                    &date);
520             if(FAILED(hres))
521                 return hres;
522             break;
523         }
524
525         /* ECMA-262 3rd Edition    15.9.3.2 */
526         case 1: {
527             VARIANT prim, num;
528
529             hres = to_primitive(dispex->ctx, get_arg(dp,0), ei, &prim);
530             if(FAILED(hres))
531                 return hres;
532
533             if(V_VT(&prim) == VT_BSTR) {
534                 FIXME("VT_BSTR not supported\n");
535                 return E_NOTIMPL;
536             }
537
538             hres = to_number(dispex->ctx, &prim, ei, &num);
539             VariantClear(&prim);
540             if(FAILED(hres))
541                 return hres;
542
543             hres = create_date(dispex->ctx, TRUE, time_clip(num_val(&num)), &date);
544             if(FAILED(hres))
545                 return hres;
546             break;
547         }
548
549         default:
550             FIXME("unimplemented argcnt %d\n", arg_cnt(dp));
551             return E_NOTIMPL;
552         }
553
554         V_VT(retv) = VT_DISPATCH;
555         V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(date);
556         return S_OK;
557
558     default:
559         FIXME("unimplemented flags %x\n", flags);
560         return E_NOTIMPL;
561     }
562
563     return S_OK;
564 }
565
566 HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx **ret)
567 {
568     DispatchEx *date;
569     HRESULT hres;
570
571     hres = create_date(ctx, FALSE, 0.0, &date);
572     if(FAILED(hres))
573         return hres;
574
575     hres = create_builtin_function(ctx, DateConstr_value, PROPF_CONSTR, date, ret);
576
577     jsdisp_release(date);
578     return hres;
579 }