Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
The aim is to create a directory. Here are the global decls:

C++
typedef NTSTATUS (__stdcall *NTDLLptr)(
    PHANDLE FileHandle, 
    ACCESS_MASK DesiredAccess, 
    OBJECT_ATTRIBUTES *ObjectAttributes, 
    PIO_STATUS_BLOCK IoStatusBlock, 
    PLARGE_INTEGER AllocationSize,
    ULONG FileAttributes, 
    ULONG ShareAccess, 
    ULONG CreateDisposition, 
    ULONG CreateOptions, 
    PVOID EaBuffer, 
    ULONG EaLength );

typedef VOID (__stdcall *my_RtlInitUnicodeString) (
    IN OUT PUNICODE_STRING  DestinationString,
    IN PCWSTR  SourceString );
//static my_RtlInitUnicodeString rtlInitUnicodeString; //Update: Makes no difference here!


NTDLLptr foundNTDLL = NULL; //returns variable here
//RtlInitUnicodeStringPtr pRtlInitUnicodeString; //for NTcreatefile fileObject
UNICODE_STRING fn;
OBJECT_ATTRIBUTES fileObject;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;


The function call to load the libs:

C++
NTDLLptr DynamicLoader (HWND hwnd,  bool progInit)
{
	HMODULE hdlNtCreateFile = LoadLibraryW(L"NtDll.dll");
	foundNTDLL = (NTDLLptr) GetProcAddress (hdlNtCreateFile, createFnString);
	if (foundNTDLL)
		{
			if (progInit)
			{
			memset(&ioStatus, 0, sizeof(ioStatus));
			memset(&fileObject, 0, sizeof(fileObject));
			fileObject.Length = sizeof(fileObject);
			fileObject.Attributes = OBJ_CASE_INSENSITIVE;
			}
			else
			{
			my_RtlInitUnicodeString RtlInitUnicodeString = (my_RtlInitUnicodeString) GetProcAddress(hdlNtCreateFile, initUnicodeFnString);
			RtlInitUnicodeString(&fn, tempDest);
			fileObject.ObjectName = &fn; //Ntdll.dll
			}
			return foundNTDLL;
		}
	else
		{
		FreeLibrary (hdlNtCreateFile);
		return foundNTDLL;
		}

}


The call is made at init:
C++
if (!DynamicLoader (hwnd, true)) DisplayError (hwnd, L"The long path function has been removed. Using short path functions...", errorcode, 0);
...
if (foundNTDLL) FreeLibrary ((HMODULE)hdlNtCreateFile);
/pre>
"tempDest" is a calloc'd wchar_t containing the path name. The NTcreatefile call is made here:
<pre lang="c++">	if (DynamicLoader (hwnd,  false))
	{

	NTSTATUS ntStatus;
	ntStatus = foundNTDLL (&hdlNTOut, FILE_LIST_DIRECTORY | FILE_TRAVERSE, &fileObject, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0);

	if (!NT_SUCCESS(ntStatus))
....
free(tempDest);
if (foundNTDLL) FreeLibrary ((HMODULE)hdlNtCreateFile);


But hdlNTOut is 0. Here are the autos just after the call:

C#
&fileObject	0x3d91cdcc struct _OBJECT_ATTRIBUTES fileObject {Length=24 RootDirectory=0x00000000 ObjectName=0x3d91cdec ...}	_OBJECT_ATTRIBUTES *
Length	24	unsigned long
RootDirectory	0x00000000	void *
ObjectName	0x3d91cdec struct _UNICODE_STRING fn {Length=60 MaximumLength=62 Buffer=0x41300098 "\\?\C:\My path" }	_UNICODE_STRING *
Length	60	unsigned short
MaximumLength	62	unsigned short
Buffer	0x41300098 "\\?\C:\My path"	wchar_t *
92 L'\'	wchar_t
Attributes	64	unsigned long
SecurityDescriptor	0x00000000	void *
SecurityQualityOfService	0x00000000	void *
&hdlNTOut	0x00494320 void * hdlNTOut	void * *
&ioStatus	0x3d91cbb0 struct _IO_STATUS_BLOCK ioStatus {Status=0 Pointer=0x00000000 Information=0 }	_IO_STATUS_BLOCK *
Status	0	long
Pointer	0x00000000	void *
Information	0	unsigned long
foundNTDLL	0x776e00f4 _NtCreateFile@44	long (void * *, unsigned long, _OBJECT_ATTRIBUTES *, _IO_STATUS_BLOCK *, _LARGE_INTEGER *, unsigned long, unsigned long, unsigned long, unsigned long, void *, unsigned long)*
ntStatus	-1073741773	long


A backslash on the end of the path gets the same output. The "L\" in ObjectName.Buffer is the only thing that doesn't look right. All was done without calling Initializeobjectattributes, but was something else missed?
Thanks for reading. :)
Posted
Updated 13-Dec-15 9:46am
v11
Comments
Richard MacCutchan 12-Dec-15 11:51am    
The leading L on a string tells the compiler to generate Unicode rather than ASCII, And since you are calling the Unicode version of LoadLibrary (trailing W), that is correct.
Richard MacCutchan 12-Dec-15 11:56am    
I cannot make head or tail of the rest of your code, so I assume there are pieces that you are not showing us.
Frankie-C 12-Dec-15 14:27pm    
I don't see the initialization of 'foundNTDLL' using 'GetProcAddress(hdlNtCreateFile, "NtCreateFile");'.
You omitted it for simplicity or you never initialized it?
Laurie Stearn 13-Dec-15 7:16am    
Thank_You for reading this. Modified the code in the question by adding a routine. Hope it helps for readability. But hdlNTOut is still zero. And there is a problem with the typedef reported here (see comment in above typedef):

http://stackoverflow.com/questions/34248470/typedef-variables-for-global-use/34248820#34248820
Richard MacCutchan 13-Dec-15 7:32am    
What error code do you get? See https://msdn.microsoft.com/en-us/library/bb432380(v=vs.85).aspx for information on return values.

1 solution

The question was incomplete as it didn't explicitly say what tempDest was initialise with, although the '\\?\C:\myPath' looks okay in the output.
For the ordinary CreateDirectoryW function the drive constant to populate tempDest worked:

const wchar_t *driveIDBaseW = L"\\\\?\\C:\\";


But this produced the STATUS_OBJECT_NAME_INVALID error. However the substituting the second backslash for the wildcard worked for NtCreateFile:
const wchar_t *driveIDBaseWNT = L"\\??\\C:\\";

Thanks for the pointers, I've learnt a fair bit, albeit a little cross-eyed after poring through the old OSR driver threads. :)
 
Share this answer
 
v2

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