[flutter_tools] tool exit from flutter create when provided just a drive letter (#106451)

diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart
index 9d272b7..02e37fa 100644
--- a/packages/flutter_tools/lib/src/commands/create_base.dart
+++ b/packages/flutter_tools/lib/src/commands/create_base.dart
@@ -132,9 +132,27 @@
     );
   }
 
+  /// Pattern for a Windows file system drive (e.g. "D:").
+  ///
+  /// `dart:io` does not recognize strings matching this pattern as absolute
+  /// paths, as they have no top level back-slash; however, users often specify
+  /// this
+  @visibleForTesting
+  static final RegExp kWindowsDrivePattern = RegExp(r'^[a-zA-Z]:$');
+
   /// The output directory of the command.
   @protected
+  @visibleForTesting
   Directory get projectDir {
+    final String argProjectDir = argResults!.rest.first;
+    if (globals.platform.isWindows && kWindowsDrivePattern.hasMatch(argProjectDir)) {
+      throwToolExit(
+        'You attempted to create a flutter project at the path "$argProjectDir", which is the name of a drive. This '
+        'is usually a mistake--you probably want to specify a containing directory, like "$argProjectDir\\app_name". '
+        'If you really want it at the drive root, re-run the command with the root directory after the drive, like '
+        '"$argProjectDir\\".',
+      );
+    }
     return globals.fs.directory(argResults!.rest.first);
   }
 
diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
index 310dddb..a09b4ef 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:async';
 import 'dart:convert';
+import 'dart:io' as io;
 
 import 'package:args/command_runner.dart';
 import 'package:file_testing/file_testing.dart';
@@ -113,6 +114,37 @@
     expect(Uuid.isValidUUID(fromString: identifier), isTrue);
   });
 
+  testUsingContext('tool exits on Windows if given a drive letter without a path', () async {
+    // Must use LocalFileSystem as it is dependent on dart:io handling of
+    // Windows paths, which the MemoryFileSystem does not implement
+    final Directory workingDir = globals.fs.directory(r'X:\path\to\working\dir');
+    // Must use [io.IOOverrides] as directory.absolute depends on Directory.current
+    // from dart:io.
+    await io.IOOverrides.runZoned<Future<void>>(
+      () async {
+        // Verify IOOverrides is working
+        expect(io.Directory.current, workingDir);
+        final CreateCommand command = CreateCommand();
+        final CommandRunner<void> runner = createTestCommandRunner(command);
+        const String driveName = 'X:';
+        await expectToolExitLater(
+          runner.run(<String>[
+            'create',
+            '--project-name',
+            'test_app',
+            '--offline',
+            driveName,
+          ]),
+          contains('You attempted to create a flutter project at the path "$driveName"'),
+        );
+      },
+      getCurrentDirectory: () => workingDir,
+    );
+  }, overrides: <Type, Generator>{
+    Logger: () => BufferLogger.test(),
+  }, skip: !io.Platform.isWindows // [intended] relies on Windows file system
+  );
+
   // Verify that we create a default project ('app') that is
   // well-formed.
   testUsingContext('can create a default project', () async {
diff --git a/packages/flutter_tools/test/general.shard/create_config_test.dart b/packages/flutter_tools/test/general.shard/create_config_test.dart
index 1699de1..4d41ec9 100644
--- a/packages/flutter_tools/test/general.shard/create_config_test.dart
+++ b/packages/flutter_tools/test/general.shard/create_config_test.dart
@@ -19,4 +19,13 @@
 
     expect(isValidPackageName('Foo_bar'), false);
   });
+
+  test('kWindowsDrivePattern', () {
+    expect(CreateBase.kWindowsDrivePattern.hasMatch(r'D:\'), isFalse);
+    expect(CreateBase.kWindowsDrivePattern.hasMatch(r'z:\'), isFalse);
+    expect(CreateBase.kWindowsDrivePattern.hasMatch(r'\d:'), isFalse);
+    expect(CreateBase.kWindowsDrivePattern.hasMatch(r'ef:'), isFalse);
+    expect(CreateBase.kWindowsDrivePattern.hasMatch(r'D:'), isTrue);
+    expect(CreateBase.kWindowsDrivePattern.hasMatch(r'c:'), isTrue);
+  });
 }