1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This is free software; you can redistribute it and/or modify
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  it under the terms of the GNU General Public License as published by
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  the Free Software Foundation; either version 2 of the License, or
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  (at your option) any later version.
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This software is distributed in the hope that it will be useful,
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  GNU General Public License for more details.
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  You should have received a copy of the GNU General Public License
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  along with this software; if not, write to the Free Software
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  USA.
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * ultrazip.c - handle ultrazip encoding.
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This file shouldn't be compiled directly.  It is included multiple times by
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbproto.c, each time with a different definition of the macro BPP.  For
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * each value of BPP, this file defines a function which handles an zlib
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * encoded rectangle with BPP bits per pixel.
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP)
31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleUltraBPP CONCAT2E(HandleUltra,BPP)
32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define CARDBPP CONCAT3E(uint,BPP,_t)
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool
35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatHandleUltraBPP (rfbClient* client, int rx, int ry, int rw, int rh)
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbZlibHeader hdr;
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int toRead=0;
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int inflateResult=0;
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  lzo_uint uncompressedBytes = (( rw * rh ) * ( BPP / 8 ));
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return FALSE;
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  toRead = rfbClientSwap32IfLE(hdr.nBytes);
46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (toRead==0) return TRUE;
47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (uncompressedBytes==0)
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  {
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw, rh, BPP);
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return FALSE;
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* First make sure we have a large enough raw buffer to hold the
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * decompressed data.  In practice, with a fixed BPP, fixed frame
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * buffer size and the first update containing the entire frame
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * buffer, this buffer allocation should only happen once, on the
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * first update.
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   */
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ( client->raw_buffer_size < (int)uncompressedBytes) {
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ( client->raw_buffer != NULL ) {
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      free( client->raw_buffer );
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->raw_buffer_size = uncompressedBytes;
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* buffer needs to be aligned on 4-byte boundaries */
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((client->raw_buffer_size % 4)!=0)
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      client->raw_buffer_size += (4-(client->raw_buffer_size % 4));
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->raw_buffer = (char*) malloc( client->raw_buffer_size );
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* allocate enough space to store the incoming compressed packet */
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ( client->ultra_buffer_size < toRead ) {
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ( client->ultra_buffer != NULL ) {
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      free( client->ultra_buffer );
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->ultra_buffer_size = toRead;
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* buffer needs to be aligned on 4-byte boundaries */
78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((client->ultra_buffer_size % 4)!=0)
79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      client->ultra_buffer_size += (4-(client->ultra_buffer_size % 4));
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->ultra_buffer = (char*) malloc( client->ultra_buffer_size );
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* Fill the buffer, obtaining data from the server. */
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (!ReadFromRFBServer(client, client->ultra_buffer, toRead))
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return FALSE;
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* uncompress the data */
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  uncompressedBytes = client->raw_buffer_size;
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  inflateResult = lzo1x_decompress(
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              (lzo_byte *)client->ultra_buffer, toRead,
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes,
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              NULL);
93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ((rw * rh * (BPP / 8)) != uncompressedBytes)
96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("Ultra decompressed too little (%d < %d)", (rw * rh * (BPP / 8)), uncompressedBytes);
97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* Put the uncompressed contents of the update on the screen. */
99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ( inflateResult == LZO_E_OK )
100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  {
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    CopyRectangle(client, (unsigned char *)client->raw_buffer, rx, ry, rw, rh);
102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  else
104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  {
105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientLog("ultra decompress returned error: %d\n",
106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            inflateResult);
107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return FALSE;
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return TRUE;
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* UltraZip is like rre in that it is composed of subrects */
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatHandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh)
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbZlibHeader hdr;
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int i=0;
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int toRead=0;
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int inflateResult=0;
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  unsigned char *ptr=NULL;
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  lzo_uint uncompressedBytes = ry + (rw * 65535);
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  unsigned int numCacheRects = rx;
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return FALSE;
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  toRead = rfbClientSwap32IfLE(hdr.nBytes);
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (toRead==0) return TRUE;
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (uncompressedBytes==0)
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  {
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry, rw, rx);
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return FALSE;
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* First make sure we have a large enough raw buffer to hold the
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * decompressed data.  In practice, with a fixed BPP, fixed frame
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * buffer size and the first update containing the entire frame
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * buffer, this buffer allocation should only happen once, on the
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   * first update.
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   */
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ( client->raw_buffer_size < (int)(uncompressedBytes + 500)) {
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ( client->raw_buffer != NULL ) {
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      free( client->raw_buffer );
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->raw_buffer_size = uncompressedBytes + 500;
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* buffer needs to be aligned on 4-byte boundaries */
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((client->raw_buffer_size % 4)!=0)
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      client->raw_buffer_size += (4-(client->raw_buffer_size % 4));
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->raw_buffer = (char*) malloc( client->raw_buffer_size );
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* allocate enough space to store the incoming compressed packet */
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ( client->ultra_buffer_size < toRead ) {
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ( client->ultra_buffer != NULL ) {
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      free( client->ultra_buffer );
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->ultra_buffer_size = toRead;
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->ultra_buffer = (char*) malloc( client->ultra_buffer_size );
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* Fill the buffer, obtaining data from the server. */
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (!ReadFromRFBServer(client, client->ultra_buffer, toRead))
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return FALSE;
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* uncompress the data */
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  uncompressedBytes = client->raw_buffer_size;
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  inflateResult = lzo1x_decompress(
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              (lzo_byte *)client->ultra_buffer, toRead,
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              (lzo_byte *)client->raw_buffer, &uncompressedBytes, NULL);
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ( inflateResult != LZO_E_OK )
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  {
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientLog("ultra decompress returned error: %d\n",
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            inflateResult);
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return FALSE;
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* Put the uncompressed contents of the update on the screen. */
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  ptr = (unsigned char *)client->raw_buffer;
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  for (i=0; i<numCacheRects; i++)
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  {
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    unsigned short sx, sy, sw, sh;
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    unsigned int se;
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy((char *)&sx, ptr, 2); ptr += 2;
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy((char *)&sy, ptr, 2); ptr += 2;
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy((char *)&sw, ptr, 2); ptr += 2;
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy((char *)&sh, ptr, 2); ptr += 2;
192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy((char *)&se, ptr, 4); ptr += 4;
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sx = rfbClientSwap16IfLE(sx);
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sy = rfbClientSwap16IfLE(sy);
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sw = rfbClientSwap16IfLE(sw);
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sh = rfbClientSwap16IfLE(sh);
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    se = rfbClientSwap32IfLE(se);
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (se == rfbEncodingRaw)
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        CopyRectangle(client, (unsigned char *)ptr, sx, sy, sw, sh);
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        ptr += ((sw * sh) * (BPP / 8));
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return TRUE;
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef CARDBPP
211