Win32 API 日本語リファレンス
ホームSystem.Services › CreateServiceW

CreateServiceW

関数
新しいサービスを作成しSCMデータベースに登録する。
DLLADVAPI32.dll文字セットUnicode (-W)呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

// ADVAPI32.dll  (Unicode / -W)
#include <windows.h>

SC_HANDLE CreateServiceW(
    SC_HANDLE hSCManager,
    LPCWSTR lpServiceName,
    LPCWSTR lpDisplayName,   // optional
    DWORD dwDesiredAccess,
    ENUM_SERVICE_TYPE dwServiceType,
    SERVICE_START_TYPE dwStartType,
    SERVICE_ERROR dwErrorControl,
    LPCWSTR lpBinaryPathName,   // optional
    LPCWSTR lpLoadOrderGroup,   // optional
    DWORD* lpdwTagId,   // optional
    LPCWSTR lpDependencies,   // optional
    LPCWSTR lpServiceStartName,   // optional
    LPCWSTR lpPassword   // optional
);

パラメーター

名前方向説明
hSCManagerSC_HANDLEinサービスコントロールマネージャーのデータベースへのハンドル。このハンドルは OpenSCManager 関数によって返され、SC_MANAGER_CREATE_SERVICE アクセス権を持っている必要があります。詳細については、 サービスのセキュリティとアクセス権 を参照してください。
lpServiceNameLPCWSTRinインストールするサービスの名前。文字列の最大長は 256 文字です。サービスコントロールマネージャーのデータベースは文字の大文字と小文字を保持しますが、サービス名の比較は常に大文字と小文字を区別しません。スラッシュ (/) とバックスラッシュ (\) はサービス名として使用できません。
lpDisplayNameLPCWSTRinoptionalユーザーインターフェイスプログラムがサービスを識別するために使用する表示名。この文字列の最大長は 256 文字です。サービスコントロールマネージャーでは大文字と小文字が保持されます。表示名の比較は常に大文字と小文字を区別しません。
dwDesiredAccessDWORDinサービスへのアクセス権。要求されたアクセスを許可する前に、システムは呼び出し元プロセスのアクセストークンを確認します。指定可能な値の一覧については、 サービスのセキュリティとアクセス権 を参照してください。
dwServiceTypeENUM_SERVICE_TYPEin

サービスの種類。このパラメーターには次のいずれかの値を指定できます。

意味
SERVICE_ADAPTER
0x00000004
予約済み。
SERVICE_FILE_SYSTEM_DRIVER
0x00000002
ファイルシステムドライバーサービス。
SERVICE_KERNEL_DRIVER
0x00000001
ドライバーサービス。
SERVICE_RECOGNIZER_DRIVER
0x00000008
予約済み。
SERVICE_WIN32_OWN_PROCESS
0x00000010
独自のプロセスで実行されるサービス。
SERVICE_WIN32_SHARE_PROCESS
0x00000020
他の 1 つ以上のサービスとプロセスを共有するサービス。詳細については、サービスプログラム を参照してください。

SERVICE_WIN32_OWN_PROCESS または SERVICE_WIN32_SHARE_PROCESS を指定し、かつサービスが LocalSystem アカウント のコンテキストで実行される場合は、次の値も指定できます。

意味
SERVICE_INTERACTIVE_PROCESS
0x00000100
サービスがデスクトップと対話できます。

詳細については、 対話型サービス を参照してください。

dwStartTypeSERVICE_START_TYPEin

サービスの開始オプション。このパラメーターには次のいずれかの値を指定できます。

意味
SERVICE_AUTO_START
0x00000002
システム起動時にサービスコントロールマネージャーによって自動的に開始されるサービス。詳細については、サービスの自動開始 を参照してください。
SERVICE_BOOT_START
0x00000000
システムローダーによって開始されるデバイスドライバー。この値はドライバーサービスに対してのみ有効です。
SERVICE_DEMAND_START
0x00000003
プロセスが StartService 関数を呼び出したときに、サービスコントロールマネージャーによって開始されるサービス。詳細については、サービスのオンデマンド開始 を参照してください。
SERVICE_DISABLED
0x00000004
開始できないサービス。このサービスを開始しようとすると、エラーコード ERROR_SERVICE_DISABLED が返されます。
SERVICE_SYSTEM_START
0x00000001
IoInitSystem 関数によって開始されるデバイスドライバー。この値はドライバーサービスに対してのみ有効です。
dwErrorControlSERVICE_ERRORin

このサービスの開始に失敗した場合のエラーの重大度と、実行される処理。このパラメーターには次のいずれかの値を指定できます。

意味
SERVICE_ERROR_CRITICAL
0x00000003
起動プログラムは可能であればエラーをイベントログに記録します。最後に正常起動した構成 (last-known-good) で起動している場合は、起動操作が失敗します。それ以外の場合は、最後に正常起動した構成でシステムが再起動されます。
SERVICE_ERROR_IGNORE
0x00000000
起動プログラムはエラーを無視して起動操作を続行します。
SERVICE_ERROR_NORMAL
0x00000001
起動プログラムはエラーをイベントログに記録しますが、起動操作は続行します。
SERVICE_ERROR_SEVERE
0x00000002
起動プログラムはエラーをイベントログに記録します。最後に正常起動した構成 (last-known-good) で起動している場合は、起動操作が続行されます。それ以外の場合は、最後に正常起動した構成でシステムが再起動されます。
lpBinaryPathNameLPCWSTRinoptional

サービスのバイナリファイルへの完全修飾パス。パスにスペースが含まれる場合は、正しく解釈されるように引用符で囲む必要があります。たとえば、"d:\my share\myservice.exe" は ""d:\my share\myservice.exe"" のように指定します。

パスには、自動開始サービス用の引数を含めることもできます。たとえば、"d:\myshare\myservice.exe arg1 arg2" のように指定します。これらの引数は、サービスのエントリポイント (通常は main 関数) に渡されます。

別のコンピューター上のパスを指定する場合、そのリモート呼び出しで使用されるセキュリティコンテキストとなるため、共有はローカルコンピューターのコンピューターアカウントからアクセスできる必要があります。ただし、この要件により、リモートコンピューターの潜在的な脆弱性がローカルコンピューターに影響を及ぼす可能性があります。したがって、ローカルファイルを使用するのが最善です。

lpLoadOrderGroupLPCWSTRinoptional

