Creating a file on desktop (C++) - c++

Currently I'm using windows 8.1....
in C++ when I'm trying to create a file on desktop with these codes ...
#include "stdafx.h"
#include <fstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ofstream myfile("C:/Users/%USERPROFILE%/Desktop/myfile.anything");
//ofstream myfile("C:/users/myfile.anything"); //Works fine with run As Administrator
return 0;
}
so the problems are completely clear 1.the userprofile don't know why? and 2.i should run the program as administrator but in here there is no need for run as....
i wanted to know if there is a little more simple way ....
Thanks

As the comments point out, you're trying to use an environment variable in your filepath, and the standard iostreams don't do environment variable expansion. You'll have to do that part yourself with platform-specific code, or simply use "normal" filepaths.
For C++ on Windows, the function to do this is GetEnvironmentVariable. It's one of those functions that takes a fixed size buffer, so using it is finicky enough that there's already a stackoverflow question all about how to call it correctly.
P.S. As the comments also pointed out, in places that do perform environment variable expansion (such as shell scripts or Windows Explorer), it's actually %USERPROFILE%, not &USERPROFILE&.

The comments to the other question were correct. Here's a basic way of fixing this (using http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188%28v=vs.85%29.aspx)
#include <fstream>
#include <Windows.h>
#include <string>
using namespace std;
int main() {
WCHAR *buffer = new WCHAR[260];
const WCHAR name[12] = "USERPROFILE";
DWORD result = GetEnvironmentVariable(name, buffer, 260);
if (result > 260) {
delete[] buffer; buffer = new WCHAR[result];
GetEnvironmentVariable(name, buffer, result);
}
wstring s("C:/Users/");
s += buffer;
s += "/Desktop/myfile.anything";
ofstream myfile(s.c_str());
// do things here
delete[] buffer;
return 0;
}

You have many ways to get user profile directory :
via the environment variable USERPROFILE :
#include <cstdlib>
...
string profile = getenv("USERPROFILE");
via Windows API, but it is bit harder :
#include <windows.h>
#include <userenv.h>
...
HANDLE processToken = ::GetCurrentProcess();
HANDLE user;
BOOL cr = ::OpenProcessToken(processToken, TOKEN_ALL_ACCESS, &user);
DWORD size = 2;
char * buff = new char[size];
cr = ::GetUserProfileDirectoryA(user, buff, &size); // find necessary size
delete[] buff;
buff = new char[size];
cr = ::GetUserProfileDirectoryA(user, buff, &size);
string profile = buff;
delete[] buff;
and you have to link with userenv.lib - the tests for return codes are left as an exercise :-)
via ExpandEnvironmentString :
size = ::ExpandEnvironmentStringsA("%USERPROFILE%\\Desktop\\myfile.anything",
NULL, 2);
buff = new char[size];
size = ::ExpandEnvironmentStringsA("%USERPROFILE%\\Desktop\\myfile.anything",
buff, size);
string profile = buff;
delete[] buff;
With third way you have directly your string, with first and second you only get profile directory and still have to concatenate it with relevant path.
But in fact, if you want you program to be language independant, you should really use SHGetSpecialFolderPath API function :
#include <shlobj.h>
...
buff = new char[255];
SHGetSpecialFolderPathA(HWND_DESKTOP, buff, CSIDL_DESKTOPDIRECTORY, FALSE);
string desktop = buff;
delete[] buff;
Because on my old XP box in french, Desktop is actually Bureau ...

Related

Replace wchar_t error return memory address

I want to replace a specific character wchar_t. as a result it return memory address. is there a way to return replaced wchar_t?
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <Psapi.h>
using namespace std;
int main()
{
wchar_t processPath[MAX_PATH];
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 3820);
GetProcessImageFileName(hProcess, processPath, MAX_PATH);
CloseHandle(hProcess);
wchar_t * pwc;
pwc = wcsstr(processPath, L"\\Device\\HardiskVolume1");
wcscpy_s(pwc, 100, L"C:", 100);
wcout << processPath;
return 0;
}
Thank you
I suggest that you use std::wstring, and then .replace, there isn't really a good 'replace' function when using c-strings:
LPCWSTR pwszReplace = L"string-of-interest";
std::size_t len = wcslen(pwszReplace);
std::wstring path(processPath),
std::size_t ndx = path.find(pwszReplace);
if(std::wstring::npos!=ndx)
{
path.replace(ndx, len, L"new-string");
}
std::wcout << L"path is now: " << path << std::endl;
Use GetModuleFileNameEx Windows XP and higher. Or QueryFullProcessImageName for Vista and higher.
Otherwise, you can't assume "\\Device\\HardiskVolume1" is always "C:"
See also this SO Q&A: Convert HarddiskVolume path to normal path
Start by changing "\Device" to "\\?":
`"\\Device\\HardiskVolume1\\path.exe"` //to
`"\\\\?\\HardiskVolume1\\path.exe"`
wchar_t buf[MAX_PATH];
wchar_t *ptr = wcsstr(processPath, L"\\Device");
if(ptr)
{
wcscpy_s(buf, L"\\\\?");
wcscat_s(buf, ptr + wcslen(L"\\Device"));
}
Now you can open buf in CreateFile, then use GetFinalPathNameByHandle to get
`"\\\\?\\C:\\path.exe"`
Note that wcsstr returns NULL if search string is not found. If search string was found and copy was successful, you end up overwriting processPath the way you have done that. Moreover, wcscpy_s is the secure version of wcscpy. If you don't want to use wcscpy_s correctly then just use wcscpy without using a random number like 100 as the argument.

