ReactOS  0.4.14-dev-608-gd495a4f
setupldr.c
Go to the documentation of this file.
1 /*
2  * PROJECT: FreeLoader
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Windows-compatible NT OS Setup Loader.
5  * COPYRIGHT: Copyright 2009-2019 Aleksey Bragin <aleksey@reactos.org>
6  */
7 
8 #include <freeldr.h>
9 #include <ndk/ldrtypes.h>
10 #include <arc/setupblk.h>
11 #include "winldr.h"
12 #include "inffile.h"
13 
14 #include <debug.h>
15 DBG_DEFAULT_CHANNEL(WINDOWS);
16 
17 #define TAG_BOOT_OPTIONS 'pOtB'
18 
19 // TODO: Move to .h
20 VOID
22  IN USHORT VersionToBoot,
23  OUT PLOADER_PARAMETER_BLOCK* OutLoaderBlock);
24 
25 static VOID
27 {
28  INFCONTEXT InfContext;
29  PCSTR AnsiName, OemName, LangName;
30 
31  /* Get ANSI codepage file */
32  if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext))
33  {
34  ERR("Failed to find 'NLS/AnsiCodepage'\n");
35  return;
36  }
37  if (!InfGetDataField(&InfContext, 1, &AnsiName))
38  {
39  ERR("Failed to get load options\n");
40  return;
41  }
42 
43  /* Get OEM codepage file */
44  if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext))
45  {
46  ERR("Failed to find 'NLS/AnsiCodepage'\n");
47  return;
48  }
49  if (!InfGetDataField(&InfContext, 1, &OemName))
50  {
51  ERR("Failed to get load options\n");
52  return;
53  }
54 
55  if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext))
56  {
57  ERR("Failed to find 'NLS/AnsiCodepage'\n");
58  return;
59  }
60  if (!InfGetDataField(&InfContext, 1, &LangName))
61  {
62  ERR("Failed to get load options\n");
63  return;
64  }
65 
66  TRACE("NLS data '%s' '%s' '%s'\n", AnsiName, OemName, LangName);
67 
68 #if DBG
69  {
70  BOOLEAN Success = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
71  (VOID)Success;
72  TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
73  }
74 #else
75  WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
76 #endif
77 
78  /* TODO: Load OEM HAL font */
79  // Value "OemHalFont"
80 }
81 
82 static
83 BOOLEAN
85  IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
86  IN HINF InfHandle,
88 {
89  INFCONTEXT InfContext;
92  PVOID PhysicalBase;
93  CHAR ErrataFilePath[MAX_PATH];
94 
95  /* Retrieve the INF file name value */
96  if (!InfFindFirstLine(InfHandle, "BiosInfo", "InfName", &InfContext))
97  {
98  WARN("Failed to find 'BiosInfo/InfName'\n");
99  return FALSE;
100  }
101  if (!InfGetDataField(&InfContext, 1, &FileName))
102  {
103  WARN("Failed to read 'InfName' value\n");
104  return FALSE;
105  }
106 
107  RtlStringCbCopyA(ErrataFilePath, sizeof(ErrataFilePath), SystemRoot);
108  RtlStringCbCatA(ErrataFilePath, sizeof(ErrataFilePath), FileName);
109 
110  /* Load the INF file */
111  PhysicalBase = WinLdrLoadModule(ErrataFilePath, &FileSize, LoaderRegistryData);
112  if (!PhysicalBase)
113  {
114  WARN("Could not load '%s'\n", ErrataFilePath);
115  return FALSE;
116  }
117 
118  LoaderBlock->Extension->EmInfFileImage = PaToVa(PhysicalBase);
119  LoaderBlock->Extension->EmInfFileSize = FileSize;
120 
121  return TRUE;
122 }
123 
124 static VOID
125 SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead, HINF InfHandle, PCSTR SearchPath)
126 {
127  INFCONTEXT InfContext, dirContext;
129  PCSTR Media, DriverName, dirIndex, ImagePath;
130  WCHAR ServiceName[256];
131  WCHAR ImagePathW[256];
132 
133  /* Open inf section */
134  if (!InfFindFirstLine(InfHandle, "SourceDisksFiles", NULL, &InfContext))
135  return;
136 
137  /* Load all listed boot drivers */
138  do
139  {
140  if (InfGetDataField(&InfContext, 7, &Media) &&
141  InfGetDataField(&InfContext, 0, &DriverName) &&
142  InfGetDataField(&InfContext, 13, &dirIndex))
143  {
144  if ((strcmp(Media, "x") == 0) &&
145  InfFindFirstLine(InfHandle, "Directories", dirIndex, &dirContext) &&
146  InfGetDataField(&dirContext, 1, &ImagePath))
147  {
148  /* Convert name to widechar */
149  swprintf(ServiceName, L"%S", DriverName);
150 
151  /* Prepare image path */
152  swprintf(ImagePathW, L"%S", ImagePath);
153  wcscat(ImagePathW, L"\\");
154  wcscat(ImagePathW, ServiceName);
155 
156  /* Remove .sys extension */
157  ServiceName[wcslen(ServiceName) - 4] = 0;
158 
159  /* Add it to the list */
160  Success = WinLdrAddDriverToList(BootDriverListHead,
161  L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
162  ImagePathW,
163  ServiceName);
164  if (!Success)
165  {
166  ERR("Could not add boot driver '%s', '%s'\n", SearchPath, DriverName);
167  return;
168  }
169  }
170  }
171  } while (InfFindNextLine(&InfContext, &InfContext));
172 }
173 
174 
175 /* SETUP STARTER **************************************************************/
176 
179  IN ULONG Argc,
180  IN PCHAR Argv[],
181  IN PCHAR Envp[])
182 {
184  PCSTR ArgValue;
186  PCHAR File;
188  CHAR BootPath[MAX_PATH];
189  CHAR BootOptions2[256];
190  PCSTR LoadOptions;
192  BOOLEAN BootFromFloppy;
194  ULONG i, ErrorLine;
195  HINF InfHandle;
196  INFCONTEXT InfContext;
197  PLOADER_PARAMETER_BLOCK LoaderBlock;
198  PSETUP_LOADER_BLOCK SetupBlock;
199  PCSTR SystemPath;
200 
201  static PCSTR SourcePaths[] =
202  {
203  "", /* Only for floppy boot */
204 #if defined(_M_IX86)
205  "I386\\",
206 #elif defined(_M_MPPC)
207  "PPC\\",
208 #elif defined(_M_MRX000)
209  "MIPS\\",
210 #endif
211  "reactos\\",
212  NULL
213  };
214 
215  /* Retrieve the (mandatory) system partition */
216  SystemPartition = GetArgumentValue(Argc, Argv, "SystemPartition");
218  {
219  ERR("No 'SystemPartition' specified, aborting!\n");
220  return EINVAL;
221  }
222 
223  UiDrawStatusText("Setup is loading...");
224 
225  UiDrawBackdrop();
226  UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup...");
227 
228  /* Retrieve the system path */
229  *BootPath = ANSI_NULL;
230  ArgValue = GetArgumentValue(Argc, Argv, "SystemPath");
231  if (ArgValue)
232  {
233  RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
234  }
235  else
236  {
237  /*
238  * IMPROVE: I don't want to use the SystemPartition here as a
239  * default choice because I can do it after (see few lines below).
240  * Instead I reset BootPath here so that we can build the full path
241  * using the general code from below.
242  */
243  // RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
244  *BootPath = ANSI_NULL;
245  }
246 
247  /*
248  * Check whether BootPath is a full path
249  * and if not, create a full boot path.
250  *
251  * See FsOpenFile for the technique used.
252  */
253  if (strrchr(BootPath, ')') == NULL)
254  {
255  /* Temporarily save the boot path */
256  RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
257 
258  /* This is not a full path: prepend the SystemPartition */
259  RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
260 
261  /* Append a path separator if needed */
262  if (*FileName != '\\' && *FileName != '/')
263  RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
264 
265  /* Append the remaining path */
266  RtlStringCbCatA(BootPath, sizeof(BootPath), FileName);
267  }
268 
269  /* Append a path separator if needed */
270  if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\')
271  RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
272 
273  TRACE("BootPath: '%s'\n", BootPath);
274 
275  /* Retrieve the boot options */
276  *BootOptions2 = ANSI_NULL;
277  ArgValue = GetArgumentValue(Argc, Argv, "Options");
278  if (ArgValue && *ArgValue)
279  RtlStringCbCopyA(BootOptions2, sizeof(BootOptions2), ArgValue);
280 
281  TRACE("BootOptions: '%s'\n", BootOptions2);
282 
283  /* Check if a ramdisk file was given */
284  File = strstr(BootOptions2, "/RDPATH=");
285  if (File)
286  {
287  /* Load the ramdisk */
288  Status = RamDiskInitialize(FALSE, BootOptions2, SystemPartition);
289  if (Status != ESUCCESS)
290  {
291  File += 8;
292  UiMessageBox("Failed to load RAM disk file '%.*s'",
293  strcspn(File, " \t"), File);
294  return Status;
295  }
296  }
297 
298  /* Check if we booted from floppy */
299  BootFromFloppy = strstr(BootPath, "fdisk") != NULL;
300 
301  /* Open 'txtsetup.sif' from any of source paths */
302  File = BootPath + strlen(BootPath);
303  for (i = BootFromFloppy ? 0 : 1; ; i++)
304  {
305  SystemPath = SourcePaths[i];
306  if (!SystemPath)
307  {
308  UiMessageBox("Failed to open txtsetup.sif");
309  return ENOENT;
310  }
311  RtlStringCbCopyA(File, sizeof(BootPath) - (File - BootPath)*sizeof(CHAR), SystemPath);
312  RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
313  RtlStringCbCatA(FileName, sizeof(FileName), "txtsetup.sif");
314  if (InfOpenFile(&InfHandle, FileName, &ErrorLine))
315  {
316  break;
317  }
318  }
319 
320  TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
321 
322  /* Get load options - debug and non-debug */
323  if (!InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext))
324  {
325  ERR("Failed to find 'SetupData/OsLoadOptions'\n");
326  return EINVAL;
327  }
328 
329  if (!InfGetDataField(&InfContext, 1, &LoadOptions))
330  {
331  ERR("Failed to get load options\n");
332  return EINVAL;
333  }
334 
335 #if DBG
336  /* Get debug load options and use them */
337  if (InfFindFirstLine(InfHandle, "SetupData", "DbgOsLoadOptions", &InfContext))
338  {
339  PCSTR DbgLoadOptions;
340 
341  if (InfGetDataField(&InfContext, 1, &DbgLoadOptions))
342  LoadOptions = DbgLoadOptions;
343  }
344 #endif
345 
346  /* Copy LoadOptions (original string will be freed) */
347  BootOptions = FrLdrTempAlloc(strlen(LoadOptions) + 1, TAG_BOOT_OPTIONS);
349  strcpy(BootOptions, LoadOptions);
350 
351  TRACE("BootOptions: '%s'\n", BootOptions);
352 
353  /* Allocate and minimally-initialize the Loader Parameter Block */
354  AllocateAndInitLPB(_WIN32_WINNT_WS03, &LoaderBlock);
355 
356  /* Allocate and initialize setup loader block */
357  SetupBlock = &WinLdrSystemBlock->SetupBlock;
358  LoaderBlock->SetupLdrBlock = SetupBlock;
359 
360  /* Set textmode setup flag */
361  SetupBlock->Flags = SETUPLDR_TEXT_MODE;
362 
363  /* Load the system hive "setupreg.hiv" for setup */
364  UiDrawBackdrop();
365  UiDrawProgressBarCenter(15, 100, "Loading setup system hive...");
366  Success = WinLdrInitSystemHive(LoaderBlock, BootPath, TRUE);
367  TRACE("Setup SYSTEM hive %s\n", (Success ? "loaded" : "not loaded"));
368  /* Bail out if failure */
369  if (!Success)
370  return ENOEXEC;
371 
372  /* Load NLS data, they are in the System32 directory of the installation medium */
373  RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
374  RtlStringCbCatA(FileName, sizeof(FileName), "system32\\");
375  SetupLdrLoadNlsData(LoaderBlock, InfHandle, FileName);
376 
377  /* Load the Firmware Errata file from the installation medium */
378  Success = SetupLdrInitErrataInf(LoaderBlock, InfHandle, BootPath);
379  TRACE("Firmware Errata file %s\n", (Success ? "loaded" : "not loaded"));
380  /* Not necessarily fatal if not found - carry on going */
381 
382  // UiDrawStatusText("Press F6 if you need to install a 3rd-party SCSI or RAID driver...");
383 
384  /* Get a list of boot drivers */
385  SetupLdrScanBootDrivers(&LoaderBlock->BootDriverListHead, InfHandle, BootPath);
386 
387  /* Close the inf file */
388  InfCloseFile(InfHandle);
389 
390  UiDrawStatusText("The Setup program is starting...");
391 
392  /* Load ReactOS Setup */
394  LoaderBlock,
395  BootOptions,
396  BootPath,
397  TRUE);
398 }
signed char * PCHAR
Definition: retypes.h:7
#define IN
Definition: typedefs.h:38
ARC_STATUS RamDiskInitialize(IN BOOLEAN InitRamDisk, IN PCSTR LoadOptions OPTIONAL, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:204
#define TRUE
Definition: types.h:120
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
BOOLEAN InfFindNextLine(PINFCONTEXT ContextIn, PINFCONTEXT ContextOut)
Definition: inffile.c:1107
Definition: arc.h:32
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static VOID SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead, HINF InfHandle, PCSTR SearchPath)
Definition: setupldr.c:125
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
Definition: arc.h:39
static VOID SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, PCSTR SearchPath)
Definition: setupldr.c:26
char CHAR
Definition: xmlstorage.h:175
#define WARN(fmt,...)
Definition: debug.h:111
ULONG ARC_STATUS
Definition: arc.h:4
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
DBG_DEFAULT_CHANNEL(WINDOWS)
BOOLEAN InfGetDataField(PINFCONTEXT Context, ULONG FieldIndex, PWCHAR *Data)
Definition: infrosget.c:127
#define SearchPath
Definition: winbase.h:3734
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _SETUP_LOADER_BLOCK * SetupLdrBlock
Definition: arc.h:511
#define ANSI_NULL
_In_opt_ PVOID _In_ PCSTR File
Definition: iofuncs.h:615
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:320
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define TRACE(s)
Definition: solgame.cpp:4
LPTSTR ServiceName
Definition: ServiceMain.c:15
static const WCHAR SystemRoot[]
Definition: reg.c:38
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
LIST_ENTRY BootDriverListHead
Definition: arc.h:495
static PPARTENTRY SystemPartition
Definition: usetup.c:61
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID UiDrawStatusText(PCSTR StatusText)
Definition: ui.c:249
BOOLEAN WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR DirectoryPath, IN PCSTR AnsiFileName, IN PCSTR OemFileName, IN PCSTR LanguageFileName)
Definition: wlregistry.c:301
static const WCHAR L[]
Definition: oid.c:1250
VOID InfCloseFile(HINF InfHandle)
Definition: inffile.c:1028
#define VOID
Definition: acefi.h:82
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
Definition: typedefs.h:117
VOID UiDrawBackdrop(VOID)
Definition: ui.c:214
Status
Definition: gdiplustypes.h:24
SETUP_LOADER_BLOCK SetupBlock
Definition: winldr.h:50
#define ERR(fmt,...)
Definition: debug.h:109
struct _FileName FileName
Definition: fatprocs.h:884
#define TAG_BOOT_OPTIONS
Definition: setupldr.c:17
BOOLEAN WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, PWSTR RegistryPath, PWSTR ImagePath, PWSTR ServiceName)
Definition: wlregistry.c:768
#define SETUPLDR_TEXT_MODE
Definition: setupblk.h:7
unsigned short USHORT
Definition: pedump.c:61
PVOID WinLdrLoadModule(PCSTR ModuleName, PULONG Size, TYPE_OF_MEMORY MemoryType)
Definition: winldr.c:355
signed char * PSTR
Definition: retypes.h:7
ARC_STATUS LoadAndBootWindowsCommon(USHORT OperatingSystemVersion, PLOADER_PARAMETER_BLOCK LoaderBlock, PCSTR BootOptions, PCSTR BootPath, BOOLEAN Setup)
Definition: winldr.c:908
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
Definition: arc.h:46
ARC_STATUS LoadReactOSSetup(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: setupldr.c:178
static BOOLEAN SetupLdrInitErrataInf(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN HINF InfHandle, IN PCSTR SystemRoot)
Definition: setupldr.c:84
#define OUT
Definition: typedefs.h:39
FORCEINLINE PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
VOID AllocateAndInitLPB(IN USHORT VersionToBoot, OUT PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
Definition: winldr.c:34
BOOLEAN InfFindFirstLine(HINF InfHandle, PCSTR Section, PCSTR Key, PINFCONTEXT Context)
Definition: inffile.c:1050
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
Definition: arc.h:47
const char * PCSTR
Definition: typedefs.h:51
Definition: File.h:15
PCHAR GetArgumentValue(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR ArgumentName)
Definition: arcsupp.c:41
IN PDCB IN POEM_STRING OemName
Definition: fatprocs.h:1294
BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot, IN BOOLEAN Setup)
Definition: wlregistry.c:123
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOLEAN InfOpenFile(PHINF InfHandle, PCSTR FileName, PULONG ErrorLine)
Definition: inffile.c:918
VOID UiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText)
Definition: ui.c:346
PLOADER_SYSTEM_BLOCK WinLdrSystemBlock
Definition: winldr.c:27
NTSTRSAFEAPI RtlStringCbCatA(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:625