+BOOLEAN
+IsValidPath(
+ IN PCWSTR InstallDir)
+{
+ UINT i, Length;
+
+ Length = wcslen(InstallDir);
+
+ // TODO: Add check for 8.3 too.
+
+ /* Path must be at least 2 characters long */
+// if (Length < 2)
+// return FALSE;
+
+ /* Path must start with a backslash */
+// if (InstallDir[0] != L'\\')
+// return FALSE;
+
+ /* Path must not end with a backslash */
+ if (InstallDir[Length - 1] == L'\\')
+ return FALSE;
+
+ /* Path must not contain whitespace characters */
+ for (i = 0; i < Length; i++)
+ {
+ if (isspace(InstallDir[i]))
+ return FALSE;
+ }
+
+ /* Path component must not end with a dot */
+ for (i = 0; i < Length; i++)
+ {
+ if (InstallDir[i] == L'\\' && i > 0)
+ {
+ if (InstallDir[i - 1] == L'.')
+ return FALSE;
+ }
+ }
+
+ if (InstallDir[Length - 1] == L'.')
+ return FALSE;
+
+ return TRUE;
+}
+
+NTSTATUS
+ConcatPaths(
+ IN OUT PWSTR PathElem1,
+ IN SIZE_T cchPathSize,
+ IN PCWSTR PathElem2 OPTIONAL)
+{
+ NTSTATUS Status;
+ SIZE_T cchPathLen;
+
+ if (!PathElem2)
+ return STATUS_SUCCESS;
+ if (cchPathSize <= 1)
+ return STATUS_SUCCESS;
+
+ cchPathLen = min(cchPathSize, wcslen(PathElem1));
+
+ if (PathElem2[0] != L'\\' && cchPathLen > 0 && PathElem1[cchPathLen-1] != L'\\')
+ {
+ /* PathElem2 does not start with '\' and PathElem1 does not end with '\' */
+ Status = RtlStringCchCatW(PathElem1, cchPathSize, L"\\");
+ if (!NT_SUCCESS(Status))
+ return Status;
+ }
+ else if (PathElem2[0] == L'\\' && cchPathLen > 0 && PathElem1[cchPathLen-1] == L'\\')
+ {
+ /* PathElem2 starts with '\' and PathElem1 ends with '\' */
+ while (*PathElem2 == L'\\')
+ ++PathElem2; // Skip any backslash
+ }
+ Status = RtlStringCchCatW(PathElem1, cchPathSize, PathElem2);
+ return Status;
+}
+
+//
+// NOTE: It may be possible to merge both DoesPathExist and DoesFileExist...
+//
+BOOLEAN
+DoesPathExist(
+ IN HANDLE RootDirectory OPTIONAL,
+ IN PCWSTR PathName)
+{
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+
+ RtlInitUnicodeString(&Name, PathName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ RootDirectory,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
+ if (NT_SUCCESS(Status))
+ NtClose(FileHandle);
+ else
+ DPRINT1("Failed to open directory %wZ, Status 0x%08lx\n", &Name, Status);
+
+ return NT_SUCCESS(Status);
+}
+