On Windows, stat and GetFileAttributes fail for paths containing strange characters

The code below demonstrates how stat and GetFileAttributes fail when the path contains some strange (but valid) ASCII characters.
As a workaround, I would use the 8.3 DOS file name. But this does not work when the drive has 8.3 names disabled.
(8.3 names are disabled with the fsutil command: fsutil behavior set disable8dot3 1).
Is it possible to get stat and/or GetFileAttributes to work in this case?
If not, is there another way of determining whether or not a path is a directory or file?
#include "stdafx.h"
#include <sys/stat.h>
#include <string>
#include <Windows.h>
#include <atlpath.h>
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
// The final characters in the path below are 0xc3 (Ã) and 0x3f (?).
// Create a test directory with the name à and set TEST_DIR below to your test directory.
const char* TEST_DIR = "D:\\tmp\\VisualStudio\\TestProject\\ConsoleApplication1\\test_data\\Ã";
int main()
{
std::string testDir = TEST_DIR;
// test stat and _wstat
struct stat st;
const auto statSucceeded = stat(testDir.c_str(), &st) == 0;
if (!statSucceeded)
{
printf("stat failed\n");
}
std::wstring testDirW = s2ws(testDir);
struct _stat64i32 stW;
const auto statSucceededW = _wstat(testDirW.data(), &stW) == 0;
if (!statSucceededW)
{
printf("_wstat failed\n");
}
// test PathIsDirectory
const auto isDir = PathIsDirectory(testDirW.c_str()) != 0;
if (!isDir)
{
printf("PathIsDirectory failed\n");
}
// test GetFileAttributes
const auto fileAttributes = ::GetFileAttributes(testDirW.c_str());
const auto getFileAttributesWSucceeded = fileAttributes != INVALID_FILE_ATTRIBUTES;
if (!getFileAttributesWSucceeded)
{
printf("GetFileAttributes failed\n");
}
return 0;
}
The problem you have encountered comes from using the MultiByteToWideChar function. Using CP_ACP can default to a code page that does not support some characters. If you change the default system code page to UTF8, your code will work. Since you cannot tell your clients what code page to use, you can use a third party library such as International Components for Unicode to convert from the host code page to UTF16.
I ran your code using console code page 65001 and VS2015 and your code worked as written. I also added positive printfs to verify that it did work.
Don't start with a narrow string literal and try to convert it, start with a wide string literal - one that represents the actual filename. You can use hexadecimal escape sequences to avoid any dependency on the encoding of the source code.
If the actual code doesn't use string literals, the best resolution depends on the situation; for example, if the file name is being read from a file, you need to make sure that you know what encoding the file is in and perform the conversion accordingly.
If the actual code reads the filename from the command line arguments, you can use wmain() instead of main() to get the arguments as wide strings.

c++ - Execute a binary file from memory

Hello Guys I really need help in my c/c++ programming skills. I have to load a binary file, maybe a simple "hello World" and execute it directly from a buffer. Therefore I loaded my buffer with the binary file and tried to set the programming pointer to the buffer. But it doesn't work correctly. Could you please help me with useful suggestions?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
int main(int argc, const char * argv[]) {
FILE *fileptr;
char *buffer;
long filelen;
fileptr = fopen("helloworld", "rb"); //Open File in binary mode
fseek(fileptr, 0, SEEK_END); //Jump to the end of file
filelen = ftell(fileptr); //Get the current byte offset in File
rewind(fileptr); // Jump back to beginnig of the file
buffer = (char *)malloc((filelen+1)*sizeof(char));
fread(buffer, filelen, 1, fileptr);
fclose(fileptr);
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)*buffer;
}
The program instructions are placed in the read only region of the process memory called text code segment and it is decided when the exe is generated by the compiler. The OS simply won't expect program instructions in the stack or the heap! Otherwise viruses would have been very easy to made....

protobuf serializetocodedstream returns "false"

