Updating environment variable from C++ fails erratically in version 14...

May 24, 2010
855
0
Northlake, Il
Vince, an update to the thread I just posted in response to your question. I got the impression you weren't aware that 32-bit programs ran in 32-bit address spaces from your statement:
Code:
I thought your machine was 64-bit!
And the reason I got that impression so strongly is because you said:
Code:
I know the 32(pset)/32(target_proc)/32(OS) one works.
and that was exactly my point. PSet 32/32/32 (by the way, you clearly knew what I meant by that in the above with the qualification that "32(OS)" is "32(TCC)" in my case) again does not work on my machine, and I just did it again starting from scratch in a new 32-bit TCC trying to update another 32-bit TCC and got:
Code:
CreateRemoteThread failed: Access is denied.
And I'm running as a Windows 7 pseudo-administrator (and getting no UAC prompt).

- Dan
 
May 24, 2010
855
0
Northlake, Il
Vince, the 32-bit DynamicSetEnvVar doesn't run at all (a message box) on my machine because I don't have the mfc100u.dll (it's evidently doesn't come with the Visual C++ version that I have).

As far as your response to my response to Scott goes, you didn't tell me anything I didn't already know. If TCC can't natively (easily) access an "environment" variable (not really!) stored in the registry, whatever is the point of doing that from TCC's "point of view"? (A function available in a plug-in doesn't count because that's not part of the "native" TCC). And it's not like other "environment variables" in that it clearly doesn't natively appear in the environment (hence the need for the "GetEnv" plugin function in the first place).

- Dan
 
May 20, 2008
9,708
67
Syracuse, NY, USA
Vince, the 32-bit DynamicSetEnvVar doesn't run at all (a message box) on my machine because I don't have the mfc100u.dll (it's evidently doesn't come with the Visual C++ version that I have).
I had that problem before I installed VS2010. If you need it, you can get the VC2010 redistributable package from MS:

http://www.microsoft.com/en-us/download/details.aspx?id=14632

["This package installs runtime components of C Runtime (CRT), Standard C++, ATL, MFC, OpenMP and MSDIA libraries."]
 
May 24, 2010
855
0
Northlake, Il
Vince, please excuse the stupid question. Where is that DLL copied to? Installing it supposedly installed it but I haven't rebooted (I'd really prefer not to) and your program still can't find it. And re-installing it brings up the "repair" option, which I do and which would seem to indicate that everything's OK. And a "Dir \mfc100u.dll /s /f" doesn't find it on either of my hard drive partitions. I can't figure this out. Weird.

- Dan
 
May 24, 2010
855
0
Northlake, Il
Vince, an update, and this is even stranger. I found on the web that the DLLs are supposed to be copied to "%Windir%\System32", but they aren't there. However and again, the install "repair" option would seem to indicate that it ran OK (and therefor presumably "repaired" the installation) and "uninstalling" it runs without complaint, also. Weirder. (I just love Microslop!) - Dan
 
May 20, 2008
9,708
67
Syracuse, NY, USA
Vince, please excuse the stupid question. Where is that DLL copied to? Installing it supposedly installed it but I haven't rebooted (I'd really prefer not to) and your program still can't find it. And re-installing it brings up the "repair" option, which I do and which would seem to indicate that everything's OK. And a "Dir \mfc100u.dll /s /f" doesn't find it on either of my hard drive partitions. I can't figure this out. Weird.

- Dan
On my 32-bit Win7 it's in \Windows\system32. If you're trying to run the 32-bit version of DynamicSetEnvVar I suppose you'll also have to get the 32-bit redistributable package: http://www.microsoft.com/en-us/download/details.aspx?id=5555

On Win7 I always use "/a" when I'm doing "dir /s" (to see hidden stuff). And in Win7/64 there's something called "file system redirector" which I'm clueless about. Read about it here. I doubt the Code Project program knows/does anything about it.
 
May 24, 2010
855
0
Northlake, Il
Vince, that did the trick for setting an environment variable in a 32-bit process. But it's got the Code Project's GUI interface, whereas your original PSet was a command-line tool. Is that because the one you sent me is experimental, so to speak? - Dan
 
May 20, 2008
9,708
67
Syracuse, NY, USA
Vince, that did the trick for setting an environment variable in a 32-bit process. But it's got the Code Project's GUI interface, whereas your original PSet was a command-line tool. Is that because the one you sent me is experimental, so to speak? - Dan
DynamicSetEnvVar **is** Code Project's application; I simply built it.

PSET is mine and is still a command line tool.

