I am writing an UEFI application (A) which will load another UEFI application (B). This another UEFI application (B) is stored on one of the Windows Partition (FAT32). I am trying to load (B) from (A).
Two things I need to perform from (A)
First of all locate the Windows Partition (Volume) where (B) is stored.
Load and Start Image (B).
So far I have been able to write following code.
EFI_STATUS
UefiMain(
EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE *st
) {
EFI_BOOT_SERVICES * bs = st->BootServices;
// set the gloabl service table before we do anything else
g_st = st;
EFI_HANDLE* handle;
UINTN n_handle ;
EFI_STATUS status;
status = bs->LocateHandleBuffer(ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&n_handle,
&handle);
if (EFI_ERROR (status))
{
print((CHAR16 *) L"LocateHandle Failed : ");
print_hex_dword(status);
print((CHAR16 *) L"\n");
return EFI_SUCCESS;
}
print((CHAR16 *) L" n_handle : ");
print_hex_dword(n_handle);
print((CHAR16 *) L"\n");
for (UINTN i=0; i<n_handle; i++)
{
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *protocol;
status = bs->OpenProtocol(handle[i],
&gEfiSimpleFileSystemProtocolGuid,
(void**)&protocol,
image_handle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR (status))
{
print((CHAR16 *) L"OpenProtocol Failed : ");
print_hex_dword(status);
print((CHAR16 *) L"\n");
return EFI_SUCCESS;
}
EFI_FILE_PROTOCOL *volume_root;
status = protocol->OpenVolume(protocol, &volume_root);
if (EFI_ERROR (status))
{
print((CHAR16 *) L"OpenVolume Failed : ");
print_hex_dword(status);
print((CHAR16 *) L"\n");
return EFI_SUCCESS;
}
EFI_FILE_PROTOCOL* root;
status = volume_root->Open(volume_root,
&root,
(CHAR16 *)L"MY_FOLDER\\myB.efi",
EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
if (EFI_ERROR (status))
{
print((CHAR16 *) L"Open Failed :");
print_hex_dword(status);
print((CHAR16 *) L"\n");
continue;
}
else
{
print((CHAR16 *) L"Open is Success\n");
}
//get file info, two try process
EFI_FILE_INFO* file_info = 0;
UINTN file_info_size = 0;
status = root->GetInfo(root, &FileInfoGuid, &file_info_size, 0 );
if (status != EFI_BUFFER_TOO_SMALL )
{
//ErrorPrint(L"Failed to stat file '%s'. (Error %d)\r\n", filename, res);
print((CHAR16 *) L"GetInfo Failed :");
print_hex_dword(status);
print((CHAR16 *) L"\n");
return EFI_NOT_FOUND ;
}
status = bs->AllocatePool(EfiLoaderData, file_info_size, (void**) &file_info);
if (status)
{
//ErrorPrint(L"Failed to allocate file info memory. (Error %d)\r\n", res);
print((CHAR16 *) L"AllocatePool Failed :");
print_hex_dword(status);
print((CHAR16 *) L"\n");
return EFI_OUT_OF_RESOURCES ;
}
status = root->GetInfo(root, &FileInfoGuid, &file_info_size,(void*) file_info);
print((CHAR16 *) L"FileSize :");
print_hex_dword(file_info->FileSize);
print((CHAR16 *) L"\n");
}
return EFI_SUCCESS;
}
I am not able to proceed further.
I believe that I will need to get DevicePath for the (B) application but I am not sure how to do that.
Any pointer will be helpful.
Thanks.
Once you've successfully opened the file, you can use FileDevicePath(handle[i], L"MY_FOLDER\\myB.efi") (which you should have if using EDK2 or GNU-EFI) to get an EFI_DEVICE_PATH which points to the file. Then you can load the image with something like as follows
// Set this from within the loop or break with an appropriate i.
EFI_DEVICE_PATH *path = FileDevicePath(handle[i], L"MY_FOLDER\\myB.efi");
EFI_HANDLE *img;
status = bs->LoadImage(false, image_handle, path, NULL, 0, &img)
if (EFI_ERROR(status)) {
print((CHAR16*) L"Failed to load image!");
return status;
}
status = bs->StartImage(img, NULL, NULL);
// We'll get here if the child image exits or if it fails to load
if (EFI_ERROR(status)) {
print((CHAR16*) L"Failed to start image!");
}
Related
I am trying to launch JVM from my C/ObjC program, but I have some issues displaying visual elements, like for example a window, on Catalina.
The part of the program that uses non-visual items, i.e. console & System.out works fine. But not any application window appears, although a proper Dock icon appears, which when clicked it does nothing.
I have written a helper function, to launch JVM. As arguments it has
the location of the libjvm.dylib
the JVM options
the size of the jvm options
the main arguments
the size of the main arguments
the main class
I looks to me that I am missing something, but I can't figure out what. Any ideas?
Here is the code:
typedef jint (*JNI_CreateJavaVM_f)(JavaVM **, void **, void *);
int launchjvm(char *jvmlib, char **jvmopts, int c_jvmopts, char **args, int c_args, char *mainclass)
{
JavaVM *vm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[c_jvmopts];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_8;
vm_args.ignoreUnrecognized = JNI_TRUE;
for (int i = 0; i < c_jvmopts; i++)
options[i].optionString = jvmopts[i];
vm_args.options = options;
vm_args.nOptions = c_jvmopts;
void *lib_handle = dlopen(jvmlib, RTLD_LOCAL | RTLD_LAZY);
if (!lib_handle)
{
printf("[%s] Unable to load library: %s\n", __FILE__, dlerror());
return 1;
}
JNI_CreateJavaVM_f JNI_CreateJavaVM = dlsym(lib_handle, "JNI_CreateJavaVM");
if (!JNI_CreateJavaVM)
{
printf("[%s] Unable to get symbol: %s\n", __FILE__, dlerror());
return 1;
}
jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
if (res != JNI_OK)
{
printf("Failed to create Java VM\n");
return res;
}
jclass cls = (*env)->FindClass(env, mainclass);
if (cls == NULL)
{
printf("Failed to find %s class\n", mainclass);
return 1;
}
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
if (mid == NULL)
{
printf("Failed to find main function in class %s\n", mainclass);
return 2;
}
jobjectArray main_args = (*env)->NewObjectArray(env, c_args, (*env)->FindClass(env, "java/lang/String"), NULL);
for(int i = 0 ; i < c_args ; i++)
(*env)->SetObjectArrayElement(env, main_args, i, (*env)->NewStringUTF(env, args[i]));
int result = 0;
(*env)->CallStaticVoidMethod(env, cls, mid, main_args);
if ((*env)->ExceptionOccurred(env)) { // check if an exception occurred
(*env)->ExceptionDescribe(env); // print the stack trace
result = -1;
}
(*vm)->DestroyJavaVM(vm);
[pool drain];
return result;
}
my goal:
I`m writing an application which writes a file to the serial port 128 bytes at a time (137 total, with ModBUS header and CRC) and waits for the reply. The writing I have managed to implement successfully. After sending a 137 byte packet I would like to wait on the serial com for a reply and process it, in case that modbus exception is thrown.
my problem:
The ReadFile function returns 170 which, from windows documentation, is 170 (0xAA) - The requested resource is in use. The only resource I am actually using is the serial port handle, which I doubt that it is this, the error is referring to.
Note -
- not using available ModBUS libraries because I use the address registers in a specific way, needing full control
- I am using overlapped I/O only because (according to WinApi doc) ReadFile never returns if no bytes come at the serial port; If timeouts are require overlapped access is a must (correct me if I`m wrong).
- I have a 2 sec max timeout (timeout for actually waiting for the reply) and 20 ms between bytes; if more than 20 ms between bytes pass I assume that no more bytes are coming;
Has anyone had any previous experience working with ReadFile and possibly Erro 170? Appreciate all the help I can get.
part of my code:
u8 WaitModBusReply(void)
{
u8 i = 0;
u8 ReplyStatus = 0xAA;
u8 ReplyBuff[ReplyBuffSize];
u8 * ptr = &ReplyBuff[0];
static u16 TotalRX_Bytes;
DWORD dwCommEvent;
DWORD dwBytesRead;
COMSTAT ComStatus;
DWORD comErrors = 0;
OVERLAPPED read_s = {0};
read_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
for (int z=0; z< ReplyBuffSize; z++)
ReplyBuff[z] = 0;
ClearCommError(ModBUS_Port, &comErrors, &ComStatus);
ResetEvent(read_s.hEvent);
if ( !WaitCommEvent(ModBUS_Port, &dwCommEvent, &read_s) )
{
//byte_timeout += MCU_Getms_TimeConsumption();
if ( (ReadFile(ModBUS_Port, ptr+TotalRX_Bytes, ReplyBuffSize-
TotalRX_Bytes, &dwBytesRead, NULL) )) //&dwBytesRead &modbus_reply
{
fprintf(stderr, "\n EXEC 3");
// ReadFile(PC_TestCenterPort, pBufPtr+TotalRX_Bytes, BufSize-
TotalRX_Bytes, &BytesRead, NULL);
TotalRX_Bytes += dwBytesRead;
i++;
ReplyStatus = Reply_Received;
}
}
else
printf("Error setting Com event mask:%d ", GetLastError());
if ( ReplyStatus == Reply_Received)
{
fprintf(stderr, "\nExit error3: %d\n", GetLastError() );
if ( (i == 4) ) // Exception returned. Parse it
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = ReplyBuff[i-2];
}
else if ( (i == 7) ) // Reply returned
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = Reply_OK;
}
}
/*
for ( int j=0; j<= 256; j++)
printf("\nReplyBuff[%d]: %X", j, ReplyBuff[j]); */
return ReplyStatus;
}
The logic for checking the reply array is not implemented so ignore that part.
This function is called by:
u8 SerialDataSend(void)
{
u8 t_status = BufferSent;
int write_status = -1;
int read_status = -1;
DWORD bytes_written = 0;
OVERLAPPED write_s;
memset(&write_s, 0, sizeof(write_s));
write_s.Internal = 0;
write_s.InternalHigh = 0;
write_s.Offset = 0;
write_s.OffsetHigh = 0;
write_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
if ( !SerialInit() )
{
while (!t_status)
{
fprintf(stderr, "Starting transmission -\n");
while(packages_left > 0 && !t_status)
{
write_status = WriteFile(ModBUS_Port, ModBUS_Buffer(), 137,
&bytes_written, &write_s); //&write_s
fprintf(stderr,"\r ModBUS transaction - Packages left:%4d",
packages_left);
if( write_status ) // Return values for success and
overlapped access ongoing
{
fprintf(stderr, "Error :%d.\n", GetLastError());
t_status = BufferFailed;
CloseHandle(ModBUS_Port);
break;
}
//FlushFileBuffers(ModBUS_Port);
read_status = WaitModBusReply();
printf("READ STATUS: %d\n", read_status);
if ( !read_status && !write_status )
{
fprintf(stderr, "\n------------------------------------------------------------");
fprintf(stderr, "\n Exception occurred: %X\n",
read_status);
t_status = BufferFailed;
Sleep(1);
break;
}
packages_left--;
Sleep(200);
}
//printf("EXEC 1\n");
if (!t_status)
{
fprintf(stderr, "\n\nTransaction Complete. Bytes written :
%d\n", FileSize);
packages_left = 10;
}
break;
}
fclose(HMI_Program);
if ( t_status != BufferFailed )
{
fprintf(stderr, "Closing serial port - ");
if ( !CloseHandle(ModBUS_Port) )
fprintf(stderr, "Error :%d.\n", GetLastError());
else
fprintf(stderr, "OK.\n");
}
}
fflush(stdout);
fflush(stderr);
return t_status;
}
and the function which initializes the Serial port:
u8 SerialInit(void)
{
memset(&SerialSettings,0,sizeof(SerialSettings));
SerialSettings.DCBlength = sizeof(SerialSettings);
SerialSettings.BaudRate = CBR_115200;
SerialSettings.ByteSize = 8;
SerialSettings.StopBits = TWOSTOPBITS;
SerialSettings.Parity = NOPARITY;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutConstant = 2000;
timeouts.ReadTotalTimeoutMultiplier = 1 ;
memset(&timeouts,0,sizeof(timeouts));
fprintf(stderr, "Opening serial port - ");
sprintf(COM_Port, "\\\\.\\COM%d", port_no);
ModBUS_Port = CreateFile(COM_Port, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if (ModBUS_Port == INVALID_HANDLE_VALUE)
fprintf(stderr, "Error\n\n");
else
fprintf(stderr, "OK\n");
if ( !GetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error getting device state.");
CloseHandle(ModBUS_Port);
}
else if( !SetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error setting device parameters.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommTimeouts(ModBUS_Port, &timeouts) )
{
fprintf(stderr, "Error setting timeouts.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommMask(ModBUS_Port, EV_RXCHAR | EV_ERR ) )
{
fprintf(stderr, "\nError setting com mask.");
CloseHandle(ModBUS_Port);
}
return GetLastError();
}
Thanks.
In OS X, how can I tell if the camera or microphone is in use by another application or process? The following doesn't seem to work unless the other application has locked the device.
NSArray *devices = [AVCaptureDevice devices];
for (AVCaptureDevice *device in devices) {
NSLog(#"In use by other application %hhd", [device isInUseByAnotherApplication]);
}
You can use CoreAudio to check if microphone is in use or not.
AudioObjectPropertyAddress propertyAddress = {
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
UInt32 dataSize = 0;
OSStatus status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
if(kAudioHardwareNoError != status) {
fprintf(stderr, "AudioObjectGetPropertyDataSize (kAudioHardwarePropertyDevices) failed: %i\n", status);
//return NULL;
return;
}
UInt32 deviceCount = (UInt32)(dataSize / sizeof(AudioDeviceID));
AudioDeviceID *audioDevices = (AudioDeviceID*)(malloc(dataSize));
if(NULL == audioDevices) {
fputs("Unable to allocate memory", stderr);
return;
}
status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, audioDevices);
if(kAudioHardwareNoError != status) {
fprintf(stderr, "AudioObjectGetPropertyData (kAudioHardwarePropertyDevices) failed: %i\n", status);
free(audioDevices), audioDevices = NULL;
return ;
}
CFMutableArrayRef inputDeviceArray = CFArrayCreateMutable(kCFAllocatorDefault, deviceCount, &kCFTypeArrayCallBacks);
if(NULL == inputDeviceArray) {
fputs("CFArrayCreateMutable failed", stderr);
free(audioDevices), audioDevices = NULL;
return ;
}`
Now Iterate through all the devices and fetch property data kAudioDevicePropertyDeviceIsRunningSomewhere
CFBooleanRef deviceIsRunning = NULL;
dataSize = sizeof(deviceIsRunning);
propertyAddress.mSelector = kAudioDevicePropertyDeviceIsRunningSomewhere;
status = AudioObjectGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceIsRunning);
Check deviceIsRunning variable.
I don't have idea about video device. But i will update my answer if i find some solution.
Hope this help.
I'm working on go module that detects camera/microphone state (using cgo) and here is my Objective-C implementations:
IsCameraOn(): https://github.com/antonfisher/go-media-devices-state/blob/main/pkg/camera/camera_darwin.mm
IsMicrophoneOn(): https://github.com/antonfisher/go-media-devices-state/blob/main/pkg/microphone/microphone_darwin.mm
Thanks #Rohan for the accepted answer!
int rename_file()
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
hFind = FindFirstFile(L"\\Hard Disk\\*.*", &FindFileData);
LPTSTR oldfilename;
LPTSTR newfilename;
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("FindFirstFile failed (%d)\n", GetLastError());
return 0;
}
else
{
int i=1000;
while (FindNextFile(hFind, &FindFileData) != 0)
{
_tprintf (TEXT("The first file found is %s\n"),FindFileData.cFileName);
oldfilename =FindFileData.cFileName;
StringCchPrintf(newfilename, 30, TEXT("%s\\newfile_%d.txt"),dirname, i);
BOOL rs = MoveFile(oldfilename,newfilename);
i++;
}
FindClose(hFind);
return 1;
}
}
i am unable to rename file ,i am working on wince 6 ,while debugging at StringCchPrintf iam getting exception in coredll.dll can any one help me ....
You have not allocated any buffer for newFileName, so when you use it in the StringCchPrintf it's just an uninitialized pointer.
Try this:
TCHAR newFile[260]; // or whatever length you wish
LPTSTR newfilename = &newFile[0];
Also you should check the return code from MoveFile, and output something sensible on error. Make a habit of doing this for all your function calls that can return an error.
How do you resolve an NT style device path, e.g. \Device\CdRom0, to its logical drive letter, e.g. G:\ ?
Edit: A Volume Name isn't the same as a Device Path so unfortunately GetVolumePathNamesForVolumeName() won't work.
Hopefully the following piece of code will give you enough to solve this - after you've initialised it, you just need to iterate through the collection to find your match. You may want to convert everything to upper/lower case before you insert into the collection to help with lookup performance.
typedef basic_string<TCHAR> tstring;
typedef map<tstring, tstring> HardDiskCollection;
void Initialise( HardDiskCollection &_hardDiskCollection )
{
TCHAR tszLinkName[MAX_PATH] = { 0 };
TCHAR tszDevName[MAX_PATH] = { 0 };
TCHAR tcDrive = 0;
_tcscpy_s( tszLinkName, MAX_PATH, _T("a:") );
for ( tcDrive = _T('a'); tcDrive < _T('z'); ++tcDrive )
{
tszLinkName[0] = tcDrive;
if ( QueryDosDevice( tszLinkName, tszDevName, MAX_PATH ) )
{
_hardDiskCollection.insert( pair<tstring, tstring>( tszLinkName, tszDevName ) );
}
}
}
Maybe you could use GetVolumeNameForMountPoint and iterate through all mount points A:\ through Z:\, breaking when you find a match?
http://msdn.microsoft.com/en-us/library/aa364994(VS.85).aspx
(I haven't tried this)
Following function does the job using C only
BOOL GetWin32FileName(const TCHAR* pszNativeFileName, TCHAR *pszWin32FileName)
{
BOOL bFound = FALSE;
// Translate path with device name to drive letters.
TCHAR szTemp[MAX_PATH];
szTemp[0] = '\0';
if (GetLogicalDriveStrings(MAX_PATH - 1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
TCHAR* p = szTemp;
do
{
// Copy the drive letter to the template string
*szDrive = *p;
// Look up each device name
if (QueryDosDevice(szDrive, szName, MAX_PATH))
{
size_t uNameLen = _tcslen(szName);
if (uNameLen < MAX_PATH)
{
bFound = _tcsnicmp(pszNativeFileName, szName, uNameLen) == 0
&& *(pszNativeFileName + uNameLen) == _T('\\');
if (bFound)
{
// Replace device path with DOS path
StringCchPrintf(pszWin32FileName,
MAX_PATH,
TEXT("%s%s"),
szDrive,
pszNativeFileName + uNameLen);
}
}
}
// Go to the next NULL character.
while (*p++);
} while (!bFound && *p);
}
return(bFound);
}
You can lookup all volumes' name to match a device name and get drive letter.Here is a sample:
int DeviceNameToVolumePathName(WCHAR *filepath) {
WCHAR fileDevName[MAX_PATH];
WCHAR devName[MAX_PATH];
WCHAR fileName[MAX_PATH];
HANDLE FindHandle = INVALID_HANDLE_VALUE;
WCHAR VolumeName[MAX_PATH];
DWORD Error = ERROR_SUCCESS;
size_t Index = 0;
DWORD CharCount = MAX_PATH + 1;
int index = 0;
// \Device\HarddiskVolume1\windows,locate \windows.
for (int i = 0; i < lstrlenW(filepath); i++) {
if (!memcmp(&filepath[i], L"\\", 2)) {
index++;
if (index == 3) {
index = i;
break;
}
}
}
filepath[index] = L'\0';
memcpy(fileDevName, filepath, (index + 1) * sizeof(WCHAR));
FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));
if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
wprintf(L"FindFirstVolumeW failed with error code %d\n", Error);
return FALSE;
}
for (;;)
{
// Skip the \\?\ prefix and remove the trailing backslash.
Index = wcslen(VolumeName) - 1;
if (VolumeName[0] != L'\\' ||
VolumeName[1] != L'\\' ||
VolumeName[2] != L'?' ||
VolumeName[3] != L'\\' ||
VolumeName[Index] != L'\\')
{
Error = ERROR_BAD_PATHNAME;
wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %s\n", VolumeName);
break;
}
VolumeName[Index] = L'\0';
CharCount = QueryDosDeviceW(&VolumeName[4], devName, 100);
if (CharCount == 0)
{
Error = GetLastError();
wprintf(L"QueryDosDeviceW failed with error code %d\n", Error);
break;
}
if (!lstrcmpW(devName, filepath)) {
VolumeName[Index] = L'\\';
Error = GetVolumePathNamesForVolumeNameW(VolumeName, fileName, CharCount, &CharCount);
if (!Error) {
Error = GetLastError();
wprintf(L"GetVolumePathNamesForVolumeNameW failed with error code %d\n", Error);
break;
}
// concat drive letter to path
lstrcatW(fileName, &filepath[index + 1]);
lstrcpyW(filepath, fileName);
Error = ERROR_SUCCESS;
break;
}
Error = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));
if (!Error)
{
Error = GetLastError();
if (Error != ERROR_NO_MORE_FILES)
{
wprintf(L"FindNextVolumeW failed with error code %d\n", Error);
break;
}
//
// Finished iterating
// through all the volumes.
Error = ERROR_BAD_PATHNAME;
break;
}
}
FindVolumeClose(FindHandle);
if (Error != ERROR_SUCCESS)
return FALSE;
return TRUE;
}
If you want to resolve it in driver,you can check this link for reference.
Here is refactored version of the solution.
I replaced TChAR with wchar_t because afaik it's not a good idea to use it in most projects.
std::map<std::wstring, std::wstring> GetDosPathDevicePathMap()
{
// It's not really related to MAX_PATH, but I guess it should be enough.
// Though the docs say "The first null-terminated string stored into the buffer is the current mapping for the device.
// The other null-terminated strings represent undeleted prior mappings for the device."
wchar_t devicePath[MAX_PATH] = { 0 };
std::map<std::wstring, std::wstring> result;
std::wstring dosPath = L"A:";
for (wchar_t letter = L'A'; letter <= L'Z'; ++letter)
{
dosPath[0] = letter;
if (QueryDosDeviceW(dosPath.c_str(), devicePath, MAX_PATH)) // may want to properly handle errors instead ... e.g. check ERROR_INSUFFICIENT_BUFFER
{
result[dosPath] = devicePath;
}
}
return result;
}