Index: base/system/services/rpcserver.c =================================================================== --- base/system/services/rpcserver.c (révision 56689) +++ base/system/services/rpcserver.c (copie de travail) @@ -4822,7 +4822,11 @@ PSERVICE_HANDLE hSvc; PSERVICE lpService = NULL; HKEY hServiceKey = NULL; + DWORD dwRequiredSize = 0; + DWORD dwType = 0; LPWSTR lpDescriptionW = NULL; + LPWSTR lpRebootMessageW = NULL; + LPWSTR lpFailureCommandW = NULL; DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n", hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); @@ -4902,14 +4906,123 @@ { lpServiceDescription->lpDescription = NULL; dwError = ERROR_SUCCESS; - goto done; } } - else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS) + else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) { - UNIMPLEMENTED; - dwError = ERROR_CALL_NOT_IMPLEMENTED; - goto done; + LPSTR lpStr; + LPSERVICE_FAILURE_ACTIONSA lpFailureActions = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer; + + /* + * Query value length + */ + dwRequiredSize = 0; + dwError = RegQueryValueExW(hServiceKey, + L"FailureActions", + NULL, + &dwType, + NULL, + &dwRequiredSize); + + if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA) + goto done; + + if (dwType != REG_BINARY) + { + dwError = ERROR_UNSUPPORTED_TYPE; + goto done; + } + + dwRequiredSize = max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize); + + dwError = ScmReadString(hServiceKey, + L"FailureCommand", + &lpFailureCommandW); + + dwError = ScmReadString(hServiceKey, + L"RebootMessage", + &lpRebootMessageW); + + if (lpRebootMessageW) + dwRequiredSize += (wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR); + + if (lpFailureCommandW) + dwRequiredSize += (wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR); + + if (cbBufSize < dwRequiredSize) + { + *pcbBytesNeeded = dwRequiredSize; + dwError = ERROR_INSUFFICIENT_BUFFER; + goto done; + } + + /* + * Now we can fill the buffer + */ + dwError = RegQueryValueExW(hServiceKey, + L"FailureActions", + NULL, + NULL, + (LPBYTE)lpFailureActions, + &dwRequiredSize); + + if (dwError != ERROR_SUCCESS) + goto done; + + // We hope that dwRequiredSize_new == dwRequiredSize_before... + if ( (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA)) || + (dwRequiredSize > cbBufSize) ) + { + dwError = ERROR_BUFFER_OVERFLOW; + goto done; + } + + if (dwError == ERROR_SUCCESS) + { + lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - FIELD_OFFSET(SERVICE_FAILURE_ACTIONSA, lpsaActions)) / sizeof(SC_ACTION)); + lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(lpFailureActions + 1) : NULL); + lpStr = (LPSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION)); + } + else + { + lpFailureActions->dwResetPeriod = 0 ; + lpFailureActions->cActions = 0 ; + lpFailureActions->lpsaActions = NULL; + lpStr = (LPSTR)(lpFailureActions + 1); + } + + lpFailureActions->lpRebootMsg = NULL; + lpFailureActions->lpCommand = NULL; + + if (lpRebootMessageW) + { + WideCharToMultiByte(CP_ACP, + 0, + lpRebootMessageW, + -1, + lpStr, + wcslen(lpRebootMessageW), + NULL, + NULL); + lpFailureActions->lpRebootMsg = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); + lpStr += strlen(lpStr) + 1; + } + + if (lpFailureCommandW) + { + WideCharToMultiByte(CP_ACP, + 0, + lpFailureCommandW, + -1, + lpStr, + wcslen(lpFailureCommandW), + NULL, + NULL); + lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); + // lpStr += strlen(lpStr) + 1; + } + + dwError = STATUS_SUCCESS; } done: @@ -4919,10 +5032,16 @@ if (lpDescriptionW != NULL) HeapFree(GetProcessHeap(), 0, lpDescriptionW); + if (lpRebootMessageW != NULL) + HeapFree(GetProcessHeap(), 0, lpRebootMessageW); + + if (lpFailureCommandW != NULL) + HeapFree(GetProcessHeap(), 0, lpFailureCommandW); + if (hServiceKey != NULL) RegCloseKey(hServiceKey); - DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError); + DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError); return dwError; } @@ -4940,10 +5059,11 @@ PSERVICE_HANDLE hSvc; PSERVICE lpService = NULL; HKEY hServiceKey = NULL; - DWORD dwRequiredSize; + DWORD dwRequiredSize = 0; + DWORD dwType = 0; LPWSTR lpDescription = NULL; + LPWSTR lpRebootMessage = NULL; LPWSTR lpFailureCommand = NULL; - LPWSTR lpRebootMessage = NULL; DPRINT("RQueryServiceConfig2W() called\n"); @@ -5021,8 +5141,28 @@ LPWSTR lpStr; LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer; - UNIMPLEMENTED; + /* + * Query value length + */ + dwRequiredSize = 0; + dwError = RegQueryValueExW(hServiceKey, + L"FailureActions", + NULL, + &dwType, + NULL, + &dwRequiredSize); + if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA) + goto done; + + if (dwType != REG_BINARY) + { + dwError = ERROR_UNSUPPORTED_TYPE; + goto done; + } + + dwRequiredSize = max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize); + dwError = ScmReadString(hServiceKey, L"FailureCommand", &lpFailureCommand); @@ -5031,14 +5171,12 @@ L"RebootMessage", &lpRebootMessage); - dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); + if (lpRebootMessage) + dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR); if (lpFailureCommand) dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR); - if (lpRebootMessage) - dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR); - if (cbBufSize < dwRequiredSize) { *pcbBytesNeeded = dwRequiredSize; @@ -5046,28 +5184,59 @@ goto done; } - lpFailureActions->cActions = 0; - lpFailureActions->dwResetPeriod = 0; - lpFailureActions->lpCommand = NULL; + /* + * Now we can fill the buffer + */ + dwError = RegQueryValueExW(hServiceKey, + L"FailureActions", + NULL, + NULL, + (LPBYTE)lpFailureActions, + &dwRequiredSize); + + if (dwError != ERROR_SUCCESS) + goto done; + + // We hope that dwRequiredSize_new == dwRequiredSize_before... + if ( (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW)) || + (dwRequiredSize > cbBufSize) ) + { + dwError = ERROR_BUFFER_OVERFLOW; + goto done; + } + + if (dwError == ERROR_SUCCESS) + { + lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - FIELD_OFFSET(SERVICE_FAILURE_ACTIONSW, lpsaActions)) / sizeof(SC_ACTION)); + lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(lpFailureActions + 1) : NULL); + lpStr = (LPWSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION)); + } + else + { + lpFailureActions->dwResetPeriod = 0 ; + lpFailureActions->cActions = 0 ; + lpFailureActions->lpsaActions = NULL; + lpStr = (LPWSTR)(lpFailureActions + 1); + } + lpFailureActions->lpRebootMsg = NULL; - lpFailureActions->lpsaActions = NULL; + lpFailureActions->lpCommand = NULL; - lpStr = (LPWSTR)(lpFailureActions + 1); if (lpRebootMessage) { wcscpy(lpStr, lpRebootMessage); - lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpRebootMessage); - lpStr += wcslen(lpRebootMessage) + 1; + lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); + lpStr += wcslen(lpStr) + 1; } if (lpFailureCommand) { wcscpy(lpStr, lpFailureCommand); - lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureCommand); - lpStr += wcslen(lpRebootMessage) + 1; + lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); + // lpStr += wcslen(lpStr) + 1; } + dwError = STATUS_SUCCESS; - goto done; } done: