|
File and folder handling with %APPDATA%
#468711
10/13/17 17:26
10/13/17 17:26
|
Joined: Apr 2002
Posts: 680 Germany
Turrican
OP
User
|
OP
User
Joined: Apr 2002
Posts: 680
Germany
|
Hey guys, for a number of reasons I want to put my game's savegame data into the user-specific %APPDATA% folder. I would like to use file_open_... commands for my savegames, rather than using game_save. Now I have several problems with that: 1. Unicode User NamesAs Emre kindly explained here, it is possible to retrieve the complete %APPDATA% path using a shell32-function. However, as this example uses "SHGetFolderPathA", it only works as long as the Windows username does not contain any unicode characters. Using non-unicode usernames is rather common for territories like east-asia, russia and so on. There is a function "SHGetFolderPathW", which is supposed to return a unicode string, but I never managed to retrieve more than a single letter "C" from it. Have a look at that here:
HRESULT WINAPI SHGetFolderPath(HWND hwndOwner, int nFolder,HANDLE hToken,DWORD dwFlags,char* pszPath);
#define PRAGMA_API SHGetFolderPath;Shell32.dll!SHGetFolderPathW
char temp_getfolder[260];
STRING* str_sv_dir="";
const int APPDATA = 0x001A;
function get_appdata_folder_startup()
{
SHGetFolderPath(NULL,APPDATA,0,NULL,temp_getfolder);
str_sv_dir=str_createw(temp_getfolder);
error(str_sv_dir); // opens a dialog box containing the letter "C"
}
BTW, I also tried using "SHGetSpecialFolderPath" from windows.h with similar results. My question is: How can I retrieve the correct appdata path as a unicode string? And once I have this - do Lite-C's "file_open..." commands actually work with such a string?2. Creating a possibly non-existing folderNow, at every start of my game, I want to make sure that the actual savegame folder and file exist to prevent Invalid Pointer errors. Therefore I refer to the manual, which states: - file_open_append (STRING* name);
Opens a file for appending additional content at the end. If the file does not exist, it is created. The functions return a file handle - that is a unique number to identify the opened file. The file handle is used by other functions to access that file.
I expected that calling this function on a non-existent file in an also non-existent folder path would simply create both the file and the folder. But instead, the engine can't find the given file, throws an "Invalid Pointer" error message, and the script execution stops. I then tried "game_save". This command actually creates the required folder, which is good - except that I don't want to use Acknex' .SAV files at all, so this is no option for me. I also tried using "CreateDirectory(char* lpPathName,long lpSecurityAttributes);" from windows.h with the String I got from "SHGetFolderPath" (see above), combined with "mygametitle". It did not work at all. Is there any other method to create a folder from inside the engine?
|
|
|
Re: File and folder handling with %APPDATA%
[Re: Superku]
#468728
10/14/17 09:14
10/14/17 09:14
|
Joined: Apr 2002
Posts: 680 Germany
Turrican
OP
User
|
OP
User
Joined: Apr 2002
Posts: 680
Germany
|
I only had a quick look at it but you usually want to use "short" arrays for Unicode, not "chars" ( in view of "temp_getfolder"). Thanks, that makes sense. I gave it a shot, still got only "C" as result. I guess this is because of the string type that SHGetFolderPathW expects ("LPWSTR"). Either that, or I made some other mistake on the way. Anyway - sadly, it's pointless to test this any further, because I just checked if the engine's "file_open_..." commands accept unicode strings as file paths. And of course, the result is: No, they don't. So working on this stuff in lite-c makes no sense at all - or am I missing something? I really can't understand why Windows Special Folders were not implemented into the engine in a hard-coded way at all. It's a standard since Vista - that was 10 years ago. Maybe someone still has an idea how to get this working...? This really is an important part for my project.
|
|
|
Re: File and folder handling with %APPDATA%
[Re: Turrican]
#468731
10/14/17 10:55
10/14/17 10:55
|
Joined: Jun 2007
Posts: 1,337 Hiporope and its pain
txesmi
Serious User
|
Serious User
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
|
Hi, unicode strings are half-implemented in the engine. There are many functions that don't work with unicode strings. error funtion is one of those, I guess. I remember str_len, str_clip and str_trunc failing too. There might be more... TEXT and PANEL digits shows unicode strings correctly.
#include <acknex.h>
#include <windows.h>
HRESULT WINAPI SHGetFolderPath(HWND hwndOwner, int nFolder,HANDLE hToken,DWORD dwFlags,char* pszPath);
#define PRAGMA_API SHGetFolderPath;Shell32.dll!SHGetFolderPathW
const int APPDATA = 0x001A;
FONT *fnt = "Arial#24";
TEXT *txtW =
{
font = fnt;
pos_x = 10;
pos_y = 10;
strings = 1;
flags = SHOW;
}
function get_appdata_folder_startup()
{
short temp_getfolder[260];
SHGetFolderPath ( NULL, APPDATA, 0, NULL, temp_getfolder );
*txtW->pstring = str_createw ( temp_getfolder );
}
void main ( )
{
while ( !key_esc )
wait ( 1 );
sys_exit ( NULL );
}
|
|
|
Re: File and folder handling with %APPDATA%
[Re: txesmi]
#468732
10/14/17 14:13
10/14/17 14:13
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
The string you retrieved is correct, however if you use it with a function that expects non-unicode strings like error() they don't work correctly. In this case the first character ('C') of your string is not one byte large as the engine expects because it's unicode (still, it happens to have the same ascii value in the first byte). When the engine continues to read the string it expects the second byte to be the next character. However, this byte is still part of the first unicode character and since it has the value 0x00 in this case, the engine interperts it as the end of string character and cuts off the rest.
Like txesmi said, TEXT and PANEL can display the string correctly. draw_text() works aswell (I believe it works the same as TEXT/PANEL drawing)
Regarding the CreateDirectory() function: when using the windows API you have to be pretty careful with unicode/non-unicode strings. If SHGetFolderPath returns a wstring (which it seems it does) you'd have to use CreateDirectoryW.
POTATO-MAN saves the day! - Random
|
|
|
Re: File and folder handling with %APPDATA%
[Re: txesmi]
#468766
10/17/17 11:58
10/17/17 11:58
|
Joined: Apr 2002
Posts: 680 Germany
Turrican
OP
User
|
OP
User
Joined: Apr 2002
Posts: 680
Germany
|
unicode strings are half-implemented in the engine. There are many functions that don't work with unicode strings. error funtion is one of those, I guess. I remember str_len, str_clip and str_trunc failing too. There might be more... Yes, I found out about that some time ago, but there were always methods to work around these problems. Anyway, as a matter of fact, it seems that file_open_write or _read belong to those commands that don't support Unicode, and there seems to be no workaround for that. The string you retrieved is correct, however if you use it with a function that expects non-unicode strings like error() they don't work correctly. In this case the first character ('C') of your string is not one byte large as the engine expects because it's unicode (still, it happens to have the same ascii value in the first byte). (...)
Like txesmi said, TEXT and PANEL can display the string correctly. draw_text() works aswell (I believe it works the same as TEXT/PANEL drawing) Sorry, yes, you were right. The retrieved string was indeed correct, and it's also displayed correctly when using draw_text. However, when I now use this string to create and write into a file, guess what happens.
HRESULT WINAPI SHGetFolderPath(HWND hwndOwner, int nFolder,HANDLE hToken,DWORD dwFlags,char* pszPath);
#define PRAGMA_API SHGetFolderPath;Shell32.dll!SHGetFolderPathW
char temp_getfolder[260];
STRING* str_sv_dir="";
const int APPDATA = 0x001A;
function get_appdata_folder_startup()
{
SHGetFolderPath(NULL,APPDATA,0,NULL,temp_getfolder);
STRING* wstr = str_createw(temp_getfolder);
str_cat(wstr,"\\MyGame\\test.txt");
var filehandle = file_open_write(wstr);
file_str_write(filehandle,"Look guys, we're writing into the file!");
file_close(filehandle);
// --> ...and now look for a file named 'C' in your project directory. :(
while(1)
{
draw_text(wstr,800,560,vector(100,100,255)); // yes, that's actually the correct path
wait(1);
}
}
I guess that's the proof that file_open_write does not know Unicode. What shall I do now? Is it really the only feasible option to create a DLL-plugin that works around this problem, with custom file and folder handling? It sure looks that way. Please tell me there's an easier way.
|
|
|
|