|
pnpfriend wrote:
c:\test\b
c:\test\b\mm.txt
Shouldn't these two come between a.txt and c.txt?
pnpfriend wrote:
So.. what do you suggest?
You were on the right path with the FindFirstFile() /FindNextFile() pair. For each file/folder encountered, add it to a CArray object if you are using MFC, or a list object if you are using STL. Then sort. Another option is to add the file/folder items to a hidden listbox control that has the LBS_SORT style.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
Hi David,
Thanks for ur reply.
No..
c:\test\b shouldnt' come between a.txt and c.txt because b is a folder not a file. I want all the file above folders.. just like you will see in ms explorer. I thought of using array.. but it is taking so long to sort it using array. I also did used ctreectrl.. again.. takes long time when minipulating huge files list..
Therefore, I was wondering to use FileSystemObject.
With FileSystemOjbect, I can sort folder first, then files later before minipulating any files information. I think.
But dont' know how to use it in c++. Do you have any idea?
|
|
|
|
|
pnpfriend wrote:
I want all the file above folders.. just like you will see in ms explorer.
That works. I initially thought you wanted each file/folder sorted in relation to ALL others.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
So do you know how to use FileSystemObject in c++?
or any other similar class that take care of it?
|
|
|
|
|
pnpfriend wrote:
So do you know how to use FileSystemObject in c++?
No, I've only used it in .wsh and .vbs files. With C++ I would opt for the FindFirstFile /FindNextFile pair, or CFileFind if using MFC.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
Thank you for your replies, David.
I have no choice that I have to use FindNextFile() FindFirstFile().
|
|
|
|
|
I am trying to check if I have the proper access to a file. Here is my testing program
<br />
#include <stdio.h><br />
#include <windows.h><br />
<br />
typedef int TBK_BOOL;<br />
typedef int TBK_PERMISSIONS;<br />
<br />
#define TBK_TRUE 1<br />
#define TBK_FALSE 0<br />
<br />
#define F_OK 0 /* exists */<br />
#define X_OK 1 /* executable */<br />
#define W_OK 2 /* writable */<br />
#define R_OK 4 /* readable */<br />
#define D_OK 8 /* deletable */<br />
<br />
static TBK_BOOL win32_access(<br />
const char * os_path,<br />
TBK_PERMISSIONS permissions )<br />
{<br />
DWORD dwDesiredAccess;<br />
<br />
<br />
switch( permissions ) {<br />
case F_OK :<br />
return TBK_TRUE;
<br />
case R_OK :<br />
dwDesiredAccess = GENERIC_READ;<br />
break;<br />
<br />
case W_OK :<br />
dwDesiredAccess = GENERIC_WRITE;<br />
break;<br />
<br />
case X_OK :<br />
dwDesiredAccess = GENERIC_EXECUTE;<br />
break;<br />
<br />
case D_OK :<br />
dwDesiredAccess = DELETE;<br />
break;<br />
<br />
default :<br />
<br />
return TBK_FALSE;<br />
}<br />
<br />
GENERIC_MAPPING genericMapping = { READ_CONTROL | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA,<br />
FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_WRITE_DATA | FILE_APPEND_DATA,<br />
READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_EXECUTE,<br />
FILE_ALL_ACCESS } ;<br />
LPCTSTR lpFilePath = LPCTSTR(os_path);<br />
PSECURITY_DESCRIPTOR pSD = NULL ;<br />
DWORD dwLenNeeded = 0;<br />
HANDLE hHeap = GetProcessHeap();<br />
<br />
PRIVILEGE_SET privileges;<br />
DWORD dwGrandedAccess, dwPrivilegeLength;<br />
BOOL bSuccess, bAccessGranded;<br />
HANDLE hProcess, hToken;<br />
<br />
fprintf(stderr, "Start checking access for %s\n", os_path);<br />
<br />
GetFileSecurity( lpFilePath ,<br />
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,<br />
pSD, 0, &dwLenNeeded );<br />
<br />
pSD = HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, dwLenNeeded);<br />
if( pSD == NULL )<br />
{<br />
DWORD dwError = GetLastError();<br />
LPVOID lpError;<br />
<br />
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM , NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpError, NULL, NULL);<br />
<br />
fprintf(stderr, "Cannot allocate memory for security descriptor.\n", (LPCTSTR) lpError );<br />
<br />
return TBK_FALSE;<br />
}<br />
<br />
bSuccess = GetFileSecurity( lpFilePath,<br />
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,<br />
pSD, dwLenNeeded, &dwLenNeeded );<br />
if( bSuccess == FALSE ) {<br />
DWORD dwError = GetLastError();<br />
LPVOID lpError;<br />
<br />
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM , NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpError, NULL, NULL);<br />
<br />
<br />
fprintf(stderr, "Cannot get security id. Buffer len is %d. Error %s\n", dwLenNeeded, (LPCTSTR) lpError );<br />
<br />
<br />
return TBK_FALSE;<br />
}<br />
hProcess = GetCurrentProcess();<br />
<br />
bSuccess = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);<br />
if( bSuccess == FALSE )<br />
fprintf(stderr, "Cannot get Process Access Token.\n");<br />
<br />
fprintf(stderr, "Access asked %x.\n", dwDesiredAccess);<br />
MapGenericMask(&dwDesiredAccess, &genericMapping);<br />
fprintf(stderr, "Access to examine %x.\n", dwDesiredAccess);<br />
<br />
bSuccess = AccessCheck( pSD, hToken, dwDesiredAccess, &genericMapping,<br />
&privileges, &dwPrivilegeLength, &dwGrandedAccess,<br />
&bAccessGranded );<br />
<br />
if( bSuccess == FALSE ) {<br />
DWORD dwError = GetLastError();<br />
LPVOID lpError;<br />
<br />
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM , NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpError, NULL, NULL);<br />
<br />
<br />
fprintf(stderr, "Cannot check permissions. Error no %d %s\n", dwError, (LPCTSTR) lpError );<br />
<br />
<br />
return TBK_FALSE;<br />
}<br />
<br />
<br />
CloseHandle(hToken);<br />
<br />
HeapFree(hHeap, 0, pSD);<br />
<br />
fprintf(stderr, "Finish checking access.\n");<br />
<br />
return ((bAccessGranded == TRUE) ? TBK_TRUE : TBK_FALSE);<br />
}<br />
<br />
int main(int argc, LPCSTR argv [])<br />
{<br />
LPCTSTR path = LPCTSTR(argv[1]);<br />
char c;<br />
<br />
fprintf(stderr, "About to check %s file.\n", (LPCTSTR) path);<br />
<br />
if( win32_access( (LPCTSTR) path, R_OK ) )<br />
fprintf(stderr, "File is readable\n.");<br />
<br />
if( win32_access( (LPCTSTR) path, W_OK ) )<br />
fprintf(stderr, "File is writeable.");<br />
<br />
if( win32_access( (LPCTSTR) path, X_OK ) )<br />
fprintf(stderr, "File is executable.");<br />
<br />
if( win32_access( (LPCTSTR) path, D_OK ) )<br />
fprintf(stderr, "File is deleteable.");<br />
<br />
return 0;<br />
}<br />
When I am running it I am getting the following results
G:\Debug>check check.obj
About to check check.obj file.
Start checking access for check.obj
Access asked 80000000.
Access to examine 20089.
Cannot check permissions. Error no 998 Invalid access to memory location.
Start checking access for check.obj
Access asked 40000000.
Access to examine 116.
Cannot check permissions. Error no 998 Invalid access to memory location.
Start checking access for check.obj
Access asked 20000000.
Access to examine 200a0.
Cannot check permissions. Error no 998 Invalid access to memory location.
Start checking access for check.obj
Access asked 10000.
Access to examine 10000.
Cannot check permissions. Error no 998 Invalid access to memory location.
I do not undrstand what is wrong in the AccessCheck call. Everything seems to be fine and all memory is been in place.
Can someone spot any mistake on this small program. Help is much appriciated.
Ανέγνως αλλ' ουκ έγνων, η γαρ έγνως ουκ αν κατέγνων...Καβάφης.
|
|
|
|
|
You need to pass buffer to the AccessCheck for the privilege set. You need to pass in a thread token, not the process token. Here are some tips:
For the PRIVILEGE_SET privileges;
I changed it to PRIVILEGE_SET* lpPrivileges;
and malloced about 8192 bytes.
Set the dwPrivilegeLength to 8192
Pass lpPrivileges (already a pointer) to AccessCheck instead of &privileges (which was your locla variable).
Then I got error 1309 instead, meaning you need to open the thread token instead of the process token. Look at using OpenThread with GetCurentThradId followed by OpenThreadToken and maybe error 1309 will go away or be replaced by something else.
|
|
|
|
|
I also forgot to mention you initialize the Generic Mappings incorrectly.
It is a data structure with four 32-bit fields.
Try
GENERIC_MAPPING genericMapping;<br />
<br />
genericMapping.GenericAll = READ_CONTROL | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA,<br />
FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_WRITE_DATA | FILE_APPEND_DATA,<br />
READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_EXECUTE,<br />
FILE_ALL_ACCESS;<br />
<br />
genericMapping.GenericExecute = genericMapping.GenericAll;<br />
genericMapping.GenericRead = genericMapping.GenericAll;<br />
genericMapping.GenericWrite = genericMapping.GenericAll;
I am not suggesting these should all be the same value, only that this syntax is 'more corrct' than what you had before.
|
|
|
|
|
Thanks a lot for you help.
Someone else sugested to use CreateFile which simplifies a lot the permission checking. Although sounds weird to 'create a file' for just checking the permissions, it looks like a simpler solution to go for.
Ανέγνως αλλ' ουκ έγνων ή γαρ έγνως ουκ αν κατέγνων...Καβάφης
|
|
|
|
|
Hi all,
I want a good way to encrypting files,
and I want to say that I am a beginner.
Please help me on this,
Cheers,
Thanks.
|
|
|
|
|
|
How about EncryptFile() ?
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
filename: cat.h<br />
<br />
#include "dog.h"<br />
<br />
namespace Mammal<br />
{<br />
namespace Dog<br />
{<br />
class Collie<br />
{<br />
void virtual init( Mammal::Cat::Siamese *siamese );<br />
}<br />
}<br />
}<br />
<br />
filename: dog.h<br />
<br />
#include "cat.h"<br />
<br />
namespace Mammal<br />
{<br />
namespace Cat<br />
{<br />
class Siamese<br />
{<br />
Mammal::Dog::Collie *collie;<br />
...<br />
}<br />
}<br />
}
If I try to compile this, I get an error that says "Siamese is not a member of Mammal::Cat
Any ideas why?
|
|
|
|
|
1. You have the two classes (Siamese and Collie) dependant on each other which even if it works is poor practice.
2. Siamese has no functions defined.
Elaine
The tigress is here
|
|
|
|
|
I know it's a circular dependancy, and I promise I'll do penance for that. But that wouldn't account for the compiler not finding Siamese in the Mammal::Cat namespace. And there is more to each class, but these are the lines that I've narrowed down as the most likely candidates for causing the problem. As far as I can tell, the namespaces are set up properly, and Visual Studio has no problem parsing them to generate the class view or to generate the drop-down list for the auto-complete feature, but the compiler won't compile it, claiming that the Siamese class is not a member of that namespace.
|
|
|
|
|
May be you could try forward declaration.
like
namespace Mammal
{
namespace Cat{ Class Siamese;}
}
then, the actual dog namespace
then, the actual cat namespace.
Sonork 100.41263:Anthony_Yio
|
|
|
|
|
I am having a difficult time finding my problem in a dll that I am trying to build. This is really my first significant dll. I am trying to export a class from this dll - the dll itself has many classes that support this class, which are not exported, including some that use COM. Some of the supporting classes need to be initialized at the beginning. I am using MFC, but the class being exported is not based on MFC and all the functions in the class use parameters that do not require MFC - so I understand that I do not need to build an MFC extension dll.
I wrote a simple dialog application that included all the classes in the dll, and the dialog with a button that exercises the class that is being exported. Everything works fine. The supporting classes initialize properly, and all the functions in the class to be exported work as expected.
Then I created a project to make the dll with all the same classes. I built the dll and built a new dialog project to test the exported class in dll. The program 'hangs' during initialization that happens in the dll. Here is my problem. When I step through the code, when a function is completed the return statement does not go back to the calling function - it is as though the call stack is somehow corrupted, and there is no next place to step through for the code. How can I find out what is happening? I have never had this particular problem before.
I have another smaller dll that I developed the same way as this which works fine - the basic difference is that this one uses COM to do some ADO, and this dll also has some global variables.
Thanks in advance.
|
|
|
|
|
Does this mean your DLL statically links with MFC ?
Did you use the AFX_MANAGE_STATE macro ?
You might need to call this from each member function of your exported class.
Just because you don't directly export a function calling MFC does not mean that you don't still need to enter the correct state for each other function that is exported.
See "Managing the State Data of MFC Modules" in the MSDN.
|
|
|
|
|
Thanks for the response.
No, I am not statically linking with MFC.
Each of the function that is exported has the AFX_MANAGE_STATE macro in the first line.
I did read the article Managing the State Data of MFC Modules in MSDN, and think that I follow the recommendations.
The problem occurs in a function that is not exported. In fact, it is part of the initialization routine - which iscalled in the InitInstance in of the CWinApp derived class for the dll.
|
|
|
|
|
Does the EXE loading the DLL initialize COM ?
If so, does the COM initialization in the EXE occur prior to the initialization in the DLL ?
You might find that your DLL initialization will need to be deferred to an exported 'initialization' call, rather than in the InitInstance, which is basically the same as DLL_PROCESS_ATTACH. As a result of deferral, some class instances dependent upon COM, if they do 'interesting' operations in their constructors, might not be able to remain global, they might have to be created dynamically. The pointers to instances of the classes could be global, but not the instances of the classes themselves.
Basically, you might need to rework in this order, then:
EXE loads DLL (statically, I am presuming, since DLL is linked to EXE)
EXE initializes COM
EXE calls 'init' function exported from DLL
DLL 'init' function 'creates' global objects
...EXE does other work...
EXE calls shutdown function in DLL
DLL frees global objects
EXE uninitializes COM
Windows unloads DLL from EXE address space
EXE exits
You can also get into trouble with COM when creating instances and references to objects that MIGHT not be activated or deleted by the same thread in the EXE as those objects were created.
|
|
|
|
|
Thanks - I will try this - makes eminent sense. It is fairly straightforward to export an Init function that the .EXE's startup can call.
I had narrowed it to being a COM related issue as the inintialization works if I comment out the COM related code.
|
|
|
|
|
Thnaks,
Once I made sure that all initialization and COM calls came after the dll has been loaded - things worked out. I had to instantiate the global objects in an exported Init function subsequent to loading as you had suggested, and have a corresponding ShutDown function that cleaned up the gloabal objects before dll was unloaded. Having the cleanup code as part of unloading the dll frequently led to access violations.
|
|
|
|
|
In my application I've set the REALTIME_PRIORITY_CLASS.
It manages a worker thread that works at REAL_TIME_PRIORITY_LEVEL
(while the main thread has been set at IDLE_PRIORITY_LEVEL).
The goal'd be to let the worked thread to loop periodically
with its own multimedia timer without being stopped by the
user interface (in example when the user clicks the mouse).
My problem is that when the user stimulates the user interface
(mouse and windows) the worker thread stops for a while.
How can I let my theard loop without being affected by the
user actions ?
Is there a way to let the user interface to have really a very low
priority ?
Thanks a lot !
|
|
|
|
|
Hello,
You can try to set the prioity of your process to a higher level. Windows will give your process a bigger timeslice. Your process will give most of the time to your worker thread.
But be carefull with setting your process priority to realtime. If you do this, Windows will give almost all the time to your process and other applications could 'freeze' because there is no time left..
Hope this helps.
I also got the blogging virus..[^]
|
|
|
|
|