32-bit and 64-bit versions of each are on ftp://lucky.syr.edu.

P.S. ... in four separate zip files
 
May 24, 2010
855
0
Northlake, Il
Well, thank you, Vince, but I don't really understand why you did that. I ran the Code Project's program myself, and it worked for 32-bit processes but not for 64-bit processes, the same as the one you gave me. The issue was/is doing it for 64-bit processes. But thanks again, anyway. - Dan
 
May 20, 2008
9,708
67
Syracuse, NY, USA
Well, thank you, Vince, but I don't really understand why you did that. I ran the Code Project's program myself, and it worked for 32-bit processes but not for 64-bit processes, the same as the one you gave me. The issue was/is doing it for 64-bit processes. But thanks again, anyway. - Dan
Are both PSETs (the new ones) working ... the 32-bit one for a 32-bit target process and the 64-bit one for a 64-bit target process?
 
May 24, 2010
855
0
Northlake, Il
Vince, I just this moment finished testing them, and yes. (However, if you're going to put these things out into the world, so to speak, the 64-bit pset should be named pset64.exe so that it is clear as to what kind of target processes it's able to handle.) (You might also want to make the error messages more reflective of what the problem is (targeting the wrong process type; i.e., "You must use PSet64" and "You must use PSet") rather than just stating what Windows API failed. The later is useless information from a user's perspective.) Although, now that I think of it (as usual!), targeting a 32-bit TCC instance from a 64-bit PSet just crashes the 32-bit TCC instance. You might be able to tell if the process failed (I no longer remember), but crashing the target TCC instance is an unacceptable outcome if it can be avoided (maybe it can't). While it would be somewhat too late, at least if you can tell that the process failed you could emit an error message to the effect "The TCC instance crashed because it was 32-bit and you used the 64-bit PSet on it."

