Reactos
1//
2// fclose.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines fclose(), which closes a stdio stream.
7//
8#include <corecrt_internal_stdio.h>
9#include <corecrt_internal_ptd_propagation.h>
10
11
12
13// Closes a stdio stream after flushing the stream and freeing any buffer
14// associated with the stream (unless the buffer was set with setbuf). Returns
15// zero on success; EOF on failure (e.g., if the flush fails, or it is not a
16// valid file or the file is not open, etc.).
17static int __cdecl _fclose_nolock_internal(FILE* const public_stream, __crt_cached_ptd_host& ptd)
18{
19 __crt_stdio_stream const stream(public_stream);
20
21 _UCRT_VALIDATE_RETURN(ptd, stream.valid(), EINVAL, EOF);
22
23 int result = EOF;
24
25 if (stream.is_in_use())
26 {
27 result = __acrt_stdio_flush_nolock(stream.public_stream(), ptd);
28 __acrt_stdio_free_buffer_nolock(stream.public_stream());
29
30 if (_close_internal(_fileno(stream.public_stream()), ptd) < 0)
31 {
32 result = EOF;
33 }
34 else if (stream->_tmpfname != nullptr)
35 {
36 _free_crt(stream->_tmpfname);
37 stream->_tmpfname = nullptr;
38 }
39 }
40
41 __acrt_stdio_free_stream(stream);
42
43 return result;
44}
45
46extern "C" int __cdecl _fclose_nolock(FILE* const public_stream)
47{
48 __crt_cached_ptd_host ptd;
49 return _fclose_nolock_internal(public_stream, ptd);
50}
51
52static int __cdecl _fclose_internal(FILE* const public_stream, __crt_cached_ptd_host& ptd)
53{
54 __crt_stdio_stream const stream(public_stream);
55
56 _UCRT_VALIDATE_RETURN(ptd, stream.valid(), EINVAL, EOF);
57
58 // If the stream is backed by a string, it requires no synchronization,
59 // flushing, etc., so we can simply free it, which resets all of its
60 // data to the defaults.
61 if (stream.is_string_backed())
62 {
63 __acrt_stdio_free_stream(stream);
64 return EOF;
65 }
66
67 int return_value = 0;
68
69 _lock_file(stream.public_stream());
70 __try
71 {
72 return_value = _fclose_nolock_internal(stream.public_stream(), ptd);
73 }
74 __finally
75 {
76 _unlock_file(stream.public_stream());
77 }
78 __endtry
79
80 return return_value;
81}
82
83extern "C" int __cdecl fclose(FILE* const public_stream)
84{
85 __crt_cached_ptd_host ptd;
86 return _fclose_internal(public_stream, ptd);
87}