このサービスが属するロード順序グループの名前。サービスがグループに属さない場合は、NULL または空の文字列を指定します。

起動プログラムは、ロード順序グループを使用して、他のグループに対して指定された順序でサービスのグループをロードします。ロード順序グループの一覧は、次のレジストリ値に格納されています。HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ServiceGroupOrder

lpdwTagIdDWORD*outoptional

lpLoadOrderGroup パラメーターで指定したグループ内で一意となるタグ値を受け取る変数へのポインター。既存のタグを変更しない場合は NULL を指定します。

次のレジストリ値にタグ順序ベクトルを指定することで、ロード順序グループ内でのサービス起動の順序付けにタグを使用できます。HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GroupOrderList

タグが評価されるのは、SERVICE_BOOT_START または SERVICE_SYSTEM_START の開始種類を持つドライバーサービスのみです。

lpDependenciesLPCWSTRinoptional

このサービスより前にシステムが開始しなければならないサービスまたはロード順序グループの名前を、NULL で区切り、二重 NULL で終端した配列へのポインター。サービスに依存関係がない場合は、NULL または空の文字列を指定します。グループへの依存とは、グループのすべてのメンバーを開始しようとした後、そのグループの少なくとも 1 つのメンバーが実行されていればこのサービスを実行できることを意味します。

サービスとサービスグループは同じ名前空間を共有するため、サービス名と区別できるように、グループ名には SC_GROUP_IDENTIFIER を接頭辞として付ける必要があります。

lpServiceStartNameLPCWSTRinoptional

サービスを実行するアカウントの名前。サービスの種類が SERVICE_WIN32_OWN_PROCESS の場合は、DomainName\UserName の形式でアカウント名を指定します。サービスプロセスはこのユーザーとしてログオンされます。アカウントが組み込みのドメインに属している場合は、.\UserName と指定できます。

このパラメーターが NULL の場合、 CreateServiceLocalSystem アカウント を使用します。サービスの種類が SERVICE_INTERACTIVE_PROCESS を指定している場合、サービスは LocalSystem アカウントで実行する必要があります。

このパラメーターが NT AUTHORITY\LocalService の場合、 CreateServiceLocalService アカウント を使用します。パラメーターが NT AUTHORITY\NetworkService の場合、 CreateServiceNetworkService アカウント を使用します。

共有プロセスは任意のユーザーとして実行できます。

サービスの種類が SERVICE_KERNEL_DRIVER または SERVICE_FILE_SYSTEM_DRIVER の場合、この名前はシステムがデバイスドライバーをロードするために使用するドライバーオブジェクト名です。ドライバーが I/O システムによって作成された既定のオブジェクト名を使用する場合は、NULL を指定します。

サービスは、管理されたアカウントまたは仮想アカウントを使用するように構成できます。サービスが管理されたサービスアカウントを使用するように構成されている場合、この名前は管理されたサービスアカウントの名前です。サービスが仮想アカウントを使用するように構成されている場合は、NT SERVICE\ServiceName の形式で名前を指定します。管理されたサービスアカウントと仮想アカウントの詳細については、サービスアカウントのステップバイステップガイド を参照してください。

Windows Server 2008、Windows Vista、Windows Server 2003、および Windows XP: 管理されたサービスアカウントと仮想アカウントは、Windows 7 および Windows Server 2008 R2 までサポートされていません。

lpPasswordLPCWSTRinoptional

lpServiceStartName パラメーターで指定したアカウント名のパスワード。アカウントにパスワードがない場合、またはサービスが LocalService、NetworkService、もしくは LocalSystem アカウントで実行される場合は、空の文字列を指定します。詳細については、 サービスレコードリスト を参照してください。

lpServiceStartName パラメーターで指定したアカウント名が、管理されたサービスアカウントまたは仮想アカウントの名前である場合、lpPassword パラメーターは NULL でなければなりません。

ドライバーサービスではパスワードは無視されます。

戻り値の型: SC_HANDLE

公式ドキュメント

サービスオブジェクトを作成し、指定したサービスコントロールマネージャーのデータベースに追加します。(Unicode)

戻り値

関数が成功した場合、戻り値はサービスへのハンドルです。

関数が失敗した場合、戻り値は NULL です。拡張エラー情報を取得するには、 GetLastError を呼び出します。

次のエラーコードはサービスコントロールマネージャーによって設定される場合があります。その他のエラーコードは、サービスコントロールマネージャーによって呼び出されるレジストリ関数によって設定される場合があります。

戻りコード 説明
ERROR_ACCESS_DENIED
SCM データベースへのハンドルに SC_MANAGER_CREATE_SERVICE アクセス権がありません。
ERROR_CIRCULAR_DEPENDENCY
循環するサービス依存関係が指定されました。
ERROR_DUPLICATE_SERVICE_NAME
指定した表示名は、サービス名または別の表示名として、サービスコントロールマネージャーのデータベースに既に存在します。
ERROR_INVALID_HANDLE
指定したサービスコントロールマネージャーのデータベースへのハンドルが無効です。
ERROR_INVALID_NAME
指定したサービス名が無効です。
ERROR_INVALID_PARAMETER
指定したパラメーターが無効です。
ERROR_INVALID_SERVICE_ACCOUNT
lpServiceStartName パラメーターで指定したユーザーアカウント名が存在しません。
ERROR_SERVICE_EXISTS
指定したサービスはこのデータベースに既に存在します。
ERROR_SERVICE_MARKED_FOR_DELETE
指定したサービスはこのデータベースに既に存在し、削除対象としてマークされています。

解説(Remarks)

CreateService 関数は、サービスオブジェクトを作成し、次のレジストリキーの下にサービスと同じ名前のキーを作成することで、それをサービスコントロールマネージャーのデータベースにインストールします。HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services

CreateServiceChangeServiceConfig、および ChangeServiceConfig2 によって指定された情報は、このキーの下に値として保存されます。次に、サービスに対して保存される値の例を示します。