However, unless 1. I can tell whether my target is 64-bit or 32-bit, and 2. I have code to set a variable that works for each target type (knowing what it is) that runs in 32-bit mode, this is all academic for me (although I was glad to test your stuff). My program needs to run equally well in both 32-bit and 64-bit TCC sessions. (Although, now that I think about it a bit, failure trying it one way could be tested for and the other way tried if that's the case.)

Although (and please forgive me for my bad memory here if that's the case) is it true that you used exactly the same source for both the 32-bit and 64-bit DynamicSetEnvVars and the only difference was that one was compiled for 32-bit and the other compiled for 64-bit? If that is the case then it does me no good whatsoever because I want one program that is able to target both 32-bit and 64-bit TCC instances. And even if the sources were somewhat different, if the 32-bit version had to be compiled for 32 bits and the 64-bit version had to be compiled for 64 bits the same thing is true for me - I intend for there to be a single executable that has to run in both 32- and 64-bit TCC instances, and if that can't be achieved I'm left with using file(s) to store my persistent data as I am working on doing now. - Dan
 
May 20, 2008
9,708
67
Syracuse, NY, USA
Vince, I just this moment finished testing them, and yes. (However, if you're going to put these things out into the world, so to speak, the 64-bit pset should be named pset64.exe so that it is clear as to what kind of target processes it's able to handle.) (You might also want to make the error messages more reflective of what the problem is (targeting the wrong process type; i.e., "You must use PSet64" and "You must use PSet") rather than just stating what Windows API failed. The later is useless information from a user's perspective.) Although, now that I think of it (as usual!), targeting a 32-bit TCC instance from a 64-bit PSet just crashes the 32-bit TCC instance. You might be able to tell if the process failed (I no longer remember), but crashing the target TCC instance is an unacceptable outcome if it can be avoided (maybe it can't). While it would be somewhat too late, at least if you can tell that the process failed you could emit an error message to the effect "The TCC instance crashed because it was 32-bit and you used the 64-bit PSet on it."

However, unless 1. I can tell whether my target is 64-bit or 32-bit, and 2. I have code to set a variable that works for each target type (knowing what it is) that runs in 32-bit mode, this is all academic for me (although I was glad to test your stuff). My program needs to run equally well in both 32-bit and 64-bit TCC sessions. (Although, now that I think about it a bit, failure trying it one way could be tested for and the other way tried if that's the case.)

Although (and please forgive me for my bad memory here if that's the case) is it true that you used exactly the same source for both the 32-bit and 64-bit DynamicSetEnvVars and the only difference was that one was compiled for 32-bit and the other compiled for 64-bit? If that is the case then it does me no good whatsoever because I want one program that is able to target both 32-bit and 64-bit TCC instances. And even if the sources were somewhat different, if the 32-bit version had to be compiled for 32 bits and the 64-bit version had to be compiled for 64 bits the same thing is true for me - I intend for there to be a single executable that has to run in both 32- and 64-bit TCC instances, and if that can't be achieved I'm left with using file(s) to store my persistent data as I am working on doing now. - Dan
 
May 20, 2008
9,708
67
Syracuse, NY, USA
PSET is not particularly for public consumption. If I can figure out how to tell if the target process is 32-bit or 64-bit I'll enhance PSET and my @PSET[] TCC plugin so it won't crash a non-compatible target.

I really doubt it's possible for any *one* such app to target both 32 and 64 bit processes. An app can't LoadLibrary() if the library isn't the same "bitness" as itself; so it can't get the addreses of functions that have to be injected into the target (functions like SetEnvironmentVariable() to name just one).

I used exactly the same code to build both versions of the Code Project app. In DevStudio (2008 or 2010) it's just a matter of creating an x64 configuration; you can even "batch build" them both at once. I only had to change one instance of "int" (32-bits) to "SIZE_T" (32 or 64 bit, depending on the build).
 
May 24, 2010
855
0
Northlake, Il
Thanks for the info, Vince, I suspected as much (I really didn't think about it too deeply because my suspicion that it couldn't be (at least easily!) done was quite strong). So I will continue to write the code that replaces the environment variable(s) by files; it's not the most elegant solution, but it is probably the only practical solution and it's guaranteed to work (at least if I code it correctly!).

I tend to think that this is the end of this (rather long!) discussion. Thanks again!

- Dan
 
May 29, 2008
543
3
Groton, CT
(Much, much later)

I've downloaded PSET64 and see that it mostly works, but the syntax PSET64 <pid> without further arguments produces a blank line, not the command line of the target process. I can live without it, but it would be nice to get this functionality back.

Perhaps I'm getting forgetful -- in which plugin is the function @PSET ?
 
May 29, 2008
543
3
Groton, CT
I spoke too soon. I find that (where PSET invokes PSET64.EXE)
Code:
PSET <pid>
yields a blank line;
Code:
PSET <pid> *
(correctly) lists all the environment variables for process <pid>;
but
Code:
PSET <pid> <envvarname>
produces the NAME of the environment variable as entered on the command line, not the value. In other words, it acts like an expensive ECHO command when the environment variable exists, with an error message if it doesn't; and
Code:
PSET <pid> <envvarname>=<value>
works correctly.

Since I'm only using the last syntax, I'm not in a rush for a fix, but a fix eventually would be appreciated.
Windows 7 x64 with TCC 15.
 
Last edited:
May 20, 2008
9,708
67
Syracuse, NY, USA
I haven't looked at PSET in years. I doubt it was tested on X64 since I don't have access to an X64 system. PSET injects code into the remote process which definitely won't work between processes of different "bitness".. I'm glad it partially works. What about the 32-bit version? And what about @PSET from the SYSUTILS plugin (both 32 and 64 bit)? I'll look for anything obvious in the code, but most likely I won't be able to do anything about it until I get a 64-bit system (which isn't likely to be soon).
 
May 29, 2008
543
3
Groton, CT
Vince, so I'm willing to help you test, now that I have an x64 system. I'm strictly using it in TCC to communicate with other TCC and TCMD processes (for now).

@PSET from SYSUTILS64 fails by killing the TCC process from which it's issued.

Again, I'm willing to test things, within reason.

So, I guess we need a function that will determine the "bitness" of a process. @BITNESS[pid] ==> 32 or 64 (or 16?)

Note, I edited my previous post about PSET pid var.

Thanks for the quick response.
Regards,

Thanks for the quick response earlier.
 
May 20, 2008
9,708
67
Syracuse, NY, USA
I found bugs in the 32-bit of PSET that made it behave as you described the 64-bit version behaving. Maybe a quick-fix tomorrow. But you might have to tolerate seeing some variables you're not accustomed to seeing:
Code:
p:\pset\release> pset32 5968 *
=C:=C:\
=G:=G:\
=H:=H:\
=L:=L:\
=P:=P:\pset\Release
ALLUSERSPROFILE=C:\ProgramData[/CODE
 
May 20, 2008
9,708
67
Syracuse, NY, USA
I uploaded new ones. PSET.ZIP contains PSET32.EXE and PSET64.EXE. I fixed the no-output bug. They contain routines to start each other when your mixing "bitness" but that's definitely broken (I'll get to it). Does your SYSUTILS have @EXEBITS? Mine does but I may not have uploaded a new one.
Code:
p:\pset\release> echo %@exebits[pset32.exe]
32-bit CUI

p:\pset\release> echo %@exebits[..\x64\Release\pset64.exe]
64-bit CUI
 
May 29, 2008
543
3
Groton, CT
Vince,

Thanks. Yes, my SYSUTILS has @EXEBITS. That's good.

So the new PSET64 seems to work correctly, and I don't see those extra things like =C:=C:\.
PSET32 works on my x64 system against 32-bit images, and also works on my XP 32-bit system.

Eventually, I assume you'll get to fix @PSET.

Thanks very much for the quick fixes!
 
Last edited:
May 20, 2008
9,708
67
Syracuse, NY, USA
Mistake #1. As I said, @PSET (like PSET) injects code into the remote process (and starts a remote thread). By putting the code to be injected into its own section in the SYSUTILS dll, I could determine its size with the DUMPBIN utility. In the code I had
Code:
/* virtual size of ".inject" code segment (from DUMPBIN) is 0x57 */
#define CODEINJECTSIZE 0x57 /* will get a whole page anyway */
and I injected exactly that amount. But in the X64 version, the size of the code to be injected is 0x77. So it failed to inject the complete code. I would have thought that would crash the target process. Dave, does the target process continue to work OK when the 64-bit @PSET crashes the current process?
Anyway, I think I fixed that. I'll look for more things that might go wrong and post an update tonight. Thanks for the offer to debug, Dave.
 
May 29, 2008
543
3
Groton, CT
First, 32-bit to 32-bit on Win XP SP3, TCC 15 running under TCMD 15:
Code:
echo %@pset[%_ppid,tzn]
result is EDT, which is correct.

Second, 64-bit to 64-bit on Win 7, TCC 15 x64 running under TCMD 15 x 64:
same code result is an error window with
Code:
Take Command has stopped working
Windows is checking for a solution to the problem...
which terminates after about 30 seconds, kills the TCC process and starts a new TCC process. The target process TCMD.EXE keeps working without a problem.

I hope this helps.
Regards,
 
May 29, 2008
543
3
Groton, CT
Vince,

First Win XP SP3, TCC 15, 32-bit, the plugin didn't load at all:
[07-08-14 03:06:49][65096] The specified procedure could not be found.
"C:\Program Files\JPSoft\TCMD\PlugIns\sysutils.dll"


Now Win 7, TCC 15 x64, @PSET[pid,username] produced:
For a 64-bit applications, some work perfectly.
For some processes, though, I get the error "TCC: (Sys) Not enough storage is available to process this command." More details below.
For a 32-bit application, "Error (@PSET): Cannot target a 32-bit process"

I'm running in a username in the Administrators group, so I should have enough privilege to check processes running in another username.

I used this command to test:
Code:
pslist |! for %%xx in (@con) (echo %@word[0-1,%xx] %@pset[%@word[1,%xx],username]) >& x.txt
.

Here's an excerpt of the resulting report, showing at least one of each different result.
Code:
smss                412
TCC: (Sys) Access is denied.
wininit            1004
TCC: (Sys) Not enough storage is available to process this command.
RegSrvc            3112
Error (@PSET): Cannot target a 32-bit process
avgcsrva           8032
TCC: (Sys) Not enough storage is available to process this command.
svchost            7256
csrss              8992 SYSTEM
winlogon           9836 SYSTEM
dwm                8172 DCantor
explorer           9600 DCantor
tpnumlk            9876 CLEOPATRA$
igfxsrvc           8792 DCantor
 
Last edited:
May 20, 2008
9,708
67
Syracuse, NY, USA
So it works. Good. "Access is denied" is expected, with some processes, even if TCC is elevated. That's Windows security. "Not enough storage" surprises me a bit but I doubt there's anything I can do about it. I'm asking Windows to allocate a little over 32,768 bytes in the remote process, enough to hold a possible value of an environment variable. And Windows is saying "No". As for XP, I'll try to identify what function(s) I'm using that don't exist in XP and consider alternatives. But I'm not keen on making sure things work with XP.
 
May 20, 2008
9,708
67
Syracuse, NY, USA
I get "Not enough storage" for anything running as a service even if I only request 1024 bytes. I can only suppose that Windows is somehow protecting these processes. I also have to inject a few (~40) bytes into remotely allocated memory that's marked "executable". Maybe the error message is Windows way of saying "You can't inject executable code into this process". In any case, it's probably a good idea.