Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hello All,

I have a program where I am trying to get flag values for whether a program has been unchecked, checked, or installed. The purpose is for this program to reboot the system but still be able to continue where it left off following the reboot. This program is cut down to one program for the same of not frusterating me trying to figure this out. Does anyone have any tips? It creates the StateFile but I am not sure how to code it to store those values of RSAFlag.State, and change those values when neccessary.

UPDATE: Ok I have cleaned up the code and moved some things around. So regarding strlen, how should I go about fixing that? I am not very good with this more complex coding. My origional program that would allow users to select between 60 different programs to install worked well but it was basic. The issue was that we found that a couple of the programs required a restart, that is why I have to start delving into more complex coding. Also, what would I call to in order to pass the RSAFlag.State value too? I thought it would be to strlen but everything I am trying is not working. Finding the solution through online research appears to be pointless as anything I can find regards console projects and not a windows application.

C++
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{		
HANDLE StateFile = CreateFile("E:\\StateFile.txt", GENERIC_ALL, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, SECURITY_ANONYMOUS);
	
char DataBuffer[MAX_PATH];
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
BOOL WriteStateFile = WriteFile(StateFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL);  
	 						   
     enum STATE{Unchecked, Checked, Installed};	
	struct STATE_FLAG	
	     {
    		STATE State;
    		STATE_FLAG(): State(Unchecked) {}
    	     };
    				      
    		STATE_FLAG RSAFlag;
						   	
bool checked = true;  
switch (message)                  /* handle the messages */
    {
    
     case WM_CTLCOLORSTATIC:
       {
    	HDC hdc = (HDC) wParam; 
    	SetTextColor(hdc, RGB(0,0,0));    
         SetBkMode (hdc, TRANSPARENT);

    	return (LRESULT)GetStockObject(NULL_BRUSH);   
       };        
        case WM_PAINT:  
             {          
               PAINTSTRUCT ps;    
               HDC hdc = BeginPaint( hwnd, &ps );  
                   TextOut( hdc, 20, 20, "Adobe Software:", 15);		
	          TextOut( hdc, 20, 70, "Microsoft Software:", 19);    	
	          TextOut( hdc, 20, 225, "Other:", 6);				
	          TextOut( hdc, 20, 415, "Model Software:", 15);			
	          TextOut( hdc, 20, 515, "OSR Software:", 13);			
               EndPaint( hwnd, &ps ); 						  
             };
             break;  
			 		
        case WM_CREATE:                                 
             
             {                              					
	       /*  Create SecureID Checkbox  */
                CreateWindowW(L"button", L"SecureID",
	       WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
	       20, 240, 188, 35,
	       hwnd, (HMENU) ID_RSA, NULL, NULL);
				
                /*  Create "Install" Button  */       
                CreateWindow(TEXT("button"), TEXT("Install"),
                WS_VISIBLE | WS_CHILD,
                650, 600, 80, 25,
                hwnd, (HMENU) ID_INSTALL, NULL, NULL);
                                   
                /*  Create "Cancel" Button  */
                CreateWindow(TEXT("Button"), TEXT("Cancel"),
                WS_VISIBLE | WS_CHILD,
                550, 600, 80, 25,
                hwnd, (HMENU) ID_CANCEL, NULL, NULL);
             }; 
             break;
                      
        case WM_COMMAND:     
              /*  If ID_CANCEL Is Pushed, Exit Program  */
              switch (LOWORD(wParam))
              {
                     case ID_CANCEL:
                          PostQuitMessage (0);
                          break;
              };   
                             
		switch (LOWORD(wParam))
              {      								 				  					 
	     /*  Identify If SecureID Is Checked  */
              case ID_RSA:
                 checked = IsDlgButtonChecked(hwnd, ID_RSA); 	   
		   if (checked) {
		       CheckDlgButton(hwnd, ID_RSA, BST_UNCHECKED);						 } else {
			    CheckDlgButton(hwnd, ID_RSA, BST_CHECKED);  						}								 											if(IsDlgButtonChecked(hwnd, ID_RSA)){
                                RSAFlag.State = Checked;								}	
	      break;						 			      }; 
			   
               switch (LOWORD(wParam))
               {  
                  case ID_INSTALL:
                                                                               	
                           	      
		        /*  Install RSA Secure ID  */							if(RSAFlag.State == Checked){
			CreateProcess(NULL,"C:\\Windows\\System32\\msiexec /i            E:\\programs\\RSA\\RSASecurIDToken400.msi /passive",
												        NULL,NULL,FALSE,								        CREATE_NEW_CONSOLE,
		        NULL,NULL,&si,&pi);						  				                                        WaitForSingleObject( pi.hProcess, INFINITE );					 						  					        RSAFlag.State = Installed;				                   }
																 
	                 /*  When program completes notify tech  */
		        CreateProcess(TEXT("E:\\Programs\\completion.bat"),
												        NULL,NULL,NULL,FALSE,							        CREATE_NEW_CONSOLE,							        NULL,NULL,&si,&pi);
WaitForSingleObject( pi.hProcess, INFINITE );					 							
	     break;                               
              };
Posted
Updated 27-Jun-14 5:36am
v3
Comments
[no name] 25-Jun-14 17:12pm    
Why does each switch statement have only one case statement? Consider combining these into one switch clause.
Member 10906282 26-Jun-14 9:38am    
Ok I will definitily take a look at that but do you have any suggestions to the question I asked?
Stefan_Lang 27-Jun-14 5:53am    
I've fixed the tag: changed it from C++ to C. There is no element of C++.

I would advise you to improve your question as well by copying that code again from your editor after making sure it doesn't auto-wrap lines - this code is very hard to read because of that!
Member 10906282 27-Jun-14 11:43am    
Here are the specific questions:
1. How do I write the RSAFlag.State value to StateFile for RSAFlag.State = Unchecked RSAFlag.State = Checked and RSAFlag.State = Installed? These State values are set during the checkbox and createprocess parts of the code, the Unchecked is supposed to be the default State value.

2. How would I go about fixing the issue you brought up about strlen?

Sorry about some of the code that I reposted, looked correct in the preview but the minute I post it the create process parts were all sorts of messed up.
Stefan_Lang 30-Jun-14 3:35am    
You should have posted this as a comment to my solution. Please see my response I've posted there.

1 solution

There are a couple of things you should do:

1. Avoid global variables! In this code snippet the variables may just as well defined locally. If they are used anywhere else, that may already be (part of) the reason for your problems! If not, there is no reason to define them globally.

2. Do not call functions to initialize global variables! Global variable initialization is done at the start of the program, before main() is called - in whatever order the compiler thinks is most efficient. You cannot control the order of such calls, and most likely the state of your program is undefined at the time the function is called. Therefore there is no guarantee the functions will deliver the expected results! Moreover, if there is a reason for these variables to be global (i. e. they are used in different places), then you can't be sure what state they are in anyway - it's therefore much better to only initialize them with trivial values that indicate they haven't been properly initialized yet (e. g. NULL-pointer), and do the function calls during the normal program execution, after verifying it hasn't been initialized before.

Special note: this is even true for trivial functions such as strlen - and your use of that function in initialization code is an actual error! As a consequence, the later (i. e. later in code, no guarantee they will be later in program execution!) 'intializations' catastrophically fail. (although, depending on the state of the memory that you access before intializing, the results may be just about anything)

3. Fix the code by
3.1 declaring StateFile and the other globals as local variables instead.
3.2 allocating a sufficiently large data buffer
3.3 filling the data buffer with actual data before trying to write it
3.4 Close the file when you're done
 
Share this answer
 
Comments
Stefan_Lang 30-Jun-14 3:32am    
In Response to Member10906282's ersponse in the comment section above:
Here are the specific questions:
1. How do I write the RSAFlag.State value to StateFile for RSAFlag.State = Unchecked RSAFlag.State = Checked and RSAFlag.State = Installed? These State values are set during the checkbox and createprocess parts of the code, the Unchecked is supposed to be the default State value.

2. How would I go about fixing the issue you brought up about strlen?

Sorry about some of the code that I reposted, looked correct in the preview but the minute I post it the create process parts were all sorts of messed up.

1. First of all, you can't write data that you don't yet have! So the first thing to do in your function is determine the data.

Second, you use WriteFile() to write a sequence of bytes. It is your task to store the data that you wish to write into that data buffer before writing it.

Third you need to copy the flag(s) to the data buffer. The format you use or the functions, don't matter all that much, as long as the functions that later read from that file are aware of the format you used and interpret the data correctly.

If the file is suposed to be human-readable, you should use the appropriate functions that print numbers in readable format. Since you need to first write to the buffer, you need sprintf() for that. Make sure you read and understand that function before you use it! There is plenty of documentation to be found on the web.


2. strlen is a function that determines the length of a well-defined C-String. A C-string is a sequence of characters that is terminated by a 0-character. You're using it however on a buffer that has never been initialized - there is no string inside, and it may contain any arbitrary values: maybe it has a 0-character at the very start, maybe there is a lengthy block of memory consisting of 5 million bytes that are not 0. So, calling this function may result in a value of, 0, 5 million, or any other number!

The real mistake of course is that you shouldn't be using the function at all! You are using it to pass a length to the function WriteFile. However, the expected value that you should pass is not the length of any existing string - it is the number of bytes that you intend to write! Of course, as explained above, there are no data to write yet - so why do you even call the function at that point???

The value you should pass here is not the length of any string, it is the number of bytes that the data you stored in your data buffer take. If you're just storing 1 or 0, then a length of 1 would be sufficient. If you store the value as a string "1" or "0", the length would be at least 2 bytes, as you need to store the string-terminating 0-byte as well. If you store additional values, the length must be adjusted with each value accordingly.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900