I am trying to serialize my Protocol Buffer message in Windows platform and my coding language is C++. After serialization is done it returns "false". Please find the below code and let me know where I am going wrong.
Proto file
message mobile_list{
required string name = 1;
required DeviceType type = 2;
required string imei = 3;
required bytes wifiAddress = 4;
optional bytes macAddress = 5;
}
Protocol buffer Code
#include <unistd.h>
#include "mobile.pb.h"
#include <iostream>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
using namespace google::protobuf::io;
using namespace std;
int main(int argv, char** argc){
mobile payload;
payload.set_name("Testing");
payload.set_type(mobile::Android);
payload.set_imei("123456");
payload.set_wifiAddress("96-00-OM-1E-4R-99");
payload.set_macAddress("96-00-OM-1E-4R-99");
int siz = payload.ByteSize();
char *pkt = new char [siz];
google::protobuf::io::ArrayOutputStream as(pkt,siz);
CodedOutputStream *coded_output = new CodedOutputStream(&as);
coded_output->WriteVarint32(payload.ByteSize());
payload.SerializeToCodedStream(coded_output);
return a.exec();
}
You are allocating a buffer equal to the size of the message (payload.ByteSize()), but then you are trying to write into it a varint followed by the actual message. This adds up to more than the message size. The serialization is failing because it ran out of space.
You should do:
int siz = payload.ByteSize();
siz += CodedOutputStream::VarintSize32(siz);
// ... continue as before ...
Also, on an unrelated note, you are calling ByteSize() multiple times, which is wasteful because the whole message has to be scanned and counted each time. Instead, you should keep a copy of the original size to reuse.

C++ reading large files part by part

I've been having a problem that I not been able to solve as of yet. This problem is related to reading files, I've looked at threads even on this website and they do not seem to solve the problem. That problem is reading files that are larger than a computers system memory. Simply when I asked this question a while ago I was referred too using the following code.
string data("");
getline(cin,data);
std::ifstream is (data);//, std::ifstream::binary);
if (is)
{
// get length of file:
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);
// allocate memory:
char * buffer = new char [length];
// read data as a block:
is.read (buffer,length);
is.close();
// print content:
std::cout.write (buffer,length);
delete[] buffer;
}
system("pause");
This code works well apart from the fact that it eats memory like fat kid in a candy store.
So after a lot of ghetto and unrefined programing, I was able to figure out a way to sort of fix the problem. However I more or less traded one problem for another in my quest.
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <iomanip>
#include <windows.h>
#include <cstdlib>
#include <thread>
using namespace std;
/*======================================================*/
string *fileName = new string("tldr");
char data[36];
int filePos(0); // The pos of the file
int tmSize(0); // The total size of the file
int split(32);
char buff;
int DNum(0);
/*======================================================*/
int getFileSize(std::string filename) // path to file
{
FILE *p_file = NULL;
p_file = fopen(filename.c_str(),"rb");
fseek(p_file,0,SEEK_END);
int size = ftell(p_file);
fclose(p_file);
return size;
}
void fs()
{
tmSize = getFileSize(*fileName);
int AX(0);
ifstream fileIn;
fileIn.open(*fileName, ios::in | ios::binary);
int n1,n2,n3;
n1 = tmSize / 32;
// Does the processing
while(filePos != tmSize)
{
fileIn.seekg(filePos,ios_base::beg);
buff = fileIn.get();
// To take into account small files
if(tmSize < 32)
{
int Count(0);
char MT[40];
if(Count != tmSize)
{
MT[Count] = buff;
cout << MT[Count];// << endl;
Count++;
}
}
// Anything larger than 32
else
{
if(AX != split)
{
data[AX] = buff;
AX++;
if(AX == split)
{
AX = 0;
}
}
}
filePos++;
}
int tz(0);
filePos = filePos - 12;
while(tz != 2)
{
fileIn.seekg(filePos,ios_base::beg);
buff = fileIn.get();
data[tz] = buff;
tz++;
filePos++;
}
fileIn.close();
}
void main ()
{
fs();
cout << tmSize << endl;
system("pause");
}
What I tried to do with this code is too work around the memory issue. Rather than allocating memory for a large file that simply does not exist on a my system, I tried to use the memory I had instead which is about 8gb, but I only wanted to use maybe a few Kilobytes of it if at all possible.
To give you a layout of what I am talking about I am going to write a line of text.
"Hello my name is cake please give me cake"
Basically what I did was read said piece of text letter by letter. Then I put those letters into a box that could store 32 of them, from there I could use something like xor and then write them onto another file.
The idea in a way works but it is horribly slow and leaves off parts of files.
So basically how can I make something like this work without going slow or cutting off files. I would love to see how xor works with very large files.
So if anyone has a better idea than what I have, then I would be very grateful for the help.
To read and process the file piece-by-piece, you can use the following snippet:
// Buffer size 1 Megabyte (or any number you like)
size_t buffer_size = 1<<20;
char *buffer = new char[buffer_size];
std::ifstream fin("input.dat");
while (fin)
{
// Try to read next chunk of data
fin.read(buffer, buffer_size);
// Get the number of bytes actually read
size_t count = fin.gcount();
// If nothing has been read, break
if (!count)
break;
// Do whatever you need with first count bytes in the buffer
// ...
}
delete[] buffer;
The buffer size of 32 bytes, as you are using, is definitely too small. You make too many calls to library functions (and the library, in turn, makes calls (although probably not every time) to OS, which are typically slow, since they cause context-switching). There is also no need of tell/seek.
If you don't need all the file content simultaneously, reduce the working set first - like a set of about 32 words, but since XOR can be applied sequentially, you may further simplify the working set with constant size, like 4 kilo-bytes.
Now, you have the option to use file reader is.read() in a loop and process a small set of data each iteration, or use memmap() to map the file content as memory pointer which you can perform both read and write operations.