mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-04 01:42:58 -05:00
Compare commits
149 Commits
v1.11RC1
...
pvt-idinfo
Author | SHA1 | Date | |
---|---|---|---|
82f84f5bf7 | |||
97c075e744 | |||
874a223bcc | |||
901a98e118 | |||
0ab4300738 | |||
52e6aa97b5 | |||
a7d82d5f8d | |||
3aadaee511 | |||
da3a8aa229 | |||
1f0fd4c280 | |||
6da92f0b54 | |||
4f5f1dd350 | |||
ba5d52e9a5 | |||
d626fb9563 | |||
69cc1820e1 | |||
c06141c8c8 | |||
760c2acded | |||
671efe625a | |||
a59b32b1ee | |||
22d81846df | |||
8c9b8362b4 | |||
e92eb023fe | |||
e550e261f0 | |||
46054c03fe | |||
db07b24342 | |||
cb81e81985 | |||
b62e1e920b | |||
c61679a35d | |||
619e41a18e | |||
80fa156e7b | |||
01d9fa1719 | |||
6846508631 | |||
0488451c3d | |||
7c3292af81 | |||
3d2ba637e5 | |||
db72b57ca4 | |||
020157a9ae | |||
d99cb2d7d1 | |||
298261c4af | |||
3c674a556d | |||
f85fb49f49 | |||
92084a56c6 | |||
53f97c9841 | |||
2770eca1bf | |||
2945971ba9 | |||
0a39ef60bd | |||
e1faf1351e | |||
7333451eac | |||
c178db127c | |||
9747af22e8 | |||
e1b2e77df0 | |||
ef9b7e22c6 | |||
4783902d1d | |||
fd27c470b0 | |||
4cd2b8c612 | |||
dacaff41e4 | |||
c187209159 | |||
a2e92207c5 | |||
be27a82879 | |||
4f5ad93f00 | |||
b9ca46694e | |||
b47c42877a | |||
e50d7adc50 | |||
d1fc5e5d0f | |||
7f73192f8d | |||
c4ecd15c0a | |||
d71049225e | |||
91d7f3b673 | |||
63e23c2039 | |||
4d1594b1cf | |||
0eb6912296 | |||
c237a55951 | |||
c15006cce8 | |||
53b44dcb5c | |||
a3765d6360 | |||
98d68c4007 | |||
6c6dd8abcc | |||
16dd729fc7 | |||
e8cec5dfc1 | |||
a2d49a1ded | |||
9ede097e73 | |||
2c3800077f | |||
84b3f98d38 | |||
16734bf37a | |||
ea189c5b68 | |||
7735506cc7 | |||
ca3170c293 | |||
9a27a3225b | |||
d44cb54bd5 | |||
ba13995d10 | |||
d1f863e9ac | |||
ccdbc9daf9 | |||
1723179430 | |||
8e0f5b457c | |||
2fc2c237d3 | |||
b99fb9a5cb | |||
538fee8e54 | |||
925fa4b6e4 | |||
b179c7a933 | |||
b25e116f08 | |||
422c369b15 | |||
d450683e2e | |||
ad1aa156dc | |||
aa012db099 | |||
b08f60bfbd | |||
a9b3cef253 | |||
b43d1f5502 | |||
de9112f6e6 | |||
329b14d838 | |||
7009324e7f | |||
f4ae097722 | |||
50be07e8ac | |||
2dd054087c | |||
7f6608cf7d | |||
39e9d8156b | |||
90acd19014 | |||
9154ec784d | |||
0b3ce52958 | |||
deee7edded | |||
f41f410546 | |||
a2dc40fe3a | |||
adeed2b79d | |||
5dda5903a8 | |||
a7bc306b2d | |||
7e59c2e5a6 | |||
637e8bb8c2 | |||
9670caa3fe | |||
005d3e4fb0 | |||
62a6bbab66 | |||
40ba537dc2 | |||
ec832b45ff | |||
fc03b485f3 | |||
651e45c3ba | |||
95c2fadce0 | |||
b4453c89cc | |||
5483dcbd73 | |||
f1cfe758ec | |||
e9143a73a6 | |||
264450f627 | |||
a731f0e5d8 | |||
d7450d740e | |||
5251dcbce9 | |||
dd3adf34ef | |||
b8a6a8efed | |||
d67acf3b3a | |||
3b104723af | |||
699278a7ed | |||
e070cdd6be | |||
fbbca110fb |
8
.github/workflows/avm.yml
vendored
8
.github/workflows/avm.yml
vendored
@ -11,8 +11,8 @@ jobs:
|
|||||||
- uses: billziss-gh/avm@v1
|
- uses: billziss-gh/avm@v1
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.6/winfsp-1.6.20027.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.7/winfsp-1.7.20172.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.8/winfsp-1.8.20304.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.9/winfsp-1.9.21096.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi
|
https://github.com/winfsp/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v1.11/winfsp-1.11.22176.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v1.12/winfsp-1.12.22301.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v1.12.22339/winfsp-1.12.22339.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v2.0B2/winfsp-2.0.23033.msi
|
||||||
|
146
Changelog.md
146
Changelog.md
@ -1,6 +1,152 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
|
||||||
|
## v2.0B2 (2023 Beta2)
|
||||||
|
|
||||||
|
This release is a major version change for WinFsp (from 1.x to 2.x). There are no backwards incompatible API changes in this release, but nevertheless enough things change that warrant a version change.
|
||||||
|
|
||||||
|
The major new feature of this release is that it allows uninstallation and reinstallation of WinFsp **without reboot**. Going forward installers named `winfsp-2.x.y.msi` can be uninstalled and reinstalled without reboot. Furthermore a later version `winfsp-2.x.y.msi` installer can be used to upgrade over an earlier version `winfsp-2.x.y.msi` installer. However note that a `winfsp-2.x.y.msi` installer cannot be used to upgrade over a "legacy" `winfsp-1.x.y.msi` installer; you will still need to uninstall the "old" `winfsp-1.x.y.msi` installer, potentially reboot and then install the "new" `winfsp-2.x.y.msi` installer.
|
||||||
|
|
||||||
|
Changes visible to file system developers are listed below:
|
||||||
|
|
||||||
|
- WinFsp executable files are now installed by default in the directory `C:\Program Files (x86)\WinFsp\SxS\sxs.<InstanceID>\bin`. The previous directory `C:\Program Files (x86)\WinFsp\bin` is now a junction that points to the above directory.
|
||||||
|
|
||||||
|
- The WinFsp driver name is no longer `winfsp`, but rather a name such as `winfsp+<InstanceID>`. This means that managing the driver using the `sc.exe` utility is no longer as easy.
|
||||||
|
|
||||||
|
- The `fsptool` utility has been updated with new commands `lsdrv`, `load`, `unload` and `ver`. The `lsdrv`, `load` and `unload` commands can be used to manage the driver from the command line. This is rarely necessary, but may be useful for troubleshooting purposes.
|
||||||
|
|
||||||
|
- Prior to this release the WinFsp driver would never unmount a file system volume unless the user mode file system requested the unmount. From this release onward it is possible for the WinFsp driver to unmount a file system volume, without a user mode file system request. This is to allow for the driver to be unloaded.
|
||||||
|
|
||||||
|
A new operation `DispatcherStopped` has been added to `FSP_FILE_SYSTEM_INTERFACE`, which is sent after the file system volume has been unmounted and the file system dispatcher has been stopped. This can happen because of a user mode file system request via `FspFileSystemStopDispatcher` or because of driver unload. The `DispatcherStopped` operation includes a `Normally` parameter, which is `TRUE` for normal file system shutdown via `FspFileSystemStopDispatcher` and `FALSE` otherwise.
|
||||||
|
|
||||||
|
Native file systems that use the `FspService` infrastructure can use the `FspFileSystemStopServiceIfNecessary` API to handle the `DispatcherStopped` operation (see the MEMFS and NTPTFS samples). FUSE file systems get this functionality for free. .NET file systems that use the `Service` class infrastructure also get this functionality for free.
|
||||||
|
|
||||||
|
- WinFsp now offers a .NET library that targets .NET Framework 3.5 (as before) and one that targets .NET Standard 2.0. This is due to work by @Noire001 in PR #451.
|
||||||
|
|
||||||
|
- FUSE now supports path components up to 255 characters long (previously it was 255 bytes). This is due to work by @zeho11 in PR #474.
|
||||||
|
|
||||||
|
- The FUSE passthrough file systems have been updated to support long paths. This is also due to work by @zeho11.
|
||||||
|
|
||||||
|
- The WinFsp symbols directory has been removed. If you are looking for WinFsp symbols you can find them at https://github.com/winfsp/winfsp.sym
|
||||||
|
|
||||||
|
|
||||||
|
## v2.0B1 (2023 Beta1)
|
||||||
|
|
||||||
|
This release is a major version change for WinFsp (from 1.x to 2.x). There are no backwards incompatible API changes in this release, but nevertheless enough things change that warrant a version change.
|
||||||
|
|
||||||
|
The major new feature of this release is that it allows uninstallation and reinstallation of WinFsp **without reboot**. Going forward installers named `winfsp-2.x.y.msi` can be uninstalled and reinstalled without reboot. Furthermore a later version `winfsp-2.x.y.msi` installer can be used to upgrade over an earlier version `winfsp-2.x.y.msi` installer. However note that a `winfsp-2.x.y.msi` installer cannot be used to upgrade over a "legacy" `winfsp-1.x.y.msi` installer; you will still need to uninstall the "old" `winfsp-1.x.y.msi` installer, potentially reboot and then install the "new" `winfsp-2.x.y.msi` installer.
|
||||||
|
|
||||||
|
Some changes that may be visible to file system developers are listed below:
|
||||||
|
|
||||||
|
- WinFsp executable files are now installed by default in the directory `C:\Program Files (x86)\WinFsp\SxS\sxs.<InstanceID>\bin`. The previous directory `C:\Program Files (x86)\WinFsp\bin` is now a junction that points to the above directory.
|
||||||
|
|
||||||
|
- The WinFsp driver name is no longer `winfsp`, but rather a name such as `winfsp+<InstanceID>`. This means that managing the driver using the `sc.exe` utility is no longer as easy.
|
||||||
|
|
||||||
|
- The `fsptool` utility has been updated with new commands `lsdrv`, `load`, `unload` and `ver`. The `lsdrv`, `load` and `unload` commands can be used to manage the driver from the command line. This is rarely necessary, but may be useful for troubleshooting purposes.
|
||||||
|
|
||||||
|
- The WinFsp symbols directory has been removed. If you are looking for WinFsp symbols you can find them at https://github.com/winfsp/winfsp.sym
|
||||||
|
|
||||||
|
|
||||||
|
## v1.12.22339 (2022.2 Update1)
|
||||||
|
|
||||||
|
*Note: This release (`v1.12.22339`) is the same as the previous release (`v1.12`) except that: (1) the kernel-mode drivers are now digitally signed only with the Microsoft Attestation signature, and that: (2) no release assets are digitally signed with SHA-1. (This change was necessary to fix a problem in older versions of Windows such as Windows 7.)*
|
||||||
|
|
||||||
|
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||||
|
|
||||||
|
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||||
|
|
||||||
|
- [FIX] A problem with Windows containers has been fixed. (GitHub issue #438.)
|
||||||
|
|
||||||
|
- [FIX] File systems can now be mounted as directories on ARM64. (GitHub issue #448.)
|
||||||
|
|
||||||
|
- [FIX] The passthrough file system now reports correct `IndexNumber`. (GitHub issue #325.)
|
||||||
|
|
||||||
|
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||||
|
|
||||||
|
|
||||||
|
## v1.12 (2022.2)
|
||||||
|
|
||||||
|
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||||
|
|
||||||
|
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||||
|
|
||||||
|
- [FIX] A problem with Windows containers has been fixed. (GitHub issue #438.)
|
||||||
|
|
||||||
|
- [FIX] File systems can now be mounted as directories on ARM64. (GitHub issue #448.)
|
||||||
|
|
||||||
|
- [FIX] The passthrough file system now reports correct `IndexNumber`. (GitHub issue #325.)
|
||||||
|
|
||||||
|
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||||
|
|
||||||
|
|
||||||
|
## v1.12B2 (2022.2 Beta2)
|
||||||
|
|
||||||
|
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||||
|
|
||||||
|
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||||
|
|
||||||
|
- [FIX] A problem with Windows containers has been fixed. (GitHub issue #438.)
|
||||||
|
|
||||||
|
- [FIX] File systems can now be mounted as directories on ARM64. (GitHub issue #448.)
|
||||||
|
|
||||||
|
- [FIX] The passthrough file system now reports correct `IndexNumber`. (GitHub issue #325.)
|
||||||
|
|
||||||
|
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||||
|
|
||||||
|
|
||||||
|
## v1.12B1 (2022.2 Beta1)
|
||||||
|
|
||||||
|
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||||
|
|
||||||
|
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||||
|
|
||||||
|
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||||
|
|
||||||
|
|
||||||
|
## v1.11 (2022+ARM64)
|
||||||
|
|
||||||
|
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||||
|
|
||||||
|
- [NEW] A new file system operation has been added to the FUSE API:
|
||||||
|
|
||||||
|
```C
|
||||||
|
int (*getpath)(const char *path, char *buf, size_t size,
|
||||||
|
struct fuse_file_info *fi);
|
||||||
|
```
|
||||||
|
|
||||||
|
The `getpath` operation allows a case-insensitive file system to report the correct case of a file path. For example, `getpath` can be used to report that the actual path of a file opened as `/PATH/TO/FILE` is really `/Path/To/File`. This capability is important for some Windows file system scenarios and can sometimes result in a performance improvement.
|
||||||
|
|
||||||
|
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
|
||||||
|
|
||||||
|
- [NEW] Many performance improvements:
|
||||||
|
|
||||||
|
- A new `PostDispositionForDirOnly` setting has been added to `FSP_FSCTL_VOLUME_PARAMS`. This allows a file system to declare that it does not want to see `SetInformation/Disposition` requests for files (such requests will still be sent for directories, because a file system is supposed to check if a directory is empty before deletion). This makes file (not directory) deletion faster. This optimization should be safe to enable for most file systems. FUSE file systems get this optimization for free.
|
||||||
|
|
||||||
|
- The FSD now implements "fast I/O" reads and writes. Fast I/O is a technique for doing I/O without using IRP's (I/O Request Packets) and can only work for file systems using the cache manager (`FileInfoTimeout==-1`). This results in significant improvement in read/write scenarios.
|
||||||
|
|
||||||
|
- The FSD now implements "fast I/O" for "transact" messages. Transact messages are used in the communication protocol between the kernel-mode FSD and the user-mode file system. Fast I/O speeds this communication protocol by as much as 10% in some scenarios. (Fast I/O for transact messages is enabled only when using the new `FSP_IOCTL_TRANSACT` control code, but does not require any other special configuration to be enabled.)
|
||||||
|
|
||||||
|
- The FSD per directory cache limit has been increased from 16K to 64K. This should allow for more directory data to be maintained in kernel and reduce round-trips to the user mode file system.
|
||||||
|
|
||||||
|
- The user mode directory buffering mechanism (`FspFileSystemAcquireDirectoryBuffer`) has been improved. The mechanism uses the quick-sort algorithm internally which can exhibit bad performance when sorting already sorted data. The quick-sort algorithm has been improved with the use use of median of three partitioning, which alleviates this problem.
|
||||||
|
|
||||||
|
- [NEW] A new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `MountBroadcastDriveChange` has been introduced, which if set to 1 will broadcast an additional "drive change" message to all top-level windows (including Explorer) during mounting and unmounting.
|
||||||
|
|
||||||
|
- Normally the Windows infrastructure broadcasts a `WM_DEVICECHANGE` message whenever a drive gets added/removed. In some rare systems it is possible for this message to get lost or stalled. The workaround for these rare systems is to enable this registry setting, in which case WinFsp will broadcast the `WM_DEVICECHANGE` using a slightly different but more reliable method than the one Windows uses.
|
||||||
|
|
||||||
|
- For more details see source code comments at [`FspMountBroadcastDriveChange`](https://github.com/winfsp/winfsp/blob/v1.11B3/src/dll/mount.c#L390-L406).
|
||||||
|
|
||||||
|
- [FIX] The WinFsp Network Provider now implements `NPGetUniversalName`. This fixes problems with some apps (e.g. Photos app).
|
||||||
|
|
||||||
|
- [FIX] WinFsp-FUSE now supports Azure AD accounts when specifying the `-o uid=-1` option. In addition a new option `-o uidmap=UID:SID` allows the specification of arbitrary UID<->SID or UID<->UserName mappings.
|
||||||
|
|
||||||
|
- [FIX] All executables (`*.exe,*.dll,*.sys`) in the WinFsp installation `bin` folder are now signed.
|
||||||
|
|
||||||
|
- [FIX] The default value for the registry setting `DistinctPermsForSameOwnerGroup` has been changed from 0 to 1.
|
||||||
|
|
||||||
|
- [BUILD] Product configuration (`MyProductName`, etc.) is done by the file `build.version.props` located in `build\VStudio`. This file was previously named `version.properties`.
|
||||||
|
|
||||||
|
|
||||||
## v1.11RC1 (2022+ARM64 RC1)
|
## v1.11RC1 (2022+ARM64 RC1)
|
||||||
|
|
||||||
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||||
|
@ -58,6 +58,7 @@ CONTRIBUTOR LIST
|
|||||||
|Ben Rubson |ben.rubson at gmail.com
|
|Ben Rubson |ben.rubson at gmail.com
|
||||||
|Bill Zissimopoulos |billziss at navimatics.com
|
|Bill Zissimopoulos |billziss at navimatics.com
|
||||||
|Brett Dutro |brett.dutro at gmail.com
|
|Brett Dutro |brett.dutro at gmail.com
|
||||||
|
|Changjian Gao (Juicedata, https://juicefs.com) |gcj at juicedata.io
|
||||||
|Colin Atkinson (Atakama, https://atakama.com) |colin at atakama.com
|
|Colin Atkinson (Atakama, https://atakama.com) |colin at atakama.com
|
||||||
|Felix Croes |felix at dworkin.nl
|
|Felix Croes |felix at dworkin.nl
|
||||||
|Francois Karam (KS2, http://www.ks2.fr) |francois.karam at ks2.fr
|
|Francois Karam (KS2, http://www.ks2.fr) |francois.karam at ks2.fr
|
||||||
@ -65,10 +66,13 @@ CONTRIBUTOR LIST
|
|||||||
|Gal Hammer (Red Hat, https://www.redhat.com) |ghammer at redhat.com
|
|Gal Hammer (Red Hat, https://www.redhat.com) |ghammer at redhat.com
|
||||||
|John Oberschelp |john at oberschelp.net
|
|John Oberschelp |john at oberschelp.net
|
||||||
|John Tyner |jtyner at gmail.com
|
|John Tyner |jtyner at gmail.com
|
||||||
|
|Konstantinos Karakostas |noiredev at protonmail.com
|
||||||
|Paweł Wegner (Google LLC, https://google.com) |lemourin at google.com
|
|Paweł Wegner (Google LLC, https://google.com) |lemourin at google.com
|
||||||
|Pedro Frejo (Arpa System, https://arpasystem.com) |pedro.frejo at arpasystem.com
|
|Pedro Frejo (Arpa System, https://arpasystem.com) |pedro.frejo at arpasystem.com
|
||||||
|
|Ronny Chan |ronny at ronnychan.ca
|
||||||
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||||
|Santiago Ganis |sganis at gmail.com
|
|Santiago Ganis |sganis at gmail.com
|
||||||
|Tobias Urlaub |saibotu at outlook.de
|
|Tobias Urlaub |saibotu at outlook.de
|
||||||
|Victor Gao |victgm at outlook.com
|
|Victor Gao |victgm at outlook.com
|
||||||
|
|Zeho Huang |zeho11 at protonmail.com
|
||||||
|===
|
|===
|
||||||
|
14
README.md
14
README.md
@ -10,18 +10,12 @@
|
|||||||
<a href="https://winfsp.dev"><b>winfsp.dev</b></a>
|
<a href="https://winfsp.dev"><b>winfsp.dev</b></a>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<a href="https://github.com/winfsp/winfsp/releases/latest">
|
<a href="https://github.com/winfsp/winfsp/releases/latest"><img src="https://img.shields.io/github/release/winfsp/winfsp.svg?label=stable&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/></a>
|
||||||
<img src="https://img.shields.io/github/release/winfsp/winfsp.svg?label=stable&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/>
|
<a href="https://github.com/winfsp/winfsp/releases"><img src="https://img.shields.io/github/release/winfsp/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/></a>
|
||||||
</a>
|
<a href="https://chocolatey.org/packages/winfsp"><img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/></a>
|
||||||
<a href="https://github.com/winfsp/winfsp/releases">
|
|
||||||
<img src="https://img.shields.io/github/release/winfsp/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/>
|
|
||||||
</a>
|
|
||||||
<a href="https://chocolatey.org/packages/winfsp">
|
|
||||||
<img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/>
|
|
||||||
</a>
|
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<img src="doc/cap.gif" height="450"/>
|
<img src="doc/cap.gif" width="75%" height="75%"/>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
</p>
|
</p>
|
||||||
|
20
appveyor.yml
20
appveyor.yml
@ -17,19 +17,25 @@ environment:
|
|||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
CONFIGURATION: Debug
|
CONFIGURATION: Debug
|
||||||
TESTING: Func
|
TESTING: Func
|
||||||
|
DOCKER_TESTING: None
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
CONFIGURATION: Release
|
CONFIGURATION: Release
|
||||||
TESTING: Func
|
TESTING: Func
|
||||||
|
DOCKER_TESTING: None
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
CONFIGURATION: Release
|
CONFIGURATION: Release
|
||||||
TESTING: Func
|
TESTING: Func
|
||||||
|
DOCKER_TESTING: None
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
CONFIGURATION: Release
|
CONFIGURATION: Release
|
||||||
TESTING: Func
|
TESTING: Func
|
||||||
|
DOCKER_TESTING: Func
|
||||||
#- CONFIGURATION: Release
|
#- CONFIGURATION: Release
|
||||||
# TESTING: Avast
|
# TESTING: Avast
|
||||||
|
# DOCKER_TESTING: None
|
||||||
#- CONFIGURATION: Release
|
#- CONFIGURATION: Release
|
||||||
# TESTING: Perf
|
# TESTING: Perf
|
||||||
|
# DOCKER_TESTING: None
|
||||||
|
|
||||||
init:
|
init:
|
||||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||||
@ -45,6 +51,11 @@ install:
|
|||||||
$targets.Save("C:\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets")
|
$targets.Save("C:\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets")
|
||||||
Add-AppveyorMessage "Hack to make WDK 1903 work on VS2015"
|
Add-AppveyorMessage "Hack to make WDK 1903 work on VS2015"
|
||||||
}
|
}
|
||||||
|
# Install .NET SDK on VS2015 image
|
||||||
|
- ps: |
|
||||||
|
if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") {
|
||||||
|
& ([scriptblock]::Create((New-Object System.Net.WebClient).DownloadString('https://dot.net/v1/dotnet-install.ps1'))) -InstallDir "C:\dotnet"
|
||||||
|
}
|
||||||
# Submodules
|
# Submodules
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
# Kernel and user mode dumps
|
# Kernel and user mode dumps
|
||||||
@ -70,6 +81,9 @@ build_script:
|
|||||||
# remove ARM64 project configurations to build in VS2015/VS2017
|
# remove ARM64 project configurations to build in VS2015/VS2017
|
||||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" tools\gensrc\remove-build-arm64.bat
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" tools\gensrc\remove-build-arm64.bat
|
||||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" tools\gensrc\remove-build-arm64.bat
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" tools\gensrc\remove-build-arm64.bat
|
||||||
|
# remove .NET library from solution for VS2015 and use the .NET SDK instead
|
||||||
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" tools\gensrc\remove-build-dotnet.bat build\VStudio
|
||||||
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set PATH=C:\dotnet;%PATH%
|
||||||
# build winfsp
|
# build winfsp
|
||||||
- tools\build.bat %CONFIGURATION%
|
- tools\build.bat %CONFIGURATION%
|
||||||
|
|
||||||
@ -80,7 +94,8 @@ test_script:
|
|||||||
- if %TESTING%==Func 7z x Test.Filter.Driver.zip.001
|
- if %TESTING%==Func 7z x Test.Filter.Driver.zip.001
|
||||||
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
||||||
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
||||||
- ps: . "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /k +spp *
|
#- ps: . "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /k +spp *
|
||||||
|
- if %DOCKER_TESTING%==Func docker run -d --name=Container0 --isolation=process "-vC:\Program Files (x86)\WinFsp:C:\Program Files (x86)\WinFsp:RO" "-vC:\projects:C:\projects:RO" mcr.microsoft.com/windows/servercore:ltsc2019 cmd.exe /c waitfor 7BF47D72F6664550B03248ECFE77C7DD
|
||||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
||||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
|
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
|
||||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample
|
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample
|
||||||
@ -88,6 +103,9 @@ test_script:
|
|||||||
- if %TESTING%==Avast choco install avastfreeantivirus && fltmc instances -v "C:"
|
- if %TESTING%==Avast choco install avastfreeantivirus && fltmc instances -v "C:"
|
||||||
- if %TESTING%==Avast tools\run-tests.bat %CONFIGURATION% avast-tests
|
- if %TESTING%==Avast tools\run-tests.bat %CONFIGURATION% avast-tests
|
||||||
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
||||||
|
- if %DOCKER_TESTING%==Func docker exec Container0 cmd.exe /c C:\projects\winfsp\build\VStudio\build\%CONFIGURATION%\winfsp-tests-x64.exe +*
|
||||||
|
#- if %DOCKER_TESTING%==Func docker run -d --name=Container1 --isolation=process "-vC:\Program Files (x86)\WinFsp:C:\Program Files (x86)\WinFsp:RO" "-vC:\projects:C:\projects:RO" mcr.microsoft.com/windows/servercore:ltsc2019 cmd.exe /c waitfor 7BF47D72F6664550B03248ECFE77C7DD
|
||||||
|
#- if %DOCKER_TESTING%==Func docker exec Container1 cmd.exe /c C:\projects\winfsp\build\VStudio\build\%CONFIGURATION%\winfsp-tests-x64.exe +*
|
||||||
- choco uninstall winfsp -y
|
- choco uninstall winfsp -y
|
||||||
|
|
||||||
on_finish:
|
on_finish:
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
<Import Project="$(MsbuildThisFileDirectory)\build.version.props" />
|
<Import Project="$(MsbuildThisFileDirectory)\build.version.props" />
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid);MyFsctlRegisterPath=$(MyFsctlRegisterPath);MyNpRegisterPath=$(MyNpRegisterPath);MyEventLogRegisterPath=$(MyEventLogRegisterPath)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ResourceCompile>
|
<ResourceCompile>
|
||||||
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid);MyFsctlRegisterPath=$(MyFsctlRegisterPath);MyNpRegisterPath=$(MyNpRegisterPath);MyEventLogRegisterPath=$(MyEventLogRegisterPath)</PreprocessorDefinitions>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(IsKernelModeToolset)'=='true'">
|
<ItemDefinitionGroup Condition="'$(IsKernelModeToolset)'=='true'">
|
||||||
|
@ -18,12 +18,12 @@
|
|||||||
<MyCompanyName>Navimatics LLC</MyCompanyName>
|
<MyCompanyName>Navimatics LLC</MyCompanyName>
|
||||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||||
|
|
||||||
<MyCanonicalVersion>1.11</MyCanonicalVersion>
|
<MyCanonicalVersion>2.0</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2022+ARM64 RC1</MyProductVersion>
|
<MyProductVersion>2023 RC1</MyProductVersion>
|
||||||
<MyProductStage>RC</MyProductStage>
|
<MyProductStage>RC</MyProductStage>
|
||||||
|
|
||||||
<MyCrossCert>DigiCert High Assurance EV Root CA.crt</MyCrossCert>
|
<MyCrossCert>DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer</MyCrossCert>
|
||||||
<MyCertIssuer>DigiCert</MyCertIssuer>
|
<MyCertIssuer>DigiCert</MyCertIssuer>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
@ -40,5 +40,37 @@
|
|||||||
<!-- When rebranding WinFsp you MUST change the following GUIDs - use VS "Create GUID" tool -->
|
<!-- When rebranding WinFsp you MUST change the following GUIDs - use VS "Create GUID" tool -->
|
||||||
<MyFspFsctlDeviceClassGuid>{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } }</MyFspFsctlDeviceClassGuid>
|
<MyFspFsctlDeviceClassGuid>{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } }</MyFspFsctlDeviceClassGuid>
|
||||||
<MyFspFsvrtDeviceClassGuid>{ 0xb48171c3, 0xdd50, 0x4852, { 0x83, 0xa3, 0x34, 0x4c, 0x50, 0xd9, 0x3b, 0x17 } }</MyFspFsvrtDeviceClassGuid>
|
<MyFspFsvrtDeviceClassGuid>{ 0xb48171c3, 0xdd50, 0x4852, { 0x83, 0xa3, 0x34, 0x4c, 0x50, 0xd9, 0x3b, 0x17 } }</MyFspFsvrtDeviceClassGuid>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Configure paths used for registration via DllRegisterServer:
|
||||||
|
|
||||||
|
- MyFsctlRegisterPath: File System Driver registration path
|
||||||
|
- MyNpRegisterPath: Network Provider registration path
|
||||||
|
- MyEventLogRegisterPath: Event Log registration path
|
||||||
|
|
||||||
|
These paths are assumed to be relative to the location of the WinFsp DLL during
|
||||||
|
registration: during DLLRegisterServer the DLL uses PathCombineW to combine its own
|
||||||
|
location with these paths to produce the final locations to be used for registration.
|
||||||
|
|
||||||
|
For example, if the DLL location is `C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll`:
|
||||||
|
|
||||||
|
- Combining with the path "." will produce the original DLL location:
|
||||||
|
`C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll`
|
||||||
|
|
||||||
|
- Combining with the path "..\\NetworkProvider.dll" will produce:
|
||||||
|
`C:\Program Files (x86)\WinFsp\bin\NetworkProvider.dll`
|
||||||
|
|
||||||
|
- For Network Provider registrations only it is allowed to use environment variables
|
||||||
|
in the path. For example combining the above DLL location with the path
|
||||||
|
"..\\NetworkProvider-\x25PROCESSOR_ARCHITECTURE\x25.dll" will produce:
|
||||||
|
`C:\Program Files (x86)\WinFsp\bin\NetworkProvider-%PROCESSOR_ARCHITECTURE%.dll`
|
||||||
|
|
||||||
|
(Note that the \x25 escape sequence must be used otherwise the VS build system will
|
||||||
|
try to interpret the string %PROCESSOR_ARCHITECTURE% as an environment variable during
|
||||||
|
the build.)
|
||||||
|
-->
|
||||||
|
<MyFsctlRegisterPath>"."</MyFsctlRegisterPath>
|
||||||
|
<MyNpRegisterPath>"."</MyNpRegisterPath>
|
||||||
|
<MyEventLogRegisterPath>"."</MyEventLogRegisterPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
@ -1,25 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project>
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<PropertyGroup>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(MSBuildProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
|
||||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.common.props))/build.common.props" />
|
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.common.props))/build.common.props" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProjectGuid>{94580219-CC8D-4FE5-A3BE-437B0B3481E1}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<ProjectName>winfsp.net</ProjectName>
|
<ProjectName>winfsp.net</ProjectName>
|
||||||
<RootNamespace>Fsp</RootNamespace>
|
<RootNamespace>Fsp</RootNamespace>
|
||||||
<AssemblyName>$(MyProductFileName)-msil</AssemblyName>
|
<AssemblyName>$(MyProductFileName)-msil</AssemblyName>
|
||||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
<TargetFrameworks>netstandard2.0;net35</TargetFrameworks>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<TargetFrameworkProfile />
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">
|
||||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
|
||||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
@ -32,7 +36,6 @@
|
|||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
|
||||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
@ -47,9 +50,6 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AssemblyOriginatorKeyFile>winfsp.net.snk</AssemblyOriginatorKeyFile>
|
<AssemblyOriginatorKeyFile>winfsp.net.snk</AssemblyOriginatorKeyFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\..\..\src\dotnet\FileSystemBase+Const.cs">
|
<Compile Include="..\..\..\src\dotnet\FileSystemBase+Const.cs">
|
||||||
<Link>FileSystemBase+Const.cs</Link>
|
<Link>FileSystemBase+Const.cs</Link>
|
||||||
@ -70,29 +70,28 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="winfsp.net.snk" />
|
<None Include="winfsp.net.snk" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<PackageReference Include="Microsoft.Win32.Registry">
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
<Version>5.0.0</Version>
|
||||||
<Target Name="AfterBuild">
|
</PackageReference>
|
||||||
</Target>
|
<PackageReference Include="System.IO.FileSystem.AccessControl">
|
||||||
-->
|
<Version>5.0.0</Version>
|
||||||
<Target Name="BeforeBuild">
|
</PackageReference>
|
||||||
<ItemGroup>
|
</ItemGroup>
|
||||||
<AssemblyInfo Include="using System.Reflection%3b" />
|
<PropertyGroup>
|
||||||
<AssemblyInfo Include="[assembly: AssemblyProduct("$(MyProductName)")]" />
|
<AssemblyName>$(MyProductFileName)-msil</AssemblyName>
|
||||||
<AssemblyInfo Include="[assembly: AssemblyTitle("$(MyDescription)")]" />
|
<AssemblyTitle>$(MyDescription)</AssemblyTitle>
|
||||||
<AssemblyInfo Include="[assembly: AssemblyCompany("$(MyCompanyName)")]" />
|
<Product>$(MyProductName)</Product>
|
||||||
<AssemblyInfo Include="[assembly: AssemblyCopyright("$(MyCopyright)")]" />
|
<Copyright>$(MyCopyright)</Copyright>
|
||||||
<AssemblyInfo Include="[assembly: AssemblyVersion("$(MyAssemblyVersion)")]" />
|
<AssemblyVersion>$(MyAssemblyVersion)</AssemblyVersion>
|
||||||
<AssemblyInfo Include="[assembly: AssemblyFileVersion("$(MyVersion)")]" />
|
<FileVersion>$(MyVersion)</FileVersion>
|
||||||
</ItemGroup>
|
<!-- NuGet metadata -->
|
||||||
<MakeDir Directories="$(IntermediateOutputPath)" />
|
<PackageId>$(MyProductFileName).net</PackageId>
|
||||||
<WriteLinesToFile File="$(IntermediateOutputPath)AssemblyInfo.cs" Lines="@(AssemblyInfo)" Overwrite="true" />
|
<Version>$(MyVersion)</Version>
|
||||||
<ItemGroup>
|
<Description>$(MyDescription)</Description>
|
||||||
<Compile Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
|
<Authors>$(MyCopyright)</Authors>
|
||||||
<FileWrites Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
|
<Company>$(MyCompanyName)</Company>
|
||||||
</ItemGroup>
|
</PropertyGroup>
|
||||||
</Target>
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>exit /b 0
|
<PostBuildEvent>exit /b 0
|
||||||
|
|
||||||
@ -110,4 +109,5 @@ for /f "delims=" %25%25l in ($(ProjectDir)winfsp.net.policy.config) do (
|
|||||||
"$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.0A\Bin\al.exe" /product:"$(MyProductName)" /title:"$(MyDescription)" /company:"$(MyCompanyName)" /copyright:"$(MyCopyright)" /version:"$(MyAssemblyPolicyVersion)" /fileversion:"$(MyVersion)" /link:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config /out:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).dll /keyfile:$(ProjectDir)$(ProjectName).snk
|
"$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.0A\Bin\al.exe" /product:"$(MyProductName)" /title:"$(MyDescription)" /company:"$(MyCompanyName)" /copyright:"$(MyCopyright)" /version:"$(MyAssemblyPolicyVersion)" /fileversion:"$(MyVersion)" /link:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config /out:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).dll /keyfile:$(ProjectDir)$(ProjectName).snk
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||||
</Project>
|
</Project>
|
@ -21,10 +21,55 @@
|
|||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shellapi.h>
|
||||||
#include <msiquery.h>
|
#include <msiquery.h>
|
||||||
#include <wcautil.h>
|
#include <wcautil.h>
|
||||||
#include <strutil.h>
|
#include <strutil.h>
|
||||||
|
|
||||||
|
static HINSTANCE DllInstance;
|
||||||
|
|
||||||
|
UINT __stdcall InstanceID(MSIHANDLE MsiHandle)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
WCHAR MessageBuf[64];
|
||||||
|
wsprintfW(MessageBuf, L"PID=%ld", GetCurrentProcessId());
|
||||||
|
MessageBoxW(0, MessageBuf, L"" __FUNCTION__ " Break", MB_OK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
UINT err = ERROR_SUCCESS;
|
||||||
|
SYSTEMTIME SystemTime;
|
||||||
|
WCHAR Result[32+1];
|
||||||
|
|
||||||
|
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||||
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
|
WcaLog(LOGMSG_STANDARD, "Initialized");
|
||||||
|
|
||||||
|
GetSystemTime(&SystemTime);
|
||||||
|
wsprintfW(Result, L"%04u%02u%02uT%02u%02u%02uZ",
|
||||||
|
SystemTime.wYear,
|
||||||
|
SystemTime.wMonth,
|
||||||
|
SystemTime.wDay,
|
||||||
|
SystemTime.wHour,
|
||||||
|
SystemTime.wMinute,
|
||||||
|
SystemTime.wSecond);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sleep 1 second to ensure timestamp uniqueness.
|
||||||
|
*
|
||||||
|
* Note that this assumes that time is monotonic and users do not change time.
|
||||||
|
* Disable for now as it is assumed that the installation takes more than 1 second to complete.
|
||||||
|
*/
|
||||||
|
//Sleep(1000);
|
||||||
|
|
||||||
|
WcaSetProperty(L"" __FUNCTION__, Result);
|
||||||
|
|
||||||
|
LExit:
|
||||||
|
err = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||||
|
return WcaFinalize(err);
|
||||||
|
}
|
||||||
|
|
||||||
UINT __stdcall ServiceRunning(MSIHANDLE MsiHandle)
|
UINT __stdcall ServiceRunning(MSIHANDLE MsiHandle)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@ -44,7 +89,7 @@ UINT __stdcall ServiceRunning(MSIHANDLE MsiHandle)
|
|||||||
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||||
ExitOnFailure(hr, "Failed to initialize");
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
WcaGetProperty(L"" __FUNCTION__, &ServiceName);
|
hr = WcaGetProperty(L"" __FUNCTION__, &ServiceName);
|
||||||
ExitOnFailure(hr, "Failed to get ServiceName");
|
ExitOnFailure(hr, "Failed to get ServiceName");
|
||||||
|
|
||||||
WcaLog(LOGMSG_STANDARD, "Initialized: \"%S\"", ServiceName);
|
WcaLog(LOGMSG_STANDARD, "Initialized: \"%S\"", ServiceName);
|
||||||
@ -70,12 +115,390 @@ LExit:
|
|||||||
return WcaFinalize(err);
|
return WcaFinalize(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT __stdcall DeferredAction(MSIHANDLE MsiHandle)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
WCHAR MessageBuf[64];
|
||||||
|
wsprintfW(MessageBuf, L"PID=%ld", GetCurrentProcessId());
|
||||||
|
MessageBoxW(0, MessageBuf, L"" __FUNCTION__ " Break", MB_OK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
UINT err = ERROR_SUCCESS;
|
||||||
|
PWSTR CommandLine = 0;
|
||||||
|
PWSTR *Argv;
|
||||||
|
int Argc;
|
||||||
|
CHAR ProcName[64];
|
||||||
|
FARPROC Proc;
|
||||||
|
|
||||||
|
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||||
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
|
hr = WcaGetProperty(L"CustomActionData", &CommandLine);
|
||||||
|
ExitOnFailure(hr, "Failed to get CommandLine");
|
||||||
|
|
||||||
|
WcaLog(LOGMSG_STANDARD, "Initialized: \"%S\"", CommandLine);
|
||||||
|
|
||||||
|
Argv = CommandLineToArgvW(CommandLine, &Argc);
|
||||||
|
ExitOnNullWithLastError(Argv, hr, "Failed to CommandLineToArgvW");
|
||||||
|
|
||||||
|
if (0 < Argc)
|
||||||
|
{
|
||||||
|
if (0 == WideCharToMultiByte(CP_UTF8, 0, Argv[0], -1, ProcName, sizeof ProcName, 0, 0))
|
||||||
|
ExitWithLastError(hr, "Failed to WideCharToMultiByte");
|
||||||
|
|
||||||
|
Proc = GetProcAddress(DllInstance, ProcName);
|
||||||
|
ExitOnNullWithLastError(Proc, hr, "Failed to GetProcAddress");
|
||||||
|
|
||||||
|
err = ((HRESULT (*)(int, PWSTR *))Proc)(Argc, Argv);
|
||||||
|
ExitOnWin32Error(err, hr, "Failed to %s", ProcName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
ExitOnFailure(hr, "Failed to get arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
LExit:
|
||||||
|
LocalFree(Argv);
|
||||||
|
ReleaseStr(CommandLine);
|
||||||
|
|
||||||
|
err = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||||
|
return WcaFinalize(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD MakeSymlink(PWSTR Symlink, PWSTR Target);
|
||||||
|
static DWORD MakeJunction(PWSTR Junction, PWSTR Target);
|
||||||
|
static DWORD CreateJunction(PWSTR Junction, PWSTR Target);
|
||||||
|
static DWORD RemoveFile(PWSTR FileName);
|
||||||
|
|
||||||
|
DWORD InstallSymlinks(int Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
/* usage: InstallSymlinks/InstallJunctions SourceDir TargetDir Name... */
|
||||||
|
|
||||||
|
DWORD Result;
|
||||||
|
BOOL Junctions;
|
||||||
|
PWSTR SourceDir, TargetDir;
|
||||||
|
WCHAR SourcePath[MAX_PATH], TargetPath[MAX_PATH];
|
||||||
|
int SourceDirLen, TargetDirLen, Len;
|
||||||
|
|
||||||
|
if (4 > Argc)
|
||||||
|
{
|
||||||
|
Result = ERROR_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Junctions = 0 == lstrcmpW(L"InstallJunctions", Argv[0]);
|
||||||
|
SourceDir = Argv[1];
|
||||||
|
TargetDir = Argv[2];
|
||||||
|
SourceDirLen = lstrlenW(SourceDir);
|
||||||
|
TargetDirLen = lstrlenW(TargetDir);
|
||||||
|
|
||||||
|
for (int Argi = 3; Argc > Argi; Argi++)
|
||||||
|
{
|
||||||
|
Len = lstrlenW(Argv[Argi]);
|
||||||
|
if (MAX_PATH < SourceDirLen + Len + 1 || MAX_PATH < TargetDirLen + Len + 1)
|
||||||
|
{
|
||||||
|
Result = ERROR_FILENAME_EXCED_RANGE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(SourcePath, SourceDir, SourceDirLen * sizeof(WCHAR));
|
||||||
|
memcpy(SourcePath + SourceDirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||||
|
SourcePath[SourceDirLen + Len] = L'\0';
|
||||||
|
|
||||||
|
memcpy(TargetPath, TargetDir, TargetDirLen * sizeof(WCHAR));
|
||||||
|
memcpy(TargetPath + TargetDirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||||
|
TargetPath[TargetDirLen + Len] = L'\0';
|
||||||
|
|
||||||
|
if (!Junctions)
|
||||||
|
Result = MakeSymlink(SourcePath, TargetPath);
|
||||||
|
else
|
||||||
|
Result = MakeJunction(SourcePath, TargetPath);
|
||||||
|
#if 0
|
||||||
|
WCHAR MessageBuf[1024];
|
||||||
|
wsprintfW(MessageBuf, L"MakeSymlink(\"%s\", \"%s\") = %lu", SourcePath, TargetPath, Result);
|
||||||
|
MessageBoxW(0, MessageBuf, L"TRACE", MB_OK);
|
||||||
|
#endif
|
||||||
|
if (ERROR_SUCCESS != Result)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD InstallJunctions(int Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
return InstallSymlinks(Argc, Argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD RemoveFiles(int Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
/* usage: RemoveFiles Dir Name... */
|
||||||
|
|
||||||
|
DWORD Result;
|
||||||
|
PWSTR Dir;
|
||||||
|
WCHAR Path[MAX_PATH];
|
||||||
|
int DirLen, Len;
|
||||||
|
|
||||||
|
if (3 > Argc)
|
||||||
|
{
|
||||||
|
Result = ERROR_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dir = Argv[1];
|
||||||
|
DirLen = lstrlenW(Dir);
|
||||||
|
|
||||||
|
for (int Argi = 2; Argc > Argi; Argi++)
|
||||||
|
{
|
||||||
|
Len = lstrlenW(Argv[Argi]);
|
||||||
|
if (MAX_PATH < DirLen + Len + 1)
|
||||||
|
{
|
||||||
|
Result = ERROR_FILENAME_EXCED_RANGE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(Path, Dir, DirLen * sizeof(WCHAR));
|
||||||
|
memcpy(Path + DirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||||
|
Path[DirLen + Len] = L'\0';
|
||||||
|
|
||||||
|
Result = RemoveFile(Path);
|
||||||
|
#if 0
|
||||||
|
WCHAR MessageBuf[1024];
|
||||||
|
wsprintfW(MessageBuf, L"RemoveFile(\"%s\") = %lu", Path, Result);
|
||||||
|
MessageBoxW(0, MessageBuf, L"TRACE", MB_OK);
|
||||||
|
#endif
|
||||||
|
if (ERROR_SUCCESS != Result)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD MakeSymlink(PWSTR Symlink, PWSTR Target)
|
||||||
|
{
|
||||||
|
DWORD Result;
|
||||||
|
DWORD FileAttributes, Flags;
|
||||||
|
|
||||||
|
RemoveFile(Symlink);
|
||||||
|
|
||||||
|
FileAttributes = GetFileAttributesW(Target);
|
||||||
|
if (INVALID_FILE_ATTRIBUTES == FileAttributes)
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
Flags = 0 != (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
|
||||||
|
|
||||||
|
if (!CreateSymbolicLinkW(Symlink, Target, Flags))
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
RemoveFile(Symlink);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD MakeJunction(PWSTR Junction, PWSTR Target)
|
||||||
|
{
|
||||||
|
DWORD Result;
|
||||||
|
DWORD FileAttributes;
|
||||||
|
|
||||||
|
RemoveFile(Junction);
|
||||||
|
|
||||||
|
FileAttributes = GetFileAttributesW(Target);
|
||||||
|
if (INVALID_FILE_ATTRIBUTES == FileAttributes)
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (0 == (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
|
{
|
||||||
|
Result = ERROR_DIRECTORY;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = CreateJunction(Junction, Target);
|
||||||
|
if (ERROR_SUCCESS != Result)
|
||||||
|
{
|
||||||
|
RemoveFile(Junction);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD CreateJunction(PWSTR Junction, PWSTR Target)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The REPARSE_DATA_BUFFER definitions appear to be missing from the user mode headers.
|
||||||
|
*/
|
||||||
|
typedef struct _REPARSE_DATA_BUFFER
|
||||||
|
{
|
||||||
|
ULONG ReparseTag;
|
||||||
|
USHORT ReparseDataLength;
|
||||||
|
USHORT Reserved;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
USHORT SubstituteNameOffset;
|
||||||
|
USHORT SubstituteNameLength;
|
||||||
|
USHORT PrintNameOffset;
|
||||||
|
USHORT PrintNameLength;
|
||||||
|
ULONG Flags;
|
||||||
|
WCHAR PathBuffer[1];
|
||||||
|
} SymbolicLinkReparseBuffer;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
USHORT SubstituteNameOffset;
|
||||||
|
USHORT SubstituteNameLength;
|
||||||
|
USHORT PrintNameOffset;
|
||||||
|
USHORT PrintNameLength;
|
||||||
|
WCHAR PathBuffer[1];
|
||||||
|
} MountPointReparseBuffer;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UCHAR DataBuffer[1];
|
||||||
|
} GenericReparseBuffer;
|
||||||
|
} DUMMYUNIONNAME;
|
||||||
|
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||||
|
const LONG REPARSE_DATA_BUFFER_HEADER_SIZE =
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer);
|
||||||
|
const DWORD FSCTL_SET_REPARSE_POINT = 0x000900a4;
|
||||||
|
|
||||||
|
DWORD Result;
|
||||||
|
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||||
|
USHORT TargetLength, ReparseDataLength;
|
||||||
|
PREPARSE_DATA_BUFFER ReparseData = 0;
|
||||||
|
PWSTR PathBuffer;
|
||||||
|
DWORD Bytes;
|
||||||
|
|
||||||
|
if (!(
|
||||||
|
((L'A' <= Target[0] && Target[0] <= L'Z') || (L'a' <= Target[0] && Target[0] <= L'z')) &&
|
||||||
|
L':' == Target[1]
|
||||||
|
))
|
||||||
|
{
|
||||||
|
Result = ERROR_INVALID_NAME;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle = CreateFileW(Junction,
|
||||||
|
FILE_WRITE_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY |
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Handle)
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetLength = (USHORT)lstrlenW(Target) * sizeof(WCHAR);
|
||||||
|
ReparseDataLength = (USHORT)(
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) -
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer)) +
|
||||||
|
4 * sizeof(WCHAR) + 2 * (TargetLength + sizeof(WCHAR));
|
||||||
|
ReparseData = (PREPARSE_DATA_BUFFER)
|
||||||
|
HeapAlloc(GetProcessHeap(), 0, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseDataLength);
|
||||||
|
if (0 == ReparseData)
|
||||||
|
{
|
||||||
|
Result = ERROR_NO_SYSTEM_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||||
|
ReparseData->ReparseDataLength = ReparseDataLength;
|
||||||
|
ReparseData->Reserved = 0;
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameOffset = 0;
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameLength =
|
||||||
|
4 * sizeof(WCHAR) + TargetLength;
|
||||||
|
ReparseData->MountPointReparseBuffer.PrintNameOffset =
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
|
||||||
|
ReparseData->MountPointReparseBuffer.PrintNameLength =
|
||||||
|
TargetLength;
|
||||||
|
|
||||||
|
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer;
|
||||||
|
PathBuffer[0] = L'\\';
|
||||||
|
PathBuffer[1] = L'?';
|
||||||
|
PathBuffer[2] = L'?';
|
||||||
|
PathBuffer[3] = L'\\';
|
||||||
|
memcpy(PathBuffer + 4, Target, TargetLength);
|
||||||
|
PathBuffer[4 + TargetLength / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer +
|
||||||
|
(ReparseData->MountPointReparseBuffer.PrintNameOffset) / sizeof(WCHAR);
|
||||||
|
memcpy(PathBuffer, Target, TargetLength);
|
||||||
|
PathBuffer[TargetLength / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
if (!DeviceIoControl(Handle, FSCTL_SET_REPARSE_POINT,
|
||||||
|
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
||||||
|
0, 0,
|
||||||
|
&Bytes, 0))
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != Handle)
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
if (0 != ReparseData)
|
||||||
|
HeapFree(GetProcessHeap(), 0, ReparseData);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD RemoveFile(PWSTR FileName)
|
||||||
|
{
|
||||||
|
DWORD Result;
|
||||||
|
|
||||||
|
if (!RemoveDirectoryW(FileName))
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
if (ERROR_DIRECTORY != Result)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (!DeleteFileW(FileName))
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||||
{
|
{
|
||||||
switch(Reason)
|
switch(Reason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
DllInstance = Instance;
|
||||||
WcaGlobalInitialize(Instance);
|
WcaGlobalInitialize(Instance);
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
@ -1,2 +1,7 @@
|
|||||||
EXPORTS
|
EXPORTS
|
||||||
|
InstanceID
|
||||||
ServiceRunning
|
ServiceRunning
|
||||||
|
DeferredAction
|
||||||
|
InstallSymlinks
|
||||||
|
InstallJunctions
|
||||||
|
RemoveFiles
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- The UpgradeCode of the old WinFsp installer that did not support upgrades. -->
|
||||||
|
<?define OldVersionUpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"?>
|
||||||
|
|
||||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||||
xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
|
xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
|
||||||
<Product
|
<Product
|
||||||
@ -7,7 +11,7 @@
|
|||||||
Manufacturer="$(var.MyCompanyName)"
|
Manufacturer="$(var.MyCompanyName)"
|
||||||
Version="$(var.MyVersion)"
|
Version="$(var.MyVersion)"
|
||||||
Language="1033"
|
Language="1033"
|
||||||
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B">
|
UpgradeCode="5466A3D8-3AA1-4240-B6A0-3A051940A3EC">
|
||||||
|
|
||||||
<Package
|
<Package
|
||||||
Description="$(var.MyProductName) - $(var.MyDescription)"
|
Description="$(var.MyProductName) - $(var.MyDescription)"
|
||||||
@ -15,13 +19,26 @@
|
|||||||
Compressed="yes"
|
Compressed="yes"
|
||||||
InstallScope="perMachine" />
|
InstallScope="perMachine" />
|
||||||
<MajorUpgrade
|
<MajorUpgrade
|
||||||
Disallow="yes"
|
Disallow="no"
|
||||||
AllowDowngrades="no"
|
AllowDowngrades="no"
|
||||||
AllowSameVersionUpgrades="no"
|
AllowSameVersionUpgrades="yes"
|
||||||
DisallowUpgradeErrorMessage="An older version of $(var.MyProductName) is already installed. You must uninstall it before you can install this version."
|
|
||||||
DowngradeErrorMessage="A newer version of $(var.MyProductName) is already installed." />
|
DowngradeErrorMessage="A newer version of $(var.MyProductName) is already installed." />
|
||||||
<Media Id="1" Cabinet="$(var.MyProductName).cab" EmbedCab="yes" />
|
<Media Id="1" Cabinet="$(var.MyProductName).cab" EmbedCab="yes" />
|
||||||
|
|
||||||
|
<!-- Determine if we are on Win7 or above. -->
|
||||||
|
<Condition Message="$(var.MyProductName) requires Windows version 7 or higher in order to be installed.">
|
||||||
|
<![CDATA[Installed OR (VersionNT >= 601)]]>
|
||||||
|
</Condition>
|
||||||
|
|
||||||
|
<!-- Determine if the old WinFsp installer that did not support upgrades is installed. -->
|
||||||
|
<Property Id="OLDVERSIONINSTALLED">
|
||||||
|
<ProductSearch UpgradeCode="$(var.OldVersionUpgradeCode)" Minimum="0.0.0.0" />
|
||||||
|
</Property>
|
||||||
|
<Condition Message="An older version of $(var.MyProductName) that cannot be upgraded is already installed. You must uninstall it before you can install this version.">
|
||||||
|
NOT OLDVERSIONINSTALLED
|
||||||
|
</Condition>
|
||||||
|
|
||||||
|
<!-- Determine OS architecture. -->
|
||||||
<Property Id="OSARCH" Secure="yes" Value="AMD64">
|
<Property Id="OSARCH" Secure="yes" Value="AMD64">
|
||||||
<RegistrySearch
|
<RegistrySearch
|
||||||
Id="R.OSARCH"
|
Id="R.OSARCH"
|
||||||
@ -31,10 +48,10 @@
|
|||||||
Type="raw" />
|
Type="raw" />
|
||||||
</Property>
|
</Property>
|
||||||
|
|
||||||
<Property Id="P.LauncherName">$(var.MyProductName).Launcher</Property>
|
<!-- Setup INSTALLDIR and SXSDIR from the registry or defaults. -->
|
||||||
<Property Id="P.LauncherRegistryKey">Software\$(var.MyProductName)\Services</Property>
|
|
||||||
<Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property>
|
<Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property>
|
||||||
<Property Id="INSTALLDIR">
|
<Property Id="P.LauncherRegistryKey">Software\$(var.MyProductName)\Services</Property>
|
||||||
|
<Property Id="INSTALLDIR" Secure="yes">
|
||||||
<RegistrySearch
|
<RegistrySearch
|
||||||
Id="R.INSTALLDIR"
|
Id="R.INSTALLDIR"
|
||||||
Root="HKLM"
|
Root="HKLM"
|
||||||
@ -42,22 +59,40 @@
|
|||||||
Name="InstallDir"
|
Name="InstallDir"
|
||||||
Type="raw" />
|
Type="raw" />
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property Id="SXSDIR" Secure="yes">
|
||||||
|
<RegistrySearch
|
||||||
|
Id="R.SXSDIR"
|
||||||
|
Root="HKLM"
|
||||||
|
Key="[P.RegistryKey]"
|
||||||
|
Name="SxsDir"
|
||||||
|
Type="raw" />
|
||||||
|
</Property>
|
||||||
|
<SetProperty Id="INSTALLDIR" Value="[ProgramFilesFolder]$(var.MyProductName)\" After="CostInitialize">
|
||||||
|
NOT INSTALLDIR
|
||||||
|
</SetProperty>
|
||||||
|
<SetProperty Id="SXSDIR" Value="[INSTALLDIR]SxS\sxs.[InstanceID]\" After="SetINSTALLDIR">
|
||||||
|
((NOT SXSDIR) OR WIX_UPGRADE_DETECTED) AND InstanceID
|
||||||
|
</SetProperty>
|
||||||
|
|
||||||
|
<!-- Setup directory structure. -->
|
||||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
<Directory Id="ProgramFilesFolder">
|
<Directory Id="ProgramFilesFolder">
|
||||||
<Directory Id="INSTALLDIR" Name="$(var.MyProductName)">
|
<Directory Id="INSTALLDIR" Name="DYNAMIC">
|
||||||
<Directory Id="BINDIR" Name="bin" />
|
<Directory Id="SXSBASEDIR" Name="SxS">
|
||||||
|
<Directory Id="SXSDIR" Name="DYNAMIC">
|
||||||
|
<Directory Id="BINDIR" Name="bin" />
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
<Directory Id="INCDIR" Name="inc" />
|
<Directory Id="INCDIR" Name="inc" />
|
||||||
<Directory Id="LIBDIR" Name="lib" />
|
<Directory Id="LIBDIR" Name="lib" />
|
||||||
<Directory Id="OPTDIR" Name="opt" />
|
<Directory Id="OPTDIR" Name="opt" />
|
||||||
<Directory Id="SMPDIR" Name="samples" />
|
<Directory Id="SMPDIR" Name="samples" />
|
||||||
<Directory Id="SYMDIR" Name="sym" />
|
|
||||||
</Directory>
|
</Directory>
|
||||||
</Directory>
|
</Directory>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
<DirectoryRef Id="INSTALLDIR">
|
<DirectoryRef Id="INSTALLDIR">
|
||||||
<Component Id="C.INSTALLDIR" Guid="{F876F26E-5016-4AC6-93B3-653C0312A6CE}">
|
<Component Id="C.INSTALLDIR" Guid="C086521F-8552-43D1-AAE2-CDD579F66FDD">
|
||||||
<RegistryValue
|
<RegistryValue
|
||||||
Root="HKLM"
|
Root="HKLM"
|
||||||
Key="[P.RegistryKey]"
|
Key="[P.RegistryKey]"
|
||||||
@ -70,6 +105,17 @@
|
|||||||
<File Name="License.txt" Source="..\..\..\License.txt" KeyPath="yes" />
|
<File Name="License.txt" Source="..\..\..\License.txt" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="SXSDIR">
|
||||||
|
<Component Id="C.SXSDIR" Guid="0F09CD39-1137-4DB8-A783-27B1F51353D1">
|
||||||
|
<RegistryValue
|
||||||
|
Root="HKLM"
|
||||||
|
Key="[P.RegistryKey]"
|
||||||
|
Name="SxsDir"
|
||||||
|
Type="string"
|
||||||
|
Value="[SXSDIR]"
|
||||||
|
KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
||||||
<Component Id="C.$(var.MyProductFileName)_a64.sys">
|
<Component Id="C.$(var.MyProductFileName)_a64.sys">
|
||||||
<File Name="$(var.MyProductFileName)-a64.sys" KeyPath="yes" />
|
<File Name="$(var.MyProductFileName)-a64.sys" KeyPath="yes" />
|
||||||
@ -82,56 +128,56 @@
|
|||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On WinArm64 register $(var.MyProductFileName)-a64.dll -->
|
<!-- On WinArm64 register $(var.MyProductFileName)-a64.dll -->
|
||||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.a64" Guid="86FB483B-0910-458E-93B4-3CCB66D27AF0">
|
<Component Id="C.$(var.MyProductFileName)_a64.dll.a64" Guid="2A7E68EB-D05F-4DD8-ABF2-EB8CB09697F0">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_a64.dll.a64" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" SelfRegCost="1" />
|
<File Id="FILE.$(var.MyProductFileName)_a64.dll.a64" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" SelfRegCost="1" />
|
||||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.a64" Guid="941FAE3E-A650-4BAC-97F5-F8C6E98DB5D2">
|
<Component Id="C.$(var.MyProductFileName)_x64.dll.a64" Guid="EA5ED4FB-FC72-4D27-9802-88D84DAE61B4">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_x64.dll.a64" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_x64.dll.a64" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.a64" Guid="C312214D-F9A3-40EB-B2C3-4FAF5BF3F938">
|
<Component Id="C.$(var.MyProductFileName)_x86.dll.a64" Guid="2A9BD712-2F96-4794-8A58-929E39F3F3CC">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_x86.dll.a64" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_x86.dll.a64" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win64 register $(var.MyProductFileName)-x64.dll -->
|
<!-- On Win64 register $(var.MyProductFileName)-x64.dll -->
|
||||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.x64" Guid="4ABB46C2-A8E3-49E8-B051-05DBF2B351AE">
|
<Component Id="C.$(var.MyProductFileName)_a64.dll.x64" Guid="026DA201-43E1-450C-9687-8A684FBF2D2D">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_a64.dll.x64" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_a64.dll.x64" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.x64" Guid="F0A67746-1A9C-4976-8EC0-882E9407FA6D">
|
<Component Id="C.$(var.MyProductFileName)_x64.dll.x64" Guid="89201BAF-5812-4ECE-91CD-12EDFFF11CB1">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_x64.dll.x64" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" SelfRegCost="1" />
|
<File Id="FILE.$(var.MyProductFileName)_x64.dll.x64" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" SelfRegCost="1" />
|
||||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.x64" Guid="950492FB-12F7-4E27-9124-8325A2BC9927">
|
<Component Id="C.$(var.MyProductFileName)_x86.dll.x64" Guid="E6EE48A4-6BC7-4135-9A2F-FBBA30DE80BE">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_x86.dll.x64" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_x86.dll.x64" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win32 register $(var.MyProductFileName)-x86.dll -->
|
<!-- On Win32 register $(var.MyProductFileName)-x86.dll -->
|
||||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.x86" Guid="071C0EB2-A0EB-46A1-B5B0-124F60ECD6B3">
|
<Component Id="C.$(var.MyProductFileName)_a64.dll.x86" Guid="2B264958-DECC-4B32-9BB2-DE32D6B6BE77">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_a64.dll.x86" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_a64.dll.x86" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.x86" Guid="4D6E7A8E-0CA6-49BE-B312-1EDADE725756">
|
<Component Id="C.$(var.MyProductFileName)_x64.dll.x86" Guid="29FB908F-1D36-4789-9778-4CE2E9C19CEA">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_x64.dll.x86" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_x64.dll.x86" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.x86" Guid="F0DEF7A6-AF55-419F-A58A-DF4018C6FA73">
|
<Component Id="C.$(var.MyProductFileName)_x86.dll.x86" Guid="80E87D91-69A8-4942-ABC1-36652B1CA700">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_x86.dll.x86" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" SelfRegCost="1" />
|
<File Id="FILE.$(var.MyProductFileName)_x86.dll.x86" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" SelfRegCost="1" />
|
||||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- install assembly -->
|
<!-- install assembly -->
|
||||||
<Component Id="C.$(var.MyProductFileName)_msil.dll" Guid="0D8BA6AE-9F87-402B-AE1A-95B0AE3BE179">
|
<Component Id="C.$(var.MyProductFileName)_msil.dll" Guid="1772CDE5-4B2F-48CF-B2DA-CA43818053A8">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_msil.dll" Name="$(var.MyProductFileName)-msil.dll" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_msil.dll" Name="$(var.MyProductFileName)-msil.dll" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.$(var.MyProductFileName)_msil.xml" Guid="1657F707-C112-454C-91AE-0FDEBBF454AB">
|
<Component Id="C.$(var.MyProductFileName)_msil.xml" Guid="C76745D2-51FA-4028-B827-3F2F3F763751">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_msil.xml" Name="$(var.MyProductFileName)-msil.xml" KeyPath="yes" />
|
<File Id="FILE.$(var.MyProductFileName)_msil.xml" Name="$(var.MyProductFileName)-msil.xml" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
<!--
|
<!--
|
||||||
<Component Id="C.$(var.MyProductFileName)_msil.dll.GAC" Guid="6469467D-8C90-4889-8138-4028F9DA6E85">
|
<Component Id="C.$(var.MyProductFileName)_msil.dll.GAC" Guid="D86F8764-2FCC-43DA-A174-23E0FD6D45B7">
|
||||||
<File Id="FILE.$(var.MyProductFileName)_msil.dll.GAC" Name="$(var.MyProductFileName)-msil.dll" KeyPath="yes" Assembly=".net" />
|
<File Id="FILE.$(var.MyProductFileName)_msil.dll.GAC" Name="$(var.MyProductFileName)-msil.dll" KeyPath="yes" Assembly=".net" />
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.policy.$(var.MyProductFileName)_msil.dll.GAC">
|
<Component Id="C.policy.$(var.MyProductFileName)_msil.dll.GAC">
|
||||||
@ -141,103 +187,103 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- On WinArm64 ServiceInstall launcher-a64.exe -->
|
<!-- On WinArm64 ServiceInstall launcher-a64.exe -->
|
||||||
<Component Id="C.launcher_a64.exe.a64" Guid="E37E6D75-C44B-4189-8E86-CE5A3E0B0626">
|
<Component Id="C.launcher_a64.exe.a64" Guid="D8B657EA-7B08-48D1-B5F7-76CFB68E1BD5">
|
||||||
<File Id="FILE.launcher_a64.exe.a64" Name="launcher-a64.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_a64.exe.a64" Name="launcher-a64.exe" KeyPath="yes" />
|
||||||
<ServiceInstall
|
<ServiceInstall
|
||||||
Id="launcher_a64.exe.a64"
|
Id="launcher_a64.exe.a64"
|
||||||
Name="[P.LauncherName]"
|
Name="$(var.MyProductName).Launcher"
|
||||||
Description="$(var.MyDescription)"
|
Description="$(var.MyDescription)"
|
||||||
Type="ownProcess"
|
Type="ownProcess"
|
||||||
Start="auto"
|
Start="auto"
|
||||||
ErrorControl="ignore" />
|
ErrorControl="ignore" />
|
||||||
<ServiceControl
|
<ServiceControl
|
||||||
Id="launcher_a64.exe.a64"
|
Id="launcher_a64.exe.a64"
|
||||||
Name="[P.LauncherName]"
|
Name="$(var.MyProductName).Launcher"
|
||||||
Start="install"
|
Start="install"
|
||||||
Stop="both"
|
Stop="both"
|
||||||
Remove="uninstall" />
|
Remove="uninstall" />
|
||||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launcher_x64.exe.a64" Guid="CF5F3EEE-F739-4F50-9938-13C0D2CD9C7A">
|
<Component Id="C.launcher_x64.exe.a64" Guid="3EFC0561-6EA2-4E7E-B707-C2EA706CFBA0">
|
||||||
<File Id="FILE.launcher_x64.exe.a64" Name="launcher-x64.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_x64.exe.a64" Name="launcher-x64.exe" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launcher_x86.exe.a64" Guid="D5E9FF96-9E00-46BA-8719-BC49CF35BBE6">
|
<Component Id="C.launcher_x86.exe.a64" Guid="69F16682-10AE-4FC4-9007-8D80CE0D8388">
|
||||||
<File Id="FILE.launcher_x86.exe.a64" Name="launcher-x86.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_x86.exe.a64" Name="launcher-x86.exe" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win64 ServiceInstall launcher-x64.exe -->
|
<!-- On Win64 ServiceInstall launcher-x64.exe -->
|
||||||
<Component Id="C.launcher_a64.exe.x64" Guid="10A3F0F9-6555-4071-9C93-EA50E4B3F115">
|
<Component Id="C.launcher_a64.exe.x64" Guid="29760ACE-69CD-4061-8C0C-8A6E72D23A45">
|
||||||
<File Id="FILE.launcher_a64.exe.x64" Name="launcher-a64.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_a64.exe.x64" Name="launcher-a64.exe" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launcher_x64.exe.x64" Guid="2AB4E729-F7CB-4B4A-BE81-6C0C3B3194FC">
|
<Component Id="C.launcher_x64.exe.x64" Guid="36ACBA60-1C92-4D2A-B497-CD4FB13A042F">
|
||||||
<File Id="FILE.launcher_x64.exe.x64" Name="launcher-x64.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_x64.exe.x64" Name="launcher-x64.exe" KeyPath="yes" />
|
||||||
<ServiceInstall
|
<ServiceInstall
|
||||||
Id="launcher_x64.exe.x64"
|
Id="launcher_x64.exe.x64"
|
||||||
Name="[P.LauncherName]"
|
Name="$(var.MyProductName).Launcher"
|
||||||
Description="$(var.MyDescription)"
|
Description="$(var.MyDescription)"
|
||||||
Type="ownProcess"
|
Type="ownProcess"
|
||||||
Start="auto"
|
Start="auto"
|
||||||
ErrorControl="ignore" />
|
ErrorControl="ignore" />
|
||||||
<ServiceControl
|
<ServiceControl
|
||||||
Id="launcher_x64.exe.x64"
|
Id="launcher_x64.exe.x64"
|
||||||
Name="[P.LauncherName]"
|
Name="$(var.MyProductName).Launcher"
|
||||||
Start="install"
|
Start="install"
|
||||||
Stop="both"
|
Stop="both"
|
||||||
Remove="uninstall" />
|
Remove="uninstall" />
|
||||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launcher_x86.exe.x64" Guid="C5B6D411-8A6A-4944-8C4F-7D9FB9A72826">
|
<Component Id="C.launcher_x86.exe.x64" Guid="98F17F67-AC1D-4E16-A147-B7AE113E3CB3">
|
||||||
<File Id="FILE.launcher_x86.exe.x64" Name="launcher-x86.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_x86.exe.x64" Name="launcher-x86.exe" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win32 ServiceInstall launcher-x86.exe -->
|
<!-- On Win32 ServiceInstall launcher-x86.exe -->
|
||||||
<Component Id="C.launcher_a64.exe.x86" Guid="5048AEF5-9DE2-406E-A2EA-F237BAD13286">
|
<Component Id="C.launcher_a64.exe.x86" Guid="9024A9FE-7445-4241-ADA3-82A57C92719A">
|
||||||
<File Id="FILE.launcher_a64.exe.x86" Name="launcher-a64.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_a64.exe.x86" Name="launcher-a64.exe" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launcher_x64.exe.x86" Guid="88CDBE92-8B67-485A-838F-FA4AD37F306F">
|
<Component Id="C.launcher_x64.exe.x86" Guid="A85DA9CD-26AA-460E-950D-CA9692B87465">
|
||||||
<File Id="FILE.launcher_x64.exe.x86" Name="launcher-x64.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_x64.exe.x86" Name="launcher-x64.exe" KeyPath="yes" />
|
||||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launcher_x86.exe.x86" Guid="E995D906-0273-4758-9B26-99A3A8CD143A">
|
<Component Id="C.launcher_x86.exe.x86" Guid="01FCCF6B-9F4B-4F29-8149-489470FFD449">
|
||||||
<File Id="FILE.launcher_x86.exe.x86" Name="launcher-x86.exe" KeyPath="yes" />
|
<File Id="FILE.launcher_x86.exe.x86" Name="launcher-x86.exe" KeyPath="yes" />
|
||||||
<ServiceInstall
|
<ServiceInstall
|
||||||
Id="launcher_x86.exe.x86"
|
Id="launcher_x86.exe.x86"
|
||||||
Name="[P.LauncherName]"
|
Name="$(var.MyProductName).Launcher"
|
||||||
Description="$(var.MyDescription)"
|
Description="$(var.MyDescription)"
|
||||||
Type="ownProcess"
|
Type="ownProcess"
|
||||||
Start="auto"
|
Start="auto"
|
||||||
ErrorControl="ignore" />
|
ErrorControl="ignore" />
|
||||||
<ServiceControl
|
<ServiceControl
|
||||||
Id="launcher_x86.exe.x86"
|
Id="launcher_x86.exe.x86"
|
||||||
Name="[P.LauncherName]"
|
Name="$(var.MyProductName).Launcher"
|
||||||
Start="install"
|
Start="install"
|
||||||
Stop="both"
|
Stop="both"
|
||||||
Remove="uninstall" />
|
Remove="uninstall" />
|
||||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<Component Id="C.launchctl_a64.exe" Guid="B9B5CF8E-317D-40EE-A208-BC46A2A99BAB">
|
<Component Id="C.launchctl_a64.exe" Guid="A7D830DD-20D2-48BF-85B6-E306BCCAFD2D">
|
||||||
<File Name="launchctl-a64.exe" KeyPath="yes" />
|
<File Name="launchctl-a64.exe" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launchctl_x64.exe" Guid="2753623B-66F1-4514-B9C7-F879178DFF49">
|
<Component Id="C.launchctl_x64.exe" Guid="CCC8974A-4CD0-443E-840D-1C92535BBD04">
|
||||||
<File Name="launchctl-x64.exe" KeyPath="yes" />
|
<File Name="launchctl-x64.exe" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.launchctl_x86.exe" Guid="EBDEC4FB-07BB-47CA-BFFF-EB854CA2D22D">
|
<Component Id="C.launchctl_x86.exe" Guid="6E382342-10D4-4274-8FA9-F1B44C40C277">
|
||||||
<File Name="launchctl-x86.exe" KeyPath="yes" />
|
<File Name="launchctl-x86.exe" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<Component Id="C.fsptool_a64.exe" Guid="F75A8B14-000C-4933-AD83-EC0D1D3AD3CA">
|
<Component Id="C.fsptool_a64.exe" Guid="8ACEB970-CAD5-491D-8CE8-12675CC0E812">
|
||||||
<File Name="fsptool-a64.exe" KeyPath="yes" />
|
<File Name="fsptool-a64.exe" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.fsptool_x64.exe" Guid="013FE508-097D-4433-9C60-717F5446E7F4">
|
<Component Id="C.fsptool_x64.exe" Guid="35EE49E2-9565-4FA2-A0AC-D51FD94FA380">
|
||||||
<File Name="fsptool-x64.exe" KeyPath="yes" />
|
<File Name="fsptool-x64.exe" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="C.fsptool_x86.exe" Guid="6C16DC2C-E12F-49FB-A665-3AF0475487AD">
|
<Component Id="C.fsptool_x86.exe" Guid="0E6D5742-D500-4E24-A0FA-E6316DB70D8B">
|
||||||
<File Name="fsptool-x86.exe" KeyPath="yes" />
|
<File Name="fsptool-x86.exe" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
@ -409,7 +455,7 @@
|
|||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On WinArm64 copy fuse-a64.pc -->
|
<!-- On WinArm64 copy fuse-a64.pc -->
|
||||||
<Component Id="C.fuse_a64.pc" Guid="74E6E9BD-AF16-4635-AE52-84B33E4E196E">
|
<Component Id="C.fuse_a64.pc" Guid="776C28B5-DA1A-4EB6-96E6-3D22FE1573AC">
|
||||||
<File
|
<File
|
||||||
Id="FILE.fuse_a64.pc"
|
Id="FILE.fuse_a64.pc"
|
||||||
Name="fuse.pc"
|
Name="fuse.pc"
|
||||||
@ -419,7 +465,7 @@
|
|||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win64 copy fuse-x64.pc -->
|
<!-- On Win64 copy fuse-x64.pc -->
|
||||||
<Component Id="C.fuse_x64.pc" Guid="407395D2-D076-411E-B1D0-D97E21E11A3C">
|
<Component Id="C.fuse_x64.pc" Guid="89D39F6E-2994-4E6F-ACB6-5B544057C051">
|
||||||
<File
|
<File
|
||||||
Id="FILE.fuse_x64.pc"
|
Id="FILE.fuse_x64.pc"
|
||||||
Name="fuse.pc"
|
Name="fuse.pc"
|
||||||
@ -429,7 +475,7 @@
|
|||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win32 copy fuse-x86.pc -->
|
<!-- On Win32 copy fuse-x86.pc -->
|
||||||
<Component Id="C.fuse_x86.pc" Guid="0568EBCB-782E-4C17-9B64-BAFCC43F64ED">
|
<Component Id="C.fuse_x86.pc" Guid="75637ECD-B3EC-4A19-98B7-9AFAB0722D9A">
|
||||||
<File
|
<File
|
||||||
Id="FILE.fuse_x86.pc"
|
Id="FILE.fuse_x86.pc"
|
||||||
Name="fuse.pc"
|
Name="fuse.pc"
|
||||||
@ -439,7 +485,7 @@
|
|||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On WinArm64 copy fuse3-x64.pc -->
|
<!-- On WinArm64 copy fuse3-x64.pc -->
|
||||||
<Component Id="C.fuse3_a64.pc" Guid="2B6444DB-25E5-45B4-BC61-157D3B992F2B">
|
<Component Id="C.fuse3_a64.pc" Guid="5A69B633-11E4-46E4-8D08-BED1BE7BF4F0">
|
||||||
<File
|
<File
|
||||||
Id="FILE.fuse3_a64.pc"
|
Id="FILE.fuse3_a64.pc"
|
||||||
Name="fuse3.pc"
|
Name="fuse3.pc"
|
||||||
@ -449,7 +495,7 @@
|
|||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win64 copy fuse3-x64.pc -->
|
<!-- On Win64 copy fuse3-x64.pc -->
|
||||||
<Component Id="C.fuse3_x64.pc" Guid="FE59E3BA-E5EA-4822-80B1-19A1DE6B62C7">
|
<Component Id="C.fuse3_x64.pc" Guid="EEAF35B5-5D6C-47D6-BEE3-5E44DD5A294B">
|
||||||
<File
|
<File
|
||||||
Id="FILE.fuse3_x64.pc"
|
Id="FILE.fuse3_x64.pc"
|
||||||
Name="fuse3.pc"
|
Name="fuse3.pc"
|
||||||
@ -459,7 +505,7 @@
|
|||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<!-- On Win32 copy fuse3-x86.pc -->
|
<!-- On Win32 copy fuse3-x86.pc -->
|
||||||
<Component Id="C.fuse3_x86.pc" Guid="176205D0-07EA-4DFC-947F-18E89ABDAFAB">
|
<Component Id="C.fuse3_x86.pc" Guid="476CF5E5-2B8E-4D75-B1A5-FFA8C3DAECB2">
|
||||||
<File
|
<File
|
||||||
Id="FILE.fuse3_x86.pc"
|
Id="FILE.fuse3_x86.pc"
|
||||||
Name="fuse3.pc"
|
Name="fuse3.pc"
|
||||||
@ -737,62 +783,6 @@
|
|||||||
</Component>
|
</Component>
|
||||||
</Directory>
|
</Directory>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="SYMDIR">
|
|
||||||
<Component Id="C.$(var.MyProductFileName)_a64.sys.pdb">
|
|
||||||
<File Name="$(var.MyProductFileName)-a64.sys.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-a64.sys.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.$(var.MyProductFileName)_x64.sys.pdb">
|
|
||||||
<File Name="$(var.MyProductFileName)-x64.sys.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x64.sys.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.$(var.MyProductFileName)_x86.sys.pdb">
|
|
||||||
<File Name="$(var.MyProductFileName)-x86.sys.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x86.sys.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.pdb">
|
|
||||||
<File Name="$(var.MyProductFileName)-a64.dll.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-a64.dll.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.pdb">
|
|
||||||
<File Name="$(var.MyProductFileName)-x64.dll.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x64.dll.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.pdb">
|
|
||||||
<File Name="$(var.MyProductFileName)-x86.dll.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x86.dll.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.launcher_a64.pdb">
|
|
||||||
<File Name="launcher-a64.pdb" Source="..\build\$(var.Configuration)\launcher-a64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.launcher_x64.pdb">
|
|
||||||
<File Name="launcher-x64.pdb" Source="..\build\$(var.Configuration)\launcher-x64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.launcher_x86.pdb">
|
|
||||||
<File Name="launcher-x86.pdb" Source="..\build\$(var.Configuration)\launcher-x86.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.launchctl_a64.pdb">
|
|
||||||
<File Name="launchctl-a64.pdb" Source="..\build\$(var.Configuration)\launchctl-a64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.launchctl_x64.pdb">
|
|
||||||
<File Name="launchctl-x64.pdb" Source="..\build\$(var.Configuration)\launchctl-x64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.launchctl_x86.pdb">
|
|
||||||
<File Name="launchctl-x86.pdb" Source="..\build\$(var.Configuration)\launchctl-x86.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.fsptool_a64.pdb">
|
|
||||||
<File Name="fsptool-a64.pdb" Source="..\build\$(var.Configuration)\fsptool-a64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.fsptool_x64.pdb">
|
|
||||||
<File Name="fsptool-x64.pdb" Source="..\build\$(var.Configuration)\fsptool-x64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.fsptool_x86.pdb">
|
|
||||||
<File Name="fsptool-x86.pdb" Source="..\build\$(var.Configuration)\fsptool-x86.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.memfs_a64.pdb">
|
|
||||||
<File Name="memfs-a64.pdb" Source="..\build\$(var.Configuration)\memfs-a64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.memfs_x64.pdb">
|
|
||||||
<File Name="memfs-x64.pdb" Source="..\build\$(var.Configuration)\memfs-x64.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
<Component Id="C.memfs_x86.pdb">
|
|
||||||
<File Name="memfs-x86.pdb" Source="..\build\$(var.Configuration)\memfs-x86.public.pdb" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
</DirectoryRef>
|
|
||||||
|
|
||||||
<ComponentGroup Id="C.$(var.MyProductName).bin">
|
<ComponentGroup Id="C.$(var.MyProductName).bin">
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_a64.sys" />
|
<ComponentRef Id="C.$(var.MyProductFileName)_a64.sys" />
|
||||||
@ -927,26 +917,6 @@
|
|||||||
<ComponentRef Id="C.notifyfs.vcxproj" />
|
<ComponentRef Id="C.notifyfs.vcxproj" />
|
||||||
<ComponentRef Id="C.notifyfs.vcxproj.filters" />
|
<ComponentRef Id="C.notifyfs.vcxproj.filters" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
<ComponentGroup Id="C.$(var.MyProductName).sym">
|
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_a64.sys.pdb" />
|
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_x64.sys.pdb" />
|
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_x86.sys.pdb" />
|
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_a64.dll.pdb" />
|
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_x64.dll.pdb" />
|
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_x86.dll.pdb" />
|
|
||||||
<ComponentRef Id="C.launcher_a64.pdb" />
|
|
||||||
<ComponentRef Id="C.launcher_x64.pdb" />
|
|
||||||
<ComponentRef Id="C.launcher_x86.pdb" />
|
|
||||||
<ComponentRef Id="C.launchctl_a64.pdb" />
|
|
||||||
<ComponentRef Id="C.launchctl_x64.pdb" />
|
|
||||||
<ComponentRef Id="C.launchctl_x86.pdb" />
|
|
||||||
<ComponentRef Id="C.fsptool_a64.pdb" />
|
|
||||||
<ComponentRef Id="C.fsptool_x64.pdb" />
|
|
||||||
<ComponentRef Id="C.fsptool_x86.pdb" />
|
|
||||||
<ComponentRef Id="C.memfs_a64.pdb" />
|
|
||||||
<ComponentRef Id="C.memfs_x64.pdb" />
|
|
||||||
<ComponentRef Id="C.memfs_x86.pdb" />
|
|
||||||
</ComponentGroup>
|
|
||||||
<ComponentGroup Id="C.$(var.MyProductName).net">
|
<ComponentGroup Id="C.$(var.MyProductName).net">
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_msil.dll" />
|
<ComponentRef Id="C.$(var.MyProductFileName)_msil.dll" />
|
||||||
<ComponentRef Id="C.$(var.MyProductFileName)_msil.xml" />
|
<ComponentRef Id="C.$(var.MyProductFileName)_msil.xml" />
|
||||||
@ -978,6 +948,7 @@
|
|||||||
Absent="disallow">
|
Absent="disallow">
|
||||||
<ComponentRef Id="C.INSTALLDIR" />
|
<ComponentRef Id="C.INSTALLDIR" />
|
||||||
<ComponentRef Id="C.License.txt" />
|
<ComponentRef Id="C.License.txt" />
|
||||||
|
<ComponentRef Id="C.SXSDIR" />
|
||||||
<Feature
|
<Feature
|
||||||
Id="F.User"
|
Id="F.User"
|
||||||
Level="1"
|
Level="1"
|
||||||
@ -1013,7 +984,6 @@
|
|||||||
<ComponentGroupRef Id="C.$(var.MyProductName).lib" />
|
<ComponentGroupRef Id="C.$(var.MyProductName).lib" />
|
||||||
<ComponentGroupRef Id="C.$(var.MyProductName).smp" />
|
<ComponentGroupRef Id="C.$(var.MyProductName).smp" />
|
||||||
<ComponentGroupRef Id="C.$(var.MyProductName).smp.net" />
|
<ComponentGroupRef Id="C.$(var.MyProductName).smp.net" />
|
||||||
<ComponentGroupRef Id="C.$(var.MyProductName).sym" />
|
|
||||||
</Feature>
|
</Feature>
|
||||||
<Feature
|
<Feature
|
||||||
Id="F.KernelDeveloper"
|
Id="F.KernelDeveloper"
|
||||||
@ -1056,7 +1026,24 @@
|
|||||||
Order="10">NOT Installed</Publish>
|
Order="10">NOT Installed</Publish>
|
||||||
</UI>
|
</UI>
|
||||||
|
|
||||||
|
<!-- Custom Actions -->
|
||||||
<Binary Id="CustomActions" SourceFile="..\build\$(var.Configuration)\CustomActions.dll" />
|
<Binary Id="CustomActions" SourceFile="..\build\$(var.Configuration)\CustomActions.dll" />
|
||||||
|
|
||||||
|
<!-- InstanceID computes a unique per-installer-run ID -->
|
||||||
|
<CustomAction
|
||||||
|
Id="Action.InstanceID"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="InstanceID"
|
||||||
|
Execute="firstSequence"
|
||||||
|
Return="check" />
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<Custom Action="Action.InstanceID" Before="AppSearch" />
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
<InstallUISequence>
|
||||||
|
<Custom Action="Action.InstanceID" Before="AppSearch" />
|
||||||
|
</InstallUISequence>
|
||||||
|
|
||||||
|
<!-- ServiceRunning determines if the old driver (that did not support unload) is running. -->
|
||||||
<CustomAction
|
<CustomAction
|
||||||
Id="Params.ServiceRunning"
|
Id="Params.ServiceRunning"
|
||||||
Property="ServiceRunning"
|
Property="ServiceRunning"
|
||||||
@ -1069,16 +1056,109 @@
|
|||||||
Return="ignore" />
|
Return="ignore" />
|
||||||
<CustomAction
|
<CustomAction
|
||||||
Id="Action.ServiceRunning.Error"
|
Id="Action.ServiceRunning.Error"
|
||||||
Error="The $(var.MyProductName) service appears to be running. If you just uninstalled $(var.MyProductName) please restart your computer. If you are running a development version of $(var.MyProductName) please remove it before proceeding." />
|
Error="A component from an older version of $(var.MyProductName) that cannot be upgraded appears to be running. If you just uninstalled an older version of $(var.MyProductName) please restart your computer." />
|
||||||
<InstallExecuteSequence>
|
<InstallExecuteSequence>
|
||||||
<Custom Action="Params.ServiceRunning" Before="Action.ServiceRunning" />
|
<Custom Action="Params.ServiceRunning" Before="Action.ServiceRunning" />
|
||||||
<Custom Action="Action.ServiceRunning" Before="LaunchConditions" />
|
<Custom Action="Action.ServiceRunning" After="LaunchConditions">
|
||||||
|
<![CDATA[NOT Installed]]>
|
||||||
|
</Custom>
|
||||||
<Custom Action="Action.ServiceRunning.Error" After="Action.ServiceRunning">
|
<Custom Action="Action.ServiceRunning.Error" After="Action.ServiceRunning">
|
||||||
<![CDATA[NOT Installed AND (0 <> ServiceRunning)]]>
|
<![CDATA[NOT Installed AND (0 <> ServiceRunning)]]>
|
||||||
</Custom>
|
</Custom>
|
||||||
<ScheduleReboot After="RemoveFiles">
|
|
||||||
<![CDATA[(REMOVE ~= "ALL") AND (0 <> ServiceRunning)]]>
|
|
||||||
</ScheduleReboot>
|
|
||||||
</InstallExecuteSequence>
|
</InstallExecuteSequence>
|
||||||
|
<InstallUISequence>
|
||||||
|
<Custom Action="Params.ServiceRunning" Before="Action.ServiceRunning" />
|
||||||
|
<Custom Action="Action.ServiceRunning" After="LaunchConditions">
|
||||||
|
<![CDATA[NOT Installed]]>
|
||||||
|
</Custom>
|
||||||
|
<Custom Action="Action.ServiceRunning.Error" After="Action.ServiceRunning">
|
||||||
|
<![CDATA[NOT Installed AND (0 <> ServiceRunning)]]>
|
||||||
|
</Custom>
|
||||||
|
</InstallUISequence>
|
||||||
|
|
||||||
|
<!-- InstallSymlinks installs SxS symlinks -->
|
||||||
|
<SetProperty
|
||||||
|
Id="Deferred.InstallSymlinks"
|
||||||
|
Value='InstallJunctions "[INSTALLDIR]\" "[SXSDIR]\" bin'
|
||||||
|
Before="Deferred.InstallSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Deferred.InstallSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="deferred"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="check" />
|
||||||
|
<SetProperty
|
||||||
|
Id="Rollback.InstallSymlinks"
|
||||||
|
Value='RemoveFiles "[INSTALLDIR]\" bin'
|
||||||
|
Before="Rollback.InstallSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Rollback.InstallSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="rollback"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="ignore" />
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<!--
|
||||||
|
deferred: `InstallSymlinks` on install or repair
|
||||||
|
rollback: `RemoveSymlinks` on install only
|
||||||
|
-->
|
||||||
|
<Custom Action="Rollback.InstallSymlinks" After="InstallFiles">
|
||||||
|
NOT Installed
|
||||||
|
</Custom>
|
||||||
|
<Custom Action="Deferred.InstallSymlinks" After="Rollback.InstallSymlinks">
|
||||||
|
(NOT Installed) OR REINSTALL
|
||||||
|
</Custom>
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
|
<!-- RemoveSymlinks removes SxS symlinks -->
|
||||||
|
<SetProperty
|
||||||
|
Id="Deferred.RemoveSymlinks"
|
||||||
|
Value='RemoveFiles "[INSTALLDIR]\" bin'
|
||||||
|
Before="Deferred.RemoveSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Deferred.RemoveSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="deferred"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="ignore" />
|
||||||
|
<SetProperty
|
||||||
|
Id="Rollback.RemoveSymlinks"
|
||||||
|
Value='InstallJunctions "[INSTALLDIR]\" "[SXSDIR]\" bin'
|
||||||
|
Before="Rollback.RemoveSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Rollback.RemoveSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="rollback"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="check" />
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<!--
|
||||||
|
deferred: `RemoveSymlinks` on uninstall
|
||||||
|
rollback: `InstallSymlinks` on uninstall
|
||||||
|
-->
|
||||||
|
<Custom Action="Rollback.RemoveSymlinks" Before="RemoveFiles">
|
||||||
|
REMOVE ~= "ALL"
|
||||||
|
</Custom>
|
||||||
|
<Custom Action="Deferred.RemoveSymlinks" After="Rollback.RemoveSymlinks">
|
||||||
|
REMOVE ~= "ALL"
|
||||||
|
</Custom>
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Specify WIXFAILWHENDEFERRED=1 on the msiexec cmdline for rollback testing.
|
||||||
|
See http://tinyurl.com/yxkaywek
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<Property Id="WIXFAILWHENDEFERRED" Value="0" Secure="yes" />
|
||||||
|
<CustomActionRef Id="WixFailWhenDeferred" />
|
||||||
|
-->
|
||||||
</Product>
|
</Product>
|
||||||
</Wix>
|
</Wix>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<SuppressAllWarnings>False</SuppressAllWarnings>
|
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||||
<Pedantic>True</Pedantic>
|
<Pedantic>True</Pedantic>
|
||||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||||
<SuppressIces>ICE30</SuppressIces>
|
<SuppressIces>ICE30;ICE61</SuppressIces>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
@ -29,12 +29,16 @@
|
|||||||
<SuppressAllWarnings>False</SuppressAllWarnings>
|
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||||
<Pedantic>True</Pedantic>
|
<Pedantic>True</Pedantic>
|
||||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||||
<SuppressIces>ICE30</SuppressIces>
|
<SuppressIces>ICE30;ICE61</SuppressIces>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Product.wxs" />
|
<Compile Include="Product.wxs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<WixExtension Include="WixUtilExtension">
|
||||||
|
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
|
||||||
|
<Name>WixUtilExtension</Name>
|
||||||
|
</WixExtension>
|
||||||
<WixExtension Include="WixUIExtension">
|
<WixExtension Include="WixUIExtension">
|
||||||
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
||||||
<Name>WixUIExtension</Name>
|
<Name>WixUIExtension</Name>
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project>
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<PropertyGroup>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(MSBuildProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
|
||||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.common.props))/build.common.props" />
|
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.common.props))/build.common.props" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProjectGuid>{4920E350-D496-4652-AE98-6C4208AEC1D8}</ProjectGuid>
|
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<ProjectName>memfs-dotnet</ProjectName>
|
<ProjectName>memfs-dotnet</ProjectName>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>memfs</RootNamespace>
|
<RootNamespace>memfs</RootNamespace>
|
||||||
<AssemblyName>memfs-dotnet-msil</AssemblyName>
|
<AssemblyName>memfs-dotnet-msil</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
<TargetFramework>net452</TargetFramework>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
|
||||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
@ -33,32 +36,16 @@
|
|||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
|
||||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<ProjectReference Include="..\dotnet\winfsp.net.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\..\..\tst\memfs-dotnet\Program.cs">
|
<Compile Include="..\..\..\tst\memfs-dotnet\Program.cs" />
|
||||||
<Link>Program.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||||
<ProjectReference Include="..\dotnet\winfsp.net.csproj">
|
|
||||||
<Project>{94580219-cc8d-4fe5-a3be-437b0b3481e1}</Project>
|
|
||||||
<Name>winfsp.net</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
</Project>
|
@ -284,6 +284,7 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\loadun-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\volpath-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\volpath-test.c" />
|
||||||
|
@ -112,6 +112,9 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\notify-test.c">
|
<ClCompile Include="..\..\..\tst\winfsp-tests\notify-test.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\loadun-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||||
|
@ -73,8 +73,10 @@
|
|||||||
<ClCompile Include="..\..\src\dll\ntstatus.c" />
|
<ClCompile Include="..\..\src\dll\ntstatus.c" />
|
||||||
<ClCompile Include="..\..\src\dll\path.c" />
|
<ClCompile Include="..\..\src\dll\path.c" />
|
||||||
<ClCompile Include="..\..\src\dll\service.c" />
|
<ClCompile Include="..\..\src\dll\service.c" />
|
||||||
|
<ClCompile Include="..\..\src\dll\sxs.c" />
|
||||||
<ClCompile Include="..\..\src\dll\util.c" />
|
<ClCompile Include="..\..\src\dll\util.c" />
|
||||||
<ClCompile Include="..\..\src\dll\wksid.c" />
|
<ClCompile Include="..\..\src\dll\wksid.c" />
|
||||||
|
<ClCompile Include="..\..\src\shared\ku\mountmgr.c" />
|
||||||
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -287,7 +289,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -314,7 +316,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -341,7 +343,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -371,7 +373,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
@ -402,7 +404,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
@ -433,7 +435,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -175,6 +175,12 @@
|
|||||||
<ClCompile Include="..\..\src\dll\debug.c">
|
<ClCompile Include="..\..\src\dll\debug.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\shared\ku\mountmgr.c">
|
||||||
|
<Filter>Source\shared\ku</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\sxs.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\dll\library.def">
|
<None Include="..\..\src\dll\library.def">
|
||||||
|
@ -228,6 +228,7 @@
|
|||||||
<FilesToPackage Include="$(TargetPath)" />
|
<FilesToPackage Include="$(TargetPath)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\src\shared\ku\mountmgr.c" />
|
||||||
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
||||||
<ClCompile Include="..\..\src\shared\ku\uuid5.c" />
|
<ClCompile Include="..\..\src\shared\ku\uuid5.c" />
|
||||||
<ClCompile Include="..\..\src\sys\cleanup.c" />
|
<ClCompile Include="..\..\src\sys\cleanup.c" />
|
||||||
@ -259,6 +260,7 @@
|
|||||||
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
||||||
<ClCompile Include="..\..\src\sys\silo.c" />
|
<ClCompile Include="..\..\src\sys\silo.c" />
|
||||||
<ClCompile Include="..\..\src\sys\statistics.c" />
|
<ClCompile Include="..\..\src\sys\statistics.c" />
|
||||||
|
<ClCompile Include="..\..\src\sys\sxs.c" />
|
||||||
<ClCompile Include="..\..\src\sys\trace.c" />
|
<ClCompile Include="..\..\src\sys\trace.c" />
|
||||||
<ClCompile Include="..\..\src\sys\util.c" />
|
<ClCompile Include="..\..\src\sys\util.c" />
|
||||||
<ClCompile Include="..\..\src\sys\volinfo.c" />
|
<ClCompile Include="..\..\src\sys\volinfo.c" />
|
||||||
@ -289,6 +291,9 @@
|
|||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
set CatalogFile=driver-$(MyProductFileArch).cat
|
set CatalogFile=driver-$(MyProductFileArch).cat
|
||||||
|
if "$(MyProductFileArch)"=="a64" set ArchDecoration=ntarm64
|
||||||
|
if "$(MyProductFileArch)"=="x64" set ArchDecoration=ntamd64
|
||||||
|
if "$(MyProductFileArch)"=="x86" set ArchDecoration=ntx86
|
||||||
|
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
||||||
@ -302,6 +307,9 @@ stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(MyProductFileArch).inf</Comma
|
|||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
set CatalogFile=driver-$(MyProductFileArch).cat
|
set CatalogFile=driver-$(MyProductFileArch).cat
|
||||||
|
if "$(MyProductFileArch)"=="a64" set ArchDecoration=ntarm64
|
||||||
|
if "$(MyProductFileArch)"=="x64" set ArchDecoration=ntamd64
|
||||||
|
if "$(MyProductFileArch)"=="x86" set ArchDecoration=ntx86
|
||||||
|
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
||||||
@ -315,6 +323,9 @@ stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(MyProductFileArch).inf</Comma
|
|||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
set CatalogFile=driver-$(MyProductFileArch).cat
|
set CatalogFile=driver-$(MyProductFileArch).cat
|
||||||
|
if "$(MyProductFileArch)"=="a64" set ArchDecoration=ntarm64
|
||||||
|
if "$(MyProductFileArch)"=="x64" set ArchDecoration=ntamd64
|
||||||
|
if "$(MyProductFileArch)"=="x86" set ArchDecoration=ntx86
|
||||||
|
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
||||||
@ -327,6 +338,9 @@ stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(MyProductFileArch).inf</Comma
|
|||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
set CatalogFile=driver-$(MyProductFileArch).cat
|
set CatalogFile=driver-$(MyProductFileArch).cat
|
||||||
|
if "$(MyProductFileArch)"=="a64" set ArchDecoration=ntarm64
|
||||||
|
if "$(MyProductFileArch)"=="x64" set ArchDecoration=ntamd64
|
||||||
|
if "$(MyProductFileArch)"=="x86" set ArchDecoration=ntx86
|
||||||
|
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
||||||
@ -341,6 +355,9 @@ stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(MyProductFileArch).inf</Comma
|
|||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
set CatalogFile=driver-$(MyProductFileArch).cat
|
set CatalogFile=driver-$(MyProductFileArch).cat
|
||||||
|
if "$(MyProductFileArch)"=="a64" set ArchDecoration=ntarm64
|
||||||
|
if "$(MyProductFileArch)"=="x64" set ArchDecoration=ntamd64
|
||||||
|
if "$(MyProductFileArch)"=="x86" set ArchDecoration=ntx86
|
||||||
|
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
||||||
@ -353,6 +370,9 @@ stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(MyProductFileArch).inf</Comma
|
|||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
set CatalogFile=driver-$(MyProductFileArch).cat
|
set CatalogFile=driver-$(MyProductFileArch).cat
|
||||||
|
if "$(MyProductFileArch)"=="a64" set ArchDecoration=ntarm64
|
||||||
|
if "$(MyProductFileArch)"=="x64" set ArchDecoration=ntamd64
|
||||||
|
if "$(MyProductFileArch)"=="x86" set ArchDecoration=ntx86
|
||||||
|
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
if exist $(OutDir)driver-$(MyProductFileArch).inf del $(OutDir)driver-$(MyProductFileArch).inf
|
||||||
|
@ -131,6 +131,12 @@
|
|||||||
<ClCompile Include="..\..\src\sys\devtimer.c">
|
<ClCompile Include="..\..\src\sys\devtimer.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\shared\ku\mountmgr.c">
|
||||||
|
<Filter>Source\shared\ku</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\sys\sxs.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\sys\driver.h">
|
<ClInclude Include="..\..\src\sys\driver.h">
|
||||||
|
@ -11,6 +11,7 @@ This document contains a list of known open-source file systems and file system
|
|||||||
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
||||||
- https://github.com/sganis/golddrive[golddrive] - Windows ssh network drive
|
- https://github.com/sganis/golddrive[golddrive] - Windows ssh network drive
|
||||||
- https://github.com/winfsp/hubfs[hubfs] - File system for GitHub
|
- https://github.com/winfsp/hubfs[hubfs] - File system for GitHub
|
||||||
|
- https://github.com/juicedata/juicefs[JuiceFS] - a distributed POSIX file system built on top of Redis and S3
|
||||||
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
||||||
- https://github.com/winfsp/nfs-win[nfs-win] - NFS for Windows
|
- https://github.com/winfsp/nfs-win[nfs-win] - NFS for Windows
|
||||||
- https://github.com/winfsp/objfs[objfs] - Object Storage File System
|
- https://github.com/winfsp/objfs[objfs] - Object Storage File System
|
||||||
@ -33,3 +34,4 @@ This document contains a list of known open-source file systems and file system
|
|||||||
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
||||||
- https://github.com/pleiszenburg/refuse[Python: refuse] - Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
- https://github.com/pleiszenburg/refuse[Python: refuse] - Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||||
- https://github.com/Scille/winfspy[Python: winfspy] - WinFSP binding for Python
|
- https://github.com/Scille/winfspy[Python: winfspy] - WinFSP binding for Python
|
||||||
|
- https://github.com/SnowflakePowered/winfsp-rs[Rust: winfsp-rs] - WinFSP binding for Rust
|
||||||
|
@ -71,6 +71,8 @@ Primary registry key used to store WinFsp settings. On a 64-bit system (x64 or A
|
|||||||
|
|
||||||
* `MountDoNotUseLauncher (REG_DWORD)`: A value of 1 disallows the use of the Launcher for drive mounting. The default value of 0 allows use of the Launcher for drive mounting when necessary. In general the Launcher is not necessary for mounting. However when running a file system in the Windows Service context (session 0) under an account that is not LocalSystem (e.g. `NT AUTHORITY\NETWORK SERVICE`), the Launcher is used to create global drives.
|
* `MountDoNotUseLauncher (REG_DWORD)`: A value of 1 disallows the use of the Launcher for drive mounting. The default value of 0 allows use of the Launcher for drive mounting when necessary. In general the Launcher is not necessary for mounting. However when running a file system in the Windows Service context (session 0) under an account that is not LocalSystem (e.g. `NT AUTHORITY\NETWORK SERVICE`), the Launcher is used to create global drives.
|
||||||
|
|
||||||
|
* `MountUseMountmgrFromFSD (REG_DWORD)`: A value of 1 instructs WinFsp to use the Mount Manager from the FSD (File System Driver) which runs in kernel mode. The default value of 0 instructs WinFsp to use the Mount Manager from the DLL which runs in user mode. Using the Mount Manager from user mode requires Administrator access and this setting allows a file system to circumvent the Administrator access requirement. This setting is not recommended for general use.
|
||||||
|
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
@ -538,7 +538,8 @@ static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo
|
|||||||
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
||||||
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
||||||
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
||||||
FileInfo->IndexNumber = 0;
|
FileInfo->IndexNumber =
|
||||||
|
((UINT64)ByHandleFileInfo.nFileIndexHigh << 32) | (UINT64)ByHandleFileInfo.nFileIndexLow;
|
||||||
FileInfo->HardLinks = 0;
|
FileInfo->HardLinks = 0;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -91,6 +91,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
|||||||
/* fsctl device codes */
|
/* fsctl device codes */
|
||||||
#define FSP_FSCTL_MOUNTDEV \
|
#define FSP_FSCTL_MOUNTDEV \
|
||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define FSP_FSCTL_MOUNTMGR \
|
||||||
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'm', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
#define FSP_FSCTL_VOLUME_NAME \
|
#define FSP_FSCTL_VOLUME_NAME \
|
||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
#define FSP_FSCTL_VOLUME_LIST \
|
#define FSP_FSCTL_VOLUME_LIST \
|
||||||
@ -109,6 +111,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
|||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 's', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 's', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
#define FSP_FSCTL_NOTIFY \
|
#define FSP_FSCTL_NOTIFY \
|
||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'n', METHOD_NEITHER, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'n', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||||
|
#define FSP_FSCTL_UNLOAD \
|
||||||
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'U', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
/* fsctl internal device codes (usable only in-kernel) */
|
/* fsctl internal device codes (usable only in-kernel) */
|
||||||
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
||||||
@ -226,7 +230,7 @@ enum
|
|||||||
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
|
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
|
||||||
UINT32 WslFeatures:1; /* support features required for WSLinux */\
|
UINT32 WslFeatures:1; /* support features required for WSLinux */\
|
||||||
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
||||||
UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\
|
UINT32 RejectIrpPriorToTransact0:1; /* DEPRECATED: reject IRP's prior to FspFsctlTransact0 */\
|
||||||
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
|
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
|
||||||
UINT32 PostDispositionWhenNecessaryOnly:1; /* post Disposition for dirs or READONLY attr check */\
|
UINT32 PostDispositionWhenNecessaryOnly:1; /* post Disposition for dirs or READONLY attr check */\
|
||||||
UINT32 KmReservedFlags:1;\
|
UINT32 KmReservedFlags:1;\
|
||||||
@ -679,6 +683,8 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
|||||||
PHANDLE PVolumeHandle);
|
PHANDLE PVolumeHandle);
|
||||||
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
||||||
BOOLEAN Persistent, GUID *UniqueId);
|
BOOLEAN Persistent, GUID *UniqueId);
|
||||||
|
FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
|
||||||
|
PWSTR MountPoint);
|
||||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||||
@ -690,6 +696,11 @@ FSP_API NTSTATUS FspFsctlNotify(HANDLE VolumeHandle,
|
|||||||
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
||||||
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
|
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
|
||||||
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath);
|
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath);
|
||||||
|
FSP_API NTSTATUS FspFsctlStartService(VOID);
|
||||||
|
FSP_API NTSTATUS FspFsctlStopService(VOID);
|
||||||
|
FSP_API NTSTATUS FspFsctlEnumServices(
|
||||||
|
VOID (*EnumFn)(PVOID Context, PWSTR ServiceName, BOOLEAN Running),
|
||||||
|
PVOID Context);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -1047,11 +1047,49 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
|
|
||||||
NTSTATUS (*Obsolete0)(VOID);
|
NTSTATUS (*Obsolete0)(VOID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inform the file system that its dispatcher has been stopped.
|
||||||
|
*
|
||||||
|
* Prior to WinFsp v2.0 the FSD would never unmount a file system volume unless
|
||||||
|
* the user mode file system requested the unmount. Since WinFsp v2.0 it is possible
|
||||||
|
* for the FSD to unmount a file system volume without an explicit user mode file system
|
||||||
|
* request. For example, this happens when the FSD is being uninstalled.
|
||||||
|
*
|
||||||
|
* A user mode file system can use this operation to determine when its dispatcher
|
||||||
|
* has been stopped. The Normally parameter can be used to determine why the dispatcher
|
||||||
|
* was stopped: it is TRUE when the file system is being stopped via
|
||||||
|
* FspFileSystemStopDispatcher and FALSE otherwise.
|
||||||
|
*
|
||||||
|
* When the file system receives a request with Normally == TRUE it need not take any
|
||||||
|
* extra steps. This case is the same as for pre-v2.0 versions: since the file system
|
||||||
|
* stopped the dispatcher via FspFileSystemStopDispatcher, it will likely exit its
|
||||||
|
* process soon.
|
||||||
|
*
|
||||||
|
* When the file system receives a request with Normally == FALSE it may need to take
|
||||||
|
* extra steps to exit its process as this is not done by default.
|
||||||
|
*
|
||||||
|
* A file system that uses the FspService infrastructure may use the
|
||||||
|
* FspFileSystemStopServiceIfNecessary API to correctly handle all cases.
|
||||||
|
*
|
||||||
|
* This operation is the last one that a file system will receive.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system on which this request is posted.
|
||||||
|
* @param Normally
|
||||||
|
* TRUE if the file system is being stopped via FspFileSystemStopDispatcher.
|
||||||
|
* FALSE if the file system is being stopped because of another reason such
|
||||||
|
* as driver unload/uninstall.
|
||||||
|
* @see
|
||||||
|
* FspFileSystemStopServiceIfNecessary
|
||||||
|
*/
|
||||||
|
VOID (*DispatcherStopped)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
BOOLEAN Normally);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This ensures that this interface will always contain 64 function pointers.
|
* This ensures that this interface will always contain 64 function pointers.
|
||||||
* Please update when changing the interface as it is important for future compatibility.
|
* Please update when changing the interface as it is important for future compatibility.
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*Reserved[32])();
|
NTSTATUS (*Reserved[31])();
|
||||||
} FSP_FILE_SYSTEM_INTERFACE;
|
} FSP_FILE_SYSTEM_INTERFACE;
|
||||||
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
||||||
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
||||||
@ -1074,7 +1112,8 @@ typedef struct _FSP_FILE_SYSTEM
|
|||||||
SRWLOCK OpGuardLock;
|
SRWLOCK OpGuardLock;
|
||||||
BOOLEAN UmFileContextIsUserContext2, UmFileContextIsFullContext;
|
BOOLEAN UmFileContextIsUserContext2, UmFileContextIsFullContext;
|
||||||
UINT16 UmNoReparsePointsDirCheck:1;
|
UINT16 UmNoReparsePointsDirCheck:1;
|
||||||
UINT16 UmReservedFlags:15;
|
UINT16 UmReservedFlags:14;
|
||||||
|
UINT16 DispatcherStopping:1;
|
||||||
} FSP_FILE_SYSTEM;
|
} FSP_FILE_SYSTEM;
|
||||||
FSP_FSCTL_STATIC_ASSERT(
|
FSP_FSCTL_STATIC_ASSERT(
|
||||||
(4 == sizeof(PVOID) && 660 == sizeof(FSP_FILE_SYSTEM)) ||
|
(4 == sizeof(PVOID) && 660 == sizeof(FSP_FILE_SYSTEM)) ||
|
||||||
@ -1108,7 +1147,7 @@ FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
|
|||||||
* @param VolumeParams
|
* @param VolumeParams
|
||||||
* Volume parameters for the newly created file system.
|
* Volume parameters for the newly created file system.
|
||||||
* @param Interface
|
* @param Interface
|
||||||
* A pointer to the actual operations that actually implement this user mode file system.
|
* A pointer to the operations that implement this user mode file system.
|
||||||
* @param PFileSystem [out]
|
* @param PFileSystem [out]
|
||||||
* Pointer that will receive the file system object created on successful return from this
|
* Pointer that will receive the file system object created on successful return from this
|
||||||
* call.
|
* call.
|
||||||
@ -1746,6 +1785,23 @@ UINT32 FspFileSystemGetEaPackedSize(PFILE_FULL_EA_INFORMATION SingleEa)
|
|||||||
*/
|
*/
|
||||||
FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
||||||
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
|
/**
|
||||||
|
* Stop a file system service, if any.
|
||||||
|
*
|
||||||
|
* This is a helper for implementing the DispatcherStopped operation, but only for file systems
|
||||||
|
* that use the FspService infrastructure.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system object.
|
||||||
|
* @param Normally
|
||||||
|
* TRUE if the file system is being stopped via FspFileSystemStopDispatcher.
|
||||||
|
* FALSE if the file system is being stopped because of another reason such
|
||||||
|
* as driver unload/uninstall.
|
||||||
|
* @see
|
||||||
|
* DispatcherStopped
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspFileSystemStopServiceIfNecessary(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
BOOLEAN Normally);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Directory buffering
|
* Directory buffering
|
||||||
@ -2043,6 +2099,8 @@ FSP_API ULONG FspServiceGetExitCode(FSP_SERVICE *Service);
|
|||||||
* to connect the service process to the Service Control Manager. If the Service Control Manager is
|
* to connect the service process to the Service Control Manager. If the Service Control Manager is
|
||||||
* not available (and console mode is allowed) it will enter console mode.
|
* not available (and console mode is allowed) it will enter console mode.
|
||||||
*
|
*
|
||||||
|
* This function should be called once per process.
|
||||||
|
*
|
||||||
* @param Service
|
* @param Service
|
||||||
* The service object.
|
* The service object.
|
||||||
* @return
|
* @return
|
||||||
@ -2120,6 +2178,7 @@ FSP_API NTSTATUS FspCallNamedPipeSecurelyEx(PWSTR PipeName,
|
|||||||
PULONG PBytesTransferred, ULONG Timeout, BOOLEAN AllowImpersonation,
|
PULONG PBytesTransferred, ULONG Timeout, BOOLEAN AllowImpersonation,
|
||||||
PSID Sid);
|
PSID Sid);
|
||||||
FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
|
FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
|
||||||
|
FSP_API PWSTR FspSxsIdent(VOID);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delay load
|
* Delay load
|
||||||
|
@ -100,9 +100,11 @@ NTSTATUS FspEventLogRegister(VOID)
|
|||||||
WCHAR Path[MAX_PATH];
|
WCHAR Path[MAX_PATH];
|
||||||
DWORD RegResult, DwordValue;
|
DWORD RegResult, DwordValue;
|
||||||
HKEY RegKey;
|
HKEY RegKey;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
Result = FspGetModuleFileName(DllInstance, Path, MAX_PATH, L"" MyEventLogRegisterPath);
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
RegResult = RegCreateKeyExW(
|
RegResult = RegCreateKeyExW(
|
||||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" FSP_EVENTLOG_NAME,
|
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" FSP_EVENTLOG_NAME,
|
||||||
|
32
src/dll/fs.c
32
src/dll/fs.c
@ -358,6 +358,21 @@ exit:
|
|||||||
CloseHandle(DispatcherThread);
|
CloseHandle(DispatcherThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GetCurrentThreadId() == GetThreadId(FileSystem->DispatcherThread))
|
||||||
|
{
|
||||||
|
if (0 != FileSystem->Interface->DispatcherStopped)
|
||||||
|
{
|
||||||
|
/* Normally = !!FileSystem->DispatcherStopping */
|
||||||
|
BOOLEAN Normally = !!(
|
||||||
|
_InterlockedOr16(
|
||||||
|
(PVOID)((PUINT8)&FileSystem->UmFileContextIsFullContext +
|
||||||
|
sizeof(FileSystem->UmFileContextIsFullContext)),
|
||||||
|
0) &
|
||||||
|
0x8000);
|
||||||
|
FileSystem->Interface->DispatcherStopped(FileSystem, Normally);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,6 +406,11 @@ FSP_API NTSTATUS FspFileSystemStartDispatcher(FSP_FILE_SYSTEM *FileSystem, ULONG
|
|||||||
if (0 == FileSystem->DispatcherThread)
|
if (0 == FileSystem->DispatcherThread)
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
#if defined(FSP_CFG_REJECT_EARLY_IRP)
|
||||||
|
FspFsctlTransact(FileSystem->VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||||
|
/* send a Transact0 to inform the FSD that the dispatcher is _almost_ ready */
|
||||||
|
#endif
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,6 +419,12 @@ FSP_API VOID FspFileSystemStopDispatcher(FSP_FILE_SYSTEM *FileSystem)
|
|||||||
if (0 == FileSystem->DispatcherThread)
|
if (0 == FileSystem->DispatcherThread)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* FileSystem->DispatcherStopping = 1 */
|
||||||
|
_InterlockedOr16(
|
||||||
|
(PVOID)((PUINT8)&FileSystem->UmFileContextIsFullContext +
|
||||||
|
sizeof(FileSystem->UmFileContextIsFullContext)),
|
||||||
|
0x8000);
|
||||||
|
|
||||||
FspFsctlStop0(FileSystem->VolumeHandle);
|
FspFsctlStop0(FileSystem->VolumeHandle);
|
||||||
|
|
||||||
WaitForSingleObject(FileSystem->DispatcherThread, INFINITE);
|
WaitForSingleObject(FileSystem->DispatcherThread, INFINITE);
|
||||||
@ -406,6 +432,12 @@ FSP_API VOID FspFileSystemStopDispatcher(FSP_FILE_SYSTEM *FileSystem)
|
|||||||
FileSystem->DispatcherThread = 0;
|
FileSystem->DispatcherThread = 0;
|
||||||
|
|
||||||
FspFsctlStop(FileSystem->VolumeHandle);
|
FspFsctlStop(FileSystem->VolumeHandle);
|
||||||
|
|
||||||
|
/* FileSystem->DispatcherStopping = 0 */
|
||||||
|
_InterlockedAnd16(
|
||||||
|
(PVOID)((PUINT8)&FileSystem->UmFileContextIsFullContext +
|
||||||
|
sizeof(FileSystem->UmFileContextIsFullContext)),
|
||||||
|
0x7fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
433
src/dll/fsctl.c
433
src/dll/fsctl.c
@ -32,19 +32,21 @@ static DWORD FspFsctlTransactCode = FSP_FSCTL_TRANSACT;
|
|||||||
static DWORD FspFsctlTransactBatchCode = FSP_FSCTL_TRANSACT_BATCH;
|
static DWORD FspFsctlTransactBatchCode = FSP_FSCTL_TRANSACT_BATCH;
|
||||||
|
|
||||||
static VOID FspFsctlServiceVersion(PUINT32 PVersion);
|
static VOID FspFsctlServiceVersion(PUINT32 PVersion);
|
||||||
static NTSTATUS FspFsctlStartService(VOID);
|
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||||
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
||||||
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
|
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
|
||||||
PHANDLE PVolumeHandle)
|
PHANDLE PVolumeHandle)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
WCHAR SxsDevicePathBuf[MAX_PATH];
|
||||||
PWSTR DeviceRoot;
|
PWSTR DeviceRoot;
|
||||||
SIZE_T DeviceRootSize, DevicePathSize, VolumeParamsSize;
|
SIZE_T DeviceRootSize, DevicePathSize, VolumeParamsSize;
|
||||||
WCHAR DevicePathBuf[MAX_PATH + sizeof *VolumeParams], *DevicePathPtr, *DevicePathEnd;
|
WCHAR DevicePathBuf[MAX_PATH + sizeof *VolumeParams], *DevicePathPtr, *DevicePathEnd;
|
||||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||||
DWORD Bytes;
|
DWORD Bytes;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
DevicePath = FspSxsAppendSuffix(SxsDevicePathBuf, sizeof SxsDevicePathBuf, DevicePath);
|
||||||
|
|
||||||
if (sizeof(WCHAR) <= VolumeNameSize)
|
if (sizeof(WCHAR) <= VolumeNameSize)
|
||||||
VolumeNameBuf[0] = L'\0';
|
VolumeNameBuf[0] = L'\0';
|
||||||
@ -130,6 +132,22 @@ FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
|
||||||
|
PWSTR MountPoint)
|
||||||
|
{
|
||||||
|
DWORD Bytes;
|
||||||
|
|
||||||
|
Bytes = 0 != MountPoint ? lstrlenW(MountPoint) * sizeof(WCHAR) : 0;
|
||||||
|
|
||||||
|
if (!DeviceIoControl(VolumeHandle,
|
||||||
|
FSP_FSCTL_MOUNTMGR,
|
||||||
|
MountPoint, Bytes, 0, 0,
|
||||||
|
&Bytes, 0))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||||
@ -213,12 +231,15 @@ exit:
|
|||||||
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
||||||
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize)
|
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
WCHAR SxsDevicePathBuf[MAX_PATH];
|
||||||
PWSTR DeviceRoot;
|
PWSTR DeviceRoot;
|
||||||
SIZE_T DeviceRootSize, DevicePathSize;
|
SIZE_T DeviceRootSize, DevicePathSize;
|
||||||
WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr;
|
WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr;
|
||||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||||
DWORD Bytes;
|
DWORD Bytes;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
DevicePath = FspSxsAppendSuffix(SxsDevicePathBuf, sizeof SxsDevicePathBuf, DevicePath);
|
||||||
|
|
||||||
/* check lengths; everything must fit within MAX_PATH */
|
/* check lengths; everything must fit within MAX_PATH */
|
||||||
DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
|
DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
|
||||||
@ -282,16 +303,71 @@ FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsctlUnload(PWSTR DevicePath)
|
||||||
|
{
|
||||||
|
WCHAR SxsDevicePathBuf[MAX_PATH];
|
||||||
|
PWSTR DeviceRoot;
|
||||||
|
SIZE_T DeviceRootSize, DevicePathSize;
|
||||||
|
WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr;
|
||||||
|
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD Bytes;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
DevicePath = FspSxsAppendSuffix(SxsDevicePathBuf, sizeof SxsDevicePathBuf, DevicePath);
|
||||||
|
|
||||||
|
/* check lengths; everything must fit within MAX_PATH */
|
||||||
|
DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
|
||||||
|
DeviceRootSize = lstrlenW(DeviceRoot) * sizeof(WCHAR);
|
||||||
|
DevicePathSize = lstrlenW(DevicePath) * sizeof(WCHAR);
|
||||||
|
if (DeviceRootSize + DevicePathSize + sizeof(WCHAR) > sizeof DevicePathBuf)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
/* prepare the device path to be opened */
|
||||||
|
DevicePathPtr = DevicePathBuf;
|
||||||
|
memcpy(DevicePathPtr, DeviceRoot, DeviceRootSize);
|
||||||
|
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DeviceRootSize);
|
||||||
|
memcpy(DevicePathPtr, DevicePath, DevicePathSize);
|
||||||
|
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DevicePathSize);
|
||||||
|
*DevicePathPtr = L'\0';
|
||||||
|
|
||||||
|
VolumeHandle = CreateFileW(DevicePathBuf,
|
||||||
|
0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == VolumeHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
if (STATUS_OBJECT_PATH_NOT_FOUND == Result ||
|
||||||
|
STATUS_OBJECT_NAME_NOT_FOUND == Result)
|
||||||
|
Result = STATUS_NO_SUCH_DEVICE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_UNLOAD, 0, 0, 0, 0, &Bytes, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != VolumeHandle)
|
||||||
|
CloseHandle(VolumeHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL WINAPI FspFsctlServiceVersionInitialize(
|
static BOOL WINAPI FspFsctlServiceVersionInitialize(
|
||||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
{
|
{
|
||||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
WCHAR DriverName[256];
|
||||||
PWSTR ModuleFileName;
|
PWSTR ModuleFileName;
|
||||||
SC_HANDLE ScmHandle = 0;
|
SC_HANDLE ScmHandle = 0;
|
||||||
SC_HANDLE SvcHandle = 0;
|
SC_HANDLE SvcHandle = 0;
|
||||||
QUERY_SERVICE_CONFIGW *ServiceConfig = 0;
|
QUERY_SERVICE_CONFIGW *ServiceConfig = 0;
|
||||||
DWORD Size;
|
DWORD Size;
|
||||||
|
|
||||||
|
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||||
|
|
||||||
ScmHandle = OpenSCManagerW(0, 0, 0);
|
ScmHandle = OpenSCManagerW(0, 0, 0);
|
||||||
if (0 == ScmHandle)
|
if (0 == ScmHandle)
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -355,29 +431,33 @@ static VOID FspFsctlServiceVersion(PUINT32 PVersion)
|
|||||||
*PVersion = FspFsctlServiceVersionValue;
|
*PVersion = FspFsctlServiceVersionValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsctlStartService(VOID)
|
static SRWLOCK FspFsctlStartStopServiceLock = SRWLOCK_INIT;
|
||||||
|
|
||||||
|
static BOOLEAN FspFsctlRunningInContainer(VOID)
|
||||||
|
{
|
||||||
|
/* Determine if we are running inside container.
|
||||||
|
*
|
||||||
|
* See https://github.com/microsoft/perfview/blob/V1.9.65/src/TraceEvent/TraceEventSession.cs#L525
|
||||||
|
* See https://stackoverflow.com/a/50748300
|
||||||
|
*/
|
||||||
|
return ERROR_SUCCESS == RegGetValueW(
|
||||||
|
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
|
||||||
|
L"ContainerType",
|
||||||
|
RRF_RT_REG_DWORD, 0,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsctlStartServiceByName(PWSTR DriverName)
|
||||||
{
|
{
|
||||||
static SRWLOCK Lock = SRWLOCK_INIT;
|
|
||||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
|
||||||
SC_HANDLE ScmHandle = 0;
|
SC_HANDLE ScmHandle = 0;
|
||||||
SC_HANDLE SvcHandle = 0;
|
SC_HANDLE SvcHandle = 0;
|
||||||
SERVICE_STATUS ServiceStatus;
|
SERVICE_STATUS ServiceStatus;
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&Lock);
|
AcquireSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||||
|
|
||||||
/* Determine if we are running inside container.
|
if (FspFsctlRunningInContainer())
|
||||||
*
|
|
||||||
* See https://github.com/microsoft/perfview/blob/V1.9.65/src/TraceEvent/TraceEventSession.cs#L525
|
|
||||||
* See https://stackoverflow.com/a/50748300
|
|
||||||
*/
|
|
||||||
LastError = RegGetValueW(
|
|
||||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
|
|
||||||
L"ContainerType",
|
|
||||||
RRF_RT_REG_DWORD, 0,
|
|
||||||
0, 0);
|
|
||||||
if (ERROR_SUCCESS == LastError)
|
|
||||||
{
|
{
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -437,7 +517,218 @@ exit:
|
|||||||
if (0 != ScmHandle)
|
if (0 != ScmHandle)
|
||||||
CloseServiceHandle(ScmHandle);
|
CloseServiceHandle(ScmHandle);
|
||||||
|
|
||||||
ReleaseSRWLockExclusive(&Lock);
|
ReleaseSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFsctlStartService_EnumFn(PVOID Context, PWSTR ServiceName, BOOLEAN Running)
|
||||||
|
{
|
||||||
|
PWSTR DriverName = Context;
|
||||||
|
if (0 > invariant_wcscmp(DriverName, ServiceName))
|
||||||
|
lstrcpyW(DriverName, ServiceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFsctlStartService(VOID)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* With the introduction of side-by-side (SxS) FSD installations,
|
||||||
|
* we revisit how the FSD is started:
|
||||||
|
*
|
||||||
|
* - If the DLL is started in non-SxS mode, we first try to start
|
||||||
|
* the non-SxS FSD. If that fails we then enumerate all SxS FSD's
|
||||||
|
* and make a best guess on which one to start.
|
||||||
|
*
|
||||||
|
* - If the DLL is started in SxS mode, we only attempt to start
|
||||||
|
* the associated SxS FSD.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (L'\0' == FspSxsIdent()[0])
|
||||||
|
{
|
||||||
|
/* non-SxS mode */
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
WCHAR DriverName[256];
|
||||||
|
|
||||||
|
Result = FspFsctlStartServiceByName(L"" FSP_FSCTL_DRIVER_NAME);
|
||||||
|
if (NT_SUCCESS(Result) || STATUS_NO_SUCH_DEVICE != Result)
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
/* DO NOT CLOBBER Result. We will return it if our best effort below fails. */
|
||||||
|
|
||||||
|
DriverName[0] = L'\0';
|
||||||
|
FspFsctlEnumServices(FspFsctlStartService_EnumFn, DriverName);
|
||||||
|
|
||||||
|
if (L'\0' == DriverName[0] || !NT_SUCCESS(FspFsctlStartServiceByName(DriverName)))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* SxS mode */
|
||||||
|
|
||||||
|
WCHAR DriverName[256];
|
||||||
|
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||||
|
return FspFsctlStartServiceByName(DriverName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFsctlStopService(VOID)
|
||||||
|
{
|
||||||
|
WCHAR DriverName[256];
|
||||||
|
HANDLE ThreadToken = 0, ProcessToken = 0;
|
||||||
|
BOOL DidSetThreadToken = FALSE, DidAdjustTokenPrivileges = FALSE;
|
||||||
|
TOKEN_PRIVILEGES Privileges, PreviousPrivileges;
|
||||||
|
PRIVILEGE_SET RequiredPrivileges;
|
||||||
|
DWORD PreviousPrivilegesLength;
|
||||||
|
BOOL PrivilegeCheckResult;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||||
|
|
||||||
|
AcquireSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||||
|
|
||||||
|
if (FspFsctlRunningInContainer())
|
||||||
|
{
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable and check SeLoadDriverPrivilege required for FSP_FSCTL_UNLOAD */
|
||||||
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, &ThreadToken))
|
||||||
|
{
|
||||||
|
if (!OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &ProcessToken) ||
|
||||||
|
!DuplicateToken(ProcessToken, SecurityDelegation, &ThreadToken) ||
|
||||||
|
!SetThreadToken(0, ThreadToken))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
DidSetThreadToken = TRUE;
|
||||||
|
CloseHandle(ThreadToken);
|
||||||
|
ThreadToken = 0;
|
||||||
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, &ThreadToken))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!LookupPrivilegeValueW(0, SE_LOAD_DRIVER_NAME, &Privileges.Privileges[0].Luid))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
Privileges.PrivilegeCount = 1;
|
||||||
|
Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
if (!AdjustTokenPrivileges(ThreadToken, FALSE,
|
||||||
|
&Privileges, sizeof PreviousPrivileges, &PreviousPrivileges, &PreviousPrivilegesLength))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
DidAdjustTokenPrivileges = 0 == GetLastError();
|
||||||
|
RequiredPrivileges.PrivilegeCount = 1;
|
||||||
|
RequiredPrivileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
||||||
|
RequiredPrivileges.Privilege[0].Attributes = 0;
|
||||||
|
RequiredPrivileges.Privilege[0].Luid = Privileges.Privileges[0].Luid;
|
||||||
|
if (!PrivilegeCheck(ThreadToken, &RequiredPrivileges, &PrivilegeCheckResult))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!PrivilegeCheckResult)
|
||||||
|
{
|
||||||
|
Result = STATUS_PRIVILEGE_NOT_HELD;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspFsctlUnload(L"" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||||
|
if (!NT_SUCCESS(Result) && STATUS_NO_SUCH_DEVICE != Result)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (DidAdjustTokenPrivileges)
|
||||||
|
AdjustTokenPrivileges(ThreadToken, FALSE, &PreviousPrivileges, 0, 0, 0);
|
||||||
|
if (DidSetThreadToken)
|
||||||
|
SetThreadToken(0, 0);
|
||||||
|
if (0 != ThreadToken)
|
||||||
|
CloseHandle(ThreadToken);
|
||||||
|
if (0 != ProcessToken)
|
||||||
|
CloseHandle(ProcessToken);
|
||||||
|
|
||||||
|
ReleaseSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFsctlEnumServices(
|
||||||
|
VOID (*EnumFn)(PVOID Context, PWSTR ServiceName, BOOLEAN Running),
|
||||||
|
PVOID Context)
|
||||||
|
{
|
||||||
|
SC_HANDLE ScmHandle = 0;
|
||||||
|
LPENUM_SERVICE_STATUSW Services = 0;
|
||||||
|
DWORD Size, ServiceCount;
|
||||||
|
DWORD LastError;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_ENUMERATE_SERVICE);
|
||||||
|
if (0 == ScmHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EnumServicesStatusW(ScmHandle,
|
||||||
|
SERVICE_FILE_SYSTEM_DRIVER, SERVICE_STATE_ALL, 0, 0, &Size, &ServiceCount, 0))
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
if (ERROR_MORE_DATA != LastError)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 == Size)
|
||||||
|
{
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Services = MemAlloc(Size);
|
||||||
|
if (0 == Services)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EnumServicesStatusW(ScmHandle,
|
||||||
|
SERVICE_FILE_SYSTEM_DRIVER, SERVICE_STATE_ALL, Services, Size, &Size, &ServiceCount, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DWORD I = 0; ServiceCount > I; I++)
|
||||||
|
{
|
||||||
|
if (0 != invariant_wcsicmp(Services[I].lpServiceName, L"" FSP_FSCTL_DRIVER_NAME) &&
|
||||||
|
0 != invariant_wcsnicmp(Services[I].lpServiceName,
|
||||||
|
L"" FSP_FSCTL_DRIVER_NAME FSP_SXS_SEPARATOR_STRING,
|
||||||
|
sizeof(FSP_FSCTL_DRIVER_NAME FSP_SXS_SEPARATOR_STRING) - 1))
|
||||||
|
continue;
|
||||||
|
EnumFn(Context,
|
||||||
|
Services[I].lpServiceName,
|
||||||
|
SERVICE_STOPPED != Services[I].ServiceStatus.dwCurrentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(Services);
|
||||||
|
if (0 != ScmHandle)
|
||||||
|
CloseServiceHandle(ScmHandle);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -445,14 +736,15 @@ exit:
|
|||||||
static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This function adds an ACE that allows Everyone to start a service.
|
* This function adds two ACE's:
|
||||||
|
* - An ACE that allows Everyone to start a service.
|
||||||
|
* - An ACE that denies Everyone (including Administrators) to stop a service.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PSID WorldSid;
|
PSID WorldSid;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
|
PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
|
||||||
EXPLICIT_ACCESSW AccessEntry;
|
EXPLICIT_ACCESSW AccessEntries[2];
|
||||||
ACCESS_MASK AccessRights;
|
|
||||||
PACL Dacl;
|
PACL Dacl;
|
||||||
BOOL DaclPresent, DaclDefaulted;
|
BOOL DaclPresent, DaclDefaulted;
|
||||||
DWORD Size;
|
DWORD Size;
|
||||||
@ -497,54 +789,40 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prepare an EXPLICIT_ACCESS for the SERVICE_QUERY_STATUS | SERVICE_START right for Everyone */
|
/* prepare an EXPLICIT_ACCESS for the SERVICE_QUERY_STATUS | SERVICE_START rights for Everyone */
|
||||||
AccessEntry.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_START;
|
AccessEntries[0].grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_START;
|
||||||
AccessEntry.grfAccessMode = GRANT_ACCESS;
|
AccessEntries[0].grfAccessMode = GRANT_ACCESS;
|
||||||
AccessEntry.grfInheritance = NO_INHERITANCE;
|
AccessEntries[0].grfInheritance = NO_INHERITANCE;
|
||||||
AccessEntry.Trustee.pMultipleTrustee = 0;
|
AccessEntries[0].Trustee.pMultipleTrustee = 0;
|
||||||
AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
AccessEntries[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||||
AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
AccessEntries[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||||
AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
AccessEntries[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
||||||
AccessEntry.Trustee.ptstrName = WorldSid;
|
AccessEntries[0].Trustee.ptstrName = WorldSid;
|
||||||
|
|
||||||
/* get the effective rights for Everyone */
|
/* prepare an EXPLICIT_ACCESS to deny the SERVICE_STOP right to Everyone */
|
||||||
AccessRights = 0;
|
AccessEntries[1].grfAccessPermissions = SERVICE_STOP;
|
||||||
if (DaclPresent && 0 != Dacl)
|
AccessEntries[1].grfAccessMode = DENY_ACCESS;
|
||||||
|
AccessEntries[1].grfInheritance = NO_INHERITANCE;
|
||||||
|
AccessEntries[1].Trustee.pMultipleTrustee = 0;
|
||||||
|
AccessEntries[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||||
|
AccessEntries[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||||
|
AccessEntries[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
||||||
|
AccessEntries[1].Trustee.ptstrName = WorldSid;
|
||||||
|
|
||||||
|
/* create a new security descriptor with the new access */
|
||||||
|
LastError = BuildSecurityDescriptorW(0, 0, 2, AccessEntries, 0, 0, SecurityDescriptor,
|
||||||
|
&Size, &NewSecurityDescriptor);
|
||||||
|
if (0 != LastError)
|
||||||
{
|
{
|
||||||
LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights);
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
if (0 != LastError)
|
goto exit;
|
||||||
/*
|
|
||||||
* Apparently GetEffectiveRightsFromAclW can fail with ERROR_CIRCULAR_DEPENDENCY
|
|
||||||
* in some rare circumstances. Calling GetEffectiveRightsFromAclW is not essential
|
|
||||||
* in this instance. It is only done to check whether the "Everyone/World" SID
|
|
||||||
* already has the access required to start the FSD; if it does not have those
|
|
||||||
* rights already they are added. It is probably safe to just assume that the
|
|
||||||
* required rights are not there if GetEffectiveRightsFromAclW fails; the worst
|
|
||||||
* that can happen is that the rights get added twice (which is benign).
|
|
||||||
*
|
|
||||||
* See https://github.com/winfsp/winfsp/issues/62
|
|
||||||
*/
|
|
||||||
AccessRights = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do we have the required access rights? */
|
/* set the new service security descriptor DACL */
|
||||||
if (AccessEntry.grfAccessPermissions != (AccessRights & AccessEntry.grfAccessPermissions))
|
if (!SetServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, NewSecurityDescriptor))
|
||||||
{
|
{
|
||||||
/* create a new security descriptor with the new access */
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor,
|
goto exit;
|
||||||
&Size, &NewSecurityDescriptor);
|
|
||||||
if (0 != LastError)
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(LastError);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the new service security descriptor DACL */
|
|
||||||
if (!SetServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, NewSecurityDescriptor))
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
@ -559,7 +837,7 @@ exit:
|
|||||||
NTSTATUS FspFsctlRegister(VOID)
|
NTSTATUS FspFsctlRegister(VOID)
|
||||||
{
|
{
|
||||||
extern HINSTANCE DllInstance;
|
extern HINSTANCE DllInstance;
|
||||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
WCHAR DriverName[256];
|
||||||
WCHAR DriverPath[MAX_PATH];
|
WCHAR DriverPath[MAX_PATH];
|
||||||
DWORD Size;
|
DWORD Size;
|
||||||
SC_HANDLE ScmHandle = 0;
|
SC_HANDLE ScmHandle = 0;
|
||||||
@ -568,8 +846,11 @@ NTSTATUS FspFsctlRegister(VOID)
|
|||||||
SERVICE_DESCRIPTION ServiceDescription;
|
SERVICE_DESCRIPTION ServiceDescription;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (0 == GetModuleFileNameW(DllInstance, DriverPath, MAX_PATH))
|
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
|
||||||
|
Result = FspGetModuleFileName(DllInstance, DriverPath, MAX_PATH, L"" MyFsctlRegisterPath);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
Size = lstrlenW(DriverPath);
|
Size = lstrlenW(DriverPath);
|
||||||
if (4 < Size &&
|
if (4 < Size &&
|
||||||
@ -583,6 +864,14 @@ NTSTATUS FspFsctlRegister(VOID)
|
|||||||
DriverPath[Size - 2] = L'y';
|
DriverPath[Size - 2] = L'y';
|
||||||
DriverPath[Size - 1] = L's';
|
DriverPath[Size - 1] = L's';
|
||||||
}
|
}
|
||||||
|
else if (4 < Size &&
|
||||||
|
(L'.' == DriverPath[Size - 4]) &&
|
||||||
|
(L'S' == DriverPath[Size - 3] || L's' == DriverPath[Size - 3]) &&
|
||||||
|
(L'Y' == DriverPath[Size - 2] || L'y' == DriverPath[Size - 2]) &&
|
||||||
|
(L'S' == DriverPath[Size - 1] || L's' == DriverPath[Size - 1]) &&
|
||||||
|
(L'\0' == DriverPath[Size]))
|
||||||
|
{
|
||||||
|
}
|
||||||
else
|
else
|
||||||
/* should not happen! */
|
/* should not happen! */
|
||||||
return STATUS_NO_SUCH_DEVICE;
|
return STATUS_NO_SUCH_DEVICE;
|
||||||
@ -649,12 +938,16 @@ exit:
|
|||||||
|
|
||||||
NTSTATUS FspFsctlUnregister(VOID)
|
NTSTATUS FspFsctlUnregister(VOID)
|
||||||
{
|
{
|
||||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
WCHAR DriverName[256];
|
||||||
SC_HANDLE ScmHandle = 0;
|
SC_HANDLE ScmHandle = 0;
|
||||||
SC_HANDLE SvcHandle = 0;
|
SC_HANDLE SvcHandle = 0;
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||||
|
|
||||||
|
FspFsctlStopService();
|
||||||
|
|
||||||
ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_CREATE_SERVICE);
|
ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_CREATE_SERVICE);
|
||||||
/*
|
/*
|
||||||
* The SC_MANAGER_CREATE_SERVICE access right is not strictly needed here,
|
* The SC_MANAGER_CREATE_SERVICE access right is not strictly needed here,
|
||||||
|
@ -1883,3 +1883,12 @@ FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
|||||||
{
|
{
|
||||||
return FspFileSystemAddXxxInfo(NotifyInfo, Buffer, Length, PBytesTransferred);
|
return FspFileSystemAddXxxInfo(NotifyInfo, Buffer, Length, PBytesTransferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemStopServiceIfNecessary(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
BOOLEAN Normally)
|
||||||
|
{
|
||||||
|
/* NOTE: .NET calls us with a zero FileSystem pointer! */
|
||||||
|
if (Normally)
|
||||||
|
return;
|
||||||
|
FspServiceStopLoop();
|
||||||
|
}
|
||||||
|
@ -180,7 +180,7 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
|||||||
const char *mountpoint, struct fuse_args *args)
|
const char *mountpoint, struct fuse_args *args)
|
||||||
{
|
{
|
||||||
struct fuse_chan *ch = 0;
|
struct fuse_chan *ch = 0;
|
||||||
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH];
|
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH + 4];
|
||||||
int Size;
|
int Size;
|
||||||
|
|
||||||
if (0 == mountpoint || '\0' == mountpoint[0] ||
|
if (0 == mountpoint || '\0' == mountpoint[0] ||
|
||||||
@ -212,6 +212,33 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
|||||||
MountPointBuf[6] = '\0';
|
MountPointBuf[6] = '\0';
|
||||||
Size = 7 * sizeof(WCHAR);
|
Size = 7 * sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
(
|
||||||
|
'\\' == mountpoint[0] &&
|
||||||
|
'\\' == mountpoint[1] &&
|
||||||
|
('?' == mountpoint[2] || '.' == mountpoint[2]) &&
|
||||||
|
'\\' == mountpoint[3]
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
('A' <= mountpoint[4] && mountpoint[4] <= 'Z') ||
|
||||||
|
('a' <= mountpoint[4] && mountpoint[4] <= 'z')
|
||||||
|
) &&
|
||||||
|
':' == mountpoint[5] && '\\' == mountpoint[6])
|
||||||
|
{
|
||||||
|
MountPointBuf[0] = '\\';
|
||||||
|
MountPointBuf[1] = '\\';
|
||||||
|
MountPointBuf[2] = mountpoint[2];
|
||||||
|
MountPointBuf[3] = '\\';
|
||||||
|
|
||||||
|
Size = 0;
|
||||||
|
if (0 != MultiByteToWideChar(CP_UTF8, 0, mountpoint + 4, -1, TempMountPointBuf, MAX_PATH))
|
||||||
|
Size = GetFullPathNameW(TempMountPointBuf, MAX_PATH, MountPointBuf + 4, 0);
|
||||||
|
|
||||||
|
if (0 == Size || MAX_PATH <= Size)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
Size = (Size + 4 + 1) * sizeof(WCHAR);
|
||||||
|
}
|
||||||
else if (
|
else if (
|
||||||
(
|
(
|
||||||
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
||||||
|
@ -1939,7 +1939,7 @@ int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SizeA = lstrlenA(name);
|
SizeA = lstrlenA(name);
|
||||||
if (SizeA > 255)
|
if (SizeA > 255 * 4)
|
||||||
{
|
{
|
||||||
fsp_fuse_intf_LogBadDirInfo(filedesc->PosixPath, name,
|
fsp_fuse_intf_LogBadDirInfo(filedesc->PosixPath, name,
|
||||||
"too long");
|
"too long");
|
||||||
@ -1949,6 +1949,13 @@ int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
|||||||
SizeW = MultiByteToWideChar(CP_UTF8, 0, name, SizeA, DirInfo->FileNameBuf, 255);
|
SizeW = MultiByteToWideChar(CP_UTF8, 0, name, SizeA, DirInfo->FileNameBuf, 255);
|
||||||
if (0 == SizeW)
|
if (0 == SizeW)
|
||||||
{
|
{
|
||||||
|
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
|
||||||
|
{
|
||||||
|
fsp_fuse_intf_LogBadDirInfo(filedesc->PosixPath, name,
|
||||||
|
"too long");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
fsp_fuse_intf_LogBadDirInfo(filedesc->PosixPath, name,
|
fsp_fuse_intf_LogBadDirInfo(filedesc->PosixPath, name,
|
||||||
"MultiByteToWideChar failed");
|
"MultiByteToWideChar failed");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1991,7 +1998,7 @@ static NTSTATUS fsp_fuse_intf_FixDirInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
SizeA = lstrlenA(filedesc->PosixPath);
|
SizeA = lstrlenA(filedesc->PosixPath);
|
||||||
PosixPath = MemAlloc(SizeA + 1 + 255 + 1);
|
PosixPath = MemAlloc(SizeA + 1 + 255 * 4 + 1);
|
||||||
if (0 == PosixPath)
|
if (0 == PosixPath)
|
||||||
{
|
{
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
@ -2040,7 +2047,7 @@ static NTSTATUS fsp_fuse_intf_FixDirInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PosixPathEnd = 0;
|
PosixPathEnd = 0;
|
||||||
SizeA = WideCharToMultiByte(CP_UTF8, 0, DirInfo->FileNameBuf, SizeW, PosixName, 255, 0, 0);
|
SizeA = WideCharToMultiByte(CP_UTF8, 0, DirInfo->FileNameBuf, SizeW, PosixName, 255 * 4, 0, 0);
|
||||||
if (0 == SizeA)
|
if (0 == SizeA)
|
||||||
{
|
{
|
||||||
/* this should never happen because we just converted using MultiByteToWideChar */
|
/* this should never happen because we just converted using MultiByteToWideChar */
|
||||||
@ -2628,6 +2635,17 @@ static NTSTATUS fsp_fuse_intf_SetEa(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
&Uid, &Gid, &Mode, FileInfo);
|
&Uid, &Gid, &Mode, FileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID fsp_fuse_intf_DispatcherStopped(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
BOOLEAN Normally)
|
||||||
|
{
|
||||||
|
if (Normally)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct fuse *f = FileSystem->UserContext;
|
||||||
|
|
||||||
|
fsp_fuse_exit(f->env, f);
|
||||||
|
}
|
||||||
|
|
||||||
FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
||||||
{
|
{
|
||||||
fsp_fuse_intf_GetVolumeInfo,
|
fsp_fuse_intf_GetVolumeInfo,
|
||||||
@ -2661,6 +2679,8 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
|||||||
fsp_fuse_intf_Overwrite,
|
fsp_fuse_intf_Overwrite,
|
||||||
fsp_fuse_intf_GetEa,
|
fsp_fuse_intf_GetEa,
|
||||||
fsp_fuse_intf_SetEa,
|
fsp_fuse_intf_SetEa,
|
||||||
|
0,
|
||||||
|
fsp_fuse_intf_DispatcherStopped,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -70,9 +70,21 @@ NTSTATUS FspNpUnregister(VOID);
|
|||||||
NTSTATUS FspEventLogRegister(VOID);
|
NTSTATUS FspEventLogRegister(VOID);
|
||||||
NTSTATUS FspEventLogUnregister(VOID);
|
NTSTATUS FspEventLogUnregister(VOID);
|
||||||
|
|
||||||
|
PWSTR FspSxsSuffix(VOID);
|
||||||
|
PWSTR FspSxsAppendSuffix(PWCHAR Buffer, SIZE_T Size, PWSTR Ident);
|
||||||
|
|
||||||
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
|
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
|
||||||
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
|
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
|
||||||
|
|
||||||
|
NTSTATUS FspMountmgrCreateDrive(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrDeleteDrive(
|
||||||
|
PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||||
|
|
||||||
ULONG FspLdapConnect(PWSTR HostName, PVOID *PLdap);
|
ULONG FspLdapConnect(PWSTR HostName, PVOID *PLdap);
|
||||||
VOID FspLdapClose(PVOID Ldap);
|
VOID FspLdapClose(PVOID Ldap);
|
||||||
ULONG FspLdapGetValue(PVOID Ldap, PWSTR Base, ULONG Scope, PWSTR Filter, PWSTR Attribute,
|
ULONG FspLdapGetValue(PVOID Ldap, PWSTR Base, ULONG Scope, PWSTR Filter, PWSTR Attribute,
|
||||||
@ -81,12 +93,24 @@ ULONG FspLdapGetDefaultNamingContext(PVOID Ldap, PWSTR *PValue);
|
|||||||
ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue);
|
ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue);
|
||||||
|
|
||||||
PWSTR FspDiagIdent(VOID);
|
PWSTR FspDiagIdent(VOID);
|
||||||
|
HANDLE FspCreateDirectoryFileW(
|
||||||
|
PWSTR FileName,
|
||||||
|
DWORD DesiredAccess,
|
||||||
|
DWORD ShareAccess,
|
||||||
|
PSECURITY_ATTRIBUTES SecurityAttributes,
|
||||||
|
DWORD FlagsAndAttributes);
|
||||||
NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion);
|
NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion);
|
||||||
|
NTSTATUS FspGetModuleFileName(
|
||||||
|
HMODULE Module,
|
||||||
|
PWSTR FileName,
|
||||||
|
ULONG Size,
|
||||||
|
PWSTR RelativePath);
|
||||||
|
|
||||||
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
|
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
|
||||||
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount);
|
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount);
|
||||||
|
|
||||||
|
VOID FspServiceStopLoop(VOID);
|
||||||
BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
|
BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
|
||||||
|
|
||||||
static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
||||||
@ -126,6 +150,12 @@ static inline BOOLEAN FspPathIsMountmgrMountPoint(PWSTR FileName)
|
|||||||
) &&
|
) &&
|
||||||
L':' == FileName[5];
|
L':' == FileName[5];
|
||||||
}
|
}
|
||||||
|
static inline BOOLEAN FspPathIsMountmgrDrive(PWSTR FileName)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
FspPathIsMountmgrMountPoint(FileName) &&
|
||||||
|
L'\0' == FileName[6];
|
||||||
|
}
|
||||||
|
|
||||||
#define FSP_NEXT_EA(Ea, EaEnd) \
|
#define FSP_NEXT_EA(Ea, EaEnd) \
|
||||||
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
||||||
|
366
src/dll/mount.c
366
src/dll/mount.c
@ -31,6 +31,7 @@ static NTSTATUS (NTAPI *FspNtClose)(
|
|||||||
HANDLE Handle);
|
HANDLE Handle);
|
||||||
static BOOLEAN FspMountDoNotUseLauncherValue;
|
static BOOLEAN FspMountDoNotUseLauncherValue;
|
||||||
static BOOLEAN FspMountBroadcastDriveChangeValue;
|
static BOOLEAN FspMountBroadcastDriveChangeValue;
|
||||||
|
static BOOLEAN FspMountUseMountmgrFromFSDValue;
|
||||||
|
|
||||||
static VOID FspMountInitializeFromRegistry(VOID)
|
static VOID FspMountInitializeFromRegistry(VOID)
|
||||||
{
|
{
|
||||||
@ -53,6 +54,14 @@ static VOID FspMountInitializeFromRegistry(VOID)
|
|||||||
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||||
if (ERROR_SUCCESS == Result)
|
if (ERROR_SUCCESS == Result)
|
||||||
FspMountBroadcastDriveChangeValue = !!Value;
|
FspMountBroadcastDriveChangeValue = !!Value;
|
||||||
|
|
||||||
|
Value = 0;
|
||||||
|
Size = sizeof Value;
|
||||||
|
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
||||||
|
L"MountUseMountmgrFromFSD",
|
||||||
|
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||||
|
if (ERROR_SUCCESS == Result)
|
||||||
|
FspMountUseMountmgrFromFSDValue = !!Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL WINAPI FspMountInitialize(
|
static BOOL WINAPI FspMountInitialize(
|
||||||
@ -80,93 +89,17 @@ static BOOL WINAPI FspMountInitialize(
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
|
||||||
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
|
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle);
|
||||||
|
static NTSTATUS FspMountRemove_Directory(HANDLE MountHandle);
|
||||||
|
|
||||||
|
static NTSTATUS FspMountSet_MountmgrDrive(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
|
||||||
{
|
{
|
||||||
HANDLE MgrHandle = INVALID_HANDLE_VALUE;
|
if (FspMountUseMountmgrFromFSDValue)
|
||||||
DWORD Bytes = 0;
|
/* use MountManager from FSD and exit */
|
||||||
NTSTATUS Result;
|
return FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
|
||||||
|
|
||||||
if (0 == POutputBufferLength)
|
|
||||||
POutputBufferLength = &Bytes;
|
|
||||||
|
|
||||||
MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
0,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
if (INVALID_HANDLE_VALUE == MgrHandle)
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DeviceIoControl(MgrHandle,
|
|
||||||
IoControlCode,
|
|
||||||
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
|
|
||||||
&Bytes, 0))
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
*POutputBufferLength = Bytes;
|
|
||||||
Result = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
if (INVALID_HANDLE_VALUE != MgrHandle)
|
|
||||||
CloseHandle(MgrHandle);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS FspMountSet_Mountmgr(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
|
|
||||||
{
|
|
||||||
/* only support drives for now! (format: \\.\X:) */
|
|
||||||
if (L'\0' != MountPoint[6])
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
/* mountmgr.h */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
Disabled = 0,
|
|
||||||
Enabled,
|
|
||||||
} MOUNTMGR_AUTO_MOUNT_STATE;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
MOUNTMGR_AUTO_MOUNT_STATE CurrentState;
|
|
||||||
} MOUNTMGR_QUERY_AUTO_MOUNT;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
MOUNTMGR_AUTO_MOUNT_STATE NewState;
|
|
||||||
} MOUNTMGR_SET_AUTO_MOUNT;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
USHORT DeviceNameLength;
|
|
||||||
WCHAR DeviceName[1];
|
|
||||||
} MOUNTMGR_TARGET_NAME;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
USHORT SymbolicLinkNameOffset;
|
|
||||||
USHORT SymbolicLinkNameLength;
|
|
||||||
USHORT DeviceNameOffset;
|
|
||||||
USHORT DeviceNameLength;
|
|
||||||
} MOUNTMGR_CREATE_POINT_INPUT;
|
|
||||||
|
|
||||||
GUID UniqueId;
|
GUID UniqueId;
|
||||||
MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
|
|
||||||
MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
|
|
||||||
MOUNTMGR_TARGET_NAME *TargetName = 0;
|
|
||||||
MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
|
|
||||||
ULONG VolumeNameSize, QueryAutoMountSize, TargetNameSize, CreatePointInputSize;
|
|
||||||
HKEY RegKey;
|
|
||||||
LONG RegResult;
|
|
||||||
WCHAR RegValueName[MAX_PATH];
|
|
||||||
UINT8 RegValueData[sizeof UniqueId];
|
|
||||||
DWORD RegValueNameSize, RegValueDataSize;
|
|
||||||
DWORD RegType;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
/* transform our volume into one that can be used by the MountManager */
|
/* transform our volume into one that can be used by the MountManager */
|
||||||
@ -174,190 +107,115 @@ static NTSTATUS FspMountSet_Mountmgr(HANDLE VolumeHandle, PWSTR VolumeName, PWST
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
VolumeNameSize = lstrlenW(VolumeName) * sizeof(WCHAR);
|
/* use the MountManager to create the drive */
|
||||||
QueryAutoMountSize = sizeof QueryAutoMount;
|
UNICODE_STRING UVolumeName, UMountPoint;
|
||||||
TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeNameSize;
|
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||||
CreatePointInputSize = sizeof *CreatePointInput +
|
UVolumeName.Buffer = VolumeName;
|
||||||
sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeNameSize;
|
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||||
|
UMountPoint.Buffer = MountPoint + 4;
|
||||||
TargetName = MemAlloc(TargetNameSize);
|
Result = FspMountmgrCreateDrive(&UVolumeName, &UniqueId, &UMountPoint);
|
||||||
if (0 == TargetName)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatePointInput = MemAlloc(CreatePointInputSize);
|
|
||||||
if (0 == CreatePointInput)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* query the current AutoMount value and save it */
|
|
||||||
Result = FspMountmgrControl(
|
|
||||||
CTL_CODE('m', 15, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
|
||||||
/* IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT */
|
|
||||||
0, 0, &QueryAutoMount, &QueryAutoMountSize);
|
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/* disable AutoMount */
|
|
||||||
SetAutoMount.NewState = 0;
|
|
||||||
Result = FspMountmgrControl(
|
|
||||||
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
|
||||||
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
|
||||||
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
/* announce volume arrival */
|
|
||||||
memset(TargetName, 0, sizeof *TargetName);
|
|
||||||
TargetName->DeviceNameLength = (USHORT)VolumeNameSize;
|
|
||||||
memcpy(TargetName->DeviceName,
|
|
||||||
VolumeName, TargetName->DeviceNameLength);
|
|
||||||
Result = FspMountmgrControl(
|
|
||||||
CTL_CODE('m', 11, METHOD_BUFFERED, FILE_READ_ACCESS),
|
|
||||||
/* IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION */
|
|
||||||
TargetName, TargetNameSize, 0, 0);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
/* reset the AutoMount value to the saved one */
|
|
||||||
SetAutoMount.NewState = QueryAutoMount.CurrentState;
|
|
||||||
FspMountmgrControl(
|
|
||||||
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
|
||||||
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
|
||||||
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
|
||||||
#if 0
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* create mount point */
|
|
||||||
memset(CreatePointInput, 0, sizeof *CreatePointInput);
|
|
||||||
CreatePointInput->SymbolicLinkNameOffset = sizeof *CreatePointInput;
|
|
||||||
CreatePointInput->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
|
||||||
CreatePointInput->DeviceNameOffset =
|
|
||||||
CreatePointInput->SymbolicLinkNameOffset + CreatePointInput->SymbolicLinkNameLength;
|
|
||||||
CreatePointInput->DeviceNameLength = (USHORT)VolumeNameSize;
|
|
||||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
|
|
||||||
L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
|
|
||||||
((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
|
|
||||||
MountPoint[4] & ~0x20;
|
|
||||||
/* convert to uppercase */
|
|
||||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
|
|
||||||
VolumeName, CreatePointInput->DeviceNameLength);
|
|
||||||
Result = FspMountmgrControl(
|
|
||||||
CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
|
||||||
/* IOCTL_MOUNTMGR_CREATE_POINT */
|
|
||||||
CreatePointInput, CreatePointInputSize, 0, 0);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
/* HACK: delete the MountManager registry entries */
|
|
||||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\MountedDevices",
|
|
||||||
0, KEY_READ | KEY_WRITE, &RegKey);
|
|
||||||
if (ERROR_SUCCESS == RegResult)
|
|
||||||
{
|
|
||||||
for (DWORD I = 0;; I++)
|
|
||||||
{
|
|
||||||
RegValueNameSize = MAX_PATH;
|
|
||||||
RegValueDataSize = sizeof RegValueData;
|
|
||||||
RegResult = RegEnumValueW(RegKey,
|
|
||||||
I, RegValueName, &RegValueNameSize, 0, &RegType, RegValueData, &RegValueDataSize);
|
|
||||||
if (ERROR_NO_MORE_ITEMS == RegResult)
|
|
||||||
break;
|
|
||||||
else if (ERROR_SUCCESS != RegResult)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (REG_BINARY == RegType &&
|
|
||||||
sizeof RegValueData == RegValueDataSize &&
|
|
||||||
InlineIsEqualGUID((GUID *)&RegValueData, &UniqueId))
|
|
||||||
{
|
|
||||||
RegResult = RegDeleteValueW(RegKey, RegValueName);
|
|
||||||
if (ERROR_SUCCESS == RegResult)
|
|
||||||
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
|
||||||
I = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(RegKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
MemFree(CreatePointInput);
|
return Result;
|
||||||
MemFree(TargetName);
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountSet_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
|
||||||
|
{
|
||||||
|
GUID UniqueId;
|
||||||
|
HANDLE MountHandle = INVALID_HANDLE_VALUE;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PMountHandle = 0;
|
||||||
|
|
||||||
|
/* create the directory mount point */
|
||||||
|
Result = FspMountSet_Directory(VolumeName, MountPoint + 4, SecurityDescriptor, &MountHandle);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (FspMountUseMountmgrFromFSDValue)
|
||||||
|
{
|
||||||
|
/* use MountManager from FSD and exit */
|
||||||
|
Result = FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
*PMountHandle = MountHandle;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* transform our volume into one that can be used by the MountManager */
|
||||||
|
Result = FspFsctlMakeMountdev(VolumeHandle, FALSE, &UniqueId);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* notify the MountManager about the created directory mount point */
|
||||||
|
UNICODE_STRING UVolumeName, UMountPoint;
|
||||||
|
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||||
|
UVolumeName.Buffer = VolumeName;
|
||||||
|
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||||
|
UMountPoint.Buffer = MountPoint + 4;
|
||||||
|
Result = FspMountmgrNotifyCreateDirectory(&UVolumeName, &UniqueId, &UMountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
*PMountHandle = MountHandle;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
|
||||||
|
FspMountRemove_Directory(MountHandle);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspMountRemove_Mountmgr(PWSTR MountPoint)
|
static NTSTATUS FspMountRemove_MountmgrDrive(HANDLE VolumeHandle, PWSTR MountPoint)
|
||||||
{
|
{
|
||||||
/* mountmgr.h */
|
if (FspMountUseMountmgrFromFSDValue)
|
||||||
typedef struct
|
/* use MountManager from FSD and exit */
|
||||||
{
|
return FspFsctlUseMountmgr(VolumeHandle, 0);
|
||||||
ULONG SymbolicLinkNameOffset;
|
|
||||||
USHORT SymbolicLinkNameLength;
|
|
||||||
USHORT Reserved1;
|
|
||||||
ULONG UniqueIdOffset;
|
|
||||||
USHORT UniqueIdLength;
|
|
||||||
USHORT Reserved2;
|
|
||||||
ULONG DeviceNameOffset;
|
|
||||||
USHORT DeviceNameLength;
|
|
||||||
USHORT Reserved3;
|
|
||||||
} MOUNTMGR_MOUNT_POINT;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
ULONG Size;
|
|
||||||
ULONG NumberOfMountPoints;
|
|
||||||
MOUNTMGR_MOUNT_POINT MountPoints[1];
|
|
||||||
} MOUNTMGR_MOUNT_POINTS;
|
|
||||||
|
|
||||||
MOUNTMGR_MOUNT_POINT *Input = 0;
|
/* use the MountManager to delete the drive */
|
||||||
MOUNTMGR_MOUNT_POINTS *Output = 0;
|
UNICODE_STRING UMountPoint;
|
||||||
ULONG InputSize, OutputSize;
|
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||||
|
UMountPoint.Buffer = MountPoint + 4;
|
||||||
|
return FspMountmgrDeleteDrive(&UMountPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountRemove_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
|
||||||
|
HANDLE MountHandle)
|
||||||
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
if (FspMountUseMountmgrFromFSDValue)
|
||||||
OutputSize = 4096;
|
/* use MountManager from FSD, but do not exit; additional processing is required below */
|
||||||
|
FspFsctlUseMountmgr(VolumeHandle, 0);
|
||||||
Input = MemAlloc(InputSize);
|
else
|
||||||
if (0 == Input)
|
|
||||||
{
|
{
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
/* notify the MountManager about the deleted directory mount point */
|
||||||
goto exit;
|
UNICODE_STRING UVolumeName, UMountPoint;
|
||||||
|
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||||
|
UVolumeName.Buffer = VolumeName;
|
||||||
|
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||||
|
UMountPoint.Buffer = MountPoint + 4;
|
||||||
|
FspMountmgrNotifyDeleteDirectory(&UVolumeName, &UMountPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
Output = MemAlloc(OutputSize);
|
/* delete the directory mount point */
|
||||||
if (0 == Output)
|
Result = FspMountRemove_Directory(MountHandle);
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(Input, 0, sizeof *Input);
|
|
||||||
Input->SymbolicLinkNameOffset = sizeof *Input;
|
|
||||||
Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
|
||||||
memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
|
|
||||||
L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
|
|
||||||
((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] = MountPoint[4] & ~0x20;
|
|
||||||
/* convert to uppercase */
|
|
||||||
Result = FspMountmgrControl(
|
|
||||||
CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
|
||||||
/* IOCTL_MOUNTMGR_DELETE_POINTS */
|
|
||||||
Input, InputSize, Output, &OutputSize);
|
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
MemFree(Output);
|
|
||||||
MemFree(Input);
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,14 +488,12 @@ static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
|
|||||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||||
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
||||||
|
|
||||||
MountHandle = CreateFileW(MountPoint,
|
MountHandle = FspCreateDirectoryFileW(MountPoint,
|
||||||
FILE_WRITE_ATTRIBUTES,
|
FILE_WRITE_ATTRIBUTES,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
&SecurityAttributes,
|
&SecurityAttributes,
|
||||||
CREATE_NEW,
|
|
||||||
FILE_ATTRIBUTE_DIRECTORY |
|
FILE_ATTRIBUTE_DIRECTORY |
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE,
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE);
|
||||||
0);
|
|
||||||
if (INVALID_HANDLE_VALUE == MountHandle)
|
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||||
{
|
{
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
@ -740,8 +596,11 @@ FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc)
|
|||||||
Desc->MountPoint[0] = L'*';
|
Desc->MountPoint[0] = L'*';
|
||||||
return STATUS_NO_SUCH_DEVICE;
|
return STATUS_NO_SUCH_DEVICE;
|
||||||
}
|
}
|
||||||
|
else if (FspPathIsMountmgrDrive(Desc->MountPoint))
|
||||||
|
return FspMountSet_MountmgrDrive(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint);
|
||||||
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||||
return FspMountSet_Mountmgr(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint);
|
return FspMountSet_MountmgrDirectory(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint,
|
||||||
|
Desc->Security, &Desc->MountHandle);
|
||||||
else if (FspPathIsDrive(Desc->MountPoint))
|
else if (FspPathIsDrive(Desc->MountPoint))
|
||||||
return FspMountSet_Drive(Desc->VolumeName, Desc->MountPoint,
|
return FspMountSet_Drive(Desc->VolumeName, Desc->MountPoint,
|
||||||
&Desc->MountHandle);
|
&Desc->MountHandle);
|
||||||
@ -754,8 +613,11 @@ FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
|
|||||||
{
|
{
|
||||||
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
||||||
|
|
||||||
if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
if (FspPathIsMountmgrDrive(Desc->MountPoint))
|
||||||
return FspMountRemove_Mountmgr(Desc->MountPoint);
|
return FspMountRemove_MountmgrDrive(Desc->VolumeHandle, Desc->MountPoint);
|
||||||
|
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||||
|
return FspMountRemove_MountmgrDirectory(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint,
|
||||||
|
Desc->MountHandle);
|
||||||
else if (FspPathIsDrive(Desc->MountPoint))
|
else if (FspPathIsDrive(Desc->MountPoint))
|
||||||
return FspMountRemove_Drive(Desc->VolumeName, Desc->MountPoint, Desc->MountHandle);
|
return FspMountRemove_Drive(Desc->VolumeName, Desc->MountPoint, Desc->MountHandle);
|
||||||
else
|
else
|
||||||
|
32
src/dll/np.c
32
src/dll/np.c
@ -1152,15 +1152,34 @@ DWORD APIENTRY NPCloseEnum(HANDLE hEnum)
|
|||||||
NTSTATUS FspNpRegister(VOID)
|
NTSTATUS FspNpRegister(VOID)
|
||||||
{
|
{
|
||||||
extern HINSTANCE DllInstance;
|
extern HINSTANCE DllInstance;
|
||||||
WCHAR ProviderPath[MAX_PATH];
|
WCHAR DllPath[MAX_PATH], ProviderPath[MAX_PATH];
|
||||||
|
PWSTR VersionInfoPath;
|
||||||
|
BOOLEAN HasPercent;
|
||||||
WCHAR RegBuffer[1024];
|
WCHAR RegBuffer[1024];
|
||||||
PWSTR P, Part;
|
PWSTR P, Part;
|
||||||
DWORD RegResult, RegType, RegBufferSize, RegBufferOffset;
|
DWORD RegResult, RegType, RegBufferSize, RegBufferOffset;
|
||||||
HKEY RegKey;
|
HKEY RegKey;
|
||||||
BOOLEAN FoundProvider;
|
BOOLEAN FoundProvider;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (0 == GetModuleFileNameW(DllInstance, ProviderPath, MAX_PATH))
|
VersionInfoPath = ProviderPath;
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
HasPercent = FALSE;
|
||||||
|
for (P = L"" MyNpRegisterPath; *P; P++)
|
||||||
|
if ('%' == *P)
|
||||||
|
{
|
||||||
|
HasPercent = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (HasPercent)
|
||||||
|
{
|
||||||
|
VersionInfoPath = DllPath;
|
||||||
|
if (0 == GetModuleFileNameW(DllInstance, DllPath, MAX_PATH))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspGetModuleFileName(DllInstance, ProviderPath, MAX_PATH, L"" MyNpRegisterPath);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
RegResult = RegCreateKeyExW(
|
RegResult = RegCreateKeyExW(
|
||||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" FSP_NP_NAME,
|
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" FSP_NP_NAME,
|
||||||
@ -1187,12 +1206,12 @@ NTSTATUS FspNpRegister(VOID)
|
|||||||
DWORD Size;
|
DWORD Size;
|
||||||
PWSTR Description;
|
PWSTR Description;
|
||||||
|
|
||||||
Size = GetFileVersionInfoSizeW(ProviderPath, &Size/*dummy*/);
|
Size = GetFileVersionInfoSizeW(VersionInfoPath, &Size/*dummy*/);
|
||||||
if (0 < Size)
|
if (0 < Size)
|
||||||
{
|
{
|
||||||
VersionInfo = MemAlloc(Size);
|
VersionInfo = MemAlloc(Size);
|
||||||
if (0 != VersionInfo &&
|
if (0 != VersionInfo &&
|
||||||
GetFileVersionInfoW(ProviderPath, 0, Size, VersionInfo) &&
|
GetFileVersionInfoW(VersionInfoPath, 0, Size, VersionInfo) &&
|
||||||
VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription",
|
VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription",
|
||||||
&Description, &Size))
|
&Description, &Size))
|
||||||
{
|
{
|
||||||
@ -1208,7 +1227,8 @@ NTSTATUS FspNpRegister(VOID)
|
|||||||
goto close_and_exit;
|
goto close_and_exit;
|
||||||
|
|
||||||
RegResult = RegSetValueExW(RegKey,
|
RegResult = RegSetValueExW(RegKey,
|
||||||
L"ProviderPath", 0, REG_SZ, (PVOID)ProviderPath, (lstrlenW(ProviderPath) + 1) * sizeof(WCHAR));
|
L"ProviderPath", 0, HasPercent ? REG_EXPAND_SZ : REG_SZ,
|
||||||
|
(PVOID)ProviderPath, (lstrlenW(ProviderPath) + 1) * sizeof(WCHAR));
|
||||||
if (ERROR_SUCCESS != RegResult)
|
if (ERROR_SUCCESS != RegResult)
|
||||||
goto close_and_exit;
|
goto close_and_exit;
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ enum
|
|||||||
GetStatus_WaitHint = 0x4000,
|
GetStatus_WaitHint = 0x4000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static SRWLOCK FspServiceLoopLock = SRWLOCK_INIT;
|
||||||
|
static SRWLOCK FspServiceTableLock = SRWLOCK_INIT;
|
||||||
static SERVICE_TABLE_ENTRYW *FspServiceTable;
|
static SERVICE_TABLE_ENTRYW *FspServiceTable;
|
||||||
static HANDLE FspServiceConsoleModeEvent;
|
static HANDLE FspServiceConsoleModeEvent;
|
||||||
static UINT32 FspServiceConsoleCtrlHandlerDisabled;
|
static UINT32 FspServiceConsoleCtrlHandlerDisabled;
|
||||||
@ -220,6 +222,14 @@ FSP_API ULONG FspServiceGetExitCode(FSP_SERVICE *Service)
|
|||||||
|
|
||||||
FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
|
FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* FspServiceLoop can only be called once per process, because of StartServiceCtrlDispatcherW
|
||||||
|
* (which returns ERROR_SERVICE_ALREADY_RUNNING if called more than once). Unfortunately this
|
||||||
|
* limitation was never documented and there may be users of FspServiceLoop out there that call
|
||||||
|
* it more than once per process.
|
||||||
|
*/
|
||||||
|
AcquireSRWLockExclusive(&FspServiceLoopLock);
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
SERVICE_TABLE_ENTRYW ServiceTable[2];
|
SERVICE_TABLE_ENTRYW ServiceTable[2];
|
||||||
|
|
||||||
@ -236,7 +246,9 @@ FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
|
|||||||
ServiceTable[0].lpServiceProc = FspServiceEntry;
|
ServiceTable[0].lpServiceProc = FspServiceEntry;
|
||||||
ServiceTable[1].lpServiceName = 0;
|
ServiceTable[1].lpServiceName = 0;
|
||||||
ServiceTable[1].lpServiceProc = 0;
|
ServiceTable[1].lpServiceProc = 0;
|
||||||
|
AcquireSRWLockExclusive(&FspServiceTableLock);
|
||||||
FspServiceTable = ServiceTable;
|
FspServiceTable = ServiceTable;
|
||||||
|
ReleaseSRWLockExclusive(&FspServiceTableLock);
|
||||||
|
|
||||||
if (!StartServiceCtrlDispatcherW(ServiceTable))
|
if (!StartServiceCtrlDispatcherW(ServiceTable))
|
||||||
{
|
{
|
||||||
@ -331,11 +343,42 @@ FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
|
|||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
AcquireSRWLockExclusive(&FspServiceTableLock);
|
||||||
FspServiceTable = 0;
|
FspServiceTable = 0;
|
||||||
|
ReleaseSRWLockExclusive(&FspServiceTableLock);
|
||||||
|
|
||||||
|
ReleaseSRWLockExclusive(&FspServiceLoopLock);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI FspServiceStopLoopThread(PVOID Context);
|
||||||
|
VOID FspServiceStopLoop(VOID)
|
||||||
|
{
|
||||||
|
BOOLEAN HasService;
|
||||||
|
HANDLE Thread;
|
||||||
|
|
||||||
|
AcquireSRWLockShared(&FspServiceTableLock);
|
||||||
|
HasService = 0 != FspServiceFromTable();
|
||||||
|
ReleaseSRWLockShared(&FspServiceTableLock);
|
||||||
|
|
||||||
|
if (HasService)
|
||||||
|
{
|
||||||
|
Thread = CreateThread(0, 0, FspServiceStopLoopThread, 0, 0, 0);
|
||||||
|
if (0 != Thread)
|
||||||
|
CloseHandle(Thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static DWORD WINAPI FspServiceStopLoopThread(PVOID Context)
|
||||||
|
{
|
||||||
|
AcquireSRWLockShared(&FspServiceTableLock);
|
||||||
|
FSP_SERVICE *Service = FspServiceFromTable();
|
||||||
|
if (0 != Service)
|
||||||
|
FspServiceStop(Service);
|
||||||
|
ReleaseSRWLockShared(&FspServiceTableLock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API VOID FspServiceStop(FSP_SERVICE *Service)
|
FSP_API VOID FspServiceStop(FSP_SERVICE *Service)
|
||||||
{
|
{
|
||||||
SERVICE_STATUS ServiceStatus;
|
SERVICE_STATUS ServiceStatus;
|
||||||
@ -393,6 +436,7 @@ static VOID WINAPI FspServiceEntry(DWORD Argc, PWSTR *Argv)
|
|||||||
FSP_SERVICE *Service;
|
FSP_SERVICE *Service;
|
||||||
|
|
||||||
Service = FspServiceFromTable();
|
Service = FspServiceFromTable();
|
||||||
|
/* we are subordinate to FspServiceLoop; no need to protect this access with FspServiceTableLock */
|
||||||
if (0 == Service)
|
if (0 == Service)
|
||||||
{
|
{
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
@ -501,6 +545,7 @@ static DWORD WINAPI FspServiceConsoleModeThread(PVOID Context)
|
|||||||
;
|
;
|
||||||
|
|
||||||
Service = FspServiceFromTable();
|
Service = FspServiceFromTable();
|
||||||
|
/* we are subordinate to FspServiceLoop; no need to protect this access with FspServiceTableLock */
|
||||||
if (0 == Service)
|
if (0 == Service)
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");
|
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");
|
||||||
|
214
src/dll/sxs.c
Normal file
214
src/dll/sxs.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/sxs.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2022 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dll/library.h>
|
||||||
|
|
||||||
|
static INIT_ONCE FspSxsIdentInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
|
static WCHAR FspSxsIdentBuf[32 + 2] = L"";
|
||||||
|
|
||||||
|
static BOOLEAN FspSxsIdentInitializeFromFile(VOID)
|
||||||
|
{
|
||||||
|
extern HINSTANCE DllInstance;
|
||||||
|
WCHAR Path[MAX_PATH];
|
||||||
|
DWORD Size;
|
||||||
|
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||||
|
CHAR Buffer[ARRAYSIZE(FspSxsIdentBuf) - 2];
|
||||||
|
WCHAR WBuffer[ARRAYSIZE(FspSxsIdentBuf) - 2];
|
||||||
|
BOOLEAN Result = FALSE;
|
||||||
|
|
||||||
|
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Size = lstrlenW(Path);
|
||||||
|
if (4 < Size &&
|
||||||
|
(L'.' == Path[Size - 4]) &&
|
||||||
|
(L'D' == Path[Size - 3] || L'd' == Path[Size - 3]) &&
|
||||||
|
(L'L' == Path[Size - 2] || L'l' == Path[Size - 2]) &&
|
||||||
|
(L'L' == Path[Size - 1] || L'l' == Path[Size - 1]) &&
|
||||||
|
(L'\0' == Path[Size]))
|
||||||
|
;
|
||||||
|
else
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Size -= 4;
|
||||||
|
for (PWCHAR P = Path + Size - 1; Path <= P; P--)
|
||||||
|
{
|
||||||
|
if (L'\\' == *P)
|
||||||
|
break;
|
||||||
|
if (L'-' == *P)
|
||||||
|
{
|
||||||
|
/* arch */
|
||||||
|
Size = (DWORD)(P - Path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Path[Size + 0] = L'.';
|
||||||
|
Path[Size + 1] = L's';
|
||||||
|
Path[Size + 2] = L'x';
|
||||||
|
Path[Size + 3] = L's';
|
||||||
|
Path[Size + 4] = L'\0';
|
||||||
|
|
||||||
|
Handle = CreateFileW(
|
||||||
|
Path,
|
||||||
|
FILE_READ_DATA,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Handle)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (!ReadFile(Handle, Buffer, sizeof Buffer, &Size, 0))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
for (PCHAR P = Buffer, EndP = P + Size; EndP > P; P++)
|
||||||
|
if ('\r' == *P || '\n' == *P)
|
||||||
|
{
|
||||||
|
Size = (DWORD)(P - Buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = MultiByteToWideChar(CP_UTF8, 0,
|
||||||
|
Buffer, Size, WBuffer, ARRAYSIZE(WBuffer));
|
||||||
|
if (0 == Size)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
FspSxsIdentBuf[0] = FSP_SXS_SEPARATOR_CHAR;
|
||||||
|
memcpy(FspSxsIdentBuf + 1, WBuffer, Size * sizeof(WCHAR));
|
||||||
|
FspSxsIdentBuf[1 + Size] = L'\0';
|
||||||
|
|
||||||
|
Result = TRUE;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != Handle)
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN FspSxsIdentInitializeFromDirectory(VOID)
|
||||||
|
{
|
||||||
|
extern HINSTANCE DllInstance;
|
||||||
|
WCHAR Path[MAX_PATH];
|
||||||
|
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||||
|
WCHAR FinalPath[MAX_PATH];
|
||||||
|
PWCHAR P, EndP, Q, EndQ;
|
||||||
|
PWCHAR Ident = 0;
|
||||||
|
BOOLEAN Result = FALSE;
|
||||||
|
|
||||||
|
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Handle = CreateFileW(
|
||||||
|
Path,
|
||||||
|
0,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Handle)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (!GetFinalPathNameByHandleW(Handle, FinalPath, MAX_PATH, VOLUME_NAME_NONE))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
EndP = FinalPath + lstrlenW(FinalPath);
|
||||||
|
for (P = EndP - 1; FinalPath <= P; P--)
|
||||||
|
{
|
||||||
|
if (L'\\' == *P &&
|
||||||
|
P + 9 < EndP &&
|
||||||
|
(L'S' == P[1] || L's' == P[1]) &&
|
||||||
|
(L'X' == P[2] || L'x' == P[2]) &&
|
||||||
|
(L'S' == P[3] || L's' == P[3]) &&
|
||||||
|
L'\\' == P[4] &&
|
||||||
|
(L'S' == P[5] || L's' == P[5]) &&
|
||||||
|
(L'X' == P[6] || L'x' == P[6]) &&
|
||||||
|
(L'S' == P[7] || L's' == P[7]) &&
|
||||||
|
L'.' == P[8] &&
|
||||||
|
L'\\' != P[9])
|
||||||
|
{
|
||||||
|
Ident = P + 9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 == Ident)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
FspSxsIdentBuf[0] = FSP_SXS_SEPARATOR_CHAR;
|
||||||
|
EndQ = FspSxsIdentBuf + (ARRAYSIZE(FspSxsIdentBuf) - 1);
|
||||||
|
for (P = Ident, Q = FspSxsIdentBuf + 1; EndP > P && EndQ > Q && L'\\' != *P; P++, Q++)
|
||||||
|
*Q = *P;
|
||||||
|
*Q = L'\0';
|
||||||
|
|
||||||
|
Result = TRUE;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != Handle)
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL WINAPI FspSxsIdentInitialize(
|
||||||
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
|
{
|
||||||
|
if (FspSxsIdentInitializeFromFile())
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (FspSxsIdentInitializeFromDirectory())
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API PWSTR FspSxsIdent(VOID)
|
||||||
|
{
|
||||||
|
InitOnceExecuteOnce(&FspSxsIdentInitOnce, FspSxsIdentInitialize, 0, 0);
|
||||||
|
return FspSxsIdentBuf + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PWSTR FspSxsSuffix(VOID)
|
||||||
|
{
|
||||||
|
InitOnceExecuteOnce(&FspSxsIdentInitOnce, FspSxsIdentInitialize, 0, 0);
|
||||||
|
return FspSxsIdentBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
PWSTR FspSxsAppendSuffix(PWCHAR Buffer, SIZE_T Size, PWSTR Ident)
|
||||||
|
{
|
||||||
|
PWSTR Suffix;
|
||||||
|
SIZE_T IdentSize, SuffixSize;
|
||||||
|
|
||||||
|
Suffix = FspSxsSuffix();
|
||||||
|
IdentSize = lstrlenW(Ident) * sizeof(WCHAR);
|
||||||
|
SuffixSize = lstrlenW(Suffix) * sizeof(WCHAR);
|
||||||
|
if (Size < IdentSize + SuffixSize + sizeof(WCHAR))
|
||||||
|
return L"<INVALID>";
|
||||||
|
|
||||||
|
memcpy(Buffer, Ident, IdentSize);
|
||||||
|
memcpy((PUINT8)Buffer + IdentSize, Suffix, SuffixSize);
|
||||||
|
*(PWCHAR)((PUINT8)Buffer + IdentSize + SuffixSize) = L'\0';
|
||||||
|
|
||||||
|
return Buffer;
|
||||||
|
}
|
170
src/dll/util.c
170
src/dll/util.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
#include <aclapi.h>
|
#include <aclapi.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
|
||||||
static INIT_ONCE FspDiagIdentInitOnce = INIT_ONCE_STATIC_INIT;
|
static INIT_ONCE FspDiagIdentInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
static WCHAR FspDiagIdentBuf[20] = L"UNKNOWN";
|
static WCHAR FspDiagIdentBuf[20] = L"UNKNOWN";
|
||||||
@ -63,6 +64,145 @@ PWSTR FspDiagIdent(VOID)
|
|||||||
return FspDiagIdentBuf;
|
return FspDiagIdentBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INIT_ONCE FspCreateDirectoryFileInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
|
static NTSTATUS (NTAPI *FspNtCreateFile)(
|
||||||
|
PHANDLE FileHandle,
|
||||||
|
ACCESS_MASK DesiredAccess,
|
||||||
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
|
PLARGE_INTEGER AllocationSize,
|
||||||
|
ULONG FileAttributes,
|
||||||
|
ULONG ShareAccess,
|
||||||
|
ULONG CreateDisposition,
|
||||||
|
ULONG CreateOptions,
|
||||||
|
PVOID EaBuffer,
|
||||||
|
ULONG EaLength);
|
||||||
|
|
||||||
|
static BOOL WINAPI FspCreateDirectoryFileInitialize(
|
||||||
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
|
{
|
||||||
|
HANDLE Handle;
|
||||||
|
|
||||||
|
Handle = GetModuleHandleW(L"ntdll.dll");
|
||||||
|
if (0 != Handle)
|
||||||
|
FspNtCreateFile = (PVOID)GetProcAddress(Handle, "NtCreateFile");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE FspCreateDirectoryFileW(
|
||||||
|
PWSTR FileName,
|
||||||
|
DWORD DesiredAccess,
|
||||||
|
DWORD ShareAccess,
|
||||||
|
PSECURITY_ATTRIBUTES SecurityAttributes,
|
||||||
|
DWORD FlagsAndAttributes)
|
||||||
|
{
|
||||||
|
InitOnceExecuteOnce(&FspCreateDirectoryFileInitOnce, FspCreateDirectoryFileInitialize, 0, 0);
|
||||||
|
if (0 == FspNtCreateFile)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_FUNCTION);
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE Handle = INVALID_HANDLE_VALUE, ParentHandle = INVALID_HANDLE_VALUE;
|
||||||
|
PWSTR FullFileName = 0;
|
||||||
|
WCHAR *FilePart, FilePartChar;
|
||||||
|
DWORD Length;
|
||||||
|
UNICODE_STRING UFullFileName;
|
||||||
|
OBJECT_ATTRIBUTES Obja;
|
||||||
|
ULONG CreateFlags;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
|
||||||
|
Length = GetFullPathNameW(FileName, 0, 0, 0);
|
||||||
|
if (0 == Length)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
FullFileName = MemAlloc((Length + 1) * sizeof(WCHAR));
|
||||||
|
if (0 == FullFileName)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Length = GetFullPathNameW(FileName, Length + 1, FullFileName, &FilePart);
|
||||||
|
if (0 == Length)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
FilePartChar = *FilePart;
|
||||||
|
*FilePart = L'\0';
|
||||||
|
|
||||||
|
ParentHandle = CreateFileW(
|
||||||
|
FullFileName,
|
||||||
|
0,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == ParentHandle)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
*FilePart = FilePartChar;
|
||||||
|
|
||||||
|
UFullFileName.Length = UFullFileName.MaximumLength = (USHORT)(lstrlenW(FilePart) * sizeof(WCHAR));
|
||||||
|
UFullFileName.Buffer = FilePart;
|
||||||
|
|
||||||
|
memset(&Obja, 0, sizeof Obja);
|
||||||
|
Obja.Length = sizeof Obja;
|
||||||
|
Obja.ObjectName = &UFullFileName;
|
||||||
|
Obja.Attributes =
|
||||||
|
(!(FlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS) ? OBJ_CASE_INSENSITIVE : 0) |
|
||||||
|
(SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0);
|
||||||
|
Obja.RootDirectory = ParentHandle;
|
||||||
|
Obja.SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
|
||||||
|
|
||||||
|
DesiredAccess |=
|
||||||
|
SYNCHRONIZE |
|
||||||
|
FILE_READ_ATTRIBUTES |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) ? DELETE : 0);
|
||||||
|
|
||||||
|
CreateFlags =
|
||||||
|
FILE_DIRECTORY_FILE |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_OVERLAPPED) ? FILE_SYNCHRONOUS_IO_NONALERT : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_NO_BUFFERING) ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS) ? FILE_RANDOM_ACCESS : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN) ? FILE_SEQUENTIAL_ONLY : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) ? FILE_DELETE_ON_CLOSE : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) ? FILE_OPEN_FOR_BACKUP_INTENT : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) ? FILE_OPEN_REPARSE_POINT : 0) |
|
||||||
|
((FlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL) ? FILE_OPEN_NO_RECALL : 0);
|
||||||
|
|
||||||
|
IoStatus.Status = FspNtCreateFile(
|
||||||
|
&Handle,
|
||||||
|
DesiredAccess,
|
||||||
|
&Obja,
|
||||||
|
&IoStatus,
|
||||||
|
0,
|
||||||
|
FlagsAndAttributes & (0x7fff & ~FILE_ATTRIBUTE_DIRECTORY),
|
||||||
|
ShareAccess,
|
||||||
|
FILE_CREATE,
|
||||||
|
CreateFlags,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
{
|
||||||
|
SetLastError(FspWin32FromNtStatus(IoStatus.Status));
|
||||||
|
Handle = INVALID_HANDLE_VALUE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLastError(0);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != ParentHandle)
|
||||||
|
CloseHandle(ParentHandle);
|
||||||
|
|
||||||
|
MemFree(FullFileName);
|
||||||
|
|
||||||
|
return Handle;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||||
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
PULONG PBytesTransferred, ULONG Timeout,
|
PULONG PBytesTransferred, ULONG Timeout,
|
||||||
@ -248,3 +388,33 @@ NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion)
|
|||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspGetModuleFileName(
|
||||||
|
HMODULE Module,
|
||||||
|
PWSTR FileName,
|
||||||
|
ULONG Size,
|
||||||
|
PWSTR RelativePath)
|
||||||
|
{
|
||||||
|
if (MAX_PATH > Size)
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
if (0 != RelativePath &&
|
||||||
|
L'\0' != RelativePath[0] &&
|
||||||
|
(L'.' != RelativePath[0] || L'\0' != RelativePath[1]))
|
||||||
|
{
|
||||||
|
WCHAR Temp[MAX_PATH];
|
||||||
|
|
||||||
|
if (0 == GetModuleFileNameW(Module, Temp, MAX_PATH))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
if (0 == PathCombineW(FileName, Temp, RelativePath))
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (0 == GetModuleFileNameW(Module, FileName, MAX_PATH))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
@ -1188,6 +1188,39 @@ namespace Fsp
|
|||||||
{
|
{
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Inform the file system that its dispatcher has been stopped.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// Prior to WinFsp v2.0 the FSD would never unmount a file system volume unless
|
||||||
|
/// the user mode file system requested the unmount. Since WinFsp v2.0 it is possible
|
||||||
|
/// for the FSD to unmount a file system volume without an explicit user mode file system
|
||||||
|
/// request. For example, this happens when the FSD is being uninstalled.
|
||||||
|
/// </para><para>
|
||||||
|
/// A user mode file system can use this operation to determine when its dispatcher
|
||||||
|
/// has been stopped. The Normally parameter can be used to determine why the dispatcher
|
||||||
|
/// was stopped: it is TRUE when the file system is being stopped normally (i.e. via the
|
||||||
|
/// native FspFileSystemStopDispatcher) and FALSE otherwise.
|
||||||
|
/// </para><para>
|
||||||
|
/// A file system that uses the Service class infrastructure may use the
|
||||||
|
/// StopServiceIfNecessary method to correctly handle all cases. The base implementation
|
||||||
|
/// of this method calls the StopServiceIfNecessary method.
|
||||||
|
/// </para><para>
|
||||||
|
/// This operation is the last one that a file system will receive.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="Normally">
|
||||||
|
/// TRUE if the file system is being stopped via the native FspFileSystemStopDispatcher.
|
||||||
|
/// FALSE if the file system is being stopped because of another reason such
|
||||||
|
/// as driver unload/uninstall.
|
||||||
|
/// </param>
|
||||||
|
/// <seealso cref="StopServiceIfNecessary"/>
|
||||||
|
public virtual void DispatcherStopped(
|
||||||
|
Boolean Normally)
|
||||||
|
{
|
||||||
|
StopServiceIfNecessary(Normally);
|
||||||
|
}
|
||||||
|
|
||||||
/* helpers */
|
/* helpers */
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1483,6 +1516,10 @@ namespace Fsp
|
|||||||
{
|
{
|
||||||
return FullEaInformation.PackedSize(EaName, EaValue, NeedEa);
|
return FullEaInformation.PackedSize(EaName, EaValue, NeedEa);
|
||||||
}
|
}
|
||||||
|
public void StopServiceIfNecessary(Boolean Normally)
|
||||||
|
{
|
||||||
|
Api.FspFileSystemStopServiceIfNecessary(IntPtr.Zero, Normally);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1426,6 +1426,21 @@ namespace Fsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DispatcherStopped(
|
||||||
|
IntPtr FileSystemPtr,
|
||||||
|
Boolean Normally)
|
||||||
|
{
|
||||||
|
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileSystem.DispatcherStopped(Normally);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExceptionHandler(FileSystem, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static FileSystemHost()
|
static FileSystemHost()
|
||||||
{
|
{
|
||||||
_FileSystemInterface.GetVolumeInfo = GetVolumeInfo;
|
_FileSystemInterface.GetVolumeInfo = GetVolumeInfo;
|
||||||
@ -1456,6 +1471,7 @@ namespace Fsp
|
|||||||
_FileSystemInterface.SetDelete = SetDelete;
|
_FileSystemInterface.SetDelete = SetDelete;
|
||||||
_FileSystemInterface.GetEa = GetEa;
|
_FileSystemInterface.GetEa = GetEa;
|
||||||
_FileSystemInterface.SetEa = SetEa;
|
_FileSystemInterface.SetEa = SetEa;
|
||||||
|
_FileSystemInterface.DispatcherStopped = DispatcherStopped;
|
||||||
|
|
||||||
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
|
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
|
||||||
/* Marshal.AllocHGlobal does not zero memory; we must do it ourselves! */
|
/* Marshal.AllocHGlobal does not zero memory; we must do it ourselves! */
|
||||||
|
@ -745,6 +745,10 @@ namespace Fsp.Interop
|
|||||||
out FileInfo FileInfo);
|
out FileInfo FileInfo);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
internal delegate Int32 Obsolete0();
|
internal delegate Int32 Obsolete0();
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal delegate void DispatcherStopped(
|
||||||
|
IntPtr FileSystem,
|
||||||
|
[MarshalAs(UnmanagedType.U1)] Boolean Normally);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int Size = IntPtr.Size * 64;
|
internal static int Size = IntPtr.Size * 64;
|
||||||
@ -781,6 +785,7 @@ namespace Fsp.Interop
|
|||||||
internal Proto.GetEa GetEa;
|
internal Proto.GetEa GetEa;
|
||||||
internal Proto.SetEa SetEa;
|
internal Proto.SetEa SetEa;
|
||||||
internal Proto.Obsolete0 Obsolete0;
|
internal Proto.Obsolete0 Obsolete0;
|
||||||
|
internal Proto.DispatcherStopped DispatcherStopped;
|
||||||
/* NTSTATUS (*Reserved[33])(); */
|
/* NTSTATUS (*Reserved[33])(); */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,6 +912,10 @@ namespace Fsp.Interop
|
|||||||
UInt32 Length,
|
UInt32 Length,
|
||||||
out UInt32 PBytesTransferred);
|
out UInt32 PBytesTransferred);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal delegate void FspFileSystemStopServiceIfNecessary(
|
||||||
|
IntPtr FileSystem,
|
||||||
|
[MarshalAs(UnmanagedType.U1)] Boolean Normally);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
[return: MarshalAs(UnmanagedType.U1)]
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
internal delegate Boolean FspFileSystemAcquireDirectoryBuffer(
|
internal delegate Boolean FspFileSystemAcquireDirectoryBuffer(
|
||||||
ref IntPtr PDirBuffer,
|
ref IntPtr PDirBuffer,
|
||||||
@ -1048,6 +1057,7 @@ namespace Fsp.Interop
|
|||||||
internal static Proto.FspFileSystemAddStreamInfo _FspFileSystemAddStreamInfo;
|
internal static Proto.FspFileSystemAddStreamInfo _FspFileSystemAddStreamInfo;
|
||||||
internal static Proto.FspFileSystemAddEa _FspFileSystemAddEa;
|
internal static Proto.FspFileSystemAddEa _FspFileSystemAddEa;
|
||||||
internal static Proto.FspFileSystemAddNotifyInfo _FspFileSystemAddNotifyInfo;
|
internal static Proto.FspFileSystemAddNotifyInfo _FspFileSystemAddNotifyInfo;
|
||||||
|
internal static Proto.FspFileSystemStopServiceIfNecessary FspFileSystemStopServiceIfNecessary;
|
||||||
internal static Proto.FspFileSystemAcquireDirectoryBuffer FspFileSystemAcquireDirectoryBuffer;
|
internal static Proto.FspFileSystemAcquireDirectoryBuffer FspFileSystemAcquireDirectoryBuffer;
|
||||||
internal static Proto.FspFileSystemFillDirectoryBuffer FspFileSystemFillDirectoryBuffer;
|
internal static Proto.FspFileSystemFillDirectoryBuffer FspFileSystemFillDirectoryBuffer;
|
||||||
internal static Proto.FspFileSystemReleaseDirectoryBuffer FspFileSystemReleaseDirectoryBuffer;
|
internal static Proto.FspFileSystemReleaseDirectoryBuffer FspFileSystemReleaseDirectoryBuffer;
|
||||||
@ -1506,6 +1516,7 @@ namespace Fsp.Interop
|
|||||||
_FspFileSystemAddStreamInfo = GetEntryPoint<Proto.FspFileSystemAddStreamInfo>(Module);
|
_FspFileSystemAddStreamInfo = GetEntryPoint<Proto.FspFileSystemAddStreamInfo>(Module);
|
||||||
_FspFileSystemAddEa = GetEntryPoint<Proto.FspFileSystemAddEa>(Module);
|
_FspFileSystemAddEa = GetEntryPoint<Proto.FspFileSystemAddEa>(Module);
|
||||||
_FspFileSystemAddNotifyInfo = GetEntryPoint<Proto.FspFileSystemAddNotifyInfo>(Module);
|
_FspFileSystemAddNotifyInfo = GetEntryPoint<Proto.FspFileSystemAddNotifyInfo>(Module);
|
||||||
|
FspFileSystemStopServiceIfNecessary = GetEntryPoint<Proto.FspFileSystemStopServiceIfNecessary>(Module);
|
||||||
FspFileSystemAcquireDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemAcquireDirectoryBuffer>(Module);
|
FspFileSystemAcquireDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemAcquireDirectoryBuffer>(Module);
|
||||||
FspFileSystemFillDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemFillDirectoryBuffer>(Module);
|
FspFileSystemFillDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemFillDirectoryBuffer>(Module);
|
||||||
FspFileSystemReleaseDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemReleaseDirectoryBuffer>(Module);
|
FspFileSystemReleaseDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemReleaseDirectoryBuffer>(Module);
|
||||||
|
@ -62,10 +62,12 @@ static void usage(void)
|
|||||||
"\n"
|
"\n"
|
||||||
"commands:\n"
|
"commands:\n"
|
||||||
" lsvol list file system devices (volumes)\n"
|
" lsvol list file system devices (volumes)\n"
|
||||||
//" list list running file system processes\n"
|
|
||||||
//" kill kill file system process\n"
|
|
||||||
" id [NAME|SID|UID] print user id\n"
|
" id [NAME|SID|UID] print user id\n"
|
||||||
" perm [PATH|SDDL|UID:GID:MODE] print permissions\n",
|
" perm [PATH|SDDL|UID:GID:MODE] print permissions\n"
|
||||||
|
" lsdrv list drivers\n"
|
||||||
|
" load load driver\n"
|
||||||
|
" unload unload driver (requires load driver priv)\n"
|
||||||
|
" ver print version\n",
|
||||||
PROGNAME);
|
PROGNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +239,29 @@ NTSTATUS FspToolGetSidFromName(PWSTR Name, PSID *PSid)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ver(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
if (1 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
UINT32 Version;
|
||||||
|
PWSTR SxsIdent;
|
||||||
|
|
||||||
|
Result = FspVersion(&Version);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
|
||||||
|
SxsIdent = FspSxsIdent();
|
||||||
|
|
||||||
|
if (L'\0' == SxsIdent[0])
|
||||||
|
info("%u.%u", Version >> 16, Version & 0xFFFF);
|
||||||
|
else
|
||||||
|
info("%u.%u (SxS=%S)", Version >> 16, Version & 0xFFFF, SxsIdent);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS lsvol_dev(PWSTR DeviceName)
|
static NTSTATUS lsvol_dev(PWSTR DeviceName)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -255,7 +280,7 @@ static NTSTATUS lsvol_dev(PWSTR DeviceName)
|
|||||||
if (L'\0' == *P)
|
if (L'\0' == *P)
|
||||||
{
|
{
|
||||||
Drive[0] = FspToolGetDriveLetter(&LogicalDrives, VolumeName);
|
Drive[0] = FspToolGetDriveLetter(&LogicalDrives, VolumeName);
|
||||||
info("%-4S%S", Drive[0] ? Drive : L"", VolumeName);
|
info("%-4S%S", Drive[0] ? Drive : L"-", VolumeName);
|
||||||
VolumeName = P + 1;
|
VolumeName = P + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,6 +566,52 @@ static int perm(int argc, wchar_t **argv)
|
|||||||
return FspWin32FromNtStatus(Result);
|
return FspWin32FromNtStatus(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID lsdrv_enumfn(PVOID Context, PWSTR ServiceName, BOOLEAN Running)
|
||||||
|
{
|
||||||
|
info("%-4s%S", Running ? "R" : "-", ServiceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lsdrv(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
if (1 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFsctlEnumServices(lsdrv_enumfn, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
if (1 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFsctlStartService();
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int unload(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
if (1 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFsctlStopService();
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int wmain(int argc, wchar_t **argv)
|
int wmain(int argc, wchar_t **argv)
|
||||||
{
|
{
|
||||||
argc--;
|
argc--;
|
||||||
@ -549,6 +620,9 @@ int wmain(int argc, wchar_t **argv)
|
|||||||
if (0 == argc)
|
if (0 == argc)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
if (0 == invariant_wcscmp(L"ver", argv[0]))
|
||||||
|
return ver(argc, argv);
|
||||||
|
else
|
||||||
if (0 == invariant_wcscmp(L"lsvol", argv[0]))
|
if (0 == invariant_wcscmp(L"lsvol", argv[0]))
|
||||||
return lsvol(argc, argv);
|
return lsvol(argc, argv);
|
||||||
else
|
else
|
||||||
@ -557,6 +631,15 @@ int wmain(int argc, wchar_t **argv)
|
|||||||
else
|
else
|
||||||
if (0 == invariant_wcscmp(L"perm", argv[0]))
|
if (0 == invariant_wcscmp(L"perm", argv[0]))
|
||||||
return perm(argc, argv);
|
return perm(argc, argv);
|
||||||
|
else
|
||||||
|
if (0 == invariant_wcscmp(L"lsdrv", argv[0]))
|
||||||
|
return lsdrv(argc, argv);
|
||||||
|
else
|
||||||
|
if (0 == invariant_wcscmp(L"load", argv[0]))
|
||||||
|
return load(argc, argv);
|
||||||
|
else
|
||||||
|
if (0 == invariant_wcscmp(L"unload", argv[0]))
|
||||||
|
return unload(argc, argv);
|
||||||
else
|
else
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
@ -30,4 +30,10 @@
|
|||||||
*/
|
*/
|
||||||
#define FSP_CFG_REJECT_EARLY_IRP
|
#define FSP_CFG_REJECT_EARLY_IRP
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SxS separator. The '+' in "WinFsp+20220906T173701Z".
|
||||||
|
*/
|
||||||
|
#define FSP_SXS_SEPARATOR_CHAR '+'
|
||||||
|
#define FSP_SXS_SEPARATOR_STRING "+"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
599
src/shared/ku/mountmgr.c
Normal file
599
src/shared/ku/mountmgr.c
Normal file
@ -0,0 +1,599 @@
|
|||||||
|
/**
|
||||||
|
* @file shared/ku/mountmgr.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2022 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <shared/ku/library.h>
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4459) /* declaration of 'identifier' hides global declaration */
|
||||||
|
|
||||||
|
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||||
|
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength);
|
||||||
|
static NTSTATUS FspMountmgrNotifyVolumeArrival(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId);
|
||||||
|
static NTSTATUS FspMountmgrNotifyMountPoint(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created);
|
||||||
|
static NTSTATUS FspMountmgrCreateMountPoint(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||||
|
static NTSTATUS FspMountmgrDeleteMountPoint(
|
||||||
|
PUNICODE_STRING MountPoint);
|
||||||
|
static VOID FspMountmgrDeleteRegistry(
|
||||||
|
GUID *UniqueId);
|
||||||
|
NTSTATUS FspMountmgrCreateDrive(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrDeleteDrive(
|
||||||
|
PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||||
|
|
||||||
|
#if defined(_KERNEL_MODE)
|
||||||
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrControl)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrNotifyVolumeArrival)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrNotifyMountPoint)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrCreateMountPoint)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrDeleteMountPoint)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrCreateDrive)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrDeleteDrive)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrNotifyCreateDirectory)
|
||||||
|
#pragma alloc_text(PAGE, FspMountmgrNotifyDeleteDirectory)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||||
|
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
|
||||||
|
{
|
||||||
|
#if defined(_KERNEL_MODE)
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
HANDLE MgrHandle = 0;
|
||||||
|
ULONG Bytes = 0;
|
||||||
|
|
||||||
|
if (0 == POutputBufferLength)
|
||||||
|
POutputBufferLength = &Bytes;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\MountPointManager");
|
||||||
|
InitializeObjectAttributes(
|
||||||
|
&ObjectAttributes,
|
||||||
|
&DeviceName,
|
||||||
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||||
|
0/*RootDirectory*/,
|
||||||
|
0);
|
||||||
|
|
||||||
|
IoStatus.Status = ZwOpenFile(
|
||||||
|
&MgrHandle,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatus,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
FILE_SYNCHRONOUS_IO_ALERT);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
IoStatus.Status = ZwDeviceIoControlFile(
|
||||||
|
MgrHandle,
|
||||||
|
0, 0, 0,
|
||||||
|
&IoStatus,
|
||||||
|
IoControlCode,
|
||||||
|
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
*POutputBufferLength = (ULONG)IoStatus.Information;
|
||||||
|
IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != MgrHandle)
|
||||||
|
ZwClose(MgrHandle);
|
||||||
|
|
||||||
|
return IoStatus.Status;
|
||||||
|
#else
|
||||||
|
HANDLE MgrHandle = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD Bytes = 0;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == POutputBufferLength)
|
||||||
|
POutputBufferLength = &Bytes;
|
||||||
|
|
||||||
|
MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == MgrHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DeviceIoControl(MgrHandle,
|
||||||
|
IoControlCode,
|
||||||
|
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
|
||||||
|
&Bytes, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*POutputBufferLength = Bytes;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != MgrHandle)
|
||||||
|
CloseHandle(MgrHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountmgrNotifyVolumeArrival(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
/* mountmgr.h */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
Disabled = 0,
|
||||||
|
Enabled,
|
||||||
|
} MOUNTMGR_AUTO_MOUNT_STATE;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MOUNTMGR_AUTO_MOUNT_STATE CurrentState;
|
||||||
|
} MOUNTMGR_QUERY_AUTO_MOUNT;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MOUNTMGR_AUTO_MOUNT_STATE NewState;
|
||||||
|
} MOUNTMGR_SET_AUTO_MOUNT;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT DeviceNameLength;
|
||||||
|
WCHAR DeviceName[1];
|
||||||
|
} MOUNTMGR_TARGET_NAME;
|
||||||
|
|
||||||
|
MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
|
||||||
|
MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
|
||||||
|
MOUNTMGR_TARGET_NAME *TargetName = 0;
|
||||||
|
ULONG QueryAutoMountSize, TargetNameSize;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
QueryAutoMountSize = sizeof QueryAutoMount;
|
||||||
|
TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeName->Length;
|
||||||
|
|
||||||
|
TargetName = MemAlloc(TargetNameSize);
|
||||||
|
if (0 == TargetName)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the current AutoMount value and save it */
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 15, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT */
|
||||||
|
0, 0, &QueryAutoMount, &QueryAutoMountSize);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* disable AutoMount */
|
||||||
|
SetAutoMount.NewState = 0;
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||||
|
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* announce volume arrival */
|
||||||
|
memset(TargetName, 0, sizeof *TargetName);
|
||||||
|
TargetName->DeviceNameLength = VolumeName->Length;
|
||||||
|
memcpy(TargetName->DeviceName, VolumeName->Buffer, VolumeName->Length);
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 11, METHOD_BUFFERED, FILE_READ_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION */
|
||||||
|
TargetName, TargetNameSize, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* reset the AutoMount value to the saved one */
|
||||||
|
SetAutoMount.NewState = QueryAutoMount.CurrentState;
|
||||||
|
FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||||
|
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(TargetName);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountmgrNotifyMountPoint(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
/* mountmgr.h */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT SourceVolumeNameOffset;
|
||||||
|
USHORT SourceVolumeNameLength;
|
||||||
|
USHORT TargetVolumeNameOffset;
|
||||||
|
USHORT TargetVolumeNameLength;
|
||||||
|
} MOUNTMGR_VOLUME_MOUNT_POINT;
|
||||||
|
|
||||||
|
MOUNTMGR_VOLUME_MOUNT_POINT *VolumeMountPoint = 0;
|
||||||
|
ULONG VolumeMountPointSize;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
VolumeMountPointSize = sizeof *VolumeMountPoint +
|
||||||
|
sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length + VolumeName->Length;
|
||||||
|
|
||||||
|
VolumeMountPoint = MemAlloc(VolumeMountPointSize);
|
||||||
|
if (0 == VolumeMountPoint)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* notify volume mount point created/deleted */
|
||||||
|
memset(VolumeMountPoint, 0, sizeof *VolumeMountPoint);
|
||||||
|
VolumeMountPoint->SourceVolumeNameOffset = sizeof *VolumeMountPoint;
|
||||||
|
VolumeMountPoint->SourceVolumeNameLength = (USHORT)(
|
||||||
|
sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length);
|
||||||
|
VolumeMountPoint->TargetVolumeNameOffset =
|
||||||
|
VolumeMountPoint->SourceVolumeNameOffset + VolumeMountPoint->SourceVolumeNameLength;
|
||||||
|
VolumeMountPoint->TargetVolumeNameLength = VolumeName->Length;
|
||||||
|
memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset,
|
||||||
|
L"\\DosDevices\\", sizeof L"\\DosDevices\\" - sizeof(WCHAR));
|
||||||
|
memcpy((PUINT8)VolumeMountPoint +
|
||||||
|
VolumeMountPoint->SourceVolumeNameOffset + (sizeof L"\\DosDevices\\" - sizeof(WCHAR)),
|
||||||
|
MountPoint->Buffer, MountPoint->Length);
|
||||||
|
memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset,
|
||||||
|
VolumeName->Buffer, VolumeName->Length);
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
Created ?
|
||||||
|
CTL_CODE('m', 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) :
|
||||||
|
/* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED */
|
||||||
|
CTL_CODE('m', 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED */
|
||||||
|
VolumeMountPoint, VolumeMountPointSize, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(VolumeMountPoint);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountmgrCreateMountPoint(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
/* mountmgr.h */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT SymbolicLinkNameOffset;
|
||||||
|
USHORT SymbolicLinkNameLength;
|
||||||
|
USHORT DeviceNameOffset;
|
||||||
|
USHORT DeviceNameLength;
|
||||||
|
} MOUNTMGR_CREATE_POINT_INPUT;
|
||||||
|
|
||||||
|
MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
|
||||||
|
ULONG CreatePointInputSize;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
CreatePointInputSize = sizeof *CreatePointInput +
|
||||||
|
sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeName->Length;
|
||||||
|
|
||||||
|
CreatePointInput = MemAlloc(CreatePointInputSize);
|
||||||
|
if (0 == CreatePointInput)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create mount point */
|
||||||
|
memset(CreatePointInput, 0, sizeof *CreatePointInput);
|
||||||
|
CreatePointInput->SymbolicLinkNameOffset = sizeof *CreatePointInput;
|
||||||
|
CreatePointInput->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||||
|
CreatePointInput->DeviceNameOffset =
|
||||||
|
CreatePointInput->SymbolicLinkNameOffset + CreatePointInput->SymbolicLinkNameLength;
|
||||||
|
CreatePointInput->DeviceNameLength = VolumeName->Length;
|
||||||
|
memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
|
||||||
|
L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
|
||||||
|
((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
|
||||||
|
MountPoint->Buffer[0] & ~0x20;
|
||||||
|
/* convert to uppercase */
|
||||||
|
memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
|
||||||
|
VolumeName->Buffer, VolumeName->Length);
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_CREATE_POINT */
|
||||||
|
CreatePointInput, CreatePointInputSize, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(CreatePointInput);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountmgrDeleteMountPoint(
|
||||||
|
PUNICODE_STRING MountPoint)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
/* mountmgr.h */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ULONG SymbolicLinkNameOffset;
|
||||||
|
USHORT SymbolicLinkNameLength;
|
||||||
|
USHORT Reserved1;
|
||||||
|
ULONG UniqueIdOffset;
|
||||||
|
USHORT UniqueIdLength;
|
||||||
|
USHORT Reserved2;
|
||||||
|
ULONG DeviceNameOffset;
|
||||||
|
USHORT DeviceNameLength;
|
||||||
|
USHORT Reserved3;
|
||||||
|
} MOUNTMGR_MOUNT_POINT;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ULONG Size;
|
||||||
|
ULONG NumberOfMountPoints;
|
||||||
|
MOUNTMGR_MOUNT_POINT MountPoints[1];
|
||||||
|
} MOUNTMGR_MOUNT_POINTS;
|
||||||
|
|
||||||
|
MOUNTMGR_MOUNT_POINT *Input = 0;
|
||||||
|
MOUNTMGR_MOUNT_POINTS *Output = 0;
|
||||||
|
ULONG InputSize, OutputSize;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||||
|
OutputSize = 4096;
|
||||||
|
|
||||||
|
Input = MemAlloc(InputSize);
|
||||||
|
if (0 == Input)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output = MemAlloc(OutputSize);
|
||||||
|
if (0 == Output)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete mount point */
|
||||||
|
memset(Input, 0, sizeof *Input);
|
||||||
|
Input->SymbolicLinkNameOffset = sizeof *Input;
|
||||||
|
Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||||
|
memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
|
||||||
|
L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
|
||||||
|
((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] =
|
||||||
|
MountPoint->Buffer[0] & ~0x20;
|
||||||
|
/* convert to uppercase */
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_DELETE_POINTS */
|
||||||
|
Input, InputSize, Output, &OutputSize);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(Output);
|
||||||
|
MemFree(Input);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspMountmgrDeleteRegistry(GUID *UniqueId)
|
||||||
|
{
|
||||||
|
#if defined(_KERNEL_MODE)
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
UNICODE_STRING Path;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
HANDLE Handle = 0;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
KEY_VALUE_FULL_INFORMATION V;
|
||||||
|
UINT8 B[FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) + 255 + sizeof *UniqueId];
|
||||||
|
} FullInformation;
|
||||||
|
ULONG FullInformationLength;
|
||||||
|
UNICODE_STRING ValueName;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\System\\MountedDevices");
|
||||||
|
InitializeObjectAttributes(
|
||||||
|
&ObjectAttributes,
|
||||||
|
&Path,
|
||||||
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||||
|
0/*RootDirectory*/,
|
||||||
|
0);
|
||||||
|
|
||||||
|
Result = ZwOpenKey(&Handle, KEY_QUERY_VALUE, &ObjectAttributes);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
for (ULONG I = 0;; I++)
|
||||||
|
{
|
||||||
|
Result = ZwEnumerateValueKey(Handle,
|
||||||
|
I, KeyValueFullInformation, &FullInformation,
|
||||||
|
sizeof FullInformation, &FullInformationLength);
|
||||||
|
if (STATUS_NO_MORE_ENTRIES == Result)
|
||||||
|
break;
|
||||||
|
else if (!NT_SUCCESS(Result))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (REG_BINARY == FullInformation.V.Type &&
|
||||||
|
sizeof *UniqueId == FullInformation.V.DataLength &&
|
||||||
|
InlineIsEqualGUID((GUID *)((PUINT8)&FullInformation.V + FullInformation.V.DataOffset),
|
||||||
|
UniqueId))
|
||||||
|
{
|
||||||
|
ValueName.Length = ValueName.MaximumLength = (USHORT)FullInformation.V.NameLength;
|
||||||
|
ValueName.Buffer = FullInformation.V.Name;
|
||||||
|
Result = ZwDeleteValueKey(Handle, &ValueName);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
||||||
|
I = (ULONG)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZwClose(Handle);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
HKEY RegKey;
|
||||||
|
LONG RegResult;
|
||||||
|
WCHAR RegValueName[MAX_PATH];
|
||||||
|
UINT8 RegValueData[sizeof *UniqueId];
|
||||||
|
DWORD RegValueNameSize, RegValueDataSize;
|
||||||
|
DWORD RegType;
|
||||||
|
|
||||||
|
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\MountedDevices",
|
||||||
|
0, KEY_READ | KEY_WRITE, &RegKey);
|
||||||
|
if (ERROR_SUCCESS == RegResult)
|
||||||
|
{
|
||||||
|
for (DWORD I = 0;; I++)
|
||||||
|
{
|
||||||
|
RegValueNameSize = MAX_PATH;
|
||||||
|
RegValueDataSize = sizeof RegValueData;
|
||||||
|
RegResult = RegEnumValueW(RegKey,
|
||||||
|
I, RegValueName, &RegValueNameSize, 0, &RegType, RegValueData, &RegValueDataSize);
|
||||||
|
if (ERROR_NO_MORE_ITEMS == RegResult)
|
||||||
|
break;
|
||||||
|
else if (ERROR_SUCCESS != RegResult)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (REG_BINARY == RegType &&
|
||||||
|
sizeof RegValueData == RegValueDataSize &&
|
||||||
|
InlineIsEqualGUID((GUID *)&RegValueData, UniqueId))
|
||||||
|
{
|
||||||
|
RegResult = RegDeleteValueW(RegKey, RegValueName);
|
||||||
|
if (ERROR_SUCCESS == RegResult)
|
||||||
|
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
||||||
|
I = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMountmgrCreateDrive(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/* notify the MountManager about the new volume */
|
||||||
|
Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* use the MountManager to create the drive */
|
||||||
|
Result = FspMountmgrCreateMountPoint(VolumeName, MountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* HACK: delete the MountManager registry entries */
|
||||||
|
FspMountmgrDeleteRegistry(UniqueId);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMountmgrDeleteDrive(
|
||||||
|
PUNICODE_STRING MountPoint)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/* use the MountManager to delete the drive */
|
||||||
|
Result = FspMountmgrDeleteMountPoint(MountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/* notify the MountManager about the new volume */
|
||||||
|
Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* notify the MountManager about the created directory mount point */
|
||||||
|
Result = FspMountmgrNotifyMountPoint(VolumeName, MountPoint, TRUE);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* HACK: delete the MountManager registry entries */
|
||||||
|
FspMountmgrDeleteRegistry(UniqueId);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
/* notify the MountManager about the deleted directory mount point */
|
||||||
|
return FspMountmgrNotifyMountPoint(VolumeName, MountPoint, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning(pop)
|
@ -154,8 +154,16 @@ NTSTATUS FspReleaseForModWrite(
|
|||||||
|
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In some rare cases and under load the mapped page writer's TopLevelIrp
|
||||||
|
* may be trashed by some outside component (observed on Windows 10 1909).
|
||||||
|
*/
|
||||||
|
PIRP TopLevelIrp = IoGetTopLevelIrp();
|
||||||
|
IoSetTopLevelIrp((PIRP)FSRTL_MOD_WRITE_TOP_LEVEL_IRP);
|
||||||
|
|
||||||
FspFileNodeRelease(FileNode, Full);
|
FspFileNodeRelease(FileNode, Full);
|
||||||
ASSERT((PIRP)FSRTL_MOD_WRITE_TOP_LEVEL_IRP == IoGetTopLevelIrp());
|
|
||||||
|
IoSetTopLevelIrp(TopLevelIrp);
|
||||||
|
|
||||||
FSP_LEAVE("FileObject=%p", FileObject);
|
FSP_LEAVE("FileObject=%p", FileObject);
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
|||||||
PDEVICE_OBJECT *PDeviceObject);
|
PDEVICE_OBJECT *PDeviceObject);
|
||||||
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
|
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
||||||
|
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject);
|
||||||
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
||||||
_IRQL_requires_(DISPATCH_LEVEL)
|
_IRQL_requires_(DISPATCH_LEVEL)
|
||||||
@ -59,19 +60,21 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I
|
|||||||
BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||||
VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||||
VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject);
|
||||||
|
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||||
|
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
|
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
|
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||||
NTSTATUS FspDeviceCopyList(
|
NTSTATUS FspDeviceCopyList(
|
||||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
||||||
VOID FspDeviceDeleteList(
|
VOID FspDeviceDeleteList(
|
||||||
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
|
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
|
||||||
VOID FspDeviceDeleteAll(VOID);
|
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspDeviceCreateSecure)
|
#pragma alloc_text(PAGE, FspDeviceCreateSecure)
|
||||||
#pragma alloc_text(PAGE, FspDeviceCreate)
|
#pragma alloc_text(PAGE, FspDeviceCreate)
|
||||||
#pragma alloc_text(PAGE, FspDeviceInitialize)
|
#pragma alloc_text(PAGE, FspDeviceInitialize)
|
||||||
#pragma alloc_text(PAGE, FspDeviceDelete)
|
#pragma alloc_text(PAGE, FspDeviceDelete)
|
||||||
|
#pragma alloc_text(PAGE, FspDeviceDoIoDeleteDevice)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
|
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
||||||
@ -84,11 +87,12 @@ VOID FspDeviceDeleteAll(VOID);
|
|||||||
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
|
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
|
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
|
||||||
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
|
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
|
||||||
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
|
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
|
||||||
#pragma alloc_text(PAGE, FspDeviceCopyList)
|
#pragma alloc_text(PAGE, FspDeviceCopyList)
|
||||||
#pragma alloc_text(PAGE, FspDeviceDeleteList)
|
#pragma alloc_text(PAGE, FspDeviceDeleteList)
|
||||||
#pragma alloc_text(PAGE, FspDeviceDeleteAll)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||||
@ -171,7 +175,7 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
|
|||||||
Result = FspFsvolDeviceInit(DeviceObject);
|
Result = FspFsvolDeviceInit(DeviceObject);
|
||||||
break;
|
break;
|
||||||
case FspFsvrtDeviceExtensionKind:
|
case FspFsvrtDeviceExtensionKind:
|
||||||
Result = STATUS_SUCCESS;
|
Result = FspFsvrtDeviceInit(DeviceObject);
|
||||||
break;
|
break;
|
||||||
case FspFsmupDeviceExtensionKind:
|
case FspFsmupDeviceExtensionKind:
|
||||||
Result = FspFsmupDeviceInit(DeviceObject);
|
Result = FspFsmupDeviceInit(DeviceObject);
|
||||||
@ -202,6 +206,7 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
|||||||
FspFsvolDeviceFini(DeviceObject);
|
FspFsvolDeviceFini(DeviceObject);
|
||||||
break;
|
break;
|
||||||
case FspFsvrtDeviceExtensionKind:
|
case FspFsvrtDeviceExtensionKind:
|
||||||
|
FspFsvrtDeviceFini(DeviceObject);
|
||||||
break;
|
break;
|
||||||
case FspFsmupDeviceExtensionKind:
|
case FspFsmupDeviceExtensionKind:
|
||||||
FspFsmupDeviceFini(DeviceObject);
|
FspFsmupDeviceFini(DeviceObject);
|
||||||
@ -213,13 +218,17 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DBG
|
FspDeviceDoIoDeleteDevice(DeviceObject);
|
||||||
#pragma prefast(suppress:28175, "Debugging only: ok to access DeviceObject->Size")
|
}
|
||||||
RtlFillMemory(&DeviceExtension->Kind,
|
|
||||||
(PUINT8)DeviceObject + DeviceObject->Size - (PUINT8)&DeviceExtension->Kind, 0xBD);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IoDeleteDevice(DeviceObject);
|
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
if (0 == InterlockedCompareExchange(&DeviceExtension->DidIoDeleteDevice, 1, 0))
|
||||||
|
IoDeleteDevice(DeviceObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject)
|
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject)
|
||||||
@ -848,6 +857,27 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject)
|
|||||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
ExInitializeFastMutex(&FsvrtDeviceExtension->MountMutex);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
|
||||||
|
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
|
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -916,22 +946,4 @@ VOID FspDeviceDeleteList(
|
|||||||
FspFree(DeviceObjects);
|
FspFree(DeviceObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspDeviceDeleteAll(VOID)
|
|
||||||
{
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
NTSTATUS Result;
|
|
||||||
PDEVICE_OBJECT *DeviceObjects = 0;
|
|
||||||
ULONG DeviceObjectCount = 0;
|
|
||||||
|
|
||||||
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (ULONG i = 0; DeviceObjectCount > i; i++)
|
|
||||||
FspDeviceDelete(DeviceObjects[i]);
|
|
||||||
|
|
||||||
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
FAST_MUTEX FspDeviceGlobalMutex;
|
FAST_MUTEX FspDeviceGlobalMutex;
|
||||||
|
@ -55,6 +55,7 @@ NTSTATUS FspDeviceInitializeAllTimers(VOID)
|
|||||||
VOID FspDeviceFinalizeAllTimers(VOID)
|
VOID FspDeviceFinalizeAllTimers(VOID)
|
||||||
{
|
{
|
||||||
KeCancelTimer(&FspDeviceTimer);
|
KeCancelTimer(&FspDeviceTimer);
|
||||||
|
KeFlushQueuedDpcs();
|
||||||
|
|
||||||
#if DBG
|
#if DBG
|
||||||
KIRQL Irql;
|
KIRQL Irql;
|
||||||
|
@ -205,6 +205,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
ASSERT(sizeof(UINT64) == DirectoryMarker->Length);
|
ASSERT(sizeof(UINT64) == DirectoryMarker->Length);
|
||||||
DirectoryMarkerFound = DirectoryNextOffset == *(PUINT64)DirectoryMarker->Buffer;
|
DirectoryMarkerFound = DirectoryNextOffset == *(PUINT64)DirectoryMarker->Buffer;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
||||||
|
226
src/sys/driver.c
226
src/sys/driver.c
@ -22,15 +22,24 @@
|
|||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
DRIVER_INITIALIZE DriverEntry;
|
DRIVER_INITIALIZE DriverEntry;
|
||||||
|
static DRIVER_UNLOAD DriverUnload;
|
||||||
static VOID FspDriverMultiVersionInitialize(VOID);
|
static VOID FspDriverMultiVersionInitialize(VOID);
|
||||||
static NTSTATUS FspDriverInitializeDevices(VOID);
|
static NTSTATUS FspDriverInitializeDevices(VOID);
|
||||||
static VOID FspDriverFinalizeDevices(VOID);
|
static VOID FspDriverFinalizeDevices(VOID);
|
||||||
|
static VOID FspDriverFinalizeDevicesForUnload(VOID);
|
||||||
|
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices);
|
||||||
|
NTSTATUS FspDriverUnload(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(INIT, DriverEntry)
|
#pragma alloc_text(INIT, DriverEntry)
|
||||||
|
#pragma alloc_text(PAGE, DriverUnload)
|
||||||
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
|
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
|
||||||
#pragma alloc_text(PAGE, FspDriverInitializeDevices)
|
#pragma alloc_text(PAGE, FspDriverInitializeDevices)
|
||||||
#pragma alloc_text(PAGE, FspDriverFinalizeDevices)
|
#pragma alloc_text(PAGE, FspDriverFinalizeDevices)
|
||||||
|
#pragma alloc_text(PAGE, FspDriverFinalizeDevicesForUnload)
|
||||||
|
#pragma alloc_text(PAGE, FspDriverFinalizeDevicesEx)
|
||||||
|
#pragma alloc_text(PAGE, FspDriverUnload)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NTSTATUS DriverEntry(
|
NTSTATUS DriverEntry(
|
||||||
@ -40,7 +49,10 @@ NTSTATUS DriverEntry(
|
|||||||
|
|
||||||
FSP_TRACE_INIT();
|
FSP_TRACE_INIT();
|
||||||
|
|
||||||
|
FspSxsIdentInitialize(&DriverObject->DriverName);
|
||||||
|
|
||||||
/* setup the driver object */
|
/* setup the driver object */
|
||||||
|
DriverObject->DriverUnload = DriverUnload;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_READ] = FspRead;
|
DriverObject->MajorFunction[IRP_MJ_READ] = FspRead;
|
||||||
@ -128,6 +140,7 @@ NTSTATUS DriverEntry(
|
|||||||
FspDriverObject = DriverObject;
|
FspDriverObject = DriverObject;
|
||||||
FspDriverMultiVersionInitialize();
|
FspDriverMultiVersionInitialize();
|
||||||
|
|
||||||
|
ExInitializeFastMutex(&FspDriverUnloadMutex);
|
||||||
ExInitializeFastMutex(&FspDeviceGlobalMutex);
|
ExInitializeFastMutex(&FspDeviceGlobalMutex);
|
||||||
|
|
||||||
Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
|
Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
|
||||||
@ -150,6 +163,10 @@ NTSTATUS DriverEntry(
|
|||||||
goto exit;
|
goto exit;
|
||||||
InitDoneDevices = TRUE;
|
InitDoneDevices = TRUE;
|
||||||
|
|
||||||
|
Result = FspSiloPostInitialize();
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -172,6 +189,26 @@ exit:
|
|||||||
&DriverObject->DriverName, RegistryPath);
|
&DriverObject->DriverName, RegistryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID DriverUnload(
|
||||||
|
PDRIVER_OBJECT DriverObject)
|
||||||
|
{
|
||||||
|
FSP_ENTER_VOID(PAGED_CODE());
|
||||||
|
|
||||||
|
FspDriverFinalizeDevices();
|
||||||
|
|
||||||
|
FspDeviceFinalizeAllTimers();
|
||||||
|
|
||||||
|
FspProcessBufferFinalize();
|
||||||
|
|
||||||
|
FspSiloFinalize();
|
||||||
|
|
||||||
|
FSP_TRACE_FINI();
|
||||||
|
|
||||||
|
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
|
||||||
|
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
|
||||||
|
&DriverObject->DriverName);
|
||||||
|
}
|
||||||
|
|
||||||
static VOID FspDriverMultiVersionInitialize(VOID)
|
static VOID FspDriverMultiVersionInitialize(VOID)
|
||||||
{
|
{
|
||||||
FspProcessorCount = KeQueryActiveProcessorCount(0);
|
FspProcessorCount = KeQueryActiveProcessorCount(0);
|
||||||
@ -202,6 +239,8 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
|||||||
FSP_SILO_GLOBALS *Globals;
|
FSP_SILO_GLOBALS *Globals;
|
||||||
UNICODE_STRING DeviceSddl;
|
UNICODE_STRING DeviceSddl;
|
||||||
UNICODE_STRING DeviceName;
|
UNICODE_STRING DeviceName;
|
||||||
|
WCHAR DeviceNameBuf[128];
|
||||||
|
UNICODE_STRING SymlinkName;
|
||||||
GUID Guid;
|
GUID Guid;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
@ -210,20 +249,46 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
|||||||
|
|
||||||
/* create the file system control device objects */
|
/* create the file system control device objects */
|
||||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf);
|
||||||
|
Result = RtlUnicodeStringPrintf(&DeviceName,
|
||||||
|
L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME "%wZ",
|
||||||
|
FspSxsSuffix());
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||||
&Globals->FsctlDiskDeviceObject);
|
&Globals->FsctlDiskDeviceObject);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
if (0 != FspSxsIdent()->Length)
|
||||||
|
{
|
||||||
|
/* \Device\WinFsp.Disk SxS symlink */
|
||||||
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||||
|
Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
Globals->InitDoneSymlinkDisk = 1;
|
||||||
|
}
|
||||||
|
RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf);
|
||||||
|
Result = RtlUnicodeStringPrintf(&DeviceName,
|
||||||
|
L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME "%wZ",
|
||||||
|
FspSxsSuffix());
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||||
&Globals->FsctlNetDeviceObject);
|
&Globals->FsctlNetDeviceObject);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
if (0 != FspSxsIdent()->Length)
|
||||||
|
{
|
||||||
|
/* \Device\WinFsp.Net SxS symlink */
|
||||||
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||||
|
Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
Globals->InitDoneSymlinkNet = 1;
|
||||||
|
}
|
||||||
Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
|
Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
|
||||||
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
|
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
|
||||||
&Globals->FsmupDeviceObject);
|
&Globals->FsmupDeviceObject);
|
||||||
@ -257,8 +322,9 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
|||||||
Result = RtlUnicodeStringPrintf(&DeviceName,
|
Result = RtlUnicodeStringPrintf(&DeviceName,
|
||||||
0 == ((PULONG)&Guid)[0] && 0 == ((PULONG)&Guid)[1] &&
|
0 == ((PULONG)&Guid)[0] && 0 == ((PULONG)&Guid)[1] &&
|
||||||
0 == ((PULONG)&Guid)[2] && 0 == ((PULONG)&Guid)[3] ?
|
0 == ((PULONG)&Guid)[2] && 0 == ((PULONG)&Guid)[3] ?
|
||||||
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME :
|
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ":
|
||||||
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||||
|
FspSxsSuffix(),
|
||||||
Guid.Data1, Guid.Data2, Guid.Data3,
|
Guid.Data1, Guid.Data2, Guid.Data3,
|
||||||
Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
|
Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
|
||||||
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
|
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
|
||||||
@ -277,12 +343,25 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
|||||||
* as a file system; we register with the MUP instead.
|
* as a file system; we register with the MUP instead.
|
||||||
*/
|
*/
|
||||||
IoRegisterFileSystem(Globals->FsctlDiskDeviceObject);
|
IoRegisterFileSystem(Globals->FsctlDiskDeviceObject);
|
||||||
|
Globals->InitDoneRegisterDisk = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reference primary device objects to allow for IoDeleteDevice during FspDriverUnload.
|
||||||
|
*/
|
||||||
|
ObReferenceObject(Globals->FsctlDiskDeviceObject);
|
||||||
|
ObReferenceObject(Globals->FsctlNetDeviceObject);
|
||||||
|
ObReferenceObject(Globals->FsmupDeviceObject);
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
|
if (Globals->InitDoneRegisterDisk)
|
||||||
|
{
|
||||||
|
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
|
||||||
|
Globals->InitDoneRegisterDisk = 0;
|
||||||
|
}
|
||||||
if (0 != Globals->MupHandle)
|
if (0 != Globals->MupHandle)
|
||||||
{
|
{
|
||||||
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
||||||
@ -293,11 +372,23 @@ exit:
|
|||||||
FspDeviceDelete(Globals->FsmupDeviceObject);
|
FspDeviceDelete(Globals->FsmupDeviceObject);
|
||||||
Globals->FsmupDeviceObject = 0;
|
Globals->FsmupDeviceObject = 0;
|
||||||
}
|
}
|
||||||
|
if (Globals->InitDoneSymlinkNet)
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||||
|
IoDeleteSymbolicLink(&SymlinkName);
|
||||||
|
Globals->InitDoneSymlinkNet = 0;
|
||||||
|
}
|
||||||
if (0 != Globals->FsctlNetDeviceObject)
|
if (0 != Globals->FsctlNetDeviceObject)
|
||||||
{
|
{
|
||||||
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
||||||
Globals->FsctlNetDeviceObject = 0;
|
Globals->FsctlNetDeviceObject = 0;
|
||||||
}
|
}
|
||||||
|
if (Globals->InitDoneSymlinkDisk)
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||||
|
IoDeleteSymbolicLink(&SymlinkName);
|
||||||
|
Globals->InitDoneSymlinkDisk = 0;
|
||||||
|
}
|
||||||
if (0 != Globals->FsctlDiskDeviceObject)
|
if (0 != Globals->FsctlDiskDeviceObject)
|
||||||
{
|
{
|
||||||
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
||||||
@ -314,13 +405,31 @@ static VOID FspDriverFinalizeDevices(VOID)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FspDriverFinalizeDevicesEx(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspDriverFinalizeDevicesForUnload(VOID)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FspDriverFinalizeDevicesEx(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
FSP_SILO_GLOBALS *Globals;
|
FSP_SILO_GLOBALS *Globals;
|
||||||
|
UNICODE_STRING SymlinkName;
|
||||||
|
|
||||||
FspSiloGetGlobals(&Globals);
|
FspSiloGetGlobals(&Globals);
|
||||||
ASSERT(0 != Globals);
|
ASSERT(0 != Globals);
|
||||||
|
|
||||||
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
|
if (Globals->InitDoneRegisterDisk)
|
||||||
|
{
|
||||||
|
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
|
||||||
|
Globals->InitDoneRegisterDisk = 0;
|
||||||
|
}
|
||||||
if (0 != Globals->MupHandle)
|
if (0 != Globals->MupHandle)
|
||||||
{
|
{
|
||||||
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
||||||
@ -328,26 +437,119 @@ static VOID FspDriverFinalizeDevices(VOID)
|
|||||||
}
|
}
|
||||||
if (0 != Globals->FsmupDeviceObject)
|
if (0 != Globals->FsmupDeviceObject)
|
||||||
{
|
{
|
||||||
FspDeviceDelete(Globals->FsmupDeviceObject);
|
if (DeleteDevices)
|
||||||
Globals->FsmupDeviceObject = 0;
|
{
|
||||||
|
FspDeviceDelete(Globals->FsmupDeviceObject);
|
||||||
|
ObDereferenceObject(Globals->FsmupDeviceObject);
|
||||||
|
Globals->FsmupDeviceObject = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FspDeviceDoIoDeleteDevice(Globals->FsmupDeviceObject);
|
||||||
|
}
|
||||||
|
if (Globals->InitDoneSymlinkNet)
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||||
|
IoDeleteSymbolicLink(&SymlinkName);
|
||||||
|
Globals->InitDoneSymlinkNet = 0;
|
||||||
}
|
}
|
||||||
if (0 != Globals->FsctlNetDeviceObject)
|
if (0 != Globals->FsctlNetDeviceObject)
|
||||||
{
|
{
|
||||||
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
if (DeleteDevices)
|
||||||
Globals->FsctlNetDeviceObject = 0;
|
{
|
||||||
|
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
||||||
|
ObDereferenceObject(Globals->FsctlNetDeviceObject);
|
||||||
|
Globals->FsctlNetDeviceObject = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FspDeviceDoIoDeleteDevice(Globals->FsctlNetDeviceObject);
|
||||||
|
}
|
||||||
|
if (Globals->InitDoneSymlinkDisk)
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||||
|
IoDeleteSymbolicLink(&SymlinkName);
|
||||||
|
Globals->InitDoneSymlinkDisk = 0;
|
||||||
}
|
}
|
||||||
if (0 != Globals->FsctlDiskDeviceObject)
|
if (0 != Globals->FsctlDiskDeviceObject)
|
||||||
{
|
{
|
||||||
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
if (DeleteDevices)
|
||||||
Globals->FsctlDiskDeviceObject = 0;
|
{
|
||||||
|
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
||||||
|
ObDereferenceObject(Globals->FsctlDiskDeviceObject);
|
||||||
|
Globals->FsctlDiskDeviceObject = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FspDeviceDoIoDeleteDevice(Globals->FsctlDiskDeviceObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
FspSiloDereferenceGlobals(Globals);
|
FspSiloDereferenceGlobals(Globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspDriverUnload(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
||||||
|
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||||
|
ASSERT(FSP_FSCTL_UNLOAD == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
UNICODE_STRING DriverServiceName, DriverName, Remain;
|
||||||
|
WCHAR DriverServiceNameBuf[64 + 256];
|
||||||
|
PDEVICE_OBJECT *DeviceObjects = 0;
|
||||||
|
ULONG DeviceObjectCount = 0;
|
||||||
|
|
||||||
|
if (!FspSiloIsHost())
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE), UserMode))
|
||||||
|
return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
|
|
||||||
|
ExAcquireFastMutexUnsafe(&FspDriverUnloadMutex);
|
||||||
|
|
||||||
|
if (!FspDriverUnloadDone)
|
||||||
|
{
|
||||||
|
FspFileNameSuffix(&FspDriverObject->DriverName, &Remain, &DriverName);
|
||||||
|
RtlInitEmptyUnicodeString(&DriverServiceName, DriverServiceNameBuf, sizeof DriverServiceNameBuf);
|
||||||
|
Result = RtlUnicodeStringPrintf(&DriverServiceName,
|
||||||
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%wZ", &DriverName);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
Result = ZwUnloadDriver(&DriverServiceName);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
FspSiloEnumerate(FspDriverFinalizeDevicesForUnload);
|
||||||
|
FspDriverFinalizeDevicesForUnload();
|
||||||
|
|
||||||
|
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
for (ULONG I = 0; DeviceObjectCount > I; I++)
|
||||||
|
{
|
||||||
|
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObjects[I]);
|
||||||
|
if (FspFsvolDeviceExtensionKind == DeviceExtension->Kind)
|
||||||
|
FspIoqStop(((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Ioq, FALSE);
|
||||||
|
}
|
||||||
|
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspDriverUnloadDone = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ExReleaseFastMutexUnsafe(&FspDriverUnloadMutex);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
PDRIVER_OBJECT FspDriverObject;
|
PDRIVER_OBJECT FspDriverObject;
|
||||||
FAST_IO_DISPATCH FspFastIoDispatch;
|
FAST_IO_DISPATCH FspFastIoDispatch;
|
||||||
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||||
|
FAST_MUTEX FspDriverUnloadMutex;
|
||||||
|
BOOLEAN FspDriverUnloadDone;
|
||||||
|
|
||||||
ULONG FspProcessorCount;
|
ULONG FspProcessorCount;
|
||||||
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
||||||
|
@ -364,6 +364,10 @@ VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Sta
|
|||||||
/* missing typedef */
|
/* missing typedef */
|
||||||
typedef const void *PCVOID;
|
typedef const void *PCVOID;
|
||||||
|
|
||||||
|
/* driver unload */
|
||||||
|
NTSTATUS FspDriverUnload(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
|
||||||
/* driver major functions */
|
/* driver major functions */
|
||||||
_Function_class_(DRIVER_DISPATCH)
|
_Function_class_(DRIVER_DISPATCH)
|
||||||
_IRQL_requires_max_(APC_LEVEL)
|
_IRQL_requires_max_(APC_LEVEL)
|
||||||
@ -739,22 +743,34 @@ LONG FspCompareUnicodeString(
|
|||||||
PCUNICODE_STRING String2,
|
PCUNICODE_STRING String2,
|
||||||
BOOLEAN CaseInsensitive);
|
BOOLEAN CaseInsensitive);
|
||||||
|
|
||||||
|
/* SxS */
|
||||||
|
VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName);
|
||||||
|
PUNICODE_STRING FspSxsIdent(VOID);
|
||||||
|
PUNICODE_STRING FspSxsSuffix(VOID);
|
||||||
|
|
||||||
/* silos */
|
/* silos */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
PVOID Silo;
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
PDEVICE_OBJECT FsctlDiskDeviceObject;
|
PDEVICE_OBJECT FsctlDiskDeviceObject;
|
||||||
PDEVICE_OBJECT FsctlNetDeviceObject;
|
PDEVICE_OBJECT FsctlNetDeviceObject;
|
||||||
PDEVICE_OBJECT FsmupDeviceObject;
|
PDEVICE_OBJECT FsmupDeviceObject;
|
||||||
HANDLE MupHandle;
|
HANDLE MupHandle;
|
||||||
WCHAR FsmupDeviceNameBuf[64];
|
WCHAR FsmupDeviceNameBuf[128];
|
||||||
|
UINT32 InitDoneSymlinkDisk:1, InitDoneSymlinkNet:1, InitDoneRegisterDisk:1;
|
||||||
} FSP_SILO_GLOBALS;
|
} FSP_SILO_GLOBALS;
|
||||||
typedef NTSTATUS (*FSP_SILO_INIT_CALLBACK)(VOID);
|
typedef NTSTATUS (*FSP_SILO_INIT_CALLBACK)(VOID);
|
||||||
typedef VOID (*FSP_SILO_FINI_CALLBACK)(VOID);
|
typedef VOID (*FSP_SILO_FINI_CALLBACK)(VOID);
|
||||||
|
typedef VOID (*FSP_SILO_ENUM_CALLBACK)(VOID);
|
||||||
|
BOOLEAN FspSiloIsHost(VOID);
|
||||||
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals);
|
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals);
|
||||||
VOID FspSiloDereferenceGlobals(FSP_SILO_GLOBALS *Globals);
|
VOID FspSiloDereferenceGlobals(FSP_SILO_GLOBALS *Globals);
|
||||||
VOID FspSiloGetContainerId(GUID *ContainerId);
|
VOID FspSiloGetContainerId(GUID *ContainerId);
|
||||||
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
||||||
|
NTSTATUS FspSiloPostInitialize(VOID);
|
||||||
VOID FspSiloFinalize(VOID);
|
VOID FspSiloFinalize(VOID);
|
||||||
|
VOID FspSiloEnumerate(FSP_SILO_ENUM_CALLBACK EnumFn);
|
||||||
|
|
||||||
/* process buffers */
|
/* process buffers */
|
||||||
#define FspProcessBufferSizeMax (64 * 1024)
|
#define FspProcessBufferSizeMax (64 * 1024)
|
||||||
@ -1181,9 +1197,8 @@ typedef struct
|
|||||||
KSPIN_LOCK SpinLock;
|
KSPIN_LOCK SpinLock;
|
||||||
LONG RefCount;
|
LONG RefCount;
|
||||||
UINT32 Kind;
|
UINT32 Kind;
|
||||||
GUID SiloContainerId;
|
FSP_DEVICE_TIMER DeviceTimer; /* IoTimer emulation */
|
||||||
/* IoTimer emulation */
|
LONG DidIoDeleteDevice;
|
||||||
FSP_DEVICE_TIMER DeviceTimer;
|
|
||||||
} FSP_DEVICE_EXTENSION;
|
} FSP_DEVICE_EXTENSION;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -1232,13 +1247,18 @@ typedef struct
|
|||||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
/* read-only after creation (and insertion in the ContextTable) */
|
||||||
FSP_DEVICE_EXTENSION Base;
|
FSP_DEVICE_EXTENSION Base;
|
||||||
UINT16 SectorSize;
|
UINT16 SectorSize;
|
||||||
LONG IsMountdev;
|
|
||||||
BOOLEAN Persistent;
|
|
||||||
GUID UniqueId;
|
|
||||||
UNICODE_STRING VolumeName;
|
UNICODE_STRING VolumeName;
|
||||||
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||||
|
FAST_MUTEX MountMutex;
|
||||||
|
/* interlocked access */
|
||||||
|
LONG IsMountdev;
|
||||||
|
/* protected under MountMutex */
|
||||||
|
BOOLEAN Persistent;
|
||||||
|
GUID UniqueId;
|
||||||
|
UNICODE_STRING MountPoint;
|
||||||
} FSP_FSVRT_DEVICE_EXTENSION;
|
} FSP_FSVRT_DEVICE_EXTENSION;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -1280,6 +1300,7 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
|||||||
PDEVICE_OBJECT *PDeviceObject);
|
PDEVICE_OBJECT *PDeviceObject);
|
||||||
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
|
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
||||||
|
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject);
|
||||||
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
||||||
static inline
|
static inline
|
||||||
@ -1435,6 +1456,18 @@ BOOLEAN FspFsvolDeviceVolumePrefixInString(PDEVICE_OBJECT DeviceObject, PUNICODE
|
|||||||
TRUE);
|
TRUE);
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
|
VOID FspFsvrtDeviceLockMount(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
ExAcquireFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
VOID FspFsvrtDeviceUnlockMount(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
ExReleaseFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
VOID FspFsmupDeviceLockPrefixTable(PDEVICE_OBJECT DeviceObject)
|
VOID FspFsmupDeviceLockPrefixTable(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
||||||
@ -1450,7 +1483,6 @@ NTSTATUS FspDeviceCopyList(
|
|||||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
||||||
VOID FspDeviceDeleteList(
|
VOID FspDeviceDeleteList(
|
||||||
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
|
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
|
||||||
VOID FspDeviceDeleteAll(VOID);
|
|
||||||
NTSTATUS FspDeviceInitializeAllTimers(VOID);
|
NTSTATUS FspDeviceInitializeAllTimers(VOID);
|
||||||
VOID FspDeviceFinalizeAllTimers(VOID);
|
VOID FspDeviceFinalizeAllTimers(VOID);
|
||||||
NTSTATUS FspDeviceInitializeTimer(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS FspDeviceInitializeTimer(PDEVICE_OBJECT DeviceObject,
|
||||||
@ -1524,6 +1556,16 @@ NTSTATUS FspMountdevMake(
|
|||||||
VOID FspMountdevFini(
|
VOID FspMountdevFini(
|
||||||
PDEVICE_OBJECT FsvrtDeviceObject);
|
PDEVICE_OBJECT FsvrtDeviceObject);
|
||||||
|
|
||||||
|
/* mountmgr */
|
||||||
|
NTSTATUS FspMountmgrCreateDrive(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrDeleteDrive(
|
||||||
|
PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||||
|
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||||
|
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||||
|
|
||||||
/* fsmup */
|
/* fsmup */
|
||||||
NTSTATUS FspMupRegister(
|
NTSTATUS FspMupRegister(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
@ -1543,6 +1585,8 @@ NTSTATUS FspVolumeMount(
|
|||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeMakeMountdev(
|
NTSTATUS FspVolumeMakeMountdev(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeUseMountmgr(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetName(
|
NTSTATUS FspVolumeGetName(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetNameList(
|
NTSTATUS FspVolumeGetNameList(
|
||||||
@ -1970,6 +2014,8 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
|
|||||||
extern PDRIVER_OBJECT FspDriverObject;
|
extern PDRIVER_OBJECT FspDriverObject;
|
||||||
extern FAST_IO_DISPATCH FspFastIoDispatch;
|
extern FAST_IO_DISPATCH FspFastIoDispatch;
|
||||||
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||||
|
extern FAST_MUTEX FspDriverUnloadMutex;
|
||||||
|
extern BOOLEAN FspDriverUnloadDone;
|
||||||
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
||||||
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
|
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
|
||||||
extern FAST_MUTEX FspDeviceGlobalMutex;
|
extern FAST_MUTEX FspDeviceGlobalMutex;
|
||||||
|
@ -8,7 +8,7 @@ Provider = !Provider!
|
|||||||
[DestinationDirs]
|
[DestinationDirs]
|
||||||
DefaultDestDir = 12
|
DefaultDestDir = 12
|
||||||
|
|
||||||
[DefaultInstall]
|
[DefaultInstall.!ArchDecoration!]
|
||||||
CopyFiles = Driver.CopyFiles
|
CopyFiles = Driver.CopyFiles
|
||||||
|
|
||||||
[Driver.CopyFiles]
|
[Driver.CopyFiles]
|
||||||
|
@ -1475,7 +1475,7 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
|
|||||||
{
|
{
|
||||||
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
||||||
DescendantFileNodes[DescendantFileNodeIndex] =
|
DescendantFileNodes[DescendantFileNodeIndex] =
|
||||||
(PVOID)((UINT_PTR)DescendantFileNode | 2);
|
(PVOID)((UINT_PTR)DescendantFileNode | 4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Result = STATUS_ACCESS_DENIED;
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
@ -33,6 +33,8 @@ static NTSTATUS FspFsvolQueryBasicInformation(PFILE_OBJECT FileObject,
|
|||||||
static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd,
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
static NTSTATUS FspFsvolQueryIdInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd);
|
||||||
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd);
|
PVOID *PBuffer, PVOID BufferEnd);
|
||||||
static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject,
|
||||||
@ -106,6 +108,7 @@ FAST_IO_QUERY_OPEN FspFastIoQueryOpen;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolQueryAttributeTagInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryAttributeTagInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryBasicInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryBasicInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEaInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryEaInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryIdInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInternalInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryInternalInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryNameInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryNameInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
||||||
@ -288,6 +291,32 @@ static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryIdInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PFILE_ID_INFORMATION Info = (PFILE_ID_INFORMATION)*PBuffer;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UINT64 IndexNumber;
|
||||||
|
FILE_ID_128 FileId;
|
||||||
|
} FileIdBuf = { .IndexNumber = FileNode->IndexNumber };
|
||||||
|
|
||||||
|
if ((PVOID)(Info + 1) > BufferEnd)
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
Info->VolumeSerialNumber = FsvolDeviceExtension->VolumeParams.VolumeSerialNumber;
|
||||||
|
Info->FileId = FileIdBuf.FileId;
|
||||||
|
|
||||||
|
*PBuffer = (PVOID)(Info + 1);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd)
|
PVOID *PBuffer, PVOID BufferEnd)
|
||||||
{
|
{
|
||||||
@ -961,6 +990,10 @@ static NTSTATUS FspFsvolQueryInformation(
|
|||||||
case FileHardLinkInformation:
|
case FileHardLinkInformation:
|
||||||
Result = STATUS_NOT_SUPPORTED; /* no hard link support */
|
Result = STATUS_NOT_SUPPORTED; /* no hard link support */
|
||||||
return Result;
|
return Result;
|
||||||
|
case FileIdInformation:
|
||||||
|
Result = FspFsvolQueryIdInformation(FileObject, &Buffer, BufferEnd);
|
||||||
|
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
|
||||||
|
return Result;
|
||||||
case FileInternalInformation:
|
case FileInternalInformation:
|
||||||
Result = FspFsvolQueryInternalInformation(FileObject, &Buffer, BufferEnd);
|
Result = FspFsvolQueryInternalInformation(FileObject, &Buffer, BufferEnd);
|
||||||
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
|
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
|
||||||
|
@ -81,6 +81,10 @@ static NTSTATUS FspFsctlFileSystemControl(
|
|||||||
if (0 != IrpSp->FileObject->FsContext2)
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
Result = FspVolumeMakeMountdev(FsctlDeviceObject, Irp, IrpSp);
|
Result = FspVolumeMakeMountdev(FsctlDeviceObject, Irp, IrpSp);
|
||||||
break;
|
break;
|
||||||
|
case FSP_FSCTL_MOUNTMGR:
|
||||||
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
|
Result = FspVolumeUseMountmgr(FsctlDeviceObject, Irp, IrpSp);
|
||||||
|
break;
|
||||||
case FSP_FSCTL_VOLUME_NAME:
|
case FSP_FSCTL_VOLUME_NAME:
|
||||||
if (0 != IrpSp->FileObject->FsContext2)
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);
|
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);
|
||||||
@ -124,6 +128,9 @@ static NTSTATUS FspFsctlFileSystemControl(
|
|||||||
if (0 != IrpSp->FileObject->FsContext2)
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
Result = FspVolumeNotify(FsctlDeviceObject, Irp, IrpSp);
|
Result = FspVolumeNotify(FsctlDeviceObject, Irp, IrpSp);
|
||||||
break;
|
break;
|
||||||
|
case FSP_FSCTL_UNLOAD:
|
||||||
|
Result = FspDriverUnload(FsctlDeviceObject, Irp, IrpSp);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (CTL_CODE(0, 0xC00, 0, 0) ==
|
if (CTL_CODE(0, 0xC00, 0, 0) ==
|
||||||
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)))
|
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)))
|
||||||
|
@ -138,7 +138,7 @@ NTSTATUS FspMountdevMake(
|
|||||||
* be mounted using the MountManager.
|
* be mounted using the MountManager.
|
||||||
*
|
*
|
||||||
* This function requires protection against concurrency. In general this
|
* This function requires protection against concurrency. In general this
|
||||||
* is achieved by acquiring the GlobalDeviceLock.
|
* is achieved by the caller acquiring the MountMutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -178,11 +178,6 @@ NTSTATUS FspMountdevMake(
|
|||||||
|
|
||||||
/* initialize the fsvrt device extension */
|
/* initialize the fsvrt device extension */
|
||||||
RtlCopyMemory(&FsvrtDeviceExtension->UniqueId, &Guid, sizeof Guid);
|
RtlCopyMemory(&FsvrtDeviceExtension->UniqueId, &Guid, sizeof Guid);
|
||||||
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
|
||||||
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
|
||||||
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
|
||||||
|
|
||||||
/* mark the fsvrt device as initialized */
|
|
||||||
InterlockedIncrement(&FspFsvrtDeviceExtension(FsvrtDeviceObject)->IsMountdev);
|
InterlockedIncrement(&FspFsvrtDeviceExtension(FsvrtDeviceObject)->IsMountdev);
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
@ -123,6 +123,27 @@ NTSTATUS FspProcessBufferInitialize(VOID)
|
|||||||
VOID FspProcessBufferFinalize(VOID)
|
VOID FspProcessBufferFinalize(VOID)
|
||||||
{
|
{
|
||||||
PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, TRUE);
|
PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free any items in our process hash table.
|
||||||
|
* Any virtual memory was released when the corresponding processes went away.
|
||||||
|
*/
|
||||||
|
for (ULONG HashIndex = 0; ProcessBufferBucketCount > HashIndex; HashIndex++)
|
||||||
|
{
|
||||||
|
for (FSP_PROCESS_BUFFER_ITEM *Item = ProcessBufferBuckets[HashIndex], *DictNext; Item; Item = DictNext)
|
||||||
|
{
|
||||||
|
for (FSP_PROCESS_BUFFER_LIST_ENTRY *P = Item->BufferList, *Next; P; P = Next)
|
||||||
|
{
|
||||||
|
Next = P->Next;
|
||||||
|
FspFree(P);
|
||||||
|
}
|
||||||
|
|
||||||
|
DictNext = Item->DictNext;
|
||||||
|
FspFree(Item);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessBufferBuckets[HashIndex] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
|
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
|
||||||
|
@ -22,9 +22,11 @@
|
|||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
||||||
|
NTSTATUS FspSiloPostInitialize(VOID);
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(INIT, FspSiloInitialize)
|
#pragma alloc_text(INIT, FspSiloInitialize)
|
||||||
|
#pragma alloc_text(INIT, FspSiloPostInitialize)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef PEJOB FSP_PESILO;
|
typedef PEJOB FSP_PESILO;
|
||||||
@ -108,6 +110,9 @@ static FSP_SILO_INIT_CALLBACK FspSiloInitCallback;
|
|||||||
static FSP_SILO_FINI_CALLBACK FspSiloFiniCallback;
|
static FSP_SILO_FINI_CALLBACK FspSiloFiniCallback;
|
||||||
static BOOLEAN FspSiloInitDone = FALSE;
|
static BOOLEAN FspSiloInitDone = FALSE;
|
||||||
|
|
||||||
|
static FAST_MUTEX FspSiloListMutex;
|
||||||
|
static LIST_ENTRY FspSiloList;
|
||||||
|
|
||||||
static FSP_SILO_GLOBALS FspSiloHostGlobals;
|
static FSP_SILO_GLOBALS FspSiloHostGlobals;
|
||||||
|
|
||||||
#define FSP_SILO_MONITOR_REGISTRATION_VERSION 1
|
#define FSP_SILO_MONITOR_REGISTRATION_VERSION 1
|
||||||
@ -123,6 +128,11 @@ static FSP_SILO_GLOBALS FspSiloHostGlobals;
|
|||||||
}
|
}
|
||||||
#define CALL(n) (FspSilo ## n)
|
#define CALL(n) (FspSilo ## n)
|
||||||
|
|
||||||
|
BOOLEAN FspSiloIsHost(VOID)
|
||||||
|
{
|
||||||
|
return !FspSiloInitDone || 0 == CALL(PsGetCurrentServerSilo)();
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals)
|
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals)
|
||||||
{
|
{
|
||||||
FSP_PESILO Silo;
|
FSP_PESILO Silo;
|
||||||
@ -189,6 +199,7 @@ static NTSTATUS NTAPI FspSiloMonitorCreateCallback(FSP_PESILO Silo)
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
RtlZeroMemory(Globals, sizeof(FSP_SILO_GLOBALS));
|
RtlZeroMemory(Globals, sizeof(FSP_SILO_GLOBALS));
|
||||||
|
Globals->Silo = Silo;
|
||||||
|
|
||||||
/* PsInsertSiloContext adds reference to Globals */
|
/* PsInsertSiloContext adds reference to Globals */
|
||||||
Result = CALL(PsInsertSiloContext)(Silo, ContextSlot, Globals);
|
Result = CALL(PsInsertSiloContext)(Silo, ContextSlot, Globals);
|
||||||
@ -196,6 +207,9 @@ static NTSTATUS NTAPI FspSiloMonitorCreateCallback(FSP_PESILO Silo)
|
|||||||
goto exit;
|
goto exit;
|
||||||
Inserted = TRUE;
|
Inserted = TRUE;
|
||||||
|
|
||||||
|
FsRtlEnterFileSystem();
|
||||||
|
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
|
||||||
if (0 != FspSiloInitCallback)
|
if (0 != FspSiloInitCallback)
|
||||||
{
|
{
|
||||||
FSP_PESILO PreviousSilo = CALL(PsAttachSiloToCurrentThread)(Silo);
|
FSP_PESILO PreviousSilo = CALL(PsAttachSiloToCurrentThread)(Silo);
|
||||||
@ -203,6 +217,12 @@ static NTSTATUS NTAPI FspSiloMonitorCreateCallback(FSP_PESILO Silo)
|
|||||||
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
InsertTailList(&FspSiloList, &Globals->ListEntry);
|
||||||
|
|
||||||
|
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
FsRtlExitFileSystem();
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
@ -237,6 +257,11 @@ static VOID NTAPI FspSiloMonitorTerminateCallback(FSP_PESILO Silo)
|
|||||||
Result = CALL(PsGetSiloContext)(Silo, ContextSlot, &Globals);
|
Result = CALL(PsGetSiloContext)(Silo, ContextSlot, &Globals);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
FsRtlEnterFileSystem();
|
||||||
|
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
|
||||||
|
RemoveEntryList(&Globals->ListEntry);
|
||||||
CALL(PsDereferenceSiloContext)(Globals);
|
CALL(PsDereferenceSiloContext)(Globals);
|
||||||
Globals = 0;
|
Globals = 0;
|
||||||
|
|
||||||
@ -247,6 +272,9 @@ static VOID NTAPI FspSiloMonitorTerminateCallback(FSP_PESILO Silo)
|
|||||||
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
FsRtlExitFileSystem();
|
||||||
|
|
||||||
/* PsRemoveSiloContext removes reference to Globals (possibly freeing it) */
|
/* PsRemoveSiloContext removes reference to Globals (possibly freeing it) */
|
||||||
CALL(PsRemoveSiloContext)(Silo, ContextSlot, 0);
|
CALL(PsRemoveSiloContext)(Silo, ContextSlot, 0);
|
||||||
}
|
}
|
||||||
@ -255,6 +283,9 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
|||||||
{
|
{
|
||||||
NTSTATUS Result = STATUS_SUCCESS;
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
ExInitializeFastMutex(&FspSiloListMutex);
|
||||||
|
InitializeListHead(&FspSiloList);
|
||||||
|
|
||||||
if (FspIsNtDdiVersionAvailable(NTDDI_WIN10_RS5))
|
if (FspIsNtDdiVersionAvailable(NTDDI_WIN10_RS5))
|
||||||
{
|
{
|
||||||
ULONG Fail = 0;
|
ULONG Fail = 0;
|
||||||
@ -293,15 +324,11 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
Result = CALL(PsStartSiloMonitor)(Monitor);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
FspSiloMonitor = Monitor;
|
FspSiloMonitor = Monitor;
|
||||||
FspSiloInitCallback = Init;
|
FspSiloInitCallback = Init;
|
||||||
FspSiloFiniCallback = Fini;
|
FspSiloFiniCallback = Fini;
|
||||||
|
|
||||||
FspSiloInitDone = TRUE;
|
FspSiloInitDone = TRUE;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -316,10 +343,62 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspSiloPostInitialize(VOID)
|
||||||
|
{
|
||||||
|
if (!FspSiloInitDone)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
return CALL(PsStartSiloMonitor)(FspSiloMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspSiloFinalize(VOID)
|
VOID FspSiloFinalize(VOID)
|
||||||
{
|
{
|
||||||
if (!FspSiloInitDone)
|
if (!FspSiloInitDone)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CALL(PsUnregisterSiloMonitor)(FspSiloMonitor);
|
CALL(PsUnregisterSiloMonitor)(FspSiloMonitor);
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
FsRtlEnterFileSystem();
|
||||||
|
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
ASSERT(IsListEmpty(&FspSiloList));
|
||||||
|
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
FsRtlExitFileSystem();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FspSiloMonitor = 0;
|
||||||
|
FspSiloInitCallback = 0;
|
||||||
|
FspSiloFiniCallback = 0;
|
||||||
|
FspSiloInitDone = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspSiloEnumerate(FSP_SILO_ENUM_CALLBACK EnumFn)
|
||||||
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
FSP_SILO_GLOBALS *Globals;
|
||||||
|
|
||||||
|
FsRtlEnterFileSystem();
|
||||||
|
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
|
||||||
|
if (!IsListEmpty(&FspSiloList))
|
||||||
|
{
|
||||||
|
KeStackAttachProcess(PsInitialSystemProcess, &ApcState);
|
||||||
|
|
||||||
|
for (ListEntry = FspSiloList.Flink;
|
||||||
|
&FspSiloList != ListEntry;
|
||||||
|
ListEntry = ListEntry->Flink)
|
||||||
|
{
|
||||||
|
Globals = CONTAINING_RECORD(ListEntry, FSP_SILO_GLOBALS, ListEntry);
|
||||||
|
|
||||||
|
FSP_PESILO PreviousSilo = CALL(PsAttachSiloToCurrentThread)(Globals->Silo);
|
||||||
|
EnumFn();
|
||||||
|
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||||
|
FsRtlExitFileSystem();
|
||||||
}
|
}
|
||||||
|
71
src/sys/sxs.c
Normal file
71
src/sys/sxs.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* @file sys/sxs.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2022 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName);
|
||||||
|
PUNICODE_STRING FspSxsIdent(VOID);
|
||||||
|
PUNICODE_STRING FspSxsSuffix(VOID);
|
||||||
|
|
||||||
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(INIT, FspSxsIdentInitialize)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static WCHAR FspSxsIdentBuf[32 + 1] = L"";
|
||||||
|
static UNICODE_STRING FspSxsIdentStr = { 0, sizeof FspSxsIdentBuf - 1, FspSxsIdentBuf + 1 };
|
||||||
|
static UNICODE_STRING FspSxsSuffixStr = { 0, sizeof FspSxsIdentBuf, FspSxsIdentBuf };
|
||||||
|
|
||||||
|
VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName)
|
||||||
|
{
|
||||||
|
PWCHAR Ident = 0;
|
||||||
|
USHORT Length;
|
||||||
|
|
||||||
|
for (PWCHAR P = DriverName->Buffer + DriverName->Length / sizeof(WCHAR) - 1; DriverName->Buffer <= P; P--)
|
||||||
|
{
|
||||||
|
if (L'\\' == *P)
|
||||||
|
break;
|
||||||
|
if (FSP_SXS_SEPARATOR_CHAR == *P)
|
||||||
|
{
|
||||||
|
Ident = P;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 == Ident)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Length = (USHORT)(((PUINT8)DriverName->Buffer + DriverName->Length) - (PUINT8)Ident);
|
||||||
|
if (Length > sizeof FspSxsIdentBuf)
|
||||||
|
Length = sizeof FspSxsIdentBuf;
|
||||||
|
|
||||||
|
RtlCopyMemory(FspSxsIdentBuf, Ident, Length);
|
||||||
|
FspSxsIdentStr.Length = Length - sizeof(WCHAR);
|
||||||
|
FspSxsSuffixStr.Length = Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
PUNICODE_STRING FspSxsIdent(VOID)
|
||||||
|
{
|
||||||
|
return &FspSxsIdentStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PUNICODE_STRING FspSxsSuffix(VOID)
|
||||||
|
{
|
||||||
|
return &FspSxsSuffixStr;
|
||||||
|
}
|
211
src/sys/volume.c
211
src/sys/volume.c
@ -38,6 +38,8 @@ static NTSTATUS FspVolumeMountNoLock(
|
|||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeMakeMountdev(
|
NTSTATUS FspVolumeMakeMountdev(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeUseMountmgr(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetName(
|
NTSTATUS FspVolumeGetName(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetNameList(
|
NTSTATUS FspVolumeGetNameList(
|
||||||
@ -76,6 +78,7 @@ NTSTATUS FspVolumeWork(
|
|||||||
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
||||||
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
||||||
#pragma alloc_text(PAGE, FspVolumeMakeMountdev)
|
#pragma alloc_text(PAGE, FspVolumeMakeMountdev)
|
||||||
|
#pragma alloc_text(PAGE, FspVolumeUseMountmgr)
|
||||||
#pragma alloc_text(PAGE, FspVolumeGetName)
|
#pragma alloc_text(PAGE, FspVolumeGetName)
|
||||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||||
@ -110,6 +113,57 @@ NTSTATUS FspVolumeCreate(
|
|||||||
|
|
||||||
FspSiloDereferenceGlobals(Globals);
|
FspSiloDereferenceGlobals(Globals);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If we have an fsvrt device, mount it NOW via opening the volume. This ensures
|
||||||
|
* that the fsvrt is mounted by the correct fsvol device early on and remedies
|
||||||
|
* a rare case where NTFS crashes the system when it attempts to mount our fsvrt.
|
||||||
|
*
|
||||||
|
* We use IoCreateFileEx with FILE_READ_DATA to ensure that the I/O Manager will
|
||||||
|
* mount the fsvrt device.
|
||||||
|
*
|
||||||
|
* We ignore the IoCreateFileEx return code as it is only used for its side effect
|
||||||
|
* of mounting the fsvrt. In the unlikely event that IoCreateFileEx fails, the
|
||||||
|
* system will retry the mount when a file is accessed, etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
HANDLE Handle;
|
||||||
|
|
||||||
|
if (0 != FsvrtDeviceObject)
|
||||||
|
{
|
||||||
|
InitializeObjectAttributes(
|
||||||
|
&ObjectAttributes,
|
||||||
|
&FsvolDeviceExtension->VolumeName,
|
||||||
|
OBJ_KERNEL_HANDLE,
|
||||||
|
0/*RootDirectory*/,
|
||||||
|
0/*SecurityDescriptor*/);
|
||||||
|
IoStatus.Status = IoCreateFileEx(
|
||||||
|
&Handle,
|
||||||
|
FILE_READ_DATA,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatus,
|
||||||
|
0/*AllocationSize*/,
|
||||||
|
0/*FileAttributes*/,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
FILE_OPEN,
|
||||||
|
0/*CreateOptions*/,
|
||||||
|
0/*EaBuffer*/,
|
||||||
|
0/*EaLength*/,
|
||||||
|
CreateFileTypeNone,
|
||||||
|
0/*InternalParameters*/,
|
||||||
|
0/*Options*/,
|
||||||
|
0/*DriverContext*/);
|
||||||
|
if (NT_SUCCESS(IoStatus.Status))
|
||||||
|
ObCloseHandle(Handle, KernelMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,6 +300,11 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
VolumeParams.AlwaysUseDoubleBuffering = 1;
|
VolumeParams.AlwaysUseDoubleBuffering = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hardcode the RejectIrpPriorToTransact0 = 1 setting.
|
||||||
|
*/
|
||||||
|
VolumeParams.RejectIrpPriorToTransact0 = 1;
|
||||||
|
|
||||||
/* load any fsext provider */
|
/* load any fsext provider */
|
||||||
if (0 != VolumeParams.FsextControlCode)
|
if (0 != VolumeParams.FsextControlCode)
|
||||||
{
|
{
|
||||||
@ -316,8 +375,12 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
{
|
{
|
||||||
if (0 != FsvrtDeviceObject)
|
if (0 != FsvrtDeviceObject)
|
||||||
{
|
{
|
||||||
FspFsvrtDeviceExtension(FsvrtDeviceObject)->SectorSize =
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
FsvolDeviceExtension->VolumeParams.SectorSize;
|
FsvrtDeviceExtension->SectorSize = FsvolDeviceExtension->VolumeParams.SectorSize;
|
||||||
|
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
||||||
|
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
||||||
|
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
||||||
|
|
||||||
Result = FspDeviceInitialize(FsvrtDeviceObject);
|
Result = FspDeviceInitialize(FsvrtDeviceObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -638,7 +701,7 @@ NTSTATUS FspVolumeMakeMountdev(
|
|||||||
if (sizeof(GUID) > OutputBufferLength)
|
if (sizeof(GUID) > OutputBufferLength)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
FspDeviceGlobalLock();
|
FspFsvrtDeviceLockMount(FsvrtDeviceObject);
|
||||||
|
|
||||||
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -654,7 +717,147 @@ NTSTATUS FspVolumeMakeMountdev(
|
|||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
FspDeviceGlobalUnlock();
|
FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspVolumeUseMountmgr(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
||||||
|
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||||
|
ASSERT(FSP_FSCTL_MOUNTMGR == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||||
|
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||||
|
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == FsvrtDeviceObject)
|
||||||
|
return STATUS_INVALID_PARAMETER; /* cannot only use fsvrt with mount manager */
|
||||||
|
if (1024 * sizeof(WCHAR) < InputBufferLength)
|
||||||
|
return STATUS_INVALID_PARAMETER; /* disallow very long paths */
|
||||||
|
|
||||||
|
FspFsvrtDeviceLockMount(FsvrtDeviceObject);
|
||||||
|
|
||||||
|
if (0 < InputBufferLength)
|
||||||
|
{
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
PWCHAR MountPointBuf = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
UNICODE_STRING RegPath;
|
||||||
|
UNICODE_STRING RegName;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
KEY_VALUE_PARTIAL_INFORMATION V;
|
||||||
|
UINT8 B[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
|
||||||
|
} RegValue;
|
||||||
|
ULONG RegLength;
|
||||||
|
BOOLEAN Persistent = FALSE;
|
||||||
|
|
||||||
|
if (!(
|
||||||
|
2 * sizeof(WCHAR) <= InputBufferLength &&
|
||||||
|
(
|
||||||
|
(L'A' <= MountPointBuf[0] && MountPointBuf[0] <= L'Z') ||
|
||||||
|
(L'a' <= MountPointBuf[0] && MountPointBuf[0] <= L'z')
|
||||||
|
) &&
|
||||||
|
L':' == MountPointBuf[1]
|
||||||
|
))
|
||||||
|
{
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
|
||||||
|
{
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&RegPath, L"" FSP_REGKEY);
|
||||||
|
RtlInitUnicodeString(&RegName, L"MountUseMountmgrFromFSD");
|
||||||
|
RegLength = sizeof RegValue;
|
||||||
|
Result = FspRegistryGetValue(&RegPath, &RegName, &RegValue.V, &RegLength);
|
||||||
|
if (!NT_SUCCESS(Result) || REG_DWORD != RegValue.V.Type || 1 != *(PULONG)&RegValue.V.Data)
|
||||||
|
{
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (STATUS_TOO_LATE != Result)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
FsvrtDeviceExtension->MountPoint.Buffer = FspAllocNonPaged(InputBufferLength);
|
||||||
|
if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
FsvrtDeviceExtension->MountPoint.Length =
|
||||||
|
FsvrtDeviceExtension->MountPoint.MaximumLength = (USHORT)InputBufferLength;
|
||||||
|
RtlCopyMemory(FsvrtDeviceExtension->MountPoint.Buffer, MountPointBuf, InputBufferLength);
|
||||||
|
|
||||||
|
if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
|
||||||
|
Result = FspMountmgrCreateDrive(
|
||||||
|
&FsvrtDeviceExtension->VolumeName,
|
||||||
|
&FsvrtDeviceExtension->UniqueId,
|
||||||
|
&FsvrtDeviceExtension->MountPoint);
|
||||||
|
else
|
||||||
|
Result = FspMountmgrNotifyCreateDirectory(
|
||||||
|
&FsvrtDeviceExtension->VolumeName,
|
||||||
|
&FsvrtDeviceExtension->UniqueId,
|
||||||
|
&FsvrtDeviceExtension->MountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||||
|
FsvrtDeviceExtension->MountPoint.Buffer = 0;
|
||||||
|
FsvrtDeviceExtension->MountPoint.Length =
|
||||||
|
FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
|
||||||
|
if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
|
||||||
|
{
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
|
||||||
|
Result = FspMountmgrDeleteDrive(
|
||||||
|
&FsvrtDeviceExtension->MountPoint);
|
||||||
|
else
|
||||||
|
Result = FspMountmgrNotifyDeleteDirectory(
|
||||||
|
&FsvrtDeviceExtension->VolumeName,
|
||||||
|
&FsvrtDeviceExtension->MountPoint);
|
||||||
|
/* ignore Result */
|
||||||
|
|
||||||
|
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||||
|
FsvrtDeviceExtension->MountPoint.Buffer = 0;
|
||||||
|
FsvrtDeviceExtension->MountPoint.Length =
|
||||||
|
FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIFOzCCAyOgAwIBAgIKYSBNtAAAAAAAJzANBgkqhkiG9w0BAQUFADB/MQswCQYD
|
|
||||||
VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
|
|
||||||
MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv
|
|
||||||
ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTA0MTUxOTQ1MzNaFw0yMTA0
|
|
||||||
MTUxOTU1MzNaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
|
|
||||||
GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhp
|
|
||||||
Z2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
|
||||||
ggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD1ZQ0Z6IKHLBfaaZAscS3
|
|
||||||
so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80ltcZF+Y7arpl/DpIT4T2JR
|
|
||||||
vvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46OFBbdzEbjbPHJEWap6xt
|
|
||||||
ABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZdHFMsfpjNGgYWpGhz0DQE
|
|
||||||
E1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdmt4i3ePLKCqg4qwpkwr9m
|
|
||||||
XZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjgcswgcgwEQYDVR0gBAowCDAG
|
|
||||||
BgRVHSAAMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSx
|
|
||||||
PsNpA/i/RwHUmCYaCALvY2QrwzAfBgNVHSMEGDAWgBRi+wohW39DbhHaCVRQa/XS
|
|
||||||
lnHxnjBVBgNVHR8ETjBMMEqgSKBGhkRodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
|
|
||||||
cGtpL2NybC9wcm9kdWN0cy9NaWNyb3NvZnRDb2RlVmVyaWZSb290LmNybDANBgkq
|
|
||||||
hkiG9w0BAQUFAAOCAgEAIIzBWe1vnGstwUo+dR1FTEFQHL2A6tmwkosGKhM/Uxae
|
|
||||||
VjlqimO2eCR59X24uUehCpbC9su9omafBuGs0nkJDv083KwCDHCvPxvseH7U60sF
|
|
||||||
YCbZc2GRIe2waGPglxKrb6AS7dmf0tonPLPkVvnR1IEPcb1CfKaJ3M3VvZWiq/GT
|
|
||||||
EX3orDEpqF1mcEGd/HXJ1bMaOSrQhQVQi6yRysSTy3GlnaSUb1gM+m4gxAgxtYWd
|
|
||||||
foH50j3KWxiFbAqG7CIJG6V0NE9/KLyVSqsdtpiwXQmkd3Z+76eOXYT2GCTL0W2m
|
|
||||||
w6GcwhB1gP+dMv3mz0M6gvfOj+FyKptit1/tlRo5XC+UbUi3AV8zL7vcLXM0iQRC
|
|
||||||
ChyLefmj+hfv+qEaEN/gssGV61wMBZc7NT4YiE3bbL8kiY3Ivdifezk6JKDV39Hz
|
|
||||||
ShqX9qZveh+wkKmzrAE5kdNht2TxPlc4A6/OetK1kPWu3DmZ1bY8l+2myxbHfWsq
|
|
||||||
TJCU5kxU/R7NIOzOaJyHWOlhYL7rDsnVGX2f6Xi9DqwhdQePqW7gjGoqa5zj52W8
|
|
||||||
vC08bdwE3GdFNjKvBIG8qABuYUyVxVzUjo6fL8EydL29EWUDB83vt14CV9qG1Boo
|
|
||||||
NK+ISbLPpd2CVm9oqhTiWVT+/+ru7+qScCJggeMlI8CfzA9JsjWqWMM6w9kWlBA=
|
|
||||||
-----END CERTIFICATE-----
|
|
BIN
tools/DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer
Normal file
BIN
tools/DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer
Normal file
Binary file not shown.
@ -27,6 +27,7 @@ if X%~nx0==Xbuild-choco.bat (
|
|||||||
set BuildArm64=yes
|
set BuildArm64=yes
|
||||||
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
||||||
set BuildArm64=no
|
set BuildArm64=no
|
||||||
|
set UseDotnetSdk=yes
|
||||||
)
|
)
|
||||||
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
|
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
|
||||||
set BuildArm64=no
|
set BuildArm64=no
|
||||||
@ -42,8 +43,11 @@ call "%~dp0vcvarsall.bat" x64
|
|||||||
if not X%SignedPackage%==X (
|
if not X%SignedPackage%==X (
|
||||||
if not exist "%~dp0..\build\VStudio\build\%Configuration%\%MyProductFileName%-*.msi" (echo previous build not found >&2 & exit /b 1)
|
if not exist "%~dp0..\build\VStudio\build\%Configuration%\%MyProductFileName%-*.msi" (echo previous build not found >&2 & exit /b 1)
|
||||||
if not exist "%SignedPackage%" (echo signed package not found >&2 & exit /b 1)
|
if not exist "%SignedPackage%" (echo signed package not found >&2 & exit /b 1)
|
||||||
|
set Version=
|
||||||
|
for %%f in (build\%Configuration%\%MyProductFileName%-*.msi) do set Version=%%~nf
|
||||||
|
set Version=!Version:%MyProductFileName%-=!
|
||||||
del "%~dp0..\build\VStudio\build\%Configuration%\%MyProductFileName%-*.msi"
|
del "%~dp0..\build\VStudio\build\%Configuration%\%MyProductFileName%-*.msi"
|
||||||
if exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg" del "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg"
|
if exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp.!Version!.nupkg" del "%~dp0..\build\VStudio\build\%Configuration%\winfsp.!Version!.nupkg"
|
||||||
for /R "%SignedPackage%" %%f in (*.sys) do (
|
for /R "%SignedPackage%" %%f in (*.sys) do (
|
||||||
copy "%%f" "%~dp0..\build\VStudio\build\%Configuration%" >nul
|
copy "%%f" "%~dp0..\build\VStudio\build\%Configuration%" >nul
|
||||||
)
|
)
|
||||||
@ -70,6 +74,13 @@ if X%SignedPackage%==X (
|
|||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if X%UseDotnetSdk%==Xyes (
|
||||||
|
dotnet build ./dotnet/winfsp.net.csproj -c "%Configuration%" -p:Platform=AnyCPU -p:SolutionDir="%cd%"\
|
||||||
|
if errorlevel 1 goto fail
|
||||||
|
dotnet build ./testing/memfs-dotnet.csproj -c "%Configuration%" -p:Platform=AnyCPU -p:SolutionDir="%cd%"\
|
||||||
|
if errorlevel 1 goto fail
|
||||||
|
)
|
||||||
|
|
||||||
pushd build\%Configuration%
|
pushd build\%Configuration%
|
||||||
set signfiles=^
|
set signfiles=^
|
||||||
%MyProductFileName%-a64.sys %MyProductFileName%-x64.sys %MyProductFileName%-x86.sys^
|
%MyProductFileName%-a64.sys %MyProductFileName%-x64.sys %MyProductFileName%-x86.sys^
|
||||||
@ -78,13 +89,19 @@ if X%SignedPackage%==X (
|
|||||||
launchctl-a64.exe launchctl-x64.exe launchctl-x86.exe^
|
launchctl-a64.exe launchctl-x64.exe launchctl-x86.exe^
|
||||||
fsptool-a64.exe fsptool-x64.exe fsptool-x86.exe^
|
fsptool-a64.exe fsptool-x64.exe fsptool-x86.exe^
|
||||||
memfs-a64.exe memfs-x64.exe memfs-x86.exe memfs-dotnet-msil.exe
|
memfs-a64.exe memfs-x64.exe memfs-x86.exe memfs-dotnet-msil.exe
|
||||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com !signfiles!
|
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 !signfiles!
|
||||||
if errorlevel 1 set /a signfail=signfail+1
|
|
||||||
signtool sign /as /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 !signfiles!
|
|
||||||
if errorlevel 1 set /a signfail=signfail+1
|
if errorlevel 1 set /a signfail=signfail+1
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd build\%Configuration%
|
pushd build\%Configuration%
|
||||||
|
mkdir unsigned
|
||||||
|
for %%f in (!signfiles!) do (
|
||||||
|
copy "%%f" unsigned >nul
|
||||||
|
)
|
||||||
|
pushd unsigned
|
||||||
|
signtool remove /q /s !signfiles!
|
||||||
|
if errorlevel 1 set /a signfail=signfail+1
|
||||||
|
popd
|
||||||
echo .OPTION EXPLICIT >driver.ddf
|
echo .OPTION EXPLICIT >driver.ddf
|
||||||
echo .Set CabinetFileCountThreshold=0 >>driver.ddf
|
echo .Set CabinetFileCountThreshold=0 >>driver.ddf
|
||||||
echo .Set FolderFileCountThreshold=0 >>driver.ddf
|
echo .Set FolderFileCountThreshold=0 >>driver.ddf
|
||||||
@ -99,13 +116,13 @@ if X%SignedPackage%==X (
|
|||||||
echo .Set DiskDirectory1=. >>driver.ddf
|
echo .Set DiskDirectory1=. >>driver.ddf
|
||||||
echo .Set DestinationDir=a64 >>driver.ddf
|
echo .Set DestinationDir=a64 >>driver.ddf
|
||||||
echo driver-a64.inf >>driver.ddf
|
echo driver-a64.inf >>driver.ddf
|
||||||
echo %MyProductFileName%-a64.sys >>driver.ddf
|
echo unsigned\%MyProductFileName%-a64.sys >>driver.ddf
|
||||||
echo .Set DestinationDir=x64 >>driver.ddf
|
echo .Set DestinationDir=x64 >>driver.ddf
|
||||||
echo driver-x64.inf >>driver.ddf
|
echo driver-x64.inf >>driver.ddf
|
||||||
echo %MyProductFileName%-x64.sys >>driver.ddf
|
echo unsigned\%MyProductFileName%-x64.sys >>driver.ddf
|
||||||
echo .Set DestinationDir=x86 >>driver.ddf
|
echo .Set DestinationDir=x86 >>driver.ddf
|
||||||
echo driver-x86.inf >>driver.ddf
|
echo driver-x86.inf >>driver.ddf
|
||||||
echo %MyProductFileName%-x86.sys >>driver.ddf
|
echo unsigned\%MyProductFileName%-x86.sys >>driver.ddf
|
||||||
makecab /F driver.ddf
|
makecab /F driver.ddf
|
||||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 driver.cab
|
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 driver.cab
|
||||||
if errorlevel 1 set /a signfail=signfail+1
|
if errorlevel 1 set /a signfail=signfail+1
|
||||||
@ -116,10 +133,8 @@ devenv winfsp.sln /build "Installer.%Configuration%|x86"
|
|||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
|
|
||||||
for %%f in (build\%Configuration%\%MyProductFileName%-*.msi) do (
|
for %%f in (build\%Configuration%\%MyProductFileName%-*.msi) do (
|
||||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com /d %MsiName% %%f
|
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 /d %MsiName% %%f
|
||||||
if errorlevel 1 set /a signfail=signfail+1
|
if errorlevel 1 set /a signfail=signfail+1
|
||||||
REM signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 /d %MsiName% %%f
|
|
||||||
REM if errorlevel 1 set /a signfail=signfail+1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not %signfail%==0 echo SIGNING FAILED! The product has been successfully built, but not signed.
|
if not %signfail%==0 echo SIGNING FAILED! The product has been successfully built, but not signed.
|
||||||
|
@ -7,7 +7,8 @@ set Config=Debug
|
|||||||
set Suffix=x64
|
set Suffix=x64
|
||||||
set Deploy=C:\Deploy\winfsp
|
set Deploy=C:\Deploy\winfsp
|
||||||
set Target=Win10DBG
|
set Target=Win10DBG
|
||||||
set Chkpnt=winfsp
|
set Chkpnt=docker+winfsp
|
||||||
|
set CImage=mcr.microsoft.com/windows/servercore:1909
|
||||||
if not X%1==X set Target=%1
|
if not X%1==X set Target=%1
|
||||||
if not X%2==X set Chkpnt=%2
|
if not X%2==X set Chkpnt=%2
|
||||||
|
|
||||||
@ -15,6 +16,10 @@ if not X%2==X set Chkpnt=%2
|
|||||||
echo regsvr32 /s winfsp-x64.dll
|
echo regsvr32 /s winfsp-x64.dll
|
||||||
) > %~dp0..\build\VStudio\build\%Config%\deploy-setup.bat
|
) > %~dp0..\build\VStudio\build\%Config%\deploy-setup.bat
|
||||||
|
|
||||||
|
(
|
||||||
|
echo docker run -it --rm --isolation=process -v%Deploy%:%Deploy%:RW %CImage% cmd.exe /k cd %Deploy%
|
||||||
|
) > %~dp0..\build\VStudio\build\%Config%\docker-run.bat
|
||||||
|
|
||||||
set Files=
|
set Files=
|
||||||
for %%f in (
|
for %%f in (
|
||||||
%~dp0..\build\VStudio\build\%Config%\
|
%~dp0..\build\VStudio\build\%Config%\
|
||||||
@ -22,7 +27,9 @@ for %%f in (
|
|||||||
winfsp-%Suffix%.dll
|
winfsp-%Suffix%.dll
|
||||||
winfsp-tests-%Suffix%.exe
|
winfsp-tests-%Suffix%.exe
|
||||||
memfs-%Suffix%.exe
|
memfs-%Suffix%.exe
|
||||||
|
fsptool-%Suffix%.exe
|
||||||
deploy-setup.bat
|
deploy-setup.bat
|
||||||
|
docker-run.bat
|
||||||
) do (
|
) do (
|
||||||
set File=%%~f
|
set File=%%~f
|
||||||
if [!File:~-1!] == [\] (
|
if [!File:~-1!] == [\] (
|
||||||
|
@ -1,28 +1,53 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
setlocal
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
echo WINFSP INSTALLATION DIRECTORY AND LAUNCHER REGISTRATIONS
|
REM Determine the SxS (side-by-side) identifier.
|
||||||
reg query HKLM\SOFTWARE\WinFsp /s /reg:32
|
set SxsDir=
|
||||||
|
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||||
|
set RegVal="SxsDir"
|
||||||
|
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||||
|
if !ERRORLEVEL! equ 0 (
|
||||||
|
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||||
|
set SxsDir=%%j
|
||||||
|
)
|
||||||
|
)
|
||||||
|
set SxsSuffix=
|
||||||
|
if defined SxsDir (
|
||||||
|
set SxsSuffix=!SxsDir:*SxS\sxs.=!
|
||||||
|
if !SxsSuffix:~-1!==\ set SxsSuffix=!SxsSuffix:~0,-1!
|
||||||
|
set SxsSuffix=+!SxsSuffix!
|
||||||
|
)
|
||||||
|
|
||||||
|
echo WINFSP FSD
|
||||||
|
sc query WinFsp!SxsSuffix!
|
||||||
|
sc qc WinFsp!SxsSuffix!
|
||||||
|
sc sdshow WinFsp!SxsSuffix!
|
||||||
|
echo.
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
echo WINFSP DLL REGISTRATIONS
|
echo WINFSP DLL
|
||||||
reg query HKLM\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order
|
reg query HKLM\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order
|
||||||
reg query HKLM\SYSTEM\CurrentControlSet\Services\WinFsp.Np\NetworkProvider
|
reg query HKLM\SYSTEM\CurrentControlSet\Services\WinFsp.Np\NetworkProvider
|
||||||
reg query HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\WinFsp
|
reg query HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\WinFsp
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
echo WINFSP FSD CONFIGURATION AND STATUS
|
echo WINFSP LAUNCHER
|
||||||
sc query WinFsp
|
|
||||||
sc qc WinFsp
|
|
||||||
sc sdshow WinFsp
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo WINFSP LAUNCHER SERVICE CONFIGURATION AND STATUS
|
|
||||||
sc query WinFsp.Launcher
|
sc query WinFsp.Launcher
|
||||||
sc qc WinFsp.Launcher
|
sc qc WinFsp.Launcher
|
||||||
sc sdshow WinFsp.Launcher
|
sc sdshow WinFsp.Launcher
|
||||||
echo.
|
echo.
|
||||||
|
echo.
|
||||||
|
|
||||||
|
echo WINFSP REGISTRY
|
||||||
|
reg query HKLM\SOFTWARE\WinFsp /s /reg:32
|
||||||
|
echo.
|
||||||
|
|
||||||
|
echo FILE SYSTEM FILTERS (REQUIRES ADMINISTRATOR)
|
||||||
|
fltmc filters
|
||||||
|
echo.
|
||||||
|
echo.
|
||||||
|
|
||||||
echo OS INFORMATION
|
echo OS INFORMATION
|
||||||
systeminfo
|
systeminfo
|
||||||
|
17
tools/gensrc/remove-build-dotnet.bat
Normal file
17
tools/gensrc/remove-build-dotnet.bat
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
if "%1"=="" (
|
||||||
|
cd %~dp0..\..
|
||||||
|
) else (
|
||||||
|
cd "%1"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if exist winfsp.sln (
|
||||||
|
powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0remove-sln-project.ps1' -Path '%cd%\winfsp.sln' -Match '*dotnet*'
|
||||||
|
) else (
|
||||||
|
echo winfsp.sln not found in %cd%
|
||||||
|
)
|
12
tools/gensrc/remove-sln-project.ps1
Normal file
12
tools/gensrc/remove-sln-project.ps1
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
param (
|
||||||
|
[Parameter(Mandatory)][string]$Path,
|
||||||
|
[Parameter(Mandatory)][string]$Match
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Removing projects that match $($Match) from $($Path)"
|
||||||
|
|
||||||
|
Get-Content $Path -Delimiter 'EndProject' |
|
||||||
|
Where-Object {$_ -notlike $Match} |
|
||||||
|
Set-Content "$($Path).new"
|
||||||
|
|
||||||
|
Move-Item -Path "$($Path).new" -Destination $Path -Force
|
637
tools/make-release.ps1
Normal file
637
tools/make-release.ps1
Normal file
@ -0,0 +1,637 @@
|
|||||||
|
param (
|
||||||
|
[string]$StateFile = "release.state"
|
||||||
|
)
|
||||||
|
|
||||||
|
function Write-Stdout ($Message) {
|
||||||
|
[System.Console]::WriteLine($Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-Stderr ($Message) {
|
||||||
|
[System.Console]::Error.WriteLine($Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Git-Describe {
|
||||||
|
$GitDesc = git describe --long --dirty
|
||||||
|
if ($GitDesc -match "^(.+)-([0-9]+)-g([0-9A-Fa-f]+)-?(dirty)?$") {
|
||||||
|
$matches[1]
|
||||||
|
$matches[2]
|
||||||
|
$matches[3]
|
||||||
|
$matches[4]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Git-Dirty {
|
||||||
|
$Dirty = $False
|
||||||
|
git status --porcelain=v2 2>$null | ForEach-Object {
|
||||||
|
$Dirty = $True
|
||||||
|
}
|
||||||
|
return $Dirty
|
||||||
|
}
|
||||||
|
|
||||||
|
function Git-LogGrep ($Tag) {
|
||||||
|
git log -n 1 --grep $Tag
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-ReleaseInfo ($Tag) {
|
||||||
|
$Found = 0
|
||||||
|
$ReleaseInfo = [PSCustomObject]@{
|
||||||
|
Tag = ""
|
||||||
|
ProductVersion = ""
|
||||||
|
Prerelease = $False
|
||||||
|
PreviousTag = ""
|
||||||
|
PreviousProductVersion = ""
|
||||||
|
Text = @()
|
||||||
|
}
|
||||||
|
foreach ($Line in Get-Content "$ProjectRoot\Changelog.md") {
|
||||||
|
if ($Line -match "^## (v[^ ]+) *\(([^)]+)\)") {
|
||||||
|
if ($Found) {
|
||||||
|
$Found = 2
|
||||||
|
$PreviousTag = $matches[1]
|
||||||
|
$PreviousProductVersion = $matches[2]
|
||||||
|
if ($PreviousTag -match "^v[0-9.]+$") {
|
||||||
|
$ReleaseInfo.PreviousTag = $PreviousTag
|
||||||
|
$ReleaseInfo.PreviousProductVersion = $PreviousProductVersion
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} elseif ($Tag -eq $matches[1]) {
|
||||||
|
$Found = 1
|
||||||
|
$ReleaseInfo.Tag = $matches[1]
|
||||||
|
$ReleaseInfo.ProductVersion = $matches[2]
|
||||||
|
$ReleaseInfo.Prerelease = !($ReleaseInfo.Tag -match "^v[0-9.]+$")
|
||||||
|
}
|
||||||
|
} elseif (1 -eq $Found) {
|
||||||
|
$ReleaseInfo.Text += $Line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($Found) {
|
||||||
|
return $ReleaseInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-HwapiCredentials {
|
||||||
|
$Credentials = (& "$ProjectRoot\tools\wincred.ps1" get "Hardware Dashboard API")
|
||||||
|
if ($Credentials) {
|
||||||
|
try { $Credentials = ConvertFrom-Json $Credentials[1] } catch {;}
|
||||||
|
}
|
||||||
|
if ($Credentials -and $Credentials.TenantId -and $Credentials.ClientId -and $Credentials.ClientId) {
|
||||||
|
return $Credentials
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-Sdcm {
|
||||||
|
Start-Job -ArgumentList $args -ScriptBlock {
|
||||||
|
$env:SDCM_CREDS_TENANTID = $using:HwapiCredentials.TenantId
|
||||||
|
$env:SDCM_CREDS_CLIENTID = $using:HwapiCredentials.ClientId
|
||||||
|
$env:SDCM_CREDS_KEY = $using:HwapiCredentials.Key
|
||||||
|
$env:SDCM_CREDS_URL = "https://manage.devcenter.microsoft.com"
|
||||||
|
$env:SDCM_CREDS_URLPREFIX = "v2.0/my"
|
||||||
|
& "$using:ProjectRoot\..\winfsp.sdcm\SurfaceDevCenterManager\bin\Debug\sdcm.exe" -creds envonly @args
|
||||||
|
} | Receive-Job -Wait -AutoRemoveJob
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-FileVersion ($FileName) {
|
||||||
|
return [System.Diagnostics.FileVersionInfo]::GetVersionInfo($FileName).FileVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
function Task ($ScriptBlock) {
|
||||||
|
$Name = (Get-PSCallStack)[1].FunctionName
|
||||||
|
if ($State -contains $Name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Stdout $Name
|
||||||
|
Invoke-Command -ScriptBlock $ScriptBlock
|
||||||
|
Write-Stdout "$Name COMPLETE"
|
||||||
|
|
||||||
|
Add-Content $StateFile -Value $Name
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function Check-Prerequisites {
|
||||||
|
$Name = (Get-PSCallStack)[0].FunctionName
|
||||||
|
|
||||||
|
# check git.exe
|
||||||
|
if (!(Get-Command "git.exe" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find git.exe"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check scdm.exe
|
||||||
|
if (!(Get-Command "$ProjectRoot\..\winfsp.sdcm\SurfaceDevCenterManager\bin\Debug\sdcm.exe" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find sdcm.exe"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check gh.exe
|
||||||
|
if (!(Get-Command "gh.exe" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find gh.exe"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check choco.exe
|
||||||
|
if (!(Get-Command "choco.exe" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find choco.exe"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check git tag
|
||||||
|
$Tag, $CommitCount, $Commit, $_ = Git-Describe
|
||||||
|
if ("0" -ne $CommitCount) {
|
||||||
|
Write-Stderr "error: cannot find clean git tag"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check release info
|
||||||
|
$script:ReleaseInfo = Get-ReleaseInfo $Tag
|
||||||
|
if (!$script:ReleaseInfo) {
|
||||||
|
Write-Stderr "error: cannot get release info for tag $Tag"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check winfsp.sym
|
||||||
|
if (!(Test-Path "$ProjectRoot\..\winfsp.sym" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find winfsp.sym repository"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check winfsp.sym git status
|
||||||
|
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||||
|
$SymDirty = Git-Dirty
|
||||||
|
Pop-Location
|
||||||
|
if ($SymDirty) {
|
||||||
|
Write-Stderr "error: winfsp.sym repository is dirty"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check hardware dashboard api credentials
|
||||||
|
$script:HwapiCredentials = Get-HwapiCredentials
|
||||||
|
if (!$script:HwapiCredentials) {
|
||||||
|
Write-Stderr "error: cannot get Hardware Dashboard API credentials"
|
||||||
|
Write-Stderr ' The expected format of the credentials is as follows:'
|
||||||
|
Write-Stderr ' TargetName: Hardware Dashboard API'
|
||||||
|
Write-Stderr ' UserName: Credentials'
|
||||||
|
Write-Stderr ' Password: {"TenantId":"TENANTID","ClientId":"CLIENTID","Key":"KEY"}'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($State -contains $Name) {
|
||||||
|
if (!($State -contains "$Tag-$CommitCount-g$Commit")) {
|
||||||
|
Write-Stderr "error: invalid state for tag $Tag"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Add-Content $StateFile -Value $Name
|
||||||
|
Add-Content $StateFile -Value "$Tag-$CommitCount-g$Commit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Check-Assets {
|
||||||
|
# check driver.cab
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\driver.cab" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find driver.cab"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check winfsp.msi
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find winfsp*.msi"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check winfsp-tests.zip
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp-tests*.zip" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find winfsp-tests*.zip"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check winfsp.net.nupkg
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp.net.*.nupkg" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find winfsp.net.*.nupkg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check winfsp.nupkg
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp.*.nupkg" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find winfsp.*.nupkg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# check winfsp signature
|
||||||
|
if ("Valid" -ne (Get-AuthenticodeSignature "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys" -ErrorAction SilentlyContinue).Status) {
|
||||||
|
Write-Stderr "error: invalid winfsp signature"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-AssetsPhase1 {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Push-Location "$ProjectRoot"
|
||||||
|
tools\build.bat Release
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot build assets"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Assets have been built but are not properly signed.
|
||||||
|
Signable assets are ready for submission to the hardware dashboard.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Submit-AssetsToHwapi {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
$MsiFile = Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi"
|
||||||
|
$MsiName = Split-Path -Leaf $MsiFile
|
||||||
|
if ($MsiName -match "winfsp-(.+)\.msi") {
|
||||||
|
$Version = $matches[1]
|
||||||
|
}
|
||||||
|
if (!$Version) {
|
||||||
|
Write-Stderr "error: cannot determine version for winfsp.msi"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$DocRequestedSignatures = @()
|
||||||
|
$Documentation = Invoke-WebRequest -Uri "https://raw.githubusercontent.com/MicrosoftDocs/windows-driver-docs/staging/windows-driver-docs-pr/dashboard/get-product-data.md"
|
||||||
|
$Documentation = $Documentation.Content
|
||||||
|
$List = $false
|
||||||
|
foreach ($Line in $Documentation -Split "`n") {
|
||||||
|
if ($Line -match "^### List of Operating System Codes") {
|
||||||
|
$List = $true
|
||||||
|
} elseif ($Line -match "^###") {
|
||||||
|
$List = $false
|
||||||
|
} elseif ($List -and $Line -cmatch "\| *(WINDOWS_v100_[^| ]+) *\|") {
|
||||||
|
$DocRequestedSignatures += $matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($DocRequestedSignatures.length -lt 32) {
|
||||||
|
Write-Stderr "error: cannot determine signatures to request"
|
||||||
|
Write-Stderr ' Does the document at the URL below still contain a "List of Operating System Codes":'
|
||||||
|
Write-Stderr " https://raw.githubusercontent.com/MicrosoftDocs/windows-driver-docs/staging/windows-driver-docs-pr/dashboard/get-product-data.md"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# start with the base signatures and add any new ones found in the docs
|
||||||
|
$RequestedSignatures = @(
|
||||||
|
"WINDOWS_v100_TH2_FULL"
|
||||||
|
"WINDOWS_v100_X64_TH2_FULL"
|
||||||
|
"WINDOWS_v100_RS1_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS1_FULL"
|
||||||
|
"WINDOWS_v100_RS2_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS2_FULL"
|
||||||
|
"WINDOWS_v100_RS3_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS3_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_RS3_FULL"
|
||||||
|
"WINDOWS_v100_RS4_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS4_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_RS4_FULL"
|
||||||
|
"WINDOWS_v100_RS5_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS5_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_RS5_FULL"
|
||||||
|
"WINDOWS_v100_19H1_FULL"
|
||||||
|
"WINDOWS_v100_X64_19H1_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_19H1_FULL"
|
||||||
|
"WINDOWS_v100_VB_FULL"
|
||||||
|
"WINDOWS_v100_X64_VB_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_VB_FULL"
|
||||||
|
"WINDOWS_v100_X64_CO_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_CO_FULL"
|
||||||
|
"WINDOWS_v100_X64_NI_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_NI_FULL"
|
||||||
|
)
|
||||||
|
foreach ($Signature in $DocRequestedSignatures) {
|
||||||
|
if ($RequestedSignatures -contains $Signature) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Signature.Contains("_SERVER_")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Signature -eq "WINDOWS_v100_TH1_FULL") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Signature -eq "WINDOWS_v100_X64_TH1_FULL") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$RequestedSignatures += $Signature
|
||||||
|
Write-Stdout "New doc signature: $Signature"
|
||||||
|
}
|
||||||
|
|
||||||
|
$CreateProduct = @{
|
||||||
|
createType = "product"
|
||||||
|
createProduct = @{
|
||||||
|
productName = "winfsp-$Version"
|
||||||
|
testHarness = "attestation"
|
||||||
|
deviceType = "internalExternal"
|
||||||
|
requestedSignatures = $RequestedSignatures
|
||||||
|
# deviceMetaDataIds = $null
|
||||||
|
# firmwareVersion = "0"
|
||||||
|
# isTestSign = $false
|
||||||
|
# isFlightSign = $false
|
||||||
|
# markettingNames = $null
|
||||||
|
# selectedProductTypes = $null
|
||||||
|
# additionalAttributes = $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$CreateSubmission = @{
|
||||||
|
createType = "submission"
|
||||||
|
createSubmission = @{
|
||||||
|
name = "winfsp-$Version"
|
||||||
|
type = "initial"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
New-Item "$ProjectRoot\build\VStudio\build\Release\hwapi" -Type Directory -ErrorAction SilentlyContinue >$null
|
||||||
|
ConvertTo-Json $CreateProduct | Out-File -Encoding Ascii "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateProduct.json"
|
||||||
|
ConvertTo-Json $CreateSubmission | Out-File -Encoding Ascii "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateSubmission.json"
|
||||||
|
|
||||||
|
Start-Sdcm -create "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateProduct.json" | Tee-Object -Variable Output
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot create product on hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if (-not ([string]$Output -match "--- Product: (\d+)")) {
|
||||||
|
Write-Stderr "error: cannot get product id from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$ProductId = $matches[1]
|
||||||
|
|
||||||
|
Start-Sdcm -create "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateSubmission.json" -productid $ProductId | Tee-Object -Variable Output
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot create submission on hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if (-not ([string]$Output -match "---- Submission: (\d+)")) {
|
||||||
|
Write-Stderr "error: cannot get submission id from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$SubmissionId = $matches[1]
|
||||||
|
|
||||||
|
Set-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\ProductId" -Value $ProductId
|
||||||
|
Set-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\SubmissionId" -Value $SubmissionId
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Product submission has been prepared on hardware dashboard.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Upload-AssetsToHwapi {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
$ProductId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\ProductId"
|
||||||
|
$SubmissionId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\SubmissionId"
|
||||||
|
|
||||||
|
Start-Sdcm -upload "$ProjectRoot\build\VStudio\build\Release\driver.cab" -productid $ProductId -submissionid $SubmissionId
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot upload driver.cab to hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sdcm -commit -productid $ProductId -submissionid $SubmissionId
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot commit submission to hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Signable assets have been uploaded to the hardware dashboard.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Download-AssetsFromHwapi {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
$ProductId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\ProductId"
|
||||||
|
$SubmissionId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\SubmissionId"
|
||||||
|
|
||||||
|
Remove-Item -Force "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -Recurse -Force "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Start-Sdcm -download "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -productid $ProductId -submissionid $SubmissionId
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot download signed drivers from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot download signed drivers from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$ExpandError = ""
|
||||||
|
Expand-Archive "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -DestinationPath "$ProjectRoot\build\VStudio\build\Release\hwapi" -ErrorVariable ExpandError
|
||||||
|
if ($ExpandError) {
|
||||||
|
Write-Stderr "error: cannot expand signed drivers archive"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot expand signed drivers archive"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Signable assets have been downloaded and can be used to complete the build.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-AssetsPhase2 {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
# check signed drivers folder
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find hwapi\drivers"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$SignedPackage = Resolve-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers"
|
||||||
|
|
||||||
|
$VerX64 = Get-FileVersion "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys"
|
||||||
|
if ($VerX64 -ne (Get-FileVersion "$SignedPackage\x64\winfsp-x64.sys")) {
|
||||||
|
Write-Stderr "error: incompatible versions in hwapi\drivers"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Push-Location "$ProjectRoot"
|
||||||
|
tools\build.bat Release $SignedPackage
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot build assets"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Assets have been built and signed. You may want to perform some smoke testing.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Make-GitHubRelease {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
$DownloadColor = "blue"
|
||||||
|
$PrereleaseOpt = ""
|
||||||
|
if ($ReleaseInfo.Prerelease) {
|
||||||
|
$DownloadColor = "e52e4b"
|
||||||
|
$PrereleaseOpt = "-p"
|
||||||
|
}
|
||||||
|
|
||||||
|
$MsiFile = Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi"
|
||||||
|
$ZipFile = Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp-tests*.zip"
|
||||||
|
$MsiName = Split-Path -Leaf $MsiFile
|
||||||
|
$ZipName = Split-Path -Leaf $ZipFile
|
||||||
|
$MsiHash = (Get-FileHash -Algorithm SHA256 $MsiFile).Hash
|
||||||
|
$ZipHash = (Get-FileHash -Algorithm SHA256 $ZipFile).Hash
|
||||||
|
|
||||||
|
if ($MsiName -match "winfsp-(.+)\.msi") {
|
||||||
|
$Version = $matches[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
$ReleaseNotes = @"
|
||||||
|
[](https://github.com/winfsp/winfsp/releases/download/$($ReleaseInfo.Tag)/winfsp-$Version.msi)
|
||||||
|
|
||||||
|
## CHANGES SINCE WINFSP $($ReleaseInfo.PreviousProductVersion)
|
||||||
|
$($ReleaseInfo.Text -join "`n")
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<b>BUILD HASHES (SHA256)</b>
|
||||||
|
<p/>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
- **``$MsiName``**: $MsiHash
|
||||||
|
- **``$ZipName``**: $ZipHash
|
||||||
|
</details>
|
||||||
|
"@
|
||||||
|
|
||||||
|
gh release create $ReleaseInfo.Tag --draft --title "WinFsp $($ReleaseInfo.ProductVersion)" --notes "$ReleaseNotes" $PrereleaseOpt $MsiFile $ZipFile
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot create GitHub release"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Draft GitHub release for tag $($ReleaseInfo.Tag) has been created.
|
||||||
|
Publish the release on GitHub and update the VirusTotal link.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Upload-Symbols {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
# check winfsp.sym git log
|
||||||
|
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||||
|
$SymHasTag = Git-LogGrep $ReleaseInfo.Tag
|
||||||
|
Pop-Location
|
||||||
|
if ($SymHasTag) {
|
||||||
|
Write-Stderr "warning: winfsp.sym repository already has commit for tag $($ReleaseInfo.Tag)"
|
||||||
|
} else {
|
||||||
|
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||||
|
.\tools\symadd.ps1 ..\winfsp\build\VStudio\build\Release -PdbKind Private
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot add files to winfsp.sym repository"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
git add .
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot add files to winfsp.sym repository staging area"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
git commit -m $ReleaseInfo.Tag
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot commit files to winfsp.sym repository"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Commit for $($ReleaseInfo.Tag) symbols has been created.
|
||||||
|
Push the winfsp.sym repository to GitHub.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Make-NugetRelease {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
Push-Location "$ProjectRoot\build\VStudio\build\Release"
|
||||||
|
nuget push (Resolve-Path winfsp.net.[0-9]*.nupkg) -Source https://api.nuget.org/v3/index.json
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot push to Nuget"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Nuget release for $($ReleaseInfo.Tag) has been pushed.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Make-ChocoRelease {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
Push-Location "$ProjectRoot\build\VStudio\build\Release"
|
||||||
|
choco push (Resolve-Path winfsp.[0-9]*.nupkg)
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot push to Chocolatey"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Chocolatey release for $($ReleaseInfo.Tag) has been pushed.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ProjectRoot = Split-Path $PSScriptRoot
|
||||||
|
$StateFile = Join-Path $pwd $StateFile
|
||||||
|
|
||||||
|
Write-Stdout "Using state file $StateFile"
|
||||||
|
$State = @(Get-Content $StateFile -ErrorAction Ignore)
|
||||||
|
|
||||||
|
Check-Prerequisites
|
||||||
|
|
||||||
|
# Workflow tasks
|
||||||
|
Build-AssetsPhase1
|
||||||
|
Submit-AssetsToHwapi
|
||||||
|
Upload-AssetsToHwapi
|
||||||
|
Download-AssetsFromHwapi
|
||||||
|
Build-AssetsPhase2
|
||||||
|
Make-GitHubRelease
|
||||||
|
Upload-Symbols
|
||||||
|
Make-NugetRelease
|
||||||
|
Make-ChocoRelease
|
||||||
|
Write-Stdout "ALL COMPLETE"
|
@ -36,6 +36,10 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x64-mountpoint-drive ^
|
winfsp-tests-x64-mountpoint-drive ^
|
||||||
winfsp-tests-x64-mountpoint-dir ^
|
winfsp-tests-x64-mountpoint-dir ^
|
||||||
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
||||||
|
winfsp-tests-x64-mountmgr-drive ^
|
||||||
|
winfsp-tests-x64-mountmgr-dir ^
|
||||||
|
winfsp-tests-x64-mountmgrfsd-drive ^
|
||||||
|
winfsp-tests-x64-mountmgrfsd-dir ^
|
||||||
winfsp-tests-x64-no-traverse ^
|
winfsp-tests-x64-no-traverse ^
|
||||||
winfsp-tests-x64-oplock ^
|
winfsp-tests-x64-oplock ^
|
||||||
winfsp-tests-x64-notify ^
|
winfsp-tests-x64-notify ^
|
||||||
@ -43,28 +47,32 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x64-external-share ^
|
winfsp-tests-x64-external-share ^
|
||||||
memfs-x64-disk-fsx ^
|
memfs-x64-disk-fsx ^
|
||||||
memfs-x64-net-fsx ^
|
memfs-x64-net-fsx ^
|
||||||
memfs-x64-disk-standby ^
|
RETIRED-memfs-x64-disk-standby ^
|
||||||
memfs-x64-net-standby ^
|
RETIRED-memfs-x64-net-standby ^
|
||||||
memfs-x64-net-use ^
|
memfs-x64-net-use ^
|
||||||
memfs-x64-disk-winfstest ^
|
memfs-x64-disk-winfstest ^
|
||||||
memfs-x64-net-winfstest ^
|
memfs-x64-net-winfstest ^
|
||||||
fscrash-x64 ^
|
fscrash-x64 ^
|
||||||
winfsp-tests-x86 ^
|
winfsp-tests-x86 ^
|
||||||
winfsp-tests-x86-case-randomize ^
|
RETIRED-winfsp-tests-x86-case-randomize ^
|
||||||
winfsp-tests-x86-flushpurge ^
|
RETIRED-winfsp-tests-x86-flushpurge ^
|
||||||
winfsp-tests-x86-legacy-unlink-rename ^
|
RETIRED-winfsp-tests-x86-legacy-unlink-rename ^
|
||||||
winfsp-tests-x86-mountpoint-drive ^
|
RETIRED-winfsp-tests-x86-mountpoint-drive ^
|
||||||
winfsp-tests-x86-mountpoint-dir ^
|
RETIRED-winfsp-tests-x86-mountpoint-dir ^
|
||||||
winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
RETIRED-winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
||||||
winfsp-tests-x86-no-traverse ^
|
RETIRED-winfsp-tests-x86-mountmgr-drive ^
|
||||||
winfsp-tests-x86-oplock ^
|
RETIRED-winfsp-tests-x86-mountmgr-dir ^
|
||||||
winfsp-tests-x86-notify ^
|
RETIRED-winfsp-tests-x86-mountmgrfsd-drive ^
|
||||||
|
RETIRED-winfsp-tests-x86-mountmgrfsd-dir ^
|
||||||
|
RETIRED-winfsp-tests-x86-no-traverse ^
|
||||||
|
RETIRED-winfsp-tests-x86-oplock ^
|
||||||
|
RETIRED-winfsp-tests-x86-notify ^
|
||||||
winfsp-tests-x86-external ^
|
winfsp-tests-x86-external ^
|
||||||
winfsp-tests-x86-external-share ^
|
winfsp-tests-x86-external-share ^
|
||||||
memfs-x86-disk-fsx ^
|
memfs-x86-disk-fsx ^
|
||||||
memfs-x86-net-fsx ^
|
memfs-x86-net-fsx ^
|
||||||
memfs-x86-disk-standby ^
|
RETIRED-memfs-x86-disk-standby ^
|
||||||
memfs-x86-net-standby ^
|
RETIRED-memfs-x86-net-standby ^
|
||||||
memfs-x86-net-use ^
|
memfs-x86-net-use ^
|
||||||
memfs-x86-disk-winfstest ^
|
memfs-x86-disk-winfstest ^
|
||||||
memfs-x86-net-winfstest ^
|
memfs-x86-net-winfstest ^
|
||||||
@ -115,19 +123,24 @@ set opt_tests=^
|
|||||||
|
|
||||||
set tests=
|
set tests=
|
||||||
for %%f in (%dfl_tests%) do (
|
for %%f in (%dfl_tests%) do (
|
||||||
if X%2==X (
|
set test=%%f
|
||||||
set tests=!tests! %%f
|
if NOT "XRETIRED-!test:RETIRED-=!"=="X!test!" (
|
||||||
) else (
|
if X%2==X (
|
||||||
set test=%%f
|
set tests=!tests! %%f
|
||||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
) else (
|
||||||
|
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for %%f in (%opt_tests%) do (
|
for %%f in (%opt_tests%) do (
|
||||||
if X%2==X (
|
set test=%%f
|
||||||
rem
|
if NOT "XRETIRED-!test:RETIRED-=!"=="X!test!" (
|
||||||
) else (
|
if X%2==X (
|
||||||
set test=%%f
|
rem
|
||||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
) else (
|
||||||
|
set test=%%f
|
||||||
|
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -151,11 +164,12 @@ for %%f in (%tests%) do (
|
|||||||
set "endtimecalc=!endtime:%time:~8,1%=%%100)*100+1!" & set "begtimecalc=!begtime:%time:~8,1%=%%100)*100+1!"
|
set "endtimecalc=!endtime:%time:~8,1%=%%100)*100+1!" & set "begtimecalc=!begtime:%time:~8,1%=%%100)*100+1!"
|
||||||
set /A "duration=((((10!endtimecalc:%time:~2,1%=%%100)*60+1!%%100)-((((10!begtimecalc:%time:~2,1%=%%100)*60+1!%%100), duration-=(duration>>31)*24*60*60*100"
|
set /A "duration=((((10!endtimecalc:%time:~2,1%=%%100)*60+1!%%100)-((((10!begtimecalc:%time:~2,1%=%%100)*60+1!%%100), duration-=(duration>>31)*24*60*60*100"
|
||||||
set /A "duration=10*duration"
|
set /A "duration=10*duration"
|
||||||
|
set /A "durationSec=duration/1000"
|
||||||
|
|
||||||
if !ERRORLEVEL_save! neq 0 (
|
if !ERRORLEVEL_save! neq 0 (
|
||||||
set /a testfail=testfail+1
|
set /a testfail=testfail+1
|
||||||
|
|
||||||
echo === Failed %%f ^(!duration! ms^)
|
echo === Failed %%f ^(!durationSec!s^)
|
||||||
|
|
||||||
if defined APPVEYOR (
|
if defined APPVEYOR (
|
||||||
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Failed -Duration !duration!
|
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Failed -Duration !duration!
|
||||||
@ -163,7 +177,7 @@ for %%f in (%tests%) do (
|
|||||||
) else (
|
) else (
|
||||||
set /a testpass=testpass+1
|
set /a testpass=testpass+1
|
||||||
|
|
||||||
echo === Passed %%f ^(!duration! ms^)
|
echo === Passed %%f ^(!durationSec!s^)
|
||||||
|
|
||||||
if defined APPVEYOR (
|
if defined APPVEYOR (
|
||||||
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Passed -Duration !duration!
|
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Passed -Duration !duration!
|
||||||
@ -232,6 +246,30 @@ winfsp-tests-x64 --mountpoint=mymnt * +ea*
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x64-mountmgr-drive
|
||||||
|
winfsp-tests-x64 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x64-mountmgr-dir
|
||||||
|
winfsp-tests-x64 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x64-mountmgrfsd-drive
|
||||||
|
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||||
|
winfsp-tests-x64 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x64-mountmgrfsd-dir
|
||||||
|
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||||
|
winfsp-tests-x64 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x64-no-traverse
|
:winfsp-tests-x64-no-traverse
|
||||||
winfsp-tests-x64 --no-traverse * +ea*
|
winfsp-tests-x64 --no-traverse * +ea*
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
@ -282,6 +320,30 @@ winfsp-tests-x86 --mountpoint=mymnt * +ea*
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x86-mountmgr-drive
|
||||||
|
winfsp-tests-x86 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x86-mountmgr-dir
|
||||||
|
winfsp-tests-x86 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x86-mountmgrfsd-drive
|
||||||
|
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||||
|
winfsp-tests-x86 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x86-mountmgrfsd-dir
|
||||||
|
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||||
|
winfsp-tests-x86 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x86-no-traverse
|
:winfsp-tests-x86-no-traverse
|
||||||
winfsp-tests-x86 --no-traverse * +ea*
|
winfsp-tests-x86 --no-traverse * +ea*
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
24
tools/sxsident.bat
Normal file
24
tools/sxsident.bat
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
set SxsDir=
|
||||||
|
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||||
|
set RegVal="SxsDir"
|
||||||
|
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||||
|
if !ERRORLEVEL! equ 0 (
|
||||||
|
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||||
|
set SxsDir=%%j
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if defined SxsDir (
|
||||||
|
set SxsDir=!SxsDir:*SxS\sxs.=!
|
||||||
|
if !SxsDir:~-1!==\ set SxsDir=!SxsDir:~0,-1!
|
||||||
|
echo !SxsDir!
|
||||||
|
)
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:fail
|
||||||
|
exit /b 1
|
124
tools/wincred.ps1
Normal file
124
tools/wincred.ps1
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
Start-Job -ArgumentList $args -ScriptBlock {
|
||||||
|
param (
|
||||||
|
[ValidateSet("get", "set", "del")]
|
||||||
|
[string]$Command
|
||||||
|
)
|
||||||
|
|
||||||
|
Add-Type -TypeDefinition @"
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
namespace Win32
|
||||||
|
{
|
||||||
|
public class Api
|
||||||
|
{
|
||||||
|
public static String[] CredRead(
|
||||||
|
String TargetName)
|
||||||
|
{
|
||||||
|
String[] Result = null;
|
||||||
|
IntPtr CredentialPtr;
|
||||||
|
if (CredReadW(TargetName, 1/*CRED_TYPE_GENERIC*/, 0, out CredentialPtr))
|
||||||
|
{
|
||||||
|
CREDENTIALW Credential = Marshal.PtrToStructure<CREDENTIALW>(CredentialPtr);
|
||||||
|
Result = new String[2]{
|
||||||
|
Credential.UserName,
|
||||||
|
Marshal.PtrToStringUni(
|
||||||
|
Credential.CredentialBlob, (int)Credential.CredentialBlobSize / 2)
|
||||||
|
};
|
||||||
|
CredFree(CredentialPtr);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
public static Boolean CredWrite(
|
||||||
|
String TargetName,
|
||||||
|
String UserName,
|
||||||
|
String Password)
|
||||||
|
{
|
||||||
|
CREDENTIALW Credential = new CREDENTIALW{
|
||||||
|
Type = 1/*CRED_TYPE_GENERIC*/,
|
||||||
|
Persist = 2/*CRED_PERSIST_LOCAL_MACHINE*/,
|
||||||
|
TargetName = TargetName,
|
||||||
|
UserName = UserName,
|
||||||
|
CredentialBlobSize = (UInt32)Password.Length * 2,
|
||||||
|
CredentialBlob = Marshal.StringToCoTaskMemUni(Password),
|
||||||
|
};
|
||||||
|
Boolean Result = CredWriteW(ref Credential, 0);
|
||||||
|
Marshal.FreeCoTaskMem(Credential.CredentialBlob);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
public static Boolean CredDelete(
|
||||||
|
String TargetName)
|
||||||
|
{
|
||||||
|
return CredDeleteW(TargetName, 1/*CRED_TYPE_GENERIC*/, 0);
|
||||||
|
}
|
||||||
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
private static extern Boolean CredReadW(
|
||||||
|
String TargetName,
|
||||||
|
UInt32 Type,
|
||||||
|
UInt32 Flags,
|
||||||
|
out IntPtr Credential);
|
||||||
|
[DllImport("advapi32.dll")]
|
||||||
|
private static extern void CredFree(
|
||||||
|
IntPtr Buffer);
|
||||||
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
private static extern Boolean CredWriteW(
|
||||||
|
ref CREDENTIALW Credential,
|
||||||
|
UInt32 Flags);
|
||||||
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
private static extern Boolean CredDeleteW(
|
||||||
|
String TargetName,
|
||||||
|
UInt32 Type,
|
||||||
|
UInt32 Flags);
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
|
private struct CREDENTIALW
|
||||||
|
{
|
||||||
|
public UInt32 Flags;
|
||||||
|
public UInt32 Type;
|
||||||
|
public String TargetName;
|
||||||
|
public String Comment;
|
||||||
|
public UInt64 LastWritten;
|
||||||
|
public UInt32 CredentialBlobSize;
|
||||||
|
public IntPtr CredentialBlob;
|
||||||
|
public UInt32 Persist;
|
||||||
|
public UInt32 AttributeCount;
|
||||||
|
public IntPtr Attributes;
|
||||||
|
public String TargetAlias;
|
||||||
|
public String UserName;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"@
|
||||||
|
|
||||||
|
function Get-WindowsCredential {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory)][string]$TargetName
|
||||||
|
)
|
||||||
|
return [Win32.Api]::CredRead($TargetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-WindowsCredential {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory)][string]$TargetName,
|
||||||
|
[Parameter(Mandatory)][string]$UserName,
|
||||||
|
[Parameter(Mandatory)][string]$Password
|
||||||
|
)
|
||||||
|
return [Win32.Api]::CredWrite($TargetName, $UserName, $Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Delete-WindowsCredential {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory)][string]$TargetName
|
||||||
|
)
|
||||||
|
return [Win32.Api]::CredDelete($TargetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
$Function = @{
|
||||||
|
"get" = "Get-WindowsCredential"
|
||||||
|
"set" = "Set-WindowsCredential"
|
||||||
|
"del" = "Delete-WindowsCredential"
|
||||||
|
}[$Command]
|
||||||
|
& $Function @args
|
||||||
|
|
||||||
|
} | Receive-Job -Wait -AutoRemoveJob
|
@ -40,6 +40,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
|
|||||||
*/
|
*/
|
||||||
//#define MEMFS_STANDALONE
|
//#define MEMFS_STANDALONE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the MEMFS_DISPATCHER_STOPPED macro to include DispatcherStopped support.
|
||||||
|
*/
|
||||||
|
#define MEMFS_DISPATCHER_STOPPED
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the MEMFS_NAME_NORMALIZATION macro to include name normalization support.
|
* Define the MEMFS_NAME_NORMALIZATION macro to include name normalization support.
|
||||||
*/
|
*/
|
||||||
@ -2269,6 +2274,14 @@ static NTSTATUS SetEa(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MEMFS_DISPATCHER_STOPPED)
|
||||||
|
static VOID DispatcherStopped(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
BOOLEAN Normally)
|
||||||
|
{
|
||||||
|
FspFileSystemStopServiceIfNecessary(FileSystem, Normally);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||||
{
|
{
|
||||||
GetVolumeInfo,
|
GetVolumeInfo,
|
||||||
@ -2336,6 +2349,12 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
#endif
|
||||||
|
0,
|
||||||
|
#if defined(MEMFS_DISPATCHER_STOPPED)
|
||||||
|
DispatcherStopped,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ enum
|
|||||||
MemfsCaseInsensitive = 0x80000000,
|
MemfsCaseInsensitive = 0x80000000,
|
||||||
MemfsFlushAndPurgeOnCleanup = 0x40000000,
|
MemfsFlushAndPurgeOnCleanup = 0x40000000,
|
||||||
MemfsLegacyUnlinkRename = 0x20000000,
|
MemfsLegacyUnlinkRename = 0x20000000,
|
||||||
|
MemfsNoSlowio = 0x10000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl, PMemfs)\
|
#define MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl, PMemfs)\
|
||||||
|
@ -1143,6 +1143,12 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID DispatcherStopped(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
BOOLEAN Normally)
|
||||||
|
{
|
||||||
|
FspFileSystemStopServiceIfNecessary(FileSystem, Normally);
|
||||||
|
}
|
||||||
|
|
||||||
static FSP_FILE_SYSTEM_INTERFACE PtfsInterface =
|
static FSP_FILE_SYSTEM_INTERFACE PtfsInterface =
|
||||||
{
|
{
|
||||||
.GetVolumeInfo = GetVolumeInfo,
|
.GetVolumeInfo = GetVolumeInfo,
|
||||||
@ -1171,6 +1177,7 @@ static FSP_FILE_SYSTEM_INTERFACE PtfsInterface =
|
|||||||
.GetStreamInfo = GetStreamInfo,
|
.GetStreamInfo = GetStreamInfo,
|
||||||
.GetEa = GetEa,
|
.GetEa = GetEa,
|
||||||
.SetEa = SetEa,
|
.SetEa = SetEa,
|
||||||
|
.DispatcherStopped = DispatcherStopped,
|
||||||
};
|
};
|
||||||
|
|
||||||
NTSTATUS PtfsCreate(
|
NTSTATUS PtfsCreate(
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
#define fi_setdirp(fi, dirp) (fi_setfh(fi, dirp, fi_dirbit))
|
#define fi_setdirp(fi, dirp) (fi_setfh(fi, dirp, fi_dirbit))
|
||||||
|
|
||||||
#define ptfs_impl_fullpath(n) \
|
#define ptfs_impl_fullpath(n) \
|
||||||
char full ## n[PATH_MAX]; \
|
char full ## n[PATH_MAX * 4]; \
|
||||||
if (!concat_path(((PTFS *)fuse_get_context()->private_data), n, full ## n))\
|
if (!concat_path(((PTFS *)fuse_get_context()->private_data), n, full ## n))\
|
||||||
return -ENAMETOOLONG; \
|
return -ENAMETOOLONG; \
|
||||||
n = full ## n
|
n = full ## n
|
||||||
|
@ -129,15 +129,50 @@ char *realpath(const char *path, char *resolved)
|
|||||||
result = resolved;
|
result = resolved;
|
||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
DWORD len = GetFullPathNameA(path, PATH_MAX, result, 0);
|
WCHAR PathBuf[PATH_MAX];
|
||||||
if (0 == len)
|
WCHAR ResultBuf[PATH_MAX];
|
||||||
|
PWSTR ResultBufBgn = &ResultBuf[6];
|
||||||
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, path, -1, PathBuf, PATH_MAX))
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
else if (PATH_MAX < len)
|
else
|
||||||
err = ERROR_INVALID_PARAMETER;
|
{
|
||||||
|
DWORD len = GetFullPathNameW(PathBuf, PATH_MAX - 6, ResultBufBgn, 0);
|
||||||
|
if (0 == len)
|
||||||
|
err = GetLastError();
|
||||||
|
else if (PATH_MAX - 6 < len)
|
||||||
|
err = ERROR_INVALID_PARAMETER;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (0 == WideCharToMultiByte(CP_UTF8, 0, ResultBufBgn, -1, result, PATH_MAX, 0, 0))
|
||||||
|
err = GetLastError();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (L'\\' == ResultBufBgn[0] && L'\\' == ResultBufBgn[1])
|
||||||
|
{
|
||||||
|
ResultBufBgn = ResultBuf;
|
||||||
|
ResultBufBgn[0] = L'\\';
|
||||||
|
ResultBufBgn[1] = L'\\';
|
||||||
|
ResultBufBgn[2] = L'?';
|
||||||
|
ResultBufBgn[3] = L'\\';
|
||||||
|
ResultBufBgn[4] = L'U';
|
||||||
|
ResultBufBgn[5] = L'N';
|
||||||
|
ResultBufBgn[6] = L'C';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ResultBufBgn = &ResultBuf[2];
|
||||||
|
ResultBufBgn[0] = L'\\';
|
||||||
|
ResultBufBgn[1] = L'\\';
|
||||||
|
ResultBufBgn[2] = L'?';
|
||||||
|
ResultBufBgn[3] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (0 == err)
|
if (0 == err)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(result,
|
HANDLE h = CreateFileW(ResultBufBgn,
|
||||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -155,13 +190,71 @@ char *realpath(const char *path, char *resolved)
|
|||||||
errno = maperror(err);
|
errno = maperror(err);
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uncpath(const char *path, WCHAR *buf, int nchar)
|
||||||
|
{
|
||||||
|
PWSTR BufP = 0;
|
||||||
|
if ('\\' == path[0] && '\\' == path[1])
|
||||||
|
{
|
||||||
|
if (8 < nchar &&
|
||||||
|
0 < MultiByteToWideChar(CP_UTF8, 0, &path[2], -1, &buf[8], nchar - 8))
|
||||||
|
{
|
||||||
|
BufP = &buf[8];
|
||||||
|
buf[0] = L'\\';
|
||||||
|
buf[1] = L'\\';
|
||||||
|
buf[2] = L'?';
|
||||||
|
buf[3] = L'\\';
|
||||||
|
buf[4] = L'U';
|
||||||
|
buf[5] = L'N';
|
||||||
|
buf[6] = L'C';
|
||||||
|
buf[7] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (4 < nchar &&
|
||||||
|
0 < MultiByteToWideChar(CP_UTF8, 0, path, -1, &buf[4], nchar - 4))
|
||||||
|
{
|
||||||
|
BufP = &buf[4];
|
||||||
|
buf[0] = L'\\';
|
||||||
|
buf[1] = L'\\';
|
||||||
|
buf[2] = L'?';
|
||||||
|
buf[3] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == BufP)
|
||||||
|
{
|
||||||
|
if (0 < nchar)
|
||||||
|
buf[0] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PWSTR P = BufP;
|
||||||
|
while (*BufP)
|
||||||
|
{
|
||||||
|
if (L'/' == *BufP || L'\\' == *BufP)
|
||||||
|
{
|
||||||
|
while (L'/' == BufP[1] || L'\\' == BufP[1])
|
||||||
|
BufP++;
|
||||||
|
}
|
||||||
|
if (L'/' == *BufP)
|
||||||
|
*P = L'\\';
|
||||||
|
else if (P != BufP)
|
||||||
|
*P = *BufP;
|
||||||
|
BufP++;
|
||||||
|
P++;
|
||||||
|
}
|
||||||
|
if (P != BufP)
|
||||||
|
*P = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
||||||
{
|
{
|
||||||
char root[PATH_MAX];
|
WCHAR root[PATH_MAX];
|
||||||
DWORD
|
DWORD
|
||||||
VolumeSerialNumber,
|
VolumeSerialNumber,
|
||||||
MaxComponentLength,
|
MaxComponentLength,
|
||||||
@ -170,9 +263,11 @@ int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
|||||||
NumberOfFreeClusters,
|
NumberOfFreeClusters,
|
||||||
TotalNumberOfClusters;
|
TotalNumberOfClusters;
|
||||||
|
|
||||||
if (!GetVolumePathNameA(path, root, PATH_MAX) ||
|
WCHAR PathBuf[PATH_MAX];
|
||||||
!GetVolumeInformationA(root, 0, 0, &VolumeSerialNumber, &MaxComponentLength, 0, 0, 0) ||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
!GetDiskFreeSpaceA(root, &SectorsPerCluster, &BytesPerSector,
|
if (!GetVolumePathNameW(PathBuf, root, PATH_MAX) ||
|
||||||
|
!GetVolumeInformationW(root, 0, 0, &VolumeSerialNumber, &MaxComponentLength, 0, 0, 0) ||
|
||||||
|
!GetDiskFreeSpaceW(root, &SectorsPerCluster, &BytesPerSector,
|
||||||
&NumberOfFreeClusters, &TotalNumberOfClusters))
|
&NumberOfFreeClusters, &TotalNumberOfClusters))
|
||||||
{
|
{
|
||||||
return error();
|
return error();
|
||||||
@ -201,7 +296,9 @@ int open(const char *path, int oflag, ...)
|
|||||||
CREATE_NEW :
|
CREATE_NEW :
|
||||||
cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8];
|
cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8];
|
||||||
|
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0/* default security */,
|
0/* default security */,
|
||||||
CreationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
|
CreationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -325,7 +422,9 @@ int close(int fd)
|
|||||||
|
|
||||||
int getpath(const char *path, char *buf, size_t size)
|
int getpath(const char *path, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -341,7 +440,9 @@ int getpath(const char *path, char *buf, size_t size)
|
|||||||
|
|
||||||
int lstat(const char *path, struct fuse_stat *stbuf)
|
int lstat(const char *path, struct fuse_stat *stbuf)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -375,7 +476,9 @@ int lchflags(const char *path, uint32_t flags)
|
|||||||
if (0 == FileAttributes)
|
if (0 == FileAttributes)
|
||||||
FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
|
|
||||||
if (!SetFileAttributesA(path, FileAttributes))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!SetFileAttributesW(PathBuf, FileAttributes))
|
||||||
return error();
|
return error();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -384,7 +487,9 @@ int lchflags(const char *path, uint32_t flags)
|
|||||||
|
|
||||||
int truncate(const char *path, fuse_off_t size)
|
int truncate(const char *path, fuse_off_t size)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -418,7 +523,9 @@ int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2],
|
|||||||
/* ignore dirfd and assume that it is always AT_FDCWD */
|
/* ignore dirfd and assume that it is always AT_FDCWD */
|
||||||
/* ignore flag and assume that it is always AT_SYMLINK_NOFOLLOW */
|
/* ignore flag and assume that it is always AT_SYMLINK_NOFOLLOW */
|
||||||
|
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -448,7 +555,9 @@ int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2],
|
|||||||
|
|
||||||
int setcrtime(const char *path, const struct fuse_timespec *tv)
|
int setcrtime(const char *path, const struct fuse_timespec *tv)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -468,7 +577,9 @@ int setcrtime(const char *path, const struct fuse_timespec *tv)
|
|||||||
|
|
||||||
int unlink(const char *path)
|
int unlink(const char *path)
|
||||||
{
|
{
|
||||||
if (!DeleteFileA(path))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!DeleteFileW(PathBuf))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -476,7 +587,11 @@ int unlink(const char *path)
|
|||||||
|
|
||||||
int rename(const char *oldpath, const char *newpath)
|
int rename(const char *oldpath, const char *newpath)
|
||||||
{
|
{
|
||||||
if (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
|
WCHAR OldPathBuf[PATH_MAX];
|
||||||
|
WCHAR NewPathBuf[PATH_MAX];
|
||||||
|
uncpath(oldpath, OldPathBuf, PATH_MAX);
|
||||||
|
uncpath(newpath, NewPathBuf, PATH_MAX);
|
||||||
|
if (!MoveFileExW(OldPathBuf, NewPathBuf, MOVEFILE_REPLACE_EXISTING))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -484,7 +599,9 @@ int rename(const char *oldpath, const char *newpath)
|
|||||||
|
|
||||||
static int lsetea(const char *path, PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
static int lsetea(const char *path, PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -519,7 +636,9 @@ static int lgetea(const char *path,
|
|||||||
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_READ_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -711,7 +830,9 @@ int lremovexattr(const char *path, const char *name)
|
|||||||
|
|
||||||
int mkdir(const char *path, fuse_mode_t mode)
|
int mkdir(const char *path, fuse_mode_t mode)
|
||||||
{
|
{
|
||||||
if (!CreateDirectoryA(path, 0/* default security */))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!CreateDirectoryW(PathBuf, 0/* default security */))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -719,7 +840,9 @@ int mkdir(const char *path, fuse_mode_t mode)
|
|||||||
|
|
||||||
int rmdir(const char *path)
|
int rmdir(const char *path)
|
||||||
{
|
{
|
||||||
if (!RemoveDirectoryA(path))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!RemoveDirectoryW(PathBuf))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -727,7 +850,9 @@ int rmdir(const char *path)
|
|||||||
|
|
||||||
DIR *opendir(const char *path)
|
DIR *opendir(const char *path)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -772,18 +897,20 @@ void rewinddir(DIR *dirp)
|
|||||||
|
|
||||||
struct dirent *readdir(DIR *dirp)
|
struct dirent *readdir(DIR *dirp)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAA FindData;
|
WIN32_FIND_DATAW FindData;
|
||||||
struct fuse_stat *stbuf = &dirp->de.d_stat;
|
struct fuse_stat *stbuf = &dirp->de.d_stat;
|
||||||
|
|
||||||
if (INVALID_HANDLE_VALUE == dirp->fh)
|
if (INVALID_HANDLE_VALUE == dirp->fh)
|
||||||
{
|
{
|
||||||
dirp->fh = FindFirstFileA(dirp->path, &FindData);
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(dirp->path, PathBuf, PATH_MAX);
|
||||||
|
dirp->fh = FindFirstFileW(PathBuf, &FindData);
|
||||||
if (INVALID_HANDLE_VALUE == dirp->fh)
|
if (INVALID_HANDLE_VALUE == dirp->fh)
|
||||||
return error0();
|
return error0();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!FindNextFileA(dirp->fh, &FindData))
|
if (!FindNextFileW(dirp->fh, &FindData))
|
||||||
{
|
{
|
||||||
if (ERROR_NO_MORE_FILES == GetLastError())
|
if (ERROR_NO_MORE_FILES == GetLastError())
|
||||||
return 0;
|
return 0;
|
||||||
@ -804,7 +931,7 @@ struct dirent *readdir(DIR *dirp)
|
|||||||
stbuf->st_flags = MapFileAttributesToFlags(FindData.dwFileAttributes);
|
stbuf->st_flags = MapFileAttributesToFlags(FindData.dwFileAttributes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
strcpy(dirp->de.d_name, FindData.cFileName);
|
WideCharToMultiByte(CP_UTF8, 0, FindData.cFileName, -1, dirp->de.d_name, 255 * 4, 0, 0);
|
||||||
|
|
||||||
return &dirp->de;
|
return &dirp->de;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ typedef struct _DIR DIR;
|
|||||||
struct dirent
|
struct dirent
|
||||||
{
|
{
|
||||||
struct fuse_stat d_stat;
|
struct fuse_stat d_stat;
|
||||||
char d_name[255];
|
char d_name[255 * 4];
|
||||||
};
|
};
|
||||||
|
|
||||||
char *realpath(const char *path, char *resolved);
|
char *realpath(const char *path, char *resolved);
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
#define fi_setdirp(fi, dirp) (fi_setfh(fi, dirp, fi_dirbit))
|
#define fi_setdirp(fi, dirp) (fi_setfh(fi, dirp, fi_dirbit))
|
||||||
|
|
||||||
#define ptfs_impl_fullpath(n) \
|
#define ptfs_impl_fullpath(n) \
|
||||||
char full ## n[PATH_MAX]; \
|
char full ## n[PATH_MAX * 4]; \
|
||||||
if (!concat_path(((PTFS *)fuse_get_context()->private_data), n, full ## n))\
|
if (!concat_path(((PTFS *)fuse_get_context()->private_data), n, full ## n))\
|
||||||
return -ENAMETOOLONG; \
|
return -ENAMETOOLONG; \
|
||||||
n = full ## n
|
n = full ## n
|
||||||
|
@ -129,15 +129,50 @@ char *realpath(const char *path, char *resolved)
|
|||||||
result = resolved;
|
result = resolved;
|
||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
DWORD len = GetFullPathNameA(path, PATH_MAX, result, 0);
|
WCHAR PathBuf[PATH_MAX];
|
||||||
if (0 == len)
|
WCHAR ResultBuf[PATH_MAX];
|
||||||
|
PWSTR ResultBufBgn = &ResultBuf[6];
|
||||||
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, path, -1, PathBuf, PATH_MAX))
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
else if (PATH_MAX < len)
|
else
|
||||||
err = ERROR_INVALID_PARAMETER;
|
{
|
||||||
|
DWORD len = GetFullPathNameW(PathBuf, PATH_MAX - 6, ResultBufBgn, 0);
|
||||||
|
if (0 == len)
|
||||||
|
err = GetLastError();
|
||||||
|
else if (PATH_MAX - 6 < len)
|
||||||
|
err = ERROR_INVALID_PARAMETER;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (0 == WideCharToMultiByte(CP_UTF8, 0, ResultBufBgn, -1, result, PATH_MAX, 0, 0))
|
||||||
|
err = GetLastError();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (L'\\' == ResultBufBgn[0] && L'\\' == ResultBufBgn[1])
|
||||||
|
{
|
||||||
|
ResultBufBgn = ResultBuf;
|
||||||
|
ResultBufBgn[0] = L'\\';
|
||||||
|
ResultBufBgn[1] = L'\\';
|
||||||
|
ResultBufBgn[2] = L'?';
|
||||||
|
ResultBufBgn[3] = L'\\';
|
||||||
|
ResultBufBgn[4] = L'U';
|
||||||
|
ResultBufBgn[5] = L'N';
|
||||||
|
ResultBufBgn[6] = L'C';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ResultBufBgn = &ResultBuf[2];
|
||||||
|
ResultBufBgn[0] = L'\\';
|
||||||
|
ResultBufBgn[1] = L'\\';
|
||||||
|
ResultBufBgn[2] = L'?';
|
||||||
|
ResultBufBgn[3] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (0 == err)
|
if (0 == err)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(result,
|
HANDLE h = CreateFileW(ResultBufBgn,
|
||||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -155,13 +190,71 @@ char *realpath(const char *path, char *resolved)
|
|||||||
errno = maperror(err);
|
errno = maperror(err);
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uncpath(const char *path, WCHAR *buf, int nchar)
|
||||||
|
{
|
||||||
|
PWSTR BufP = 0;
|
||||||
|
if ('\\' == path[0] && '\\' == path[1])
|
||||||
|
{
|
||||||
|
if (8 < nchar &&
|
||||||
|
0 < MultiByteToWideChar(CP_UTF8, 0, &path[2], -1, &buf[8], nchar - 8))
|
||||||
|
{
|
||||||
|
BufP = &buf[8];
|
||||||
|
buf[0] = L'\\';
|
||||||
|
buf[1] = L'\\';
|
||||||
|
buf[2] = L'?';
|
||||||
|
buf[3] = L'\\';
|
||||||
|
buf[4] = L'U';
|
||||||
|
buf[5] = L'N';
|
||||||
|
buf[6] = L'C';
|
||||||
|
buf[7] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (4 < nchar &&
|
||||||
|
0 < MultiByteToWideChar(CP_UTF8, 0, path, -1, &buf[4], nchar - 4))
|
||||||
|
{
|
||||||
|
BufP = &buf[4];
|
||||||
|
buf[0] = L'\\';
|
||||||
|
buf[1] = L'\\';
|
||||||
|
buf[2] = L'?';
|
||||||
|
buf[3] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == BufP)
|
||||||
|
{
|
||||||
|
if (0 < nchar)
|
||||||
|
buf[0] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PWSTR P = BufP;
|
||||||
|
while (*BufP)
|
||||||
|
{
|
||||||
|
if (L'/' == *BufP || L'\\' == *BufP)
|
||||||
|
{
|
||||||
|
while (L'/' == BufP[1] || L'\\' == BufP[1])
|
||||||
|
BufP++;
|
||||||
|
}
|
||||||
|
if (L'/' == *BufP)
|
||||||
|
*P = L'\\';
|
||||||
|
else if (P != BufP)
|
||||||
|
*P = *BufP;
|
||||||
|
BufP++;
|
||||||
|
P++;
|
||||||
|
}
|
||||||
|
if (P != BufP)
|
||||||
|
*P = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
||||||
{
|
{
|
||||||
char root[PATH_MAX];
|
WCHAR root[PATH_MAX];
|
||||||
DWORD
|
DWORD
|
||||||
VolumeSerialNumber,
|
VolumeSerialNumber,
|
||||||
MaxComponentLength,
|
MaxComponentLength,
|
||||||
@ -170,9 +263,11 @@ int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
|||||||
NumberOfFreeClusters,
|
NumberOfFreeClusters,
|
||||||
TotalNumberOfClusters;
|
TotalNumberOfClusters;
|
||||||
|
|
||||||
if (!GetVolumePathNameA(path, root, PATH_MAX) ||
|
WCHAR PathBuf[PATH_MAX];
|
||||||
!GetVolumeInformationA(root, 0, 0, &VolumeSerialNumber, &MaxComponentLength, 0, 0, 0) ||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
!GetDiskFreeSpaceA(root, &SectorsPerCluster, &BytesPerSector,
|
if (!GetVolumePathNameW(PathBuf, root, PATH_MAX) ||
|
||||||
|
!GetVolumeInformationW(root, 0, 0, &VolumeSerialNumber, &MaxComponentLength, 0, 0, 0) ||
|
||||||
|
!GetDiskFreeSpaceW(root, &SectorsPerCluster, &BytesPerSector,
|
||||||
&NumberOfFreeClusters, &TotalNumberOfClusters))
|
&NumberOfFreeClusters, &TotalNumberOfClusters))
|
||||||
{
|
{
|
||||||
return error();
|
return error();
|
||||||
@ -201,7 +296,9 @@ int open(const char *path, int oflag, ...)
|
|||||||
CREATE_NEW :
|
CREATE_NEW :
|
||||||
cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8];
|
cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8];
|
||||||
|
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0/* default security */,
|
0/* default security */,
|
||||||
CreationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
|
CreationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -305,7 +402,9 @@ int close(int fd)
|
|||||||
|
|
||||||
int lstat(const char *path, struct fuse_stat *stbuf)
|
int lstat(const char *path, struct fuse_stat *stbuf)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -339,7 +438,9 @@ int lchflags(const char *path, uint32_t flags)
|
|||||||
if (0 == FileAttributes)
|
if (0 == FileAttributes)
|
||||||
FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
|
|
||||||
if (!SetFileAttributesA(path, FileAttributes))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!SetFileAttributesW(PathBuf, FileAttributes))
|
||||||
return error();
|
return error();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -348,7 +449,9 @@ int lchflags(const char *path, uint32_t flags)
|
|||||||
|
|
||||||
int truncate(const char *path, fuse_off_t size)
|
int truncate(const char *path, fuse_off_t size)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -382,7 +485,9 @@ int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2],
|
|||||||
/* ignore dirfd and assume that it is always AT_FDCWD */
|
/* ignore dirfd and assume that it is always AT_FDCWD */
|
||||||
/* ignore flag and assume that it is always AT_SYMLINK_NOFOLLOW */
|
/* ignore flag and assume that it is always AT_SYMLINK_NOFOLLOW */
|
||||||
|
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -412,7 +517,9 @@ int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2],
|
|||||||
|
|
||||||
int setcrtime(const char *path, const struct fuse_timespec *tv)
|
int setcrtime(const char *path, const struct fuse_timespec *tv)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -432,7 +539,9 @@ int setcrtime(const char *path, const struct fuse_timespec *tv)
|
|||||||
|
|
||||||
int unlink(const char *path)
|
int unlink(const char *path)
|
||||||
{
|
{
|
||||||
if (!DeleteFileA(path))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!DeleteFileW(PathBuf))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -440,7 +549,11 @@ int unlink(const char *path)
|
|||||||
|
|
||||||
int rename(const char *oldpath, const char *newpath)
|
int rename(const char *oldpath, const char *newpath)
|
||||||
{
|
{
|
||||||
if (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
|
WCHAR OldPathBuf[PATH_MAX];
|
||||||
|
WCHAR NewPathBuf[PATH_MAX];
|
||||||
|
uncpath(oldpath, OldPathBuf, PATH_MAX);
|
||||||
|
uncpath(newpath, NewPathBuf, PATH_MAX);
|
||||||
|
if (!MoveFileExW(OldPathBuf, NewPathBuf, MOVEFILE_REPLACE_EXISTING))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -448,7 +561,9 @@ int rename(const char *oldpath, const char *newpath)
|
|||||||
|
|
||||||
static int lsetea(const char *path, PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
static int lsetea(const char *path, PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_WRITE_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_WRITE_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -483,7 +598,9 @@ static int lgetea(const char *path,
|
|||||||
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_READ_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_EA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -675,7 +792,9 @@ int lremovexattr(const char *path, const char *name)
|
|||||||
|
|
||||||
int mkdir(const char *path, fuse_mode_t mode)
|
int mkdir(const char *path, fuse_mode_t mode)
|
||||||
{
|
{
|
||||||
if (!CreateDirectoryA(path, 0/* default security */))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!CreateDirectoryW(PathBuf, 0/* default security */))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -683,7 +802,9 @@ int mkdir(const char *path, fuse_mode_t mode)
|
|||||||
|
|
||||||
int rmdir(const char *path)
|
int rmdir(const char *path)
|
||||||
{
|
{
|
||||||
if (!RemoveDirectoryA(path))
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
if (!RemoveDirectoryW(PathBuf))
|
||||||
return error();
|
return error();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -691,7 +812,9 @@ int rmdir(const char *path)
|
|||||||
|
|
||||||
DIR *opendir(const char *path)
|
DIR *opendir(const char *path)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(path, PathBuf, PATH_MAX);
|
||||||
|
HANDLE h = CreateFileW(PathBuf,
|
||||||
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
0,
|
0,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
@ -736,18 +859,20 @@ void rewinddir(DIR *dirp)
|
|||||||
|
|
||||||
struct dirent *readdir(DIR *dirp)
|
struct dirent *readdir(DIR *dirp)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAA FindData;
|
WIN32_FIND_DATAW FindData;
|
||||||
struct fuse_stat *stbuf = &dirp->de.d_stat;
|
struct fuse_stat *stbuf = &dirp->de.d_stat;
|
||||||
|
|
||||||
if (INVALID_HANDLE_VALUE == dirp->fh)
|
if (INVALID_HANDLE_VALUE == dirp->fh)
|
||||||
{
|
{
|
||||||
dirp->fh = FindFirstFileA(dirp->path, &FindData);
|
WCHAR PathBuf[PATH_MAX];
|
||||||
|
uncpath(dirp->path, PathBuf, PATH_MAX);
|
||||||
|
dirp->fh = FindFirstFileW(PathBuf, &FindData);
|
||||||
if (INVALID_HANDLE_VALUE == dirp->fh)
|
if (INVALID_HANDLE_VALUE == dirp->fh)
|
||||||
return error0();
|
return error0();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!FindNextFileA(dirp->fh, &FindData))
|
if (!FindNextFileW(dirp->fh, &FindData))
|
||||||
{
|
{
|
||||||
if (ERROR_NO_MORE_FILES == GetLastError())
|
if (ERROR_NO_MORE_FILES == GetLastError())
|
||||||
return 0;
|
return 0;
|
||||||
@ -768,7 +893,7 @@ struct dirent *readdir(DIR *dirp)
|
|||||||
stbuf->st_flags = MapFileAttributesToFlags(FindData.dwFileAttributes);
|
stbuf->st_flags = MapFileAttributesToFlags(FindData.dwFileAttributes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
strcpy(dirp->de.d_name, FindData.cFileName);
|
WideCharToMultiByte(CP_UTF8, 0, FindData.cFileName, -1, dirp->de.d_name, 255 * 4, 0, 0);
|
||||||
|
|
||||||
return &dirp->de;
|
return &dirp->de;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ typedef struct _DIR DIR;
|
|||||||
struct dirent
|
struct dirent
|
||||||
{
|
{
|
||||||
struct fuse_stat d_stat;
|
struct fuse_stat d_stat;
|
||||||
char d_name[255];
|
char d_name[255 * 4];
|
||||||
};
|
};
|
||||||
|
|
||||||
char *realpath(const char *path, char *resolved);
|
char *realpath(const char *path, char *resolved);
|
||||||
|
@ -62,7 +62,8 @@ static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo
|
|||||||
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
||||||
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
||||||
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
||||||
FileInfo->IndexNumber = 0;
|
FileInfo->IndexNumber =
|
||||||
|
((UINT64)ByHandleFileInfo.nFileIndexHigh << 32) | (UINT64)ByHandleFileInfo.nFileIndexLow;
|
||||||
FileInfo->HardLinks = 0;
|
FileInfo->HardLinks = 0;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -1287,6 +1287,38 @@ void create_namelen_dotest(ULONG Flags, PWSTR Prefix, PWSTR Drive)
|
|||||||
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||||
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||||
|
|
||||||
|
for (P = FilePathBgn, EndP = P + MaxComponentLength - 1; EndP > P; P++)
|
||||||
|
*P = (P - FilePathBgn) % 10 + 0x3041;
|
||||||
|
*P = L'\0';
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (P = FilePathBgn, EndP = P + MaxComponentLength; EndP > P; P++)
|
||||||
|
*P = (P - FilePathBgn) % 10 + 0x3041;
|
||||||
|
*P = L'\0';
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (P = FilePathBgn, EndP = P + MaxComponentLength + 1; EndP > P; P++)
|
||||||
|
*P = (P - FilePathBgn) % 10 + 0x3041;
|
||||||
|
*P = L'\0';
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||||
|
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||||
|
|
||||||
memfs_stop(memfs);
|
memfs_stop(memfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,52 @@
|
|||||||
|
|
||||||
#include "winfsp-tests.h"
|
#include "winfsp-tests.h"
|
||||||
|
|
||||||
|
typedef struct _FILE_FULL_DIR_INFORMATION
|
||||||
|
{
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
ULONG FileIndex;
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
LARGE_INTEGER EndOfFile;
|
||||||
|
LARGE_INTEGER AllocationSize;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG FileNameLength;
|
||||||
|
ULONG EaSize;
|
||||||
|
WCHAR FileName[1];
|
||||||
|
} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
|
||||||
|
|
||||||
|
typedef struct _FILE_DIRECTORY_INFORMATION
|
||||||
|
{
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
ULONG FileIndex;
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
LARGE_INTEGER EndOfFile;
|
||||||
|
LARGE_INTEGER AllocationSize;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG FileNameLength;
|
||||||
|
WCHAR FileName[1];
|
||||||
|
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NtQueryDirectoryFile (
|
||||||
|
HANDLE FileHandle,
|
||||||
|
HANDLE Event,
|
||||||
|
PIO_APC_ROUTINE ApcRoutine,
|
||||||
|
PVOID ApcContext,
|
||||||
|
PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
|
PVOID FileInformation,
|
||||||
|
ULONG Length,
|
||||||
|
FILE_INFORMATION_CLASS FileInformationClass,
|
||||||
|
BOOLEAN ReturnSingleEntry,
|
||||||
|
PUNICODE_STRING FileName,
|
||||||
|
BOOLEAN RestartScan);
|
||||||
|
|
||||||
static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
@ -269,6 +315,212 @@ void querydir_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t hash_chars(const wchar_t *s, size_t length)
|
||||||
|
{
|
||||||
|
/* djb2: see http://www.cse.yorku.ca/~oz/hash.html */
|
||||||
|
size_t h = 5381;
|
||||||
|
for (const wchar_t *t = s + length; t > s; ++s)
|
||||||
|
h = 33 * h + *s;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
static NTSTATUS querydir_nodup_dotest_thread_loop(void *FilePath)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
void *Buffer = 0;
|
||||||
|
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
size_t hash[64], hash_count = 0;
|
||||||
|
|
||||||
|
Buffer = malloc(4096);
|
||||||
|
if (0 == Buffer)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle = CreateFileW(
|
||||||
|
FilePath,
|
||||||
|
FILE_LIST_DIRECTORY,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Handle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Result = NtQueryDirectoryFile(
|
||||||
|
Handle,
|
||||||
|
0, 0, 0,
|
||||||
|
&IoStatus,
|
||||||
|
Buffer,
|
||||||
|
4096,
|
||||||
|
2/*FileFullDirectoryInformation*/,
|
||||||
|
FALSE,
|
||||||
|
0,
|
||||||
|
FALSE);
|
||||||
|
if (STATUS_NO_MORE_FILES == Result)
|
||||||
|
break;
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
for (FILE_FULL_DIR_INFORMATION *DirInfo = Buffer;;
|
||||||
|
DirInfo = (PVOID)((PUINT8)DirInfo + DirInfo->NextEntryOffset))
|
||||||
|
{
|
||||||
|
size_t h = hash_chars(DirInfo->FileName, DirInfo->FileNameLength / sizeof(WCHAR));
|
||||||
|
for (size_t i = 0; hash_count > i; i++)
|
||||||
|
if (hash[i] == h)
|
||||||
|
{
|
||||||
|
WCHAR FileName[256];
|
||||||
|
memcpy(FileName, DirInfo->FileName, DirInfo->FileNameLength);
|
||||||
|
FileName[DirInfo->FileNameLength / sizeof(WCHAR)] = L'\0';
|
||||||
|
FspDebugLog(__FUNCTION__ ": duplicate \"%S\"\n", FileName);
|
||||||
|
Result = STATUS_UNSUCCESSFUL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (sizeof hash / sizeof hash[0] > hash_count)
|
||||||
|
hash[hash_count++] = h;
|
||||||
|
if (0 == DirInfo->NextEntryOffset)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != Handle)
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
free(Buffer);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
static unsigned __stdcall querydir_nodup_dotest_thread(void *FilePath)
|
||||||
|
{
|
||||||
|
FspDebugLog(__FUNCTION__ ": \"%S\"\n", FilePath);
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
for (size_t i = 0; 5000 > i; i++)
|
||||||
|
{
|
||||||
|
Result = querydir_nodup_dotest_thread_loop(FilePath);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void querydir_nodup_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
|
|
||||||
|
static WCHAR *FileNames[] =
|
||||||
|
{
|
||||||
|
L"Extensions.cs",
|
||||||
|
L"JsonSchema.cs",
|
||||||
|
L"JsonSchemaBuilder.cs",
|
||||||
|
L"JsonSchemaConstants.cs",
|
||||||
|
L"JsonSchemaException.cs",
|
||||||
|
L"JsonSchemaGenerator.cs",
|
||||||
|
L"JsonSchemaModel.cs",
|
||||||
|
L"JsonSchemaModelBuilder.cs",
|
||||||
|
L"JsonSchemaNode.cs",
|
||||||
|
L"JsonSchemaNodeCollection.cs",
|
||||||
|
L"JsonSchemaResolver.cs",
|
||||||
|
L"JsonSchemaType.cs",
|
||||||
|
L"JsonSchemaWriter.cs",
|
||||||
|
L"UndefinedSchemaIdHandling.cs",
|
||||||
|
L"ValidationEventArgs.cs",
|
||||||
|
L"ValidationEventHandler.cs",
|
||||||
|
};
|
||||||
|
HANDLE Handle;
|
||||||
|
BOOL Success;
|
||||||
|
WCHAR FilePath[MAX_PATH];
|
||||||
|
HANDLE Threads[2];
|
||||||
|
DWORD ExitCode;
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
Success = CreateDirectoryW(FilePath, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (size_t i = 0; sizeof FileNames / sizeof FileNames[0] > i; i++)
|
||||||
|
{
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0\\%s",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileNames[i]);
|
||||||
|
Handle = CreateFileW(FilePath, GENERIC_ALL, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
for (size_t i = 0; sizeof Threads / sizeof Threads[0] > i; i++)
|
||||||
|
{
|
||||||
|
Threads[i] = (HANDLE)_beginthreadex(0, 0, querydir_nodup_dotest_thread, FilePath, 0, 0);
|
||||||
|
ASSERT(0 != Threads[i]);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; sizeof Threads / sizeof Threads[0] > i; i++)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(Threads[i], INFINITE);
|
||||||
|
GetExitCodeThread(Threads[i], &ExitCode);
|
||||||
|
CloseHandle(Threads[i]);
|
||||||
|
ASSERT(0 == ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; sizeof FileNames / sizeof FileNames[0] > i; i++)
|
||||||
|
{
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0\\%s",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileNames[i]);
|
||||||
|
Success = DeleteFileW(FilePath);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
Success = RemoveDirectoryW(FilePath);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void querydir_nodup_test(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Test GitHub issue #475. Credit for the investigation and reproduction
|
||||||
|
* of this issue goes to GitHub user @hach-que.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (NtfsTests)
|
||||||
|
{
|
||||||
|
WCHAR DirBuf[MAX_PATH];
|
||||||
|
GetTestDirectory(DirBuf);
|
||||||
|
querydir_nodup_dotest(-1, DirBuf, 0);
|
||||||
|
}
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
{
|
||||||
|
querydir_nodup_dotest(MemfsDisk | MemfsNoSlowio, 0, 0);
|
||||||
|
querydir_nodup_dotest(MemfsDisk | MemfsNoSlowio, 0, 1000);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if (WinFspNetTests)
|
||||||
|
{
|
||||||
|
querydir_nodup_dotest(MemfsNet | MemfsNoSlowio, L"\\\\memfs\\share", 0);
|
||||||
|
querydir_nodup_dotest(MemfsNet | MemfsNoSlowio, L"\\\\memfs\\share", 1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void querydir_single_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
static void querydir_single_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
@ -368,36 +620,6 @@ void querydir_expire_cache_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _FILE_DIRECTORY_INFORMATION {
|
|
||||||
ULONG NextEntryOffset;
|
|
||||||
ULONG FileIndex;
|
|
||||||
LARGE_INTEGER CreationTime;
|
|
||||||
LARGE_INTEGER LastAccessTime;
|
|
||||||
LARGE_INTEGER LastWriteTime;
|
|
||||||
LARGE_INTEGER ChangeTime;
|
|
||||||
LARGE_INTEGER EndOfFile;
|
|
||||||
LARGE_INTEGER AllocationSize;
|
|
||||||
ULONG FileAttributes;
|
|
||||||
ULONG FileNameLength;
|
|
||||||
WCHAR FileName[1];
|
|
||||||
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
NtQueryDirectoryFile (
|
|
||||||
_In_ HANDLE FileHandle,
|
|
||||||
_In_opt_ HANDLE Event,
|
|
||||||
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
|
|
||||||
_In_opt_ PVOID ApcContext,
|
|
||||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
|
||||||
_Out_writes_bytes_(Length) PVOID FileInformation,
|
|
||||||
_In_ ULONG Length,
|
|
||||||
_In_ FILE_INFORMATION_CLASS FileInformationClass,
|
|
||||||
_In_ BOOLEAN ReturnSingleEntry,
|
|
||||||
_In_opt_ PUNICODE_STRING FileName,
|
|
||||||
_In_ BOOLEAN RestartScan
|
|
||||||
);
|
|
||||||
|
|
||||||
static void querydir_buffer_overflow_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
static void querydir_buffer_overflow_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
@ -576,6 +798,40 @@ static void querydir_namelen_dotest(ULONG Flags, PWSTR Prefix, PWSTR Drive)
|
|||||||
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||||
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||||
|
|
||||||
|
for (P = FilePathBgn, EndP = P + MaxComponentLength - 1; EndP > P; P++)
|
||||||
|
*P = (P - FilePathBgn) % 10 + 0x3041;
|
||||||
|
*P = L'\0';
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
querydir_namelen_exists(FilePath);
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (P = FilePathBgn, EndP = P + MaxComponentLength; EndP > P; P++)
|
||||||
|
*P = (P - FilePathBgn) % 10 + 0x3041;
|
||||||
|
*P = L'\0';
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
querydir_namelen_exists(FilePath);
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (P = FilePathBgn, EndP = P + MaxComponentLength + 1; EndP > P; P++)
|
||||||
|
*P = (P - FilePathBgn) % 10 + 0x3041;
|
||||||
|
*P = L'\0';
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||||
|
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||||
|
|
||||||
memfs_stop(memfs);
|
memfs_stop(memfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,6 +988,7 @@ void dirnotify_test(void)
|
|||||||
void dirctl_tests(void)
|
void dirctl_tests(void)
|
||||||
{
|
{
|
||||||
TEST(querydir_test);
|
TEST(querydir_test);
|
||||||
|
TEST_OPT(querydir_nodup_test);
|
||||||
if (!OptShareName)
|
if (!OptShareName)
|
||||||
TEST_OPT(querydir_single_test);
|
TEST_OPT(querydir_single_test);
|
||||||
TEST(querydir_expire_cache_test);
|
TEST(querydir_expire_cache_test);
|
||||||
|
@ -273,6 +273,28 @@ void getfileinfo_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
|||||||
ASSERT(0 == FileInfo.nFileSizeLow && 0 == FileInfo.nFileSizeHigh);
|
ASSERT(0 == FileInfo.nFileSizeLow && 0 == FileInfo.nFileSizeHigh);
|
||||||
ASSERT(1 == FileInfo.nNumberOfLinks);
|
ASSERT(1 == FileInfo.nNumberOfLinks);
|
||||||
|
|
||||||
|
if (-1 != Flags)
|
||||||
|
{
|
||||||
|
/* WinFsp file systems respond to FileIdInformation queries with the IndexNumber zero-extended */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/* FILE_ID_INFO is missing from old version of SDK that we are still using */
|
||||||
|
ULONGLONG VolumeSerialNumber;
|
||||||
|
UINT8 FileId[16];
|
||||||
|
} IdInfo;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UINT64 IndexNumber;
|
||||||
|
UINT8 FileId[16];
|
||||||
|
} ExpectedFileId = { 0 };
|
||||||
|
Success = GetFileInformationByHandleEx(Handle, 0x12/*FileIdInfo*/, &IdInfo, sizeof IdInfo);
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
ExpectedFileId.IndexNumber = ((UINT64)FileInfo.nFileIndexHigh << 32) | (UINT64)FileInfo.nFileIndexLow;
|
||||||
|
ASSERT(0 == memcmp(&ExpectedFileId.FileId, &IdInfo.FileId, sizeof IdInfo.FileId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(Handle);
|
CloseHandle(Handle);
|
||||||
|
|
||||||
memfs_stop(memfs);
|
memfs_stop(memfs);
|
||||||
|
48
tst/winfsp-tests/loadun-test.c
Normal file
48
tst/winfsp-tests/loadun-test.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @file loadun-test.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2022 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#include <tlib/testsuite.h>
|
||||||
|
|
||||||
|
#include "winfsp-tests.h"
|
||||||
|
|
||||||
|
static void load_unload_test(void)
|
||||||
|
{
|
||||||
|
/* this is not a real test! */
|
||||||
|
|
||||||
|
FspFsctlStartService();
|
||||||
|
FspFsctlStartService();
|
||||||
|
|
||||||
|
FspFsctlStopService();
|
||||||
|
FspFsctlStopService();
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_unload_tests(void)
|
||||||
|
{
|
||||||
|
if (OptExternal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An attempt to unload the driver while other tests are executing can make all tests fail.
|
||||||
|
* For this reason we do not enable this test, except when doing specialized testing.
|
||||||
|
*/
|
||||||
|
//TEST_OPT(load_unload_test);
|
||||||
|
}
|
@ -48,9 +48,9 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
|||||||
FileInfoTimeout,
|
FileInfoTimeout,
|
||||||
1024,
|
1024,
|
||||||
1024 * 1024,
|
1024 * 1024,
|
||||||
50, /*SlowioMaxDelay*/
|
(Flags & MemfsNoSlowio) ? 0 : 50, /*SlowioMaxDelay*/
|
||||||
10, /*SlowioPercentDelay*/
|
(Flags & MemfsNoSlowio) ? 0 : 10, /*SlowioPercentDelay*/
|
||||||
5, /*SlowioRarefyDelay*/
|
(Flags & MemfsNoSlowio) ? 0 : 5, /*SlowioRarefyDelay*/
|
||||||
0,
|
0,
|
||||||
MemfsNet == Flags ? L"\\memfs\\share" : 0,
|
MemfsNet == Flags ? L"\\memfs\\share" : 0,
|
||||||
0,
|
0,
|
||||||
@ -67,6 +67,9 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
|||||||
Result = MemfsStart(Memfs);
|
Result = MemfsStart(Memfs);
|
||||||
ASSERT(NT_SUCCESS(Result));
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
|
Result = FspFsctlTransact(MemfsFileSystem(Memfs)->VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
memfs_running = 1;
|
memfs_running = 1;
|
||||||
memfs_handle = MemfsFileSystem(Memfs)->VolumeHandle;
|
memfs_handle = MemfsFileSystem(Memfs)->VolumeHandle;
|
||||||
|
|
||||||
|
@ -215,6 +215,9 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
|||||||
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
||||||
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
||||||
|
|
||||||
|
Result = FspFsctlTransact(VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName);
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName);
|
||||||
Thread = (HANDLE)_beginthreadex(0, 0, mount_volume_transact_dotest_thread, FilePath, 0, 0);
|
Thread = (HANDLE)_beginthreadex(0, 0, mount_volume_transact_dotest_thread, FilePath, 0, 0);
|
||||||
@ -246,6 +249,8 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
|||||||
ASSERT(0 != Request->Hint);
|
ASSERT(0 != Request->Hint);
|
||||||
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
||||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
||||||
|
/* since we made RejectIrpPriorToTransact0 mandatory the assertions below do not hold */
|
||||||
|
#if 0
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
{
|
{
|
||||||
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
||||||
@ -265,6 +270,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
|||||||
ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size);
|
ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size);
|
||||||
ASSERT(0 == mywcscmp((PVOID)Request->Buffer, -1, L"\\file0", -1));
|
ASSERT(0 == mywcscmp((PVOID)Request->Buffer, -1, L"\\file0", -1));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ASSERT(FspFsctlTransactCanProduceResponse(Response, ResponseBufEnd));
|
ASSERT(FspFsctlTransactCanProduceResponse(Response, ResponseBufEnd));
|
||||||
|
|
||||||
@ -294,7 +300,8 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
|||||||
GetExitCodeThread(Thread, &ExitCode);
|
GetExitCodeThread(Thread, &ExitCode);
|
||||||
CloseHandle(Thread);
|
CloseHandle(Thread);
|
||||||
|
|
||||||
ASSERT(ERROR_ACCESS_DENIED == ExitCode || ERROR_OPERATION_ABORTED == ExitCode);
|
ASSERT(0 != ExitCode);
|
||||||
|
//ASSERT(ERROR_ACCESS_DENIED == ExitCode || ERROR_OPERATION_ABORTED == ExitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mount_volume_transact_test(void)
|
void mount_volume_transact_test(void)
|
||||||
|
@ -158,7 +158,10 @@ static void posix_map_sid_test(void)
|
|||||||
|
|
||||||
CloseHandle(Token);
|
CloseHandle(Token);
|
||||||
|
|
||||||
for (size_t i = 0; sizeof map / sizeof map[0] > i; i++)
|
size_t n = sizeof map / sizeof map[0];
|
||||||
|
if (RunningInContainer)
|
||||||
|
n -= 2; /* container: disable tests for "user manager\containeradministrator" */
|
||||||
|
for (size_t i = 0; n > i; i++)
|
||||||
{
|
{
|
||||||
Success = ConvertStringSidToSidW(map[i].SidStr, &Sid0);
|
Success = ConvertStringSidToSidW(map[i].SidStr, &Sid0);
|
||||||
ASSERT(Success);
|
ASSERT(Success);
|
||||||
|
@ -187,6 +187,8 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
|||||||
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
||||||
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
||||||
|
|
||||||
|
Result = FspFsctlTransact(VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 RequestBuf[FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN];
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 RequestBuf[FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN];
|
||||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 ResponseBuf[FSP_FSCTL_TRANSACT_RSP_SIZEMAX];
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 ResponseBuf[FSP_FSCTL_TRANSACT_RSP_SIZEMAX];
|
||||||
@ -223,6 +225,8 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
|||||||
ASSERT(0 != Request->Hint);
|
ASSERT(0 != Request->Hint);
|
||||||
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
||||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
||||||
|
/* since we made RejectIrpPriorToTransact0 mandatory the assertions below do not hold */
|
||||||
|
#if 0
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
{
|
{
|
||||||
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
||||||
@ -239,6 +243,7 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
|||||||
ASSERT(!Request->Req.Create.OpenTargetDirectory);
|
ASSERT(!Request->Req.Create.OpenTargetDirectory);
|
||||||
ASSERT(!Request->Req.Create.CaseSensitive);
|
ASSERT(!Request->Req.Create.CaseSensitive);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ResponseBufSize = 0;
|
ResponseBufSize = 0;
|
||||||
RequestBufSize = sizeof RequestBuf;
|
RequestBufSize = sizeof RequestBuf;
|
||||||
|
@ -89,7 +89,7 @@ static void volpath_test(void)
|
|||||||
* when *not* using the MountManager and therefore disable
|
* when *not* using the MountManager and therefore disable
|
||||||
* this test when using a non-MountManager mount point.
|
* this test when using a non-MountManager mount point.
|
||||||
*/
|
*/
|
||||||
if (!NtfsTests && !OptMountPoint)
|
if (NtfsTests || OptMountPoint)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (WinFspDiskTests)
|
if (WinFspDiskTests)
|
||||||
@ -107,8 +107,15 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
|||||||
BOOLEAN Success, VolumePathNameSuccess[8];
|
BOOLEAN Success, VolumePathNameSuccess[8];
|
||||||
WCHAR FilePath[MAX_PATH];
|
WCHAR FilePath[MAX_PATH];
|
||||||
WCHAR VolumePathName[MAX_PATH], VolumeName[MAX_PATH];
|
WCHAR VolumePathName[MAX_PATH], VolumeName[MAX_PATH];
|
||||||
|
WCHAR FinalPath[MAX_PATH];
|
||||||
|
DWORD FinalResult;
|
||||||
|
|
||||||
Result = FspFileSystemSetMountPoint(MemfsFileSystem(memfs), MountPoint);
|
Result = FspFileSystemSetMountPoint(MemfsFileSystem(memfs), MountPoint);
|
||||||
|
if (STATUS_ACCESS_DENIED == Result)
|
||||||
|
{
|
||||||
|
FspDebugLog(__FUNCTION__ ": need Administrator\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
ASSERT(NT_SUCCESS(Result));
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
Prefix = FspFileSystemMountPoint(MemfsFileSystem(memfs));
|
Prefix = FspFileSystemMountPoint(MemfsFileSystem(memfs));
|
||||||
@ -125,6 +132,9 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
|||||||
Handle = CreateFileW(FilePath,
|
Handle = CreateFileW(FilePath,
|
||||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
FinalResult = GetFinalPathNameByHandleW(
|
||||||
|
Handle, FinalPath, MAX_PATH - 1, VOLUME_NAME_DOS | FILE_NAME_OPENED);
|
||||||
|
ASSERT(0 != FinalResult && FinalResult < MAX_PATH);
|
||||||
CloseHandle(Handle);
|
CloseHandle(Handle);
|
||||||
|
|
||||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||||
@ -187,6 +197,9 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
|||||||
Handle = CreateFileW(FilePath,
|
Handle = CreateFileW(FilePath,
|
||||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
FinalResult = GetFinalPathNameByHandleW(
|
||||||
|
Handle, FinalPath, MAX_PATH - 1, VOLUME_NAME_DOS | FILE_NAME_OPENED);
|
||||||
|
ASSERT(0 != FinalResult && FinalResult < MAX_PATH);
|
||||||
CloseHandle(Handle);
|
CloseHandle(Handle);
|
||||||
|
|
||||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||||
@ -232,6 +245,7 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
|||||||
ASSERT(VolumePathNameSuccess[6]);
|
ASSERT(VolumePathNameSuccess[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
memfs_stop(memfs);
|
memfs_stop(memfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,8 +254,13 @@ static void volpath_mount_test(void)
|
|||||||
/*
|
/*
|
||||||
* This test does FspFileSystemSetMountPoint and therefore
|
* This test does FspFileSystemSetMountPoint and therefore
|
||||||
* cannot be used with --external or --mountpoint.
|
* cannot be used with --external or --mountpoint.
|
||||||
|
*
|
||||||
|
* Also the MountMgr appears to be buggy and fail with spurious
|
||||||
|
* STATUS_NOT_SUPPORTED and STATUS_INVALID_PARAMETER error codes
|
||||||
|
* under Windows Containers (at least with ServerCore 1909). So
|
||||||
|
* disable if RunningInContainer.
|
||||||
*/
|
*/
|
||||||
if (NtfsTests || OptMountPoint)
|
if (NtfsTests || OptMountPoint || RunningInContainer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (WinFspDiskTests)
|
if (WinFspDiskTests)
|
||||||
@ -270,6 +289,24 @@ static void volpath_mount_test(void)
|
|||||||
|
|
||||||
//volpath_mount_dotest(MemfsDisk, 0, 0);
|
//volpath_mount_dotest(MemfsDisk, 0, 0);
|
||||||
volpath_mount_dotest(MemfsDisk, 0, MountPoint);
|
volpath_mount_dotest(MemfsDisk, 0, MountPoint);
|
||||||
|
|
||||||
|
WCHAR DirBuf[MAX_PATH];
|
||||||
|
int DirBufLen;
|
||||||
|
GetTestDirectory(DirBuf);
|
||||||
|
ASSERT(
|
||||||
|
L'\\' == DirBuf[0] &&
|
||||||
|
L'\\' == DirBuf[1] &&
|
||||||
|
L'?' == DirBuf[2] &&
|
||||||
|
L'\\' == DirBuf[3]);
|
||||||
|
DirBuf[2] = '.';
|
||||||
|
DirBufLen = lstrlenW(DirBuf);
|
||||||
|
ASSERT(MAX_PATH >= DirBufLen + 5);
|
||||||
|
DirBuf[DirBufLen++] = L'\\';
|
||||||
|
DirBuf[DirBufLen++] = L'm';
|
||||||
|
DirBuf[DirBufLen++] = L'n';
|
||||||
|
DirBuf[DirBufLen++] = L't';
|
||||||
|
DirBuf[DirBufLen++] = L'\0';
|
||||||
|
volpath_mount_dotest(MemfsDisk, 0, DirBuf);
|
||||||
}
|
}
|
||||||
if (WinFspNetTests)
|
if (WinFspNetTests)
|
||||||
{
|
{
|
||||||
@ -290,7 +327,12 @@ void volpath_tests(void)
|
|||||||
/*
|
/*
|
||||||
* This test does FspFileSystemSetMountPoint and therefore
|
* This test does FspFileSystemSetMountPoint and therefore
|
||||||
* cannot be used with --external or --mountpoint.
|
* cannot be used with --external or --mountpoint.
|
||||||
|
*
|
||||||
|
* Also the MountMgr appears to be buggy and fail with spurious
|
||||||
|
* STATUS_NOT_SUPPORTED and STATUS_INVALID_PARAMETER error codes
|
||||||
|
* under Windows Containers (at least with ServerCore 1909). So
|
||||||
|
* disable if RunningInContainer.
|
||||||
*/
|
*/
|
||||||
if (!NtfsTests && !OptMountPoint)
|
if (!NtfsTests && !OptMountPoint && !RunningInContainer)
|
||||||
TEST(volpath_mount_test);
|
TEST(volpath_mount_test);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
int NtfsTests = 0;
|
int NtfsTests = 0;
|
||||||
int WinFspDiskTests = 1;
|
int WinFspDiskTests = 1;
|
||||||
int WinFspNetTests = 1;
|
int WinFspNetTests = 1;
|
||||||
|
int RunningInContainer = 0;
|
||||||
|
|
||||||
BOOLEAN OptExternal = FALSE;
|
BOOLEAN OptExternal = FALSE;
|
||||||
BOOLEAN OptFuseExternal = FALSE;
|
BOOLEAN OptFuseExternal = FALSE;
|
||||||
@ -220,6 +221,7 @@ LONG WINAPI UnhandledExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
|
|||||||
argv[argc] = 0
|
argv[argc] = 0
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
TESTSUITE(load_unload_tests);
|
||||||
TESTSUITE(fuse_opt_tests);
|
TESTSUITE(fuse_opt_tests);
|
||||||
TESTSUITE(fuse_tests);
|
TESTSUITE(fuse_tests);
|
||||||
TESTSUITE(posix_tests);
|
TESTSUITE(posix_tests);
|
||||||
@ -258,6 +260,12 @@ int main(int argc, char *argv[])
|
|||||||
if (0 == getenv("WINFSP_TESTS_EXCEPTION_FILTER_DISABLE"))
|
if (0 == getenv("WINFSP_TESTS_EXCEPTION_FILTER_DISABLE"))
|
||||||
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
||||||
|
|
||||||
|
RunningInContainer = ERROR_SUCCESS == RegGetValueW(
|
||||||
|
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
|
||||||
|
L"ContainerType",
|
||||||
|
RRF_RT_REG_DWORD, 0,
|
||||||
|
0, 0);
|
||||||
|
|
||||||
for (int argi = 1; argc > argi; argi++)
|
for (int argi = 1; argc > argi; argi++)
|
||||||
{
|
{
|
||||||
const char *a = argv[argi];
|
const char *a = argv[argi];
|
||||||
@ -266,6 +274,7 @@ int main(int argc, char *argv[])
|
|||||||
if (0 == strcmp("--ntfs", a) || 0 == strcmp("--external", a))
|
if (0 == strcmp("--ntfs", a) || 0 == strcmp("--external", a))
|
||||||
{
|
{
|
||||||
OptExternal = TRUE;
|
OptExternal = TRUE;
|
||||||
|
OptFuseExternal = FALSE;
|
||||||
NtfsTests = 1;
|
NtfsTests = 1;
|
||||||
WinFspDiskTests = 0;
|
WinFspDiskTests = 0;
|
||||||
WinFspNetTests = 0;
|
WinFspNetTests = 0;
|
||||||
@ -404,6 +413,10 @@ int main(int argc, char *argv[])
|
|||||||
if (!NtfsTests && OptShareName)
|
if (!NtfsTests && OptShareName)
|
||||||
ABORT("option --share requires --ntfs/--external");
|
ABORT("option --share requires --ntfs/--external");
|
||||||
|
|
||||||
|
if (RunningInContainer)
|
||||||
|
/* container: disable network file system tests */
|
||||||
|
WinFspNetTests = 0;
|
||||||
|
|
||||||
DisableBackupRestorePrivileges();
|
DisableBackupRestorePrivileges();
|
||||||
|
|
||||||
AddNetShareIfNeeded();
|
AddNetShareIfNeeded();
|
||||||
|
@ -213,6 +213,7 @@ VOID GetTestDirectoryEx(PWSTR DirBuf, ULONG DirBufSize, PWSTR DriveBuf);
|
|||||||
extern int NtfsTests;
|
extern int NtfsTests;
|
||||||
extern int WinFspDiskTests;
|
extern int WinFspDiskTests;
|
||||||
extern int WinFspNetTests;
|
extern int WinFspNetTests;
|
||||||
|
extern int RunningInContainer;
|
||||||
|
|
||||||
extern BOOLEAN OptExternal;
|
extern BOOLEAN OptExternal;
|
||||||
extern BOOLEAN OptFuseExternal;
|
extern BOOLEAN OptFuseExternal;
|
||||||
|
Reference in New Issue
Block a user