Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add IsWindows8OrGreater() and GetCurrentPackageFullName() APIs #943

Closed
halildurmus opened this issue Dec 31, 2024 · 4 comments · Fixed by #944
Closed

feat: add IsWindows8OrGreater() and GetCurrentPackageFullName() APIs #943

halildurmus opened this issue Dec 31, 2024 · 4 comments · Fixed by #944
Assignees
Labels
feature A new feature or request package: win32 Issue with package:win32

Comments

@halildurmus
Copy link
Owner

halildurmus commented Dec 31, 2024

I have a concrete use-case at YehudaKremer/msix#292: Determining if your app is running with package identity:

#include <windows.h>
#include <appmodel.h>
#include <atlbase.h>
#include <VersionHelpers.h>

std::optional<bool> NativePlugin::checkIdentity() {
  if (!IsWindows8OrGreater()) return false;
  uint32_t length = 0;
  auto error = GetCurrentPackageFullName(&length, nullptr);
  if (error == APPMODEL_ERROR_NO_PACKAGE) {
    return false;
  } else if (error != ERROR_INSUFFICIENT_BUFFER) {
    return std::nullopt;
  }
  std::vector<wchar_t> fullName(length);
  error = GetCurrentPackageFullName(&length, fullName.data());
  if (error != ERROR_SUCCESS) return std::nullopt;
  return true;
}

Seems this package doesn't include <appmodel.h>, so I can't use IsWindows8OrGreater() or GetCurrentPackageFullName().

Originally posted by @Levi-Lesches in #819 (comment)

@halildurmus halildurmus added the feature A new feature or request label Dec 31, 2024
@halildurmus halildurmus self-assigned this Dec 31, 2024
@halildurmus halildurmus added the package: win32 Issue with package:win32 label Dec 31, 2024
@Levi-Lesches
Copy link

I was trying this myself, and ran into an issue. IsWindows8OrGreater is inline, and the function it calls, IsWindowsVersionOrGreater, is also inline! How can I call these in Dart without re-implementing them? I checked the kernel32.dll and sure enough, they're not even in there. Should I just translate the function to Dart FFI directly?

@halildurmus
Copy link
Owner Author

halildurmus commented Dec 31, 2024

I was trying this myself, and ran into an issue. IsWindows8OrGreater is inline, and the function it calls, IsWindowsVersionOrGreater, is also inline! How can I call these in Dart without re-implementing them?

You need to implement inline functions yourself, you can't wrap them with FFI. See packages/win32/lib/src/inline.dart file which implements several inline functions:

int IsWindowsVersionOrGreater(

Here's the implementation of the IsWindows8OrGreater:

const _WIN32_WINNT_WIN8 = 0x0602;

/// Indicates if the current OS version matches, or is greater than, the
/// Windows 8 version.
///
/// {@category version}
int IsWindows8OrGreater() => IsWindowsVersionOrGreater(
      HIBYTE(_WIN32_WINNT_WIN8),
      LOBYTE(_WIN32_WINNT_WIN8),
      0,
    );

And GetCurrentPackageFullName:

final _kernel32 = DynamicLibrary.open('kernel32.dll');

/// Gets the package full name for the calling process.
///
/// ```c
/// LONG GetCurrentPackageFullName(
///   UINT32 *packageFullNameLength,
///   PWSTR  packageFullName
/// );
/// ```
/// {@category kernel32}
int GetCurrentPackageFullName(Pointer<Uint32> packageFullNameLength,
        Pointer<Utf16> packageFullName) =>
    _GetCurrentPackageFullName(packageFullNameLength, packageFullName);

final _GetCurrentPackageFullName = _kernel32.lookupFunction<
    Uint32 Function(
        Pointer<Uint32> packageFullNameLength, Pointer<Utf16> packageFullName),
    int Function(Pointer<Uint32> packageFullNameLength,
        Pointer<Utf16> packageFullName)>('GetCurrentPackageFullName');

I'll probably add these to the package tomorrow.

I didn't test it but this should work:

import 'dart:ffi';

import 'package:ffi/ffi.dart';
import 'package:win32/win32.dart';

bool checkIdentity() {
  if (IsWindows8OrGreater() == FALSE) return false;
  final length = calloc<Uint32>();
  try {
    var error = GetCurrentPackageFullName(length, nullptr);
    if (error == WIN32_ERROR.APPMODEL_ERROR_NO_PACKAGE) {
      return false;
    } else if (error != WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER) {
      return false;
    }
    final packageFullName = wsalloc(length.value);
    error = GetCurrentPackageFullName(length, packageFullName);
    free(packageFullName);
    return error == WIN32_ERROR.ERROR_SUCCESS;
  } finally {
    free(length);
  }
}

void main() {
  if (checkIdentity()) {
    print('This is a Windows 8+ Store App');
  } else {
    print('This is not a Windows 8+ Store App');
  }
}

@Levi-Lesches
Copy link

It works, thanks!

image

@Levi-Lesches
Copy link

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A new feature or request package: win32 Issue with package:win32
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants