[ADVAPI32] SystemFunction004 and SystemFunction005 must return the required output...
[reactos.git] / dll / win32 / advapi32 / misc / sysfunc.c
index 97d4ad2..b6bee62 100644 (file)
@@ -1,17 +1,21 @@
 /*
- *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
- * FILE:            dll/win32/advapi32/misc/sysfun.c
+ * FILE:            dll/win32/advapi32/misc/sysfunc.c
  * PURPOSE:         advapi32.dll system functions (undocumented)
  * PROGRAMMER:      Emanuele Aliberti
  * UPDATE HISTORY:
- *     19990413 EA     created
- *     19990415 EA
- *     20080424 Ported from WINE
+ *  19990413 EA created
+ *  19990415 EA
+ *  20080424 Ported from WINE
  */
 
 #include <advapi32.h>
+#include <ntsecapi.h>
+#include <ksecioctl.h>
+#include <md4.h>
+#include <md5.h>
+#include <rc4.h>
 
 static const unsigned char CRYPT_LMhash_Magic[8] =
     { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
@@ -126,7 +130,10 @@ WINAPI SystemFunction004(const struct ustring *in,
 
     crypt_len = ((in->Length+7)&~7);
     if (out->MaximumLength < (crypt_len+8))
+    {
+        out->Length = crypt_len + 8;
         return STATUS_BUFFER_TOO_SMALL;
+    }
 
     data.ui[0] = in->Length;
     data.ui[1] = 1;
@@ -199,7 +206,10 @@ WINAPI SystemFunction005(const struct ustring *in,
 
     crypt_len = data.ui[0];
     if (crypt_len > out->MaximumLength)
+    {
+        out->Length = crypt_len;
         return STATUS_BUFFER_TOO_SMALL;
+    }
 
     for (ofs=0; (ofs+8)<crypt_len; ofs+=8)
         CRYPT_DESunhash(out->Buffer+ofs, deskey, in->Buffer+ofs+8);
@@ -445,8 +455,8 @@ SystemFunction028(INT a, INT b)
 {
     //NDRCContextBinding()
     //SystemFunction034()
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return 28;
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 28;
 }
 
 
@@ -459,8 +469,8 @@ WINAPI
 SystemFunction029(INT a, INT b)
 {
     //I_RpcBindingIsClientLocal()
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return 29;
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 29;
 }
 
 
@@ -477,9 +487,9 @@ SystemFunction029(INT a, INT b)
  *  FALSE if blocks are different
  */
 BOOL
-WINAPI SystemFunction030(PVOID b1, PVOID b2)
+WINAPI SystemFunction030(LPCVOID b1, LPCVOID b2)
 {
-       return !memcmp(b1, b2, 0x10);
+    return !memcmp(b1, b2, 0x10);
 }
 
 
@@ -500,12 +510,12 @@ WINAPI SystemFunction030(PVOID b1, PVOID b2)
  *  see http://web.it.kth.se/~rom/ntsec.html#crypto-strongavail
  */
 NTSTATUS
-WINAPI SystemFunction032(struct ustring *data, struct ustring *key)
+WINAPI SystemFunction032(struct ustring *data, const struct ustring *key)
 {
-    arc4_info a4i;
+    RC4_CONTEXT a4i;
 
-    arc4_init(&a4i, key->Buffer, key->Length);
-    arc4_ProcessString(&a4i, data->Buffer, data->Length);
+    rc4_init(&a4i, key->Buffer, key->Length);
+    rc4_crypt(&a4i, data->Buffer, data->Length);
 
     return STATUS_SUCCESS;
 }
@@ -519,8 +529,8 @@ INT
 WINAPI
 SystemFunction033(INT a, INT b)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return 33;
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 33;
 }
 
 /**********************************************************************
@@ -535,20 +545,24 @@ SystemFunction034(INT a, INT b)
     //I_RpcMapWin32Status
     //RpcStringBindingParseW
     //RpcStringFreeW
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return 34;
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 34;
 }
 
 
-/**********************************************************************
+/******************************************************************************
+ * SystemFunction035   (ADVAPI32.@)
  *
- * @unimplemented
+ * Described here:
+http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
+ *
+ * NOTES
+ *  Stub, always return TRUE.
  */
-BOOL
-WINAPI
-SystemFunction035(LPCSTR lpszDllFilePath)
+BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
 {
-       return TRUE;
+    //FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
+    return TRUE;
 }
 
 /******************************************************************************
@@ -570,7 +584,7 @@ SystemFunction036(PVOID pbBuffer, ULONG dwLen)
     ////////////////////////////////////////////////////////////////
     //////////////////// B I G   W A R N I N G  !!! ////////////////
     // This function will output numbers based on the tick count. //
-    // It will NOT OUPUT CRYPTOGRAPHIC-SAFE RANDOM NUMBERS !!!    //
+    // It will NOT OUTPUT CRYPTOGRAPHIC-SAFE RANDOM NUMBERS !!!    //
     ////////////////////////////////////////////////////////////////
 
     DWORD dwSeed;
@@ -600,14 +614,101 @@ SystemFunction036(PVOID pbBuffer, ULONG dwLen)
         do
         {
             /* Get each byte from the pseudo random number and store it in the buffer */
-            *pBuffer = (BYTE)(uPseudoRandom >> 8 * (dwLen % 4) & 0xFF);
+            *pBuffer = (BYTE)(uPseudoRandom >> 8 * (dwLen % 3) & 0xFF);
             ++pBuffer;
-        } while(--dwLen % 4);
+        } while(--dwLen % 3);
     } while(dwLen);
 
     return TRUE;
 }
 
