Process Hacker
svcapi.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * server API
4  *
5  * Copyright (C) 2011-2015 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <phapp.h>
24 #include <secedit.h>
25 #include <phsvc.h>
26 #include <phplug.h>
27 #include <extmgri.h>
28 #include <symprv.h>
29 #include <accctrl.h>
30 
31 typedef struct _PHSVCP_CAPTURED_RUNAS_SERVICE_PARAMETERS
32 {
33  PPH_STRING UserName;
34  PPH_STRING Password;
35  PPH_STRING CurrentDirectory;
36  PPH_STRING CommandLine;
37  PPH_STRING FileName;
38  PPH_STRING DesktopName;
41 
43 {
63 };
65 
67  VOID
68  )
69 {
70  return STATUS_SUCCESS;
71 }
72 
74  _In_ PPHSVC_CLIENT Client,
75  _Inout_ PPHSVC_API_PAYLOAD Payload,
76  _Out_ PHANDLE ReplyPortHandle
77  )
78 {
79  NTSTATUS status;
80 
81  if (
82  Payload->ApiNumber == 0 ||
83  (ULONG)Payload->ApiNumber >= (ULONG)PhSvcMaximumApiNumber ||
84  !PhSvcApiCallTable[Payload->ApiNumber - 1]
85  )
86  {
87  Payload->ReturnStatus = STATUS_INVALID_SYSTEM_SERVICE;
88  *ReplyPortHandle = Client->PortHandle;
89  return;
90  }
91 
92  status = PhSvcApiCallTable[Payload->ApiNumber - 1](Client, Payload);
93  Payload->ReturnStatus = status;
94 
95  *ReplyPortHandle = Client->PortHandle;
96 }
97 
99  _In_ PPH_RELATIVE_STRINGREF String,
100  _In_ ULONG Alignment
101  )
102 {
104  PVOID address;
105 
106  address = (PCHAR)client->ClientViewBase + String->Offset;
107 
108  if ((ULONG_PTR)address + String->Length < (ULONG_PTR)address ||
109  (ULONG_PTR)address < (ULONG_PTR)client->ClientViewBase ||
110  (ULONG_PTR)address + String->Length > (ULONG_PTR)client->ClientViewLimit)
111  {
112  return NULL;
113  }
114 
115  if ((ULONG_PTR)address & (Alignment - 1))
116  {
117  return NULL;
118  }
119 
120  return address;
121 }
122 
124  _In_ PPH_RELATIVE_STRINGREF String,
125  _In_ ULONG Alignment,
126  _In_ BOOLEAN AllowNull,
127  _Out_ PVOID *Pointer
128  )
129 {
130  PVOID address;
131 
132  if (String->Offset != 0)
133  {
134  address = PhSvcValidateString(String, Alignment);
135 
136  if (!address)
137  return STATUS_ACCESS_VIOLATION;
138 
139  *Pointer = address;
140  }
141  else
142  {
143  if (!AllowNull)
144  return STATUS_ACCESS_VIOLATION;
145 
146  *Pointer = NULL;
147  }
148 
149  return STATUS_SUCCESS;
150 }
151 
153  _In_ PPH_RELATIVE_STRINGREF String,
154  _In_ BOOLEAN AllowNull,
155  _Out_ PVOID *CapturedBuffer
156  )
157 {
158  PVOID address;
159  PVOID buffer;
160 
161  if (String->Offset != 0)
162  {
163  address = PhSvcValidateString(String, 1);
164 
165  if (!address)
166  return STATUS_ACCESS_VIOLATION;
167 
168  buffer = PhAllocateSafe(String->Length);
169 
170  if (!buffer)
171  return STATUS_NO_MEMORY;
172 
173  memcpy(buffer, address, String->Length);
174  *CapturedBuffer = buffer;
175  }
176  else
177  {
178  if (!AllowNull)
179  return STATUS_ACCESS_VIOLATION;
180 
181  *CapturedBuffer = NULL;
182  }
183 
184  return STATUS_SUCCESS;
185 }
186 
188  _In_ PPH_RELATIVE_STRINGREF String,
189  _In_ BOOLEAN AllowNull,
190  _Out_ PPH_STRING *CapturedString
191  )
192 {
193  PVOID address;
194 
195  if (String->Length & 1)
196  return STATUS_INVALID_BUFFER_SIZE;
197  if (String->Length > 0xfffe)
198  return STATUS_INVALID_BUFFER_SIZE;
199 
200  if (String->Offset != 0)
201  {
202  address = PhSvcValidateString(String, sizeof(WCHAR));
203 
204  if (!address)
205  return STATUS_ACCESS_VIOLATION;
206 
207  if (String->Length != 0)
208  *CapturedString = PhCreateStringEx(address, String->Length);
209  else
210  *CapturedString = PhReferenceEmptyString();
211  }
212  else
213  {
214  if (!AllowNull)
215  return STATUS_ACCESS_VIOLATION;
216 
217  *CapturedString = NULL;
218  }
219 
220  return STATUS_SUCCESS;
221 }
222 
224  _In_ PPH_RELATIVE_STRINGREF String,
225  _In_ BOOLEAN AllowNull,
226  _Out_ PSID *CapturedSid
227  )
228 {
229  NTSTATUS status;
230  PSID sid;
231 
232  if (!NT_SUCCESS(status = PhSvcCaptureBuffer(String, AllowNull, &sid)))
233  return status;
234 
235  if (sid)
236  {
237  if (String->Length < FIELD_OFFSET(struct _SID, IdentifierAuthority) ||
238  String->Length < RtlLengthRequiredSid(((struct _SID *)sid)->SubAuthorityCount) ||
239  !RtlValidSid(sid))
240  {
241  PhFree(sid);
242  return STATUS_INVALID_SID;
243  }
244 
245  *CapturedSid = sid;
246  }
247  else
248  {
249  *CapturedSid = NULL;
250  }
251 
252  return STATUS_SUCCESS;
253 }
254 
256  _In_ PPH_RELATIVE_STRINGREF String,
257  _In_ BOOLEAN AllowNull,
258  _In_ SECURITY_INFORMATION RequiredInformation,
259  _Out_ PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor
260  )
261 {
262  NTSTATUS status;
263  PSECURITY_DESCRIPTOR securityDescriptor;
264  ULONG bufferSize;
265 
266  if (!NT_SUCCESS(status = PhSvcCaptureBuffer(String, AllowNull, &securityDescriptor)))
267  return status;
268 
269  if (securityDescriptor)
270  {
271  if (!RtlValidRelativeSecurityDescriptor(securityDescriptor, String->Length, RequiredInformation))
272  {
273  PhFree(securityDescriptor);
274  return STATUS_INVALID_SECURITY_DESCR;
275  }
276 
277  bufferSize = String->Length;
278  status = RtlSelfRelativeToAbsoluteSD2(securityDescriptor, &bufferSize);
279 
280  if (status == STATUS_BUFFER_TOO_SMALL)
281  {
282  PVOID newBuffer;
283 
284  newBuffer = PhAllocate(bufferSize);
285  memcpy(newBuffer, securityDescriptor, String->Length);
286  PhFree(securityDescriptor);
287  securityDescriptor = newBuffer;
288 
289  status = RtlSelfRelativeToAbsoluteSD2(securityDescriptor, &bufferSize);
290  }
291 
292  if (!NT_SUCCESS(status))
293  {
294  PhFree(securityDescriptor);
295  return status;
296  }
297 
298  *CapturedSecurityDescriptor = securityDescriptor;
299  }
300  else
301  {
302  *CapturedSecurityDescriptor = NULL;
303  }
304 
305  return STATUS_SUCCESS;
306 }
307 
309  _In_ PPHSVC_CLIENT Client,
310  _Inout_ PPHSVC_API_PAYLOAD Payload
311  )
312 {
313  return STATUS_NOT_IMPLEMENTED;
314 }
315 
316 NTSTATUS PhSvcApiPlugin(
317  _In_ PPHSVC_CLIENT Client,
318  _Inout_ PPHSVC_API_PAYLOAD Payload
319  )
320 {
321  NTSTATUS status;
322  PPH_STRING apiId;
323  PPH_PLUGIN plugin;
324  PH_STRINGREF pluginName;
325  PH_PLUGIN_PHSVC_REQUEST request;
326 
327  if (NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.Plugin.i.ApiId, FALSE, &apiId)))
328  {
329  if (PhPluginsEnabled &&
330  PhEmParseCompoundId(&apiId->sr, &pluginName, &request.SubId) &&
331  (plugin = PhFindPlugin2(&pluginName)))
332  {
333  request.ReturnStatus = STATUS_NOT_IMPLEMENTED;
334  request.InBuffer = Payload->u.Plugin.i.Data;
335  request.InLength = sizeof(Payload->u.Plugin.i.Data);
336  request.OutBuffer = Payload->u.Plugin.o.Data;
337  request.OutLength = sizeof(Payload->u.Plugin.o.Data);
338 
339  request.ProbeBuffer = PhSvcProbeBuffer;
342 
344  status = request.ReturnStatus;
345  }
346  else
347  {
348  status = STATUS_NOT_FOUND;
349  }
350 
351  PhDereferenceObject(apiId);
352  }
353 
354  return status;
355 }
356 
358  _In_ PPHSVC_CLIENT Client,
359  _Inout_ PPHSVC_API_PAYLOAD Payload,
360  _Out_ PPH_RUNAS_SERVICE_PARAMETERS Parameters,
361  _Out_ PPHSVCP_CAPTURED_RUNAS_SERVICE_PARAMETERS CapturedParameters
362  )
363 {
364  NTSTATUS status;
365 
366  memset(CapturedParameters, 0, sizeof(PHSVCP_CAPTURED_RUNAS_SERVICE_PARAMETERS));
367 
368  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ExecuteRunAsCommand.i.UserName, TRUE, &CapturedParameters->UserName)))
369  return status;
370  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ExecuteRunAsCommand.i.Password, TRUE, &CapturedParameters->Password)))
371  return status;
372  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ExecuteRunAsCommand.i.CurrentDirectory, TRUE, &CapturedParameters->CurrentDirectory)))
373  return status;
374  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ExecuteRunAsCommand.i.CommandLine, TRUE, &CapturedParameters->CommandLine)))
375  return status;
376  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ExecuteRunAsCommand.i.FileName, TRUE, &CapturedParameters->FileName)))
377  return status;
378  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ExecuteRunAsCommand.i.DesktopName, TRUE, &CapturedParameters->DesktopName)))
379  return status;
380  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ExecuteRunAsCommand.i.ServiceName, TRUE, &CapturedParameters->ServiceName)))
381  return status;
382 
383  Parameters->ProcessId = Payload->u.ExecuteRunAsCommand.i.ProcessId;
384  Parameters->UserName = PhGetString(CapturedParameters->UserName);
385  Parameters->Password = PhGetString(CapturedParameters->Password);
386  Parameters->LogonType = Payload->u.ExecuteRunAsCommand.i.LogonType;
387  Parameters->SessionId = Payload->u.ExecuteRunAsCommand.i.SessionId;
388  Parameters->CurrentDirectory = PhGetString(CapturedParameters->CurrentDirectory);
389  Parameters->CommandLine = PhGetString(CapturedParameters->CommandLine);
390  Parameters->FileName = PhGetString(CapturedParameters->FileName);
391  Parameters->DesktopName = PhGetString(CapturedParameters->DesktopName);
392  Parameters->UseLinkedToken = Payload->u.ExecuteRunAsCommand.i.UseLinkedToken;
393  Parameters->ServiceName = PhGetString(CapturedParameters->ServiceName);
394 
395  return status;
396 }
397 
399  _In_ PPHSVCP_CAPTURED_RUNAS_SERVICE_PARAMETERS CapturedParameters
400  )
401 {
402  if (CapturedParameters->UserName)
403  PhDereferenceObject(CapturedParameters->UserName);
404 
405  if (CapturedParameters->Password)
406  {
407  RtlSecureZeroMemory(CapturedParameters->Password->Buffer, CapturedParameters->Password->Length);
408  PhDereferenceObject(CapturedParameters->Password);
409  }
410 
411  if (CapturedParameters->CurrentDirectory)
412  PhDereferenceObject(CapturedParameters->CurrentDirectory);
413  if (CapturedParameters->CommandLine)
414  PhDereferenceObject(CapturedParameters->CommandLine);
415  if (CapturedParameters->FileName)
416  PhDereferenceObject(CapturedParameters->FileName);
417  if (CapturedParameters->DesktopName)
418  PhDereferenceObject(CapturedParameters->DesktopName);
419  if (CapturedParameters->ServiceName)
420  PhDereferenceObject(CapturedParameters->ServiceName);
421 }
422 
424  _In_ PPH_RUNAS_SERVICE_PARAMETERS Parameters
425  )
426 {
427  if ((!Parameters->UserName || !Parameters->Password) && !Parameters->ProcessId)
428  return STATUS_INVALID_PARAMETER_MIX;
429  if (!Parameters->FileName && !Parameters->CommandLine)
430  return STATUS_INVALID_PARAMETER_MIX;
431  if (!Parameters->ServiceName)
432  return STATUS_INVALID_PARAMETER;
433 
434  return STATUS_SUCCESS;
435 }
436 
438  _In_ PPHSVC_CLIENT Client,
439  _Inout_ PPHSVC_API_PAYLOAD Payload
440  )
441 {
442  NTSTATUS status;
443  PH_RUNAS_SERVICE_PARAMETERS parameters;
444  PHSVCP_CAPTURED_RUNAS_SERVICE_PARAMETERS capturedParameters;
445 
446  if (NT_SUCCESS(status = PhSvcpCaptureRunAsServiceParameters(Client, Payload, &parameters, &capturedParameters)))
447  {
448  if (NT_SUCCESS(status = PhSvcpValidateRunAsServiceParameters(&parameters)))
449  {
450  status = PhExecuteRunAsCommand(&parameters);
451  }
452  }
453 
454  PhSvcpReleaseRunAsServiceParameters(&capturedParameters);
455 
456  return status;
457 }
458 
460  _In_ PPHSVC_CLIENT Client,
461  _Inout_ PPHSVC_API_PAYLOAD Payload
462  )
463 {
464  NTSTATUS status;
465  PPH_STRING name;
466 
467  if (NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.UnloadDriver.i.Name, TRUE, &name)))
468  {
469  status = PhUnloadDriver(Payload->u.UnloadDriver.i.BaseAddress, PhGetString(name));
470  PhClearReference(&name);
471  }
472 
473  return status;
474 }
475 
477  _In_ PPHSVC_CLIENT Client,
478  _Inout_ PPHSVC_API_PAYLOAD Payload
479  )
480 {
481  NTSTATUS status;
482  HANDLE processId;
483  HANDLE processHandle;
484 
485  processId = Payload->u.ControlProcess.i.ProcessId;
486 
487  switch (Payload->u.ControlProcess.i.Command)
488  {
490  if (NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_TERMINATE, processId)))
491  {
492  status = PhTerminateProcess(processHandle, 1); // see notes in PhUiTerminateProcesses
493  NtClose(processHandle);
494  }
495  break;
497  if (NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_SUSPEND_RESUME, processId)))
498  {
499  status = PhSuspendProcess(processHandle);
500  NtClose(processHandle);
501  }
502  break;
504  if (NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_SUSPEND_RESUME, processId)))
505  {
506  status = PhResumeProcess(processHandle);
507  NtClose(processHandle);
508  }
509  break;
511  if (NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_SET_INFORMATION, processId)))
512  {
513  PROCESS_PRIORITY_CLASS priorityClass;
514 
515  priorityClass.Foreground = FALSE;
516  priorityClass.PriorityClass = (UCHAR)Payload->u.ControlProcess.i.Argument;
517  status = NtSetInformationProcess(processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS));
518 
519  NtClose(processHandle);
520  }
521  break;
523  if (NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_SET_INFORMATION, processId)))
524  {
525  status = PhSetProcessIoPriority(processHandle, Payload->u.ControlProcess.i.Argument);
526  NtClose(processHandle);
527  }
528  break;
529  default:
530  status = STATUS_INVALID_PARAMETER;
531  break;
532  }
533 
534  return status;
535 }
536 
538  _In_ PPHSVC_CLIENT Client,
539  _Inout_ PPHSVC_API_PAYLOAD Payload
540  )
541 {
542  NTSTATUS status;
543  PPH_STRING serviceName;
544  SC_HANDLE serviceHandle;
545  SERVICE_STATUS serviceStatus;
546 
547  if (NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ControlService.i.ServiceName, FALSE, &serviceName)))
548  {
549  switch (Payload->u.ControlService.i.Command)
550  {
552  if (serviceHandle = PhOpenService(
553  serviceName->Buffer,
554  SERVICE_START
555  ))
556  {
557  if (!StartService(serviceHandle, 0, NULL))
559 
560  CloseServiceHandle(serviceHandle);
561  }
562  else
563  {
565  }
566  break;
568  if (serviceHandle = PhOpenService(
569  serviceName->Buffer,
570  SERVICE_PAUSE_CONTINUE
571  ))
572  {
573  if (!ControlService(serviceHandle, SERVICE_CONTROL_CONTINUE, &serviceStatus))
575 
576  CloseServiceHandle(serviceHandle);
577  }
578  else
579  {
581  }
582  break;
584  if (serviceHandle = PhOpenService(
585  serviceName->Buffer,
586  SERVICE_PAUSE_CONTINUE
587  ))
588  {
589  if (!ControlService(serviceHandle, SERVICE_CONTROL_PAUSE, &serviceStatus))
591 
592  CloseServiceHandle(serviceHandle);
593  }
594  else
595  {
597  }
598  break;
600  if (serviceHandle = PhOpenService(
601  serviceName->Buffer,
602  SERVICE_STOP
603  ))
604  {
605  if (!ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus))
607 
608  CloseServiceHandle(serviceHandle);
609  }
610  else
611  {
613  }
614  break;
616  if (serviceHandle = PhOpenService(
617  serviceName->Buffer,
618  DELETE
619  ))
620  {
621  if (!DeleteService(serviceHandle))
623 
624  CloseServiceHandle(serviceHandle);
625  }
626  else
627  {
629  }
630  break;
631  default:
632  status = STATUS_INVALID_PARAMETER;
633  break;
634  }
635 
636  PhDereferenceObject(serviceName);
637  }
638 
639  return status;
640 }
641 
643  _In_ PPHSVC_CLIENT Client,
644  _Inout_ PPHSVC_API_PAYLOAD Payload
645  )
646 {
647  NTSTATUS status;
648  PPH_STRING serviceName = NULL;
649  PPH_STRING displayName = NULL;
650  PPH_STRING binaryPathName = NULL;
651  PPH_STRING loadOrderGroup = NULL;
652  PPH_STRING dependencies = NULL;
653  PPH_STRING serviceStartName = NULL;
654  PPH_STRING password = NULL;
655  ULONG tagId = 0;
656  SC_HANDLE scManagerHandle;
657  SC_HANDLE serviceHandle;
658 
659  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateService.i.ServiceName, FALSE, &serviceName)))
660  goto CleanupExit;
661  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateService.i.DisplayName, TRUE, &displayName)))
662  goto CleanupExit;
663  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateService.i.BinaryPathName, TRUE, &binaryPathName)))
664  goto CleanupExit;
665  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateService.i.LoadOrderGroup, TRUE, &loadOrderGroup)))
666  goto CleanupExit;
667  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateService.i.Dependencies, TRUE, &dependencies)))
668  goto CleanupExit;
669  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateService.i.ServiceStartName, TRUE, &serviceStartName)))
670  goto CleanupExit;
671  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateService.i.Password, TRUE, &password)))
672  goto CleanupExit;
673 
674  if (scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE))
675  {
676  if (serviceHandle = CreateService(
677  scManagerHandle,
678  serviceName->Buffer,
679  PhGetString(displayName),
680  SERVICE_CHANGE_CONFIG,
681  Payload->u.CreateService.i.ServiceType,
682  Payload->u.CreateService.i.StartType,
683  Payload->u.CreateService.i.ErrorControl,
684  PhGetString(binaryPathName),
685  PhGetString(loadOrderGroup),
686  Payload->u.CreateService.i.TagIdSpecified ? &tagId : NULL,
687  PhGetString(dependencies),
688  PhGetString(serviceStartName),
689  PhGetString(password)
690  ))
691  {
692  Payload->u.CreateService.o.TagId = tagId;
693  CloseServiceHandle(serviceHandle);
694  }
695  else
696  {
698  }
699 
700  CloseServiceHandle(scManagerHandle);
701  }
702  else
703  {
705  }
706 
707 CleanupExit:
708  if (password)
709  {
710  RtlSecureZeroMemory(password->Buffer, password->Length);
711  PhDereferenceObject(password);
712  }
713 
714  PhClearReference(&serviceStartName);
715  PhClearReference(&dependencies);
716  PhClearReference(&loadOrderGroup);
717  PhClearReference(&binaryPathName);
718  PhClearReference(&displayName);
719  PhClearReference(&serviceName);
720 
721  return status;
722 }
723 
725  _In_ PPHSVC_CLIENT Client,
726  _Inout_ PPHSVC_API_PAYLOAD Payload
727  )
728 {
729  NTSTATUS status;
730  PPH_STRING serviceName = NULL;
731  PPH_STRING binaryPathName = NULL;
732  PPH_STRING loadOrderGroup = NULL;
733  PPH_STRING dependencies = NULL;
734  PPH_STRING serviceStartName = NULL;
735  PPH_STRING password = NULL;
736  PPH_STRING displayName = NULL;
737  ULONG tagId = 0;
738  SC_HANDLE serviceHandle;
739 
740  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig.i.ServiceName, FALSE, &serviceName)))
741  goto CleanupExit;
742  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig.i.BinaryPathName, TRUE, &binaryPathName)))
743  goto CleanupExit;
744  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig.i.LoadOrderGroup, TRUE, &loadOrderGroup)))
745  goto CleanupExit;
746  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig.i.Dependencies, TRUE, &dependencies)))
747  goto CleanupExit;
748  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig.i.ServiceStartName, TRUE, &serviceStartName)))
749  goto CleanupExit;
750  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig.i.Password, TRUE, &password)))
751  goto CleanupExit;
752  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig.i.DisplayName, TRUE, &displayName)))
753  goto CleanupExit;
754 
755  if (serviceHandle = PhOpenService(serviceName->Buffer, SERVICE_CHANGE_CONFIG))
756  {
757  if (ChangeServiceConfig(
758  serviceHandle,
759  Payload->u.ChangeServiceConfig.i.ServiceType,
760  Payload->u.ChangeServiceConfig.i.StartType,
761  Payload->u.ChangeServiceConfig.i.ErrorControl,
762  PhGetString(binaryPathName),
763  PhGetString(loadOrderGroup),
764  Payload->u.ChangeServiceConfig.i.TagIdSpecified ? &tagId : NULL,
765  PhGetString(dependencies),
766  PhGetString(serviceStartName),
767  PhGetString(password),
768  PhGetString(displayName)
769  ))
770  {
771  Payload->u.ChangeServiceConfig.o.TagId = tagId;
772  }
773  else
774  {
776  }
777 
778  CloseServiceHandle(serviceHandle);
779  }
780  else
781  {
783  }
784 
785 CleanupExit:
786  PhClearReference(&displayName);
787 
788  if (password)
789  {
790  RtlSecureZeroMemory(password->Buffer, password->Length);
791  PhDereferenceObject(password);
792  }
793 
794  PhClearReference(&serviceStartName);
795  PhClearReference(&dependencies);
796  PhClearReference(&loadOrderGroup);
797  PhClearReference(&binaryPathName);
798  PhClearReference(&serviceName);
799 
800  return status;
801 }
802 
804  _In_ PPH_RELATIVE_STRINGREF PackedData,
805  _In_ PVOID CapturedBuffer,
806  _In_ SIZE_T Length,
807  _Out_ PVOID *ValidatedBuffer
808  )
809 {
810  if (Length > PackedData->Length)
811  return STATUS_ACCESS_VIOLATION;
812 
813  *ValidatedBuffer = CapturedBuffer;
814 
815  return STATUS_SUCCESS;
816 }
817 
819  _In_ PPH_RELATIVE_STRINGREF PackedData,
820  _In_ PVOID CapturedBuffer,
821  _In_ PVOID *OffsetInBuffer,
822  _In_ SIZE_T Length,
823  _In_ ULONG Alignment,
824  _In_ BOOLEAN AllowNull
825  )
826 {
827  SIZE_T offset;
828 
829  offset = (SIZE_T)*OffsetInBuffer;
830 
831  if (offset == 0)
832  {
833  if (AllowNull)
834  return STATUS_SUCCESS;
835  else
836  return STATUS_ACCESS_VIOLATION;
837  }
838 
839  if (offset + Length < offset)
840  return STATUS_ACCESS_VIOLATION;
841  if (offset + Length > PackedData->Length)
842  return STATUS_ACCESS_VIOLATION;
843  if (offset & (Alignment - 1))
844  return STATUS_DATATYPE_MISALIGNMENT;
845 
846  *OffsetInBuffer = (PVOID)((ULONG_PTR)CapturedBuffer + offset);
847 
848  return STATUS_SUCCESS;
849 }
850 
852  _In_ PPH_RELATIVE_STRINGREF PackedData,
853  _In_ PVOID CapturedBuffer,
854  _In_ PVOID *OffsetInBuffer,
855  _In_ BOOLEAN Multi,
856  _In_ BOOLEAN AllowNull
857  )
858 {
859  SIZE_T offset;
860  PWCHAR start;
861  PWCHAR end;
862  PH_STRINGREF remainingPart;
863  PH_STRINGREF firstPart;
864 
865  offset = (SIZE_T)*OffsetInBuffer;
866 
867  if (offset == 0)
868  {
869  if (AllowNull)
870  return STATUS_SUCCESS;
871  else
872  return STATUS_ACCESS_VIOLATION;
873  }
874 
875  if (offset >= PackedData->Length)
876  return STATUS_ACCESS_VIOLATION;
877  if (offset & 1)
878  return STATUS_DATATYPE_MISALIGNMENT;
879 
880  start = (PWCHAR)((ULONG_PTR)CapturedBuffer + offset);
881  end = (PWCHAR)((ULONG_PTR)CapturedBuffer + (PackedData->Length & -2));
882  remainingPart.Buffer = start;
883  remainingPart.Length = (end - start) * sizeof(WCHAR);
884 
885  if (Multi)
886  {
887  SIZE_T validatedLength = 0;
888 
889  while (PhSplitStringRefAtChar(&remainingPart, 0, &firstPart, &remainingPart))
890  {
891  validatedLength += firstPart.Length + sizeof(WCHAR);
892 
893  if (firstPart.Length == 0)
894  {
895  *OffsetInBuffer = start;
896 
897  return STATUS_SUCCESS;
898  }
899  }
900  }
901  else
902  {
903  if (PhSplitStringRefAtChar(&remainingPart, 0, &firstPart, &remainingPart))
904  {
905  *OffsetInBuffer = start;
906 
907  return STATUS_SUCCESS;
908  }
909  }
910 
911  return STATUS_ACCESS_VIOLATION;
912 }
913 
915  _In_ PPHSVC_CLIENT Client,
916  _Inout_ PPHSVC_API_PAYLOAD Payload
917  )
918 {
919  NTSTATUS status;
920  PPH_STRING serviceName = NULL;
921  PVOID info = NULL;
922  SC_HANDLE serviceHandle = NULL;
923  PH_RELATIVE_STRINGREF packedData;
924  PVOID unpackedInfo = NULL;
925  ACCESS_MASK desiredAccess = SERVICE_CHANGE_CONFIG;
926 
927  if (!NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.ChangeServiceConfig2.i.ServiceName, FALSE, &serviceName)))
928  goto CleanupExit;
929  if (!NT_SUCCESS(status = PhSvcCaptureBuffer(&Payload->u.ChangeServiceConfig2.i.Info, FALSE, &info)))
930  goto CleanupExit;
931 
932  packedData = Payload->u.ChangeServiceConfig2.i.Info;
933 
934  switch (Payload->u.ChangeServiceConfig2.i.InfoLevel)
935  {
936  case SERVICE_CONFIG_FAILURE_ACTIONS:
937  {
938  LPSERVICE_FAILURE_ACTIONS failureActions;
939 
940  if (!NT_SUCCESS(status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_FAILURE_ACTIONS), &failureActions)))
941  goto CleanupExit;
942  if (!NT_SUCCESS(status = PhSvcpUnpackStringZ(&packedData, info, &failureActions->lpRebootMsg, FALSE, TRUE)))
943  goto CleanupExit;
944  if (!NT_SUCCESS(status = PhSvcpUnpackStringZ(&packedData, info, &failureActions->lpCommand, FALSE, TRUE)))
945  goto CleanupExit;
946  if (!NT_SUCCESS(status = PhSvcpUnpackBuffer(&packedData, info, &failureActions->lpsaActions, failureActions->cActions * sizeof(SC_ACTION), __alignof(SC_ACTION), TRUE)))
947  goto CleanupExit;
948 
949  if (failureActions->lpsaActions)
950  {
951  ULONG i;
952 
953  for (i = 0; i < failureActions->cActions; i++)
954  {
955  if (failureActions->lpsaActions[i].Type == SC_ACTION_RESTART)
956  {
957  desiredAccess |= SERVICE_START;
958  break;
959  }
960  }
961  }
962 
963  unpackedInfo = failureActions;
964  }
965  break;
966  case SERVICE_CONFIG_DELAYED_AUTO_START_INFO:
967  status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_DELAYED_AUTO_START_INFO), &unpackedInfo);
968  break;
969  case SERVICE_CONFIG_FAILURE_ACTIONS_FLAG:
970  status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_FAILURE_ACTIONS_FLAG), &unpackedInfo);
971  break;
972  case SERVICE_CONFIG_SERVICE_SID_INFO:
973  status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_SID_INFO), &unpackedInfo);
974  break;
975  case SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO:
976  {
977  LPSERVICE_REQUIRED_PRIVILEGES_INFO requiredPrivilegesInfo;
978 
979  if (!NT_SUCCESS(status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_REQUIRED_PRIVILEGES_INFO), &requiredPrivilegesInfo)))
980  goto CleanupExit;
981  if (!NT_SUCCESS(status = PhSvcpUnpackStringZ(&packedData, info, &requiredPrivilegesInfo->pmszRequiredPrivileges, TRUE, FALSE)))
982  goto CleanupExit;
983 
984  unpackedInfo = requiredPrivilegesInfo;
985  }
986  break;
987  case SERVICE_CONFIG_PRESHUTDOWN_INFO:
988  status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_PRESHUTDOWN_INFO), &unpackedInfo);
989  break;
990  case SERVICE_CONFIG_TRIGGER_INFO:
991  {
992  PSERVICE_TRIGGER_INFO triggerInfo;
993  ULONG i;
994  PSERVICE_TRIGGER trigger;
995  ULONG j;
996  PSERVICE_TRIGGER_SPECIFIC_DATA_ITEM dataItem;
997  ULONG alignment;
998 
999  if (!NT_SUCCESS(status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_TRIGGER_INFO), &triggerInfo)))
1000  goto CleanupExit;
1001  if (!NT_SUCCESS(status = PhSvcpUnpackBuffer(&packedData, info, &triggerInfo->pTriggers, triggerInfo->cTriggers * sizeof(SERVICE_TRIGGER), __alignof(SERVICE_TRIGGER), TRUE)))
1002  goto CleanupExit;
1003 
1004  if (triggerInfo->pTriggers)
1005  {
1006  for (i = 0; i < triggerInfo->cTriggers; i++)
1007  {
1008  trigger = &triggerInfo->pTriggers[i];
1009 
1010  if (!NT_SUCCESS(status = PhSvcpUnpackBuffer(&packedData, info, &trigger->pTriggerSubtype, sizeof(GUID), __alignof(GUID), TRUE)))
1011  goto CleanupExit;
1012  if (!NT_SUCCESS(status = PhSvcpUnpackBuffer(&packedData, info, &trigger->pDataItems, trigger->cDataItems * sizeof(SERVICE_TRIGGER_SPECIFIC_DATA_ITEM), __alignof(SERVICE_TRIGGER_SPECIFIC_DATA_ITEM), TRUE)))
1013  goto CleanupExit;
1014 
1015  if (trigger->pDataItems)
1016  {
1017  for (j = 0; j < trigger->cDataItems; j++)
1018  {
1019  dataItem = &trigger->pDataItems[j];
1020  alignment = 1;
1021 
1022  switch (dataItem->dwDataType)
1023  {
1024  case SERVICE_TRIGGER_DATA_TYPE_BINARY:
1025  case SERVICE_TRIGGER_DATA_TYPE_LEVEL:
1026  alignment = sizeof(CHAR);
1027  break;
1028  case SERVICE_TRIGGER_DATA_TYPE_STRING:
1029  alignment = sizeof(WCHAR);
1030  break;
1031  case SERVICE_TRIGGER_DATA_TYPE_KEYWORD_ANY:
1032  case SERVICE_TRIGGER_DATA_TYPE_KEYWORD_ALL:
1033  alignment = sizeof(ULONG64);
1034  break;
1035  }
1036 
1037  if (!NT_SUCCESS(status = PhSvcpUnpackBuffer(&packedData, info, &dataItem->pData, dataItem->cbData, alignment, FALSE)))
1038  goto CleanupExit;
1039  }
1040  }
1041  }
1042  }
1043 
1044  unpackedInfo = triggerInfo;
1045  }
1046  break;
1047  case SERVICE_CONFIG_LAUNCH_PROTECTED:
1048  status = PhSvcpUnpackRoot(&packedData, info, sizeof(SERVICE_LAUNCH_PROTECTED_INFO), &unpackedInfo);
1049  break;
1050  default:
1051  status = STATUS_INVALID_PARAMETER;
1052  break;
1053  }
1054 
1055  if (NT_SUCCESS(status))
1056  {
1057  assert(unpackedInfo);
1058 
1059  if (!(serviceHandle = PhOpenService(serviceName->Buffer, desiredAccess)))
1060  {
1061  status = PhGetLastWin32ErrorAsNtStatus();
1062  goto CleanupExit;
1063  }
1064 
1065  if (!ChangeServiceConfig2(
1066  serviceHandle,
1067  Payload->u.ChangeServiceConfig2.i.InfoLevel,
1068  unpackedInfo
1069  ))
1070  {
1071  status = PhGetLastWin32ErrorAsNtStatus();
1072  }
1073  }
1074 
1075 CleanupExit:
1076  if (serviceHandle)
1077  CloseServiceHandle(serviceHandle);
1078  if (info)
1079  PhFree(info);
1080  if (serviceName)
1081  PhDereferenceObject(serviceName);
1082 
1083  return status;
1084 }
1085 
1087  _In_ PPHSVC_CLIENT Client,
1088  _Inout_ PPHSVC_API_PAYLOAD Payload
1089  )
1090 {
1091  static PVOID setTcpEntry = NULL;
1092 
1093  ULONG (__stdcall *localSetTcpEntry)(PVOID TcpRow);
1094  struct
1095  {
1096  DWORD dwState;
1097  DWORD dwLocalAddr;
1098  DWORD dwLocalPort;
1099  DWORD dwRemoteAddr;
1100  DWORD dwRemotePort;
1101  } tcpRow;
1102  ULONG result;
1103 
1104  localSetTcpEntry = setTcpEntry;
1105 
1106  if (!localSetTcpEntry)
1107  {
1108  HMODULE iphlpapiModule;
1109 
1110  iphlpapiModule = LoadLibrary(L"iphlpapi.dll");
1111 
1112  if (iphlpapiModule)
1113  {
1114  localSetTcpEntry = (PVOID)GetProcAddress(iphlpapiModule, "SetTcpEntry");
1115 
1116  if (localSetTcpEntry)
1117  {
1118  if (_InterlockedExchangePointer(&setTcpEntry, localSetTcpEntry) != NULL)
1119  {
1120  // Another thread got the address of SetTcpEntry already.
1121  // Decrement the reference count of iphlpapi.dll.
1122  FreeLibrary(iphlpapiModule);
1123  }
1124  }
1125  }
1126  }
1127 
1128  if (!localSetTcpEntry)
1129  return STATUS_NOT_SUPPORTED;
1130 
1131  tcpRow.dwState = Payload->u.SetTcpEntry.i.State;
1132  tcpRow.dwLocalAddr = Payload->u.SetTcpEntry.i.LocalAddress;
1133  tcpRow.dwLocalPort = Payload->u.SetTcpEntry.i.LocalPort;
1134  tcpRow.dwRemoteAddr = Payload->u.SetTcpEntry.i.RemoteAddress;
1135  tcpRow.dwRemotePort = Payload->u.SetTcpEntry.i.RemotePort;
1136  result = localSetTcpEntry(&tcpRow);
1137 
1138  return NTSTATUS_FROM_WIN32(result);
1139 }
1140 
1142  _In_ PPHSVC_CLIENT Client,
1143  _Inout_ PPHSVC_API_PAYLOAD Payload
1144  )
1145 {
1146  NTSTATUS status;
1147  HANDLE threadId;
1148  HANDLE threadHandle;
1149 
1150  threadId = Payload->u.ControlThread.i.ThreadId;
1151 
1152  switch (Payload->u.ControlThread.i.Command)
1153  {
1155  if (NT_SUCCESS(status = PhOpenThread(&threadHandle, THREAD_TERMINATE, threadId)))
1156  {
1157  status = PhTerminateThread(threadHandle, STATUS_SUCCESS);
1158  NtClose(threadHandle);
1159  }
1160  break;
1162  if (NT_SUCCESS(status = PhOpenThread(&threadHandle, THREAD_SUSPEND_RESUME, threadId)))
1163  {
1164  status = PhSuspendThread(threadHandle, NULL);
1165  NtClose(threadHandle);
1166  }
1167  break;
1169  if (NT_SUCCESS(status = PhOpenThread(&threadHandle, THREAD_SUSPEND_RESUME, threadId)))
1170  {
1171  status = PhResumeThread(threadHandle, NULL);
1172  NtClose(threadHandle);
1173  }
1174  break;
1176  if (NT_SUCCESS(status = PhOpenThread(&threadHandle, THREAD_SET_INFORMATION, threadId)))
1177  {
1178  status = PhSetThreadIoPriority(threadHandle, Payload->u.ControlThread.i.Argument);
1179  NtClose(threadHandle);
1180  }
1181  break;
1182  default:
1183  status = STATUS_INVALID_PARAMETER;
1184  break;
1185  }
1186 
1187  return status;
1188 }
1189 
1191  _In_ PPHSVC_CLIENT Client,
1192  _Inout_ PPHSVC_API_PAYLOAD Payload
1193  )
1194 {
1195  NTSTATUS status;
1196  PSID accountSid;
1197  PPH_STRING userRight;
1198  LSA_HANDLE policyHandle;
1199  UNICODE_STRING userRightUs;
1200 
1201  if (NT_SUCCESS(status = PhSvcCaptureSid(&Payload->u.AddAccountRight.i.AccountSid, FALSE, &accountSid)))
1202  {
1203  if (NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.AddAccountRight.i.UserRight, FALSE, &userRight)))
1204  {
1205  if (NT_SUCCESS(status = PhOpenLsaPolicy(&policyHandle, POLICY_LOOKUP_NAMES | POLICY_CREATE_ACCOUNT, NULL)))
1206  {
1207  PhStringRefToUnicodeString(&userRight->sr, &userRightUs);
1208  status = LsaAddAccountRights(policyHandle, accountSid, &userRightUs, 1);
1209  LsaClose(policyHandle);
1210  }
1211 
1212  PhDereferenceObject(userRight);
1213  }
1214 
1215  PhFree(accountSid);
1216  }
1217 
1218  return status;
1219 }
1220 
1222  _In_ PPHSVC_CLIENT Client,
1223  _Inout_ PPHSVC_API_PAYLOAD Payload
1224  )
1225 {
1226  NTSTATUS status;
1227  PH_RUNAS_SERVICE_PARAMETERS parameters;
1228  PHSVCP_CAPTURED_RUNAS_SERVICE_PARAMETERS capturedParameters;
1229 
1230  if (NT_SUCCESS(status = PhSvcpCaptureRunAsServiceParameters(Client, Payload, &parameters, &capturedParameters)))
1231  {
1232  if (NT_SUCCESS(status = PhSvcpValidateRunAsServiceParameters(&parameters)))
1233  {
1234  status = PhInvokeRunAsService(&parameters);
1235  }
1236  }
1237 
1238  PhSvcpReleaseRunAsServiceParameters(&capturedParameters);
1239 
1240  return status;
1241 }
1242 
1244  _In_ PPHSVC_CLIENT Client,
1245  _Inout_ PPHSVC_API_PAYLOAD Payload
1246  )
1247 {
1248  NTSTATUS status;
1249 
1250  status = NtSetSystemInformation(
1252  &Payload->u.IssueMemoryListCommand.i.Command,
1254  );
1255 
1256  return status;
1257 }
1258 
1260  _In_ PPHSVC_CLIENT Client,
1261  _Inout_ PPHSVC_API_PAYLOAD Payload
1262  )
1263 {
1264  if (PostMessage(
1265  Payload->u.PostMessage.i.hWnd,
1266  Payload->u.PostMessage.i.Msg,
1267  Payload->u.PostMessage.i.wParam,
1268  Payload->u.PostMessage.i.lParam
1269  ))
1270  {
1271  return STATUS_SUCCESS;
1272  }
1273  else
1274  {
1276  }
1277 }
1278 
1280  _In_ PPHSVC_CLIENT Client,
1281  _Inout_ PPHSVC_API_PAYLOAD Payload
1282  )
1283 {
1284  if (SendMessage(
1285  Payload->u.PostMessage.i.hWnd,
1286  Payload->u.PostMessage.i.Msg,
1287  Payload->u.PostMessage.i.wParam,
1288  Payload->u.PostMessage.i.lParam
1289  ))
1290  {
1291  return STATUS_SUCCESS;
1292  }
1293  else
1294  {
1296  }
1297 }
1298 
1300  _In_ PPHSVC_CLIENT Client,
1301  _Inout_ PPHSVC_API_PAYLOAD Payload
1302  )
1303 {
1304  NTSTATUS status;
1305  PPH_STRING fileName;
1306 
1307  if (NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.CreateProcessIgnoreIfeoDebugger.i.FileName, FALSE, &fileName)))
1308  {
1309  if (!PhCreateProcessIgnoreIfeoDebugger(fileName->Buffer))
1310  status = STATUS_UNSUCCESSFUL;
1311 
1312  PhDereferenceObject(fileName);
1313  }
1314 
1315  return status;
1316 }
1317 
1319  _In_ PPHSVC_CLIENT Client,
1320  _Inout_ PPHSVC_API_PAYLOAD Payload
1321  )
1322 {
1323  NTSTATUS status;
1324  PPH_STRING serviceName;
1325  PSECURITY_DESCRIPTOR securityDescriptor;
1326  ACCESS_MASK desiredAccess;
1327  SC_HANDLE serviceHandle;
1328 
1329  if (NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.SetServiceSecurity.i.ServiceName, FALSE, &serviceName)))
1330  {
1331  if (NT_SUCCESS(status = PhSvcCaptureSecurityDescriptor(&Payload->u.SetServiceSecurity.i.SecurityDescriptor, FALSE, 0, &securityDescriptor)))
1332  {
1333  desiredAccess = 0;
1334 
1335  if ((Payload->u.SetServiceSecurity.i.SecurityInformation & OWNER_SECURITY_INFORMATION) ||
1336  (Payload->u.SetServiceSecurity.i.SecurityInformation & GROUP_SECURITY_INFORMATION))
1337  {
1338  desiredAccess |= WRITE_OWNER;
1339  }
1340 
1341  if (Payload->u.SetServiceSecurity.i.SecurityInformation & DACL_SECURITY_INFORMATION)
1342  {
1343  desiredAccess |= WRITE_DAC;
1344  }
1345 
1346  if (Payload->u.SetServiceSecurity.i.SecurityInformation & SACL_SECURITY_INFORMATION)
1347  {
1348  desiredAccess |= ACCESS_SYSTEM_SECURITY;
1349  }
1350 
1351  if (serviceHandle = PhOpenService(serviceName->Buffer, desiredAccess))
1352  {
1353  status = PhSetSeObjectSecurity(
1354  serviceHandle,
1355  SE_SERVICE,
1356  Payload->u.SetServiceSecurity.i.SecurityInformation,
1357  securityDescriptor
1358  );
1359  CloseServiceHandle(serviceHandle);
1360  }
1361  else
1362  {
1363  status = PhGetLastWin32ErrorAsNtStatus();
1364  }
1365 
1366  PhFree(securityDescriptor);
1367  }
1368 
1369  PhDereferenceObject(serviceName);
1370  }
1371 
1372  return status;
1373 }
1374 
1376  _In_ PPHSVC_CLIENT Client,
1377  _Inout_ PPHSVC_API_PAYLOAD Payload
1378  )
1379 {
1380  static BOOLEAN alreadyLoaded;
1381 
1382  NTSTATUS status;
1383  PPH_STRING dbgHelpPath;
1384 
1385  if (alreadyLoaded)
1386  return STATUS_SOME_NOT_MAPPED;
1387 
1388  if (NT_SUCCESS(status = PhSvcCaptureString(&Payload->u.LoadDbgHelp.i.DbgHelpPath, FALSE, &dbgHelpPath)))
1389  {
1390  PhLoadDbgHelpFromPath(dbgHelpPath->Buffer);
1391  PhDereferenceObject(dbgHelpPath);
1392  alreadyLoaded = TRUE;
1393  }
1394 
1395  return status;
1396 }
1397 
1399  _In_ PPHSVC_CLIENT Client,
1400  _Inout_ PPHSVC_API_PAYLOAD Payload
1401  )
1402 {
1404  UlongToHandle(Payload->u.WriteMiniDumpProcess.i.LocalProcessHandle),
1405  UlongToHandle(Payload->u.WriteMiniDumpProcess.i.ProcessId),
1406  UlongToHandle(Payload->u.WriteMiniDumpProcess.i.LocalFileHandle),
1407  Payload->u.WriteMiniDumpProcess.i.DumpType,
1408  NULL,
1409  NULL,
1410  NULL
1411  ))
1412  {
1413  return STATUS_SUCCESS;
1414  }
1415  else
1416  {
1417  ULONG error;
1418 
1419  error = GetLastError();
1420 
1421  if (error == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
1422  return STATUS_INVALID_PARAMETER;
1423  else
1424  return STATUS_UNSUCCESSFUL;
1425  }
1426 }