Commit | Line | Data |
---|---|---|
df61f5a9 SH |
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 |