msxml3: Initial implementation of attributeDecl() in writer.
[wine] / dlls / wineqtdecoder / qtdatahandler.c
1 /*
2  * QuickTime Data Handler
3  *
4  * Copyright 2011 Aric Stewart for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #define ULONG CoreFoundation_ULONG
24 #define HRESULT CoreFoundation_HRESULT
25
26 #define LoadResource __carbon_LoadResource
27 #define CompareString __carbon_CompareString
28 #define GetCurrentThread __carbon_GetCurrentThread
29 #define GetCurrentProcess __carbon_GetCurrentProcess
30 #define AnimatePalette __carbon_AnimatePalette
31 #define EqualRgn __carbon_EqualRgn
32 #define FillRgn __carbon_FillRgn
33 #define FrameRgn __carbon_FrameRgn
34 #define GetPixel __carbon_GetPixel
35 #define InvertRgn __carbon_InvertRgn
36 #define LineTo __carbon_LineTo
37 #define OffsetRgn __carbon_OffsetRgn
38 #define PaintRgn __carbon_PaintRgn
39 #define Polygon __carbon_Polygon
40 #define ResizePalette __carbon_ResizePalette
41 #define SetRectRgn __carbon_SetRectRgn
42
43 #define CheckMenuItem __carbon_CheckMenuItem
44 #define DeleteMenu __carbon_DeleteMenu
45 #define DrawMenuBar __carbon_DrawMenuBar
46 #define EnableMenuItem __carbon_EnableMenuItem
47 #define EqualRect __carbon_EqualRect
48 #define FillRect __carbon_FillRect
49 #define FrameRect __carbon_FrameRect
50 #define GetCursor __carbon_GetCursor
51 #define GetMenu __carbon_GetMenu
52 #define InvertRect __carbon_InvertRect
53 #define IsWindowVisible __carbon_IsWindowVisible
54 #define MoveWindow __carbon_MoveWindow
55 #define OffsetRect __carbon_OffsetRect
56 #define PtInRect __carbon_PtInRect
57 #define SetCursor __carbon_SetCursor
58 #define SetRect __carbon_SetRect
59 #define ShowCursor __carbon_ShowCursor
60 #define ShowWindow __carbon_ShowWindow
61 #define UnionRect __carbon_UnionRect
62
63 #include <QuickTime/QuickTimeComponents.h>
64
65 #undef LoadResource
66 #undef CompareString
67 #undef GetCurrentThread
68 #undef _CDECL
69 #undef DPRINTF
70 #undef GetCurrentProcess
71 #undef AnimatePalette
72 #undef EqualRgn
73 #undef FillRgn
74 #undef FrameRgn
75 #undef GetPixel
76 #undef InvertRgn
77 #undef LineTo
78 #undef OffsetRgn
79 #undef PaintRgn
80 #undef Polygon
81 #undef ResizePalette
82 #undef SetRectRgn
83 #undef CheckMenuItem
84 #undef DeleteMenu
85 #undef DrawMenuBar
86 #undef EnableMenuItem
87 #undef EqualRect
88 #undef FillRect
89 #undef FrameRect
90 #undef GetCursor
91 #undef GetMenu
92 #undef InvertRect
93 #undef IsWindowVisible
94 #undef MoveWindow
95 #undef OffsetRect
96 #undef PtInRect
97 #undef SetCursor
98 #undef SetRect
99 #undef ShowCursor
100 #undef ShowWindow
101 #undef UnionRect
102
103 #undef ULONG
104 #undef HRESULT
105 #undef DPRINTF
106 #undef STDMETHODCALLTYPE
107
108 #include <assert.h>
109 #include <stdio.h>
110 #include <stdarg.h>
111
112 #define NONAMELESSSTRUCT
113 #define NONAMELESSUNION
114 #define COBJMACROS
115
116 #include "windef.h"
117 #include "winbase.h"
118 #include "wtypes.h"
119 #include "winuser.h"
120 #include "dshow.h"
121
122 #include "wine/unicode.h"
123 #include "wine/debug.h"
124
125 #include "qtprivate.h"
126
127 WINE_DEFAULT_DEBUG_CHANNEL(qtdatahandler);
128
129 static ComponentDescription myType =
130 {
131     'dhlr',
132     'WINE',
133     'WINE',
134     0,
135     0
136 };
137
138 typedef struct DHData
139 {
140     WineDataRefRecord dataRef;
141
142    Ptr AsyncPtr;
143    long AsyncRefCon;
144    DataHCompletionUPP AsyncCompletionRtn;
145 } DHData;
146
147 static pascal ComponentResult myComponentRoutineProc ( ComponentParameters *
148 cp, Handle componentStorage);
149
150 void RegisterWineDataHandler( void )
151 {
152     ComponentRoutineUPP MyComponentRoutineUPP;
153
154     MyComponentRoutineUPP = NewComponentRoutineUPP(&myComponentRoutineProc);
155     RegisterComponent( &myType , MyComponentRoutineUPP, 0, NULL, NULL, NULL);
156 }
157
158 static pascal ComponentResult myDataHCanUseDataRef ( DataHandler dh,
159                                        Handle dataRef,
160                                        long *useFlags
161 )
162 {
163     WineDataRefRecord *record = (WineDataRefRecord*)(*dataRef);
164     TRACE("%p %p %p\n",dh,dataRef,useFlags);
165     if (record->pReader == NULL)
166         return badComponentSelector;
167     *useFlags = kDataHCanRead;
168     return noErr;
169 }
170
171 static pascal ComponentResult myDataHSetDataRef ( DataHandler dh, Handle dataRef)
172 {
173     Handle storage = GetComponentInstanceStorage(dh);
174     DHData *data = (DHData*)*storage;
175     WineDataRefRecord* newRef = (WineDataRefRecord*)(*dataRef);
176     TRACE("\n");
177     if (newRef->pReader != data->dataRef.pReader)
178         IAsyncReader_AddRef(newRef->pReader);
179     data->dataRef = *newRef;
180     return noErr;
181 }
182
183 static pascal ComponentResult myDataHGetAvailableFileSize ( DataHandler dh,
184                                                    long *fileSize)
185 {
186     Handle storage = GetComponentInstanceStorage(dh);
187     DHData *data = (DHData*)*storage;
188     LONGLONG total;
189     LONGLONG available;
190
191     TRACE("%p\n",dh);
192
193     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
194     *fileSize = available;
195     return noErr;
196 }
197
198 static pascal ComponentResult myDataHGetFileSize ( DataHandler dh, long *fileSize)
199 {
200     Handle storage = GetComponentInstanceStorage(dh);
201     DHData *data = (DHData*)*storage;
202     LONGLONG total;
203     LONGLONG available;
204
205     TRACE("%p\n",dh);
206
207     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
208     *fileSize = total;
209     return noErr;
210 }
211
212 static pascal ComponentResult myDataHScheduleData ( DataHandler dh,
213                                              Ptr PlaceToPutDataPtr,
214                                              long FileOffset,
215                                              long DataSize,
216                                              long RefCon,
217                                              DataHSchedulePtr scheduleRec,
218                                              DataHCompletionUPP CompletionRtn)
219 {
220     Handle storage = GetComponentInstanceStorage(dh);
221     DHData *data = (DHData*)*storage;
222     HRESULT hr;
223     LONGLONG offset = FileOffset;
224     BYTE* buffer = (BYTE*)PlaceToPutDataPtr;
225
226     TRACE("%p %p %li %li %li %p %p\n",dh, PlaceToPutDataPtr, FileOffset, DataSize, RefCon, scheduleRec, CompletionRtn);
227
228     hr = IAsyncReader_SyncRead(data->dataRef.pReader, offset, DataSize, buffer);
229     TRACE("result %x\n",hr);
230     if (CompletionRtn)
231     {
232         if (data->AsyncCompletionRtn)
233             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
234
235         data->AsyncPtr = PlaceToPutDataPtr;
236         data->AsyncRefCon = RefCon;
237         data->AsyncCompletionRtn = CompletionRtn;
238     }
239
240     return noErr;
241 }
242
243 static pascal ComponentResult myDataHFinishData (DataHandler dh, Ptr PlaceToPutDataPtr, Boolean Cancel)
244 {
245     Handle storage = GetComponentInstanceStorage(dh);
246     DHData *data = (DHData*)*storage;
247     if (!data->AsyncCompletionRtn)
248         return noErr;
249     if (!PlaceToPutDataPtr || PlaceToPutDataPtr == data->AsyncPtr)
250     {
251         if (!Cancel)
252             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
253         data->AsyncPtr = NULL;
254         data->AsyncRefCon = 0;
255         data->AsyncCompletionRtn = NULL;
256     }
257     return noErr;
258 }
259
260 static pascal ComponentResult myDataHGetData ( DataHandler dh,
261                                         Handle h,
262                                         long hOffset,
263                                         long offset,
264                                         long size)
265 {
266     Handle storage = GetComponentInstanceStorage(dh);
267     DHData *data = (DHData*)*storage;
268     BYTE *target = (BYTE*)*h;
269     LONGLONG off = offset;
270     HRESULT hr;
271
272     TRACE("%p %p %li %li %li\n",dh, h, hOffset, offset, size);
273     hr = IAsyncReader_SyncRead(data->dataRef.pReader, off, size, target+hOffset);
274     TRACE("result %x\n",hr);
275
276     return noErr;
277 }
278
279 static pascal ComponentResult myDataHCompareDataRef ( DataHandler dh,
280                                                Handle dataRef, Boolean *equal)
281 {
282     WineDataRefRecord *ptr1;
283     Handle storage = GetComponentInstanceStorage(dh);
284     DHData *data = (DHData*)*storage;
285     TRACE("\n");
286
287     ptr1 = (WineDataRefRecord*)dataRef;
288
289     *equal = (ptr1->pReader == data->dataRef.pReader);
290     return noErr;
291 }
292
293 static pascal ComponentResult myDataHGetDataRef ( DataHandler dh, Handle *dataRef)
294 {
295     Handle storage = GetComponentInstanceStorage(dh);
296     TRACE("\n");
297     *dataRef = storage;
298     HandToHand(dataRef);
299     return noErr;
300 }
301
302 static pascal ComponentResult myDataHGetScheduleAheadTime ( DataHandler dh,
303                                                        long *millisecs)
304 {
305     TRACE("\n");
306     *millisecs = 1000;
307     return noErr;
308 }
309
310 static pascal ComponentResult myDataHGetInfoFlags ( DataHandler dh, UInt32 *flags)
311 {
312     TRACE("\n");
313     *flags = 0;
314     return noErr;
315 }
316
317 static pascal ComponentResult myDataHGetFileTypeOrdering ( DataHandler dh,
318                            DataHFileTypeOrderingHandle *orderingListHandle)
319 {
320     OSType orderlist[1] = {kDataHFileTypeExtension};
321     TRACE("\n");
322     PtrToHand( &orderlist, (Handle*)orderingListHandle, sizeof(OSType));
323     return noErr;
324 }
325
326 typedef struct {
327     const CFStringRef fname;
328     const int sig_length;
329     const BYTE sig[10];
330 } signature;
331
332 static const signature stream_sigs[] = {
333     {CFSTR("video.asf"),4,{0x30,0x26,0xb2,0x75}},
334     {CFSTR("video.mov"),8,{0x00,0x00,0x00,0x14,0x66,0x74,0x79,0x70}},
335     {CFSTR("video.mp4"),8,{0x00,0x00,0x00,0x18,0x66,0x74,0x79,0x70}},
336     {CFSTR("video.m4v"),8,{0x00,0x00,0x00,0x1c,0x66,0x74,0x79,0x70}},
337     {CFSTR("video.flv"),4,{0x46,0x4C,0x56,0x01}},
338     {CFSTR("video.mpg"),3,{0x00,0x00,0x01}},
339     {CFSTR("avideo.rm"),4,{0x2E,0x52,0x4D,0x46}}
340 };
341
342 static pascal ComponentResult myDataHGetFileName ( DataHandler dh, Str255 str)
343 {
344     Handle storage = GetComponentInstanceStorage(dh);
345     DHData *data = (DHData*)*storage;
346     TRACE("%p %s\n",str,debugstr_guid(&data->dataRef.streamSubtype));
347
348     /* Todo Expand this list */
349     if (IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_MPEG1Video) ||
350         IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_MPEG1System))
351         CFStringGetPascalString(CFSTR("video.mpg"),str,256,kCFStringEncodingMacRoman);
352     else if(IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_Asf))
353         CFStringGetPascalString(CFSTR("video.asf"),str,256,kCFStringEncodingMacRoman);
354     else if(IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_Avi))
355         CFStringGetPascalString(CFSTR("video.avi"),str,256,kCFStringEncodingMacRoman);
356     else if(IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_QTMovie))
357         CFStringGetPascalString(CFSTR("video.mov"),str,256,kCFStringEncodingMacRoman);
358     else
359     {
360         BYTE header[10] = {0,0,0,0,0,0,0,0,0,0};
361         int i;
362         IAsyncReader_SyncRead(data->dataRef.pReader, 0, 8, header);
363
364         for (i=0; i < sizeof(stream_sigs)/sizeof(signature); i++)
365             if (memcmp(header, stream_sigs[i].sig, stream_sigs[i].sig_length)==0)
366             {
367                 CFStringGetPascalString(stream_sigs[i].fname,str,256,kCFStringEncodingMacRoman);
368                 return noErr;
369             }
370
371         return badComponentSelector;
372     }
373
374     return noErr;
375 }
376
377 static pascal ComponentResult myDataHOpenForRead(DataHandler dh)
378 {
379     TRACE("\n");
380     return noErr;
381 }
382
383 static pascal ComponentResult myDataHTask(DataHandler dh)
384 {
385     Handle storage = GetComponentInstanceStorage(dh);
386     DHData *data = (DHData*)*storage;
387
388     if (data->AsyncCompletionRtn)
389     {
390         TRACE("Sending Completion\n");
391         InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
392         data->AsyncPtr = NULL;
393         data->AsyncRefCon = 0;
394         data->AsyncCompletionRtn = NULL;
395     }
396     return noErr;
397 }
398
399 static pascal ComponentResult myDataHPlaybackHints(DataHandler dh, long flags,
400                 unsigned long minFileOffset, unsigned long maxFileOffset,
401                 long bytesPerSecond)
402 {
403     TRACE("%lu %lu %li\n",minFileOffset, maxFileOffset, bytesPerSecond);
404     return noErr;
405 }
406
407 static pascal ComponentResult myDataHPlaybackHints64(DataHandler dh, long flags,
408                 wide *minFileOffset, wide *maxFileOffset,
409                 long bytesPerSecond)
410 {
411     if (TRACE_ON(qtdatahandler))
412     {
413         SInt64 minFileOffset64 = WideToSInt64(*minFileOffset);
414         LONGLONG minFileOffsetLL = minFileOffset64;
415         SInt64 maxFileOffset64 = WideToSInt64(*maxFileOffset);
416         LONGLONG maxFileOffsetLL = maxFileOffset64;
417
418         TRACE("%s %s %li\n",wine_dbgstr_longlong(minFileOffsetLL), wine_dbgstr_longlong(maxFileOffsetLL), bytesPerSecond);
419     }
420     return noErr;
421 }
422
423 static pascal ComponentResult myDataHGetFileSize64(DataHandler dh, wide * fileSize)
424 {
425     Handle storage = GetComponentInstanceStorage(dh);
426     DHData *data = (DHData*)*storage;
427     LONGLONG total;
428     LONGLONG available;
429     SInt64 total64;
430
431     TRACE("%p\n",dh);
432
433     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
434     total64 = total;
435     *fileSize = SInt64ToWide(total64);
436     return noErr;
437 }
438
439 static pascal ComponentResult myDataHGetFileSizeAsync ( DataHandler dh, wide *fileSize, DataHCompletionUPP CompletionRtn, long RefCon )
440 {
441     Handle storage = GetComponentInstanceStorage(dh);
442     DHData *data = (DHData*)*storage;
443     LONGLONG total;
444     LONGLONG available;
445     SInt64 total64;
446
447     TRACE("%p\n",dh);
448
449     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
450     total64 = total;
451     *fileSize = SInt64ToWide(total64);
452
453     if (CompletionRtn)
454     {
455         if (data->AsyncCompletionRtn)
456             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
457
458         data->AsyncPtr = (Ptr)fileSize;
459         data->AsyncRefCon = RefCon;
460         data->AsyncCompletionRtn = CompletionRtn;
461     }
462
463     return noErr;
464 }
465
466 static pascal ComponentResult myDataHGetAvailableFileSize64(DataHandler dh, wide * fileSize)
467 {
468     Handle storage = GetComponentInstanceStorage(dh);
469     DHData *data = (DHData*)*storage;
470     LONGLONG total;
471     LONGLONG available;
472     SInt64 total64;
473
474     TRACE("%p\n",dh);
475
476     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
477     total64 = available;
478     *fileSize = SInt64ToWide(total64);
479     return noErr;
480 }
481
482 static pascal ComponentResult myDataHScheduleData64( DataHandler dh,
483                                           Ptr PlaceToPutDataPtr,
484                                           const wide * FileOffset,
485                                           long DataSize,
486                                           long RefCon,
487                                           DataHSchedulePtr scheduleRec,
488                                           DataHCompletionUPP CompletionRtn)
489 {
490     Handle storage = GetComponentInstanceStorage(dh);
491     DHData *data = (DHData*)*storage;
492     HRESULT hr;
493     SInt64 fileOffset64 = WideToSInt64(*FileOffset);
494     LONGLONG offset = fileOffset64;
495     BYTE* buffer = (BYTE*)PlaceToPutDataPtr;
496
497     TRACE("%p %p %s %li %li %p %p\n",dh, PlaceToPutDataPtr, wine_dbgstr_longlong(offset), DataSize, RefCon, scheduleRec, CompletionRtn);
498
499     hr = IAsyncReader_SyncRead(data->dataRef.pReader, offset, DataSize, buffer);
500     TRACE("result %x\n",hr);
501     if (CompletionRtn)
502     {
503         if (data->AsyncCompletionRtn)
504             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
505
506         data->AsyncPtr = PlaceToPutDataPtr;
507         data->AsyncRefCon = RefCon;
508         data->AsyncCompletionRtn = CompletionRtn;
509     }
510
511     return noErr;
512 }
513
514 static const struct { LPVOID proc; ProcInfoType type;} componentFunctions[] =
515 {
516     {NULL, 0}, /* 0 */
517     {NULL, 0}, /* 1 */
518     {myDataHGetData,  kPascalStackBased
519             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
520             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
521             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
522             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
523             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
524             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
525 }, /* kDataHGetDataSelect                        */
526     {NULL, 0}, /* kDataHPutDataSelect                        */
527     {NULL, 0}, /* kDataHFlushDataSelect                      */
528     {NULL, 0}, /* kDataHOpenForWriteSelect                   */
529     {NULL, 0}, /* kDataHCloseForWriteSelect                  */
530     {NULL, 0}, /* 7 */
531     {myDataHOpenForRead, kPascalStackBased
532             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
533             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
534 }, /* kDataHOpenForReadSelect
535 */
536     {NULL, 0}, /* kDataHCloseForReadSelect                   */
537     {myDataHSetDataRef,  kPascalStackBased
538             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
539             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
540             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
541 }, /* kDataHSetDataRefSelect                     */
542     {myDataHGetDataRef,  kPascalStackBased
543             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
544             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
545             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
546 }, /* kDataHGetDataRefSelect                     */
547     {myDataHCompareDataRef,  kPascalStackBased
548             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
549             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
550             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
551             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Boolean*)))
552 }, /* kDataHCompareDataRefSelect                 */
553     {myDataHTask, kPascalStackBased
554             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
555             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
556 }, /* kDataHTaskSelect                           */
557     {myDataHScheduleData,  kPascalStackBased
558             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
559             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
560             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
561             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
562             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
563             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
564             | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(DataHSchedulePtr)))
565             | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(DataHCompletionUPP)))
566 }, /* kDataHScheduleDataSelect                   */
567     {myDataHFinishData, kPascalStackBased
568             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
569             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
570             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
571             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Boolean)))
572 }, /* kDataHFinishDataSelect                     */
573     {NULL, 0}, /* kDataHFlushCacheSelect       0x10              */
574     {NULL, 0}, /* kDataHResolveDataRefSelect                 */
575     {myDataHGetFileSize,  kPascalStackBased
576             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
577             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
578             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long*)))
579 }, /* kDataHGetFileSizeSelect                    */
580     {myDataHCanUseDataRef,  kPascalStackBased
581             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
582             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
583             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
584             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long*)))
585 }, /* kDataHCanUseDataRefSelect                  */
586     {NULL, 0}, /* kDataHGetVolumeListSelect                  */
587     {NULL, 0}, /* kDataHWriteSelect                          */
588     {NULL, 0}, /* kDataHPreextendSelect                      */
589     {NULL, 0}, /* kDataHSetFileSizeSelect                    */
590     {NULL, 0}, /* kDataHGetFreeSpaceSelect                   */
591     {NULL, 0}, /* kDataHCreateFileSelect                     */
592     {NULL, 0}, /* kDataHGetPreferredBlockSizeSelect          */
593     {NULL, 0}, /* kDataHGetDeviceIndexSelect                 */
594     {NULL, 0}, /* kDataHIsStreamingDataHandlerSelect         */
595     {NULL, 0}, /* kDataHGetDataInBufferSelect                */
596     {myDataHGetScheduleAheadTime,  kPascalStackBased
597             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
598             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
599             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long*)))
600 }, /* kDataHGetScheduleAheadTimeSelect           */
601 /* End of Required List */
602     {NULL, 0}, /* kDataHSetCacheSizeLimitSelect              */
603     {NULL, 0}, /* kDataHGetCacheSizeLimitSelect       0x20   */
604     {NULL, 0}, /* kDataHGetMovieSelect                       */
605     {NULL, 0}, /* kDataHAddMovieSelect                       */
606     {NULL, 0}, /* kDataHUpdateMovieSelect                    */
607     {NULL, 0}, /* kDataHDoesBufferSelect                     */
608     {myDataHGetFileName,  kPascalStackBased
609             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
610             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
611             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Str255*)))
612 }, /* kDataHGetFileNameSelect                    */
613     {myDataHGetAvailableFileSize,   kPascalStackBased
614             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
615             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
616             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long*)))
617 }, /* kDataHGetAvailableFileSizeSelect           */
618     {NULL, 0}, /* kDataHGetMacOSFileTypeSelect               */
619     {NULL, 0}, /* kDataHGetMIMETypeSelect                    */
620     {NULL, 0}, /* kDataHSetDataRefWithAnchorSelect           */
621     {NULL, 0}, /* kDataHGetDataRefWithAnchorSelect           */
622     {NULL, 0}, /* kDataHSetMacOSFileTypeSelect               */
623     {NULL, 0}, /* kDataHSetTimeBaseSelect                    */
624     {myDataHGetInfoFlags,  kPascalStackBased
625             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
626             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
627             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(UInt32*)))
628 }, /* kDataHGetInfoFlagsSelect                   */
629     {myDataHScheduleData64, kPascalStackBased
630             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
631             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
632             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
633             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(wide*)))
634             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
635             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
636             | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(DataHSchedulePtr)))
637             | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(DataHCompletionUPP)))
638 }, /* kDataHScheduleData64Select                 */
639     {NULL, 0}, /* kDataHWrite64Select                        */
640     {myDataHGetFileSize64, kPascalStackBased
641             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
642             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
643             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(wide*)))
644 }, /* kDataHGetFileSize64Select     0x30         */
645     {NULL, 0}, /* kDataHPreextend64Select                    */
646     {NULL, 0}, /* kDataHSetFileSize64Select                  */
647     {NULL, 0}, /* kDataHGetFreeSpace64Select                 */
648     {NULL, 0}, /* kDataHAppend64Select                       */
649     {NULL, 0}, /* kDataHReadAsyncSelect                      */
650     {NULL, 0}, /* kDataHPollReadSelect                       */
651     {NULL, 0}, /* kDataHGetDataAvailabilitySelect            */
652     {NULL, 0}, /* 0x0038 */
653     {NULL, 0}, /* 0x0039 */
654     {myDataHGetFileSizeAsync, kPascalStackBased
655             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
656             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
657             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(wide*)))
658             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(DataHCompletionUPP)))
659             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
660 }, /* kDataHGetFileSizeAsyncSelect               */
661     {NULL, 0}, /* kDataHGetDataRefAsTypeSelect               */
662     {NULL, 0}, /* kDataHSetDataRefExtensionSelect            */
663     {NULL, 0}, /* kDataHGetDataRefExtensionSelect            */
664     {NULL, 0}, /* kDataHGetMovieWithFlagsSelect              */
665     {NULL, 0}, /* 0x3F */
666     {myDataHGetFileTypeOrdering, kPascalStackBased
667             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
668             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
669             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(DataHFileTypeOrderingHandle*)))
670 }, /* kDataHGetFileTypeOrderingSelect  0x40      */
671     {NULL, 0}, /* kDataHCreateFileWithFlagsSelect            */
672     {NULL, 0}, /* kDataHGetMIMETypeAsyncSelect               */
673     {NULL, 0}, /* kDataHGetInfoSelect                        */
674     {NULL, 0}, /* kDataHSetIdleManagerSelect                 */
675     {NULL, 0}, /* kDataHDeleteFileSelect                     */
676     {NULL, 0}, /* kDataHSetMovieUsageFlagsSelect             */
677     {NULL, 0}, /* kDataHUseTemporaryDataRefSelect            */
678     {NULL, 0}, /* kDataHGetTemporaryDataRefCapabilitiesSelect */
679     {NULL, 0}, /* kDataHRenameFileSelect                     */
680     {NULL, 0}, /* 0x4A */
681     {NULL, 0}, /* 0x4B */
682     {NULL, 0}, /* 0x4C */
683     {NULL, 0}, /* 0x4D */
684     {myDataHGetAvailableFileSize64, kPascalStackBased
685             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
686             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
687             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(wide*)))
688 }, /* kDataHGetAvailableFileSize64Select         */
689     {NULL, 0}, /* kDataHGetDataAvailability64Select          */
690 };
691
692 static const struct { LPVOID proc; ProcInfoType type;} componentFunctions_2[] =
693 {
694     {myDataHPlaybackHints, kPascalStackBased
695             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
696             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
697             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
698             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(unsigned long)))
699             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(unsigned long)))
700             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
701 }, /* kDataHPlaybackHintsSelect     0x103 */
702     {myDataHPlaybackHints64, kPascalStackBased
703             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
704             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
705             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
706             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(wide*)))
707             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(wide*)))
708             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
709 }, /* kDataHPlaybackHints64Select   0x10E */
710     {NULL, 0}, /* kDataHGetDataRateSelect       0x110 */
711     {NULL, 0}, /* kDataHSetTimeHintsSelect      0x111 */
712 };
713
714 /* Component Functions */
715
716 static pascal ComponentResult myComponentOpen(ComponentInstance ci, ComponentInstance self)
717 {
718     DHData myData;
719     Handle storage;
720
721     ZeroMemory(&myData,sizeof(DHData));
722     PtrToHand( &myData, &storage, sizeof(DHData));
723     SetComponentInstanceStorage(self,storage);
724
725     return noErr;
726 }
727
728 static pascal ComponentResult myComponentClose(ComponentInstance ci, ComponentInstance self)
729 {
730     Handle storage = GetComponentInstanceStorage(self);
731     DHData *data;
732     if (storage)
733     {
734         data = (DHData*)*storage;
735         if (data && data->dataRef.pReader != NULL)
736             IAsyncReader_Release(data->dataRef.pReader);
737         DisposeHandle(storage);
738         SetComponentInstanceStorage(self,NULL);
739     }
740     return noErr;
741 }
742
743 static pascal ComponentResult myComponentCanDo(ComponentInstance ci, SInt16 ftnNumber)
744 {
745     TRACE("test 0x%x\n",ftnNumber);
746     if (ftnNumber <= kComponentOpenSelect && ftnNumber >= kComponentCanDoSelect)
747         return TRUE;
748     if (ftnNumber == kDataHPlaybackHintsSelect)
749         return TRUE;
750     if (ftnNumber == kDataHPlaybackHints64Select)
751         return TRUE;
752     if (ftnNumber > kDataHGetDataAvailability64Select)
753         return FALSE;
754     TRACE("impl? %i\n",(componentFunctions[ftnNumber].proc != NULL));
755     return (componentFunctions[ftnNumber].proc != NULL);
756 }
757
758 /* Main Proc */
759
760 static ComponentResult callOurFunction(LPVOID proc, ProcInfoType type, ComponentParameters * cp)
761 {
762     ComponentRoutineUPP myUUP;
763     ComponentResult result;
764
765     myUUP = NewComponentFunctionUPP(proc, type);
766     result = CallComponentFunction(cp, myUUP);
767     DisposeComponentFunctionUPP(myUUP);
768     return result;
769 }
770
771 static pascal ComponentResult myComponentRoutineProc ( ComponentParameters * cp,
772                                          Handle componentStorage)
773 {
774     switch (cp->what)
775     {
776         case kComponentOpenSelect:
777             return callOurFunction(myComponentOpen, uppCallComponentOpenProcInfo,  cp);
778         case kComponentCloseSelect:
779             return callOurFunction(myComponentClose, uppCallComponentOpenProcInfo,  cp);
780         case kComponentCanDoSelect:
781             return callOurFunction(myComponentCanDo, uppCallComponentCanDoProcInfo,  cp);
782         case kDataHPlaybackHintsSelect:
783             return callOurFunction(componentFunctions_2[0].proc, componentFunctions_2[0].type, cp);
784         case kDataHPlaybackHints64Select:
785             return callOurFunction(componentFunctions_2[1].proc, componentFunctions_2[1].type, cp);
786     }
787
788     if (cp->what > 0 && cp->what <=kDataHGetDataAvailability64Select && componentFunctions[cp->what].proc)
789         return callOurFunction(componentFunctions[cp->what].proc, componentFunctions[cp->what].type, cp);
790
791     FIXME("unhandled select 0x%x\n",cp->what);
792     return badComponentSelector;
793 }