説明
DependOnGroup lpDependencies で指定された、このサービスが依存するロード順序グループ。
DependOnService lpDependencies で指定された、このサービスが依存するサービス。
Description ChangeServiceConfig2 で指定された説明。
DisplayName lpDisplayName で指定された表示名。
ErrorControl dwErrorControl で指定されたエラー制御。
FailureActions ChangeServiceConfig2 で指定された失敗時の動作。
Group lpLoadOrderGroup で指定されたロード順序グループ。この値を設定すると、DependOnService 値の設定が上書きされる場合があることに注意してください。
ImagePath lpBinaryPathName で指定された、バイナリファイルの名前。
ObjectName lpServiceStartName で指定されたアカウント名。
Start dwStartType で指定された、サービスを開始するタイミング。
Tag lpdwTagId で指定されたタグ識別子。
Type dwServiceType で指定されたサービスの種類。

セットアッププログラムやサービス自体は、サービス固有の情報のために追加のサブキーを作成できます。

返されるハンドルは、 CreateService を呼び出したプロセスでのみ有効です。このハンドルは CloseServiceHandle 関数を呼び出すことで閉じることができます。

プロセスを共有するサービスを作成する場合は、 ExitProcess など、プロセス全体に影響を与える関数の呼び出しを避けてください。また、サービス DLL をアンロードしないでください。

例については、 サービスのインストール を参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// ADVAPI32.dll  (Unicode / -W)
#include <windows.h>

