Algo había cambiado en Win10 y como es una API indocumentada M$ no tiene porqué informar nada. Busqué en la red, pero no encontré nada, de esta forma tocaba usar el debugger y comparar direcciones de memoria de las API. El resultado es que Win10 usa la API exportada en KernelBase.dll y no la clásica Kernell32.dll. Una vez conocido este detalle el hook vuelve a funcionar.
Voy a poner un ejemplo hecho en delphi Berlin para resarcir la duda y aclarar la definición de esa API en delphi:
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, APIHook, ShellAPI; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; // Defino esta estructura para los que quieran probar en delphi 7 PSTARTUPINFOW = ^_STARTUPINFOW; _STARTUPINFOW = record cb: DWORD; lpReserved: PWideChar; lpDesktop: PWideChar; lpTitle: PWideChar; dwX: DWORD; dwY: DWORD; dwXSize: DWORD; dwYSize: DWORD; dwXCountChars: DWORD; dwYCountChars: DWORD; dwFillAttribute: DWORD; dwFlags: DWORD; wShowWindow: Word; cbReserved2: Word; lpReserved2: PByte; hStdInput: THandle; hStdOutput: THandle; hStdError: THandle; end; PCreateProcessInternalW = function(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR; lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR; lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall; var OldCreateProcessInternalW: PCreateProcessInternalW = nil; var Form1: TForm1; implementation {$R *.dfm} function NewCreateProcessInternalW(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR; lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR; lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall; begin Result:= FALSE; Winapi.Windows.Beep(500, 100); exit; // Result:= OldCreateProcessInternalW(hToken, pApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, // dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken); end; //---------------------------------------------------------------------------- // Instalando los Hooks a las API procedure InstallHooks; begin InstallHook(@NewCreateProcessInternalW, @OldCreateProcessInternalW, 'Kernelbase.dll', 'CreateProcessInternalW', true); end; procedure UnInstallHooks; begin UnInstallHook(@OldCreateProcessInternalW, 'KernelBase.dll', 'CreateProcessInternalW'); end; procedure Execute(ProcessName: AnsiString); var si: TStartupInfoA; pi: TProcessInformation; begin ZeroMemory(@si, SizeOf(TStartupInfoA)); si.cb := SizeOf(TStartupInfoA); si.dwFlags:= STARTF_USESHOWWINDOW; si.wShowWindow:= SW_SHOW; CreateProcessA(nil, PAnsiChar(ProcessName), nil, nil, false, 0, nil, nil, si, pi); end; procedure TForm1.Button1Click(Sender: TObject); begin InstallHooks; Execute('cmd.exe'); ShellExecute(0,'open','cmd.exe', nil, nil, SW_SHOW); UnInstallHooks; end; end. end.
El ejemplo muestra como un hook a la API CreateProcessInternalW es capaz de interceptar distintas formas de ejecutar un proceso.
El misterio queda resuelto.
Saludos.