Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvolume.c
Go to the documentation of this file.
00001 /* $Id: volume.c 52819 2011-07-23 18:54:29Z ion $ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS system libraries 00005 * FILE: lib/kernel32/file/volume.c 00006 * PURPOSE: File volume functions 00007 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) 00008 * Erik Bos, Alexandre Julliard : 00009 * GetLogicalDriveStringsA, 00010 * GetLogicalDriveStringsW, GetLogicalDrives 00011 * UPDATE HISTORY: 00012 * Created 01/11/98 00013 */ 00014 //WINE copyright notice: 00015 /* 00016 * DOS drives handling functions 00017 * 00018 * Copyright 1993 Erik Bos 00019 * Copyright 1996 Alexandre Julliard 00020 */ 00021 00022 #include <k32.h> 00023 #define NDEBUG 00024 #include <debug.h> 00025 DEBUG_CHANNEL(kernel32file); 00026 00027 #define MAX_DOS_DRIVES 26 00028 00029 00030 static HANDLE 00031 InternalOpenDirW(LPCWSTR DirName, 00032 BOOLEAN Write) 00033 { 00034 UNICODE_STRING NtPathU; 00035 OBJECT_ATTRIBUTES ObjectAttributes; 00036 NTSTATUS errCode; 00037 IO_STATUS_BLOCK IoStatusBlock; 00038 HANDLE hFile; 00039 00040 if (!RtlDosPathNameToNtPathName_U(DirName, 00041 &NtPathU, 00042 NULL, 00043 NULL)) 00044 { 00045 WARN("Invalid path\n"); 00046 SetLastError(ERROR_BAD_PATHNAME); 00047 return INVALID_HANDLE_VALUE; 00048 } 00049 00050 InitializeObjectAttributes(&ObjectAttributes, 00051 &NtPathU, 00052 OBJ_CASE_INSENSITIVE, 00053 NULL, 00054 NULL); 00055 00056 errCode = NtCreateFile (&hFile, 00057 Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ, 00058 &ObjectAttributes, 00059 &IoStatusBlock, 00060 NULL, 00061 0, 00062 FILE_SHARE_READ|FILE_SHARE_WRITE, 00063 FILE_OPEN, 00064 0, 00065 NULL, 00066 0); 00067 00068 RtlFreeHeap(RtlGetProcessHeap(), 00069 0, 00070 NtPathU.Buffer); 00071 00072 if (!NT_SUCCESS(errCode)) 00073 { 00074 BaseSetLastNTError (errCode); 00075 return INVALID_HANDLE_VALUE; 00076 } 00077 return hFile; 00078 } 00079 00080 00081 /* 00082 * @implemented 00083 */ 00084 /* Synced to Wine-2008/12/28 */ 00085 DWORD WINAPI 00086 GetLogicalDriveStringsA(DWORD nBufferLength, 00087 LPSTR lpBuffer) 00088 { 00089 DWORD drive, count; 00090 DWORD dwDriveMap; 00091 LPSTR p; 00092 00093 dwDriveMap = GetLogicalDrives(); 00094 00095 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) 00096 { 00097 if (dwDriveMap & (1<<drive)) 00098 count++; 00099 } 00100 00101 00102 if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1); 00103 00104 p = lpBuffer; 00105 00106 for (drive = 0; drive < MAX_DOS_DRIVES; drive++) 00107 if (dwDriveMap & (1<<drive)) 00108 { 00109 *p++ = 'A' + (UCHAR)drive; 00110 *p++ = ':'; 00111 *p++ = '\\'; 00112 *p++ = '\0'; 00113 } 00114 *p = '\0'; 00115 00116 return (count * 4); 00117 } 00118 00119 00120 /* 00121 * @implemented 00122 */ 00123 /* Synced to Wine-2008/12/28 */ 00124 DWORD WINAPI 00125 GetLogicalDriveStringsW(DWORD nBufferLength, 00126 LPWSTR lpBuffer) 00127 { 00128 DWORD drive, count; 00129 DWORD dwDriveMap; 00130 LPWSTR p; 00131 00132 dwDriveMap = GetLogicalDrives(); 00133 00134 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) 00135 { 00136 if (dwDriveMap & (1<<drive)) 00137 count++; 00138 } 00139 00140 if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1); 00141 00142 p = lpBuffer; 00143 for (drive = 0; drive < MAX_DOS_DRIVES; drive++) 00144 if (dwDriveMap & (1<<drive)) 00145 { 00146 *p++ = (WCHAR)('A' + drive); 00147 *p++ = (WCHAR)':'; 00148 *p++ = (WCHAR)'\\'; 00149 *p++ = (WCHAR)'\0'; 00150 } 00151 *p = (WCHAR)'\0'; 00152 00153 return (count * 4); 00154 } 00155 00156 00157 /* 00158 * @implemented 00159 */ 00160 /* Synced to Wine-? */ 00161 DWORD WINAPI 00162 GetLogicalDrives(VOID) 00163 { 00164 NTSTATUS Status; 00165 PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo; 00166 00167 /* Get the Device Map for this Process */ 00168 Status = NtQueryInformationProcess(NtCurrentProcess(), 00169 ProcessDeviceMap, 00170 &ProcessDeviceMapInfo, 00171 sizeof(ProcessDeviceMapInfo), 00172 NULL); 00173 00174 /* Return the Drive Map */ 00175 if (!NT_SUCCESS(Status)) 00176 { 00177 BaseSetLastNTError(Status); 00178 return 0; 00179 } 00180 00181 return ProcessDeviceMapInfo.Query.DriveMap; 00182 } 00183 00184 00185 /* 00186 * @implemented 00187 */ 00188 BOOL WINAPI 00189 GetDiskFreeSpaceA ( 00190 LPCSTR lpRootPathName, 00191 LPDWORD lpSectorsPerCluster, 00192 LPDWORD lpBytesPerSector, 00193 LPDWORD lpNumberOfFreeClusters, 00194 LPDWORD lpTotalNumberOfClusters 00195 ) 00196 { 00197 PWCHAR RootPathNameW=NULL; 00198 00199 if (lpRootPathName) 00200 { 00201 if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) 00202 return FALSE; 00203 } 00204 00205 return GetDiskFreeSpaceW (RootPathNameW, 00206 lpSectorsPerCluster, 00207 lpBytesPerSector, 00208 lpNumberOfFreeClusters, 00209 lpTotalNumberOfClusters); 00210 } 00211 00212 00213 /* 00214 * @implemented 00215 */ 00216 BOOL WINAPI 00217 GetDiskFreeSpaceW( 00218 LPCWSTR lpRootPathName, 00219 LPDWORD lpSectorsPerCluster, 00220 LPDWORD lpBytesPerSector, 00221 LPDWORD lpNumberOfFreeClusters, 00222 LPDWORD lpTotalNumberOfClusters 00223 ) 00224 { 00225 FILE_FS_SIZE_INFORMATION FileFsSize; 00226 IO_STATUS_BLOCK IoStatusBlock; 00227 WCHAR RootPathName[MAX_PATH]; 00228 HANDLE hFile; 00229 NTSTATUS errCode; 00230 00231 if (lpRootPathName) 00232 { 00233 wcsncpy (RootPathName, lpRootPathName, 3); 00234 } 00235 else 00236 { 00237 GetCurrentDirectoryW (MAX_PATH, RootPathName); 00238 } 00239 RootPathName[3] = 0; 00240 00241 hFile = InternalOpenDirW(RootPathName, FALSE); 00242 if (INVALID_HANDLE_VALUE == hFile) 00243 { 00244 SetLastError(ERROR_PATH_NOT_FOUND); 00245 return FALSE; 00246 } 00247 00248 errCode = NtQueryVolumeInformationFile(hFile, 00249 &IoStatusBlock, 00250 &FileFsSize, 00251 sizeof(FILE_FS_SIZE_INFORMATION), 00252 FileFsSizeInformation); 00253 if (!NT_SUCCESS(errCode)) 00254 { 00255 CloseHandle(hFile); 00256 BaseSetLastNTError (errCode); 00257 return FALSE; 00258 } 00259 00260 if (lpSectorsPerCluster) 00261 *lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit; 00262 if (lpBytesPerSector) 00263 *lpBytesPerSector = FileFsSize.BytesPerSector; 00264 if (lpNumberOfFreeClusters) 00265 *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart; 00266 if (lpTotalNumberOfClusters) 00267 *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart; 00268 CloseHandle(hFile); 00269 00270 return TRUE; 00271 } 00272 00273 00274 /* 00275 * @implemented 00276 */ 00277 BOOL WINAPI 00278 GetDiskFreeSpaceExA ( 00279 LPCSTR lpDirectoryName OPTIONAL, 00280 PULARGE_INTEGER lpFreeBytesAvailableToCaller, 00281 PULARGE_INTEGER lpTotalNumberOfBytes, 00282 PULARGE_INTEGER lpTotalNumberOfFreeBytes 00283 ) 00284 { 00285 PWCHAR DirectoryNameW=NULL; 00286 00287 if (lpDirectoryName) 00288 { 00289 if (!(DirectoryNameW = FilenameA2W(lpDirectoryName, FALSE))) 00290 return FALSE; 00291 } 00292 00293 return GetDiskFreeSpaceExW (DirectoryNameW , 00294 lpFreeBytesAvailableToCaller, 00295 lpTotalNumberOfBytes, 00296 lpTotalNumberOfFreeBytes); 00297 } 00298 00299 00300 /* 00301 * @implemented 00302 */ 00303 BOOL WINAPI 00304 GetDiskFreeSpaceExW( 00305 LPCWSTR lpDirectoryName OPTIONAL, 00306 PULARGE_INTEGER lpFreeBytesAvailableToCaller, 00307 PULARGE_INTEGER lpTotalNumberOfBytes, 00308 PULARGE_INTEGER lpTotalNumberOfFreeBytes 00309 ) 00310 { 00311 union 00312 { 00313 FILE_FS_SIZE_INFORMATION FsSize; 00314 FILE_FS_FULL_SIZE_INFORMATION FsFullSize; 00315 } FsInfo; 00316 IO_STATUS_BLOCK IoStatusBlock; 00317 ULARGE_INTEGER BytesPerCluster; 00318 HANDLE hFile; 00319 NTSTATUS Status; 00320 00321 if (lpDirectoryName == NULL) 00322 lpDirectoryName = L"\\"; 00323 00324 hFile = InternalOpenDirW(lpDirectoryName, FALSE); 00325 if (INVALID_HANDLE_VALUE == hFile) 00326 { 00327 return FALSE; 00328 } 00329 00330 if (lpFreeBytesAvailableToCaller != NULL || lpTotalNumberOfBytes != NULL) 00331 { 00332 /* To get the free space available to the user associated with the 00333 current thread, try FileFsFullSizeInformation. If this is not 00334 supported by the file system, fall back to FileFsSize */ 00335 00336 Status = NtQueryVolumeInformationFile(hFile, 00337 &IoStatusBlock, 00338 &FsInfo.FsFullSize, 00339 sizeof(FsInfo.FsFullSize), 00340 FileFsFullSizeInformation); 00341 00342 if (NT_SUCCESS(Status)) 00343 { 00344 /* Close the handle before returning data 00345 to avoid a handle leak in case of a fault! */ 00346 CloseHandle(hFile); 00347 00348 BytesPerCluster.QuadPart = 00349 FsInfo.FsFullSize.BytesPerSector * FsInfo.FsFullSize.SectorsPerAllocationUnit; 00350 00351 if (lpFreeBytesAvailableToCaller != NULL) 00352 { 00353 lpFreeBytesAvailableToCaller->QuadPart = 00354 BytesPerCluster.QuadPart * FsInfo.FsFullSize.CallerAvailableAllocationUnits.QuadPart; 00355 } 00356 00357 if (lpTotalNumberOfBytes != NULL) 00358 { 00359 lpTotalNumberOfBytes->QuadPart = 00360 BytesPerCluster.QuadPart * FsInfo.FsFullSize.TotalAllocationUnits.QuadPart; 00361 } 00362 00363 if (lpTotalNumberOfFreeBytes != NULL) 00364 { 00365 lpTotalNumberOfFreeBytes->QuadPart = 00366 BytesPerCluster.QuadPart * FsInfo.FsFullSize.ActualAvailableAllocationUnits.QuadPart; 00367 } 00368 00369 return TRUE; 00370 } 00371 } 00372 00373 Status = NtQueryVolumeInformationFile(hFile, 00374 &IoStatusBlock, 00375 &FsInfo.FsSize, 00376 sizeof(FsInfo.FsSize), 00377 FileFsSizeInformation); 00378 00379 /* Close the handle before returning data 00380 to avoid a handle leak in case of a fault! */ 00381 CloseHandle(hFile); 00382 00383 if (!NT_SUCCESS(Status)) 00384 { 00385 BaseSetLastNTError (Status); 00386 return FALSE; 00387 } 00388 00389 BytesPerCluster.QuadPart = 00390 FsInfo.FsSize.BytesPerSector * FsInfo.FsSize.SectorsPerAllocationUnit; 00391 00392 if (lpFreeBytesAvailableToCaller) 00393 { 00394 lpFreeBytesAvailableToCaller->QuadPart = 00395 BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart; 00396 } 00397 00398 if (lpTotalNumberOfBytes) 00399 { 00400 lpTotalNumberOfBytes->QuadPart = 00401 BytesPerCluster.QuadPart * FsInfo.FsSize.TotalAllocationUnits.QuadPart; 00402 } 00403 00404 if (lpTotalNumberOfFreeBytes) 00405 { 00406 lpTotalNumberOfFreeBytes->QuadPart = 00407 BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart; 00408 } 00409 00410 return TRUE; 00411 } 00412 00413 00414 /* 00415 * @implemented 00416 */ 00417 UINT WINAPI 00418 GetDriveTypeA(LPCSTR lpRootPathName) 00419 { 00420 PWCHAR RootPathNameW; 00421 00422 if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) 00423 return DRIVE_UNKNOWN; 00424 00425 return GetDriveTypeW(RootPathNameW); 00426 } 00427 00428 00429 /* 00430 * @implemented 00431 */ 00432 UINT WINAPI 00433 GetDriveTypeW(LPCWSTR lpRootPathName) 00434 { 00435 FILE_FS_DEVICE_INFORMATION FileFsDevice; 00436 IO_STATUS_BLOCK IoStatusBlock; 00437 00438 HANDLE hFile; 00439 NTSTATUS errCode; 00440 00441 hFile = InternalOpenDirW(lpRootPathName, FALSE); 00442 if (hFile == INVALID_HANDLE_VALUE) 00443 { 00444 return DRIVE_NO_ROOT_DIR; /* According to WINE regression tests */ 00445 } 00446 00447 errCode = NtQueryVolumeInformationFile (hFile, 00448 &IoStatusBlock, 00449 &FileFsDevice, 00450 sizeof(FILE_FS_DEVICE_INFORMATION), 00451 FileFsDeviceInformation); 00452 if (!NT_SUCCESS(errCode)) 00453 { 00454 CloseHandle(hFile); 00455 BaseSetLastNTError (errCode); 00456 return 0; 00457 } 00458 CloseHandle(hFile); 00459 00460 switch (FileFsDevice.DeviceType) 00461 { 00462 case FILE_DEVICE_CD_ROM: 00463 case FILE_DEVICE_CD_ROM_FILE_SYSTEM: 00464 return DRIVE_CDROM; 00465 case FILE_DEVICE_VIRTUAL_DISK: 00466 return DRIVE_RAMDISK; 00467 case FILE_DEVICE_NETWORK_FILE_SYSTEM: 00468 return DRIVE_REMOTE; 00469 case FILE_DEVICE_DISK: 00470 case FILE_DEVICE_DISK_FILE_SYSTEM: 00471 if (FileFsDevice.Characteristics & FILE_REMOTE_DEVICE) 00472 return DRIVE_REMOTE; 00473 if (FileFsDevice.Characteristics & FILE_REMOVABLE_MEDIA) 00474 return DRIVE_REMOVABLE; 00475 return DRIVE_FIXED; 00476 } 00477 00478 ERR("Returning DRIVE_UNKNOWN for device type %d\n", FileFsDevice.DeviceType); 00479 00480 return DRIVE_UNKNOWN; 00481 } 00482 00483 00484 /* 00485 * @implemented 00486 */ 00487 BOOL WINAPI 00488 GetVolumeInformationA( 00489 LPCSTR lpRootPathName, 00490 LPSTR lpVolumeNameBuffer, 00491 DWORD nVolumeNameSize, 00492 LPDWORD lpVolumeSerialNumber, 00493 LPDWORD lpMaximumComponentLength, 00494 LPDWORD lpFileSystemFlags, 00495 LPSTR lpFileSystemNameBuffer, 00496 DWORD nFileSystemNameSize 00497 ) 00498 { 00499 UNICODE_STRING FileSystemNameU; 00500 UNICODE_STRING VolumeNameU = { 0, 0, NULL }; 00501 ANSI_STRING VolumeName; 00502 ANSI_STRING FileSystemName; 00503 PWCHAR RootPathNameW; 00504 BOOL Result; 00505 00506 if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) 00507 return FALSE; 00508 00509 if (lpVolumeNameBuffer) 00510 { 00511 VolumeNameU.MaximumLength = (USHORT)nVolumeNameSize * sizeof(WCHAR); 00512 VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), 00513 0, 00514 VolumeNameU.MaximumLength); 00515 if (VolumeNameU.Buffer == NULL) 00516 { 00517 goto FailNoMem; 00518 } 00519 } 00520 00521 if (lpFileSystemNameBuffer) 00522 { 00523 FileSystemNameU.Length = 0; 00524 FileSystemNameU.MaximumLength = (USHORT)nFileSystemNameSize * sizeof(WCHAR); 00525 FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), 00526 0, 00527 FileSystemNameU.MaximumLength); 00528 if (FileSystemNameU.Buffer == NULL) 00529 { 00530 if (VolumeNameU.Buffer != NULL) 00531 { 00532 RtlFreeHeap(RtlGetProcessHeap(), 00533 0, 00534 VolumeNameU.Buffer); 00535 } 00536 00537 FailNoMem: 00538 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00539 return FALSE; 00540 } 00541 } 00542 00543 Result = GetVolumeInformationW (RootPathNameW, 00544 lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL, 00545 nVolumeNameSize, 00546 lpVolumeSerialNumber, 00547 lpMaximumComponentLength, 00548 lpFileSystemFlags, 00549 lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL, 00550 nFileSystemNameSize); 00551 00552 if (Result) 00553 { 00554 if (lpVolumeNameBuffer) 00555 { 00556 VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR); 00557 VolumeName.Length = 0; 00558 VolumeName.MaximumLength = (USHORT)nVolumeNameSize; 00559 VolumeName.Buffer = lpVolumeNameBuffer; 00560 } 00561 00562 if (lpFileSystemNameBuffer) 00563 { 00564 FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR); 00565 FileSystemName.Length = 0; 00566 FileSystemName.MaximumLength = (USHORT)nFileSystemNameSize; 00567 FileSystemName.Buffer = lpFileSystemNameBuffer; 00568 } 00569 00570 /* convert unicode strings to ansi (or oem) */ 00571 if (bIsFileApiAnsi) 00572 { 00573 if (lpVolumeNameBuffer) 00574 { 00575 RtlUnicodeStringToAnsiString (&VolumeName, 00576 &VolumeNameU, 00577 FALSE); 00578 } 00579 if (lpFileSystemNameBuffer) 00580 { 00581 RtlUnicodeStringToAnsiString (&FileSystemName, 00582 &FileSystemNameU, 00583 FALSE); 00584 } 00585 } 00586 else 00587 { 00588 if (lpVolumeNameBuffer) 00589 { 00590 RtlUnicodeStringToOemString (&VolumeName, 00591 &VolumeNameU, 00592 FALSE); 00593 } 00594 if (lpFileSystemNameBuffer) 00595 { 00596 RtlUnicodeStringToOemString (&FileSystemName, 00597 &FileSystemNameU, 00598 FALSE); 00599 } 00600 } 00601 } 00602 00603 if (lpVolumeNameBuffer) 00604 { 00605 RtlFreeHeap (RtlGetProcessHeap (), 00606 0, 00607 VolumeNameU.Buffer); 00608 } 00609 if (lpFileSystemNameBuffer) 00610 { 00611 RtlFreeHeap (RtlGetProcessHeap (), 00612 0, 00613 FileSystemNameU.Buffer); 00614 } 00615 00616 return Result; 00617 } 00618 00619 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION)) 00620 00621 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) 00622 00623 /* 00624 * @implemented 00625 */ 00626 BOOL WINAPI 00627 GetVolumeInformationW( 00628 LPCWSTR lpRootPathName, 00629 LPWSTR lpVolumeNameBuffer, 00630 DWORD nVolumeNameSize, 00631 LPDWORD lpVolumeSerialNumber, 00632 LPDWORD lpMaximumComponentLength, 00633 LPDWORD lpFileSystemFlags, 00634 LPWSTR lpFileSystemNameBuffer, 00635 DWORD nFileSystemNameSize 00636 ) 00637 { 00638 PFILE_FS_VOLUME_INFORMATION FileFsVolume; 00639 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute; 00640 IO_STATUS_BLOCK IoStatusBlock; 00641 WCHAR RootPathName[MAX_PATH]; 00642 UCHAR Buffer[max(FS_VOLUME_BUFFER_SIZE, FS_ATTRIBUTE_BUFFER_SIZE)]; 00643 00644 HANDLE hFile; 00645 NTSTATUS errCode; 00646 00647 FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer; 00648 FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer; 00649 00650 TRACE("FileFsVolume %p\n", FileFsVolume); 00651 TRACE("FileFsAttribute %p\n", FileFsAttribute); 00652 00653 if (!lpRootPathName || !wcscmp(lpRootPathName, L"")) 00654 { 00655 GetCurrentDirectoryW (MAX_PATH, RootPathName); 00656 } 00657 else 00658 { 00659 wcsncpy (RootPathName, lpRootPathName, 3); 00660 } 00661 RootPathName[3] = 0; 00662 00663 hFile = InternalOpenDirW(RootPathName, FALSE); 00664 if (hFile == INVALID_HANDLE_VALUE) 00665 { 00666 return FALSE; 00667 } 00668 00669 TRACE("hFile: %x\n", hFile); 00670 errCode = NtQueryVolumeInformationFile(hFile, 00671 &IoStatusBlock, 00672 FileFsVolume, 00673 FS_VOLUME_BUFFER_SIZE, 00674 FileFsVolumeInformation); 00675 if ( !NT_SUCCESS(errCode) ) 00676 { 00677 WARN("Status: %x\n", errCode); 00678 CloseHandle(hFile); 00679 BaseSetLastNTError (errCode); 00680 return FALSE; 00681 } 00682 00683 if (lpVolumeSerialNumber) 00684 *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber; 00685 00686 if (lpVolumeNameBuffer) 00687 { 00688 if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR)) 00689 { 00690 memcpy(lpVolumeNameBuffer, 00691 FileFsVolume->VolumeLabel, 00692 FileFsVolume->VolumeLabelLength); 00693 lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0; 00694 } 00695 else 00696 { 00697 CloseHandle(hFile); 00698 SetLastError(ERROR_MORE_DATA); 00699 return FALSE; 00700 } 00701 } 00702 00703 errCode = NtQueryVolumeInformationFile (hFile, 00704 &IoStatusBlock, 00705 FileFsAttribute, 00706 FS_ATTRIBUTE_BUFFER_SIZE, 00707 FileFsAttributeInformation); 00708 CloseHandle(hFile); 00709 if (!NT_SUCCESS(errCode)) 00710 { 00711 WARN("Status: %x\n", errCode); 00712 BaseSetLastNTError (errCode); 00713 return FALSE; 00714 } 00715 00716 if (lpFileSystemFlags) 00717 *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes; 00718 if (lpMaximumComponentLength) 00719 *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength; 00720 if (lpFileSystemNameBuffer) 00721 { 00722 if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR)) 00723 { 00724 memcpy(lpFileSystemNameBuffer, 00725 FileFsAttribute->FileSystemName, 00726 FileFsAttribute->FileSystemNameLength); 00727 lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0; 00728 } 00729 else 00730 { 00731 SetLastError(ERROR_MORE_DATA); 00732 return FALSE; 00733 } 00734 } 00735 return TRUE; 00736 } 00737 00738 00739 /* 00740 * @implemented 00741 */ 00742 BOOL 00743 WINAPI 00744 SetVolumeLabelA ( 00745 LPCSTR lpRootPathName, 00746 LPCSTR lpVolumeName /* NULL if deleting label */ 00747 ) 00748 { 00749 PWCHAR RootPathNameW; 00750 PWCHAR VolumeNameW = NULL; 00751 BOOL Result; 00752 00753 if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) 00754 return FALSE; 00755 00756 if (lpVolumeName) 00757 { 00758 if (!(VolumeNameW = FilenameA2W(lpVolumeName, TRUE))) 00759 return FALSE; 00760 } 00761 00762 Result = SetVolumeLabelW (RootPathNameW, 00763 VolumeNameW); 00764 00765 if (VolumeNameW) 00766 { 00767 RtlFreeHeap (RtlGetProcessHeap (), 00768 0, 00769 VolumeNameW ); 00770 } 00771 00772 return Result; 00773 } 00774 00775 00776 /* 00777 * @implemented 00778 */ 00779 BOOL WINAPI 00780 SetVolumeLabelW( 00781 LPCWSTR lpRootPathName, 00782 LPCWSTR lpVolumeName /* NULL if deleting label */ 00783 ) 00784 { 00785 PFILE_FS_LABEL_INFORMATION LabelInfo; 00786 IO_STATUS_BLOCK IoStatusBlock; 00787 ULONG LabelLength; 00788 HANDLE hFile; 00789 NTSTATUS Status; 00790 00791 LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR); 00792 LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(), 00793 0, 00794 sizeof(FILE_FS_LABEL_INFORMATION) + 00795 LabelLength); 00796 if (LabelInfo == NULL) 00797 { 00798 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00799 return FALSE; 00800 } 00801 LabelInfo->VolumeLabelLength = LabelLength; 00802 memcpy(LabelInfo->VolumeLabel, 00803 lpVolumeName, 00804 LabelLength); 00805 00806 hFile = InternalOpenDirW(lpRootPathName, TRUE); 00807 if (INVALID_HANDLE_VALUE == hFile) 00808 { 00809 RtlFreeHeap(RtlGetProcessHeap(), 00810 0, 00811 LabelInfo); 00812 return FALSE; 00813 } 00814 00815 Status = NtSetVolumeInformationFile(hFile, 00816 &IoStatusBlock, 00817 LabelInfo, 00818 sizeof(FILE_FS_LABEL_INFORMATION) + 00819 LabelLength, 00820 FileFsLabelInformation); 00821 00822 RtlFreeHeap(RtlGetProcessHeap(), 00823 0, 00824 LabelInfo); 00825 00826 if (!NT_SUCCESS(Status)) 00827 { 00828 WARN("Status: %x\n", Status); 00829 CloseHandle(hFile); 00830 BaseSetLastNTError(Status); 00831 return FALSE; 00832 } 00833 00834 CloseHandle(hFile); 00835 return TRUE; 00836 } 00837 00857 BOOL WINAPI 00858 GetVolumeNameForVolumeMountPointW( 00859 IN LPCWSTR VolumeMountPoint, 00860 OUT LPWSTR VolumeName, 00861 IN DWORD VolumeNameLength) 00862 { 00863 UNICODE_STRING NtFileName; 00864 OBJECT_ATTRIBUTES ObjectAttributes; 00865 HANDLE FileHandle; 00866 IO_STATUS_BLOCK Iosb; 00867 ULONG BufferLength; 00868 PMOUNTDEV_NAME MountDevName; 00869 PMOUNTMGR_MOUNT_POINT MountPoint; 00870 ULONG MountPointSize; 00871 PMOUNTMGR_MOUNT_POINTS MountPoints; 00872 ULONG Index; 00873 PUCHAR SymbolicLinkName; 00874 BOOL Result; 00875 NTSTATUS Status; 00876 00877 if (!VolumeMountPoint || !VolumeMountPoint[0]) 00878 { 00879 SetLastError(ERROR_PATH_NOT_FOUND); 00880 return FALSE; 00881 } 00882 00883 /* 00884 * First step is to convert the passed volume mount point name to 00885 * an NT acceptable name. 00886 */ 00887 00888 if (!RtlDosPathNameToNtPathName_U(VolumeMountPoint, &NtFileName, NULL, NULL)) 00889 { 00890 SetLastError(ERROR_PATH_NOT_FOUND); 00891 return FALSE; 00892 } 00893 00894 if (NtFileName.Length > sizeof(WCHAR) && 00895 NtFileName.Buffer[(NtFileName.Length / sizeof(WCHAR)) - 1] == '\\') 00896 { 00897 NtFileName.Length -= sizeof(WCHAR); 00898 } 00899 00900 /* 00901 * Query mount point device name which we will later use for determining 00902 * the volume name. 00903 */ 00904 00905 InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL); 00906 Status = NtOpenFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, 00907 &ObjectAttributes, &Iosb, 00908 FILE_SHARE_READ | FILE_SHARE_WRITE, 00909 FILE_SYNCHRONOUS_IO_NONALERT); 00910 RtlFreeUnicodeString(&NtFileName); 00911 if (!NT_SUCCESS(Status)) 00912 { 00913 BaseSetLastNTError(Status); 00914 return FALSE; 00915 } 00916 00917 BufferLength = sizeof(MOUNTDEV_NAME) + 50 * sizeof(WCHAR); 00918 do 00919 { 00920 MountDevName = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength); 00921 if (MountDevName == NULL) 00922 { 00923 NtClose(FileHandle); 00924 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00925 return FALSE; 00926 } 00927 00928 Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, 00929 IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, 00930 NULL, 0, MountDevName, BufferLength); 00931 if (!NT_SUCCESS(Status)) 00932 { 00933 RtlFreeHeap(GetProcessHeap(), 0, MountDevName); 00934 if (Status == STATUS_BUFFER_OVERFLOW) 00935 { 00936 BufferLength = sizeof(MOUNTDEV_NAME) + MountDevName->NameLength; 00937 continue; 00938 } 00939 else 00940 { 00941 NtClose(FileHandle); 00942 BaseSetLastNTError(Status); 00943 return FALSE; 00944 } 00945 } 00946 } 00947 while (!NT_SUCCESS(Status)); 00948 00949 NtClose(FileHandle); 00950 00951 /* 00952 * Get the mount point information from mount manager. 00953 */ 00954 00955 MountPointSize = MountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT); 00956 MountPoint = RtlAllocateHeap(GetProcessHeap(), 0, MountPointSize); 00957 if (MountPoint == NULL) 00958 { 00959 RtlFreeHeap(GetProcessHeap(), 0, MountDevName); 00960 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00961 return FALSE; 00962 } 00963 RtlZeroMemory(MountPoint, sizeof(MOUNTMGR_MOUNT_POINT)); 00964 MountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT); 00965 MountPoint->DeviceNameLength = MountDevName->NameLength; 00966 RtlCopyMemory(MountPoint + 1, MountDevName->Name, MountDevName->NameLength); 00967 RtlFreeHeap(RtlGetProcessHeap(), 0, MountDevName); 00968 00969 RtlInitUnicodeString(&NtFileName, L"\\??\\MountPointManager"); 00970 InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL); 00971 Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, 00972 &Iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, 00973 FILE_SYNCHRONOUS_IO_NONALERT); 00974 if (!NT_SUCCESS(Status)) 00975 { 00976 BaseSetLastNTError(Status); 00977 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); 00978 return FALSE; 00979 } 00980 00981 BufferLength = sizeof(MOUNTMGR_MOUNT_POINTS); 00982 do 00983 { 00984 MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength); 00985 if (MountPoints == NULL) 00986 { 00987 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); 00988 NtClose(FileHandle); 00989 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00990 return FALSE; 00991 } 00992 00993 Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, 00994 IOCTL_MOUNTMGR_QUERY_POINTS, 00995 MountPoint, MountPointSize, 00996 MountPoints, BufferLength); 00997 if (!NT_SUCCESS(Status)) 00998 { 00999 if (Status == STATUS_BUFFER_OVERFLOW) 01000 { 01001 BufferLength = MountPoints->Size; 01002 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); 01003 continue; 01004 } 01005 else if (!NT_SUCCESS(Status)) 01006 { 01007 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); 01008 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); 01009 NtClose(FileHandle); 01010 BaseSetLastNTError(Status); 01011 return FALSE; 01012 } 01013 } 01014 } 01015 while (!NT_SUCCESS(Status)); 01016 01017 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); 01018 NtClose(FileHandle); 01019 01020 /* 01021 * Now we've gathered info about all mount points mapped to our device, so 01022 * select the correct one and copy it into the output buffer. 01023 */ 01024 01025 for (Index = 0; Index < MountPoints->NumberOfMountPoints; Index++) 01026 { 01027 MountPoint = MountPoints->MountPoints + Index; 01028 SymbolicLinkName = (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset; 01029 01030 /* 01031 * Check for "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\" 01032 * (with the last slash being optional) style symbolic links. 01033 */ 01034 01035 if (MountPoint->SymbolicLinkNameLength == 48 * sizeof(WCHAR) || 01036 (MountPoint->SymbolicLinkNameLength == 49 * sizeof(WCHAR) && 01037 SymbolicLinkName[48] == L'\\')) 01038 { 01039 if (RtlCompareMemory(SymbolicLinkName, L"\\??\\Volume{", 01040 11 * sizeof(WCHAR)) == 11 * sizeof(WCHAR) && 01041 SymbolicLinkName[19] == L'-' && SymbolicLinkName[24] == L'-' && 01042 SymbolicLinkName[29] == L'-' && SymbolicLinkName[34] == L'-' && 01043 SymbolicLinkName[47] == L'}') 01044 { 01045 if (VolumeNameLength >= MountPoint->SymbolicLinkNameLength / sizeof(WCHAR)) 01046 { 01047 RtlCopyMemory(VolumeName, 01048 (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset, 01049 MountPoint->SymbolicLinkNameLength); 01050 VolumeName[1] = L'\\'; 01051 Result = TRUE; 01052 } 01053 else 01054 { 01055 SetLastError(ERROR_FILENAME_EXCED_RANGE); 01056 Result = FALSE; 01057 } 01058 01059 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); 01060 01061 return Result; 01062 } 01063 } 01064 } 01065 01066 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); 01067 SetLastError(ERROR_INVALID_PARAMETER); 01068 01069 return FALSE; 01070 } 01071 01072 /* 01073 * @implemented (Wine 13 sep 2008) 01074 */ 01075 BOOL 01076 WINAPI 01077 GetVolumeNameForVolumeMountPointA( 01078 LPCSTR lpszVolumeMountPoint, 01079 LPSTR lpszVolumeName, 01080 DWORD cchBufferLength 01081 ) 01082 { 01083 BOOL ret; 01084 WCHAR volumeW[50], *pathW = NULL; 01085 DWORD len = min( sizeof(volumeW) / sizeof(WCHAR), cchBufferLength ); 01086 01087 TRACE("(%s, %p, %x)\n", debugstr_a(lpszVolumeMountPoint), lpszVolumeName, cchBufferLength); 01088 01089 if (!lpszVolumeMountPoint || !(pathW = FilenameA2W( lpszVolumeMountPoint, TRUE ))) 01090 return FALSE; 01091 01092 if ((ret = GetVolumeNameForVolumeMountPointW( pathW, volumeW, len ))) 01093 FilenameW2A_N( lpszVolumeName, len, volumeW, -1 ); 01094 01095 RtlFreeHeap( RtlGetProcessHeap(), 0, pathW ); 01096 return ret; 01097 } 01098 01099 /* 01100 * @implemented (Wine 13 sep 2008) 01101 */ 01102 HANDLE 01103 WINAPI 01104 FindFirstVolumeW( 01105 LPWSTR volume, 01106 DWORD len 01107 ) 01108 { 01109 DWORD size = 1024; 01110 HANDLE mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, 01111 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE ); 01112 if (mgr == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; 01113 01114 for (;;) 01115 { 01116 MOUNTMGR_MOUNT_POINT input; 01117 MOUNTMGR_MOUNT_POINTS *output; 01118 01119 if (!(output = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) 01120 { 01121 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 01122 break; 01123 } 01124 memset( &input, 0, sizeof(input) ); 01125 01126 if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_POINTS, &input, sizeof(input), 01127 output, size, NULL, NULL )) 01128 { 01129 if (GetLastError() != ERROR_MORE_DATA) break; 01130 size = output->Size; 01131 RtlFreeHeap( RtlGetProcessHeap(), 0, output ); 01132 continue; 01133 } 01134 CloseHandle( mgr ); 01135 /* abuse the Size field to store the current index */ 01136 output->Size = 0; 01137 if (!FindNextVolumeW( output, volume, len )) 01138 { 01139 RtlFreeHeap( RtlGetProcessHeap(), 0, output ); 01140 return INVALID_HANDLE_VALUE; 01141 } 01142 return (HANDLE)output; 01143 } 01144 CloseHandle( mgr ); 01145 return INVALID_HANDLE_VALUE; 01146 } 01147 01148 /* 01149 * @implemented (Wine 13 sep 2008) 01150 */ 01151 HANDLE 01152 WINAPI 01153 FindFirstVolumeA( 01154 LPSTR volume, 01155 DWORD len 01156 ) 01157 { 01158 WCHAR *buffer = NULL; 01159 HANDLE handle; 01160 01161 buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, len * sizeof(WCHAR) ); 01162 01163 if (!buffer) 01164 { 01165 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01166 return INVALID_HANDLE_VALUE; 01167 } 01168 01169 handle = FindFirstVolumeW( buffer, len ); 01170 01171 if (handle != INVALID_HANDLE_VALUE) 01172 { 01173 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) 01174 { 01175 FindVolumeClose( handle ); 01176 handle = INVALID_HANDLE_VALUE; 01177 } 01178 } 01179 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); 01180 return handle; 01181 } 01182 01183 /* 01184 * @implemented (Wine 13 sep 2008) 01185 */ 01186 BOOL 01187 WINAPI 01188 FindVolumeClose( 01189 HANDLE hFindVolume 01190 ) 01191 { 01192 return RtlFreeHeap(RtlGetProcessHeap(), 0, hFindVolume); 01193 } 01194 01195 /* 01196 * @implemented 01197 */ 01198 BOOL 01199 WINAPI 01200 GetVolumePathNameA(LPCSTR lpszFileName, 01201 LPSTR lpszVolumePathName, 01202 DWORD cchBufferLength) 01203 { 01204 PWCHAR FileNameW = NULL; 01205 WCHAR VolumePathName[MAX_PATH]; 01206 BOOL Result; 01207 01208 if (lpszFileName) 01209 { 01210 if (!(FileNameW = FilenameA2W(lpszFileName, FALSE))) 01211 return FALSE; 01212 } 01213 01214 Result = GetVolumePathNameW(FileNameW, VolumePathName, cchBufferLength); 01215 01216 if (Result) 01217 FilenameW2A_N(lpszVolumePathName, MAX_PATH, VolumePathName, -1); 01218 01219 return Result; 01220 } 01221 01222 /* 01223 * @implemented 01224 */ 01225 BOOL 01226 WINAPI 01227 GetVolumePathNameW(LPCWSTR lpszFileName, 01228 LPWSTR lpszVolumePathName, 01229 DWORD cchBufferLength) 01230 { 01231 DWORD PathLength; 01232 UNICODE_STRING UnicodeFilePath; 01233 LPWSTR FilePart; 01234 PWSTR FullFilePath, FilePathName; 01235 ULONG PathSize; 01236 WCHAR VolumeName[MAX_PATH]; 01237 DWORD ErrorCode; 01238 BOOL Result = FALSE; 01239 01240 if (!(PathLength = GetFullPathNameW(lpszFileName, 0, NULL, NULL))) 01241 { 01242 return Result; 01243 } 01244 else 01245 { 01246 PathLength = PathLength + 10; 01247 PathSize = PathLength * sizeof(WCHAR); 01248 01249 if (!(FullFilePath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize))) 01250 { 01251 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01252 return Result; 01253 } 01254 01255 if (!GetFullPathNameW(lpszFileName, PathLength, FullFilePath, &FilePart)) 01256 { 01257 RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath); 01258 return Result; 01259 } 01260 01261 RtlInitUnicodeString(&UnicodeFilePath, FullFilePath); 01262 01263 if (UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] != '\\') 01264 { 01265 UnicodeFilePath.Length += sizeof(WCHAR); 01266 UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] = '\\'; 01267 UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; 01268 } 01269 01270 if (!(FilePathName = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize))) 01271 { 01272 RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath); 01273 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01274 return Result; 01275 } 01276 01277 while (!GetVolumeNameForVolumeMountPointW(UnicodeFilePath.Buffer, 01278 VolumeName, 01279 MAX_PATH)) 01280 { 01281 if (((UnicodeFilePath.Length == 4) && (UnicodeFilePath.Buffer[0] == '\\') && 01282 (UnicodeFilePath.Buffer[1] == '\\')) || ((UnicodeFilePath.Length == 6) && 01283 (UnicodeFilePath.Buffer[1] == ':'))) 01284 { 01285 break; 01286 } 01287 01288 UnicodeFilePath.Length -= sizeof(WCHAR); 01289 UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; 01290 01291 memcpy(FilePathName, UnicodeFilePath.Buffer, UnicodeFilePath.Length); 01292 FilePathName[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; 01293 01294 if (!GetFullPathNameW(FilePathName, PathLength, FullFilePath, &FilePart)) 01295 { 01296 goto Cleanup2; 01297 } 01298 01299 if (!FilePart) 01300 { 01301 RtlInitUnicodeString(&UnicodeFilePath, FullFilePath); 01302 UnicodeFilePath.Length += sizeof(WCHAR); 01303 UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] = '\\'; 01304 UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; 01305 break; 01306 } 01307 01308 FilePart[0] = '\0'; 01309 RtlInitUnicodeString(&UnicodeFilePath, FullFilePath); 01310 } 01311 } 01312 01313 if (UnicodeFilePath.Length > (cchBufferLength * sizeof(WCHAR)) - sizeof(WCHAR)) 01314 { 01315 ErrorCode = ERROR_FILENAME_EXCED_RANGE; 01316 goto Cleanup1; 01317 } 01318 01319 memcpy(lpszVolumePathName, UnicodeFilePath.Buffer, UnicodeFilePath.Length); 01320 lpszVolumePathName[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; 01321 01322 Result = TRUE; 01323 goto Cleanup2; 01324 01325 Cleanup1: 01326 SetLastError(ErrorCode); 01327 Cleanup2: 01328 RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath); 01329 RtlFreeHeap(RtlGetProcessHeap(), 0, FilePathName); 01330 return Result; 01331 } 01332 01333 01334 /* 01335 * @unimplemented 01336 */ 01337 BOOL 01338 WINAPI 01339 SetVolumeMountPointW( 01340 LPCWSTR lpszVolumeMountPoint, 01341 LPCWSTR lpszVolumeName 01342 ) 01343 { 01344 STUB; 01345 return 0; 01346 } 01347 01348 /* 01349 * @unimplemented 01350 */ 01351 BOOL 01352 WINAPI 01353 DeleteVolumeMountPointA( 01354 LPCSTR lpszVolumeMountPoint 01355 ) 01356 { 01357 STUB; 01358 return 0; 01359 } 01360 01361 /* 01362 * @unimplemented 01363 */ 01364 HANDLE 01365 WINAPI 01366 FindFirstVolumeMountPointA( 01367 LPCSTR lpszRootPathName, 01368 LPSTR lpszVolumeMountPoint, 01369 DWORD cchBufferLength 01370 ) 01371 { 01372 STUB; 01373 return 0; 01374 } 01375 01376 /* 01377 * @implemented 01378 */ 01379 BOOL 01380 WINAPI 01381 FindNextVolumeA(HANDLE handle, 01382 LPSTR volume, 01383 DWORD len) 01384 { 01385 WCHAR *buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, len * sizeof(WCHAR)); 01386 BOOL ret; 01387 01388 if (!buffer) 01389 { 01390 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01391 return FALSE; 01392 } 01393 01394 if ((ret = FindNextVolumeW( handle, buffer, len ))) 01395 { 01396 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE; 01397 } 01398 01399 HeapFree( GetProcessHeap(), 0, buffer ); 01400 return ret; 01401 } 01402 01403 /* 01404 * @unimplemented 01405 */ 01406 BOOL 01407 WINAPI 01408 FindNextVolumeMountPointA( 01409 HANDLE hFindVolumeMountPoint, 01410 LPSTR lpszVolumeMountPoint, 01411 DWORD cchBufferLength 01412 ) 01413 { 01414 STUB; 01415 return 0; 01416 } 01417 01418 /* 01419 * @unimplemented 01420 */ 01421 BOOL 01422 WINAPI 01423 GetVolumePathNamesForVolumeNameA( 01424 LPCSTR lpszVolumeName, 01425 LPSTR lpszVolumePathNames, 01426 DWORD cchBufferLength, 01427 PDWORD lpcchReturnLength 01428 ) 01429 { 01430 STUB; 01431 return 0; 01432 } 01433 01434 /* 01435 * @unimplemented 01436 */ 01437 BOOL 01438 WINAPI 01439 SetVolumeMountPointA( 01440 LPCSTR lpszVolumeMountPoint, 01441 LPCSTR lpszVolumeName 01442 ) 01443 { 01444 STUB; 01445 return 0; 01446 } 01447 01448 /* 01449 * @unimplemented 01450 */ 01451 BOOL 01452 WINAPI 01453 FindVolumeMountPointClose( 01454 HANDLE hFindVolumeMountPoint 01455 ) 01456 { 01457 STUB; 01458 return 0; 01459 } 01460 01461 /* 01462 * @unimplemented 01463 */ 01464 BOOL 01465 WINAPI 01466 DeleteVolumeMountPointW( 01467 LPCWSTR lpszVolumeMountPoint 01468 ) 01469 { 01470 STUB; 01471 return 0; 01472 } 01473 01474 /* 01475 * @unimplemented 01476 */ 01477 HANDLE 01478 WINAPI 01479 FindFirstVolumeMountPointW( 01480 LPCWSTR lpszRootPathName, 01481 LPWSTR lpszVolumeMountPoint, 01482 DWORD cchBufferLength 01483 ) 01484 { 01485 STUB; 01486 return 0; 01487 } 01488 01489 /* 01490 * @implemented 01491 */ 01492 BOOL 01493 WINAPI 01494 FindNextVolumeW( 01495 HANDLE handle, 01496 LPWSTR volume, 01497 DWORD len 01498 ) 01499 { 01500 MOUNTMGR_MOUNT_POINTS *data = handle; 01501 01502 while (data->Size < data->NumberOfMountPoints) 01503 { 01504 static const WCHAR volumeW[] = {'\\','?','?','\\','V','o','l','u','m','e','{',}; 01505 WCHAR *link = (WCHAR *)((char *)data + data->MountPoints[data->Size].SymbolicLinkNameOffset); 01506 DWORD size = data->MountPoints[data->Size].SymbolicLinkNameLength; 01507 data->Size++; 01508 /* skip non-volumes */ 01509 if (size < sizeof(volumeW) || memcmp( link, volumeW, sizeof(volumeW) )) continue; 01510 if (size + sizeof(WCHAR) >= len * sizeof(WCHAR)) 01511 { 01512 SetLastError( ERROR_FILENAME_EXCED_RANGE ); 01513 return FALSE; 01514 } 01515 memcpy( volume, link, size ); 01516 volume[1] = '\\'; /* map \??\ to \\?\ */ 01517 volume[size / sizeof(WCHAR)] = '\\'; /* Windows appends a backslash */ 01518 volume[size / sizeof(WCHAR) + 1] = 0; 01519 DPRINT( "returning entry %u %s\n", data->Size - 1, volume ); 01520 return TRUE; 01521 } 01522 SetLastError( ERROR_NO_MORE_FILES ); 01523 return FALSE; 01524 } 01525 01526 /* 01527 * @unimplemented 01528 */ 01529 BOOL 01530 WINAPI 01531 FindNextVolumeMountPointW( 01532 HANDLE hFindVolumeMountPoint, 01533 LPWSTR lpszVolumeMountPoint, 01534 DWORD cchBufferLength 01535 ) 01536 { 01537 STUB; 01538 return 0; 01539 } 01540 01541 /* 01542 * @unimplemented 01543 */ 01544 BOOL 01545 WINAPI 01546 GetVolumePathNamesForVolumeNameW( 01547 LPCWSTR lpszVolumeName, 01548 LPWSTR lpszVolumePathNames, 01549 DWORD cchBufferLength, 01550 PDWORD lpcchReturnLength 01551 ) 01552 { 01553 STUB; 01554 return 0; 01555 } 01556 01557 01558 /* EOF */ Generated on Sat May 26 2012 04:18:07 for ReactOS by
1.7.6.1
|