Windows user home folder in C (MinGW) - c

I'm trying to port an application written in C from linux to windows.
At the moment I'm done fixing the 'hard' parts like missing posix features and the like.
The application compiles, links and works on Windows now (except for the fork() stuff which will be replaced with windows service code later).
The only problem I'm having now is that within the MSYS shell it all works (this maps unix paths for me).
Outside of the MSYS shell it won't work because ~ is not available.
I'm looking for the best way to set the windows user home within my #ifdef stuff.
I read about %USERPROFILE% somewhere but that doesn't seem to work.

Use SHGetKnownFolderPath (Vista+) or SHGetFolderPath depending on your Windows version.

I think you should use the SHGetFolderLocation API:
http://msdn.microsoft.com/en-us/library/bb762180%28VS.85%29.aspx
well not enought, you should even retrieve the ID of the user folder, but by starting at the doc location above you should have all what you neeed.
This should works on any windows version.

Related

How to synchronize code files on windows with WSL/linux?

Basically I have some C/C++ code that I need to build and debug on a Linux machine. Unfortunately, my windows laptop doesn't have enough free hard space to install some Linux dist nor does it have enough free RAM to comfortably run VM.
Until now, I dealt with it rather comfortably using WSL, but the scale was rather small. It was easy to edit and debug 2-3 .c files through CLI and gdb, but it became really annoying on a large scale projects.
I want something simple as "edit code in windows IDE [X], compile it on remote Linux/WSL (the project uses Makefiles), and preferably debug it via gdb".
VS has something close to what I want, but it can't deal with existing Linux projects. It needs to create a new configuration which is alien to the project's Makefile.
I know this question is a bit old, but I think the solution is to make a symlink between your WSL folder and the Window's folder. This is how I handled it for a Ubuntu-20.04 WSL:
Access PowerShell in Administrator mode
Type cmd.exe in the PowerShell
Once cmd.exe is opened, type mklink /d C:\<path_to_your_Windows_folder> \\wsl$\Ubuntu-20.04\home\<your_user>\<path_to_your_WSL_folder>
EDIT
This was tested under Windows 10 Version 2004 with WSL2
I'm unsure about C and C++ but it sounds like this is exactly the same as how i work in node and javascript every day.
I checkout my code using git inside WSL to a location like /mnt/c/code/myproject. Then using sublime/VS code/webstorm i edit the files in windows in the location c:\code\myproject this works really well and have been doing this every day for over a year.
Things to be aware of are that you need to ensure that your editor of choice saves files with linux line endings and that all command line operations are done inside WSL.
Please see this article to see the differences between windows and linux files and how this works inside the WSL.
I want something simple as "edit code in windows IDE , compile it on remote linux/WSL
You will have something as simple as that.
Only with Windows 19.03 though:
See "Updated WSL in Windows 10 version 1903 lets you access Linux files from Windows"
Microsoft's Craig Loewen says:
In the past, creating and changing Linux files from Windows resulted in losing files or corrupting data. Making this possible has been a highly requested and long anticipated feature. We're proud to announce you can now easily access all the files in your Linux distros from Windows.
So how does this work? He goes on to explain:
To put it briefly: a 9P protocol file server facilitates file related requests, with Windows acting as the client.
We've modified the WSL init daemon to include a 9P server. This server contains protocols that support Linux metadata, including permissions.
There is a Windows service and driver that acts as the client and talks to the 9P server (which is running inside of a WSL instance).
Client and server communicate over AF_UNIX sockets, since WSL allows interop between a Windows application and a Linux application using AF_UNIX as described in this post.
Warning:
The old rules still apply, you should NOT access your Linux files inside of the AppData folder!
If you try to access your Linux files through your AppData folder, you are bypassing using the 9P server, which means that you will not have access to your Linux files, and you could possibly corrupt your Linux distro.

VB6 Application Creating Files under "Program Files" in Vista or later OS

I have a legacy VB6 system which is installed in C:/Program Files/IronDuke
In the past it has written some files into this directory. I understand that these files are hidden away if the application is installed under Vista or a later OS, but not if they were written under XP or earlier OS.
How can I retrieve a copy of these 'hidden' files when written under Vista or Windows 7 or 8?
You are looking at a feature called UAC Virtualization, this blog posting gives a pretty good rundown on what is happening and where the files are located.
From above article:
For example, if an application attempts to write to C:\Program Files\Contoso\Settings.ini, and the user does not have permissions to write to that directory (the Program Files), the write operation will be redirected to C:\Users\Username\AppData\Local\VirtualStore\Program Files\Contoso\settings.ini. If an application attempts to write to HKEY_LOCAL_MACHINE\Software\Contoso\ in the registry, it will automatically be redirected to HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software\Contoso or HKEY_USERS\UserSID_Classes\VirtualStore\Machine\Software\Contoso.
so in your case if you are trying to find the files you need to look in:
C:\Users\Username\AppData\Local\VirtualStore\Program Files\IronDuke\
You cannot write to Program Files under Windows 7 / 8 - system security prevents programs running as regular users from doing so. One option for you is to write these files to the user's profile folder (you'll have to update the VB6 program for this, although the changes should be pretty small if the program is otherwise well-written). This would be your best option since the updated code would work well in the future without more changes.
You amy be able to get the program running using Compatibility Mode but I doubt it - on my Windows 8 system I don't even get 'Windows XP' as a compatibility option anymore. All other options will likely enforce security.
You can try running your program as administrator but I'd only do this if you don't have the source to make the changes - it's poor practice to run programs with all privileges since it opens up the system for attacks.

