System Error 1784

I'm starting to hate the 'system'. I added a 'WriteFile' function and it's throwing a System Error 1784: The supplied user buffer is not valid for the requested operation. ERROR_INVALID_USER_BUFFER
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//handle declarations
	HWND txtfld;
	HWND btn;
	HWND txtbx;
	HANDLE hfile;
	HWND txtbx2;
	HWND txtbx3;
	HWND txtbx4;
	HWND txtbx5;
	HWND txtbx6;
	HWND txtbx7;
	HANDLE hfile2;
//variable declarations
    std::string line;
    char* ntns=new char[8000];
    size_t srchd;
    char* dtls=new char[200];
    char txtmem[40];
    char txtmem2[40];
    char txtmem3[40];
    char txtmem4[40];
    char txtmem5[40];
    char txtmem6[40];
    char txtmem7[40];
    char* add_buf=new char[8001];
    char* ntns2=new char[8000];
	
/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {

	
	switch(Message) {
	
    case WM_CREATE:
    	{
    		txtfld = CreateWindowA("STATIC", "    CommonwealthCore Database Application", WS_VISIBLE | WS_CHILD | WS_BORDER, 150, 20, 300, 20, hwnd, NULL, NULL, NULL);
    		txtfld = CreateWindowA("STATIC", "                     Find A Nation:", WS_VISIBLE | WS_CHILD | WS_BORDER, 20, 70, 250, 20, hwnd, NULL, NULL, NULL);
    		txtbx = CreateWindowA("EDIT", "NationShortName", WS_VISIBLE | WS_CHILD | WS_BORDER, 20, 110, 250, 20, hwnd, NULL, NULL, NULL);
    		btn = CreateWindowA("BUTTON", "SEARCH", WS_VISIBLE | WS_CHILD | WS_BORDER, 100, 150, 100, 30, hwnd, (HMENU) 1, NULL, NULL);
    		txtfld = CreateWindowA("STATIC", "            Add Nation To Database:", WS_VISIBLE | WS_CHILD | WS_BORDER, 300, 70, 250, 20, hwnd, NULL, NULL, NULL);
    		txtbx2 = CreateWindowA("EDIT", "NationShortName", WS_VISIBLE | WS_CHILD | WS_BORDER, 300, 110, 250, 20, hwnd, NULL, NULL, NULL);
    		txtbx3 = CreateWindowA("EDIT", "Population (no commas)", WS_VISIBLE | WS_CHILD | WS_BORDER, 300, 150, 250, 20, hwnd, NULL, NULL, NULL);
    		txtbx4 = CreateWindowA("EDIT", "Tax Rate (do not include % sign)", WS_VISIBLE | WS_CHILD | WS_BORDER, 300, 190, 250, 20, hwnd, NULL, NULL, NULL);
    		txtbx5 = CreateWindowA("EDIT", "% Defense Spending (no % sign)", WS_VISIBLE | WS_CHILD | WS_BORDER, 300, 230, 250, 20, hwnd, NULL, NULL, NULL);
    		txtbx6 = CreateWindowA("EDIT", "Economy Points", WS_VISIBLE | WS_CHILD | WS_BORDER, 300, 270, 250, 20, hwnd, NULL, NULL, NULL);
    		txtbx7 = CreateWindowA("EDIT", "Password (case sensitive)", WS_VISIBLE | WS_CHILD | WS_BORDER, 300, 310, 250, 20, hwnd, NULL, NULL, NULL);
    		btn = CreateWindowA("BUTTON", "ADD", WS_VISIBLE | WS_CHILD | WS_BORDER, 380, 350, 100, 30, hwnd, (HMENU) 2, NULL, NULL);
    		break;
    	}

	case WM_COMMAND:
		{
		
		switch (LOWORD (wParam) )
		{
			case 1:
				{
					//search engine--------------------------
					int gwt1=0;
					char * txtmemptr = &txtmem[0];
					gwt1=GetWindowText(txtbx, &txtmem[0], 40);
					::MessageBeep(MB_ICONERROR);
					::MessageBoxA(hwnd, txtmemptr , "Searching For Nation:", MB_OK);
					hfile=CreateFile("nations.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
					int x=ReadFile(hfile, (LPVOID)ntns, 8000, NULL, NULL);
					std::string ntnst=(std::string)ntns;
					srchd=ntnst.find(txtmemptr);
					//display details------------------------
					if(srchd!=std::string::npos)
					{
					::MessageBoxA(hwnd, "The above nation was found.\nDetails will be displayed.", txtmemptr, MB_OK);
					dtls=(char*)ntnst.c_str();
					std::vector<char> rslts;
					for(int i=0;i<148;i++)
					{
					rslts.push_back(dtls[srchd+i]);
					}
					std::stringstream ssrslts;
					for(int j=0;j<148;j++)
					{
					ssrslts << rslts[j];
					}
					std::string strrslts=ssrslts.str();
					char * rsltst=new char[148];
					rsltst=(char*)strrslts.c_str();
					CreateWindowA("STATIC", rsltst, WS_VISIBLE | WS_CHILD | WS_BORDER, 20, 200, 250, 200, hwnd, NULL, NULL, NULL);
					}
					else
					{
						::MessageBoxA(hwnd, "The above nation was not found.", txtmemptr, MB_OK);
					}
					CancelIo(hfile);
					break;
				}
			case 2:
				{
					hfile=CreateFile("nations.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
					hfile2=CreateFile("nations.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
					//read/save file before re-writing-------
					int x=ReadFile(hfile, (LPVOID)ntns2, 8000, NULL, NULL);
					std::string ntns2t=(std::string)ntns2;
					CancelIo(hfile);
					//add nation to database-----------------
					int gwt2=0;
					int gwt3=0;
					int gwt4=0;
					int gwt5=0;
					int gwt6=0;
					int gwt7=0;
					char * txtmemptr2=&txtmem2[0];
					char * txtmemptr3=&txtmem3[0];
					char * txtmemptr4=&txtmem4[0];
					char * txtmemptr5=&txtmem5[0];
					char * txtmemptr6=&txtmem6[0];
					char * txtmemptr7=&txtmem7[0];
					gwt2=GetWindowText(txtbx7, &txtmem2[0], 40);
					std::string txtmem2str=txtmem2;
					if(txtmem2str != "CCPW01")
					{
						::MessageBoxA(hwnd, "Incorrect Password.\nApplication Will Terminate.", "PERMISSIONS ERROR", MB_OK);
						PostQuitMessage(0);
					}
					else
					{
						::MessageBoxA(hwnd, "Password Accepted\nClick 'OK' To Proceed.", "Password Accepted", MB_OK);
					}
					gwt3=GetWindowText(txtbx2, &txtmem3[0], 40);
					gwt4=GetWindowText(txtbx3, &txtmem4[0], 40);
					gwt5=GetWindowText(txtbx4, &txtmem5[0], 40);
					gwt6=GetWindowText(txtbx5, &txtmem6[0], 40);
					gwt7=GetWindowText(txtbx6, &txtmem7[0], 40);
					std::stringstream add_buf_strm;
					add_buf_strm << ntns2t << "\n" << "Nation: " << txtmem3 << "\n" << "Population: " << txtmem4 << "\n" << "% Tax Rate: " << txtmem5 << "\n" << "% Defense Spending: " << txtmem6 << "\n" << "Economy Points: " << txtmem7 << "\n" << "                                       ";
					std::string add_buf_pre = add_buf_strm.str();
					add_buf=(char*)add_buf_pre.c_str();
					::MessageBoxA(hwnd, (LPCSTR)add_buf, "Received Input:", MB_OK);
					DWORD num=8000;
					int rslt_of_wf = WriteFile(hfile2, (LPCVOID)add_buf, num, NULL, NULL);
					ErrorExit("Error:");
					if(rslt_of_wf !=0)
					{
						::MessageBoxA(hwnd, "Process was successful.\nFile added to database.\nSearch nation to confirm.", "SUCCESS", MB_OK);
					}
					else
					{
						::MessageBeep(MB_ICONERROR);
						::MessageBoxA(hwnd, "Process failed.\nUnable to add file to database.", "FAILURE", MB_OK);
					}
				}
				
		}
}


I've tried everything. The CancelIo function, tinkering with the buffer size, etc.

I've spend the past 4 or so hours researching and trying things and nothing works. It seems that most people get this error because they didn't allow enough space for the buffer. This is weird because my ReadFile functions work fine, and the ::MessageBox displays exactly what should be written to the file. (using the exact same var, just casted differently).

So is there a solution to this problem? From all of my research, i've found not a single article/post (not even on stackoverflow).

Thanks again,
~Hom
To be honest I don't use these functions myself, so don't have direct experience to offer. But I thought I'd look through the code.

One thing which leapt out at me was this memory leak:
84
85
    char * rsltst = new char[148];
    rsltst = (char*)strrslts.c_str();

A char pointer rsltst is declared. The new operator is used to allocate a block of 148 bytes, and the address of the newly-requested memory is saved in the pointer rsltst. Then on the very next line, the address stored in the pointer is replaced, by assigning the address of the c_str(). Thus those 148 bytes can never be accessed as the address was discarded.

It looks like there is a similar issue with add_buf.
At line 25 there is this: char* add_buf=new char[8001];, an 8kb buffer is allocated.
later, at line 135 is this: add_buf=(char*)add_buf_pre.c_str();
Another memory leak. Those 8001 bytes can no longer be accessed as the pointer now points to the c_str().

The fact that you have to cast using (char*)add_buf_pre.c_str() should flag up a warning sign. The c_str() address is a const char* meaning that memory cannot be modified.

Possibly the offending code could be replaced by what I guess might have been the intention, actually copy the string into the buffer, using strcpy.
http://www.cplusplus.com/reference/cstring/strcpy/
or a bit safer, strncpy;
http://www.cplusplus.com/reference/cstring/strncpy/
example:
 
strcpy(rsltst, strrslts.c_str() ); // copy from strrslts to buffer rsltst  




But still, you should also take care to match new [] with a corresponding delete [] when finished, to avoid memory leaks.
Last edited on
Chervil:

Thanks. The strcpy() had me on the right path. Apparently if you #include <windows.h> you have to use the WinApi alternative, StringCbCopyA(), which does the exact same thing. (on MSDN it even says use as replacement for strcpy() )

But there was an even worse problem. Once I got to around the WriteFile function, the program would crash. It turns out that in my debugging efforts (after I posted this question) I changed the writefile to this:
1
2
LPDWORD bytesWritten;
int rslt_of_wf = WriteFile(hfile2, (LPCVOID)add_buf, num, bytesWritten, NULL);

When I changed the second to last argument to NULL it worked perfectly!

Thanks (once again)
~Hom
LPDWORD means a pointer to a DWORD, but no memory allocated for the DWORD itself. So change the code like this:
1
2
3
4
DWORD bytesWritten;
int rslt_of_wf = WriteFile(hfile2, (LPCVOID)add_buf, num, &bytesWritten, NULL);

	


Also the cast to LPCVOID looks suspicious to me, why do you need that ?
Parameter 2 of WriteFile is of type LPCVOID.

~Hom
Yes, it is (LPCVOID = const void*). I just said that the cast is not required, as the compiler does the conversion automatically.
Last edited on
+1 to modoran

@ OP: You sometimes have to question the things you see in the MSDN tutorials. The conspiracy theorist in me suspects that it's intentional for some reason. Almost like they are saying "Ha ha, you don't know what you're doing so we're going to make you do senseless busy work!".
MSDN...The fact that they call them 'tutorials' or even 'reference' is a disgrace to those terms....
Topic archived. No new replies allowed.