1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev#define NGX_UTF16_BUFLEN  256
13e18a033bSKonstantin Ananyev
14e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_win32_check_filename(u_char *name, u_short *u,
15e18a033bSKonstantin Ananyev    size_t len);
16e18a033bSKonstantin Ananyevstatic u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len);
17e18a033bSKonstantin Ananyev
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyev/* FILE_FLAG_BACKUP_SEMANTICS allows to obtain a handle to a directory */
20e18a033bSKonstantin Ananyev
21e18a033bSKonstantin Ananyevngx_fd_t
22e18a033bSKonstantin Ananyevngx_open_file(u_char *name, u_long mode, u_long create, u_long access)
23e18a033bSKonstantin Ananyev{
24e18a033bSKonstantin Ananyev    size_t      len;
25e18a033bSKonstantin Ananyev    u_short    *u;
26e18a033bSKonstantin Ananyev    ngx_fd_t    fd;
27e18a033bSKonstantin Ananyev    ngx_err_t   err;
28e18a033bSKonstantin Ananyev    u_short     utf16[NGX_UTF16_BUFLEN];
29e18a033bSKonstantin Ananyev
30e18a033bSKonstantin Ananyev    len = NGX_UTF16_BUFLEN;
31e18a033bSKonstantin Ananyev    u = ngx_utf8_to_utf16(utf16, name, &len);
32e18a033bSKonstantin Ananyev
33e18a033bSKonstantin Ananyev    if (u == NULL) {
34e18a033bSKonstantin Ananyev        return INVALID_HANDLE_VALUE;
35e18a033bSKonstantin Ananyev    }
36e18a033bSKonstantin Ananyev
37e18a033bSKonstantin Ananyev    fd = INVALID_HANDLE_VALUE;
38e18a033bSKonstantin Ananyev
39e18a033bSKonstantin Ananyev    if (create == NGX_FILE_OPEN
40e18a033bSKonstantin Ananyev        && ngx_win32_check_filename(name, u, len) != NGX_OK)
41e18a033bSKonstantin Ananyev    {
42e18a033bSKonstantin Ananyev        goto failed;
43e18a033bSKonstantin Ananyev    }
44e18a033bSKonstantin Ananyev
45e18a033bSKonstantin Ananyev    fd = CreateFileW(u, mode,
46e18a033bSKonstantin Ananyev                     FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
47e18a033bSKonstantin Ananyev                     NULL, create, FILE_FLAG_BACKUP_SEMANTICS, NULL);
48e18a033bSKonstantin Ananyev
49e18a033bSKonstantin Ananyevfailed:
50e18a033bSKonstantin Ananyev
51e18a033bSKonstantin Ananyev    if (u != utf16) {
52e18a033bSKonstantin Ananyev        err = ngx_errno;
53e18a033bSKonstantin Ananyev        ngx_free(u);
54e18a033bSKonstantin Ananyev        ngx_set_errno(err);
55e18a033bSKonstantin Ananyev    }
56e18a033bSKonstantin Ananyev
57e18a033bSKonstantin Ananyev    return fd;
58e18a033bSKonstantin Ananyev}
59e18a033bSKonstantin Ananyev
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyevssize_t
62e18a033bSKonstantin Ananyevngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
63e18a033bSKonstantin Ananyev{
64e18a033bSKonstantin Ananyev    u_long      n;
65e18a033bSKonstantin Ananyev    ngx_err_t   err;
66e18a033bSKonstantin Ananyev    OVERLAPPED  ovlp, *povlp;
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev    ovlp.Internal = 0;
69e18a033bSKonstantin Ananyev    ovlp.InternalHigh = 0;
70e18a033bSKonstantin Ananyev    ovlp.Offset = (u_long) offset;
71e18a033bSKonstantin Ananyev    ovlp.OffsetHigh = (u_long) (offset >> 32);
72e18a033bSKonstantin Ananyev    ovlp.hEvent = NULL;
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyev    povlp = &ovlp;
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyev    if (ReadFile(file->fd, buf, size, &n, povlp) == 0) {
77e18a033bSKonstantin Ananyev        err = ngx_errno;
78e18a033bSKonstantin Ananyev
79e18a033bSKonstantin Ananyev        if (err == ERROR_HANDLE_EOF) {
80e18a033bSKonstantin Ananyev            return 0;
81e18a033bSKonstantin Ananyev        }
82e18a033bSKonstantin Ananyev
83e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ERR, file->log, err,
84e18a033bSKonstantin Ananyev                      "ReadFile() \"%s\" failed", file->name.data);
85e18a033bSKonstantin Ananyev        return NGX_ERROR;
86e18a033bSKonstantin Ananyev    }
87e18a033bSKonstantin Ananyev
88e18a033bSKonstantin Ananyev    file->offset += n;
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyev    return n;
91e18a033bSKonstantin Ananyev}
92e18a033bSKonstantin Ananyev
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyevssize_t
95e18a033bSKonstantin Ananyevngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
96e18a033bSKonstantin Ananyev{
97e18a033bSKonstantin Ananyev    u_long      n;
98e18a033bSKonstantin Ananyev    OVERLAPPED  ovlp, *povlp;
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev    ovlp.Internal = 0;
101e18a033bSKonstantin Ananyev    ovlp.InternalHigh = 0;
102e18a033bSKonstantin Ananyev    ovlp.Offset = (u_long) offset;
103e18a033bSKonstantin Ananyev    ovlp.OffsetHigh = (u_long) (offset >> 32);
104e18a033bSKonstantin Ananyev    ovlp.hEvent = NULL;
105e18a033bSKonstantin Ananyev
106e18a033bSKonstantin Ananyev    povlp = &ovlp;
107e18a033bSKonstantin Ananyev
108e18a033bSKonstantin Ananyev    if (WriteFile(file->fd, buf, size, &n, povlp) == 0) {
109e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno,
110e18a033bSKonstantin Ananyev                      "WriteFile() \"%s\" failed", file->name.data);
111e18a033bSKonstantin Ananyev        return NGX_ERROR;
112e18a033bSKonstantin Ananyev    }
113e18a033bSKonstantin Ananyev
114e18a033bSKonstantin Ananyev    if (n != size) {
115e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, file->log, 0,
116e18a033bSKonstantin Ananyev                      "WriteFile() \"%s\" has written only %ul of %uz",
117e18a033bSKonstantin Ananyev                      file->name.data, n, size);
118e18a033bSKonstantin Ananyev        return NGX_ERROR;
119e18a033bSKonstantin Ananyev    }
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev    file->offset += n;
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev    return n;
124e18a033bSKonstantin Ananyev}
125e18a033bSKonstantin Ananyev
126e18a033bSKonstantin Ananyev
127e18a033bSKonstantin Ananyevssize_t
128e18a033bSKonstantin Ananyevngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
129e18a033bSKonstantin Ananyev    ngx_pool_t *pool)
130e18a033bSKonstantin Ananyev{
131e18a033bSKonstantin Ananyev    u_char   *buf, *prev;
132e18a033bSKonstantin Ananyev    size_t    size;
133e18a033bSKonstantin Ananyev    ssize_t   total, n;
134e18a033bSKonstantin Ananyev
135e18a033bSKonstantin Ananyev    total = 0;
136e18a033bSKonstantin Ananyev
137e18a033bSKonstantin Ananyev    while (cl) {
138e18a033bSKonstantin Ananyev        buf = cl->buf->pos;
139e18a033bSKonstantin Ananyev        prev = buf;
140e18a033bSKonstantin Ananyev        size = 0;
141e18a033bSKonstantin Ananyev
142e18a033bSKonstantin Ananyev        /* coalesce the neighbouring bufs */
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev        while (cl && prev == cl->buf->pos) {
145e18a033bSKonstantin Ananyev            size += cl->buf->last - cl->buf->pos;
146e18a033bSKonstantin Ananyev            prev = cl->buf->last;
147e18a033bSKonstantin Ananyev            cl = cl->next;
148e18a033bSKonstantin Ananyev        }
149e18a033bSKonstantin Ananyev
150e18a033bSKonstantin Ananyev        n = ngx_write_file(file, buf, size, offset);
151e18a033bSKonstantin Ananyev
152e18a033bSKonstantin Ananyev        if (n == NGX_ERROR) {
153e18a033bSKonstantin Ananyev            return NGX_ERROR;
154e18a033bSKonstantin Ananyev        }
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyev        total += n;
157e18a033bSKonstantin Ananyev        offset += n;
158e18a033bSKonstantin Ananyev    }
159e18a033bSKonstantin Ananyev
160e18a033bSKonstantin Ananyev    return total;
161e18a033bSKonstantin Ananyev}
162e18a033bSKonstantin Ananyev
163e18a033bSKonstantin Ananyev
164e18a033bSKonstantin Ananyevssize_t
165e18a033bSKonstantin Ananyevngx_read_fd(ngx_fd_t fd, void *buf, size_t size)
166e18a033bSKonstantin Ananyev{
167e18a033bSKonstantin Ananyev    u_long  n;
168e18a033bSKonstantin Ananyev
169e18a033bSKonstantin Ananyev    if (ReadFile(fd, buf, size, &n, NULL) != 0) {
170e18a033bSKonstantin Ananyev        return (size_t) n;
171e18a033bSKonstantin Ananyev    }
172e18a033bSKonstantin Ananyev
173e18a033bSKonstantin Ananyev    return -1;
174e18a033bSKonstantin Ananyev}
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyevssize_t
178e18a033bSKonstantin Ananyevngx_write_fd(ngx_fd_t fd, void *buf, size_t size)
179e18a033bSKonstantin Ananyev{
180e18a033bSKonstantin Ananyev    u_long  n;
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev    if (WriteFile(fd, buf, size, &n, NULL) != 0) {
183e18a033bSKonstantin Ananyev        return (size_t) n;
184e18a033bSKonstantin Ananyev    }
185e18a033bSKonstantin Ananyev
186e18a033bSKonstantin Ananyev    return -1;
187e18a033bSKonstantin Ananyev}
188e18a033bSKonstantin Ananyev
189e18a033bSKonstantin Ananyev
190e18a033bSKonstantin Ananyevssize_t
191e18a033bSKonstantin Ananyevngx_write_console(ngx_fd_t fd, void *buf, size_t size)
192e18a033bSKonstantin Ananyev{
193e18a033bSKonstantin Ananyev    u_long  n;
194e18a033bSKonstantin Ananyev
195e18a033bSKonstantin Ananyev    (void) CharToOemBuff(buf, buf, size);
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev    if (WriteFile(fd, buf, size, &n, NULL) != 0) {
198e18a033bSKonstantin Ananyev        return (size_t) n;
199e18a033bSKonstantin Ananyev    }
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev    return -1;
202e18a033bSKonstantin Ananyev}
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev
205e18a033bSKonstantin Ananyevngx_err_t
206e18a033bSKonstantin Ananyevngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log)
207e18a033bSKonstantin Ananyev{
208e18a033bSKonstantin Ananyev    u_char             *name;
209e18a033bSKonstantin Ananyev    ngx_err_t           err;
210e18a033bSKonstantin Ananyev    ngx_uint_t          collision;
211e18a033bSKonstantin Ananyev    ngx_atomic_uint_t   num;
212e18a033bSKonstantin Ananyev
213e18a033bSKonstantin Ananyev    name = ngx_alloc(to->len + 1 + NGX_ATOMIC_T_LEN + 1 + sizeof("DELETE"),
214e18a033bSKonstantin Ananyev                     log);
215e18a033bSKonstantin Ananyev    if (name == NULL) {
216e18a033bSKonstantin Ananyev        return NGX_ENOMEM;
217e18a033bSKonstantin Ananyev    }
218e18a033bSKonstantin Ananyev
219e18a033bSKonstantin Ananyev    ngx_memcpy(name, to->data, to->len);
220e18a033bSKonstantin Ananyev
221e18a033bSKonstantin Ananyev    collision = 0;
222e18a033bSKonstantin Ananyev
223e18a033bSKonstantin Ananyev    /* mutex_lock() (per cache or single ?) */
224e18a033bSKonstantin Ananyev
225e18a033bSKonstantin Ananyev    for ( ;; ) {
226e18a033bSKonstantin Ananyev        num = ngx_next_temp_number(collision);
227e18a033bSKonstantin Ananyev
228e18a033bSKonstantin Ananyev        ngx_sprintf(name + to->len, ".%0muA.DELETE%Z", num);
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev        if (MoveFile((const char *) to->data, (const char *) name) != 0) {
231e18a033bSKonstantin Ananyev            break;
232e18a033bSKonstantin Ananyev        }
233e18a033bSKonstantin Ananyev
234e18a033bSKonstantin Ananyev        collision = 1;
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
237e18a033bSKonstantin Ananyev                      "MoveFile() \"%s\" to \"%s\" failed", to->data, name);
238e18a033bSKonstantin Ananyev    }
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev    if (MoveFile((const char *) from->data, (const char *) to->data) == 0) {
241e18a033bSKonstantin Ananyev        err = ngx_errno;
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev    } else {
244e18a033bSKonstantin Ananyev        err = 0;
245e18a033bSKonstantin Ananyev    }
246e18a033bSKonstantin Ananyev
247e18a033bSKonstantin Ananyev    if (DeleteFile((const char *) name) == 0) {
248e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
249e18a033bSKonstantin Ananyev                      "DeleteFile() \"%s\" failed", name);
250e18a033bSKonstantin Ananyev    }
251e18a033bSKonstantin Ananyev
252e18a033bSKonstantin Ananyev    /* mutex_unlock() */
253e18a033bSKonstantin Ananyev
254e18a033bSKonstantin Ananyev    ngx_free(name);
255e18a033bSKonstantin Ananyev
256e18a033bSKonstantin Ananyev    return err;
257e18a033bSKonstantin Ananyev}
258e18a033bSKonstantin Ananyev
259e18a033bSKonstantin Ananyev
260e18a033bSKonstantin Ananyevngx_int_t
261e18a033bSKonstantin Ananyevngx_file_info(u_char *file, ngx_file_info_t *sb)
262e18a033bSKonstantin Ananyev{
263e18a033bSKonstantin Ananyev    size_t                      len;
264e18a033bSKonstantin Ananyev    long                        rc;
265e18a033bSKonstantin Ananyev    u_short                    *u;
266e18a033bSKonstantin Ananyev    ngx_err_t                   err;
267e18a033bSKonstantin Ananyev    WIN32_FILE_ATTRIBUTE_DATA   fa;
268e18a033bSKonstantin Ananyev    u_short                     utf16[NGX_UTF16_BUFLEN];
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev    len = NGX_UTF16_BUFLEN;
271e18a033bSKonstantin Ananyev
272e18a033bSKonstantin Ananyev    u = ngx_utf8_to_utf16(utf16, file, &len);
273e18a033bSKonstantin Ananyev
274e18a033bSKonstantin Ananyev    if (u == NULL) {
275e18a033bSKonstantin Ananyev        return NGX_FILE_ERROR;
276e18a033bSKonstantin Ananyev    }
277e18a033bSKonstantin Ananyev
278e18a033bSKonstantin Ananyev    rc = NGX_FILE_ERROR;
279e18a033bSKonstantin Ananyev
280e18a033bSKonstantin Ananyev    if (ngx_win32_check_filename(file, u, len) != NGX_OK) {
281e18a033bSKonstantin Ananyev        goto failed;
282e18a033bSKonstantin Ananyev    }
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyev    rc = GetFileAttributesExW(u, GetFileExInfoStandard, &fa);
285e18a033bSKonstantin Ananyev
286e18a033bSKonstantin Ananyev    sb->dwFileAttributes = fa.dwFileAttributes;
287e18a033bSKonstantin Ananyev    sb->ftCreationTime = fa.ftCreationTime;
288e18a033bSKonstantin Ananyev    sb->ftLastAccessTime = fa.ftLastAccessTime;
289e18a033bSKonstantin Ananyev    sb->ftLastWriteTime = fa.ftLastWriteTime;
290e18a033bSKonstantin Ananyev    sb->nFileSizeHigh = fa.nFileSizeHigh;
291e18a033bSKonstantin Ananyev    sb->nFileSizeLow = fa.nFileSizeLow;
292e18a033bSKonstantin Ananyev
293e18a033bSKonstantin Ananyevfailed:
294e18a033bSKonstantin Ananyev
295e18a033bSKonstantin Ananyev    if (u != utf16) {
296e18a033bSKonstantin Ananyev        err = ngx_errno;
297e18a033bSKonstantin Ananyev        ngx_free(u);
298e18a033bSKonstantin Ananyev        ngx_set_errno(err);
299e18a033bSKonstantin Ananyev    }
300e18a033bSKonstantin Ananyev
301e18a033bSKonstantin Ananyev    return rc;
302e18a033bSKonstantin Ananyev}
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev
305e18a033bSKonstantin Ananyevngx_int_t
306e18a033bSKonstantin Ananyevngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
307e18a033bSKonstantin Ananyev{
308e18a033bSKonstantin Ananyev    uint64_t  intervals;
309e18a033bSKonstantin Ananyev    FILETIME  ft;
310e18a033bSKonstantin Ananyev
311e18a033bSKonstantin Ananyev    /* 116444736000000000 is commented in src/os/win32/ngx_time.c */
312e18a033bSKonstantin Ananyev
313e18a033bSKonstantin Ananyev    intervals = s * 10000000 + 116444736000000000;
314e18a033bSKonstantin Ananyev
315e18a033bSKonstantin Ananyev    ft.dwLowDateTime = (DWORD) intervals;
316e18a033bSKonstantin Ananyev    ft.dwHighDateTime = (DWORD) (intervals >> 32);
317e18a033bSKonstantin Ananyev
318e18a033bSKonstantin Ananyev    if (SetFileTime(fd, NULL, NULL, &ft) != 0) {
319e18a033bSKonstantin Ananyev        return NGX_OK;
320e18a033bSKonstantin Ananyev    }
321e18a033bSKonstantin Ananyev
322e18a033bSKonstantin Ananyev    return NGX_ERROR;
323e18a033bSKonstantin Ananyev}
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyev
326e18a033bSKonstantin Ananyevngx_int_t
327e18a033bSKonstantin Ananyevngx_create_file_mapping(ngx_file_mapping_t *fm)
328e18a033bSKonstantin Ananyev{
329e18a033bSKonstantin Ananyev    LARGE_INTEGER  size;
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev    fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
332e18a033bSKonstantin Ananyev                           NGX_FILE_DEFAULT_ACCESS);
333e18a033bSKonstantin Ananyev    if (fm->fd == NGX_INVALID_FILE) {
334e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
335e18a033bSKonstantin Ananyev                      ngx_open_file_n " \"%s\" failed", fm->name);
336e18a033bSKonstantin Ananyev        return NGX_ERROR;
337e18a033bSKonstantin Ananyev    }
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev    fm->handle = NULL;
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev    size.QuadPart = fm->size;
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev    if (SetFilePointerEx(fm->fd, size, NULL, FILE_BEGIN) == 0) {
344e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
345e18a033bSKonstantin Ananyev                      "SetFilePointerEx(\"%s\", %uz) failed",
346e18a033bSKonstantin Ananyev                      fm->name, fm->size);
347e18a033bSKonstantin Ananyev        goto failed;
348e18a033bSKonstantin Ananyev    }
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev    if (SetEndOfFile(fm->fd) == 0) {
351e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
352e18a033bSKonstantin Ananyev                      "SetEndOfFile() \"%s\" failed", fm->name);
353e18a033bSKonstantin Ananyev        goto failed;
354e18a033bSKonstantin Ananyev    }
355e18a033bSKonstantin Ananyev
356e18a033bSKonstantin Ananyev    fm->handle = CreateFileMapping(fm->fd, NULL, PAGE_READWRITE,
357e18a033bSKonstantin Ananyev                                   (u_long) ((off_t) fm->size >> 32),
358e18a033bSKonstantin Ananyev                                   (u_long) ((off_t) fm->size & 0xffffffff),
359e18a033bSKonstantin Ananyev                                   NULL);
360e18a033bSKonstantin Ananyev    if (fm->handle == NULL) {
361e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
362e18a033bSKonstantin Ananyev                      "CreateFileMapping(%s, %uz) failed",
363e18a033bSKonstantin Ananyev                      fm->name, fm->size);
364e18a033bSKonstantin Ananyev        goto failed;
365e18a033bSKonstantin Ananyev    }
366e18a033bSKonstantin Ananyev
367e18a033bSKonstantin Ananyev    fm->addr = MapViewOfFile(fm->handle, FILE_MAP_WRITE, 0, 0, 0);
368e18a033bSKonstantin Ananyev
369e18a033bSKonstantin Ananyev    if (fm->addr != NULL) {
370e18a033bSKonstantin Ananyev        return NGX_OK;
371e18a033bSKonstantin Ananyev    }
372e18a033bSKonstantin Ananyev
373e18a033bSKonstantin Ananyev    ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
374e18a033bSKonstantin Ananyev                  "MapViewOfFile(%uz) of file mapping \"%s\" failed",
375e18a033bSKonstantin Ananyev                  fm->size, fm->name);
376e18a033bSKonstantin Ananyev
377e18a033bSKonstantin Ananyevfailed:
378e18a033bSKonstantin Ananyev
379e18a033bSKonstantin Ananyev    if (fm->handle) {
380e18a033bSKonstantin Ananyev        if (CloseHandle(fm->handle) == 0) {
381e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
382e18a033bSKonstantin Ananyev                          "CloseHandle() of file mapping \"%s\" failed",
383e18a033bSKonstantin Ananyev                          fm->name);
384e18a033bSKonstantin Ananyev        }
385e18a033bSKonstantin Ananyev    }
386e18a033bSKonstantin Ananyev
387e18a033bSKonstantin Ananyev    if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
388e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
389e18a033bSKonstantin Ananyev                      ngx_close_file_n " \"%s\" failed", fm->name);
390e18a033bSKonstantin Ananyev    }
391e18a033bSKonstantin Ananyev
392e18a033bSKonstantin Ananyev    return NGX_ERROR;
393e18a033bSKonstantin Ananyev}
394e18a033bSKonstantin Ananyev
395e18a033bSKonstantin Ananyev
396e18a033bSKonstantin Ananyevvoid
397e18a033bSKonstantin Ananyevngx_close_file_mapping(ngx_file_mapping_t *fm)
398e18a033bSKonstantin Ananyev{
399e18a033bSKonstantin Ananyev    if (UnmapViewOfFile(fm->addr) == 0) {
400e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
401e18a033bSKonstantin Ananyev                      "UnmapViewOfFile(%p) of file mapping \"%s\" failed",
402e18a033bSKonstantin Ananyev                      fm->addr, &fm->name);
403e18a033bSKonstantin Ananyev    }
404e18a033bSKonstantin Ananyev
405e18a033bSKonstantin Ananyev    if (CloseHandle(fm->handle) == 0) {
406e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
407e18a033bSKonstantin Ananyev                      "CloseHandle() of file mapping \"%s\" failed",
408e18a033bSKonstantin Ananyev                      &fm->name);
409e18a033bSKonstantin Ananyev    }
410e18a033bSKonstantin Ananyev
411e18a033bSKonstantin Ananyev    if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
412e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
413e18a033bSKonstantin Ananyev                      ngx_close_file_n " \"%s\" failed", fm->name);
414e18a033bSKonstantin Ananyev    }
415e18a033bSKonstantin Ananyev}
416e18a033bSKonstantin Ananyev
417e18a033bSKonstantin Ananyev
418e18a033bSKonstantin Ananyevu_char *
419