+HANDLE KsecDeviceHandle;
+
+static
+NTSTATUS
+KsecOpenDevice()
+{
+    UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KsecDD");
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    HANDLE DeviceHandle;
+    NTSTATUS Status;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &DeviceName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenFile(&DeviceHandle,
+                        FILE_READ_DATA | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    if (InterlockedCompareExchangePointer(&KsecDeviceHandle, DeviceHandle, NULL) != NULL)
+    {
+        NtClose(DeviceHandle);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+CloseKsecDdHandle(VOID)
+{
+    /* Check if we already opened a handle to ksecdd */
+    if (KsecDeviceHandle != NULL)
+    {
+        /* Close it */
+        CloseHandle(KsecDeviceHandle);
+        KsecDeviceHandle = NULL;
+    }
+}
+
+static
+NTSTATUS
+KsecDeviceIoControl(
+    ULONG IoControlCode,
+    PVOID InputBuffer,
+    SIZE_T InputBufferLength,
+    PVOID OutputBuffer,
+    SIZE_T OutputBufferLength)
+{
+    IO_STATUS_BLOCK IoStatusBlock;
+    NTSTATUS Status;
+
+    /* Check if we already have a handle */
+    if (KsecDeviceHandle == NULL)
+    {
+        /* Try to open the device */
+        Status = KsecOpenDevice();
+        if (!NT_SUCCESS(Status))
+        {
+            //ERR("Failed to open handle to KsecDd driver!\n");
+            return Status;
+        }
+    }
+
+    /* Call the driver */
+    Status = NtDeviceIoControlFile(KsecDeviceHandle,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &IoStatusBlock,
+                                   IoControlCode,
+                                   InputBuffer,
+                                   InputBufferLength,
+                                   OutputBuffer,
+                                   OutputBufferLength);
+
+    return Status;
+}
+
 /*
    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
    in crypt32.dll.
@@ -616,33 +717,103 @@ SystemFunction036(PVOID pbBuffer, ULONG dwLen)
 /******************************************************************************
  * SystemFunction040   (ADVAPI32.@)
  *
- * PARAMS:
- *   memory : pointer to memory to encrypt
- *   length : length of region to encrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
- *   flags  : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
- *            control whether other processes are able to decrypt the memory. The same value must be given
- *            when decrypting the memory.
+ * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
+ *
+ * PARAMS
+ *  memory [I/O] Pointer to memory to encrypt.
+ *  length [I] Length of region to encrypt in bytes.
+ *  flags  [I] Control whether other processes are able to decrypt the memory.
+ *    RTL_ENCRYPT_OPTION_SAME_PROCESS
+ *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
+ *    RTL_ENCRYPT_OPTION_SAME_LOGON
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: NTSTATUS error code
+ *
+ * NOTES
+ *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
+ *  If flags are specified when encrypting, the same flag value must be given
+ *  when decrypting the memory.
  */
-NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)  /* RtlEncryptMemory */
+NTSTATUS
+WINAPI
+SystemFunction040(
+    _Inout_ PVOID Memory,
+    _In_ ULONG MemoryLength,
+    _In_ ULONG OptionFlags)
 {
-       //FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
-       return STATUS_SUCCESS;
+    ULONG IoControlCode;
+
+    if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_ENCRYPT_CROSS_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
+    {
+        IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_LOGON;
+    }
+    else
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength);
 }
 
 /******************************************************************************
  * SystemFunction041  (ADVAPI32.@)
  *
- * PARAMS:
- *   memory : pointer to memory to decrypt
- *   length : length of region to decrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
- *   flags  : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
- *            control whether other processes are able to decrypt the memory. The same value must be given
- *            when encrypting the memory.
+ * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
+ *
+ * PARAMS
+ *  memory [I/O] Pointer to memory to decrypt.
+ *  length [I] Length of region to decrypt in bytes.
+ *  flags  [I] Control whether other processes are able to decrypt the memory.
+ *    RTL_ENCRYPT_OPTION_SAME_PROCESS
+ *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
+ *    RTL_ENCRYPT_OPTION_SAME_LOGON
+ *
+ * RETURNS
+ *  Success: STATUS_SUCCESS
+ *  Failure: NTSTATUS error code
+ *
+ * NOTES
+ *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
+ *  If flags are specified when encrypting, the same flag value must be given
+ *  when decrypting the memory.
  */
-NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)  /* RtlDecryptMemory */
+NTSTATUS
+WINAPI
+SystemFunction041(
+    _Inout_ PVOID Memory,
+    _In_ ULONG MemoryLength,
+    _In_ ULONG OptionFlags)
 {
-       //FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
-       return STATUS_SUCCESS;
+    ULONG IoControlCode;
+
+    if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_DECRYPT_SAME_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_DECRYPT_CROSS_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
+    {
+        IoControlCode = IOCTL_KSEC_DECRYPT_SAME_LOGON;
+    }
+    else
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength);
 }
 
 /* EOF */