ntdll: Fix a few memory leaks in tests.
[wine] / dlls / ntdll / large_int.c
1 /*
2  * Large integer functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  * Copyright 2003 Thomas Mertes
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winternl.h"
28
29 #ifndef _WIN64
30
31 /*
32  * Note: we use LONGLONG instead of LARGE_INTEGER, because
33  * the latter is a structure and the calling convention for
34  * returning a structure would not be binary-compatible.
35  *
36  * FIXME: for platforms that don't have a native LONGLONG type,
37  * we should define LONGLONG as a structure similar to LARGE_INTEGER
38  * and do everything by hand. You are welcome to do it...
39  */
40
41 /******************************************************************************
42  *        RtlLargeIntegerAdd   (NTDLL.@)
43  *
44  * Add two 64 bit integers.
45  *
46  * PARAMS
47  *  a [I] Initial number.
48  *  b [I] Number to add to a.
49  *
50  * RETURNS
51  *  The sum of a and b.
52  */
53 LONGLONG WINAPI RtlLargeIntegerAdd( LONGLONG a, LONGLONG b )
54 {
55     return a + b;
56 }
57
58
59 /******************************************************************************
60  *        RtlLargeIntegerSubtract   (NTDLL.@)
61  *
62  * Subtract two 64 bit integers.
63  *
64  * PARAMS
65  *  a [I] Initial number.
66  *  b [I] Number to subtract from a.
67  *
68  * RETURNS
69  *  The difference of a and b.
70  */
71 LONGLONG WINAPI RtlLargeIntegerSubtract( LONGLONG a, LONGLONG b )
72 {
73     return a - b;
74 }
75
76
77 /******************************************************************************
78  *        RtlLargeIntegerNegate   (NTDLL.@)
79  *
80  * Negate a 64 bit integer.
81  *
82  * PARAMS
83  *  a     [I] Initial number.
84  *
85  * RETURNS
86  *  The value of a negated.
87  */
88 LONGLONG WINAPI RtlLargeIntegerNegate( LONGLONG a )
89 {
90     return -a;
91 }
92
93
94 /******************************************************************************
95  *        RtlLargeIntegerShiftLeft   (NTDLL.@)
96  *
97  * Perform a shift left on a 64 bit integer.
98  *
99  * PARAMS
100  *  a     [I] Initial number.
101  *  count [I] Number of bits to shift by
102  *
103  * RETURNS
104  *  The value of a following the shift.
105  */
106 LONGLONG WINAPI RtlLargeIntegerShiftLeft( LONGLONG a, INT count )
107 {
108     return a << count;
109 }
110
111
112 /******************************************************************************
113  *        RtlLargeIntegerShiftRight   (NTDLL.@)
114  *
115  * Perform a shift right on a 64 bit integer.
116  *
117  * PARAMS
118  *  a     [I] Initial number.
119  *  count [I] Number of bits to shift by
120  *
121  * RETURNS
122  *  The value of a following the shift.
123  */
124 LONGLONG WINAPI RtlLargeIntegerShiftRight( LONGLONG a, INT count )
125 {
126     return (ULONGLONG)a >> count;
127 }
128
129
130 /******************************************************************************
131  *        RtlLargeIntegerArithmeticShift   (NTDLL.@)
132  *
133  * Perform an arithmetic shift right on a 64 bit integer.
134  *
135  * PARAMS
136  *  a     [I] Initial number.
137  *  count [I] Number of bits to shift by
138  *
139  * RETURNS
140  *  The value of a following the shift.
141  */
142 LONGLONG WINAPI RtlLargeIntegerArithmeticShift( LONGLONG a, INT count )
143 {
144     /* FIXME: gcc does arithmetic shift here, but it may not be true on all platforms */
145     return a >> count;
146 }
147
148
149 /******************************************************************************
150  *        RtlLargeIntegerDivide   (NTDLL.@)
151  *
152  * Divide one 64 bit unsigned integer by another, with remainder.
153  *
154  * PARAMS
155  *  a   [I] Initial number.
156  *  b   [I] Number to divide a by
157  *  rem [O] Destination for remainder
158  *
159  * RETURNS
160  *  The dividend of a and b. If rem is non-NULL it is set to the remainder.
161  *
162  * FIXME
163  *  Should it be signed division instead?
164  */
165 ULONGLONG WINAPI RtlLargeIntegerDivide( ULONGLONG a, ULONGLONG b, ULONGLONG *rem )
166 {
167     ULONGLONG ret = a / b;
168     if (rem) *rem = a - ret * b;
169     return ret;
170 }
171
172
173 /******************************************************************************
174  *        RtlConvertLongToLargeInteger   (NTDLL.@)
175  *
176  * Convert a 32 bit integer into 64 bits.
177  *
178  * PARAMS
179  *  a [I] Number to convert
180  *
181  * RETURNS
182  *  a.
183  */
184 LONGLONG WINAPI RtlConvertLongToLargeInteger( LONG a )
185 {
186     return a;
187 }
188
189
190 /******************************************************************************
191  *        RtlConvertUlongToLargeInteger   (NTDLL.@)
192  *
193  * Convert a 32 bit unsigned integer into 64 bits.
194  *
195  * PARAMS
196  *  a [I] Number to convert
197  *
198  * RETURNS
199  *  a.
200  */
201 ULONGLONG WINAPI RtlConvertUlongToLargeInteger( ULONG a )
202 {
203     return a;
204 }
205
206
207 /******************************************************************************
208  *        RtlEnlargedIntegerMultiply   (NTDLL.@)
209  *
210  * Multiply two integers giving a 64 bit integer result.
211  *
212  * PARAMS
213  *  a [I] Initial number.
214  *  b [I] Number to multiply a by.
215  *
216  * RETURNS
217  *  The product of a and b.
218  */
219 LONGLONG WINAPI RtlEnlargedIntegerMultiply( INT a, INT b )
220 {
221     return (LONGLONG)a * b;
222 }
223
224
225 /******************************************************************************
226  *        RtlEnlargedUnsignedMultiply   (NTDLL.@)
227  *
228  * Multiply two unsigned integers giving a 64 bit unsigned integer result.
229  *
230  * PARAMS
231  *  a [I] Initial number.
232  *  b [I] Number to multiply a by.
233  *
234  * RETURNS
235  *  The product of a and b.
236  */
237 ULONGLONG WINAPI RtlEnlargedUnsignedMultiply( UINT a, UINT b )
238 {
239     return (ULONGLONG)a * b;
240 }
241
242
243 /******************************************************************************
244  *        RtlEnlargedUnsignedDivide   (NTDLL.@)
245  *
246  * Divide one 64 bit unsigned integer by a 32 bit unsigned integer, with remainder.
247  *
248  * PARAMS
249  *  a      [I] Initial number.
250  *  b      [I] Number to divide a by
251  *  remptr [O] Destination for remainder
252  *
253  * RETURNS
254  *  The dividend of a and b. If remptr is non-NULL it is set to the remainder.
255  */
256 UINT WINAPI RtlEnlargedUnsignedDivide( ULONGLONG a, UINT b, UINT *remptr )
257 {
258 #if defined(__i386__) && defined(__GNUC__)
259     UINT ret, rem, p1, p2;
260
261     p1 = a >> 32;
262     p2 = a &  0xffffffffLL;
263
264     __asm__("div %4,%%eax"
265             : "=a" (ret), "=d" (rem)
266             : "0" (p2), "1" (p1), "g" (b) );
267     if (remptr) *remptr = rem;
268     return ret;
269 #else
270     UINT ret = a / b;
271     if (remptr) *remptr = a % b;
272     return ret;
273 #endif
274 }
275
276
277 /******************************************************************************
278  *        RtlExtendedLargeIntegerDivide   (NTDLL.@)
279  *
280  * Divide one 64 bit integer by a 32 bit integer, with remainder.
281  *
282  * PARAMS
283  *  a   [I] Initial number.
284  *  b   [I] Number to divide a by
285  *  rem [O] Destination for remainder
286  *
287  * RETURNS
288  *  The dividend of a and b. If rem is non-NULL it is set to the remainder.
289  */
290 LONGLONG WINAPI RtlExtendedLargeIntegerDivide( LONGLONG a, INT b, INT *rem )
291 {
292     LONGLONG ret = a / b;
293     if (rem) *rem = a - b * ret;
294     return ret;
295 }
296
297
298 /******************************************************************************
299  *        RtlExtendedIntegerMultiply   (NTDLL.@)
300  *
301  * Multiply one 64 bit integer by another 32 bit integer.
302  *
303  * PARAMS
304  *  a [I] Initial number.
305  *  b [I] Number to multiply a by.
306  *
307  * RETURNS
308  *  The product of a and b.
309  */
310 LONGLONG WINAPI RtlExtendedIntegerMultiply( LONGLONG a, INT b )
311 {
312     return a * b;
313 }
314
315
316 /******************************************************************************
317  *        RtlExtendedMagicDivide   (NTDLL.@)
318  *
319  * Allows replacing a division by a longlong constant with a multiplication by
320  * the inverse constant.
321  *
322  * RETURNS
323  *  (dividend * inverse_divisor) >> (64 + shift)
324  *
325  * NOTES
326  *  If the divisor of a division is constant, the constants inverse_divisor and
327  *  shift must be chosen such that inverse_divisor = 2^(64 + shift) / divisor.
328  *  Then we have RtlExtendedMagicDivide(dividend,inverse_divisor,shift) ==
329  *  dividend * inverse_divisor / 2^(64 + shift) == dividend / divisor.
330  *
331  *  The Parameter inverse_divisor although defined as LONGLONG is used as
332  *  ULONGLONG.
333  */
334 #define LOWER_32(A) ((A) & 0xffffffff)
335 #define UPPER_32(A) ((A) >> 32)
336 LONGLONG WINAPI RtlExtendedMagicDivide(
337     LONGLONG dividend,        /* [I] Dividend to be divided by the constant divisor */
338     LONGLONG inverse_divisor, /* [I] Constant computed manually as 2^(64+shift) / divisor */
339     INT shift)                /* [I] Constant shift chosen to make inverse_divisor as big as possible for 64 bits */
340 {
341     ULONGLONG dividend_high;
342     ULONGLONG dividend_low;
343     ULONGLONG inverse_divisor_high;
344     ULONGLONG inverse_divisor_low;
345     ULONGLONG ah_bl;
346     ULONGLONG al_bh;
347     LONGLONG result;
348     int positive;
349
350     if (dividend < 0) {
351         dividend_high = UPPER_32((ULONGLONG) -dividend);
352         dividend_low =  LOWER_32((ULONGLONG) -dividend);
353         positive = 0;
354     } else {
355         dividend_high = UPPER_32((ULONGLONG) dividend);
356         dividend_low =  LOWER_32((ULONGLONG) dividend);
357         positive = 1;
358     } /* if */
359     inverse_divisor_high = UPPER_32((ULONGLONG) inverse_divisor);
360     inverse_divisor_low =  LOWER_32((ULONGLONG) inverse_divisor);
361
362     ah_bl = dividend_high * inverse_divisor_low;
363     al_bh = dividend_low * inverse_divisor_high;
364
365     result = (LONGLONG) ((dividend_high * inverse_divisor_high +
366             UPPER_32(ah_bl) +
367             UPPER_32(al_bh) +
368             UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) +
369                      UPPER_32(dividend_low * inverse_divisor_low))) >> shift);
370
371     if (positive) {
372         return result;
373     } else {
374         return -result;
375     } /* if */
376 }
377
378 #endif  /* _WIN64 */
379
380 /******************************************************************************
381  *      RtlLargeIntegerToChar   [NTDLL.@]
382  *
383  * Convert an unsigned large integer to a character string.
384  *
385  * RETURNS
386  *  Success: STATUS_SUCCESS. str contains the converted number
387  *  Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
388  *           STATUS_BUFFER_OVERFLOW, if str would be larger than length.
389  *           STATUS_ACCESS_VIOLATION, if str is NULL.
390  *
391  * NOTES
392  *  Instead of base 0 it uses 10 as base.
393  *  Writes at most length characters to the string str.
394  *  Str is '\0' terminated when length allows it.
395  *  When str fits exactly in length characters the '\0' is omitted.
396  *  If value_ptr is NULL it crashes, as the native function does.
397  *
398  * DIFFERENCES
399  * - Accept base 0 as 10 instead of crashing as native function does.
400  * - The native function does produce garbage or STATUS_BUFFER_OVERFLOW for
401  *   base 2, 8 and 16 when the value is larger than 0xFFFFFFFF.
402  */
403 NTSTATUS WINAPI RtlLargeIntegerToChar(
404     const ULONGLONG *value_ptr, /* [I] Pointer to the value to be converted */
405     ULONG base,                 /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
406     ULONG length,               /* [I] Length of the str buffer in bytes */
407     PCHAR str)                  /* [O] Destination for the converted value */
408 {
409     ULONGLONG value = *value_ptr;
410     CHAR buffer[65];
411     PCHAR pos;
412     CHAR digit;
413     ULONG len;
414
415     if (base == 0) {
416         base = 10;
417     } else if (base != 2 && base != 8 && base != 10 && base != 16) {
418         return STATUS_INVALID_PARAMETER;
419     } /* if */
420
421     pos = &buffer[64];
422     *pos = '\0';
423
424     do {
425         pos--;
426         digit = value % base;
427         value = value / base;
428         if (digit < 10) {
429             *pos = '0' + digit;
430         } else {
431             *pos = 'A' + digit - 10;
432         } /* if */
433     } while (value != 0L);
434
435     len = &buffer[64] - pos;
436     if (len > length) {
437         return STATUS_BUFFER_OVERFLOW;
438     } else if (str == NULL) {
439         return STATUS_ACCESS_VIOLATION;
440     } else if (len == length) {
441         memcpy(str, pos, len);
442     } else {
443         memcpy(str, pos, len + 1);
444     } /* if */
445     return STATUS_SUCCESS;
446 }
447
448
449 /**************************************************************************
450  *      RtlInt64ToUnicodeString (NTDLL.@)
451  *
452  * Convert a large unsigned integer to a '\0' terminated unicode string.
453  *
454  * RETURNS
455  *  Success: STATUS_SUCCESS. str contains the converted number
456  *  Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
457  *           STATUS_BUFFER_OVERFLOW, if str is too small to hold the string
458  *                  (with the '\0' termination). In this case str->Length
459  *                  is set to the length, the string would have (which can
460  *                  be larger than the MaximumLength).
461  *
462  * NOTES
463  *  Instead of base 0 it uses 10 as base.
464  *  If str is NULL it crashes, as the native function does.
465  *
466  * DIFFERENCES
467  * - Accept base 0 as 10 instead of crashing as native function does.
468  * - Do not return STATUS_BUFFER_OVERFLOW when the string is long enough.
469  *   The native function does this when the string would be longer than 31
470  *   characters even when the string parameter is long enough.
471  * - The native function does produce garbage or STATUS_BUFFER_OVERFLOW for
472  *   base 2, 8 and 16 when the value is larger than 0xFFFFFFFF. 
473  */
474 NTSTATUS WINAPI RtlInt64ToUnicodeString(
475     ULONGLONG value,     /* [I] Value to be converted */
476     ULONG base,          /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
477     UNICODE_STRING *str) /* [O] Destination for the converted value */
478 {
479     WCHAR buffer[65];
480     PWCHAR pos;
481     WCHAR digit;
482
483     if (base == 0) {
484         base = 10;
485     } else if (base != 2 && base != 8 && base != 10 && base != 16) {
486         return STATUS_INVALID_PARAMETER;
487     } /* if */
488
489     pos = &buffer[64];
490     *pos = '\0';
491
492     do {
493         pos--;
494         digit = value % base;
495         value = value / base;
496         if (digit < 10) {
497             *pos = '0' + digit;
498         } else {
499             *pos = 'A' + digit - 10;
500         } /* if */
501     } while (value != 0L);
502
503     str->Length = (&buffer[64] - pos) * sizeof(WCHAR);
504     if (str->Length >= str->MaximumLength) {
505         return STATUS_BUFFER_OVERFLOW;
506     } else {
507         memcpy(str->Buffer, pos, str->Length + sizeof(WCHAR));
508     } /* if */
509     return STATUS_SUCCESS;
510 }
511
512
513 #ifdef __i386__
514
515 /******************************************************************************
516  *        _alldiv   (NTDLL.@)
517  *
518  * Divide two 64 bit unsigned integers.
519  *
520  * PARAMS
521  *  a [I] Initial number.
522  *  b [I] Number to multiply a by.
523  *
524  * RETURNS
525  *  The dividend of a and b.
526  */
527 LONGLONG WINAPI _alldiv( LONGLONG a, LONGLONG b )
528 {
529     return a / b;
530 }
531
532
533 /******************************************************************************
534  *        _allmul   (NTDLL.@)
535  *
536  * Multiply two 64 bit integers.
537  *
538  * PARAMS
539  *  a [I] Initial number.
540  *  b [I] Number to multiply a by.
541  *
542  * RETURNS
543  *  The product of a and b.
544  */
545 LONGLONG WINAPI _allmul( LONGLONG a, LONGLONG b )
546 {
547     return a * b;
548 }
549
550
551 /******************************************************************************
552  *        _allrem   (NTDLL.@)
553  *
554  * Calculate the remainder after dividing two 64 bit integers.
555  *
556  * PARAMS
557  *  a [I] Initial number.
558  *  b [I] Number to divide a by.
559  *
560  * RETURNS
561  *  The remainder of a divided by b.
562  */
563 LONGLONG WINAPI _allrem( LONGLONG a, LONGLONG b )
564 {
565     return a % b;
566 }
567
568
569 /******************************************************************************
570  *        _aulldiv   (NTDLL.@)
571  *
572  * Divide two 64 bit unsigned integers.
573  *
574  * PARAMS
575  *  a [I] Initial number.
576  *  b [I] Number to multiply a by.
577  *
578  * RETURNS
579  *  The dividend of a and b.
580  */
581 ULONGLONG WINAPI _aulldiv( ULONGLONG a, ULONGLONG b )
582 {
583     return a / b;
584 }
585
586
587 /******************************************************************************
588  *        _aullrem   (NTDLL.@)
589  *
590  * Calculate the remainder after dividing two 64 bit unsigned integers.
591  *
592  * PARAMS
593  *  a [I] Initial number.
594  *  b [I] Number to divide a by.
595  *
596  * RETURNS
597  *  The remainder of a divided by b.
598  */
599 ULONGLONG WINAPI _aullrem( ULONGLONG a, ULONGLONG b )
600 {
601     return a % b;
602 }
603
604 #endif  /* __i386__ */