SC_HANDLE CreateServiceW(
    SC_HANDLE hSCManager,
    LPCWSTR lpServiceName,
    LPCWSTR lpDisplayName,   // optional
    DWORD dwDesiredAccess,
    ENUM_SERVICE_TYPE dwServiceType,
    SERVICE_START_TYPE dwStartType,
    SERVICE_ERROR dwErrorControl,
    LPCWSTR lpBinaryPathName,   // optional
    LPCWSTR lpLoadOrderGroup,   // optional
    DWORD* lpdwTagId,   // optional
    LPCWSTR lpDependencies,   // optional
    LPCWSTR lpServiceStartName,   // optional
    LPCWSTR lpPassword   // optional
);
[DllImport("ADVAPI32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
static extern IntPtr CreateServiceW(
    IntPtr hSCManager,   // SC_HANDLE
    [MarshalAs(UnmanagedType.LPWStr)] string lpServiceName,   // LPCWSTR
    [MarshalAs(UnmanagedType.LPWStr)] string lpDisplayName,   // LPCWSTR optional
    uint dwDesiredAccess,   // DWORD
    uint dwServiceType,   // ENUM_SERVICE_TYPE
    uint dwStartType,   // SERVICE_START_TYPE
    uint dwErrorControl,   // SERVICE_ERROR
    [MarshalAs(UnmanagedType.LPWStr)] string lpBinaryPathName,   // LPCWSTR optional
    [MarshalAs(UnmanagedType.LPWStr)] string lpLoadOrderGroup,   // LPCWSTR optional
    IntPtr lpdwTagId,   // DWORD* optional, out
    [MarshalAs(UnmanagedType.LPWStr)] string lpDependencies,   // LPCWSTR optional
    [MarshalAs(UnmanagedType.LPWStr)] string lpServiceStartName,   // LPCWSTR optional
    [MarshalAs(UnmanagedType.LPWStr)] string lpPassword   // LPCWSTR optional
);
<DllImport("ADVAPI32.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function CreateServiceW(
    hSCManager As IntPtr,   ' SC_HANDLE
    <MarshalAs(UnmanagedType.LPWStr)> lpServiceName As String,   ' LPCWSTR
    <MarshalAs(UnmanagedType.LPWStr)> lpDisplayName As String,   ' LPCWSTR optional
    dwDesiredAccess As UInteger,   ' DWORD
    dwServiceType As UInteger,   ' ENUM_SERVICE_TYPE
    dwStartType As UInteger,   ' SERVICE_START_TYPE
    dwErrorControl As UInteger,   ' SERVICE_ERROR
    <MarshalAs(UnmanagedType.LPWStr)> lpBinaryPathName As String,   ' LPCWSTR optional
    <MarshalAs(UnmanagedType.LPWStr)> lpLoadOrderGroup As String,   ' LPCWSTR optional
    lpdwTagId As IntPtr,   ' DWORD* optional, out
    <MarshalAs(UnmanagedType.LPWStr)> lpDependencies As String,   ' LPCWSTR optional
    <MarshalAs(UnmanagedType.LPWStr)> lpServiceStartName As String,   ' LPCWSTR optional
    <MarshalAs(UnmanagedType.LPWStr)> lpPassword As String   ' LPCWSTR optional
) As IntPtr
End Function
' hSCManager : SC_HANDLE
' lpServiceName : LPCWSTR
' lpDisplayName : LPCWSTR optional
' dwDesiredAccess : DWORD
' dwServiceType : ENUM_SERVICE_TYPE
' dwStartType : SERVICE_START_TYPE
' dwErrorControl : SERVICE_ERROR
' lpBinaryPathName : LPCWSTR optional
' lpLoadOrderGroup : LPCWSTR optional
' lpdwTagId : DWORD* optional, out
' lpDependencies : LPCWSTR optional
' lpServiceStartName : LPCWSTR optional
' lpPassword : LPCWSTR optional
Declare PtrSafe Function CreateServiceW Lib "advapi32" ( _
    ByVal hSCManager As LongPtr, _
    ByVal lpServiceName As LongPtr, _
    ByVal lpDisplayName As LongPtr, _
    ByVal dwDesiredAccess As Long, _
    ByVal dwServiceType As Long, _
    ByVal dwStartType As Long, _
    ByVal dwErrorControl As Long, _
    ByVal lpBinaryPathName As LongPtr, _
    ByVal lpLoadOrderGroup As LongPtr, _
    ByVal lpdwTagId As LongPtr, _
    ByVal lpDependencies As LongPtr, _
    ByVal lpServiceStartName As LongPtr, _
    ByVal lpPassword As LongPtr) As LongPtr
' Unicode(W): 文字列は ByVal As LongPtr とし StrPtr(unicodeStr) を渡す
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

CreateServiceW = ctypes.windll.advapi32.CreateServiceW
CreateServiceW.restype = ctypes.c_void_p
CreateServiceW.argtypes = [
    wintypes.HANDLE,  # hSCManager : SC_HANDLE
    wintypes.LPCWSTR,  # lpServiceName : LPCWSTR
    wintypes.LPCWSTR,  # lpDisplayName : LPCWSTR optional
    wintypes.DWORD,  # dwDesiredAccess : DWORD
    wintypes.DWORD,  # dwServiceType : ENUM_SERVICE_TYPE
    wintypes.DWORD,  # dwStartType : SERVICE_START_TYPE
    wintypes.DWORD,  # dwErrorControl : SERVICE_ERROR
    wintypes.LPCWSTR,  # lpBinaryPathName : LPCWSTR optional
    wintypes.LPCWSTR,  # lpLoadOrderGroup : LPCWSTR optional
    ctypes.POINTER(wintypes.DWORD),  # lpdwTagId : DWORD* optional, out
    wintypes.LPCWSTR,  # lpDependencies : LPCWSTR optional
    wintypes.LPCWSTR,  # lpServiceStartName : LPCWSTR optional
    wintypes.LPCWSTR,  # lpPassword : LPCWSTR optional
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('ADVAPI32.dll')
CreateServiceW = Fiddle::Function.new(
  lib['CreateServiceW'],
  [
    Fiddle::TYPE_VOIDP,  # hSCManager : SC_HANDLE
    Fiddle::TYPE_VOIDP,  # lpServiceName : LPCWSTR
    Fiddle::TYPE_VOIDP,  # lpDisplayName : LPCWSTR optional
    -Fiddle::TYPE_INT,  # dwDesiredAccess : DWORD
    -Fiddle::TYPE_INT,  # dwServiceType : ENUM_SERVICE_TYPE
    -Fiddle::TYPE_INT,  # dwStartType : SERVICE_START_TYPE
    -Fiddle::TYPE_INT,  # dwErrorControl : SERVICE_ERROR
    Fiddle::TYPE_VOIDP,  # lpBinaryPathName : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # lpLoadOrderGroup : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # lpdwTagId : DWORD* optional, out
    Fiddle::TYPE_VOIDP,  # lpDependencies : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # lpServiceStartName : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # lpPassword : LPCWSTR optional
  ],
  Fiddle::TYPE_VOIDP)
# Wide strings: pass str.encode("UTF-16LE") + "\x00\x00"
#[link(name = "advapi32")]
extern "system" {
    fn CreateServiceW(
        hSCManager: *mut core::ffi::c_void,  // SC_HANDLE
        lpServiceName: *const u16,  // LPCWSTR
        lpDisplayName: *const u16,  // LPCWSTR optional
        dwDesiredAccess: u32,  // DWORD
        dwServiceType: u32,  // ENUM_SERVICE_TYPE
        dwStartType: u32,  // SERVICE_START_TYPE
        dwErrorControl: u32,  // SERVICE_ERROR
        lpBinaryPathName: *const u16,  // LPCWSTR optional
        lpLoadOrderGroup: *const u16,  // LPCWSTR optional
        lpdwTagId: *mut u32,  // DWORD* optional, out
        lpDependencies: *const u16,  // LPCWSTR optional
        lpServiceStartName: *const u16,  // LPCWSTR optional
        lpPassword: *const u16  // LPCWSTR optional
    ) -> *mut core::ffi::c_void;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("ADVAPI32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateServiceW(IntPtr hSCManager, [MarshalAs(UnmanagedType.LPWStr)] string lpServiceName, [MarshalAs(UnmanagedType.LPWStr)] string lpDisplayName, uint dwDesiredAccess, uint dwServiceType, uint dwStartType, uint dwErrorControl, [MarshalAs(UnmanagedType.LPWStr)] string lpBinaryPathName, [MarshalAs(UnmanagedType.LPWStr)] string lpLoadOrderGroup, IntPtr lpdwTagId, [MarshalAs(UnmanagedType.LPWStr)] string lpDependencies, [MarshalAs(UnmanagedType.LPWStr)] string lpServiceStartName, [MarshalAs(UnmanagedType.LPWStr)] string lpPassword);
"@
$api = Add-Type -MemberDefinition $sig -Name 'ADVAPI32_CreateServiceW' -Namespace Win32 -PassThru
# $api::CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
#uselib "ADVAPI32.dll"
#func global CreateServiceW "CreateServiceW" wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr
; CreateServiceW hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, varptr(lpdwTagId), lpDependencies, lpServiceStartName, lpPassword   ; 戻り値は stat
; hSCManager : SC_HANDLE -> "wptr"
; lpServiceName : LPCWSTR -> "wptr"
; lpDisplayName : LPCWSTR optional -> "wptr"
; dwDesiredAccess : DWORD -> "wptr"
; dwServiceType : ENUM_SERVICE_TYPE -> "wptr"
; dwStartType : SERVICE_START_TYPE -> "wptr"
; dwErrorControl : SERVICE_ERROR -> "wptr"
; lpBinaryPathName : LPCWSTR optional -> "wptr"
; lpLoadOrderGroup : LPCWSTR optional -> "wptr"
; lpdwTagId : DWORD* optional, out -> "wptr"
; lpDependencies : LPCWSTR optional -> "wptr"
; lpServiceStartName : LPCWSTR optional -> "wptr"
; lpPassword : LPCWSTR optional -> "wptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "ADVAPI32.dll"
#cfunc global CreateServiceW "CreateServiceW" sptr, wstr, wstr, int, int, int, int, wstr, wstr, var, wstr, wstr, wstr
; res = CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
; hSCManager : SC_HANDLE -> "sptr"
; lpServiceName : LPCWSTR -> "wstr"
; lpDisplayName : LPCWSTR optional -> "wstr"
; dwDesiredAccess : DWORD -> "int"
; dwServiceType : ENUM_SERVICE_TYPE -> "int"
; dwStartType : SERVICE_START_TYPE -> "int"
; dwErrorControl : SERVICE_ERROR -> "int"
; lpBinaryPathName : LPCWSTR optional -> "wstr"
; lpLoadOrderGroup : LPCWSTR optional -> "wstr"
; lpdwTagId : DWORD* optional, out -> "var"
; lpDependencies : LPCWSTR optional -> "wstr"
; lpServiceStartName : LPCWSTR optional -> "wstr"
; lpPassword : LPCWSTR optional -> "wstr"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; SC_HANDLE CreateServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName, LPCWSTR lpDisplayName, DWORD dwDesiredAccess, ENUM_SERVICE_TYPE dwServiceType, SERVICE_START_TYPE dwStartType, SERVICE_ERROR dwErrorControl, LPCWSTR lpBinaryPathName, LPCWSTR lpLoadOrderGroup, DWORD* lpdwTagId, LPCWSTR lpDependencies, LPCWSTR lpServiceStartName, LPCWSTR lpPassword)
#uselib "ADVAPI32.dll"
#cfunc global CreateServiceW "CreateServiceW" intptr, wstr, wstr, int, int, int, int, wstr, wstr, var, wstr, wstr, wstr
; res = CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
; hSCManager : SC_HANDLE -> "intptr"
; lpServiceName : LPCWSTR -> "wstr"
; lpDisplayName : LPCWSTR optional -> "wstr"
; dwDesiredAccess : DWORD -> "int"
; dwServiceType : ENUM_SERVICE_TYPE -> "int"
; dwStartType : SERVICE_START_TYPE -> "int"
; dwErrorControl : SERVICE_ERROR -> "int"
; lpBinaryPathName : LPCWSTR optional -> "wstr"
; lpLoadOrderGroup : LPCWSTR optional -> "wstr"
; lpdwTagId : DWORD* optional, out -> "var"
; lpDependencies : LPCWSTR optional -> "wstr"
; lpServiceStartName : LPCWSTR optional -> "wstr"
; lpPassword : LPCWSTR optional -> "wstr"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	advapi32 = windows.NewLazySystemDLL("ADVAPI32.dll")
	procCreateServiceW = advapi32.NewProc("CreateServiceW")
)

// hSCManager (SC_HANDLE), lpServiceName (LPCWSTR), lpDisplayName (LPCWSTR optional), dwDesiredAccess (DWORD), dwServiceType (ENUM_SERVICE_TYPE), dwStartType (SERVICE_START_TYPE), dwErrorControl (SERVICE_ERROR), lpBinaryPathName (LPCWSTR optional), lpLoadOrderGroup (LPCWSTR optional), lpdwTagId (DWORD* optional, out), lpDependencies (LPCWSTR optional), lpServiceStartName (LPCWSTR optional), lpPassword (LPCWSTR optional)
r1, _, err := procCreateServiceW.Call(
	uintptr(hSCManager),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpServiceName))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpDisplayName))),
	uintptr(dwDesiredAccess),
	uintptr(dwServiceType),
	uintptr(dwStartType),
	uintptr(dwErrorControl),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpBinaryPathName))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpLoadOrderGroup))),
	uintptr(lpdwTagId),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpDependencies))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpServiceStartName))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpPassword))),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // SC_HANDLE
