Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencreate.c
Go to the documentation of this file.
00001 /* $Id: create.c 54326 2011-11-07 00:18:13Z ion $ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS system libraries 00005 * FILE: lib/kernel32/file/create.c 00006 * PURPOSE: Directory functions 00007 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) 00008 * UPDATE HISTORY: 00009 * Created 01/11/98 00010 * Removed use of SearchPath (not used by Windows) 00011 * 18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion) 00012 * 24/08/2002: removed superfluous DPRINTs (KJK::Hyperion) 00013 */ 00014 00015 /* INCLUDES *****************************************************************/ 00016 00017 #include <k32.h> 00018 #define NDEBUG 00019 #include <debug.h> 00020 00021 #if DBG 00022 DEBUG_CHANNEL(kernel32file); 00023 #endif 00024 00025 #define SYMLINK_FLAG_RELATIVE 1 00026 00027 typedef struct _REPARSE_DATA_BUFFER { 00028 ULONG ReparseTag; 00029 USHORT ReparseDataLength; 00030 USHORT Reserved; 00031 union { 00032 struct { 00033 USHORT SubstituteNameOffset; 00034 USHORT SubstituteNameLength; 00035 USHORT PrintNameOffset; 00036 USHORT PrintNameLength; 00037 ULONG Flags; 00038 WCHAR PathBuffer[1]; 00039 } SymbolicLinkReparseBuffer; 00040 struct { 00041 USHORT SubstituteNameOffset; 00042 USHORT SubstituteNameLength; 00043 USHORT PrintNameOffset; 00044 USHORT PrintNameLength; 00045 WCHAR PathBuffer[1]; 00046 } MountPointReparseBuffer; 00047 struct { 00048 UCHAR DataBuffer[1]; 00049 } GenericReparseBuffer; 00050 }; 00051 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; 00052 00053 #define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) 00054 00055 /* FUNCTIONS ****************************************************************/ 00056 00057 /* 00058 * @implemented 00059 */ 00060 HANDLE WINAPI CreateFileA (LPCSTR lpFileName, 00061 DWORD dwDesiredAccess, 00062 DWORD dwShareMode, 00063 LPSECURITY_ATTRIBUTES lpSecurityAttributes, 00064 DWORD dwCreationDisposition, 00065 DWORD dwFlagsAndAttributes, 00066 HANDLE hTemplateFile) 00067 { 00068 PWCHAR FileNameW; 00069 HANDLE FileHandle; 00070 00071 TRACE("CreateFileA(lpFileName %s)\n",lpFileName); 00072 00073 if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) 00074 return INVALID_HANDLE_VALUE; 00075 00076 FileHandle = CreateFileW (FileNameW, 00077 dwDesiredAccess, 00078 dwShareMode, 00079 lpSecurityAttributes, 00080 dwCreationDisposition, 00081 dwFlagsAndAttributes, 00082 hTemplateFile); 00083 00084 return FileHandle; 00085 } 00086 00087 00088 /* 00089 * @implemented 00090 */ 00091 HANDLE WINAPI CreateFileW (LPCWSTR lpFileName, 00092 DWORD dwDesiredAccess, 00093 DWORD dwShareMode, 00094 LPSECURITY_ATTRIBUTES lpSecurityAttributes, 00095 DWORD dwCreationDisposition, 00096 DWORD dwFlagsAndAttributes, 00097 HANDLE hTemplateFile) 00098 { 00099 OBJECT_ATTRIBUTES ObjectAttributes; 00100 IO_STATUS_BLOCK IoStatusBlock; 00101 UNICODE_STRING NtPathU; 00102 HANDLE FileHandle; 00103 NTSTATUS Status; 00104 ULONG FileAttributes, Flags = 0; 00105 PVOID EaBuffer = NULL; 00106 ULONG EaLength = 0; 00107 00108 if (!lpFileName || !lpFileName[0]) 00109 { 00110 SetLastError( ERROR_PATH_NOT_FOUND ); 00111 return INVALID_HANDLE_VALUE; 00112 } 00113 00114 TRACE("CreateFileW(lpFileName %S)\n",lpFileName); 00115 00116 /* validate & translate the creation disposition */ 00117 switch (dwCreationDisposition) 00118 { 00119 case CREATE_NEW: 00120 dwCreationDisposition = FILE_CREATE; 00121 break; 00122 00123 case CREATE_ALWAYS: 00124 dwCreationDisposition = FILE_OVERWRITE_IF; 00125 break; 00126 00127 case OPEN_EXISTING: 00128 dwCreationDisposition = FILE_OPEN; 00129 break; 00130 00131 case OPEN_ALWAYS: 00132 dwCreationDisposition = FILE_OPEN_IF; 00133 break; 00134 00135 case TRUNCATE_EXISTING: 00136 dwCreationDisposition = FILE_OVERWRITE; 00137 break; 00138 00139 default: 00140 SetLastError(ERROR_INVALID_PARAMETER); 00141 return (INVALID_HANDLE_VALUE); 00142 } 00143 00144 /* check for console input/output */ 00145 if (0 == _wcsicmp(L"CONOUT$", lpFileName) 00146 || 0 == _wcsicmp(L"CONIN$", lpFileName)) 00147 { 00148 return OpenConsoleW(lpFileName, 00149 dwDesiredAccess, 00150 lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE, 00151 FILE_SHARE_READ | FILE_SHARE_WRITE); 00152 } 00153 00154 /* validate & translate the flags */ 00155 00156 /* translate the flags that need no validation */ 00157 if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)) 00158 { 00159 /* yes, nonalert is correct! apc's are not delivered 00160 while waiting for file io to complete */ 00161 Flags |= FILE_SYNCHRONOUS_IO_NONALERT; 00162 } 00163 00164 if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) 00165 Flags |= FILE_WRITE_THROUGH; 00166 00167 if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING) 00168 Flags |= FILE_NO_INTERMEDIATE_BUFFERING; 00169 00170 if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS) 00171 Flags |= FILE_RANDOM_ACCESS; 00172 00173 if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN) 00174 Flags |= FILE_SEQUENTIAL_ONLY; 00175 00176 if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) 00177 Flags |= FILE_DELETE_ON_CLOSE; 00178 00179 if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) 00180 { 00181 if(dwDesiredAccess & GENERIC_ALL) 00182 Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REMOTE_INSTANCE; 00183 else 00184 { 00185 if(dwDesiredAccess & GENERIC_READ) 00186 Flags |= FILE_OPEN_FOR_BACKUP_INTENT; 00187 00188 if(dwDesiredAccess & GENERIC_WRITE) 00189 Flags |= FILE_OPEN_REMOTE_INSTANCE; 00190 } 00191 } 00192 else 00193 Flags |= FILE_NON_DIRECTORY_FILE; 00194 00195 if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) 00196 Flags |= FILE_OPEN_REPARSE_POINT; 00197 00198 if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL) 00199 Flags |= FILE_OPEN_NO_RECALL; 00200 00201 FileAttributes = (dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY)); 00202 00203 /* handle may allways be waited on and querying attributes are allways allowed */ 00204 dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; 00205 00206 /* FILE_FLAG_POSIX_SEMANTICS is handled later */ 00207 00208 /* validate & translate the filename */ 00209 if (!RtlDosPathNameToNtPathName_U (lpFileName, 00210 &NtPathU, 00211 NULL, 00212 NULL)) 00213 { 00214 WARN("Invalid path\n"); 00215 SetLastError(ERROR_FILE_NOT_FOUND); 00216 return INVALID_HANDLE_VALUE; 00217 } 00218 00219 TRACE("NtPathU \'%wZ\'\n", &NtPathU); 00220 00221 if (hTemplateFile != NULL) 00222 { 00223 FILE_EA_INFORMATION EaInformation; 00224 00225 for (;;) 00226 { 00227 /* try to get the size of the extended attributes, if we fail just continue 00228 creating the file without copying the attributes! */ 00229 Status = NtQueryInformationFile(hTemplateFile, 00230 &IoStatusBlock, 00231 &EaInformation, 00232 sizeof(FILE_EA_INFORMATION), 00233 FileEaInformation); 00234 if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0)) 00235 { 00236 /* there's extended attributes to read, let's give it a try */ 00237 EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 00238 0, 00239 EaInformation.EaSize); 00240 if (EaBuffer == NULL) 00241 { 00242 RtlFreeHeap(RtlGetProcessHeap(), 00243 0, 00244 NtPathU.Buffer); 00245 00246 /* the template file handle is valid and has extended attributes, 00247 however we seem to lack some memory here. We should fail here! */ 00248 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00249 return INVALID_HANDLE_VALUE; 00250 } 00251 00252 Status = NtQueryEaFile(hTemplateFile, 00253 &IoStatusBlock, 00254 EaBuffer, 00255 EaInformation.EaSize, 00256 FALSE, 00257 NULL, 00258 0, 00259 NULL, 00260 TRUE); 00261 00262 if (NT_SUCCESS(Status)) 00263 { 00264 /* we successfully read the extended attributes, break the loop 00265 and continue */ 00266 EaLength = EaInformation.EaSize; 00267 break; 00268 } 00269 else 00270 { 00271 RtlFreeHeap(RtlGetProcessHeap(), 00272 0, 00273 EaBuffer); 00274 EaBuffer = NULL; 00275 00276 if (Status != STATUS_BUFFER_TOO_SMALL) 00277 { 00278 /* unless we just allocated not enough memory, break the loop 00279 and just continue without copying extended attributes */ 00280 break; 00281 } 00282 } 00283 } 00284 else 00285 { 00286 /* we either failed to get the size of the extended attributes or 00287 they're empty, just continue as there's no need to copy 00288 attributes */ 00289 break; 00290 } 00291 } 00292 } 00293 00294 /* build the object attributes */ 00295 InitializeObjectAttributes(&ObjectAttributes, 00296 &NtPathU, 00297 0, 00298 NULL, 00299 NULL); 00300 00301 if (lpSecurityAttributes) 00302 { 00303 if(lpSecurityAttributes->bInheritHandle) 00304 ObjectAttributes.Attributes |= OBJ_INHERIT; 00305 00306 ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; 00307 } 00308 00309 if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS)) 00310 ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE; 00311 00312 /* perform the call */ 00313 Status = NtCreateFile (&FileHandle, 00314 dwDesiredAccess, 00315 &ObjectAttributes, 00316 &IoStatusBlock, 00317 NULL, 00318 FileAttributes, 00319 dwShareMode, 00320 dwCreationDisposition, 00321 Flags, 00322 EaBuffer, 00323 EaLength); 00324 00325 RtlFreeHeap(RtlGetProcessHeap(), 00326 0, 00327 NtPathU.Buffer); 00328 00329 /* free the extended attributes buffer if allocated */ 00330 if (EaBuffer != NULL) 00331 { 00332 RtlFreeHeap(RtlGetProcessHeap(), 00333 0, 00334 EaBuffer); 00335 } 00336 00337 /* error */ 00338 if (!NT_SUCCESS(Status)) 00339 { 00340 /* In the case file creation was rejected due to CREATE_NEW flag 00341 * was specified and file with that name already exists, correct 00342 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS. 00343 * Note: RtlNtStatusToDosError is not the subject to blame here. 00344 */ 00345 if (Status == STATUS_OBJECT_NAME_COLLISION && 00346 dwCreationDisposition == FILE_CREATE) 00347 { 00348 SetLastError( ERROR_FILE_EXISTS ); 00349 } 00350 else 00351 { 00352 BaseSetLastNTError (Status); 00353 } 00354 00355 return INVALID_HANDLE_VALUE; 00356 } 00357 00358 /* 00359 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED 00360 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED 00361 */ 00362 if (dwCreationDisposition == FILE_OPEN_IF) 00363 { 00364 SetLastError(IoStatusBlock.Information == FILE_OPENED ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS); 00365 } 00366 else if (dwCreationDisposition == FILE_OVERWRITE_IF) 00367 { 00368 SetLastError(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS); 00369 } 00370 else 00371 { 00372 SetLastError(ERROR_SUCCESS); 00373 } 00374 00375 return FileHandle; 00376 } 00377 00378 /* 00379 * @implemented 00380 */ 00381 HFILE WINAPI 00382 OpenFile(LPCSTR lpFileName, 00383 LPOFSTRUCT lpReOpenBuff, 00384 UINT uStyle) 00385 { 00386 OBJECT_ATTRIBUTES ObjectAttributes; 00387 IO_STATUS_BLOCK IoStatusBlock; 00388 UNICODE_STRING FileNameString; 00389 UNICODE_STRING FileNameU; 00390 ANSI_STRING FileName; 00391 WCHAR PathNameW[MAX_PATH]; 00392 HANDLE FileHandle = NULL; 00393 NTSTATUS errCode; 00394 PWCHAR FilePart; 00395 ULONG Len; 00396 00397 TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle); 00398 00399 if (lpReOpenBuff == NULL) 00400 { 00401 return HFILE_ERROR; 00402 } 00403 00404 lpReOpenBuff->nErrCode = 0; 00405 00406 if (uStyle & OF_REOPEN) lpFileName = lpReOpenBuff->szPathName; 00407 00408 if (!lpFileName) 00409 { 00410 return HFILE_ERROR; 00411 } 00412 00413 if (!GetFullPathNameA(lpFileName, 00414 sizeof(lpReOpenBuff->szPathName), 00415 lpReOpenBuff->szPathName, 00416 NULL)) 00417 { 00418 lpReOpenBuff->nErrCode = GetLastError(); 00419 return HFILE_ERROR; 00420 } 00421 00422 if (uStyle & OF_PARSE) 00423 { 00424 lpReOpenBuff->fFixedDisk = (GetDriveTypeA(lpReOpenBuff->szPathName) != DRIVE_REMOVABLE); 00425 TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName, lpReOpenBuff->szPathName); 00426 return 0; 00427 } 00428 00429 if ((uStyle & OF_EXIST) && !(uStyle & OF_CREATE)) 00430 { 00431 DWORD dwAttributes = GetFileAttributesA(lpReOpenBuff->szPathName); 00432 00433 switch (dwAttributes) 00434 { 00435 case 0xFFFFFFFF: /* File does not exist */ 00436 SetLastError(ERROR_FILE_NOT_FOUND); 00437 lpReOpenBuff->nErrCode = (WORD) ERROR_FILE_NOT_FOUND; 00438 return -1; 00439 00440 case FILE_ATTRIBUTE_DIRECTORY: 00441 SetLastError(ERROR_ACCESS_DENIED); 00442 lpReOpenBuff->nErrCode = (WORD) ERROR_ACCESS_DENIED; 00443 return -1; 00444 00445 default: 00446 lpReOpenBuff->cBytes = sizeof(OFSTRUCT); 00447 return 1; 00448 } 00449 } 00450 lpReOpenBuff->cBytes = sizeof(OFSTRUCT); 00451 if ((uStyle & OF_CREATE) == OF_CREATE) 00452 { 00453 DWORD Sharing; 00454 switch (uStyle & 0x70) 00455 { 00456 case OF_SHARE_EXCLUSIVE: Sharing = 0; break; 00457 case OF_SHARE_DENY_WRITE: Sharing = FILE_SHARE_READ; break; 00458 case OF_SHARE_DENY_READ: Sharing = FILE_SHARE_WRITE; break; 00459 case OF_SHARE_DENY_NONE: 00460 case OF_SHARE_COMPAT: 00461 default: 00462 Sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 00463 } 00464 return (HFILE) CreateFileA (lpFileName, 00465 GENERIC_READ | GENERIC_WRITE, 00466 Sharing, 00467 NULL, 00468 CREATE_ALWAYS, 00469 FILE_ATTRIBUTE_NORMAL, 00470 0); 00471 } 00472 00473 RtlInitAnsiString (&FileName, (LPSTR)lpFileName); 00474 00475 /* convert ansi (or oem) string to unicode */ 00476 if (bIsFileApiAnsi) 00477 RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE); 00478 else 00479 RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE); 00480 00481 Len = SearchPathW (NULL, 00482 FileNameU.Buffer, 00483 NULL, 00484 OFS_MAXPATHNAME, 00485 PathNameW, 00486 &FilePart); 00487 00488 RtlFreeUnicodeString(&FileNameU); 00489 00490 if (Len == 0 || Len > OFS_MAXPATHNAME) 00491 { 00492 lpReOpenBuff->nErrCode = GetLastError(); 00493 return (HFILE)INVALID_HANDLE_VALUE; 00494 } 00495 00496 if (uStyle & OF_DELETE) 00497 { 00498 if (!DeleteFileW(PathNameW)) 00499 { 00500 lpReOpenBuff->nErrCode = GetLastError(); 00501 return HFILE_ERROR; 00502 } 00503 TRACE("(%s): OF_DELETE return = OK\n", lpFileName); 00504 return TRUE; 00505 } 00506 00507 FileName.Buffer = lpReOpenBuff->szPathName; 00508 FileName.Length = 0; 00509 FileName.MaximumLength = OFS_MAXPATHNAME; 00510 00511 RtlInitUnicodeString(&FileNameU, PathNameW); 00512 00513 /* convert unicode string to ansi (or oem) */ 00514 if (bIsFileApiAnsi) 00515 RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE); 00516 else 00517 RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE); 00518 00519 if (!RtlDosPathNameToNtPathName_U (PathNameW, 00520 &FileNameString, 00521 NULL, 00522 NULL)) 00523 { 00524 return (HFILE)INVALID_HANDLE_VALUE; 00525 } 00526 00527 // FILE_SHARE_READ 00528 // FILE_NO_INTERMEDIATE_BUFFERING 00529 00530 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); 00531 ObjectAttributes.RootDirectory = NULL; 00532 ObjectAttributes.ObjectName = &FileNameString; 00533 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; 00534 ObjectAttributes.SecurityDescriptor = NULL; 00535 ObjectAttributes.SecurityQualityOfService = NULL; 00536 00537 errCode = NtOpenFile (&FileHandle, 00538 GENERIC_READ|SYNCHRONIZE, 00539 &ObjectAttributes, 00540 &IoStatusBlock, 00541 FILE_SHARE_READ, 00542 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT); 00543 00544 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString.Buffer); 00545 00546 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode); 00547 00548 if (!NT_SUCCESS(errCode)) 00549 { 00550 BaseSetLastNTError (errCode); 00551 return (HFILE)INVALID_HANDLE_VALUE; 00552 } 00553 00554 if (uStyle & OF_EXIST) 00555 { 00556 NtClose(FileHandle); 00557 return (HFILE)1; 00558 } 00559 00560 return (HFILE)FileHandle; 00561 } 00562 00563 /* 00564 * @unimplemented 00565 */ 00566 BOOL 00567 WINAPI 00568 OpenDataFile(HANDLE hFile, DWORD dwUnused) 00569 { 00570 STUB; 00571 return FALSE; 00572 } 00573 00574 /* 00575 * @unimplemented 00576 */ 00577 HANDLE 00578 WINAPI 00579 ReOpenFile(IN HANDLE hOriginalFile, 00580 IN DWORD dwDesiredAccess, 00581 IN DWORD dwShareMode, 00582 IN DWORD dwFlags) 00583 { 00584 STUB; 00585 return INVALID_HANDLE_VALUE; 00586 } 00587 00588 /* EOF */ Generated on Sun May 27 2012 04:16:58 for ReactOS by
1.7.6.1
|