dokan-dev / dokany

User mode file system library for windows with FUSE Wrapper
http://dokan-dev.github.io
5.27k stars 666 forks source link

The window does not refresh the mounted volume by itself when run the mirror by service #528

Open noairman opened 7 years ago

noairman commented 7 years ago

Environment

Check List

Description

I add the mirror.exe path to a service(the HKLM\SYSTEM\CurrentControlSet\Services registry tree) with the follwing value: StartType=0x2 (SERVICE_AUTO_START) ServiceType=0x00000010 (SERVICE_WIN32_OWN_PROCESS) https://docs.microsoft.com/zh-cn/windows-hardware/drivers/install/inf-addservice-directive reg content

In that case ,I start the service and I can't find the M: volume until i refresh on the contextmenu or use the F5 key.And when I stop the service, unmounted it ,the M: volume is still there until refresh the window I change the StartType to 0x0 (SERVICE_BOOT_START) or 0x1 (SERVICE_SYSTEM_START) and ServiceType to 0x00000020 (SERVICE_WIN32_SHARE_PROCESS) or 0x00000002 (SERVICE_FILE_SYSTEM_DRIVER),it is still the same. I mount it with /o flag(mount manager), it is still the same

but if we just run the mirror.exe in the cmd.exe,the window will show the M: volume by itself,and disappear by itself when stop the service.

Is there any thing about the application compatibility – Session 0 Isolation https://blogs.technet.microsoft.com/askperf/2007/04/27/application-compatibility-session-0-isolation/ And i do not know how can i locate the cause of the error. But with the dokan 0.6 sys,I did the same thing,there is no issue

