This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update DB_File to CPAN version 1.854
[perl5.git] / cpan / Win32API-File / buffers.h
1 /* buffers.h -- Version 1.11 */\r
2 \r
3 /* The following abbreviations are used at start of parameter names\r
4  * to indicate the type of data:\r
5  *      s       string (char * or WCHAR *) [PV]\r
6  *      sw      wide string (WCHAR *) [PV]\r
7  *      p       pointer (usually to some structure) [PV]\r
8  *      a       array (packed array as in C) (usually of some structure) [PV]\r
9  *                  called a "vector" or "vect" in some places.\r
10  *      n       generic number [IV, UV, or NV]\r
11  *      iv      signed integral value [IV]\r
12  *      u       unsigned integral value [UV]\r
13  *      d       floating-point number (double) [NV]\r
14  *      b       boolean (bool) [IV]\r
15  *      c       count of items [UV]\r
16  *      l       length (in bytes) [UV]\r
17  *      lw      length in WCHARs [UV]\r
18  *      h       a handle [IV]\r
19  *      r       record (structure) [PV]\r
20  *      sv      Perl scalar (s, i, u, d, n, or rv) [SV]\r
21  *      rv      Perl reference (usually to scalar) [RV]\r
22  *      hv      reference to Perl hash [HV]\r
23  *      av      reference to Perl array [AV]\r
24  *      cv      Perl code reference [PVCV]\r
25  *\r
26  * Unusual combined types:\r
27  *      pp      single pointer (to non-Perl data) packed into string [PV]\r
28  *      pap     vector of pointers (to non-Perl data) packed into string [PV]\r
29  *\r
30  * Whether a parameter is for input data, output data, or both is usually\r
31  * not reflected by the data type prefix.  In cases where this is not\r
32  * obvious nor reflected in the variable name proper, you can use\r
33  * the following in front of the data type prefix:\r
34  *      i       an input parameter given to API (usually omitted)\r
35  *      o       an Output parameter taken from API\r
36  *      io      Input given to API then overwritten with Output taken from API\r
37  */\r
38 \r
39 /* Buffer arguments are usually followed by an argument (or two) specifying\r
40  * their size and/or returning the size of data written.  The size can be\r
41  * measured in bytes ["lSize"] or in characters [for (char *) buffers such as\r
42  * for *A() routines, these sizes are also called "lSize", but are called\r
43  * "lwSize" for (WCHAR *) buffers, UNICODE strings, such as for *W() routines].\r
44  *\r
45  * Before calling the actual C function, you must make sure the Perl variable\r
46  * actually has a big enough buffer allocated, and, if the user didn't want\r
47  * to specify a buffer size, set the buffer size to be correct.  This is what\r
48  * the grow_*() macros are for.  They also handle special meanings of the\r
49  * buffer size argument [described below].\r
50  *\r
51  * Once the actual C function returns, you must set the Perl variable to know\r
52  * the size of the written data.  This is what the trunc_*() macros are for.\r
53  *\r
54  * The size sometimes does and sometimes doesn't include the trailing '\0'\r
55  * [or L'\0'], so we always add or subtract 1 in the appropriate places so\r
56  * we don't care about this detail.\r
57  *\r
58  * A call may  1) request a pointer to the buffer size which means that\r
59  * the buffer size will be overwritten with the size of the data written;\r
60  * 2) have an extra argument which is a pointer to the place to write the\r
61  * size of the written data;  3) provide the size of the written data in\r
62  * the function's return value;  4) format the data so that the length\r
63  * can be determined by examining the data [such as with '\0'-terminated\r
64  * strings];  or  5) write fixed-length data [usually sizeof(STRUCT)].\r
65  * This obviously determines what you should use in the trunc_*() macro\r
66  # to specify the size of the output value.\r
67  *\r
68  * The user can pass in an empty list reference, C<[]>, to indicate C<NULL>\r
69  * for the pointer to the buffer which means that they don't want that data.\r
70  *\r
71  * The user can pass in C<[]> or C<0> to indicate that they don't care about\r
72  * the buffer size [we aren't programming in C here, after all] and just try\r
73  * to get the data.  This will work if either the buffer already allocated for\r
74  * the SV [scalar value] is large enough to hold the data or the API provides\r
75  * an easy way to determine the required size [and the XS code uses it].\r
76  *\r
77  * If the user passes in a numeric value for a buffer size, then the XS\r
78  * code makes sure that the buffer is at least large enough to hold a value\r
79  * of that size and then passes in how large the buffer is.  So the buffer\r
80  * size passed to the API call is the larger of the size requested by the\r
81  * user and the size of the buffer already allocated to the SV.\r
82  *\r
83  * The user can also pass in a string consisting of a leading "=" followed\r
84  * by digits for a buffer size.  This means just use the size specified after\r
85  * the equals sign, even if the allocated buffer is larger.  The XS code will\r
86  * still allocate a large enough buffer before the first call.\r
87  *\r
88  * If the function is nice enough to tell us that a buffer was too small\r
89  * [usually via ERROR_MORE_DATA] _and_ how large the buffer needs to be,\r
90  * then the XS code should enlarge the buffer(s) and repeat the call [once].\r
91  * This resizing is _not_ done for buffers whose size was specified with a\r
92  * leading "=".\r
93  *\r
94  * Only grow_buf() and perhaps trunc_buf() can be used in a typemap file.\r
95  * The other macros would be used in the parameter declarations or INPUT:\r
96  * section [grow_*()], the INIT: section [init_*()], or the OUTPUT: section\r
97  * [trunc_*()].\r
98  *\r
99  * Buffer arguments should be initialised with C<= NO_INIT> [or C<= NULL;>].\r
100  *\r
101  * See also the F<typemap> file.  C<oDWORD>, for example, is for an output-\r
102  * only parameter of type C<DWORD> and you should simply C<#define> it to be\r
103  * C<DWORD>.  In F<typemap>, C<oDWORD> is treated differently than C<DWORD>\r
104  * in two ways.\r
105  *\r
106  * First, if C<undef> is passed in, a C<DWORD> could generate a warning\r
107  * when it gets converted to 0 while C<oDWORD> will never generate such a\r
108  * warning for C<undef>.  This first difference doesn't apply if specific\r
109  * initialization is specified for the variable, as in C<= init_buf_l($var);>.\r
110  * In particular, the init_*() macros also convert C<undef> to 0 without\r
111  * ever producing a warning.\r
112  *\r
113  * Second, passing in a read-only SV for a C<oDWORD> parameter will generate\r
114  * a fatal error on output when we try to update the SV.  For C<DWORD>, we\r
115  * won't update a read-only SV since passing in a literal constant for a\r
116  * buffer size is a useful thing to do even though it prevents us from\r
117  * returning the size of data written via that SV.  Since we should use a\r
118  * trunc_*() macro to output the actual data, the user should be able to\r
119  * determine the size of data written based on the size of the scalar we\r
120  * output anyway.\r
121  *\r
122  * This second difference doesn't apply unless the parameter is listed in\r
123  * the OUTPUT: section without specific output instructions.  We define\r
124  * no macros for outputting buffer length parameters so be careful to use\r
125  * C<oDWORD> [for example] for them if and only if they are output-only.\r
126  *\r
127  * Note that C<oDWORD> is the same as C<DWORD> in that, if a defined value\r
128  * is passed in, it is used [and can generate a warning if the value is\r
129  * "not numeric"].  So although C<oDWORD> is for output-only parameters,\r
130  * we still initialize the C variable before calling the API.  This is good\r
131  * in case the parameter isn't always strictly output-only due to upgrades,\r
132  * bugs, etc.\r
133  *\r
134  * Here is a made-up example that shows several cases:\r
135  *\r
136  * # Actual GetDataW() returns length of data written to ioswName, not bool.\r
137  * bool\r
138  * GetDataW( ioswName, ilwName, oswText, iolwText, opJunk, opRec, ilRec, olRec )\r
139  *      WCHAR * ioswName        = NO_INIT\r
140  *      DWORD   ilwName         = NO_INIT\r
141  *      WCHAR * oswText         = NO_INIT\r
142  *      DWORD   &iolwText       = init_buf_l($arg);\r
143  *      void *  opJunk          = NO_INIT\r
144  *      BYTE *  opRec           = NO_INIT\r
145  *      DWORD   ilRec           = init_buf_l($arg);\r
146  *      oDWORD  &olRec\r
147  * PREINIT:\r
148  *      DWORD   olwName;\r
149  * INIT:\r
150  *      grow_buf_lw( ioswName,ST(0), ilwName,ST(1) );\r
151  *      grow_buf_lw( oswText,ST(2), iolwText,ST(3) );\r
152  *      grow_buf_typ( opJunk,ST(4),void *, LONG_STRUCT_TYPEDEF );\r
153  *      grow_buf_l( opRec,ST(5),BYTE *, ilRec,ST(6) );\r
154  * CODE:\r
155  *      olwName= GetDataW( ioswName, ilwName, oswText, &iolwText,\r
156  *                         (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec );\r
157  *      if(  0 == olwName  &&  ERROR_MORE_DATA == GetLastError()\r
158  *       &&  ( autosize(ST(1)) || autosize(ST(3)) || autosize(ST(6)) )  ) {\r
159  *          if(  autosize(ST(1))  )\r
160  *              grow_buf_lw( ioswName,ST(0), ilwName,ST(1) );\r
161  *          if(  autosize(ST(3))  )\r
162  *              grow_buf_lw( oswText,ST(2), iolwText,ST(3) );\r
163  *          if(  autosize(ST(6))  )\r
164  *              grow_buf_l( opRec,ST(5),BYTE *, iolRec,ST(6) );\r
165  *          olwName= GetDataW( ioswName, ilwName, oswText, &iolwText,\r
166  *                             (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec );\r
167  *      }\r
168  *      RETVAL=  0 != olwName;\r
169  * OUTPUT:\r
170  *      RETVAL\r
171  *      ioswName        trunc_buf_lw( RETVAL, ioswName,ST(0), olwName );\r
172  *      oswText         trunc_buf_lw( RETVAL, oswText,ST(2), iolwText );\r
173  *      iolwText\r
174  *      opJunk          trunc_buf_typ(RETVAL,opJunk,ST(4),LONG_STRUCT_TYPEDEF);\r
175  *      opRec           trunc_buf_l( RETVAL, opRec,ST(5), olRec );\r
176  *      olRec\r
177  *\r
178  * The above example would be more complex and less efficient if we used\r
179  * C<DWORD * iolwText> in place of C<DWORD  &iolwText>.  The only possible\r
180  * advantage would be that C<NULL> would be passed in for C<iolwText> if\r
181  * _both_ C<$oswText> and C<$iolwText> were specified as C<[]>.  The *_pl*()\r
182  * macros are defined [and C<DWORD *> specified in F<typemap>] so we can\r
183  * handle those cases but it is usually better to use the *_l*() macros\r
184  * instead by specifying C<&> instead of C<*>.  Using C<&> instead of C<*>\r
185  * is usually better when dealing with scalars, even if they aren't buffer\r
186  * sizes.  But you must use C<*> if it is important for that parameter to\r
187  * be able to pass C<NULL> to the underlying API.\r
188  *\r
189  * In Win32API::, we try to use C<*> for buffer sizes of optional buffers\r
190  * and C<&> for buffer sizes of required buffers.\r
191  *\r
192  * For parameters that are pointers to things other than buffers or buffer\r
193  * sizes, we use C<*> for "important" parameters [so that using C<[]>\r
194  * generates an error rather than fetching the value and just throwing it\r
195  * away], and for optional parameters [in case specifying C<NULL> is or\r
196  * becomes important].  Otherwise we use C<&> [for "unimportant" but\r
197  * required parameters] so the user can specify C<[]> if they don't care\r
198  * about it.  The output handle of an "open" routine is "important".\r
199  */\r
200 \r
201 #ifndef Debug\r
202 # define        Debug(list)     /*Nothing*/\r
203 #endif\r
204 \r
205 /*#ifndef CAST\r
206  *# ifdef __cplusplus\r
207  *#  define   CAST(type,expr)   static_cast<type>(expr)\r
208  *# else*/\r
209 #  define   CAST(type,expr)     (type)(expr)\r
210 /*# endif\r
211  *#endif*/\r
212 \r
213 /* Is an argument C<[]>, meaning we should pass C<NULL>? */\r
214 #define null_arg(sv)    (  SvROK(sv)  &&  SVt_PVAV == SvTYPE(SvRV(sv))  \\r
215                            &&  -1 == av_len((AV*)SvRV(sv))  )\r
216 \r
217 #define PV_or_null(sv)  ( null_arg(sv) ? NULL : SvPV_nolen(sv) )\r
218 \r
219 /* Minimum buffer size to use when no buffer existed: */\r
220 #define MIN_GROW_SIZE   128\r
221 \r
222 #ifdef Debug\r
223 /* Used in Debug() messages to show which macro call is involved: */\r
224 #define string(arg) #arg\r
225 #endif\r
226 \r
227 /* Simplify using SvGROW() for byte-sized buffers: */\r
228 #define lSvGROW(sv,n)   SvGROW( sv, 0==(n) ? MIN_GROW_SIZE : (n)+1 )\r
229 \r
230 /* Simplify using SvGROW() for WCHAR-sized buffers: */\r
231 #define lwSvGROW(sv,n)  CAST( WCHAR *,          \\r
232         SvGROW( sv, sizeof(WCHAR)*( 0==(n) ? MIN_GROW_SIZE : (n)+1 ) ) )\r
233 \r
234 /* Whether the buffer size we got lets us change what buffer size we use: */\r
235 #define autosize(sv)    (!(  SvOK(sv)  &&  ! SvROK(sv)          \\r
236                          &&  SvPV_nolen(sv)  &&  '=' == *SvPV_nolen(sv)  ))\r
237 \r
238 /* Get the IV/UV for a parameter that might be C<[]> or C<undef>: */\r
239 #define optIV(sv)       ( null_arg(sv) ? 0 : !SvOK(sv) ? 0 : SvIV(sv) )\r
240 #define optUV(sv)       ( null_arg(sv) ? 0 : !SvOK(sv) ? 0 : SvUV(sv) )\r
241 \r
242 /* Allocate temporary storage that will automatically be freed later: */\r
243 #ifndef TempAlloc       /* Can be C<#define>d to be C<_alloca>, for example */\r
244 # define TempAlloc( size )      sv_grow( sv_newmortal(), size )\r
245 #endif\r
246 \r
247 /* Initialize a buffer size argument of type (DWORD *): */\r
248 #define init_buf_pl( plSize, svSize, tpSize )           STMT_START {    \\r
249         if(  null_arg(svSize)  )                                        \\r
250             plSize= NULL;                                               \\r
251         else {                                                          \\r
252             STRLEN n_a;                                                 \\r
253             *( plSize= CAST( tpSize, TempAlloc(sizeof(*plSize)) ) )=    \\r
254               autosize(svSize) ? optUV(svSize)                          \\r
255                 : strtoul( 1+SvPV(svSize,n_a), NULL, 10 );              \\r
256         } } STMT_END\r
257 /* In INPUT section put ": init_buf_pl($var,$arg,$type);" after var name. */\r
258 \r
259 /* Initialize a buffer size argument of type DWORD: */\r
260 #define init_buf_l( svSize )                                            \\r
261         (  null_arg(svSize) ? 0 : autosize(svSize) ? optUV(svSize)      \\r
262            : strtoul( 1+SvPV_nolen(svSize), NULL, 10 )  )\r
263 /* In INPUT section put "= init_buf_l($arg);" after variable name. */\r
264 \r
265 /* Lengths in WCHARs are initialized the same as lengths in bytes: */\r
266 #define init_buf_plw    init_buf_pl\r
267 #define init_buf_lw     init_buf_l\r
268 \r
269 /* grow_buf_pl() and grow_buf_plw() are included so you can define\r
270  * parameters of type C<DWORD *>, for example.  In practice, it is\r
271  * usually better to define such parameters as "DWORD &". */\r
272 \r
273 /* Grow a buffer where we have a pointer to its size in bytes: */\r
274 #define grow_buf_pl( sBuf,svBuf,tpBuf, plSize,svSize,tpSize ) STMT_START { \\r
275         Debug(("grow_buf_pl( %s==0x%lX,[%s:%ld/%ld, %s==0x%lX:%ld,[%s )\n",\\r
276           string(sBuf),sBuf,strchr(string(svBuf),'('),SvPOK(svBuf)?     \\r
277           SvCUR(svBuf):-1,SvPOK(svBuf)?SvLEN(svBuf):-1,string(plSize),  \\r
278           plSize,plSize?*plSize:-1,strchr(string(svSize),'(')));        \\r
279         if(  null_arg(svBuf)  ) {                                       \\r
280             sBuf= NULL;                                                 \\r
281         } else {                                                        \\r
282             STRLEN n_a;                                                 \\r
283             if(  NULL == plSize  )                                      \\r
284                 *( plSize= CAST(tpSize,TempAlloc(sizeof(*plSize))) )= 0;\\r
285             if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \\r
286             (void) SvPV_force( svBuf, n_a );                            \\r
287             sBuf= CAST( tpBuf, lSvGROW( svBuf, *plSize ) );             \\r
288             if(  autosize(svSize)  )   *plSize= SvLEN(svBuf) - 1;       \\r
289             Debug(("more buf_pl( %s==0x%lX,[%s:%ld/%ld, %s==0x%lX:%ld,[%s )\n",\\r
290               string(sBuf),sBuf,strchr(string(svBuf),'('),SvPOK(svBuf)? \\r
291               SvCUR(svBuf):-1,SvPOK(svBuf)?SvLEN(svBuf):-1,string(plSize),\\r
292               plSize,plSize?*plSize:-1,strchr(string(svSize),'(')));    \\r
293         } } STMT_END\r
294 \r
295 /* Grow a buffer where we have a pointer to its size in WCHARs: */\r
296 #define grow_buf_plw( sBuf,svBuf, plwSize,svSize,tpSize ) STMT_START {  \\r
297         if(  null_arg(svBuf)  ) {                                       \\r
298             sBuf= NULL;                                                 \\r
299         } else {                                                        \\r
300             STRLEN n_a;                                                 \\r
301             if(  NULL == plwSize  )                                     \\r
302                 *( plwSize= CAST(tpSize,TempAlloc(sizeof(*plwSize))) )= 0;\\r
303             if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \\r
304             (void) SvPV_force( svBuf, n_a );                            \\r
305             sBuf= lwSvGROW( svBuf, *plwSize );                          \\r
306             if(  autosize(svSize)  )                                    \\r
307                 *plwSize= SvLEN(svBuf)/sizeof(WCHAR) - 1;               \\r
308         } } STMT_END\r
309 \r
310 /* Grow a buffer where we have its size in bytes: */\r
311 #define grow_buf_l( sBuf,svBuf,tpBuf, lSize,svSize )    STMT_START {    \\r
312         if(  null_arg(svBuf)  ) {                                       \\r
313             sBuf= NULL;                                                 \\r
314         } else {                                                        \\r
315             STRLEN n_a;                                                 \\r
316             if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \\r
317             (void) SvPV_force( svBuf, n_a );                            \\r
318             sBuf= CAST( tpBuf, lSvGROW( svBuf, lSize ) );               \\r
319             if(  autosize(svSize)  )   lSize= SvLEN(svBuf) - 1;         \\r
320         } } STMT_END\r
321 \r
322 /* Grow a buffer where we have its size in WCHARs: */\r
323 #define grow_buf_lw( swBuf,svBuf, lwSize,svSize )       STMT_START {    \\r
324         if(  null_arg(svBuf)  ) {                                       \\r
325             swBuf= NULL;                                                \\r
326         } else {                                                        \\r
327             STRLEN n_a;                                                 \\r
328             if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \\r
329             (void) SvPV_force( svBuf, n_a );                            \\r
330             swBuf= lwSvGROW( svBuf, lwSize );                           \\r
331             if(  autosize(svSize)  )                                    \\r
332                 lwSize= SvLEN(svBuf)/sizeof(WCHAR) - 1;                 \\r
333         } } STMT_END\r
334 \r
335 /* Grow a buffer that contains the declared fixed data type: */\r
336 #define grow_buf( pBuf,svBuf, tpBuf )                   STMT_START {    \\r
337         if(  null_arg(svBuf)  ) {                                       \\r
338             pBuf= NULL;                                                 \\r
339         } else {                                                        \\r
340             STRLEN n_a;                                                 \\r
341             if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \\r
342             (void) SvPV_force( svBuf, n_a );                            \\r
343             pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(*pBuf) ) );        \\r
344         } } STMT_END\r
345 \r
346 /* Grow a buffer that contains a fixed data type other than that declared: */\r
347 #define grow_buf_typ( pBuf,svBuf,tpBuf, Type )          STMT_START {    \\r
348         if(  null_arg(svBuf)  ) {                                       \\r
349             pBuf= NULL;                                                 \\r
350         } else {                                                        \\r
351             STRLEN n_a;                                                 \\r
352             if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \\r
353             (void) SvPV_force( svBuf, n_a );                            \\r
354             pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(Type) ) ); \\r
355         } } STMT_END\r
356 \r
357 /* Grow a buffer that contains a list of items of the declared data type: */\r
358 #define grow_vect( pBuf,svBuf,tpBuf, cItems )           STMT_START {    \\r
359         if(  null_arg(svBuf)  ) {                                       \\r
360             pBuf= NULL;                                                 \\r
361         } else {                                                        \\r
362             STRLEN n_a;                                                 \\r
363             if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \\r
364             (void) SvPV_force( svBuf, n_a );                            \\r
365             pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(*pBuf)*cItems ) ); \\r
366         } } STMT_END\r
367 \r
368 /* If call succeeded, set data length to returned length (in bytes): */\r
369 #define trunc_buf_l( bOkay, sBuf,svBuf, lSize )         STMT_START {    \\r
370         if(  bOkay  &&  NULL != sBuf  ) {                               \\r
371             SvPOK_only( svBuf );                                        \\r
372             SvCUR_set( svBuf, lSize );                                  \\r
373         } } STMT_END\r
374 \r
375 /* Same as above except we have a pointer to the returned length: */\r
376 #define trunc_buf_pl( bOkay, sBuf,svBuf, plSize )                       \\r
377         trunc_buf_l( bOkay, sBuf,svBuf, *plSize )\r
378 \r
379 /* If call succeeded, set data length to returned length (in WCHARs): */\r
380 #define trunc_buf_lw( bOkay, sBuf,svBuf, lwSize )       STMT_START {    \\r
381         if(  bOkay  &&  NULL != sBuf  ) {                               \\r
382             SvPOK_only( svBuf );                                        \\r
383             SvCUR_set( svBuf, (lwSize)*sizeof(WCHAR) );                 \\r
384         } } STMT_END\r
385 \r
386 /* Same as above except we have a pointer to the returned length: */\r
387 #define trunc_buf_plw( bOkay, swBuf,svBuf, plwSize )                    \\r
388         trunc_buf_lw( bOkay, swBuf,svBuf, *plwSize )\r
389 \r
390 /* Set data length for a buffer that contains the declared fixed data type: */\r
391 #define trunc_buf( bOkay, pBuf,svBuf )                  STMT_START {    \\r
392         if(  bOkay  &&  NULL != pBuf  ) {                               \\r
393             SvPOK_only( svBuf );                                        \\r
394             SvCUR_set( svBuf, sizeof(*pBuf) );                          \\r
395         } } STMT_END\r
396 \r
397 /* Set data length for a buffer that contains some other fixed data type: */\r
398 #define trunc_buf_typ( bOkay, pBuf,svBuf, Type )        STMT_START {    \\r
399         if(  bOkay  &&  NULL != pBuf  ) {                               \\r
400             SvPOK_only( svBuf );                                        \\r
401             SvCUR_set( svBuf, sizeof(Type) );                           \\r
402         } } STMT_END\r
403 \r
404 /* Set length for buffer that contains list of items of the declared type: */\r
405 #define trunc_vect( bOkay, pBuf,svBuf, cItems )         STMT_START {    \\r
406         if(  bOkay  &&  NULL != pBuf  ) {                               \\r
407             SvPOK_only( svBuf );                                        \\r
408             SvCUR_set( svBuf, sizeof(*pBuf)*cItems );                   \\r
409         } } STMT_END\r
410 \r
411 /* Set data length for a buffer where a '\0'-terminate string was stored: */\r
412 #define trunc_buf_z( bOkay, sBuf,svBuf )                STMT_START {    \\r
413         if(  bOkay  &&  NULL != sBuf  ) {                               \\r
414             SvPOK_only( svBuf );                                        \\r
415             SvCUR_set( svBuf, strlen(sBuf) );                           \\r
416         } } STMT_END\r
417 \r
418 /* Set data length for a buffer where a L'\0'-terminate string was stored: */\r
419 #define trunc_buf_zw( bOkay, sBuf,svBuf )               STMT_START {    \\r
420         if(  bOkay  &&  NULL != sBuf  ) {                               \\r
421             SvPOK_only( svBuf );                                        \\r
422             SvCUR_set( svBuf, wcslen(sBuf)*sizeof(WCHAR) );             \\r
423         } } STMT_END\r