summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/Windows/FileSystem.cpp
blob: 3ebfb7523f78d3d76b98fb64d6a1a2f5b13b13b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Windows/FileSystem.cpp

#include "StdAfx.h"

#include "FileSystem.h"
#include "Defs.h"

#ifndef _UNICODE
extern bool g_IsNT;
#endif

namespace NWindows {
namespace NFile {
namespace NSystem {

bool MyGetVolumeInformation(
    LPCTSTR rootPathName,
    CSysString &volumeName,
    LPDWORD volumeSerialNumber,
    LPDWORD maximumComponentLength,
    LPDWORD fileSystemFlags,
    CSysString &fileSystemName)
{
  bool result = BOOLToBool(GetVolumeInformation(
      rootPathName,
      volumeName.GetBuffer(MAX_PATH), MAX_PATH,
      volumeSerialNumber,
      maximumComponentLength,
      fileSystemFlags,
      fileSystemName.GetBuffer(MAX_PATH), MAX_PATH));
  volumeName.ReleaseBuffer();
  fileSystemName.ReleaseBuffer();
  return result;
}


#ifndef _UNICODE
bool MyGetVolumeInformation(
    LPCWSTR rootPathName,
    UString &volumeName,
    LPDWORD volumeSerialNumber,
    LPDWORD maximumComponentLength,
    LPDWORD fileSystemFlags,
    UString &fileSystemName)
{
  if (g_IsNT)
  {
    bool result = BOOLToBool(GetVolumeInformationW(
      rootPathName,
      volumeName.GetBuffer(MAX_PATH), MAX_PATH,
      volumeSerialNumber,
      maximumComponentLength,
      fileSystemFlags,
      fileSystemName.GetBuffer(MAX_PATH), MAX_PATH));
    volumeName.ReleaseBuffer();
    fileSystemName.ReleaseBuffer();
    return result;
  }
  AString volumeNameA, fileSystemNameA;
  bool result = MyGetVolumeInformation(GetSystemString(rootPathName), volumeNameA,
      volumeSerialNumber, maximumComponentLength, fileSystemFlags,fileSystemNameA);
  if (result)
  {
    volumeName = GetUnicodeString(volumeNameA);
    fileSystemName = GetUnicodeString(fileSystemNameA);
  }
  return result;
}
#endif

typedef BOOL (WINAPI * GetDiskFreeSpaceExPointer)(
  LPCTSTR lpDirectoryName,                 // directory name
  PULARGE_INTEGER lpFreeBytesAvailable,    // bytes available to caller
  PULARGE_INTEGER lpTotalNumberOfBytes,    // bytes on disk
  PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk
);

bool MyGetDiskFreeSpace(LPCTSTR rootPathName,
    UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize)
{
  GetDiskFreeSpaceExPointer pGetDiskFreeSpaceEx =
      (GetDiskFreeSpaceExPointer)GetProcAddress(
      GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA");

  bool sizeIsDetected = false;
  if (pGetDiskFreeSpaceEx)
  {
    ULARGE_INTEGER i64FreeBytesToCaller, totalSize2, freeSize2;
    sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(rootPathName,
                &i64FreeBytesToCaller,
                &totalSize2,
                &freeSize2));
    totalSize = totalSize2.QuadPart;
    freeSize = freeSize2.QuadPart;
  }

  DWORD numSectorsPerCluster;
  DWORD bytesPerSector;
  DWORD numberOfFreeClusters;
  DWORD totalNumberOfClusters;

  if (!::GetDiskFreeSpace(rootPathName,
      &numSectorsPerCluster,
      &bytesPerSector,
      &numberOfFreeClusters,
      &totalNumberOfClusters))
    return false;

  clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster;
  if (!sizeIsDetected)
  {
    totalSize =  clusterSize * (UInt64)totalNumberOfClusters;
    freeSize =  clusterSize * (UInt64)numberOfFreeClusters;
  }
  return true;
}

#ifndef _UNICODE
bool MyGetDiskFreeSpace(LPCWSTR rootPathName,
    UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize)
{
  return MyGetDiskFreeSpace(GetSystemString(rootPathName), clusterSize, totalSize, freeSize);
}
#endif

}}}