Writing new line character in file - c++

I just want write blank line into the file. i use following code but is not working.
char* RegID;
RegID = "10";
char* mndtime;
mndtime = "10";
char* resourcetype;
resourcetype = "Backup";
char* ressubtype;
ressubtype = "shadowprotect";
char* DataBuffer = new char[100];
StrCpy(DataBuffer,"<wpshadowprotectstatus>");
strcat(DataBuffer,"\n");
strcat(DataBuffer,"<mndtime>");
strcat(DataBuffer,RegID);
strcat(DataBuffer,"<\\mndtime>\n");
strcat(DataBuffer,"<resourcetype>");
strcat(DataBuffer,RegID);
strcat(DataBuffer,"<\\resourcetype>\n");
strcat(DataBuffer,"<ressubtype>");
strcat(DataBuffer,RegID);
strcat(DataBuffer,"<\\ressubtype>\n");
strcat(DataBuffer,"<jobname>");
strcat(DataBuffer,RegID);
strcat(DataBuffer,"<\\jobname>\n");
strcat(DataBuffer,"<jobstarttime>");
strcat(DataBuffer,RegID);
strcat(DataBuffer,"<\\jobstarttime>\n");
HANDLE hFile;
hFile = CreateFile("text.txt", // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
return 0;
}
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
bErrorFlag = WriteFile(hFile, // open file handle
DataBuffer, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
but i dont known why new line is not dump in text file.
Note :-
1)I dont want to use std:: library c++.
2)Dont want to use xml parser.

Use \r\n for line breaks on Windows.
And your XML is malformed. XML closing tags use the / character, not the \ character. And you are writing the same RegID variable for all of the XML values instead of using your other variables (mndtime, resourcetype, etc).

Windows?
If so, replace \n with \r\n. For FILE* / iostream it is done automatically by runtime, but not for WriteFile.
And, of course, you need two line endings to get blank line.
BTW, generating long string with strcat has O(N^2) complexity, which is very bad.

Related

Windows API ReadFile() skips one out of every two characters