WinAPI C - RunAsUser from REDMON_USER and REDMON_SESSIONID

I installed a PostScript printer driver and have setup REDMON (redmonnt.dll) for redirecting postscript output to my program. In my rather simple c program I capture the data from STDIN and I am able to successfully save it into a .ps file. The file looks OK.
However, I want to start gsview.exe for viewing the file. If I call ShellExecute it fails in Windows 7 because of permission issues. It seems that my program is called under a different user account (LOCAL SERVICE). So I am looking for a way to run gsview.exe under a specific username (the user who initiated the print job) which is available to the program in a variable called REDMON_USER along with the SESSIONID as well.
Q: What are the minimum WinAPI calls required to start a program given a username and a sessionid?
Any code examples in C/C++, .NET would be very helpful.
EDIT: What I am trying accomplish is something very similar to redrunee (from redmonee). I don't want to use redrunee because it opens about a console window for a brief moment.
Note:
1) The program is called by the printer service as [LOCAL SERVICE] account.
2) The first parameter Username (REDMON_USER), in effect, points to the user currently looking at the screen
Look at CreateProcessAsUser.
Also look at CreateProcessWithLogonW and CreateProcess.
They are linked from the CreateProcessAsUser
EDIT In reply to comments by OP.
Follow advice from this thread.
I am copying this here verbatim, in case the original link stops working:
The same code works for us on Vista as
on XP, etc. The service is running as
the Local System.
use WTSGetActiveConsoleSessionId to get the ID of the current active
Windows session at the console (i.e.
the machine keyboard and display, as
opposed to WTS sessions).
use WTSQueryUserToken to get the token for that session.
use DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,
&hTokenDup) to duplicate that token.
use CreateEnvironmentBlock to create an environment that you will be
passing to the process.
use CreateProcessAsUser with the duplicated token and the created
environment. Actually, we use
CreateProcessAsUserW, since the A
version had some sort of bug on some
older systems.
Don't forget to CloseHandle on the various tokens, etc, and to
DestroyEnvironmentBlock the
environment.
Thank you efratian.
PS. Oh joy of Windows programming, did not do it for quite a while. Now I remember why. The only thing that is close or even worse documented is OpenSSH programming.
The documentation describes the "Run as User" feature, which seems to be exactly what you want:
Run as User is intended for launching a GUI program such as GSview locally via RedRun.

Confusion about System.Data.SQLite.dll

The site, http://sqlite.phxsoftware.com/, talks about a mixed-mode assembly and a managed-only version of the provider. Are they both named System.Data.SQLite.dll? I installed the managed-only version in windows and it is working. Which, as I understand it, means that I must also have the native sqlite3.dll file somewhere on my machine that it is finding, right?
When I try to get my assembly to run on Linux with Mono, I get an EntryPointNotFoundException looking for sqlite3_open_v2. So I downloaded the precompiled shared-library for Linux without the TCL bindings from http://www.sqlite.org/download.html and placed it in the same folder as the other assemblies. But that didn't change anything.
The page at http://www.mono-project.com/Interop_with_Native_Libraries says Linux will look at my LD_LIBRARY_PATH environment variable. So I set that to contain '.', the current directory. That didn't work either.
So then I copied sqlite-3.6.19.so to sqlite-3.so, sqlite3.so and sqlite.so. Still no change.
What am I missing?
Instead of using System.Data.SQLite.dll on Windows and Linux, I decided to use Mono.Data.Sqlite.dll on both sides.

Eclipse cross-compile... how can I do that?

I am developing on a Windows machine using Eclipse in C code.
All the files are physically located on a Linux server.
I am using Eclipse only for editing and code browsing.
When I want to compile, I open a terminal and telnet to the Linux server from which I call a file that sets up few variables and eventually invoke a "make" command.
The server is pretty busy.. I would then like to be able to compile locally [and then just ftp these executable files back to the Linux machine so that I can execute them.. unless Eclipse can do that on its own :) ].... any idea how can that be done? I am not well versed in Eclipse or OS usage.... so if you could answer and explain what I should do.. I would really appreciate...
I changed the Build Command under Project Properties menu by just calling the script file on the server I usually invoke to compile... That looked fairly simple.. well... that was too good to be true... and of course.. it didn't work! I am getting this error if I use the default "make" (Cannot run program "make": Launching failed).... while getting (Cannot run program "T:\compile": Launching failed) if I try to invoke my script file that I use to compile...
thanks,
You should take a look at running a crosstool-ng setup on your windows box inside cygwin. And then have eclipse use that compiler. This will allow you to develop for your target Linux platform easily.
Here's some slides
It sounds like you're developing for a desktop/server platform, so you'll have to make sure you set up your crosstool-ng with the same versions of standard libs as your server has (libc, libstdc++, etc). You also want to make sure your crosstool-ng has the same version of gcc as the target as well.
If you don't want to mess with getting all that setup, you could always install Linux as a virtual machine on your windows box and work inside there.

Resources