diff --git a/reactos/base/system/services/rpcserver.c b/reactos/base/system/services/rpcserver.c index 110e55d2fa8..7fc7222c9f7 100644 --- a/reactos/base/system/services/rpcserver.c +++ b/reactos/base/system/services/rpcserver.c @@ -4712,9 +4712,6 @@ Done: } -// -// WARNING: This function is untested -// /* Function 36 */ DWORD RChangeServiceConfig2A( SC_RPC_HANDLE hService, @@ -4731,48 +4728,57 @@ DWORD RChangeServiceConfig2A( if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) { - LPSERVICE_DESCRIPTIONW lpServiceDescriptonW; - //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA; + LPSERVICE_DESCRIPTIONW lpServiceDescriptionW; + //LPSERVICE_DESCRIPTIONA lpServiceDescriptionA; - //lpServiceDescriptonA = Info.psd; + //lpServiceDescriptionA = Info.psd; - ///if (lpServiceDescriptonA && - ///lpServiceDescriptonA->lpDescription) + ///if (lpServiceDescriptionA && + ///lpServiceDescriptionA->lpDescription) ///{ dwLength = (DWORD)((strlen(Info.lpDescription) + 1) * sizeof(WCHAR)); - lpServiceDescriptonW = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - dwLength + sizeof(SERVICE_DESCRIPTIONW)); - if (!lpServiceDescriptonW) + lpServiceDescriptionW = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwLength + sizeof(SERVICE_DESCRIPTIONW)); + if (!lpServiceDescriptionW) { return ERROR_NOT_ENOUGH_MEMORY; } - lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1); + lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1); MultiByteToWideChar(CP_ACP, 0, Info.lpDescription, -1, - lpServiceDescriptonW->lpDescription, + lpServiceDescriptionW->lpDescription, dwLength); - ptr = lpServiceDescriptonW; - InfoW.psd = lpServiceDescriptonW; + ptr = lpServiceDescriptionW; + InfoW.psd = lpServiceDescriptionW; ///} } else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) { LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW; LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA; - DWORD dwRebootLen = 0; + DWORD dwRebootLen = 0; DWORD dwCommandLen = 0; + DWORD dwActionArrayLen = 0; + LPWSTR lpStr = NULL; lpServiceFailureActionsA = Info.psfa; if (lpServiceFailureActionsA) { + /* + * The following code is inspired by the + * SERVICE_CONFIG_FAILURE_ACTIONS case of + * the RQueryServiceConfig2W function. + */ + + /* Retrieve the needed length for the two data strings */ if (lpServiceFailureActionsA->lpRebootMsg) { dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR)); @@ -4781,8 +4787,22 @@ DWORD RChangeServiceConfig2A( { dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR)); } - dwLength = dwRebootLen + dwCommandLen + sizeof(SERVICE_FAILURE_ACTIONSW); + /* + * Retrieve the size of the lpsaActions array if needed. + * We will copy the lpsaActions array only if there is at + * least one action AND that the original array is valid. + */ + if (lpServiceFailureActionsA->cActions > 0 && lpServiceFailureActionsA->lpsaActions) + { + dwActionArrayLen = lpServiceFailureActionsA->cActions * sizeof(SC_ACTION); + } + + /* Compute the total length for the UNICODE structure, including data */ + dwLength = sizeof(SERVICE_FAILURE_ACTIONSW) + + dwActionArrayLen + dwRebootLen + dwCommandLen; + + /* Allocate the structure */ lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); @@ -4791,22 +4811,56 @@ DWORD RChangeServiceConfig2A( return ERROR_NOT_ENOUGH_MEMORY; } - lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; + /* Copy the members */ lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod; - CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION)); + lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; - if (lpServiceFailureActionsA->lpRebootMsg) + /* Copy the lpsaActions array if needed */ + if (dwActionArrayLen > 0) { + /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */ + lpServiceFailureActionsW->lpsaActions = (LPSC_ACTION)((ULONG_PTR)(lpServiceFailureActionsW + 1)); + + /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */ + RtlCopyMemory(lpServiceFailureActionsW->lpsaActions, + lpServiceFailureActionsA->lpsaActions, + dwActionArrayLen); + } + else + { + /* No lpsaActions array */ + lpServiceFailureActionsW->lpsaActions = NULL; + } + /* The data strings are stored just after the lpsaActions array */ + lpStr = (LPWSTR)((ULONG_PTR)(lpServiceFailureActionsW + 1) + dwActionArrayLen); + + /* + * Convert the data strings to UNICODE + */ + + lpServiceFailureActionsW->lpRebootMsg = NULL; + lpServiceFailureActionsW->lpCommand = NULL; + + if (dwRebootLen) + { + /* lpRebootMsg points just after the lpsaActions array */ + lpServiceFailureActionsW->lpRebootMsg = lpStr; + MultiByteToWideChar(CP_ACP, 0, lpServiceFailureActionsA->lpRebootMsg, -1, lpServiceFailureActionsW->lpRebootMsg, dwRebootLen); + + lpStr += dwRebootLen / sizeof(WCHAR); } - if (lpServiceFailureActionsA->lpCommand) + if (dwCommandLen) { + /* lpRebootMsg points just after the lpRebootMsg data string */ + lpServiceFailureActionsW->lpCommand = lpStr; + MultiByteToWideChar(CP_ACP, 0, lpServiceFailureActionsA->lpCommand, @@ -4815,7 +4869,9 @@ DWORD RChangeServiceConfig2A( dwCommandLen); } + /* Set the pointers */ ptr = lpServiceFailureActionsW; + InfoW.psfa = lpServiceFailureActionsW; } }