function CreateServiceW(
  hSCManager: THandle;   // SC_HANDLE
  lpServiceName: PWideChar;   // LPCWSTR
  lpDisplayName: PWideChar;   // LPCWSTR optional
  dwDesiredAccess: DWORD;   // DWORD
  dwServiceType: DWORD;   // ENUM_SERVICE_TYPE
  dwStartType: DWORD;   // SERVICE_START_TYPE
  dwErrorControl: DWORD;   // SERVICE_ERROR
  lpBinaryPathName: PWideChar;   // LPCWSTR optional
  lpLoadOrderGroup: PWideChar;   // LPCWSTR optional
  lpdwTagId: Pointer;   // DWORD* optional, out
  lpDependencies: PWideChar;   // LPCWSTR optional
  lpServiceStartName: PWideChar;   // LPCWSTR optional
  lpPassword: PWideChar   // LPCWSTR optional
): THandle; stdcall;
  external 'ADVAPI32.dll' name 'CreateServiceW';
result := DllCall("ADVAPI32\CreateServiceW"
    , "Ptr", hSCManager   ; SC_HANDLE
    , "WStr", lpServiceName   ; LPCWSTR
    , "WStr", lpDisplayName   ; LPCWSTR optional
    , "UInt", dwDesiredAccess   ; DWORD
    , "UInt", dwServiceType   ; ENUM_SERVICE_TYPE
    , "UInt", dwStartType   ; SERVICE_START_TYPE
    , "UInt", dwErrorControl   ; SERVICE_ERROR
    , "WStr", lpBinaryPathName   ; LPCWSTR optional
    , "WStr", lpLoadOrderGroup   ; LPCWSTR optional
    , "Ptr", lpdwTagId   ; DWORD* optional, out
    , "WStr", lpDependencies   ; LPCWSTR optional
    , "WStr", lpServiceStartName   ; LPCWSTR optional
    , "WStr", lpPassword   ; LPCWSTR optional
    , "Ptr")   ; return: SC_HANDLE
●CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword) = DLL("ADVAPI32.dll", "void* CreateServiceW(void*, char*, char*, dword, dword, dword, dword, char*, char*, void*, char*, char*, char*)")
# 呼び出し: CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
# hSCManager : SC_HANDLE -> "void*"
# lpServiceName : LPCWSTR -> "char*"
# lpDisplayName : LPCWSTR optional -> "char*"
# dwDesiredAccess : DWORD -> "dword"
# dwServiceType : ENUM_SERVICE_TYPE -> "dword"
# dwStartType : SERVICE_START_TYPE -> "dword"
# dwErrorControl : SERVICE_ERROR -> "dword"
# lpBinaryPathName : LPCWSTR optional -> "char*"
# lpLoadOrderGroup : LPCWSTR optional -> "char*"
# lpdwTagId : DWORD* optional, out -> "void*"
# lpDependencies : LPCWSTR optional -> "char*"
# lpServiceStartName : LPCWSTR optional -> "char*"
# lpPassword : LPCWSTR optional -> "char*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
# ※-W(Unicode)関数。なでしこ1はANSIのため -A 版の利用を推奨。
const std = @import("std");

