Commit 3c6bdcce authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

Implement directory object in wineserver.

Implement Nt[Create|Open]DirectoryObject. Change tests accordingly.
parent 4cbf118d
......@@ -362,30 +362,77 @@ NTSTATUS WINAPI NtClose( HANDLE Handle )
* Success: ERROR_SUCCESS.
* Failure: An NTSTATUS error code.
*/
NTSTATUS WINAPI NtOpenDirectoryObject(
PHANDLE DirectoryHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
NTSTATUS WINAPI NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
{
FIXME("(%p,0x%08lx,%p): stub\n",
DirectoryHandle, DesiredAccess, ObjectAttributes);
dump_ObjectAttributes(ObjectAttributes);
return 0;
NTSTATUS ret;
TRACE("(%p,0x%08lx)\n", DirectoryHandle, DesiredAccess);
dump_ObjectAttributes(ObjectAttributes);
if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
/* Have to test it here because server won't know difference between
* ObjectName == NULL and ObjectName == "" */
if (!ObjectAttributes->ObjectName)
{
if (ObjectAttributes->RootDirectory)
return STATUS_OBJECT_NAME_INVALID;
else
return STATUS_OBJECT_PATH_SYNTAX_BAD;
}
SERVER_START_REQ(open_directory)
{
req->access = DesiredAccess;
req->attributes = ObjectAttributes->Attributes;
req->rootdir = ObjectAttributes->RootDirectory;
if (ObjectAttributes->ObjectName)
wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
ObjectAttributes->ObjectName->Length);
ret = wine_server_call( req );
*DirectoryHandle = reply->handle;
}
SERVER_END_REQ;
return ret;
}
/******************************************************************************
* NtCreateDirectoryObject [NTDLL.@]
* ZwCreateDirectoryObject [NTDLL.@]
*
* Create a namespace directory object.
*
* PARAMS
* DirectoryHandle [O] Destination for the new directory handle
* DesiredAccess [I] Desired access to the directory
* ObjectAttributes [I] Structure describing the directory
*
* RETURNS
* Success: ERROR_SUCCESS.
* Failure: An NTSTATUS error code.
*/
NTSTATUS WINAPI NtCreateDirectoryObject(
PHANDLE DirectoryHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
{
FIXME("(%p,0x%08lx,%p),stub!\n",
DirectoryHandle,DesiredAccess,ObjectAttributes);
dump_ObjectAttributes(ObjectAttributes);
return 0;
NTSTATUS ret;
TRACE("(%p,0x%08lx)\n", DirectoryHandle, DesiredAccess);
dump_ObjectAttributes(ObjectAttributes);
if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
SERVER_START_REQ(create_directory)
{
req->access = DesiredAccess;
req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
if (ObjectAttributes && ObjectAttributes->ObjectName)
wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
ObjectAttributes->ObjectName->Length);
ret = wine_server_call( req );
*DirectoryHandle = reply->handle;
}
SERVER_END_REQ;
return ret;
}
/******************************************************************************
......
......@@ -186,11 +186,11 @@ static void test_name_collisions(void)
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
pRtlCreateUnicodeStringFromAsciiz(&str, "\\");
h = 0;
todo_wine{ DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_COLLISION) }
DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_COLLISION)
ok(h == 0, "Failed create returned valid handle! (%p)\n", h);
InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, 0, NULL);
todo_wine{ DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_EXISTS) }
DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_EXISTS)
pNtClose(h);
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH,
......@@ -199,7 +199,7 @@ static void test_name_collisions(void)
pRtlCreateUnicodeStringFromAsciiz(&str, "\\??\\PIPE\\om.c-mutant");
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH,
todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
"NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08lx)\n", status);
pRtlFreeUnicodeString(&str);
......@@ -289,22 +289,22 @@ void test_directory(void)
/* No name and/or no attributes */
status = pNtCreateDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
todo_wine ok(status == STATUS_ACCESS_VIOLATION,
ok(status == STATUS_ACCESS_VIOLATION,
"NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08lx)\n", status);
status = pNtOpenDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
todo_wine ok(status == STATUS_ACCESS_VIOLATION,
ok(status == STATUS_ACCESS_VIOLATION,
"NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08lx)\n", status);
status = pNtCreateDirectoryObject(&h, DIRECTORY_QUERY, NULL);
ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08lx)\n", status);
pNtClose(h);
status = pNtOpenDirectoryObject(&h, DIRECTORY_QUERY, NULL);
todo_wine ok(status == STATUS_INVALID_PARAMETER,
ok(status == STATUS_INVALID_PARAMETER,
"NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08lx)\n", status);
InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
DIR_TEST_CREATE_SUCCESS(&dir)
todo_wine{ DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD) }
DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
/* Bad name */
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
......@@ -312,15 +312,15 @@ void test_directory(void)
pRtlCreateUnicodeStringFromAsciiz(&str, "");
DIR_TEST_CREATE_SUCCESS(&h)
pNtClose(h);
todo_wine{ DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD) }
DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
pRtlFreeUnicodeString(&str);
pNtClose(dir);
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", STATUS_OBJECT_PATH_SYNTAX_BAD) }
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", STATUS_OBJECT_NAME_INVALID) }
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", STATUS_OBJECT_NAME_INVALID) }
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", STATUS_OBJECT_NAME_INVALID) }
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND) }
DIR_TEST_CREATE_OPEN_FAILURE(&h, "BaseNamedObjects", STATUS_OBJECT_PATH_SYNTAX_BAD)
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\", STATUS_OBJECT_NAME_INVALID)
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\\\BaseNamedObjects", STATUS_OBJECT_NAME_INVALID)
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\\\om.c-test", STATUS_OBJECT_NAME_INVALID)
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\BaseNamedObjects\\om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\om.c-test");
DIR_TEST_CREATE_SUCCESS(&h)
......@@ -351,14 +351,14 @@ void test_directory(void)
pRtlFreeUnicodeString(&str);
InitializeObjectAttributes(&attr, NULL, 0, dir, NULL);
todo_wine{ DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID) }
DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID)
InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
DIR_TEST_CREATE_OPEN_SUCCESS(&h, "")
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD) }
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD) }
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD) }
todo_wine{ DIR_TEST_CREATE_OPEN_FAILURE(&h, "om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND) }
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD)
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
DIR_TEST_CREATE_OPEN_FAILURE(&h, "om.c-test\\", STATUS_OBJECT_PATH_NOT_FOUND)
pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
DIR_TEST_CREATE_SUCCESS(&dir1)
......@@ -374,7 +374,7 @@ void test_directory(void)
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
DIR_TEST_OPEN_SUCCESS(&dir)
InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
todo_wine{ DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD) }
DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_PATH_SYNTAX_BAD)
pRtlFreeUnicodeString(&str);
pNtClose(dir);
......@@ -396,15 +396,15 @@ void test_directory(void)
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Global\\om.c-test");
DIR_TEST_CREATE_SUCCESS(&dir)
todo_wine{ DIR_TEST_CREATE_SUCCESS(&dir) }
pRtlFreeUnicodeString(&str);
pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local\\om.c-test\\one more level");
DIR_TEST_CREATE_SUCCESS(&h)
todo_wine{ DIR_TEST_CREATE_SUCCESS(&h) }
pRtlFreeUnicodeString(&str);
pNtClose(h);
InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
DIR_TEST_CREATE_SUCCESS(&dir)
todo_wine{ DIR_TEST_CREATE_SUCCESS(&dir) }
pRtlFreeUnicodeString(&str);
pNtClose(h);
......
......@@ -3577,6 +3577,38 @@ struct set_mailslot_info_reply
#define MAILSLOT_SET_READ_TIMEOUT 1
struct create_directory_request
{
struct request_header __header;
unsigned int access;
unsigned int attributes;
obj_handle_t rootdir;
/* VARARG(directory_name,unicode_str); */
};
struct create_directory_reply
{
struct reply_header __header;
obj_handle_t handle;
};
struct open_directory_request
{
struct request_header __header;
unsigned int access;
unsigned int attributes;
obj_handle_t rootdir;
/* VARARG(directory_name,unicode_str); */
};
struct open_directory_reply
{
struct reply_header __header;
obj_handle_t handle;
};
enum request
{
REQ_new_process,
......@@ -3784,6 +3816,8 @@ enum request
REQ_create_mailslot,
REQ_open_mailslot,
REQ_set_mailslot_info,
REQ_create_directory,
REQ_open_directory,
REQ_NB_REQUESTS
};
......@@ -3996,6 +4030,8 @@ union generic_request
struct create_mailslot_request create_mailslot_request;
struct open_mailslot_request open_mailslot_request;
struct set_mailslot_info_request set_mailslot_info_request;
struct create_directory_request create_directory_request;
struct open_directory_request open_directory_request;
};
union generic_reply
{
......@@ -4206,8 +4242,10 @@ union generic_reply
struct create_mailslot_reply create_mailslot_reply;
struct open_mailslot_reply open_mailslot_reply;
struct set_mailslot_info_reply set_mailslot_info_reply;
struct create_directory_reply create_directory_reply;
struct open_directory_reply open_directory_reply;
};
#define SERVER_PROTOCOL_VERSION 199
#define SERVER_PROTOCOL_VERSION 200
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -17,6 +17,7 @@ C_SRCS = \
context_sparc.c \
context_x86_64.c \
debugger.c \
directory.c \
event.c \
fd.c \
file.c \
......
......@@ -135,6 +135,7 @@ int main( int argc, char *argv[] )
if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
init_signals();
init_directories();
init_registry();
main_loop();
return 0;
......
......@@ -40,9 +40,10 @@
struct object_name
{
struct list entry; /* entry in the hash list */
struct object *obj;
size_t len;
struct list entry; /* entry in the hash list */
struct object *obj; /* object owning this name */
struct object *parent; /* parent object */
size_t len; /* name length in bytes */
WCHAR name[1];
};
......@@ -108,6 +109,7 @@ static struct object_name *alloc_name( const struct unicode_str *name )
if ((ptr = mem_alloc( sizeof(*ptr) + name->len - sizeof(ptr->name) )))
{
ptr->len = name->len;
ptr->parent = NULL;
memcpy( ptr->name, name->str, name->len );
}
return ptr;
......@@ -118,6 +120,7 @@ static void free_name( struct object *obj )
{
struct object_name *ptr = obj->name;
list_remove( &ptr->entry );
if (ptr->parent) release_object( ptr->parent );
free( ptr );
}
......@@ -159,11 +162,27 @@ void *alloc_object( const struct object_ops *ops )
return NULL;
}
void *create_object( struct namespace *namespace, const struct object_ops *ops,
const struct unicode_str *name, struct object *parent )
{
struct object *obj;
struct object_name *name_ptr;
if (!(name_ptr = alloc_name( name ))) return NULL;
if ((obj = alloc_object( ops )))
{
set_object_name( namespace, obj, name_ptr );
if (parent) name_ptr->parent = grab_object( parent );
}
else
free( name_ptr );
return obj;
}
void *create_named_object( struct namespace *namespace, const struct object_ops *ops,
const struct unicode_str *name, unsigned int attributes )
{
struct object *obj;
struct object_name *name_ptr;
if (!name || !name->len) return alloc_object( ops );
......@@ -182,13 +201,7 @@ void *create_named_object( struct namespace *namespace, const struct object_ops
}
return obj;
}
if (!(name_ptr = alloc_name( name ))) return NULL;
if ((obj = alloc_object( ops )))
{
set_object_name( namespace, obj, name_ptr );
clear_error();
}
else free( name_ptr );
if ((obj = create_object( namespace, ops, name, NULL ))) clear_error();
return obj;
}
......
......@@ -44,6 +44,7 @@ struct wait_queue_entry;
struct async;
struct async_queue;
struct winstation;
struct directory;
struct unicode_str
......@@ -102,6 +103,8 @@ extern void *memdup( const void *data, size_t len );
extern void *alloc_object( const struct object_ops *ops );
extern const WCHAR *get_object_name( struct object *obj, size_t *len );
extern void dump_object_name( struct object *obj );
extern void *create_object( struct namespace *namespace, const struct object_ops *ops,
const struct unicode_str *name, struct object *parent );
extern void *create_named_object( struct namespace *namespace, const struct object_ops *ops,
const struct unicode_str *name, unsigned int attributes );
extern struct namespace *create_namespace( unsigned int hash_size );
......@@ -177,6 +180,19 @@ extern atom_t find_global_atom( struct winstation *winstation, const WCHAR *str,
extern int grab_global_atom( struct winstation *winstation, atom_t atom );
extern void release_global_atom( struct winstation *winstation, atom_t atom );
/* directory functions */
extern struct directory *get_directory_obj( struct process *process, obj_handle_t handle, unsigned int access );
extern struct object *find_object_dir( struct directory *root, const struct unicode_str *name,
unsigned int attr, struct unicode_str *name_left );
extern void *create_named_object_dir( struct directory *root, const struct unicode_str *name,
unsigned int attr, const struct object_ops *ops );
extern obj_handle_t open_object_dir( struct directory *root, const struct unicode_str *name,
unsigned int attr, const struct object_ops *ops,
unsigned int access );
extern void init_directories(void);
extern void close_directories(void);
/* global variables */
/* command-line options */
......
......@@ -2505,3 +2505,25 @@ enum message_type
unsigned int next_msgsize;
@END
#define MAILSLOT_SET_READ_TIMEOUT 1
/* Create a directory object */
@REQ(create_directory)
unsigned int access; /* access flags */
unsigned int attributes; /* object attributes */
obj_handle_t rootdir; /* root directory */
VARARG(directory_name,unicode_str); /* Directory name */
@REPLY
obj_handle_t handle; /* handle to the directory */
@END
/* Open a directory object */
@REQ(open_directory)
unsigned int access; /* access flags */
unsigned int attributes; /* object attributes */
obj_handle_t rootdir; /* root directory */
VARARG(directory_name,unicode_str); /* Directory name */
@REPLY
obj_handle_t handle; /* handle to the directory */
@END
......@@ -801,6 +801,7 @@ static void close_socket_timeout( void *arg )
close_signals();
close_global_handles();
close_registry();
close_directories();
dump_objects(); /* dump any remaining objects */
#else
exit(0);
......
......@@ -315,6 +315,8 @@ DECL_HANDLER(get_token_user);
DECL_HANDLER(create_mailslot);
DECL_HANDLER(open_mailslot);
DECL_HANDLER(set_mailslot_info);
DECL_HANDLER(create_directory);
DECL_HANDLER(open_directory);
#ifdef WANT_REQUEST_HANDLERS
......@@ -526,6 +528,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_create_mailslot,
(req_handler)req_open_mailslot,
(req_handler)req_set_mailslot_info,
(req_handler)req_create_directory,
(req_handler)req_open_directory,
};
#endif /* WANT_REQUEST_HANDLERS */
......
......@@ -3093,6 +3093,34 @@ static void dump_set_mailslot_info_reply( const struct set_mailslot_info_reply *
fprintf( stderr, " next_msgsize=%08x", req->next_msgsize );
}
static void dump_create_directory_request( const struct create_directory_request *req )
{
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " attributes=%08x,", req->attributes );
fprintf( stderr, " rootdir=%p,", req->rootdir );
fprintf( stderr, " directory_name=" );
dump_varargs_unicode_str( cur_size );
}
static void dump_create_directory_reply( const struct create_directory_reply *req )
{
fprintf( stderr, " handle=%p", req->handle );
}
static void dump_open_directory_request( const struct open_directory_request *req )
{
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " attributes=%08x,", req->attributes );
fprintf( stderr, " rootdir=%p,", req->rootdir );
fprintf( stderr, " directory_name=" );
dump_varargs_unicode_str( cur_size );
}
static void dump_open_directory_reply( const struct open_directory_reply *req )
{
fprintf( stderr, " handle=%p", req->handle );
}
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request,
......@@ -3299,6 +3327,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_mailslot_request,
(dump_func)dump_open_mailslot_request,
(dump_func)dump_set_mailslot_info_request,
(dump_func)dump_create_directory_request,
(dump_func)dump_open_directory_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
......@@ -3507,6 +3537,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_mailslot_reply,
(dump_func)dump_open_mailslot_reply,
(dump_func)dump_set_mailslot_info_reply,
(dump_func)dump_create_directory_reply,
(dump_func)dump_open_directory_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
......@@ -3715,6 +3747,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_mailslot",
"open_mailslot",
"set_mailslot_info",
"create_directory",
"open_directory",
};
static const struct
......@@ -3752,6 +3786,7 @@ static const struct
{ "KEY_DELETED", STATUS_KEY_DELETED },
{ "MEDIA_WRITE_PROTECTED", STATUS_MEDIA_WRITE_PROTECTED },
{ "MUTANT_NOT_OWNED", STATUS_MUTANT_NOT_OWNED },
{ "NAME_TOO_LONG", STATUS_NAME_TOO_LONG },
{ "NOT_ALL_ASSIGNED", STATUS_NOT_ALL_ASSIGNED },
{ "NOT_A_DIRECTORY", STATUS_NOT_A_DIRECTORY },
{ "NOT_IMPLEMENTED", STATUS_NOT_IMPLEMENTED },
......@@ -3769,6 +3804,8 @@ static const struct
{ "OBJECT_NAME_INVALID", STATUS_OBJECT_NAME_INVALID },
{ "OBJECT_NAME_NOT_FOUND", STATUS_OBJECT_NAME_NOT_FOUND },
{ "OBJECT_PATH_INVALID", STATUS_OBJECT_PATH_INVALID },
{ "OBJECT_PATH_NOT_FOUND", STATUS_OBJECT_PATH_NOT_FOUND },
{ "OBJECT_PATH_SYNTAX_BAD", STATUS_OBJECT_PATH_SYNTAX_BAD },
{ "OBJECT_TYPE_MISMATCH", STATUS_OBJECT_TYPE_MISMATCH },
{ "PENDING", STATUS_PENDING },
{ "PIPE_BUSY", STATUS_PIPE_BUSY },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment