ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

volume.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.