Following is the implementation of infix to postfix conversion, it is working fine on my computer, but as I am submitting in on SPOJ it is giving me Runtime error SIGSEGV, I am new to competitive programming and I am unable to handle such type of errors.
#include <iostream>
#include <stack>
#include<string.h>
#include<ctype.h>
using namespace std;
int prec(char ch){
switch(ch){
case '^' : return 3;
break;
case '*':
case '/': return 2;
break;
case '+':
case '-': return 1;
break;
default: return -1;
}
}
void pti(char a[]){
stack<int> post;
int k = -1;
for(int i = 0;i<strlen(a);i++){
if(isalnum(a[i]))
a[++k] = a[i];
else if(a[i] == '(')
post.push(a[i]);
else if(a[i] == ')'){
while(!post.empty() && post.top()!= '('){
a[++k] = post.top();
post.pop();
}
post.pop();
}
else {
while(!post.empty() && prec(a[i]) <= prec(post.top())){
a[++k] = post.top();
post.pop();
}
post.push(a[i]);
}
}
while(!post.empty()){
a[++k] = post.top();
post.pop();
}
a[++k] = '\0';
cout<<a<<endl;
}
int main()
{
int t;
cin>>t;
for(int i = 0;i<t;i++){
char a[100];
cin>>a;
pti(a);
}
}
You just need to make the input array longer, e.g. a size of 1000 gets AC.
The SIGSEGV signal means a segmentation fault occured, which basically means you accessed memory that doesn't belong to you.
I'm a little bit short of reaching my goal.
GetFileVersionInfoSize() is working fine along with other two functions GetFileVersionInfo() and VerQueryValue(). I would like to just add more features to it to make it complete.
I've coded it to run on WCHAR and would like to know making it run for CHAR would make sense?
Is there a way around it so that I code it once and it would work for both?
Also, is there a way I could enumerate the contents of \\StringFileInfo\\lang-codepage\\* ?
DWORD GetFileVersionInfo3(const TCHAR *pszFilePath, std::vector<std::pair<std::wstring, std::wstring>> *lplist)
{
DWORD dwSize = 0;
BYTE *pbVersionInfo = NULL;
VS_FIXEDFILEINFO *pFileInfo = NULL;
UINT puLenFileInfo = 0;
dwSize = GetFileVersionInfoSize(pszFilePath, NULL);
if (dwSize == 0)
{
printf("\nError in GetFileVersionInfoSize: %d\n", GetLastError());
return 1;
}
pbVersionInfo = new BYTE[dwSize];
memset(pbVersionInfo, '\0', dwSize);
if (!GetFileVersionInfo(pszFilePath, 0, dwSize, pbVersionInfo))
{
printf("\nError in GetFileVersionInfo: %d\n", GetLastError());
delete[] pbVersionInfo;
return 1;
}
if (!VerQueryValue(pbVersionInfo, TEXT("\\"), (LPVOID*)&pFileInfo, &puLenFileInfo))
{
printf("\nError in VerQueryValue: %d\n", GetLastError());
delete[] pbVersionInfo;
return 1;
}
if (!VerQueryValue(pbVersionInfo, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &puLenFileInfo))
{
printf("\nError in VerQueryValue: %d\n", GetLastError());
return 1;
}
std::vector<std::wstring>::iterator itr;
std::vector<std::wstring> wlist;
wlist.clear();
wlist.push_back(L"FileDescription");
wlist.push_back(L"InternalName");
wlist.push_back(L"OriginalFilename");
wlist.push_back(L"CompanyName");
wlist.push_back(L"FileVersion");
wlist.push_back(L"ProductName");
wlist.push_back(L"ProductVersion");
wlist.push_back(L"LegalCopyright");
char fileEntry[1024];
for (int i = 0; i < (puLenFileInfo / sizeof(struct LANGANDCODEPAGE)); i++)
{
sprintf_s(fileEntry, 1024, "\\StringFileInfo\\%04x%04x\\",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
lplist->push_back(std::pair<std::wstring, std::wstring>(L"File: ", pszFilePath));
std::string s1(fileEntry);
for (itr = wlist.begin(); itr != wlist.end(); itr++)
{
std::wstring item = *itr;
std::wstring wstr;
wstr.append(s1.begin(), s1.end());
wstr.append(item);
LPVOID lpBuffer = NULL;
UINT dwBytes = 0;
bool bRes = VerQueryValue(pbVersionInfo, wstr.c_str(), (LPVOID*)&lpBuffer, &dwBytes);
if (!bRes)
{
continue;
}
LPTSTR wsResult;
wsResult = (LPTSTR)lpBuffer;
lplist->push_back(std::pair<std::wstring, std::wstring>(item, wsResult));
}
}
return 0;
}
Since you are using TCHAR, use std:::basic_string<TCHAR> instead of std::wstring to match. Otherwise, drop TCHAR and use WCHAR for everything.
Hey there wonderful community!
I'm back with a question regarding a console server application I've made with winsock. It's finally reaching a stage where I would need a to add a GUI, and to do so, I need it to be using the Windows subsystem.
And so I started the migration.
Yet I'm hitting a stack overflow somewhere in my application, and for the life of me I can't figure out where. Perhaps it has to do with WIN being a non-blocking subsystem (hope I used my vocab correctly).
Anyway, I hope to enlist you all as helpers. Many thanks :)
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <conio.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
int minitialize();
int msend(char msendbuf[512]);
char* mrecv(bool show);
int mshutdown();
void GoToXY(int column, int line);
int scroll(void);
int printm(char *inp);
int printm(char *inp, DWORD color);
int mexit();
char *vir = "true";
int clientnumber=0;
int currentclient=0;
int lastclient=0;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "10150"
struct _client
{
bool con;
sockaddr_in addr; //Client info like ip address
SOCKET cs; //Client socket
fd_set set; //used to check if there is data in the socket
std::string ip;
std::string name;
int i; //any piece of additional info
} client[100];
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
DWORD WINAPI recvfunc(LPVOID randparam)
{
while (true) {
ClientSocket=client[currentclient].cs;
if (mrecv(true)=="1") {
client[currentclient].con=false;
ClientSocket=client[lastclient].cs;
break;
}
}
return 0;
}
DWORD WINAPI headerfunc(LPVOID randparam)
{
Sleep(500);
while (true) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,0);
HANDLE hHeaderColor;
hHeaderColor = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hHeaderColor, FOREGROUND_GREEN);
std::cout<<"Server Started. Current Client:"<<currentclient<<" Clients connected: "<<clientnumber<<" ("<<xx<<","<<yy<<") "<<lastclient;
SetConsoleTextAttribute(hHeaderColor, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
GoToXY(xx,yy);
Sleep(2000);
}
return 0;
}
DWORD WINAPI sendfunc(LPVOID randparam)
{
while (true) {
char mmessage[512];
std::cin.getline(mmessage, 512);
if (strlen(mmessage)<2) {
GoToXY(0,23);
sendfunc("1");
}
char msendbuf[512]="Server> ";
strcat(msendbuf,mmessage);
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
if ((strncmp(msendbuf,"Server> /",9)) != 0) {
printm(msendbuf,FOREGROUND_INTENSITY);
}
GoToXY(0,23);
for (int sp=0; sp<72; sp++) {
std::cout<<" ";
}
GoToXY(0,23);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
minitialize();
HANDLE hRecvThread;
HANDLE hSendThread;
HANDLE hHeaderThread;
DWORD dwRecvThreadId;
DWORD dwSendThreadId;
DWORD dwHeaderThreadId;
hHeaderThread = CreateThread(NULL,0,headerfunc,"1",0,&dwHeaderThreadId);
for (int mf=2; mf<25; mf++) {
std::cout<<"\n";
}
hSendThread = CreateThread(NULL,0,sendfunc,"1",0,&dwSendThreadId);
// Accept a client socket
for (int sock=1; sock<100; sock++) {
ClientSocket = accept(ListenSocket, NULL, NULL);
char sockprint[80];
char sockchar[4];
itoa(sock,sockchar,10);
strcpy(sockprint,"Client ");
strcat(sockprint,sockchar);
strcat(sockprint," connected.");
printm(sockprint);
GoToXY(0,23);
if (ClientSocket == INVALID_SOCKET) {
printm("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
client[sock].cs=ClientSocket;
client[sock].con=true;
lastclient=clientnumber;
clientnumber++;
currentclient=clientnumber;
hRecvThread = CreateThread(NULL,0,recvfunc,"1",0,&dwRecvThreadId);
}
// shutdown the connection since we're done
mshutdown();
std::cin.ignore();
return 0;
}
int printm(char *inp, DWORD color) {
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
color);
printm(inp);
SetConsoleTextAttribute(hOut, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
return 0;
}
int printm(char *inp) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,22);
std::cout<<inp<<"\n";
scroll();
GoToXY(xx,yy);
return 1;
}
int msend(char msendbuf[512]) // Send a message
{
if (strncmp(msendbuf,"Server> /exit",(strlen(msendbuf))) == 0) {
mexit();
}
if (strncmp(msendbuf,"Server> /set_client",19) == 0) {
int nm=atoi(&msendbuf[20]);
currentclient=nm;
ClientSocket=client[nm].cs;
char sockchar[4];
itoa(ClientSocket,sockchar,10);
char sockprint[80];
strcpy(sockprint,"New Socket: ");
strcat(sockprint,sockchar);
printm(sockprint);
char clientprint[80];
strcpy(clientprint,"Client: ");
strcat(clientprint,&msendbuf[20]);
printm(clientprint);
}
if (strncmp(msendbuf,"Server> /list_clients",(strlen(msendbuf))) == 0) {
printm("Clients:",FOREGROUND_RED);
for (int cm=1; cm < 100; cm++) {
int cn=client[cm].cs;
if (cn>0) {
char cli[80];
char cmchar[4];
char cnchar[80];
itoa(cn,cnchar,10);
itoa(cm,cmchar,10);
strcpy(cli,cmchar);
strcat(cli," ");
strcat(cli,cnchar);
strcat(cli," ");
strcat(cli,client[cm].ip.c_str());
strcat(cli," ");
strcat(cli,client[cm].name.c_str());
printm(cli,FOREGROUND_RED);
}
else {
break;
}
}
}
if (strncmp(msendbuf,"Server> /test",(strlen(msendbuf))) == 0) {
char ipcon[500];
*ipcon=(system("ipconfig"));
}
if (strncmp(msendbuf,"Server> /help",(strlen(msendbuf))) == 0) {
printm("Type /help for help or:");
printm("/set_client [client number]");
printm("/list_clients");
}
int iResult3 = send( ClientSocket, msendbuf, 512, 0 );
if (iResult3 == SOCKET_ERROR) {
printm("send failed with error: %d\n", WSAGetLastError());
return 1;
}
}
char* mrecv(bool show) //Recieve a message
{
int iResult2 = recv(ClientSocket, recvbuf, 512, 0);
if (iResult2 > 0) {
if ((strncmp(recvbuf,"/",1)) != 0) {
printm(recvbuf);
}
if (strncmp(recvbuf,"/ip",3) == 0) {
client[clientnumber].ip=&recvbuf[4];
char prin[80];
strcpy(prin,"client[clientnumber].ip: ");
strcat(prin,client[clientnumber].ip.c_str());
printm(prin,FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/name",5) == 0) {
client[clientnumber].name=&recvbuf[6];
char prin2[80];
strcpy(prin2,"client[clientnumber].name: ");
strcat(prin2,client[clientnumber].name.c_str());
printm(prin2,FOREGROUND_GREEN | FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/alert",5) == 0) {
char *message=&recvbuf[7];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
if (strncmp(recvbuf,"Client> /alert",14) == 0) {
char *message=&recvbuf[15];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
}
else if (iResult2 == 0) {
printf("Connection closing...\n");
closesocket(ClientSocket);
WSACleanup();
return "1";
}
else {
printm("recv failed with error: %d\n", WSAGetLastError());
printm("Client must have disconnected. Please select a new client.");
return "1";
}
return recvbuf;
}
int minitialize() //initialize the winsock server
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printm("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printm("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printm("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printm("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printm("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
unsigned long b=1;
ioctlsocket(ClientSocket,FIONBIO,&b);
}
int mshutdown() //shutdown the server
{
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printm("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
void GoToXY(int column, int line)
{
// Create a COORD structure and fill in its members.
// This specifies the new position of the cursor that we will set.
COORD coord;
coord.X = column;
coord.Y = line;
// Obtain a handle to the console screen buffer.
// (You're just using the standard console, so you can use STD_OUTPUT_HANDLE
// in conjunction with the GetStdHandle() to retrieve the handle.)
// Note that because it is a standard handle, we don't need to close it.
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Finally, call the SetConsoleCursorPosition function.
if (!SetConsoleCursorPosition(hConsole, coord))
{
// Uh-oh! The function call failed, so you need to handle the error.
// You can call GetLastError() to get a more specific error code.
// ...
return;
}
}
int scroll( void )
{
HANDLE hStdout;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
SMALL_RECT srctScrollRect, srctClipRect;
CHAR_INFO chiFill;
COORD coordDest;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdout == INVALID_HANDLE_VALUE)
{
printf("GetStdHandle failed with %d\n", GetLastError());
return 1;
}
// Get the screen buffer size.
if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
printf("GetConsoleScreenBufferInfo failed %d\n", GetLastError());
return 1;
}
// The scrolling rectangle
srctScrollRect.Top = 1;
srctScrollRect.Bottom = 22;
srctScrollRect.Left = 0;
srctScrollRect.Right = csbiInfo.dwSize.X - 1;
// The destination for the scroll rectangle is one row up.
coordDest.X = 0;
coordDest.Y = 0;
// The clipping rectangle
srctClipRect.Top = 2;
srctClipRect.Bottom = 22;
srctClipRect.Left = 0;
srctClipRect.Right = csbiInfo.dwSize.X - 1;
// Fill the bottom row with blanks.
chiFill.Attributes = FOREGROUND_RED;
chiFill.Char.AsciiChar = (char)' ';
// Scroll up one line.
if(!ScrollConsoleScreenBuffer(
hStdout, // screen buffer handle
&srctScrollRect, // scrolling rectangle
&srctClipRect, // clipping rectangle
coordDest, // top left destination cell
&chiFill)) // fill character and color
{
printf("ScrollConsoleScreenBuffer failed %d\n", GetLastError());
return 1;
}
return 0;
}
int mexit()
{
msend("/server_closed");
mshutdown();
exit(0);
}
Turns out it was the recursive calling in my "sendfunc" thread that tripped me up.
Specifically,
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
Because I continued to call "sendfunc" from itself, it caused the stack overflow.
So, for anyone else having these problems, watch for overkill recursive function calls.
I simply removed my sending function and I was good to go.
I have a map that is acting up and not returning the correct number. It did then it didn't, now it's just not returning. Any help is appreciated. Thank you.
struct file_data
{
std::wstring sLastAccessTime;
__int64 nFileSize ;
};
int GetFileList(const wchar_t *searchkey, std::map<std::wstring, file_data> &map)
{
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile(searchkey,&fd);
if(h == INVALID_HANDLE_VALUE)
{
return 0; // no files found
}
while(1)
{
wchar_t buf[128];
FILETIME ft = fd.ftLastWriteTime;
SYSTEMTIME sysTime;
FileTimeToSystemTime(&ft, &sysTime);
wsprintf(buf, L"%d-%02d-%02d",sysTime.wYear, sysTime.wMonth, sysTime.wDay);
file_data filedata;
filedata.sLastAccessTime= buf;
filedata.nFileSize = (((__int64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
map[fd.cFileName]= filedata;
if (FindNextFile(h, &fd) == FALSE)
break;
}
return map.size();
}
int main()
{
std::map<std::wstring, file_data> map;
int count = GetFileList(L"C:\\Users\\DS\\Downloads\\*.pdf", map);
int count1 = GetFileList(L"C:\\Users\\DS\\Downloads\\*.txt", map);
int count2 = GetFileList(L"C:\\Users\\DS\\Downloads\\*.jpg", map);
for(std::map<std::wstring, file_data>::const_iterator it = map.begin(); it != map.end(); ++it)
{
if (count2 != 0)
{
printf("\n How Many: %i \n", count2);
}
else
{
printf ("%s \n", "Nothing");
}
return 0;
}
}
Note that GetFileList() returns the number of items in the map.
In your implementation it is cumulative. Maybe you want to clear the map between consecutive calls to GetFileList().
OK found the solution. This is it.
GetFileList(L"C:\\Users\\DS\\Downloads\\*.pdf", map);
GetFileList(L"C:\\Users\\DS\\Downloads\\*.txt", map);
GetFileList(L"C:\\Users\\DS\\Downloads\\*.jpg", map);
if( map.size() > 0
then...........
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;
}