extern "advapi32" fn CreateServiceW(
    hSCManager: ?*anyopaque, // SC_HANDLE
    lpServiceName: [*c]const u16, // LPCWSTR
    lpDisplayName: [*c]const u16, // LPCWSTR optional
    dwDesiredAccess: u32, // DWORD
    dwServiceType: u32, // ENUM_SERVICE_TYPE
    dwStartType: u32, // SERVICE_START_TYPE
    dwErrorControl: u32, // SERVICE_ERROR
    lpBinaryPathName: [*c]const u16, // LPCWSTR optional
    lpLoadOrderGroup: [*c]const u16, // LPCWSTR optional
    lpdwTagId: [*c]u32, // DWORD* optional, out
    lpDependencies: [*c]const u16, // LPCWSTR optional
    lpServiceStartName: [*c]const u16, // LPCWSTR optional
    lpPassword: [*c]const u16 // LPCWSTR optional
) callconv(std.os.windows.WINAPI) ?*anyopaque;
// Unicode(-W): UTF-16LE のヌル終端バッファ([*c]const u16)を渡す。
proc CreateServiceW(
    hSCManager: pointer,  # SC_HANDLE
    lpServiceName: WideCString,  # LPCWSTR
    lpDisplayName: WideCString,  # LPCWSTR optional
    dwDesiredAccess: uint32,  # DWORD
    dwServiceType: uint32,  # ENUM_SERVICE_TYPE
    dwStartType: uint32,  # SERVICE_START_TYPE
    dwErrorControl: uint32,  # SERVICE_ERROR
    lpBinaryPathName: WideCString,  # LPCWSTR optional
    lpLoadOrderGroup: WideCString,  # LPCWSTR optional
    lpdwTagId: ptr uint32,  # DWORD* optional, out
    lpDependencies: WideCString,  # LPCWSTR optional
    lpServiceStartName: WideCString,  # LPCWSTR optional
    lpPassword: WideCString  # LPCWSTR optional
): pointer {.importc: "CreateServiceW", stdcall, dynlib: "ADVAPI32.dll".}
# Unicode(-W): WideCString は newWideCString("...") で生成。
pragma(lib, "advapi32");
extern(Windows)
void* CreateServiceW(
    void* hSCManager,   // SC_HANDLE
    const(wchar)* lpServiceName,   // LPCWSTR
    const(wchar)* lpDisplayName,   // LPCWSTR optional
    uint dwDesiredAccess,   // DWORD
    uint dwServiceType,   // ENUM_SERVICE_TYPE
    uint dwStartType,   // SERVICE_START_TYPE
    uint dwErrorControl,   // SERVICE_ERROR
    const(wchar)* lpBinaryPathName,   // LPCWSTR optional
    const(wchar)* lpLoadOrderGroup,   // LPCWSTR optional
    uint* lpdwTagId,   // DWORD* optional, out
    const(wchar)* lpDependencies,   // LPCWSTR optional
    const(wchar)* lpServiceStartName,   // LPCWSTR optional
    const(wchar)* lpPassword   // LPCWSTR optional
);
ccall((:CreateServiceW, "ADVAPI32.dll"), stdcall, Ptr{Cvoid},
      (Ptr{Cvoid}, Cwstring, Cwstring, UInt32, UInt32, UInt32, UInt32, Cwstring, Cwstring, Ptr{UInt32}, Cwstring, Cwstring, Cwstring),
      hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
# hSCManager : SC_HANDLE -> Ptr{Cvoid}
# lpServiceName : LPCWSTR -> Cwstring
# lpDisplayName : LPCWSTR optional -> Cwstring
# dwDesiredAccess : DWORD -> UInt32
# dwServiceType : ENUM_SERVICE_TYPE -> UInt32
# dwStartType : SERVICE_START_TYPE -> UInt32
# dwErrorControl : SERVICE_ERROR -> UInt32
# lpBinaryPathName : LPCWSTR optional -> Cwstring
# lpLoadOrderGroup : LPCWSTR optional -> Cwstring
# lpdwTagId : DWORD* optional, out -> Ptr{UInt32}
# lpDependencies : LPCWSTR optional -> Cwstring
# lpServiceStartName : LPCWSTR optional -> Cwstring
# lpPassword : LPCWSTR optional -> Cwstring
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
# Unicode(-W): Cwstring には transcode(UInt16, "...") 等で UTF-16 を渡す。
local ffi = require("ffi")
ffi.cdef[[
void* CreateServiceW(
    void* hSCManager,
    const uint16_t* lpServiceName,
    const uint16_t* lpDisplayName,
    uint32_t dwDesiredAccess,
    uint32_t dwServiceType,
    uint32_t dwStartType,
    uint32_t dwErrorControl,
    const uint16_t* lpBinaryPathName,
    const uint16_t* lpLoadOrderGroup,
    uint32_t* lpdwTagId,
    const uint16_t* lpDependencies,
    const uint16_t* lpServiceStartName,
    const uint16_t* lpPassword);
]]
local advapi32 = ffi.load("advapi32")
-- advapi32.CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
-- hSCManager : SC_HANDLE
-- lpServiceName : LPCWSTR
-- lpDisplayName : LPCWSTR optional
-- dwDesiredAccess : DWORD
-- dwServiceType : ENUM_SERVICE_TYPE
-- dwStartType : SERVICE_START_TYPE
-- dwErrorControl : SERVICE_ERROR
-- lpBinaryPathName : LPCWSTR optional
-- lpLoadOrderGroup : LPCWSTR optional
-- lpdwTagId : DWORD* optional, out
-- lpDependencies : LPCWSTR optional
-- lpServiceStartName : LPCWSTR optional
-- lpPassword : LPCWSTR optional
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
-- Unicode(-W): uint16_t* には UTF-16LE のバッファ(ffi.new("uint16_t[?]", ...))を渡す。
const koffi = require('koffi');
const lib = koffi.load('ADVAPI32.dll');
const CreateServiceW = lib.func('__stdcall', 'CreateServiceW', 'void *', ['void *', 'str16', 'str16', 'uint32_t', 'uint32_t', 'uint32_t', 'uint32_t', 'str16', 'str16', 'uint32_t *', 'str16', 'str16', 'str16']);
// CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
// hSCManager : SC_HANDLE -> 'void *'
// lpServiceName : LPCWSTR -> 'str16'
// lpDisplayName : LPCWSTR optional -> 'str16'
// dwDesiredAccess : DWORD -> 'uint32_t'
// dwServiceType : ENUM_SERVICE_TYPE -> 'uint32_t'
// dwStartType : SERVICE_START_TYPE -> 'uint32_t'
// dwErrorControl : SERVICE_ERROR -> 'uint32_t'
// lpBinaryPathName : LPCWSTR optional -> 'str16'
// lpLoadOrderGroup : LPCWSTR optional -> 'str16'
// lpdwTagId : DWORD* optional, out -> 'uint32_t *'
// lpDependencies : LPCWSTR optional -> 'str16'
// lpServiceStartName : LPCWSTR optional -> 'str16'
// lpPassword : LPCWSTR optional -> 'str16'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("ADVAPI32.dll", {
  CreateServiceW: { parameters: ["pointer", "buffer", "buffer", "u32", "u32", "u32", "u32", "buffer", "buffer", "pointer", "buffer", "buffer", "buffer"], result: "pointer" },
});
// lib.symbols.CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword)
// hSCManager : SC_HANDLE -> "pointer"
// lpServiceName : LPCWSTR -> "buffer"
// lpDisplayName : LPCWSTR optional -> "buffer"
// dwDesiredAccess : DWORD -> "u32"
// dwServiceType : ENUM_SERVICE_TYPE -> "u32"
// dwStartType : SERVICE_START_TYPE -> "u32"
// dwErrorControl : SERVICE_ERROR -> "u32"
// lpBinaryPathName : LPCWSTR optional -> "buffer"
// lpLoadOrderGroup : LPCWSTR optional -> "buffer"
// lpdwTagId : DWORD* optional, out -> "pointer"
// lpDependencies : LPCWSTR optional -> "buffer"
// lpServiceStartName : LPCWSTR optional -> "buffer"
// lpPassword : LPCWSTR optional -> "buffer"
// 文字列は "buffer"。Unicode(-W) は new TextEncoder() ではなく UTF-16LE のバイト列(末尾に \x00\x00)を Uint8Array で渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
void* CreateServiceW(
    void* hSCManager,
    const uint16_t* lpServiceName,
    const uint16_t* lpDisplayName,
    uint32_t dwDesiredAccess,
    uint32_t dwServiceType,
    uint32_t dwStartType,
    uint32_t dwErrorControl,
    const uint16_t* lpBinaryPathName,
    const uint16_t* lpLoadOrderGroup,
    uint32_t* lpdwTagId,
    const uint16_t* lpDependencies,
    const uint16_t* lpServiceStartName,
    const uint16_t* lpPassword);