My aim is to read all the text located in a file. For some reason whenever I read from the file and print the result (drawText), the buffer seems to be skipping one character every two positions. HELLO will become HLO and SCAVENGER becomes SAEGR.
This is for Windows API. I wonder if CreateFile() and ReadFile() are just fine and whether it's something else causing the issue.
void init(HDC hdc)
{
HANDLE hFile;
LPCSTR fileName = "c:\\Users\\kanaa\\Desktop\\code\\HW2_StarterCode\\words.txt";
hFile = CreateFileA(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwFileSize = GetFileSize(hFile, NULL);
DWORD dwBytesRead;
WCHAR* buffer = new WCHAR[dwFileSize / 2 + 1];
buffer[dwFileSize / 2] = 0;
bool read = ReadFile(hFile, buffer, dwFileSize, &dwBytesRead, NULL);
std::wstring wstr(buffer);
std::string str(wstr.begin(), wstr.end());
delete[] buffer;
CloseHandle(hFile);
if (read) parse(str, hdc);
}
void parse(std::string word, HDC hdc)
{
std::string to = word;
std::wstring wword = std::wstring(to.begin(), to.end());
const WCHAR* wcword = wword.c_str();
Graphics graphics(hdc);
drawText(&graphics, wcword);
}
The problem was the WCHAR buffer. Below are the corrections
CHAR* buffer = new CHAR[dwFileSize/sizeof(char) + 1];
bool read = ReadFile(hFile, buffer, dwFileSize, &dwBytesRead, NULL);
buffer[dwBytesRead] = 0;
You are processing the file data using a wchar_t[] buffer. wchar_t is 2 bytes in size on Windows. So, in the statement:
std::string str(wstr.begin(), wstr.end());
You are iterating through the file data 2 bytes at a time, interpreting each byte pair as a single wchar_t that gets truncated to a 1-byte char, discarding the other byte. That is why your str ends up skipping every other character.
Process the file data using a char[] buffer instead. However, there are easier ways to read 7/8-bit file data into a std::string.
Lastly, in this statement:
std::wstring wword = std::wstring(to.begin(), to.end());
This is not the correct way to convert a std::string to a std::wstring. All you are doing is iterating through the chars converting each one as-is into a 2-byte wchar_t. Windows APIs expect wchar_t strings to be encoded in UTF-16, which your code is not converting to. You need to use MultiByteToWideChar(), std::wstring_convert, or other equivalent Unicode library call to perform that conversion. In which case, you first need to know the encoding of the source file in order to convert it to Unicode correctly.

Why does WriteFile not run more than once?

Here's my code in which I've got on an infinite loop (to my knowledge)
while(true) {
DWORD TitleID = XamGetCurrentTitleId();
std::ostringstream titleMessageSS;
titleMessageSS << "Here's the current title we're on : " << TitleID << "\n\n";
std::string titleMessage = titleMessageSS.str(); // get the string from the stream
DWORD dwBytesToWrite = (DWORD)titleMessage.size();
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
bErrorFlag = WriteFile(logFile, titleMessage.c_str(), dwBytesToWrite, &dwBytesWritten, NULL);
CloseHandle(logFile);
Sleep(30000);
}
return NULL;
Does anyone see a reason as to why this only writes just once? I've waited over 5 minutes to see if it does anything in the end to no avail.
The Flag CREATE_NEW in CreateFile prevents the update of the file because CreateFile fail with ERROR_FILE_EXISTS. Use OPEN_ALWAYS instead.
Also it will always truncate. Replace GENERIC_WRITE with FILE_APPEND_DATA if you want to add a new line at the end of your logfile.
The whole CreateFile line should be:
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", FILE_APPEND_DATA , 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
Read CreateFile documentation carefully, it worth it, because it has a central role in the windows IO universe:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
look also add:
https://stackoverflow.com/a/9891875/1922748
As Martin James mentioned, from MSDN:
CREATE_NEW
Creates a new file, only if it does not already exist.
If the specified file exists, the function fails and the last-error
code is set to ERROR_FILE_EXISTS (80).
If the specified file does not exist and is a valid path to a writable
location, a new file is created.
So it seems that the handle is invalid after the first call, and hence WriteFile() fails.

How can I add new line to the file? [duplicate]

This question already has an answer here:
How to writefile in new line in WIN32 API
(1 answer)
Closed 8 years ago.
I am using windows programming my project requires working with files I tried the following code
HANDLE hFile;
char DataBuffer[255] = "This is some test data to write to the file.";
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DataBuffer[dwBytesToWrite+1]='\n';
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
hFile = CreateFile(L"Myfile.txt", // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
The below code was used add two lines to the file
bErrorFlag = WriteFile(
hFile, // open file handle
DataBuffer, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
char DataBuffer1[] = "\n\nThe second line of code\n\n";
dwBytesToWrite=sizeof(DataBuffer1);
bErrorFlag = WriteFile(
hFile, // open file handle
DataBuffer1, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL);
The program works fine but when i try to open "Myfile.txt" with the notepad i get the following results
" This is some test data to write to the file.The second line of code. "
Is there any other way to insert a new line to a file?
use \r\n instead of \n for newline.
instead of
char DataBuffer1[] = "\n\nThe second line of code\n\n";
Use
char DataBuffer1[] = "\r\nThe second line of code\r\n";

forwarding a file write with ShellExecute in c++ [duplicate]

I'm having a serious problem here. I need to execute a CMD command line via C++ without the console window displaying. Therefore I cannot use system(cmd), since the window will display.
I have tried winExec(cmd, SW_HIDE), but this does not work either. CreateProcess is another one I tried. However, this is for running programs or batch files.
I have ended up trying ShellExecute:
ShellExecute( NULL, "open",
"cmd.exe",
"ipconfig > myfile.txt",
"c:\projects\b",
SW_SHOWNORMAL
);
Can anyone see anything wrong with the above code? I have used SW_SHOWNORMAL until I know this works.
I really need some help with this. Nothing has come to light, and I have been trying for quite a while. Any advice anyone could give would be great :)
Redirecting the output to your own pipe is a tidier solution because it avoids creating the output file, but this works fine:
ShellExecute(0, "open", "cmd.exe", "/C ipconfig > out.txt", 0, SW_HIDE);
You don't see the cmd window and the output is redirected as expected.
Your code is probably failing (apart from the /C thing) because you specify the path as "c:\projects\b" rather than "c:\\projects\\b".
Here is my implementation of a DosExec function that allows to (silently) execute any DOS command and retrieve the generated output as a unicode string.
// Convert an OEM string (8-bit) to a UTF-16 string (16-bit)
#define OEMtoUNICODE(str) CHARtoWCHAR(str, CP_OEMCP)
/* Convert a single/multi-byte string to a UTF-16 string (16-bit).
We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string.
*/
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
size_t len = strlen(str) + 1;
int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
return wstr;
}
/* Execute a DOS command.
If the function succeeds, the return value is a non-NULL pointer to the output of the invoked command.
Command will produce a 8-bit characters stream using OEM code-page.
As charset depends on OS config (ex: CP437 [OEM-US/latin-US], CP850 [OEM 850/latin-1]),
before being returned, output is converted to a wide-char string with function OEMtoUNICODE.
Resulting buffer is allocated with LocalAlloc.
It is the caller's responsibility to free the memory used by the argument list when it is no longer needed.
To free the memory, use a single call to LocalFree function.
*/
LPWSTR DosExec(LPWSTR command){
// Allocate 1Mo to store the output (final buffer will be sized to actual output)
// If output exceeds that size, it will be truncated
const SIZE_T RESULT_SIZE = sizeof(char)*1024*1024;
char* output = (char*) LocalAlloc(LPTR, RESULT_SIZE);
HANDLE readPipe, writePipe;
SECURITY_ATTRIBUTES security;
STARTUPINFOA start;
PROCESS_INFORMATION processInfo;
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.bInheritHandle = true;
security.lpSecurityDescriptor = NULL;
if ( CreatePipe(
&readPipe, // address of variable for read handle
&writePipe, // address of variable for write handle
&security, // pointer to security attributes
0 // number of bytes reserved for pipe
) ){
GetStartupInfoA(&start);
start.hStdOutput = writePipe;
start.hStdError = writePipe;
start.hStdInput = readPipe;
start.dwFlags = STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
start.wShowWindow = SW_HIDE;
// We have to start the DOS app the same way cmd.exe does (using the current Win32 ANSI code-page).
// So, we use the "ANSI" version of createProcess, to be able to pass a LPSTR (single/multi-byte character string)
// instead of a LPWSTR (wide-character string) and we use the UNICODEtoANSI function to convert the given command
if (CreateProcessA(NULL, // pointer to name of executable module
UNICODEtoANSI(command), // pointer to command line string
&security, // pointer to process security attributes
&security, // pointer to thread security attributes
TRUE, // handle inheritance flag
NORMAL_PRIORITY_CLASS, // creation flags
NULL, // pointer to new environment block
NULL, // pointer to current directory name
&start, // pointer to STARTUPINFO
&processInfo // pointer to PROCESS_INFORMATION
)){
// wait for the child process to start
for(UINT state = WAIT_TIMEOUT; state == WAIT_TIMEOUT; state = WaitForSingleObject(processInfo.hProcess, 100) );
DWORD bytesRead = 0, count = 0;
const int BUFF_SIZE = 1024;
char* buffer = (char*) malloc(sizeof(char)*BUFF_SIZE+1);
strcpy(output, "");
do {
DWORD dwAvail = 0;
if (!PeekNamedPipe(readPipe, NULL, 0, NULL, &dwAvail, NULL)) {
// error, the child process might have ended
break;
}
if (!dwAvail) {
// no data available in the pipe
break;
}
ReadFile(readPipe, buffer, BUFF_SIZE, &bytesRead, NULL);
buffer[bytesRead] = '\0';
if((count+bytesRead) > RESULT_SIZE) break;
strcat(output, buffer);
count += bytesRead;
} while (bytesRead >= BUFF_SIZE);
free(buffer);
}
}
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
CloseHandle(writePipe);
CloseHandle(readPipe);
// convert result buffer to a wide-character string
LPWSTR result = OEMtoUNICODE(output);
LocalFree(output);
return result;
}
You should use CreateProcess on cmd.exe with the /C parameter to tunnel the ipconfig command. The > does not work per se on the command line. You have to redirect programmatically the stdout.
I have a similar program [windows7 and 10 tested] on github
https://github.com/vlsireddy/remwin/tree/master/remwin
This is server program which
listens on "Local Area Connection" named interface in windows for UDP port (5555) and receives udp packet.
received udp packet content is executed on cmd.exe [please not cmd.exe is NOT closed after running the command and the output string [the output of the executed command] is fedback to the client program over same udp port].
In other words,
command received in udp packet -> parsed udp packet -> executed on cmd.exe -> output sent back on same port to client program
This does not show "console window"
No need for someone to execute manually command on cmd.exe
remwin.exe can be running in background and its a thin server program
To add to #Cédric Françoys answer, I fixed a few things in his code for a Windows build:
Missing function definition:
To make the code compile, add the following function definition:
#define UNICODEtoANSI(str) WCHARtoCHAR(str, CP_OEMCP)
LPSTR WCHARtoCHAR(LPWSTR wstr, UINT codePage) {
int len = (int)wcslen(wstr) + 1;
int size_needed = WideCharToMultiByte(codePage, 0, wstr, len, NULL, 0, NULL, NULL);
LPSTR str = (LPSTR)LocalAlloc(LPTR, sizeof(CHAR) * size_needed);
WideCharToMultiByte(codePage, 0, wstr, len, str, size_needed, NULL, NULL);
return str;
}
Unsafe CRT string function calls:
To make the code compile, replace strcpy and strcat with the following calls
strcpy_s(output, sizeof(output), "");
strcat_s(output, RESULT_SIZE, buffer);
Remove redundant null-termination:
Remove in the do-while loop:
buffer[bytesRead] = '\0';
because strcat_s takes care of that.
You could use
string command = "start /B cmd /c " + myCommand;
system(command.c_str());
Hopefully this works for you

Creating a file with the same name as registry

I want to create a text file with the same name as a registry.
Say, I get the variable valueName, and I want it's value to be the name of a .txt file in C:\ How can I do that?
Almost final code:
void EnumerateValues(HKEY hKey, DWORD numValues)
{
for (DWORD dwIndex = 0; dwIndex < numValues; dwIndex++)
{BOOL bErrorFlag = FALSE;
char valueName[64];
DWORD valNameLen = sizeof(valueName);
DWORD dataType;
DWORD dataSize = 0;
DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
NULL, &dataType, NULL, &dataSize);
if (retval == ERROR_SUCCESS)
{//pregatesc calea
char* val = new char[strlen(valueName)];
sprintf(val, "C:\\%s.txt", valueName);
printf("S-a creat fisierul: %s\n", val);
//creez/suprascriu fisierul
HANDLE hFile;
hFile=CreateFile(val,GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ,
NULL, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile == INVALID_HANDLE_VALUE)
{ printf("Eroare la creat fisierul %s!\n",val);
}
//sciru in fisier
char str[] = "Example text testing WriteFile";
DWORD bytesWritten=0;
DWORD dwBytesToWrite = (DWORD)strlen(str);
bErrorFlag=WriteFile(hFile, str, dwBytesToWrite, &bytesWritten, NULL);
if (FALSE == bErrorFlag)
{
printf("Eroare la scriere in fisier\n");
}
//inchid fisierul
CloseHandle(hFile);
}
//eroare regenumv
else printf("\nError RegEnumValue");
}
}
The fundamental problem is that you seem to want to convert a registry key, HKEY into a path. And there's no API to do that. You will need to keep track of the path and pass it to the function in the question, along with the HKEY.
You are passing uninitialized values to RegEnumValue, specifically dataSize. Since you don't care about the data, don't ask for it. Pass NULL for the data pointer, and zero for data size.
Your call to new is not allocating enough memory. You need space for the directory name, the file extension, and the null-terminator.
These problems are exacerbated by your complete neglect for error checking. That might sound harsh, but frankly you need some shock treatment. In order to be able to fail gracefully you need to check for errors. More pressing for you, in order to be able to debug code, you need to check for errors.
You've tagged the code C++ but write as if it were C. If you really are using C++ then you can use standard containers, std::string, avoid raw memory allocation and the result leaks. Yes, you code leaks as it stands.
first of all your program is more C like than C++, but if you want to solve this in C++ you can use stringstream in the following way:
std::stringstream stream;
stream << "C:\\";
stream << valueName;
stream << ".txt";
std::string filename(stream.str());
HANDLE hFile=CreateFile(filename.c_str() ,GENERIC_READ,FILE_SHARE_READ,
NULL, CREATE_NEW , FILE_ATTRIBUTE_NORMAL,NULL);
Also you need a include:
#include <sstream>