@@ -2126,133 +2126,123 @@ static void fs__access(uv_fs_t* req) {
2126
2126
SET_REQ_WIN32_ERROR (req , GetLastError ());
2127
2127
return ;
2128
2128
}
2129
+ DWORD sdLen = 0 , err = 0 , tokenAccess = 0 , executeAccessRights = 0 ,
2130
+ grantedAccess = 0 , privilegesLen = 0 ;
2131
+ SECURITY_INFORMATION si = NULL ;
2132
+ PSECURITY_DESCRIPTOR sd = NULL ;
2133
+ HANDLE hToken = NULL , hImpersonatedToken = NULL ;
2134
+ GENERIC_MAPPING mapping = { 0xFFFFFFFF };
2135
+ PRIVILEGE_SET privileges = { 0 };
2136
+ BOOL result = FALSE;
2129
2137
2130
2138
/*
2131
- * If write access was requested, ensure that either
2132
- * the requested file is not marked as READONLY,
2133
- * or that it's actually a directory (directories
2134
- * cannot be read-only in Windows)
2135
- */
2136
- if ((req -> fs .info .mode & W_OK ) &&
2137
- ((attr & FILE_ATTRIBUTE_READONLY ) ||
2138
- !(attr & FILE_ATTRIBUTE_DIRECTORY ))) {
2139
- SET_REQ_WIN32_ERROR (req , UV_EPERM );
2139
+ * First, we must allocate enough space. We do that
2140
+ * by first passing in a zero-length null pointer,
2141
+ * storing the desired length into `sd_length`.
2142
+ * We expect this call to fail with a certain error code.
2143
+ */
2144
+ si = OWNER_SECURITY_INFORMATION |
2145
+ GROUP_SECURITY_INFORMATION |
2146
+ DACL_SECURITY_INFORMATION ;
2147
+ if (GetFileSecurityW (req -> file .pathw , si , NULL , 0 , & sdLen )) {
2148
+ SET_REQ_RESULT (req , UV_UNKNOWN );
2149
+ return ;
2150
+ }
2151
+ err = GetLastError ();
2152
+ if (ERROR_INSUFFICIENT_BUFFER != err ) {
2153
+ SET_REQ_WIN32_ERROR (req , err );
2140
2154
return ;
2141
2155
}
2142
2156
2143
- /*
2144
- * If executable access was requested, we must check
2145
- * with the AccessCheck() ACL call. This is mildly
2146
- * expensive, so only do it if `X_OK` was requested.
2147
- */
2148
- if (req -> fs .info .mode & X_OK ) {
2149
- DWORD sdLen = 0 , err = 0 , tokenAccess = 0 , executeAccessRights = 0 ,
2150
- grantedAccess = 0 , privilegesLen = 0 ;
2151
- SECURITY_INFORMATION si = NULL ;
2152
- PSECURITY_DESCRIPTOR sd = NULL ;
2153
- HANDLE hToken = NULL , hImpersonatedToken = NULL ;
2154
- GENERIC_MAPPING mapping = { 0xFFFFFFFF };
2155
- PRIVILEGE_SET privileges = { 0 };
2156
- BOOL result = FALSE;
2157
-
2158
- /*
2159
- * First, we must allocate enough space. We do that
2160
- * by first passing in a zero-length null pointer,
2161
- * storing the desired length into `sd_length`.
2162
- * We expect this call to fail with a certain error code.
2163
- */
2164
- si = OWNER_SECURITY_INFORMATION |
2165
- GROUP_SECURITY_INFORMATION |
2166
- DACL_SECURITY_INFORMATION ;
2167
- if (GetFileSecurityW (req -> file .pathw , si , NULL , 0 , & sdLen )) {
2168
- SET_REQ_RESULT (req , UV_UNKNOWN );
2169
- return ;
2170
- }
2171
- err = GetLastError ();
2172
- if (ERROR_INSUFFICIENT_BUFFER != err ) {
2173
- SET_REQ_WIN32_ERROR (req , err );
2174
- return ;
2175
- }
2157
+ /* Now that we know how big `sd` must be, allocate it */
2158
+ sd = (PSECURITY_DESCRIPTOR )uv__malloc (sdLen );
2159
+ if (!sd ) {
2160
+ uv_fatal_error (ERROR_OUTOFMEMORY , "uv__malloc" );
2161
+ }
2176
2162
2177
- /* Now that we know how big `sd` must be, allocate it */
2178
- sd = ( PSECURITY_DESCRIPTOR ) uv__malloc ( sdLen );
2179
- if (! sd ) {
2180
- uv_fatal_error ( ERROR_OUTOFMEMORY , "uv__malloc" ) ;
2181
- }
2163
+ /* Call `GetFileSecurity()` with the requisite `sd` structure. */
2164
+ if (! GetFileSecurityW ( req -> file . pathw , si , sd , sdLen , & sdLen )) {
2165
+ SET_REQ_WIN32_ERROR ( req , GetLastError ());
2166
+ goto accesscheck_cleanup ;
2167
+ }
2182
2168
2183
- /* Call `GetFileSecurity()` with the requisite `sd` structure. */
2184
- if (!GetFileSecurityW (req -> file .pathw , si , sd , sdLen , & sdLen )) {
2185
- SET_REQ_WIN32_ERROR (req , GetLastError ());
2186
- goto accesscheck_cleanup ;
2187
- }
2169
+ /*
2170
+ * Next we need to create an impersonation token representing
2171
+ * the current user and the current process.
2172
+ */
2173
+ tokenAccess = TOKEN_IMPERSONATE |
2174
+ TOKEN_QUERY |
2175
+ TOKEN_DUPLICATE |
2176
+ STANDARD_RIGHTS_READ ;
2177
+ if (!OpenProcessToken (GetCurrentProcess (), tokenAccess , & hToken )) {
2178
+ SET_REQ_WIN32_ERROR (req , GetLastError ());
2179
+ goto accesscheck_cleanup ;
2180
+ }
2181
+ if (!DuplicateToken (hToken , SecurityImpersonation , & hImpersonatedToken )) {
2182
+ SET_REQ_WIN32_ERROR (req , GetLastError ());
2183
+ goto accesscheck_cleanup ;
2184
+ }
2188
2185
2186
+ /*
2187
+ * Next, construct a mapping from generic access rights to
2188
+ * the more specific access rights that AccessCheck expects.
2189
+ */
2190
+ executeAccessRights = 0 ;
2191
+ if (req -> fs .info .mode & R_OK ) {
2192
+ executeAccessRights |= FILE_GENERIC_READ ;
2193
+ mapping .GenericRead = FILE_GENERIC_READ ;
2194
+ }
2195
+ if (req -> fs .info .mode & W_OK ) {
2196
+ executeAccessRights |= FILE_GENERIC_WRITE ;
2197
+ mapping .GenericWrite = FILE_GENERIC_WRITE ;
2198
+ }
2199
+ if (req -> fs .info .mode & X_OK ) {
2200
+ executeAccessRights |= FILE_GENERIC_EXECUTE ;
2201
+ mapping .GenericExecute = FILE_GENERIC_EXECUTE ;
2202
+ }
2203
+ MapGenericMask (& executeAccessRights , & mapping );
2204
+
2205
+ privilegesLen = sizeof (privileges );
2206
+ result = FALSE;
2207
+ if (AccessCheck (sd ,
2208
+ hImpersonatedToken ,
2209
+ executeAccessRights ,
2210
+ & mapping ,
2211
+ & privileges ,
2212
+ & privilegesLen ,
2213
+ & grantedAccess ,
2214
+ & result )) {
2189
2215
/*
2190
- * Next we need to create an impersonation token representing
2191
- * the current user and the current process.
2192
- */
2193
- tokenAccess = TOKEN_IMPERSONATE |
2194
- TOKEN_QUERY |
2195
- TOKEN_DUPLICATE |
2196
- STANDARD_RIGHTS_READ ;
2197
- if (!OpenProcessToken (GetCurrentProcess (), tokenAccess , & hToken )) {
2198
- SET_REQ_WIN32_ERROR (req , GetLastError ());
2199
- goto accesscheck_cleanup ;
2200
- }
2201
- if (!DuplicateToken (hToken , SecurityImpersonation , & hImpersonatedToken )) {
2202
- SET_REQ_WIN32_ERROR (req , GetLastError ());
2216
+ * If AccessCheck passes, nothing went wrong, but
2217
+ * we must still check that we have access.
2218
+ */
2219
+ if (!result ) {
2220
+ SET_REQ_WIN32_ERROR (req , UV_EPERM );
2203
2221
goto accesscheck_cleanup ;
2204
2222
}
2205
-
2223
+ } else {
2206
2224
/*
2207
- * Next, construct a mapping from generic access rights to
2208
- * the more specific access rights that AccessCheck expects.
2209
- */
2210
- executeAccessRights = FILE_GENERIC_EXECUTE ;
2211
- mapping .GenericExecute = FILE_GENERIC_EXECUTE ;
2212
- MapGenericMask (& executeAccessRights , & mapping );
2213
-
2214
- privilegesLen = sizeof (privileges );
2215
- result = FALSE;
2216
- if (AccessCheck (sd ,
2217
- hImpersonatedToken ,
2218
- executeAccessRights ,
2219
- & mapping ,
2220
- & privileges ,
2221
- & privilegesLen ,
2222
- & grantedAccess ,
2223
- & result )) {
2224
- /*
2225
- * If AccessCheck passes, nothing went wrong, but
2226
- * we must still check that we have access.
2227
- */
2228
- if (!result ) {
2229
- SET_REQ_WIN32_ERROR (req , UV_EPERM );
2230
- goto accesscheck_cleanup ;
2231
- }
2232
- } else {
2233
- /*
2234
- * This signifies that something went wrong with the
2235
- * actual AccessCheck() invocation itself.
2236
- */
2237
- SET_REQ_WIN32_ERROR (req , GetLastError ());
2238
- goto accesscheck_cleanup ;
2239
- }
2225
+ * This signifies that something went wrong with the
2226
+ * actual AccessCheck() invocation itself.
2227
+ */
2228
+ SET_REQ_WIN32_ERROR (req , GetLastError ());
2229
+ goto accesscheck_cleanup ;
2230
+ }
2240
2231
2241
2232
accesscheck_cleanup :
2242
- uv__free (sd );
2243
- if (hImpersonatedToken != NULL ) {
2244
- CloseHandle (hImpersonatedToken );
2245
- }
2246
- if (hToken != NULL ) {
2247
- CloseHandle (hToken );
2248
- }
2249
- /*
2250
- * If the result is false, return immediately.
2251
- * Some error code has been set in the `req` already.
2252
- */
2253
- if (!result ) {
2254
- return ;
2255
- }
2233
+ uv__free (sd );
2234
+ if (hImpersonatedToken != NULL ) {
2235
+ CloseHandle (hImpersonatedToken );
2236
+ }
2237
+ if (hToken != NULL ) {
2238
+ CloseHandle (hToken );
2239
+ }
2240
+ /*
2241
+ * If the result is false, return immediately.
2242
+ * Some error code has been set in the `req` already.
2243
+ */
2244
+ if (!result ) {
2245
+ return ;
2256
2246
}
2257
2247
2258
2248
/* If we get to the end, everything worked out. */
0 commit comments