diff --git a/src/dll/fs.c b/src/dll/fs.c index e65558e0..9b358936 100644 --- a/src/dll/fs.c +++ b/src/dll/fs.c @@ -16,7 +16,6 @@ */ #include -#include enum { @@ -373,254 +372,3 @@ FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem, FspFsctlStop(FileSystem->VolumeHandle); } } - -static NTSTATUS FspFileSystemFixServiceSecurity(HANDLE SvcHandle) -{ - /* - * This function adds an ACE that allows Everyone to start a service. - */ - - PSID WorldSid = 0; - PSECURITY_DESCRIPTOR SecurityDescriptor = 0; - PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0; - EXPLICIT_ACCESSW AccessEntry; - ACCESS_MASK AccessRights; - PACL Dacl; - BOOL DaclPresent, DaclDefaulted; - DWORD Size; - DWORD LastError; - NTSTATUS Result; - - /* get the Everyone (World) SID */ - Size = SECURITY_MAX_SID_SIZE; - WorldSid = MemAlloc(Size); - if (0 == WorldSid) - { - Result = STATUS_INSUFFICIENT_RESOURCES; - goto exit; - } - if (!CreateWellKnownSid(WinWorldSid, 0, WorldSid, &Size)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - /* get the service security descriptor DACL */ - Size = 0; - if (!QueryServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size)) - { - LastError = GetLastError(); - if (ERROR_INSUFFICIENT_BUFFER != LastError) - { - Result = FspNtStatusFromWin32(LastError); - goto exit; - } - } - SecurityDescriptor = MemAlloc(Size); - if (0 == SecurityDescriptor) - { - Result = STATUS_INSUFFICIENT_RESOURCES; - goto exit; - } - if (!QueryServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - /* extract the DACL */ - if (!GetSecurityDescriptorDacl(SecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - /* prepare an EXPLICIT_ACCESS for the SERVICE_START right for Everyone */ - AccessEntry.grfAccessPermissions = SERVICE_START; - AccessEntry.grfAccessMode = GRANT_ACCESS; - AccessEntry.grfInheritance = NO_INHERITANCE; - AccessEntry.Trustee.pMultipleTrustee = 0; - AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID; - AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - AccessEntry.Trustee.ptstrName = WorldSid; - - /* get the effective rights for Everyone */ - AccessRights = 0; - if (DaclPresent && 0 != Dacl) - { - LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights); - if (0 != LastError) - { - Result = FspNtStatusFromWin32(LastError); - goto exit; - } - } - - /* do we have the required access rights? */ - if (AccessEntry.grfAccessPermissions != (AccessRights & AccessEntry.grfAccessPermissions)) - { - /* create a new security descriptor with the new access */ - LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor, - &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; - -exit: - LocalFree(NewSecurityDescriptor); - MemFree(SecurityDescriptor); - MemFree(WorldSid); - - return Result; -} - -NTSTATUS FspFileSystemRegister(VOID) -{ - extern HINSTANCE DllInstance; - PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; - WCHAR DriverPath[MAX_PATH]; - DWORD Size; - SC_HANDLE ScmHandle = 0; - SC_HANDLE SvcHandle = 0; - PVOID VersionInfo = 0; - SERVICE_DESCRIPTION ServiceDescription; - NTSTATUS Result; - - if (0 == GetModuleFileNameW(DllInstance, DriverPath, MAX_PATH)) - return FspNtStatusFromWin32(GetLastError()); - - Size = lstrlenW(DriverPath); - if (4 < Size && - (L'.' == DriverPath[Size - 4]) && - (L'D' == DriverPath[Size - 3] || L'd' == DriverPath[Size - 3]) && - (L'L' == DriverPath[Size - 2] || L'l' == DriverPath[Size - 2]) && - (L'L' == DriverPath[Size - 1] || L'l' == DriverPath[Size - 1]) && - (L'\0' == DriverPath[Size])) - { - DriverPath[Size - 3] = L's'; - DriverPath[Size - 2] = L'y'; - DriverPath[Size - 1] = L's'; - } - else - /* should not happen! */ - return STATUS_NO_SUCH_DEVICE; - - ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_CREATE_SERVICE); - if (0 == ScmHandle) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_CHANGE_CONFIG | READ_CONTROL | WRITE_DAC); - if (0 != SvcHandle) - { - if (!ChangeServiceConfigW(SvcHandle, - SERVICE_FILE_SYSTEM_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath, - 0, 0, 0, 0, 0, DriverName)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - } - else - { - SvcHandle = CreateServiceW(ScmHandle, DriverName, DriverName, - SERVICE_CHANGE_CONFIG | READ_CONTROL | WRITE_DAC, - SERVICE_FILE_SYSTEM_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath, - 0, 0, 0, 0, 0); - if (0 == SvcHandle) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - } - - Size = GetFileVersionInfoSizeW(DriverPath, &Size/*dummy*/); - if (0 < Size) - { - VersionInfo = MemAlloc(Size); - if (0 != VersionInfo && - GetFileVersionInfoW(DriverPath, 0, Size, VersionInfo) && - VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription", - &ServiceDescription.lpDescription, &Size)) - { - ChangeServiceConfig2W(SvcHandle, SERVICE_CONFIG_DESCRIPTION, &ServiceDescription); - } - } - - Result = FspFileSystemFixServiceSecurity(SvcHandle); - if (!NT_SUCCESS(Result)) - goto exit; - - Result = STATUS_SUCCESS; - -exit: - MemFree(VersionInfo); - if (0 != SvcHandle) - CloseServiceHandle(SvcHandle); - if (0 != ScmHandle) - CloseServiceHandle(ScmHandle); - - return Result; -} - -NTSTATUS FspFileSystemUnregister(VOID) -{ - PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; - SC_HANDLE ScmHandle = 0; - SC_HANDLE SvcHandle = 0; - DWORD LastError; - NTSTATUS Result; - - ScmHandle = OpenSCManagerW(0, 0, 0); - if (0 == ScmHandle) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - SvcHandle = OpenServiceW(ScmHandle, DriverName, DELETE); - if (0 == SvcHandle) - { - LastError = GetLastError(); - if (ERROR_SERVICE_DOES_NOT_EXIST != LastError) - Result = FspNtStatusFromWin32(LastError); - else - Result = STATUS_SUCCESS; - goto exit; - } - - if (!DeleteService(SvcHandle)) - { - LastError = GetLastError(); - if (ERROR_SERVICE_MARKED_FOR_DELETE != LastError) - Result = FspNtStatusFromWin32(LastError); - else - Result = STATUS_SUCCESS; - goto exit; - } - - Result = STATUS_SUCCESS; - -exit: - if (0 != SvcHandle) - CloseServiceHandle(SvcHandle); - if (0 != ScmHandle) - CloseServiceHandle(ScmHandle); - - return Result; -} diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c index 58d9b944..885a4101 100644 --- a/src/dll/fsctl.c +++ b/src/dll/fsctl.c @@ -16,72 +16,13 @@ */ #include +#include #define GLOBALROOT L"\\\\?\\GLOBALROOT" #define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX #define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR)) -NTSTATUS FspFsctlStartService(VOID) -{ - PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; - SC_HANDLE ScmHandle = 0; - SC_HANDLE SvcHandle = 0; - SERVICE_STATUS ServiceStatus; - DWORD LastError; - NTSTATUS Result; - - ScmHandle = OpenSCManagerW(0, 0, 0); - if (0 == ScmHandle) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_QUERY_STATUS | SERVICE_START); - if (0 == SvcHandle) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - if (!StartServiceW(SvcHandle, 0, 0)) - { - LastError = GetLastError(); - if (ERROR_SERVICE_ALREADY_RUNNING != LastError) - Result = FspNtStatusFromWin32(LastError); - else - Result = STATUS_SUCCESS; - goto exit; - } - - /* Poll until the service is running! Yes, that's the best we can do! */ - Result = STATUS_DRIVER_UNABLE_TO_LOAD; - for (DWORD Timeout = 500, N = 20, I = 0; N > I; I++) - /* wait up to 500ms * 20 = 10000ms = 10s */ - { - if (!QueryServiceStatus(SvcHandle, &ServiceStatus)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - if (SERVICE_RUNNING == ServiceStatus.dwCurrentState) - { - Result = STATUS_SUCCESS; - break; - } - - Sleep(Timeout); - } - -exit: - if (0 != SvcHandle) - CloseServiceHandle(SvcHandle); - if (0 != ScmHandle) - CloseServiceHandle(ScmHandle); - - return Result; -} +static NTSTATUS FspFsctlStartService(VOID); FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath, const FSP_FSCTL_VOLUME_PARAMS *VolumeParams, @@ -251,3 +192,316 @@ exit: return Result; } + +static NTSTATUS FspFsctlStartService(VOID) +{ + PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; + SC_HANDLE ScmHandle = 0; + SC_HANDLE SvcHandle = 0; + SERVICE_STATUS ServiceStatus; + DWORD LastError; + NTSTATUS Result; + + ScmHandle = OpenSCManagerW(0, 0, 0); + if (0 == ScmHandle) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_QUERY_STATUS | SERVICE_START); + if (0 == SvcHandle) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + if (!StartServiceW(SvcHandle, 0, 0)) + { + LastError = GetLastError(); + if (ERROR_SERVICE_ALREADY_RUNNING != LastError) + Result = FspNtStatusFromWin32(LastError); + else + Result = STATUS_SUCCESS; + goto exit; + } + + /* Poll until the service is running! Yes, that's the best we can do! */ + Result = STATUS_DRIVER_UNABLE_TO_LOAD; + for (DWORD Timeout = 500, N = 20, I = 0; N > I; I++) + /* wait up to 500ms * 20 = 10000ms = 10s */ + { + if (!QueryServiceStatus(SvcHandle, &ServiceStatus)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + if (SERVICE_RUNNING == ServiceStatus.dwCurrentState) + { + Result = STATUS_SUCCESS; + break; + } + + Sleep(Timeout); + } + +exit: + if (0 != SvcHandle) + CloseServiceHandle(SvcHandle); + if (0 != ScmHandle) + CloseServiceHandle(ScmHandle); + + return Result; +} + +static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle) +{ + /* + * This function adds an ACE that allows Everyone to start a service. + */ + + PSID WorldSid = 0; + PSECURITY_DESCRIPTOR SecurityDescriptor = 0; + PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0; + EXPLICIT_ACCESSW AccessEntry; + ACCESS_MASK AccessRights; + PACL Dacl; + BOOL DaclPresent, DaclDefaulted; + DWORD Size; + DWORD LastError; + NTSTATUS Result; + + /* get the Everyone (World) SID */ + Size = SECURITY_MAX_SID_SIZE; + WorldSid = MemAlloc(Size); + if (0 == WorldSid) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + if (!CreateWellKnownSid(WinWorldSid, 0, WorldSid, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + /* get the service security descriptor DACL */ + Size = 0; + if (!QueryServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size)) + { + LastError = GetLastError(); + if (ERROR_INSUFFICIENT_BUFFER != LastError) + { + Result = FspNtStatusFromWin32(LastError); + goto exit; + } + } + SecurityDescriptor = MemAlloc(Size); + if (0 == SecurityDescriptor) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + if (!QueryServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + /* extract the DACL */ + if (!GetSecurityDescriptorDacl(SecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + /* prepare an EXPLICIT_ACCESS for the SERVICE_QUERY_STATUS | SERVICE_START right for Everyone */ + AccessEntry.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_START; + AccessEntry.grfAccessMode = GRANT_ACCESS; + AccessEntry.grfInheritance = NO_INHERITANCE; + AccessEntry.Trustee.pMultipleTrustee = 0; + AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID; + AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + AccessEntry.Trustee.ptstrName = WorldSid; + + /* get the effective rights for Everyone */ + AccessRights = 0; + if (DaclPresent && 0 != Dacl) + { + LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights); + if (0 != LastError) + { + Result = FspNtStatusFromWin32(LastError); + goto exit; + } + } + + /* do we have the required access rights? */ + if (AccessEntry.grfAccessPermissions != (AccessRights & AccessEntry.grfAccessPermissions)) + { + /* create a new security descriptor with the new access */ + LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor, + &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; + +exit: + LocalFree(NewSecurityDescriptor); + MemFree(SecurityDescriptor); + MemFree(WorldSid); + + return Result; +} + +NTSTATUS FspFsctlRegister(VOID) +{ + extern HINSTANCE DllInstance; + PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; + WCHAR DriverPath[MAX_PATH]; + DWORD Size; + SC_HANDLE ScmHandle = 0; + SC_HANDLE SvcHandle = 0; + PVOID VersionInfo = 0; + SERVICE_DESCRIPTION ServiceDescription; + NTSTATUS Result; + + if (0 == GetModuleFileNameW(DllInstance, DriverPath, MAX_PATH)) + return FspNtStatusFromWin32(GetLastError()); + + Size = lstrlenW(DriverPath); + if (4 < Size && + (L'.' == DriverPath[Size - 4]) && + (L'D' == DriverPath[Size - 3] || L'd' == DriverPath[Size - 3]) && + (L'L' == DriverPath[Size - 2] || L'l' == DriverPath[Size - 2]) && + (L'L' == DriverPath[Size - 1] || L'l' == DriverPath[Size - 1]) && + (L'\0' == DriverPath[Size])) + { + DriverPath[Size - 3] = L's'; + DriverPath[Size - 2] = L'y'; + DriverPath[Size - 1] = L's'; + } + else + /* should not happen! */ + return STATUS_NO_SUCH_DEVICE; + + ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_CREATE_SERVICE); + if (0 == ScmHandle) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_CHANGE_CONFIG | READ_CONTROL | WRITE_DAC); + if (0 != SvcHandle) + { + if (!ChangeServiceConfigW(SvcHandle, + SERVICE_FILE_SYSTEM_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath, + 0, 0, 0, 0, 0, DriverName)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + } + else + { + SvcHandle = CreateServiceW(ScmHandle, DriverName, DriverName, + SERVICE_CHANGE_CONFIG | READ_CONTROL | WRITE_DAC, + SERVICE_FILE_SYSTEM_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath, + 0, 0, 0, 0, 0); + if (0 == SvcHandle) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + } + + Size = GetFileVersionInfoSizeW(DriverPath, &Size/*dummy*/); + if (0 < Size) + { + VersionInfo = MemAlloc(Size); + if (0 != VersionInfo && + GetFileVersionInfoW(DriverPath, 0, Size, VersionInfo) && + VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription", + &ServiceDescription.lpDescription, &Size)) + { + ChangeServiceConfig2W(SvcHandle, SERVICE_CONFIG_DESCRIPTION, &ServiceDescription); + } + } + + Result = FspFsctlFixServiceSecurity(SvcHandle); + if (!NT_SUCCESS(Result)) + goto exit; + + Result = STATUS_SUCCESS; + +exit: + MemFree(VersionInfo); + if (0 != SvcHandle) + CloseServiceHandle(SvcHandle); + if (0 != ScmHandle) + CloseServiceHandle(ScmHandle); + + return Result; +} + +NTSTATUS FspFsctlUnregister(VOID) +{ + PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; + SC_HANDLE ScmHandle = 0; + SC_HANDLE SvcHandle = 0; + DWORD LastError; + NTSTATUS Result; + + ScmHandle = OpenSCManagerW(0, 0, 0); + if (0 == ScmHandle) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + SvcHandle = OpenServiceW(ScmHandle, DriverName, DELETE); + if (0 == SvcHandle) + { + LastError = GetLastError(); + if (ERROR_SERVICE_DOES_NOT_EXIST != LastError) + Result = FspNtStatusFromWin32(LastError); + else + Result = STATUS_SUCCESS; + goto exit; + } + + if (!DeleteService(SvcHandle)) + { + LastError = GetLastError(); + if (ERROR_SERVICE_MARKED_FOR_DELETE != LastError) + Result = FspNtStatusFromWin32(LastError); + else + Result = STATUS_SUCCESS; + goto exit; + } + + Result = STATUS_SUCCESS; + +exit: + if (0 != SvcHandle) + CloseServiceHandle(SvcHandle); + if (0 != ScmHandle) + CloseServiceHandle(ScmHandle); + + return Result; +} diff --git a/src/dll/library.c b/src/dll/library.c index 5529e2fe..4233120f 100644 --- a/src/dll/library.c +++ b/src/dll/library.c @@ -51,18 +51,15 @@ HRESULT WINAPI DllRegisterServer(VOID) { NTSTATUS Result; - Result = FspFileSystemRegister(); - FspDebugLog("FspFileSystemRegister = %lx\n", Result); + Result = FspFsctlRegister(); + FspDebugLog("FspFsctlRegister = %lx\n", Result); if (!NT_SUCCESS(Result)) goto exit; Result = FspNpRegister(); FspDebugLog("FspNpRegister = %lx\n", Result); if (!NT_SUCCESS(Result)) - { - FspFileSystemUnregister(); goto exit; - } exit: return NT_SUCCESS(Result) ? S_OK : 0x80040201/*SELFREG_E_CLASS*/; @@ -77,10 +74,11 @@ HRESULT WINAPI DllUnregisterServer(VOID) if (!NT_SUCCESS(Result)) goto exit; - Result = FspFileSystemUnregister(); - FspDebugLog("FspFileSystemUnregister = %lx\n", Result); + Result = FspFsctlUnregister(); + FspDebugLog("FspFsctlUnregister = %lx\n", Result); if (!NT_SUCCESS(Result)) { + /* roll back network provider unregistration if possible */ FspNpRegister(); goto exit; } diff --git a/src/dll/library.h b/src/dll/library.h index b655180f..40aa6c12 100644 --- a/src/dll/library.h +++ b/src/dll/library.h @@ -105,8 +105,9 @@ BOOLEAN RemoveEntryList(PLIST_ENTRY Entry) VOID FspFileSystemInitialize(VOID); VOID FspFileSystemFinalize(VOID); -NTSTATUS FspFileSystemRegister(VOID); -NTSTATUS FspFileSystemUnregister(VOID); + +NTSTATUS FspFsctlRegister(VOID); +NTSTATUS FspFsctlUnregister(VOID); NTSTATUS FspNpRegister(VOID); NTSTATUS FspNpUnregister(VOID);