C, "ADVAPI32.dll");
// $ffi->CreateServiceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword);
// hSCManager : SC_HANDLE
// lpServiceName : LPCWSTR
// lpDisplayName : LPCWSTR optional
// dwDesiredAccess : DWORD
// dwServiceType : ENUM_SERVICE_TYPE
// dwStartType : SERVICE_START_TYPE
// dwErrorControl : SERVICE_ERROR
// lpBinaryPathName : LPCWSTR optional
// lpLoadOrderGroup : LPCWSTR optional
// lpdwTagId : DWORD* optional, out
// lpDependencies : LPCWSTR optional
// lpServiceStartName : LPCWSTR optional
// lpPassword : LPCWSTR optional
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Advapi32 extends StdCallLibrary {
    Advapi32 INSTANCE = Native.load("advapi32", Advapi32.class, W32APIOptions.UNICODE_OPTIONS);
    Pointer CreateServiceW(
        Pointer hSCManager,   // SC_HANDLE
        WString lpServiceName,   // LPCWSTR
        WString lpDisplayName,   // LPCWSTR optional
        int dwDesiredAccess,   // DWORD
        int dwServiceType,   // ENUM_SERVICE_TYPE
        int dwStartType,   // SERVICE_START_TYPE
        int dwErrorControl,   // SERVICE_ERROR
        WString lpBinaryPathName,   // LPCWSTR optional
        WString lpLoadOrderGroup,   // LPCWSTR optional
        IntByReference lpdwTagId,   // DWORD* optional, out
        WString lpDependencies,   // LPCWSTR optional
        WString lpServiceStartName,   // LPCWSTR optional
        WString lpPassword   // LPCWSTR optional
    );
}
// Unicode(-W): WString(入力)/char[](出力)で UTF-16 をマーシャリング。
@[Link("advapi32")]
lib LibADVAPI32
  fun CreateServiceW = CreateServiceW(
    hSCManager : Void*,   # SC_HANDLE
    lpServiceName : UInt16*,   # LPCWSTR
    lpDisplayName : UInt16*,   # LPCWSTR optional
    dwDesiredAccess : UInt32,   # DWORD
    dwServiceType : UInt32,   # ENUM_SERVICE_TYPE
    dwStartType : UInt32,   # SERVICE_START_TYPE
    dwErrorControl : UInt32,   # SERVICE_ERROR
    lpBinaryPathName : UInt16*,   # LPCWSTR optional
    lpLoadOrderGroup : UInt16*,   # LPCWSTR optional
    lpdwTagId : UInt32*,   # DWORD* optional, out
    lpDependencies : UInt16*,   # LPCWSTR optional
    lpServiceStartName : UInt16*,   # LPCWSTR optional
    lpPassword : UInt16*   # LPCWSTR optional
  ) : Void*
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef CreateServiceWNative = Pointer<Void> Function(Pointer<Void>, Pointer<Utf16>, Pointer<Utf16>, Uint32, Uint32, Uint32, Uint32, Pointer<Utf16>, Pointer<Utf16>, Pointer<Uint32>, Pointer<Utf16>, Pointer<Utf16>, Pointer<Utf16>);
typedef CreateServiceWDart = Pointer<Void> Function(Pointer<Void>, Pointer<Utf16>, Pointer<Utf16>, int, int, int, int, Pointer<Utf16>, Pointer<Utf16>, Pointer<Uint32>, Pointer<Utf16>, Pointer<Utf16>, Pointer<Utf16>);
final CreateServiceW = DynamicLibrary.open('ADVAPI32.dll')
    .lookupFunction<CreateServiceWNative, CreateServiceWDart>('CreateServiceW');
// hSCManager : SC_HANDLE -> Pointer<Void>
// lpServiceName : LPCWSTR -> Pointer<Utf16>
// lpDisplayName : LPCWSTR optional -> Pointer<Utf16>
// dwDesiredAccess : DWORD -> Uint32
// dwServiceType : ENUM_SERVICE_TYPE -> Uint32
// dwStartType : SERVICE_START_TYPE -> Uint32
// dwErrorControl : SERVICE_ERROR -> Uint32
// lpBinaryPathName : LPCWSTR optional -> Pointer<Utf16>
// lpLoadOrderGroup : LPCWSTR optional -> Pointer<Utf16>
// lpdwTagId : DWORD* optional, out -> Pointer<Uint32>
// lpDependencies : LPCWSTR optional -> Pointer<Utf16>
// lpServiceStartName : LPCWSTR optional -> Pointer<Utf16>
// lpPassword : LPCWSTR optional -> Pointer<Utf16>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function CreateServiceW(
  hSCManager: THandle;   // SC_HANDLE
  lpServiceName: PWideChar;   // LPCWSTR
  lpDisplayName: PWideChar;   // LPCWSTR optional
  dwDesiredAccess: DWORD;   // DWORD
  dwServiceType: DWORD;   // ENUM_SERVICE_TYPE
  dwStartType: DWORD;   // SERVICE_START_TYPE
  dwErrorControl: DWORD;   // SERVICE_ERROR
  lpBinaryPathName: PWideChar;   // LPCWSTR optional
  lpLoadOrderGroup: PWideChar;   // LPCWSTR optional
  lpdwTagId: Pointer;   // DWORD* optional, out
  lpDependencies: PWideChar;   // LPCWSTR optional
  lpServiceStartName: PWideChar;   // LPCWSTR optional
  lpPassword: PWideChar   // LPCWSTR optional
): THandle; stdcall;
  external 'ADVAPI32.dll' name 'CreateServiceW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "CreateServiceW"
  c_CreateServiceW :: Ptr () -> CWString -> CWString -> Word32 -> Word32 -> Word32 -> Word32 -> CWString -> CWString -> Ptr Word32 -> CWString -> CWString -> CWString -> IO (Ptr ())
