ReactOS 0.4.15-dev-7834-g00c4b3d
ungif.c
Go to the documentation of this file.
1/*
2 * Gif extracting routines - derived from libungif
3 *
4 * Portions Copyright 2006 Mike McCormack
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/*
22 * Original copyright notice:
23 *
24 * The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond
25 *
26 * Permission is hereby granted, free of charge, to any person obtaining a copy
27 * of this software and associated documentation files (the "Software"), to deal
28 * in the Software without restriction, including without limitation the rights
29 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30 * copies of the Software, and to permit persons to whom the Software is
31 * furnished to do so, subject to the following conditions:
32 *
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
35 */
36
37
38/******************************************************************************
39 * "Gif-Lib" - Yet another gif library.
40 *
41 * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990
42 ******************************************************************************
43 * The kernel of the GIF Decoding process can be found here.
44 ******************************************************************************
45 * History:
46 * 16 Jun 89 - Version 1.0 by Gershon Elber.
47 * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names).
48 *****************************************************************************/
49
50#include <stdlib.h>
51#include <string.h>
52
53#include <stdarg.h>
54#include "windef.h"
55#include "winbase.h"
56#include "ungif.h"
57#include "wine/debug.h"
58
60
61static void *ungif_alloc( size_t sz )
62{
63 return HeapAlloc( GetProcessHeap(), 0, sz );
64}
65
66static void *ungif_calloc( size_t num, size_t sz )
67{
69}
70
71static void *ungif_realloc( void *ptr, size_t sz )
72{
73 return HeapReAlloc( GetProcessHeap(), 0, ptr, sz );
74}
75
76static void ungif_free( void *ptr )
77{
79}
80
81#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
82#define LZ_BITS 12
83
84#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
85
86typedef struct GifFilePrivateType {
87 GifWord BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */
88 ClearCode, /* The CLEAR LZ code. */
89 EOFCode, /* The EOF LZ code. */
90 RunningCode, /* The next code algorithm can generate. */
91 RunningBits, /* The number of bits required to represent RunningCode. */
92 MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
93 LastCode, /* The code before the current code. */
94 CrntCode, /* Current algorithm code. */
95 StackPtr, /* For character stack (see below). */
96 CrntShiftState; /* Number of bits in CrntShiftDWord. */
97 unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
98 unsigned long PixelCount; /* Number of pixels in image. */
99 InputFunc Read; /* function to read gif input (TVT) */
100 GifByteType Buf[256]; /* Compressed input is buffered here. */
101 GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
102 GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */
105
106/* avoid extra function call in case we use fread (TVT) */
107#define READ(_gif,_buf,_len) \
108 ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len)
109
110static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
111static int DGifSetupDecompress(GifFileType *GifFile);
112static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen);
113static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, int ClearCode);
114static int DGifDecompressInput(GifFileType *GifFile, int *Code);
115static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
116 GifByteType *NextByte);
117
118static int DGifGetExtensionNext(GifFileType * GifFile, GifByteType ** GifExtension);
119static int DGifGetCodeNext(GifFileType * GifFile, GifByteType ** GifCodeBlock);
120
121/******************************************************************************
122 * Miscellaneous utility functions
123 *****************************************************************************/
124
125/* return smallest bitfield size n will fit in */
126static int
127BitSize(int n) {
128
129 register int i;
130
131 for (i = 1; i <= 8; i++)
132 if ((1 << i) >= n)
133 break;
134 return (i);
135}
136
137/******************************************************************************
138 * Color map object functions
139 *****************************************************************************/
140
141/*
142 * Allocate a color map of given size; initialize with contents of
143 * ColorMap if that pointer is non-NULL.
144 */
145static ColorMapObject *
146MakeMapObject(int ColorCount,
147 const GifColorType * ColorMap) {
148
150
151 /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
152 * make the user know that or should we automatically round up instead? */
153 if (ColorCount != (1 << BitSize(ColorCount))) {
154 return NULL;
155 }
156
158 if (Object == NULL) {
159 return NULL;
160 }
161
162 Object->Colors = ungif_calloc(ColorCount, sizeof(GifColorType));
163 if (Object->Colors == NULL) {
165 return NULL;
166 }
167
168 Object->ColorCount = ColorCount;
169 Object->BitsPerPixel = BitSize(ColorCount);
170
171 if (ColorMap) {
172 memcpy(Object->Colors, ColorMap, ColorCount * sizeof(GifColorType));
173 }
174
175 return (Object);
176}
177
178/*
179 * Free a color map object
180 */
181static void
183
184 if (Object != NULL) {
185 ungif_free(Object->Colors);
187 /*** FIXME:
188 * When we are willing to break API we need to make this function
189 * FreeMapObject(ColorMapObject **Object)
190 * and do this assignment to NULL here:
191 * *Object = NULL;
192 */
193 }
194}
195
196static int
198 int Len,
199 const unsigned char ExtData[]) {
200
201 ExtensionBlock *ep;
202
203 if (New->ExtensionBlocks == NULL)
204 New->ExtensionBlocks = ungif_alloc(sizeof(ExtensionBlock));
205 else
206 New->ExtensionBlocks = ungif_realloc(New->ExtensionBlocks,
207 sizeof(ExtensionBlock) *
208 (New->ExtensionBlockCount + 1));
209
210 if (New->ExtensionBlocks == NULL)
211 return (GIF_ERROR);
212
213 ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
214
215 ep->ByteCount=Len + 3;
216 ep->Bytes = ungif_alloc(ep->ByteCount + 3);
217 if (ep->Bytes == NULL)
218 return (GIF_ERROR);
219
220 /* Extension Header */
221 ep->Bytes[0] = 0x21;
222 ep->Bytes[1] = New->Function;
223 ep->Bytes[2] = Len;
224
225 if (ExtData) {
226 memcpy(ep->Bytes + 3, ExtData, Len);
227 ep->Function = New->Function;
228 }
229
230 return (GIF_OK);
231}
232
233static int
235 int Len,
236 const unsigned char ExtData[])
237{
238 ExtensionBlock *ep;
239
240 if (New->ExtensionBlocks == NULL)
241 return (GIF_ERROR);
242
243 ep = &New->ExtensionBlocks[New->ExtensionBlockCount - 1];
244
245 ep->Bytes = ungif_realloc(ep->Bytes, ep->ByteCount + Len + 1);
246 if (ep->Bytes == NULL)
247 return (GIF_ERROR);
248
249 ep->Bytes[ep->ByteCount] = Len;
250
251 if (ExtData)
252 memcpy(ep->Bytes + ep->ByteCount + 1, ExtData, Len);
253
254 ep->ByteCount += Len + 1;
255
256 return (GIF_OK);
257}
258
259static void
261{
262 ExtensionBlock *ep;
263
264 if ((Extensions == NULL) || (Extensions->ExtensionBlocks == NULL)) {
265 return;
266 }
267 for (ep = Extensions->ExtensionBlocks;
269 ungif_free(ep->Bytes);
272}
273
274/******************************************************************************
275 * Image block allocation functions
276******************************************************************************/
277
278static void
280
281 SavedImage *sp;
282
283 if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
284 return;
285 }
286 for (sp = GifFile->SavedImages;
287 sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
288 if (sp->ImageDesc.ColorMap) {
289 FreeMapObject(sp->ImageDesc.ColorMap);
290 sp->ImageDesc.ColorMap = NULL;
291 }
292
293 ungif_free(sp->RasterBits);
294
295 if (sp->Extensions.ExtensionBlocks)
296 FreeExtension(&sp->Extensions);
297 }
298 ungif_free(GifFile->SavedImages);
299 GifFile->SavedImages=NULL;
300}
301
302/******************************************************************************
303 * This routine should be called before any other DGif calls. Note that
304 * this routine is called automatically from DGif file open routines.
305 *****************************************************************************/
306static int
308
309 int i, BitsPerPixel, SortFlag;
310 GifByteType Buf[3];
311
312 /* Put the screen descriptor into the file: */
313 if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
314 DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
315 return GIF_ERROR;
316
317 if (READ(GifFile, Buf, 3) != 3) {
318 return GIF_ERROR;
319 }
320 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
321 SortFlag = (Buf[0] & 0x08) != 0;
322 BitsPerPixel = (Buf[0] & 0x07) + 1;
323 GifFile->SBackGroundColor = Buf[1];
324 GifFile->SAspectRatio = Buf[2];
325 if (Buf[0] & 0x80) { /* Do we have global color map? */
326
327 GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
328 if (GifFile->SColorMap == NULL) {
329 return GIF_ERROR;
330 }
331
332 /* Get the global color map: */
333 GifFile->SColorMap->SortFlag = SortFlag;
334 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
335 if (READ(GifFile, Buf, 3) != 3) {
336 FreeMapObject(GifFile->SColorMap);
337 GifFile->SColorMap = NULL;
338 return GIF_ERROR;
339 }
340 GifFile->SColorMap->Colors[i].Red = Buf[0];
341 GifFile->SColorMap->Colors[i].Green = Buf[1];
342 GifFile->SColorMap->Colors[i].Blue = Buf[2];
343 }
344 } else {
345 GifFile->SColorMap = NULL;
346 }
347
348 return GIF_OK;
349}
350
351/******************************************************************************
352 * This routine should be called before any attempt to read an image.
353 *****************************************************************************/
354static int
357
358 GifByteType Buf;
359
360 if (READ(GifFile, &Buf, 1) != 1) {
361 /* Wine-specific behavior: Native accepts broken GIF files that have no
362 * terminator, so we match this by treating EOF as a terminator. */
364 return GIF_OK;
365 }
366
367 switch (Buf) {
368 case ',':
370 break;
371 case '!':
373 break;
374 case ';':
376 break;
377 default:
379 return GIF_ERROR;
380 }
381
382 return GIF_OK;
383}
384
385/******************************************************************************
386 * This routine should be called before any attempt to read an image.
387 * Note it is assumed the Image desc. header (',') has been read.
388 *****************************************************************************/
389static int
391
392 int i, BitsPerPixel, SortFlag;
393 GifByteType Buf[3];
394 GifFilePrivateType *Private = GifFile->Private;
395 SavedImage *sp;
396
397 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
398 DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
399 DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
400 DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
401 return GIF_ERROR;
402 if (READ(GifFile, Buf, 1) != 1) {
403 return GIF_ERROR;
404 }
405 BitsPerPixel = (Buf[0] & 0x07) + 1;
406 SortFlag = (Buf[0] & 0x20) != 0;
407 GifFile->Image.Interlace = (Buf[0] & 0x40);
408 if (Buf[0] & 0x80) { /* Does this image have local color map? */
409
410 FreeMapObject(GifFile->Image.ColorMap);
411
412 GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
413 if (GifFile->Image.ColorMap == NULL) {
414 return GIF_ERROR;
415 }
416
417 /* Get the image local color map: */
418 GifFile->Image.ColorMap->SortFlag = SortFlag;
419 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
420 if (READ(GifFile, Buf, 3) != 3) {
421 FreeMapObject(GifFile->Image.ColorMap);
422 GifFile->Image.ColorMap = NULL;
423 return GIF_ERROR;
424 }
425 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
426 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
427 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
428 }
429 } else if (GifFile->Image.ColorMap) {
430 FreeMapObject(GifFile->Image.ColorMap);
431 GifFile->Image.ColorMap = NULL;
432 }
433
434 if (GifFile->SavedImages) {
435 if ((GifFile->SavedImages = ungif_realloc(GifFile->SavedImages,
436 sizeof(SavedImage) *
437 (GifFile->ImageCount + 1))) == NULL) {
438 return GIF_ERROR;
439 }
440 } else {
441 if ((GifFile->SavedImages = ungif_alloc(sizeof(SavedImage))) == NULL) {
442 return GIF_ERROR;
443 }
444 }
445
446 sp = &GifFile->SavedImages[GifFile->ImageCount];
447 sp->ImageDesc = GifFile->Image;
448 if (GifFile->Image.ColorMap != NULL) {
449 sp->ImageDesc.ColorMap = MakeMapObject(
450 GifFile->Image.ColorMap->ColorCount,
451 GifFile->Image.ColorMap->Colors);
452 if (sp->ImageDesc.ColorMap == NULL) {
453 return GIF_ERROR;
454 }
455 sp->ImageDesc.ColorMap->SortFlag = GifFile->Image.ColorMap->SortFlag;
456 }
457 sp->RasterBits = NULL;
458 sp->Extensions.ExtensionBlockCount = 0;
459 sp->Extensions.ExtensionBlocks = NULL;
460
461 GifFile->ImageCount++;
462
463 Private->PixelCount = (long)GifFile->Image.Width *
464 (long)GifFile->Image.Height;
465
466 DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
467
468 return GIF_OK;
469}
470
471/******************************************************************************
472 * Get one full scanned line (Line) of length LineLen from GIF file.
473 *****************************************************************************/
474static int
477 int LineLen) {
478
479 GifByteType *Dummy;
480 GifFilePrivateType *Private = GifFile->Private;
481
482 if (!LineLen)
483 LineLen = GifFile->Image.Width;
484
485 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
486 return GIF_ERROR;
487 }
488
489 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
490 if (Private->PixelCount == 0) {
491 /* We probably would not be called any more, so lets clean
492 * everything before we return: need to flush out all rest of
493 * image until empty block (size 0) detected. We use GetCodeNext. */
494 do
495 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
496 {
497 WARN("GIF is not properly terminated\n");
498 break;
499 }
500 while (Dummy != NULL) ;
501 }
502 return GIF_OK;
503 } else
504 return GIF_ERROR;
505}
506
507/******************************************************************************
508 * Get an extension block (see GIF manual) from gif file. This routine only
509 * returns the first data block, and DGifGetExtensionNext should be called
510 * after this one until NULL extension is returned.
511 * The Extension should NOT be freed by the user (not dynamically allocated).
512 * Note it is assumed the Extension desc. header ('!') has been read.
513 *****************************************************************************/
514static int
516 int *ExtCode,
518
519 GifByteType Buf;
520
521 if (READ(GifFile, &Buf, 1) != 1) {
522 return GIF_ERROR;
523 }
524 *ExtCode = Buf;
525
526 return DGifGetExtensionNext(GifFile, Extension);
527}
528
529/******************************************************************************
530 * Get a following extension block (see GIF manual) from gif file. This
531 * routine should be called until NULL Extension is returned.
532 * The Extension should NOT be freed by the user (not dynamically allocated).
533 *****************************************************************************/
534static int
537
538 GifByteType Buf;
539 GifFilePrivateType *Private = GifFile->Private;
540
541 if (READ(GifFile, &Buf, 1) != 1) {
542 return GIF_ERROR;
543 }
544 if (Buf > 0) {
545 *Extension = Private->Buf; /* Use private unused buffer. */
546 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
547 if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
548 return GIF_ERROR;
549 }
550 } else
551 *Extension = NULL;
552
553 return GIF_OK;
554}
555
556/******************************************************************************
557 * Get 2 bytes (word) from the given file:
558 *****************************************************************************/
559static int
561 GifWord *Word) {
562
563 unsigned char c[2];
564
565 if (READ(GifFile, c, 2) != 2) {
566 return GIF_ERROR;
567 }
568
569 *Word = (((unsigned int)c[1]) << 8) + c[0];
570 return GIF_OK;
571}
572
573/******************************************************************************
574 * Continue to get the image code in compressed form. This routine should be
575 * called until NULL block is returned.
576 * The block should NOT be freed by the user (not dynamically allocated).
577 *****************************************************************************/
578static int
580 GifByteType ** CodeBlock) {
581
582 GifByteType Buf;
583 GifFilePrivateType *Private = GifFile->Private;
584
585 if (READ(GifFile, &Buf, 1) != 1) {
586 return GIF_ERROR;
587 }
588
589 if (Buf > 0) {
590 *CodeBlock = Private->Buf; /* Use private unused buffer. */
591 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
592 if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
593 return GIF_ERROR;
594 }
595 } else {
596 *CodeBlock = NULL;
597 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
598 Private->PixelCount = 0; /* And local info. indicate image read. */
599 }
600
601 return GIF_OK;
602}
603
604/******************************************************************************
605 * Setup the LZ decompression for this image:
606 *****************************************************************************/
607static int
609
610 int i, BitsPerPixel;
611 GifByteType CodeSize;
613 GifFilePrivateType *Private = GifFile->Private;
614
615 READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
616 BitsPerPixel = CodeSize;
617
618 Private->Buf[0] = 0; /* Input Buffer empty. */
619 Private->BitsPerPixel = BitsPerPixel;
620 Private->ClearCode = (1 << BitsPerPixel);
621 Private->EOFCode = Private->ClearCode + 1;
622 Private->RunningCode = Private->EOFCode + 1;
623 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
624 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
625 Private->StackPtr = 0; /* No pixels on the pixel stack. */
626 Private->LastCode = NO_SUCH_CODE;
627 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
628 Private->CrntShiftDWord = 0;
629
630 Prefix = Private->Prefix;
631 for (i = 0; i <= LZ_MAX_CODE; i++)
633
634 return GIF_OK;
635}
636
637/******************************************************************************
638 * The LZ decompression routine:
639 * This version decompress the given gif file into Line of length LineLen.
640 * This routine can be called few times (one per scan line, for example), in
641 * order the complete the whole image.
642 *****************************************************************************/
643static int
646 int LineLen) {
647
648 int i = 0;
649 int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
650 GifByteType *Stack, *Suffix;
652 GifFilePrivateType *Private = GifFile->Private;
653
654 StackPtr = Private->StackPtr;
655 Prefix = Private->Prefix;
656 Suffix = Private->Suffix;
657 Stack = Private->Stack;
658 EOFCode = Private->EOFCode;
659 ClearCode = Private->ClearCode;
660 LastCode = Private->LastCode;
661
662 if (StackPtr != 0) {
663 /* Let pop the stack off before continuing to read the gif file: */
664 while (StackPtr != 0 && i < LineLen)
665 Line[i++] = Stack[--StackPtr];
666 }
667
668 while (i < LineLen) { /* Decode LineLen items. */
669 if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
670 return GIF_ERROR;
671
672 if (CrntCode == EOFCode) {
673 /* Note, however, that usually we will not be here as we will stop
674 * decoding as soon as we got all the pixel, or EOF code will
675 * not be read at all, and DGifGetLine/Pixel clean everything. */
676 if (i != LineLen - 1 || Private->PixelCount != 0) {
677 return GIF_ERROR;
678 }
679 i++;
680 } else if (CrntCode == ClearCode) {
681 /* We need to start over again: */
682 for (j = 0; j <= LZ_MAX_CODE; j++)
684 Private->RunningCode = Private->EOFCode + 1;
685 Private->RunningBits = Private->BitsPerPixel + 1;
686 Private->MaxCode1 = 1 << Private->RunningBits;
687 LastCode = Private->LastCode = NO_SUCH_CODE;
688 } else {
689 /* It's a regular code - if in pixel range simply add it to output
690 * stream, otherwise trace to codes linked list until the prefix
691 * is in pixel range: */
692 if (CrntCode < ClearCode) {
693 /* This is simple - its pixel scalar, so add it to output: */
694 Line[i++] = CrntCode;
695 } else {
696 /* It's a code to be traced: trace the linked list
697 * until the prefix is a pixel, while pushing the suffix
698 * pixels on our stack. If we done, pop the stack in reverse
699 * order (that's what stack is good for!) for output. */
700 if (Prefix[CrntCode] == NO_SUCH_CODE) {
701 /* Only allowed if CrntCode is exactly the running code:
702 * In that case CrntCode = XXXCode, CrntCode or the
703 * prefix code is last code and the suffix char is
704 * exactly the prefix of last code! */
705 if (CrntCode == Private->RunningCode - 2) {
706 CrntPrefix = LastCode;
707 Suffix[Private->RunningCode - 2] =
708 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
709 LastCode,
710 ClearCode);
711 } else {
712 return GIF_ERROR;
713 }
714 } else
715 CrntPrefix = CrntCode;
716
717 /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
718 * during the trace. As we might loop forever, in case of
719 * defective image, we count the number of loops we trace
720 * and stop if we got LZ_MAX_CODE. Obviously we cannot
721 * loop more than that. */
722 j = 0;
723 while (j++ <= LZ_MAX_CODE &&
724 CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
725 Stack[StackPtr++] = Suffix[CrntPrefix];
726 CrntPrefix = Prefix[CrntPrefix];
727 }
728 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
729 return GIF_ERROR;
730 }
731 /* Push the last character on stack: */
732 Stack[StackPtr++] = CrntPrefix;
733
734 /* Now lets pop all the stack into output: */
735 while (StackPtr != 0 && i < LineLen)
736 Line[i++] = Stack[--StackPtr];
737 }
738 if (LastCode != NO_SUCH_CODE) {
739 Prefix[Private->RunningCode - 2] = LastCode;
740
741 if (CrntCode == Private->RunningCode - 2) {
742 /* Only allowed if CrntCode is exactly the running code:
743 * In that case CrntCode = XXXCode, CrntCode or the
744 * prefix code is last code and the suffix char is
745 * exactly the prefix of last code! */
746 Suffix[Private->RunningCode - 2] =
747 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
748 } else {
749 Suffix[Private->RunningCode - 2] =
750 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
751 }
752 }
753 LastCode = CrntCode;
754 }
755 }
756
757 Private->LastCode = LastCode;
758 Private->StackPtr = StackPtr;
759
760 return GIF_OK;
761}
762
763/******************************************************************************
764 * Routine to trace the Prefixes linked list until we get a prefix which is
765 * not code, but a pixel value (less than ClearCode). Returns that pixel value.
766 * If image is defective, we might loop here forever, so we limit the loops to
767 * the maximum possible if image O.k. - LZ_MAX_CODE times.
768 *****************************************************************************/
769static int
771 int Code,
772 int ClearCode) {
773
774 int i = 0;
775
776 while (Code > ClearCode && i++ <= LZ_MAX_CODE)
777 Code = Prefix[Code];
778 return Code;
779}
780
781/******************************************************************************
782 * The LZ decompression input routine:
783 * This routine is responsible for the decompression of the bit stream from
784 * 8 bits (bytes) packets, into the real codes.
785 * Returns GIF_OK if read successfully.
786 *****************************************************************************/
787static int
789 int *Code) {
790
791 GifFilePrivateType *Private = GifFile->Private;
792
793 GifByteType NextByte;
794 static const unsigned short CodeMasks[] = {
795 0x0000, 0x0001, 0x0003, 0x0007,
796 0x000f, 0x001f, 0x003f, 0x007f,
797 0x00ff, 0x01ff, 0x03ff, 0x07ff,
798 0x0fff
799 };
800 /* The image can't contain more than LZ_BITS per code. */
801 if (Private->RunningBits > LZ_BITS) {
802 return GIF_ERROR;
803 }
804
805 while (Private->CrntShiftState < Private->RunningBits) {
806 /* Needs to get more bytes from input stream for next code: */
807 if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
808 return GIF_ERROR;
809 }
810 Private->CrntShiftDWord |=
811 ((unsigned long)NextByte) << Private->CrntShiftState;
812 Private->CrntShiftState += 8;
813 }
814 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
815
816 Private->CrntShiftDWord >>= Private->RunningBits;
817 Private->CrntShiftState -= Private->RunningBits;
818
819 /* If code cannot fit into RunningBits bits, must raise its size. Note
820 * however that codes above 4095 are used for special signaling.
821 * If we're using LZ_BITS bits already and we're at the max code, just
822 * keep using the table as it is, don't increment Private->RunningCode.
823 */
824 if (Private->RunningCode < LZ_MAX_CODE + 2 &&
825 ++Private->RunningCode > Private->MaxCode1 &&
826 Private->RunningBits < LZ_BITS) {
827 Private->MaxCode1 <<= 1;
828 Private->RunningBits++;
829 }
830 return GIF_OK;
831}
832
833/******************************************************************************
834 * This routines read one gif data block at a time and buffers it internally
835 * so that the decompression routine could access it.
836 * The routine returns the next byte from its internal buffer (or read next
837 * block in if buffer empty) and returns GIF_OK if successful.
838 *****************************************************************************/
839static int
841 GifByteType * Buf,
842 GifByteType * NextByte) {
843
844 if (Buf[0] == 0) {
845 /* Needs to read the next buffer - this one is empty: */
846 if (READ(GifFile, Buf, 1) != 1) {
847 return GIF_ERROR;
848 }
849 /* There shouldn't be any empty data blocks here as the LZW spec
850 * says the LZW termination code should come first. Therefore we
851 * shouldn't be inside this routine at that point.
852 */
853 if (Buf[0] == 0) {
854 return GIF_ERROR;
855 }
856 if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
857 return GIF_ERROR;
858 }
859 *NextByte = Buf[1];
860 Buf[1] = 2; /* We use now the second place as last char read! */
861 Buf[0]--;
862 } else {
863 *NextByte = Buf[Buf[1]++];
864 Buf[0]--;
865 }
866
867 return GIF_OK;
868}
869
870/******************************************************************************
871 * This routine reads an entire GIF into core, hanging all its state info off
872 * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle()
873 * first to initialize I/O. Its inverse is EGifSpew().
874 ******************************************************************************/
875int
877
878 int ImageSize;
879 GifRecordType RecordType;
880 SavedImage *sp;
881 GifByteType *ExtData;
882 Extensions temp_save;
883
884 temp_save.ExtensionBlocks = NULL;
885 temp_save.ExtensionBlockCount = 0;
886
887 do {
888 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
889 return (GIF_ERROR);
890
891 switch (RecordType) {
893 if (DGifGetImageDesc(GifFile) == GIF_ERROR)
894 return (GIF_ERROR);
895
896 sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
897 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
898
899 sp->RasterBits = ungif_alloc(ImageSize * sizeof(GifPixelType));
900 if (sp->RasterBits == NULL) {
901 return GIF_ERROR;
902 }
903 if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) ==
904 GIF_ERROR)
905 return (GIF_ERROR);
906 if (temp_save.ExtensionBlocks) {
907 sp->Extensions.ExtensionBlocks = temp_save.ExtensionBlocks;
908 sp->Extensions.ExtensionBlockCount = temp_save.ExtensionBlockCount;
909
910 temp_save.ExtensionBlocks = NULL;
911 temp_save.ExtensionBlockCount = 0;
912
913 /* FIXME: The following is wrong. It is left in only for
914 * backwards compatibility. Someday it should go away. Use
915 * the sp->ExtensionBlocks->Function variable instead. */
916 sp->Extensions.Function = sp->Extensions.ExtensionBlocks[0].Function;
917 }
918 break;
919
921 {
922 int Function;
924
925 if (DGifGetExtension(GifFile, &Function, &ExtData) == GIF_ERROR)
926 return (GIF_ERROR);
927
928 if (GifFile->ImageCount || Function == GRAPHICS_EXT_FUNC_CODE)
929 Extensions = &temp_save;
930 else
931 Extensions = &GifFile->Extensions;
932
934
935 if (ExtData)
936 {
937 /* Create an extension block with our data */
938 if (AddExtensionBlock(Extensions, ExtData[0], &ExtData[1]) == GIF_ERROR)
939 return (GIF_ERROR);
940 }
941 else /* Empty extension block */
942 {
944 return (GIF_ERROR);
945 }
946
947 while (ExtData != NULL) {
948 int Len;
950
951 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
952 return (GIF_ERROR);
953
954 if (ExtData)
955 {
956 Len = ExtData[0];
957 Data = &ExtData[1];
958 }
959 else
960 {
961 Len = 0;
962 Data = NULL;
963 }
964
966 return (GIF_ERROR);
967 }
968 break;
969 }
970
972 break;
973
974 default: /* Should be trapped by DGifGetRecordType */
975 break;
976 }
977 } while (RecordType != TERMINATE_RECORD_TYPE);
978
979 /* Just in case the Gif has an extension block without an associated
980 * image... (Should we save this into a savefile structure with no image
981 * instead? Have to check if the present writing code can handle that as
982 * well.... */
983 if (temp_save.ExtensionBlocks)
984 FreeExtension(&temp_save);
985
986 return (GIF_OK);
987}
988
989/******************************************************************************
990 * GifFileType constructor with user supplied input function (TVT)
991 *****************************************************************************/
993DGifOpen(void *userData,
994 InputFunc readFunc) {
995
996 unsigned char Buf[GIF_STAMP_LEN + 1];
997 GifFileType *GifFile;
998 GifFilePrivateType *Private;
999
1000 GifFile = ungif_alloc(sizeof(GifFileType));
1001 if (GifFile == NULL) {
1002 return NULL;
1003 }
1004
1005 memset(GifFile, '\0', sizeof(GifFileType));
1006
1007 Private = ungif_alloc(sizeof(GifFilePrivateType));
1008 if (!Private) {
1009 ungif_free(GifFile);
1010 return NULL;
1011 }
1012
1013 GifFile->Private = (void*)Private;
1014
1015 Private->Read = readFunc; /* TVT */
1016 GifFile->UserData = userData; /* TVT */
1017
1018 /* Lets see if this is a GIF file: */
1019 if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
1020 ungif_free(Private);
1021 ungif_free(GifFile);
1022 return NULL;
1023 }
1024
1025 /* The GIF Version number is ignored at this time. Maybe we should do
1026 * something more useful with it. */
1027 Buf[GIF_STAMP_LEN] = 0;
1028 if (memcmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
1029 ungif_free(Private);
1030 ungif_free(GifFile);
1031 return NULL;
1032 }
1033
1034 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
1035 ungif_free(Private);
1036 ungif_free(GifFile);
1037 return NULL;
1038 }
1039
1040 return GifFile;
1041}
1042
1043/******************************************************************************
1044 * This routine should be called last, to close the GIF file.
1045 *****************************************************************************/
1046int
1048
1049 GifFilePrivateType *Private;
1050
1051 if (GifFile == NULL)
1052 return GIF_ERROR;
1053
1054 Private = GifFile->Private;
1055
1056 if (GifFile->Image.ColorMap) {
1057 FreeMapObject(GifFile->Image.ColorMap);
1058 GifFile->Image.ColorMap = NULL;
1059 }
1060
1061 if (GifFile->SColorMap) {
1062 FreeMapObject(GifFile->SColorMap);
1063 GifFile->SColorMap = NULL;
1064 }
1065
1066 ungif_free(Private);
1067 Private = NULL;
1068
1069 if (GifFile->SavedImages) {
1070 FreeSavedImages(GifFile);
1071 GifFile->SavedImages = NULL;
1072 }
1073
1074 FreeExtension(&GifFile->Extensions);
1075
1076 ungif_free(GifFile);
1077
1078 return GIF_OK;
1079}
Type
Definition: Type.h:7
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WARN(fmt,...)
Definition: debug.h:112
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
#define Code
Definition: deflate.h:80
#define Len
Definition: deflate.h:82
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
_Inout_opt_ PUNICODE_STRING Extension
Definition: fltkernel.h:1092
GLdouble n
Definition: glext.h:7729
const GLubyte * c
Definition: glext.h:8905
GLuint GLuint num
Definition: glext.h:9618
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static const WCHAR sp[]
Definition: suminfo.c:287
#define long
Definition: qsort.c:33
#define New(t)
Definition: rtf.h:1086
#define memset(x, y, z)
Definition: compat.h:39
GifColorType * Colors
Definition: ungif.h:92
int SortFlag
Definition: ungif.h:91
int ColorCount
Definition: ungif.h:89
char * Bytes
Definition: ungif.h:105
int ByteCount
Definition: ungif.h:104
int Function
Definition: ungif.h:103
int Function
Definition: ungif.h:109
ExtensionBlock * ExtensionBlocks
Definition: ungif.h:111
int ExtensionBlockCount
Definition: ungif.h:110
GifByteType Blue
Definition: ungif.h:85
GifByteType Green
Definition: ungif.h:85
GifByteType Red
Definition: ungif.h:85
GifWord CrntCode
Definition: ungif.c:94
GifWord MaxCode1
Definition: ungif.c:92
GifByteType Stack[LZ_MAX_CODE]
Definition: ungif.c:101
GifWord EOFCode
Definition: ungif.c:89
GifWord RunningBits
Definition: ungif.c:91
GifWord LastCode
Definition: ungif.c:93
unsigned long PixelCount
Definition: ungif.c:98
InputFunc Read
Definition: ungif.c:99
GifByteType Suffix[LZ_MAX_CODE+1]
Definition: ungif.c:102
GifWord CrntShiftState
Definition: ungif.c:96
GifWord StackPtr
Definition: ungif.c:95
GifWord BitsPerPixel
Definition: ungif.c:87
GifByteType Buf[256]
Definition: ungif.c:100
GifWord ClearCode
Definition: ungif.c:88
GifPrefixType Prefix[LZ_MAX_CODE+1]
Definition: ungif.c:103
GifWord RunningCode
Definition: ungif.c:90
unsigned long CrntShiftDWord
Definition: ungif.c:97
GifWord SAspectRatio
Definition: ungif.h:118
Extensions Extensions
Definition: ungif.h:120
GifWord SWidth
Definition: ungif.h:115
GifImageDesc Image
Definition: ungif.h:122
struct SavedImage * SavedImages
Definition: ungif.h:123
GifWord SColorResolution
Definition: ungif.h:116
ColorMapObject * SColorMap
Definition: ungif.h:119
void * Private
Definition: ungif.h:125
GifWord SBackGroundColor
Definition: ungif.h:117
GifWord SHeight
Definition: ungif.h:115
int ImageCount
Definition: ungif.h:121
void * UserData
Definition: ungif.h:124
ColorMapObject * ColorMap
Definition: ungif.h:98
GifWord Interlace
Definition: ungif.h:97
GifWord Top
Definition: ungif.h:96
GifWord Left
Definition: ungif.h:96
GifWord Width
Definition: ungif.h:96
GifWord Height
Definition: ungif.h:96
Definition: ncftp.h:79
static int DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
Definition: ungif.c:515
static void FreeMapObject(ColorMapObject *Object)
Definition: ungif.c:182
static int AppendExtensionBlock(Extensions *New, int Len, const unsigned char ExtData[])
Definition: ungif.c:234
static int DGifGetScreenDesc(GifFileType *GifFile)
Definition: ungif.c:307
static void FreeExtension(Extensions *Extensions)
Definition: ungif.c:260
static int DGifSetupDecompress(GifFileType *GifFile)
Definition: ungif.c:608
static void ungif_free(void *ptr)
Definition: ungif.c:76
static int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
Definition: ungif.c:355
static int DGifGetImageDesc(GifFileType *GifFile)
Definition: ungif.c:390
GifFileType * DGifOpen(void *userData, InputFunc readFunc)
Definition: ungif.c:993
static void * ungif_realloc(void *ptr, size_t sz)
Definition: ungif.c:71
int DGifCloseFile(GifFileType *GifFile)
Definition: ungif.c:1047
#define LZ_MAX_CODE
Definition: ungif.c:81
int DGifSlurp(GifFileType *GifFile)
Definition: ungif.c:876
#define READ(_gif, _buf, _len)
Definition: ungif.c:107
static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
Definition: ungif.c:840
static int DGifDecompressInput(GifFileType *GifFile, int *Code)
Definition: ungif.c:788
static int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock)
Definition: ungif.c:579
#define LZ_BITS
Definition: ungif.c:82
static int DGifGetWord(GifFileType *GifFile, GifWord *Word)
Definition: ungif.c:560
static int AddExtensionBlock(Extensions *New, int Len, const unsigned char ExtData[])
Definition: ungif.c:197
static void * ungif_calloc(size_t num, size_t sz)
Definition: ungif.c:66
static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, int ClearCode)
Definition: ungif.c:770
static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
Definition: ungif.c:644
static void * ungif_alloc(size_t sz)
Definition: ungif.c:61
#define NO_SUCH_CODE
Definition: ungif.c:84
static void FreeSavedImages(GifFileType *GifFile)
Definition: ungif.c:279
static int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
Definition: ungif.c:475
static ColorMapObject * MakeMapObject(int ColorCount, const GifColorType *ColorMap)
Definition: ungif.c:146
static int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension)
Definition: ungif.c:535
static int BitSize(int n)
Definition: ungif.c:127
#define GIF_VERSION_POS
Definition: ungif.h:71
unsigned int GifPrefixType
Definition: ungif.h:81
unsigned char GifPixelType
Definition: ungif.h:78
unsigned char GifByteType
Definition: ungif.h:80
#define GIF_STAMP_LEN
Definition: ungif.h:70
GifRecordType
Definition: ungif.h:128
@ EXTENSION_RECORD_TYPE
Definition: ungif.h:132
@ UNDEFINED_RECORD_TYPE
Definition: ungif.h:129
@ IMAGE_DESC_RECORD_TYPE
Definition: ungif.h:131
@ TERMINATE_RECORD_TYPE
Definition: ungif.h:133
#define GIF_OK
Definition: ungif.h:56
#define GRAPHICS_EXT_FUNC_CODE
Definition: ungif.h:142
int(* InputFunc)(GifFileType *, GifByteType *, int)
Definition: ungif.h:137
int GifWord
Definition: ungif.h:82
#define GIF_STAMP
Definition: ungif.h:69
#define GIF_ERROR
Definition: ungif.h:55
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1701
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ __drv_aliasesMem PSTRING Prefix
Definition: rtlfuncs.h:1630