summaryrefslogtreecommitdiff
path: root/src/os_win/os_errno.c
blob: 590fcdc9d44c65c32d4791a0a1acd86fab531a9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*-
 * Copyright (c) 2014-2016 MongoDB, Inc.
 * Copyright (c) 2008-2014 WiredTiger, Inc.
 *	All rights reserved.
 *
 * See the file LICENSE for redistribution information.
 */

#include "wt_internal.h"

static const int windows_error_offset = -29000;

/*
 * __wt_map_error_to_windows_error --
 *	Return a negative integer, an encoded Windows error
 * Standard C errors are positive integers from 0 - ~200
 * Windows errors are from 0 - 15999 according to the documentation
 */
static DWORD
__wt_map_error_to_windows_error(int error)
{
	/*
	 * Ensure we do not exceed the error range
	 * Also validate we do not get any COM errors
	 * (which are negative integers)
	 */
	WT_ASSERT(NULL, error < 0);

	return (error + -(windows_error_offset));
}

/*
 * __wt_map_windows_error_to_error --
 *	Return a positive integer, a decoded Windows error
 */
static int
__wt_map_windows_error_to_error(DWORD winerr)
{
	return (winerr + windows_error_offset);
}

/*
 * __wt_map_error_rdonly --
 *	Map an error into a  WiredTiger error code specific for
 *	read-only operation which intercepts based on certain types
 *	of failures.
 */
int
__wt_map_error_rdonly(int winerr)
{
	if (winerr == ERROR_FILE_NOT_FOUND)
		return (WT_NOTFOUND);
	else if (winerr == ERROR_ACCESS_DENIED)
		return (WT_PERM_DENIED);
	return (winerr);
}

/*
 * __wt_errno --
 *	Return errno, or WT_ERROR if errno not set.
 */
int
__wt_errno(void)
{
	/*
	 * Called when we know an error occurred, and we want the system
	 * error code, but there's some chance it's not set.
	 */
	DWORD err = GetLastError();

	/* GetLastError should only be called if we hit an actual error */
	WT_ASSERT(NULL, err != ERROR_SUCCESS);

	return (err == ERROR_SUCCESS ?
	    WT_ERROR : __wt_map_windows_error_to_error(err));
}

/*
 * __wt_strerror --
 *	Windows implementation of WT_SESSION.strerror and wiredtiger_strerror.
 */
const char *
__wt_strerror(WT_SESSION_IMPL *session, int error, char *errbuf, size_t errlen)
{
	DWORD lasterror;
	const char *p;
	char buf[512];

	/*
	 * Check for a WiredTiger or POSIX constant string, no buffer needed.
	 */
	if ((p = __wt_wiredtiger_error(error)) != NULL)
		return (p);

	/*
	 * When called from wiredtiger_strerror, write a passed-in buffer.
	 * When called from WT_SESSION.strerror, write the session's buffer.
	 *
	 * Check for Windows errors.
	 */
	if (error < 0) {
		error = __wt_map_error_to_windows_error(error);

		lasterror = FormatMessageA(
			FORMAT_MESSAGE_FROM_SYSTEM |
			    FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			error,
			0, /* let system choose the correct LANGID */
			buf,
			sizeof(buf),
			NULL);

		if (lasterror != 0 && session == NULL &&
		    snprintf(errbuf, errlen, "%s", buf) > 0)
			return (errbuf);
		if (lasterror != 0 && session != NULL &&
		    __wt_buf_fmt(session, &session->err, "%s", buf) == 0)
			return (session->err.data);
	}

	/* Fallback to a generic message. */
	if (session == NULL &&
	    snprintf(errbuf, errlen, "error return: %d", error) > 0)
		return (errbuf);
	if (session != NULL && __wt_buf_fmt(
	    session, &session->err, "error return: %d", error) == 0)
		return (session->err.data);

	/* Defeated. */
	return ("Unable to return error string");
}