-- hSCManager : SC_HANDLE -> Ptr ()
-- lpServiceName : LPCWSTR -> CWString
-- lpDisplayName : LPCWSTR optional -> CWString
-- dwDesiredAccess : DWORD -> Word32
-- dwServiceType : ENUM_SERVICE_TYPE -> Word32
-- dwStartType : SERVICE_START_TYPE -> Word32
-- dwErrorControl : SERVICE_ERROR -> Word32
-- lpBinaryPathName : LPCWSTR optional -> CWString
-- lpLoadOrderGroup : LPCWSTR optional -> CWString
-- lpdwTagId : DWORD* optional, out -> Ptr Word32
-- lpDependencies : LPCWSTR optional -> CWString
-- lpServiceStartName : LPCWSTR optional -> CWString
-- lpPassword : LPCWSTR optional -> CWString
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let createservicew =
  foreign "CreateServiceW"
    ((ptr void) @-> (ptr uint16_t) @-> (ptr uint16_t) @-> uint32_t @-> uint32_t @-> uint32_t @-> uint32_t @-> (ptr uint16_t) @-> (ptr uint16_t) @-> (ptr uint32_t) @-> (ptr uint16_t) @-> (ptr uint16_t) @-> (ptr uint16_t) @-> returning (ptr void))
(* hSCManager : SC_HANDLE -> (ptr void) *)
(* lpServiceName : LPCWSTR -> (ptr uint16_t) *)
(* lpDisplayName : LPCWSTR optional -> (ptr uint16_t) *)
(* dwDesiredAccess : DWORD -> uint32_t *)
(* dwServiceType : ENUM_SERVICE_TYPE -> uint32_t *)
(* dwStartType : SERVICE_START_TYPE -> uint32_t *)
(* dwErrorControl : SERVICE_ERROR -> uint32_t *)
(* lpBinaryPathName : LPCWSTR optional -> (ptr uint16_t) *)
(* lpLoadOrderGroup : LPCWSTR optional -> (ptr uint16_t) *)
(* lpdwTagId : DWORD* optional, out -> (ptr uint32_t) *)
(* lpDependencies : LPCWSTR optional -> (ptr uint16_t) *)
(* lpServiceStartName : LPCWSTR optional -> (ptr uint16_t) *)
(* lpPassword : LPCWSTR optional -> (ptr uint16_t) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library advapi32 (t "ADVAPI32.dll"))
(cffi:use-foreign-library advapi32)

(cffi:defcfun ("CreateServiceW" create-service-w :convention :stdcall) :pointer
  (h-scmanager :pointer)   ; SC_HANDLE
  (lp-service-name (:string :encoding :utf-16le))   ; LPCWSTR
  (lp-display-name (:string :encoding :utf-16le))   ; LPCWSTR optional
  (dw-desired-access :uint32)   ; DWORD
  (dw-service-type :uint32)   ; ENUM_SERVICE_TYPE
  (dw-start-type :uint32)   ; SERVICE_START_TYPE
  (dw-error-control :uint32)   ; SERVICE_ERROR
  (lp-binary-path-name (:string :encoding :utf-16le))   ; LPCWSTR optional
  (lp-load-order-group (:string :encoding :utf-16le))   ; LPCWSTR optional
  (lpdw-tag-id :pointer)   ; DWORD* optional, out
  (lp-dependencies (:string :encoding :utf-16le))   ; LPCWSTR optional
  (lp-service-start-name (:string :encoding :utf-16le))   ; LPCWSTR optional
  (lp-password (:string :encoding :utf-16le)))   ; LPCWSTR optional
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $CreateServiceW = Win32::API::More->new('ADVAPI32',
    'HANDLE CreateServiceW(HANDLE hSCManager, LPCWSTR lpServiceName, LPCWSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, LPCWSTR lpLoadOrderGroup, LPVOID lpdwTagId, LPCWSTR lpDependencies, LPCWSTR lpServiceStartName, LPCWSTR lpPassword)');
# my $ret = $CreateServiceW->Call($hSCManager, $lpServiceName, $lpDisplayName, $dwDesiredAccess, $dwServiceType, $dwStartType, $dwErrorControl, $lpBinaryPathName, $lpLoadOrderGroup, $lpdwTagId, $lpDependencies, $lpServiceStartName, $lpPassword);
# hSCManager : SC_HANDLE -> HANDLE
# lpServiceName : LPCWSTR -> LPCWSTR
# lpDisplayName : LPCWSTR optional -> LPCWSTR
# dwDesiredAccess : DWORD -> DWORD
# dwServiceType : ENUM_SERVICE_TYPE -> DWORD
# dwStartType : SERVICE_START_TYPE -> DWORD
# dwErrorControl : SERVICE_ERROR -> DWORD
# lpBinaryPathName : LPCWSTR optional -> LPCWSTR
# lpLoadOrderGroup : LPCWSTR optional -> LPCWSTR
# lpdwTagId : DWORD* optional, out -> LPVOID
# lpDependencies : LPCWSTR optional -> LPCWSTR
# lpServiceStartName : LPCWSTR optional -> LPCWSTR
# lpPassword : LPCWSTR optional -> LPCWSTR
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# Unicode(-W): LPCWSTR/LPWSTR は Win32::API が UTF-16 変換を行う。

関連項目

文字セット違い
公式の関連項目
使用する型