And i test the volume management functions(https://msdn.microsoft.com/en-us/library/windows/desktop/aa365730(v=vs.85).aspx) : a. some of the functions return false when mount without the /o flag,like the GetVolumePathName , GetVolumeInformationByHandleW or GetVolumeNameForVolumeMountPoint, and the last error is 87 ERROR_INVALID_PARAMETER.But the window can see it even if the api return false, and i don't know why b. when mount with the /o flag,the function SetVolumeMountPoint return false ,and the last error is 145 directory is not empty,but the VolumeMountPoint in M:,the directory is not empty )

marinkobabic commented 7 years ago

So please use the mount manager parameter for mirror

Am 12.06.2017 09:08 schrieb "noairman" notifications@github.com:

Environment

  • Windows version: 10 or 7
  • Processor architecture: 64 bit
  • Dokany version: Release 1.0.3
  • Library type (Dokany/FUSE): dokany

Check List

Description

I add the mirror.exe path to a service(the HKLM\SYSTEM\CurrentControlSet\Services registry tree) with the follwing value: StartType=0x2 (SERVICE_AUTO_START) ServiceType=0x00000010 (SERVICE_WIN32_OWN_PROCESS) But with the dokan 0.6 sys,I did the same thing,there is no issue https://docs.microsoft.com/zh-cn/windows-hardware/drivers/ install/inf-addservice-directive

1.

In that case ,I start the service and I can't find the M: volume until i refresh on the contextmenu or use the F5 key.And when I stop the service, unmounted it ,the M: volume is still there until refresh the window but if we just run the mirror.exe in the cmd.exe,the window will show the M: volume by itself,and disappear by itself when stop the service. But with the dokan 0.6 sys,I did the same thing,there is no issue

Is there any thing about the application compatibility – Session 0 Isolation https://blogs.technet.microsoft.com/askperf/2007/04/ 27/application-compatibility-session-0-isolation/

What's more,I change the StartType to 0x0 (SERVICE_BOOT_START) or 0x1 (SERVICE_SYSTEM_START)and ServerType to 0x00000020 (SERVICE_WIN32_SHARE_PROCESS) or 0x00000002 (SERVICE_FILE_SYSTEM_DRIVER),it is still the same.

And i do not know how can i locate the cause of the error.

1.

And i test the volume management functions(https://msdn. microsoft.com/en-us/library/windows/desktop/aa365730(v=vs.85).aspx),there is no error (some of the functions return false when without the /o flag,like the GetVolumePathName , GetVolumeInformationByHandleW or GetVolumeNameForVolumeMountPoint, and the last error is 87 ERROR_INVALID_PARAMETER.But the window can see it even if the api return false, and i don't know why)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOHe2YIxzMfb1D2Wdupijbv3lRCTaks5sDOPwgaJpZM4N2uhy .

noairman commented 7 years ago

hi, @marinkobabic , the mount manager parameter means the /o flag when mount it ? I tried the mount manager as i said, mirror.exe /o /r c: /l M: ,it is still the same

marinkobabic commented 7 years ago

Did you setup your service so that a desktop interaction is possible?

Am 12.06.2017 12:15 schrieb "noairman" notifications@github.com:

hi, @marinkobabic https://github.com/marinkobabic , the mount manager parameter means the /o flag when mount it ? I tried the mount manager as i said, mirror.exe /o /r c: /l M: ,it is still the same

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-307748509, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOG5Bb4-PMZISBdHeRqp-Ah4TeOoZks5sDQ_VgaJpZM4N2uhy .

noairman commented 7 years ago

@marinkobabic ,you mean the "allow the service to interact with desktop" I setup it ,it still the same.

Liryna commented 7 years ago

@noairman This is probably related to broadcast notification that seems to not be send when using service.

Did you try to run the service as à user and not local system ?

noairman commented 7 years ago

@Liryna ,you mean this,run service as a user account,not a local system account? But it doesn't help. ser

marinkobabic commented 7 years ago

Please attach the kernel log. Strange that it doesn't work. Using a user for service in combination with interaction with desktop should work. You are mounting the drive globally and not just for the current session?

When you kill the explorer.exe and start the task explorer.exe then is the drive visible?

Am 13.06.2017 05:10 schrieb "noairman" notifications@github.com:

@Liryna https://github.com/liryna ,you mean this,run service as a user account,not a local system account? But it doesn't help. [image: ser] https://user-images.githubusercontent.com/10110303/27062705-5c1da2e0-501f-11e7-90a3-a762c9d2f0cd.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-307984873, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOF2IAPK8FsF3vwoDtVrCnovXMeRkks5sDe2vgaJpZM4N2uhy .

noairman commented 7 years ago

@Liryna ,as you say,the BroadcastSystemMessage's receipients is BSM_APPLICATIONS and BSM_ALLDESKTOPS,it broadcasted the message to the explorer,but maybe the explorer.exe didn't receive it when using service.and this is strange. @marinkobabic ,i do not need to kill the explorer.exe and start it again to see the drive,i just need to refresh it using F5 key or the contextmenu refresh menu.And i just mout it with /r and /l,not using the /c for current session only.

Liryna commented 7 years ago

@noairman I faced this behaviour already :( I moved the mount to starting tray application at user session start.

I cannot say if the broadcast should be changed or is it normal that it cannot simply broadcast to applications :(

We can compare what dokan 0.6.0 were doing compared to right now in this broadcast function.

IvanKonov commented 7 years ago

I think you should fix this bug. The situation when the disk mounts the service is not so rare. On my Win10x64 Explorer it is necessary to restart so that it sees the disk. Normal update or F5 does not help.

Liryna commented 7 years ago

@IvanKonov This could be debug by anyone since it happens in the library (see my previous post). Contributions are always appreciated !

zhucaibing commented 7 years ago

This problem happened to me also. The function BroadcastSystemMessage return success, but the volume not appeared in Explorer. My code need to run as a service, is there anyway to notify explorer in a service?

linyuan0 commented 6 years ago

I have a way to solve this, but this does not seem to be a good solution.

session.txt

dokan/mount.c DokanBroadcastLink call the above function

redfs_service.exe need to call SHChangeNotify

Because service-initiated mirror is at session 0, it is still at session 0 when executed to DokanBroadcastLink function; we can not refresh explorer by notifying explorer.exe at session 1 by SHChangeNotify function. So we need to create a Session 1 process to call SHChangeNotify function to notify the same in the session 1 of the explorer; The above new function is to achieve this function.

IvanKonov commented 6 years ago

@linyuan870 Many thanks! This can help those who already have this process in session 1. Prompt, with what parameters it is necessary to cause function SHChangeNotify?

Liryna commented 6 years ago

Oh thank you @linyuan870 ! This is very helpful for people that will face this issue !

@IvanKonov I think here, DokanBroadcastLink would "just" need to be called with session 1. It has already all the correct param https://github.com/dokan-dev/dokany/blob/b1a388d1a480ad4a7124b74e8a57229b479d532c/dokan/mount.c#L506

@linyuan870 do you think we can add a check in DokanBroadcastLink to see if we are running in session 0 and otherwise fork/call an exe (new dokanctl option ?) that recall DokanBroadcastLink in session 1 ? Also, is there are cases where session 1 could not be called from session 0 ? Fail to CreateProcessAsUser ?

IvanKonov commented 6 years ago

@Liryna Thank you. I have already been able to successfully use this method from the application manager of my service (C#)


public static void RefreshDrive(Char label_drive_s)
        {
            NativeMethods.MessageBroadcastRecipients message_broadcast_recipients = NativeMethods.MessageBroadcastRecipients.BSM_APPLICATIONS;
            const UInt32 wm_devicechange = 0x0219;
            const Int32 dbt_devicearrival = 0x8000;
            const UInt32 dbt_devtyp_volume = 0x00000002;

            NativeMethods.DEV_BROADCAST_VOLUME broadcast_volume = new NativeMethods.DEV_BROADCAST_VOLUME();
            broadcast_volume.dbch_Size = (UInt32)Marshal.SizeOf(structure: broadcast_volume);
            broadcast_volume.dbch_Devicetype = dbt_devtyp_volume;
            broadcast_volume.dbch_Reserved = 0;
            broadcast_volume.dbch_Unitmask = (UInt32)(1 << (Char.ToUpper(c: label_drive_s) - 'A'));
            broadcast_volume.dbch_Flags = 0;

            NativeMethods.BroadcastSystemMessage(
                flags: NativeMethods.MessageBroadcastFlags.BSF_NOHANG | NativeMethods.MessageBroadcastFlags.BSF_NOTIMEOUTIFNOTHUNG | NativeMethods.MessageBroadcastFlags.BSF_FORCEIFHUNG,
                lpInfo: ref message_broadcast_recipients,
                Msg: wm_devicechange,
                wParam: dbt_devicearrival,
                lParam: broadcast_volume);
        }
linyuan0 commented 6 years ago

@Liryna Hi, You say add a check in DokanBroadcastLink, the following if statement seems to be successful only in the session 0. if (safe && EnableTokenPrivilege(SE_TCB_NAME, TRUE)) { receipients |= BSM_ALLDESKTOPS; } @IvanKonov Hi,
The method you use is recall DokanBroadcastLink in session 1?

linyuan0 commented 6 years ago

@Liryna Hi, I think it's possible to add a new dokanctl option, but the exe path in the CreateProcessAsUser function needs to be handled to make it work for everyone.

IvanKonov commented 6 years ago

@linyuan870 Hello! This method calls BroadcastSystemMessage (user32.dll), and it works for me. Because I have a process in the system tray, and the service gives the command to this process to execute the method, while mounting the disk.

linyuan0 commented 6 years ago

@IvanKonov Hello, The method you need to use CreateProcessAsUser to create your process?

Liryna commented 6 years ago

@linyuan870 exe path can be foung with env variable DokanLibraryLibx64EnvPath or DokanLibraryLibx86EnvPath but it would probably safer to be able to run directly DokanBroadcastLink in the same process (thread/fork) in another session (do not know if this is possible in windows).

linyuan0 commented 6 years ago

@Liryna I want to get dokanctl.exe path, such as G: \ test \ banben \ 1.0.5 \ dokany \ x64 \ Debug \ dokanctl.exe; how to get through DokanLibraryLibx64EnvPath.

Liryna commented 6 years ago

@linyuan870 My bad, I gave the wrong value.

The installer will add in the env the variable DokanLibrary$(var.MajorVersion) => DokanLibrary1 The path is directly the folder of the dokanctl.exe this path will be to the x64 if x64 OS or x86 for x86 OS. https://github.com/dokan-dev/dokany/blob/08aeab6ff1305e9eec2799f7f6a2b97d28781dec/dokan_wix/Dokan_x64.wxs#L206 So just need to be sure to start the process correctly from a x86/x64 process regarding https://stackoverflow.com/questions/3038363/can-a-wow64-process-create-fork-etc-pure-x64-process

linyuan0 commented 6 years ago

@Liryna I added an option in

dokan_control / dokanctl.c

case L's': { DWORD wEventId = lstrcmpi(argv[2], TEXT("1")) == 0 ? SHCNE_DRIVEREMOVED : SHCNE_DRIVEADD; SHChangeNotify(wEventId, SHCNF_PATH | SHCNF_FLUSHNOWAIT, TEXT("A:\"), NULL); } break; It is successful. SHChangeNotify inside the DokanBroadcastLink function can already be refreshed. Is it necessary to call DokanBroadcastLink? Still do not know how to get DokanLibraryEnvPath from dokany / dokan_wix / Dokan_x64.wxs.

linyuan0 commented 6 years ago

@Liryna WCHAR path[MAX_PATH]= TEXT("G:\test\banben\1.0.5\dokany\x64\Debug\dokanctl.exe"); CreateProcessAsUser(hTokenDup, NULL,path, NULL, NULL, FALSE, dwCreationFlag, pEnv, NULL, &si, &pi);

If you get DokanLibraryEnvPath, you do not need to specify the path to dokanctl.exe above; this may actually solve the problem.

linyuan0 commented 6 years ago

https://github.com/linyuan870/dokany/commit/9f24adcfa888e88e4d1539d5e3f004764705eee4 Now it's not enough that you need to change the path above to your dokanctl.exe path. such as WCHAR path[MAX_PATH] = TEXT("G:\test\dokany\x64\Debug\dokanctl.exe");

Liryna commented 6 years ago

You can use GetEnvironmentVariable to get the env variable. Should probably check if variable is set, if the dokanctl really does exist and such.

But to tell the truth I feel that all of this is overkill for just a SHChangeNotify. Probably this is more simple to be just be handle a tray like @IvanKonov did. Adding this case in the FAQ to inform people using service.

Rondom commented 6 years ago

Usual uninformed naive question from me...: Why does Explorer not use the message sent by BroadcastSystemMessage? Why is an additonal SHChangeNotify needed? https://github.com/dokan-dev/dokany/blob/b1a388d1a480ad4a7124b74e8a57229b479d532c/dokan/mount.c#L533

How do tools like SUBST handle this? Or does SUBST only work for the current session?

Liryna commented 6 years ago

Windows services have no access/broadcast to Desktop applications. They cannot interact with the user interface with a window or such. It mean that dokan when running as service is just sending the message of device arrival to no one 😃

SUBST is a service ?

marinkobabic commented 6 years ago

For some reason only DefineDosDevice works in a service I assume so. I also think that SUBST command uses this one which does a broadcast.

On 26 Nov 2017 8:56 pm, "Liryna" notifications@github.com wrote:

Windows services have no access/broadcast to Desktop applications. They cannot interact with the user interface with a window or such. It mean that dokan when running as service is just sending the message of device arrival to no one 😃

SUBST is a service ?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-347033814, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOFxvB7kWYnLANIXz4yQE2vzq4Fvvks5s6cKCgaJpZM4N2uhy .

Rondom commented 6 years ago

Ah, I see. I thought that BSM_ALLDESKTOPS from a service would enable sending messages to everything.

Subst is no service of course. I remember using it under MS-DOS 5.0...haha Googling says it uses a function called DefineDosDevice, but what would happen when running SUBST inside a service?

Would the checkbox "Allow this service to interact with the desktop" help?

Liryna commented 6 years ago

Would the checkbox "Allow this service to interact with the desktop" help?

I did the test and nothing 😢 Also same report here https://github.com/dokan-dev/dokany/issues/528#issuecomment-307753993

linyuan0 commented 6 years ago

@Liryna As he said "Because I have a process in the system tray", if his method works well for people who do not have this process then his approach is definitely better (what if we did not have that process? My method is to think of each of us have dokanctl.exe, really a little overkill); GetEnvironmentVariable seemingly only access such as% HOMEPATH% this environment variable.

Liryna commented 6 years ago

@linyuan870 DokanLibrary1 is a environment variable. GetEnvironmentVariable should be able to get it.

linyuan0 commented 6 years ago

@Liryna I've tried DokanLibrary1, but GetEnvironmentVariable does not get the path; is it because I disabled driver signing at install time?

1 DokanLibrary1 environment variables will appear in the picture above?

Liryna commented 6 years ago

@linyuan870 It should appear yes 😢

linyuan0 commented 6 years ago

@Liryna But I did not show up。

marinkobabic commented 6 years ago

Makes it any difference when the service is started with a admin user credentials?

On 27 Nov 2017 15:03, "liny" notifications@github.com wrote:

@Liryna https://github.com/liryna But I did not show up。

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-347190318, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOAwqTV-f5azmPzjhoDFnfht1HMNdks5s6sE4gaJpZM4N2uhy .

linyuan0 commented 6 years ago

@marinkobabic I use the admin user but did not appear; What is the difference between the credentials mean?

marinkobabic commented 6 years ago

The expectation was that system user may not have permission to do a broadcast.

On 27 Nov 2017 15:50, "liny" notifications@github.com wrote:

@marinkobabic https://github.com/marinkobabic I use the admin user but did not appear; What is the difference between the credentials mean?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-347205007, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOLFMm2Y2_rAMHbxT7BVAy6rZj4f9ks5s6sxCgaJpZM4N2uhy .

linyuan0 commented 6 years ago

@marinkobabic Again this question.....

marinkobabic commented 6 years ago

For some reason the DefineDosDevice can do the broadcast and Dokan not. We need to figure out why.

On 27 Nov 2017 15:57, "liny" notifications@github.com wrote:

@marinkobabic https://github.com/marinkobabic Again this question.....

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-347207013, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOBnYUP42f0pM6BhHxbQh0VGoA6pbks5s6s26gaJpZM4N2uhy .

marinkobabic commented 6 years ago

Does the account have SE_TCB_NAME permission?

On 27 Nov 2017 3:58 pm, "Marinko Babic" marinko.android@gmail.com wrote:

For some reason the DefineDosDevice can do the broadcast and Dokan not. We need to figure out why.

On 27 Nov 2017 15:57, "liny" notifications@github.com wrote:

@marinkobabic https://github.com/marinkobabic Again this question.....

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-347207013, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOBnYUP42f0pM6BhHxbQh0VGoA6pbks5s6s26gaJpZM4N2uhy .

linyuan0 commented 6 years ago

@marinkobabic SE_TCB_NAME permission when service starts.

linyuan0 commented 6 years ago

@marinkobabic SE_TCB_NAME permission to start the service at this time even HOMEPATH no path; When I start the service can get the path to HOMEPATH, but still can not get DokanLibrary1. The reason I think the problem is that there is no DokanLibrary1 in my system environment variables or user environment variables. Dokanctl.exe / i d (compile-time disabled driver signature) Installation dokan1.sys, so there should be no problem installing it?

marinkobabic commented 6 years ago

@liny For testing purposes you can add the environment variable manually on machine level. Then you should be able to access it. Normally the variable is set properly during the setup.

On 28 Nov 2017 3:06 am, "liny" notifications@github.com wrote:

@marinkobabic https://github.com/marinkobabic SE_TCB_NAME permission to start the service at this time even HOMEPATH no path; When I start the service can get the path to HOMEPATH, but still can not get DokanLibrary1. The reason I think the problem is that there is no DokanLibrary1 in my system environment variables or user environment variables. Dokanctl.exe / i d (compile-time disabled driver signature) Installation dokan1.sys, so there should be no problem installing it?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-347390168, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOKQr0U_EtErWlTC8NI-W_AFJ8Dygks5s62qIgaJpZM4N2uhy .

linyuan0 commented 6 years ago

@marinkobabic My program to start the service mount the drive letter problem is solved, because I have a service installation program; GetModuleFileName can get the program path directly. The path I get this variable is mainly to solve the problem that other people can not automatically refresh (because there are dokanctl.exe); However, the value of the environment variable (such as% HOMEPATH%) can not be obtained by GetEnvironmentVariable function when starting the service; So now There is no point in having the DokanLibrary1 variable for environment variables.

marinkobabic commented 6 years ago

@liny Can you access any machine level variable? The HOMEPATH is user specific and you are running as system user. It may not exist. Why you should you generally not be able to access machine level variables?

On 28 Nov 2017 7:48 am, "liny" notifications@github.com wrote:

@marinkobabic https://github.com/marinkobabic My program to start the service mount the drive letter problem is solved, because I have a service installation program; GetModuleFileName can get the program path directly. The path I get this variable is mainly to solve the problem that other people can not automatically refresh (because there are dokanctl.exe); However, the value of the environment variable (such as% HOMEPATH%) can not be obtained by GetEnvironmentVariable function when starting the service; So now There is no point in having the DokanLibrary1 variable for environment variables.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dokan-dev/dokany/issues/528#issuecomment-347429970, or mute the thread https://github.com/notifications/unsubscribe-auth/ADHSOMcj_KFL6kCpu54SM0z0sNAqxM6cks5s66y3gaJpZM4N2uhy .

linyuan0 commented 6 years ago

@marinkobabic I may not make it clear. As a user login, you can get the value of the environment variable; As system user, you can not get it. To start the service is this, so no way to get DokanLibrary1 variable.

linyuan0 commented 6 years ago

@marinkobabic I tried it, As system user, you can get the system environment variables; Then DokanLibrary1 variable installation of user variables or system environment variables? If it is a system environment variables should be solved