Calling GetDiskFreeSpaceExW api from WindowsPhone 8.1 - c#

I am trying to call GetDiskFreeSpaceExW Win Api call in my Windows Phone 8.1 application, and I am always failing the certification.
This function is in the List of supported Win32 APIs :
https://msdn.microsoft.com/en-us/library/windows/apps/jj662956(v=vs.105).aspx#BKMK_ListofsupportedWin32APIs
My call:
[DllImport("api-ms-win-core-file-l1-2-0.dll", SetLastError = true)]
static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
out ulong lpFreeBytesAvailable,
out ulong lpTotalNumberOfBytes,
out ulong lpTotalNumberOfFreeBytes);
Erorr:
This API is not supported for this application type -
Api=GetDiskFreeSpaceEx. Module=api-ms-win-core-file-l1-2-0.dll.
File=Glide.WindowsCommon.dll.
What am I missing here?

[DllImport("api-ms-win-core-file-l1-2-0.dll", SetLastError = true)]
static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
out ulong lpFreeBytesAvailable,
out ulong lpTotalNumberOfBytes,
out ulong lpTotalNumberOfFreeBytes);
Because you did not specify a CharSet value, this is marshalled with CharSet of CharSet.Ansi by default. You should specify CharSet.Unicode like so:
[DllImport("api-ms-win-core-file-l1-2-0.dll", CharSet = CharSet.Unicode,
SetLastError = true)]
static extern bool GetDiskFreeSpaceEx(...);
It seems that the certification process also requires explicit statement of the entry point name:
[DllImport("api-ms-win-core-file-l1-2-0.dll", CharSet = CharSet.Unicode,
Entry point = "GetDiskFreeSpaceExW", SetLastError = true)]
static extern bool GetDiskFreeSpaceEx(...);

This is very confusing, simply changing the function name from GetDiskFreeSpaceEx to GetDiskFreeSpaceExW worked (passed the certification) + CharSet = CharSet.Unicode as in #David Heffernan answer :)

Related

c# Calling method using P/Invoke causing AccessViolation Exception

I interfacing with a device using P/Invoke. But I've come stuck at calling the following method:
BOOL __stdcall voGetFirmwareVersion(IN OUT LPTSTR lpVersion, IN OUT DWORD *dwSize);
In my wrapper I have called the method like so:
[DllImport(DLL_LOCATION, CharSet = CharSet.Ansi)]
private static extern Boolean voGetFirmwareVersion(string s, uint d);
I have attempted to change the inputs to Out/Ref and tried adding the [In,Out] attributes but I am constantly getting a AccessViolation Exception. Can anyone point me in the right direction? I've been at this for a couple of hours now and google hasn't been able to put me straight
dwSize is passed by address, so it should be a ref parameter.
BOOL return type must be marshaled if any nonzero value may come as a true value
I am not sure if you really want to use Ansi charset. Try Auto or Unicode.
LPStr and StdCall are not a must, they are the default settings.
So try this:
[DllImport(DLL_LOCATION, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool voGetFirmwareVersion([MarshalAs(UnmanagedType.LPTStr)] string s, ref uint d);

How to get system privilege

I have a C# program that require SeSystemEnvironmentPrivilege to access the UEFI NVRAM.
I found a really long code, that uses Win32 API to get the privilege, but is there a .NET version to get it? In process class, or somewhere else?
If it is really necessary you can use the AdjustTokenPrivileges function.
Something like this:
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
You can get more info here:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619%28v=vs.85%29.aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa375728(v=vs.85).aspx#privilege_constants

Delay Sleep or Power Off mode to execute a method c#

I am using these system notifications to detect a power off or power on event for windows. Now I am trying to delay power off event and execute one function before that So how is that possible.
[DllImport(#"User32", EntryPoint = "RegisterPowerSettingNotification",
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterPowerSettingNotification(
IntPtr hRecipient,
ref Guid PowerSettingGuid,
Int32 Flags);
[DllImport(#"User32", EntryPoint = "UnregisterPowerSettingNotification",
CallingConvention = CallingConvention.StdCall)]
private static extern bool UnregisterPowerSettingNotification(
IntPtr handle);

Getting value of a char* exported by unmanaged dll in .NET

Im trying to get a value of a string exported by an unmanaged dll.
The string in the dll is declared as
extern "C" __declspec(dllexport) const char* _Version = "0.1";
The code I'm using to get the value is below. I get the address for the variable from the call to GetProcAddress but Marshal.PtrToStringAuto returns garbage...
Whats wrong?
public string GetDllVersion()
{
IntPtr lib = LoadLibrary(#"some.dll");
if(lib == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
IntPtr procAddress = GetProcAddress(lib, "_Version");
var ver2 = Marshal.PtrToStringAuto(procAddress);
if(!FreeLibrary(lib))
throw new Win32Exception(Marshal.GetLastWin32Error());
return ver2;
}
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeLibrary(IntPtr hModule);
You have to use Marshal.PtrToStringAnsi() here.
"Auto" means "operating system default". With Windows 98 and ME on the endangered species list, that's very likely Unicode on your machine. Your string isn't const wchar_t*.
Here is my solution; checked-it, it works.
IntPtr procAddress = GetProcAddress(lib, "_Version");
IntPtr verAddress = Marshal.ReadIntPtr(procAddress);
var ver2 = Marshal.PtrToStringAnsi(verAddress);
Fixed this by dereferencing the pointer from GetProcAddress:
procAddress = Marshal.ReadIntPtr(GetProcAddress(lib, "_Version"));
Also changed the way to read the string per suggestion from Hans Passant (other answer):
var ver2 = Marshal.PtrToStringAnsi(procAddress);

Need to use win32 api to copy files in c# - how do I do this?

I'm trying to copy some files around, and occasionally the lengths of the names exceeds the length that the System.IO.File.Copy method can accept (260 chars according to the exception that is getting thrown)
According to the research I've done, I should be able to use the win32 api's file methods in conjunction with \?\ prepended to paths to get a 32,000 character limit, but I'm not sure witch methods I need to import.
Can someone help me with this? I'm looking for something like (obviously a different function, but you get the idea):
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFileW(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll",
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CopyFile(
[MarshalAs(UnmanagedType.LPWStr)] string lpExistingFileName,
[MarshalAs(UnmanagedType.LPWStr)] string lpNewFileName,
[MarshalAs(UnmanagedType.Bool)] bool bFailIfExists);
http://www.pinvoke.net/default.aspx/kernel32/CopyFile.html
Try using CopyFile.
For PInvoke syntax, you can check pinvoke.net.

Categories