License: X11
ChangeLog:
Jon Griffiths <jon_p_griffiths@xxxxxxxxx>
+dlls/ntdll/ntdll.spec dlls/ntdll/error.c dlls/ntdll/rtlstr.c
Add RtlNtStatusToDosErrorNoTeb,RtlGet/Set/RestorLastWin32Error,
RtlGUIDFromString,RtlStringFromGUID
+dlls/ntdll/tests/rtlstr.c
Test Rtl guid<->string conversions
__________________________________
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/
diff -ur wine/dlls/ntdll/error.c wine-test/dlls/ntdll/error.c
--- wine/dlls/ntdll/error.c 2003-09-24 20:21:28.000000000 +0000
+++ wine-test/dlls/ntdll/error.c 2003-12-11 19:23:53.000000000 +0000
@@ -20,6 +20,7 @@
*/
#include "config.h"
+#include "wine/port.h"
#include <stdarg.h>
#include "ntstatus.h"
@@ -42,7 +43,7 @@
static const struct error_table error_table[20];
/**************************************************************************
- * RtlNtStatusToDosError (NTDLL.@)
+ * RtlNtStatusToDosErrorNoTeb (NTDLL.@)
*
* Convert an NTSTATUS code to a Win32 error code.
*
@@ -53,7 +54,7 @@
* The mapped Win32 error code, or ERROR_MR_MID_NOT_FOUND if there is no
* mapping defined.
*/
-ULONG WINAPI RtlNtStatusToDosError( NTSTATUS status )
+ULONG WINAPI RtlNtStatusToDosErrorNoTeb( NTSTATUS status )
{
const struct error_table *table = error_table;
@@ -81,6 +82,70 @@
return ERROR_MR_MID_NOT_FOUND;
}
+/**************************************************************************
+ * RtlNtStatusToDosError (NTDLL.@)
+ *
+ * Convert an NTSTATUS code to a Win32 error code.
+ *
+ * PARAMS
+ * status [I] Nt error code to map.
+ *
+ * RETURNS
+ * The mapped Win32 error code, or ERROR_MR_MID_NOT_FOUND if there is no
+ * mapping defined.
+ */
+ULONG WINAPI RtlNtStatusToDosError( NTSTATUS status )
+{
+ /* FIXME: This function obviously does something with the Teb */
+ return RtlNtStatusToDosErrorNoTeb( status );
+}
+
+/**********************************************************************
+ * RtlGetLastWin32Error (NTDLL.@)
+ *
+ * Get the current per-thread error value set by a system function or the user.
+ *
+ * PARAMS
+ * None.
+ *
+ * RETURNS
+ * The current error value for the thread, as set by SetLastWin32Error() or SetLastError().
+ */
+#ifdef __i386__
+__ASM_GLOBAL_FUNC( RtlGetLastWin32Error, ".byte 0x64\n\tmovl 0x34,%eax\n\tret" );
+#else
+DWORD WINAPI RtlGetLastWin32Error(void)
+{
+ return NtCurrentTeb()->LastErrorValue;
+}
+#endif
+
+/***********************************************************************
+ * RtlSetLastWin32Error (NTDLL.@)
+ * RtlRestoreLastWin32Error (NTDLL.@)
+ *
+ * Set the per-thread error value.
+ *
+ * PARAMS
+ * err [I] The new error value to set
+ *
+ * RETURNS
+ * The previous error value of the thread.
+ */
+#ifdef __i386__
+__ASM_GLOBAL_FUNC( RtlSetLastWin32Error,
+ ".byte 0x64\n\tmovl 0x34,%eax\n\t"
+ "movl 4(%esp),%ecx\n\t"
+ ".byte 0x64\n\tmovl %ecx,0x34\n\t"
+ "ret $4" );
+#else
+DWORD WINAPI RtlSetLastWin32Error( DWORD err )
+{
+ DWORD previous = NtCurrentTeb()->LastErrorValue;
+ NtCurrentTeb()->LastErrorValue = err;
+ return previous;
+}
+#endif
/* conversion tables */
diff -ur wine/dlls/ntdll/ntdll.spec wine-test/dlls/ntdll/ntdll.spec
--- wine/dlls/ntdll/ntdll.spec 2003-12-07 19:33:00.000000000 +0000
+++ wine-test/dlls/ntdll/ntdll.spec 2003-12-11 19:23:53.000000000 +0000
@@ -416,6 +416,7 @@
@ stub RtlGetElementGenericTable
@ stdcall RtlGetFullPathName_U(wstr long ptr ptr)
@ stdcall RtlGetGroupSecurityDescriptor(ptr ptr ptr)
+@ stdcall RtlGetLastWin32Error()
@ stdcall RtlGetLongestNtPathLength()
@ stub RtlGetNtGlobalFlags
@ stdcall RtlGetNtProductType(ptr)
@@ -423,6 +424,7 @@
@ stdcall RtlGetProcessHeaps(long ptr)
@ stdcall RtlGetSaclSecurityDescriptor(ptr ptr ptr ptr)
@ stub RtlGetUserInfoHeap
+@ stdcall RtlGUIDFromString(ptr ptr)
@ stdcall RtlIdentifierAuthoritySid(ptr)
@ stdcall RtlImageDirectoryEntryToData(long long long ptr)
@ stdcall RtlImageNtHeader(long)
@@ -476,6 +478,7 @@
@ stdcall RtlNewSecurityObject(long long long long long long)
@ stdcall RtlNormalizeProcessParams(ptr)
@ stdcall RtlNtStatusToDosError(long)
+@ stdcall RtlNtStatusToDosErrorNoTeb(long)
@ stub RtlNumberGenericTableElements
@ stdcall RtlNumberOfClearBits(ptr)
@ stdcall RtlNumberOfSetBits(ptr)
@@ -500,6 +503,7 @@
@ stdcall RtlRaiseException(ptr)
@ stdcall RtlRaiseStatus(long)
@ stdcall RtlRandom(ptr)
+@ stdcall RtlRestoreLastWin32Error(long) RtlSetLastWin32Error
@ stdcall RtlReAllocateHeap(long long ptr long)
@ stub RtlRealPredecessor
@ stub RtlRealSuccessor
@@ -521,6 +525,7 @@
@ stdcall RtlSetEnvironmentVariable(ptr ptr ptr)
@ stdcall RtlSetGroupSecurityDescriptor(ptr ptr long)
@ stub RtlSetInformationAcl
+@ stdcall RtlSetLastWin32Error(long)
@ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long)
@ stdcall RtlSetSaclSecurityDescriptor(ptr long ptr long)
@ stub RtlSetSecurityObject
@@ -530,7 +535,7 @@
@ stdcall RtlSizeHeap(long long ptr)
@ stub RtlSplay
@ stub RtlStartRXact
-@ stub RtlStringFromGUID
+@ stdcall RtlStringFromGUID(ptr ptr)
@ stdcall RtlSubAuthorityCountSid(ptr)
@ stdcall RtlSubAuthoritySid(ptr long)
@ stub RtlSubtreePredecessor
diff -ur wine/dlls/ntdll/rtlstr.c wine-test/dlls/ntdll/rtlstr.c
--- wine/dlls/ntdll/rtlstr.c 2003-12-07 19:33:00.000000000 +0000
+++ wine-test/dlls/ntdll/rtlstr.c 2003-12-11 19:23:53.000000000 +0000
@@ -1799,3 +1799,135 @@
} /* if */
return STATUS_SUCCESS;
}
+
+
+/*************************************************************************
+ * RtlGUIDFromString (NTDLL.@)
+ *
+ * Convert a string representation of a GUID into a GUID.
+ *
+ * PARAMS
+ * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
+ * guid [O] Destination for the converted GUID
+ *
+ * RETURNS
+ * Success: STATUS_SUCCESS. guid contains the converted value.
+ * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
+ *
+ * SEE ALSO
+ * See RtlStringFromGUID.
+ */
+NTSTATUS WINAPI RtlGUIDFromString(const UNICODE_STRING *str, GUID* guid)
+{
+ int i = 0;
+ const WCHAR *lpszCLSID = str->Buffer;
+ BYTE* lpOut = (BYTE*)guid;
+
+ TRACE("(%s,%p)\n", debugstr_us(str), guid);
+
+ /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+ * to memory: DWORD... WORD WORD BYTES............
+ */
+ while (i < 37)
+ {
+ switch (i)
+ {
+ case 0:
+ if (*lpszCLSID != '{')
+ return STATUS_INVALID_PARAMETER;
+ break;
+
+ case 9: case 14: case 19: case 24:
+ if (*lpszCLSID != '-')
+ return STATUS_INVALID_PARAMETER;
+ break;
+
+ case 37:
+ if (*lpszCLSID != '}')
+ return STATUS_INVALID_PARAMETER;
+ break;
+
+ default:
+ {
+ WCHAR ch = *lpszCLSID, ch2 = lpszCLSID[1];
+ unsigned char byte;
+
+ /* Read two hex digits as a byte value */
+ if (ch >= '0' && ch <= '9') ch = ch - '0';
+ else if (ch >= 'a' && ch <= 'f') ch = ch - 'a' + 10;
+ else if (ch >= 'A' && ch <= 'F') ch = ch - 'A' + 10;
+ else return STATUS_INVALID_PARAMETER;
+
+ if (ch2 >= '0' && ch2 <= '9') ch2 = ch2 - '0';
+ else if (ch2 >= 'a' && ch2 <= 'f') ch2 = ch2 - 'a' + 10;
+ else if (ch2 >= 'A' && ch2 <= 'F') ch2 = ch2 - 'A' + 10;
+ else return STATUS_INVALID_PARAMETER;
+
+ byte = ch << 4 | ch2;
+
+ switch (i)
+ {
+#ifndef WORDS_BIGENDIAN
+ /* For Big Endian machines, we store the data such that the
+ * dword/word members can be read as DWORDS and WORDS correctly. */
+ /* Dword */
+ case 1: lpOut[3] = byte; break;
+ case 3: lpOut[2] = byte; break;
+ case 5: lpOut[1] = byte; break;
+ case 7: lpOut[0] = byte; lpOut += 4; break;
+ /* Word */
+ case 10: case 15: lpOut[1] = byte; break;
+ case 12: case 17: lpOut[0] = byte; lpOut += 2; break;
+#endif
+ /* Byte */
+ default: lpOut[0] = byte; lpOut++; break;
+ }
+ lpszCLSID++; /* Skip 2nd character of byte */
+ i++;
+ }
+ }
+ lpszCLSID++;
+ i++;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*************************************************************************
+ * RtlStringFromGUID (NTDLL.@)
+ *
+ * Convert a GUID into a string representation of a GUID.
+ *
+ * PARAMS
+ * guid [I] GUID to convert
+ * str [O] Destination for the converted string
+ *
+ * RETURNS
+ * Success: STATUS_SUCCESS. str contains the converted value.
+ * Failure: STATUS_NO_MEMORY, if memory for str cannot be allocated.
+ *
+ * SEE ALSO
+ * See RtlGUIDFromString.
+ */
+NTSTATUS WINAPI RtlStringFromGUID(const GUID* guid, UNICODE_STRING *str)
+{
+ static const WCHAR szFormat[] = { '{','%','0','8','l','X','-',
+ '%','0','4','X','-', '%','0','4','X','-','%','0','2','X','%','0','2','X',
+ '-', '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
+ '%','0','2','X','%','0','2','X','}','\0' };
+
+ TRACE("(%p,%p)\n", guid, str);
+
+ str->Buffer = (WCHAR*)RtlAllocateHeap( ntdll_get_process_heap(), 0, 40 * sizeof(WCHAR));
+ if (!str->Buffer)
+ {
+ str->Length = str->MaximumLength = 0;
+ return STATUS_NO_MEMORY;
+ }
+ str->Length = str->MaximumLength = 40;
+ sprintfW(str->Buffer, szFormat, guid->Data1, guid->Data2, guid->Data3,
+ guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+ guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+
+ return STATUS_SUCCESS;
+}
diff -ur wine/dlls/ntdll/tests/rtlstr.c wine-test/dlls/ntdll/tests/rtlstr.c
--- wine/dlls/ntdll/tests/rtlstr.c 2003-10-07 13:52:45.000000000 +0000
+++ wine-test/dlls/ntdll/tests/rtlstr.c 2003-12-11 19:23:53.000000000 +0000
@@ -25,14 +25,17 @@
#include <stdarg.h>
#include <stdlib.h>
+#define INITGUID
#include "ntstatus.h"
#include "windef.h"
#include "winbase.h"
#include "wine/test.h"
+#include "wine/unicode.h"
#include "winnt.h"
#include "winnls.h"
#include "winreg.h"
#include "winternl.h"
+#include "guiddef.h"
/* Function ptrs for ntdll calls */
static HMODULE hntdll = 0;
@@ -64,6 +67,8 @@
static CHAR (WINAPI *pRtlUpperChar)(CHAR);
static NTSTATUS (WINAPI *pRtlUpperString)(STRING *, const STRING *);
static NTSTATUS (WINAPI *pRtlValidateUnicodeString)(long, UNICODE_STRING *);
+static NTSTATUS (WINAPI *pRtlGUIDFromString)(const UNICODE_STRING*,GUID*);
+static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
/*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/
/*static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);*/
@@ -130,6 +135,8 @@
pRtlUpperChar = (void *)GetProcAddress(hntdll, "RtlUpperChar");
pRtlUpperString = (void *)GetProcAddress(hntdll, "RtlUpperString");
pRtlValidateUnicodeString = (void *)GetProcAddress(hntdll, "RtlValidateUnicodeString");
+ pRtlGUIDFromString = (void *)GetProcAddress(hntdll, "RtlGUIDFromString");
+ pRtlStringFromGUID = (void *)GetProcAddress(hntdll, "RtlStringFromGUID");
} /* if */
}
@@ -1669,6 +1676,38 @@
int2str[0].value, int2str[0].base, int2str[0].MaximumLength, result, STATUS_ACCESS_VIOLATION);
}
+static const WCHAR szGuid[] = { '{','0','1','0','2','0','3','0','4','-',
+ '0','5','0','6','-' ,'0','7','0','8','-','0','9','0','A','-',
+ '0','B','0','C','0','D','0','E','0','F','0','A','}','\0' };
+DEFINE_GUID(IID_Endianess, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x0A);
+
+static void test_RtlGUIDFromString(void)
+{
+ GUID guid;
+ UNICODE_STRING str;
+ NTSTATUS ret;
+
+ str.Length = str.MaximumLength = (sizeof(szGuid) - 1) / sizeof(WCHAR);
+ str.Buffer = (LPWSTR)szGuid;
+
+ ret = pRtlGUIDFromString(&str, &guid);
+ ok(ret == 0, "expected ret=0, got 0x%0lx\n", ret);
+ ok(memcmp(&guid, &IID_Endianess, sizeof(guid)) == 0, "Endianess broken\n");
+}
+
+static void test_RtlStringFromGUID(void)
+{
+ UNICODE_STRING str;
+ NTSTATUS ret;
+
+ str.Length = str.MaximumLength = 0;
+ str.Buffer = NULL;
+
+ ret = pRtlStringFromGUID(&IID_Endianess, &str);
+ ok(ret == 0, "expected ret=0, got 0x%0lx\n", ret);
+ ok(str.Buffer && !strcmpW(str.Buffer, szGuid), "Endianess broken\n");
+}
START_TEST(rtlstr)
{
@@ -1690,16 +1729,17 @@
test_RtlAppendUnicodeStringToString();
} /* if */
- if (pRtlInitUnicodeStringEx) {
- test_RtlInitUnicodeStringEx();
- } /* if */
- if (pRtlDuplicateUnicodeString) {
+ if (pRtlInitUnicodeStringEx)
+ test_RtlInitUnicodeStringEx();
+ if (pRtlDuplicateUnicodeString)
test_RtlDuplicateUnicodeString();
- } /* if */
- if (pRtlFindCharInUnicodeString) {
+ if (pRtlFindCharInUnicodeString)
test_RtlFindCharInUnicodeString();
- } /* if */
- /*
+ if (pRtlGUIDFromString)
+ test_RtlGUIDFromString();
+ if (pRtlStringFromGUID)
+ test_RtlStringFromGUID();
+ /*
* test_RtlUpcaseUnicodeChar();
* test_RtlUpcaseUnicodeString();
* test_RtlDowncaseUnicodeString();